4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright (c) 2016 by Delphix. All rights reserved.
27 * NOTE:I'm trying to use "struct sadb_foo" instead of "sadb_foo_t"
28 * as a maximal PF_KEY portability test.
30 * Also, this is a deliberately single-threaded app, also for portability
31 * to systems without POSIX threads.
34 #include <sys/types.h>
36 #include <sys/socket.h>
37 #include <sys/sysmacros.h>
38 #include <sys/fcntl.h>
39 #include <net/pfkeyv2.h>
40 #include <arpa/inet.h>
41 #include <netinet/in.h>
59 #include <sys/cladm.h>
61 #include <ipsec_util.h>
64 static int cluster_socket
;
67 static boolean_t vflag
= B_FALSE
; /* Verbose? */
68 static boolean_t cflag
= B_FALSE
; /* Check Only */
71 FILE *debugfile
= stdout
;
72 static struct sockaddr_in cli_addr
;
73 static boolean_t in_cluster_mode
= B_FALSE
;
75 #define MAX_GET_SIZE 1024
77 * WARN() and ERROR() do the same thing really, with ERROR() the function
78 * that prints the error buffer needs to be called at the end of a code block
79 * This will print out all accumulated errors before bailing. The WARN()
80 * macro calls handle_errors() in such a way that it prints the message
82 * If the FATAL() macro used call handle_errors() immediately.
84 #define ERROR(x, y, z) x = record_error(x, y, z)
85 #define ERROR1(w, x, y, z) w = record_error(w, x, y, z)
86 #define ERROR2(v, w, x, y, z) v = record_error(v, w, x, y, z)
87 #define WARN(x, y, z) ERROR(x, y, z);\
88 handle_errors(x, NULL, B_FALSE, B_FALSE); x = NULL
89 #define WARN1(w, x, y, z) ERROR1(w, x, y, z);\
90 handle_errors(w, NULL, B_FALSE, B_FALSE); w = NULL
91 #define WARN2(v, w, x, y, z) ERROR2(v, w, x, y, z);\
92 handle_errors(v, NULL, B_FALSE, B_FALSE); v = NULL
93 #define FATAL(x, y, z) ERROR(x, y, z);\
94 handle_errors(x, y, B_TRUE, B_TRUE)
95 #define FATAL1(w, x, y, z) ERROR1(w, x, y, z);\
96 handle_errors(w, x, B_TRUE, B_TRUE)
98 /* Defined as a uint64_t array for alignment purposes. */
99 static uint64_t get_buffer
[MAX_GET_SIZE
];
102 * Disable default TAB completion for now (until some brave soul tackles it).
106 CPL_MATCH_FN(no_match
)
112 * Create/Grow a buffer large enough to hold error messages. If *ebuf
113 * is not NULL then it will contain a copy of the command line that
114 * triggered the error/warning, copy this into a new buffer or
115 * append new messages to the existing buffer.
119 record_error(char *ep
, char *ebuf
, char *fmt
, ...)
128 length
= vsnprintf(tmp_buff
, sizeof (tmp_buff
), fmt
, ap
);
131 /* There is a new line character */
136 length
+= strlen(ebuf
);
138 length
+= strlen(ep
);
142 err_ptr
= calloc(length
, sizeof (char));
144 err_ptr
= realloc(err_ptr
, length
);
147 Bail("realloc() failure");
150 * If (ep == NULL) then this is the first error to record,
151 * copy in the command line that triggered this error/warning.
153 if (ep
== NULL
&& ebuf
!= NULL
)
154 (void) strlcpy(err_ptr
, ebuf
, length
);
157 * Now the actual error.
159 (void) strlcat(err_ptr
, tmp_buff
, length
);
164 * If not in interactive mode print usage message and exit.
170 (void) fprintf(stderr
, gettext("Usage:\t"
171 "ipseckey [ -nvp ] | cmd [sa_type] [extfield value]*\n"));
172 (void) fprintf(stderr
,
173 gettext("\tipseckey [ -nvp ] -f infile\n"));
174 (void) fprintf(stderr
,
175 gettext("\tipseckey [ -nvp ] -s outfile\n"));
178 (void) fprintf(stderr
,
179 gettext("Type help or ? for usage info\n"));
185 * Print out any errors, tidy up as required.
186 * error pointer ep will be free()'d
189 handle_errors(char *ep
, char *ebuf
, boolean_t fatal
, boolean_t done
)
192 if (my_fmri
== NULL
) {
194 * For now suppress the errors when run from smf(5)
195 * because potentially sensitive information could
196 * end up in a publicly readable logfile.
198 (void) fprintf(stdout
, "%s\n", ep
);
199 (void) fflush(stdout
);
206 /* reset command buffer */
214 * No errors, if this is the last time that this function
215 * is called, free(ebuf) and reset command buffer.
221 /* reset command buffer */
231 * Initialize a PF_KEY base message.
234 msg_init(struct sadb_msg
*msg
, uint8_t type
, uint8_t satype
)
236 msg
->sadb_msg_version
= PF_KEY_V2
;
237 msg
->sadb_msg_type
= type
;
238 msg
->sadb_msg_errno
= 0;
239 msg
->sadb_msg_satype
= satype
;
240 /* For starters... */
241 msg
->sadb_msg_len
= SADB_8TO64(sizeof (*msg
));
242 msg
->sadb_msg_reserved
= 0;
243 msg
->sadb_msg_seq
= ++seq
;
244 msg
->sadb_msg_pid
= mypid
;
248 * parseXXX and rparseXXX commands parse input and convert them to PF_KEY
249 * field values, or do the reverse for the purposes of saving the SA tables.
250 * (See the save_XXX functions.)
255 #define CMD_UPDATE_PAIR 3
258 #define CMD_DELETE_PAIR 6
262 #define CMD_MONITOR 11
263 #define CMD_PMONITOR 12
272 parsecmd(char *cmdstr
)
274 static struct cmdtable
{
279 * Q: Do we want to do GETSPI?
280 * A: No, it's for automated key mgmt. only. Either that,
281 * or it isn't relevant until we support non IPsec SA types.
283 {"update", CMD_UPDATE
},
284 {"update-pair", CMD_UPDATE_PAIR
},
286 {"delete", CMD_DELETE
},
287 {"delete-pair", CMD_DELETE_PAIR
},
290 * Q: And ACQUIRE and REGISTER and EXPIRE?
291 * A: not until we support non IPsec SA types.
293 {"flush", CMD_FLUSH
},
295 {"monitor", CMD_MONITOR
},
296 {"passive_monitor", CMD_PMONITOR
},
297 {"pmonitor", CMD_PMONITOR
},
305 struct cmdtable
*ct
= table
;
307 while (ct
->cmd
!= NULL
&& strcmp(ct
->cmd
, cmdstr
) != 0)
313 * Convert a number from a command line. I picked "u_longlong_t" for the
314 * number because we need the largest number available. Also, the strto<num>
315 * calls don't deal in units of uintNN_t.
318 parsenum(char *num
, boolean_t bail
, char *ebuf
)
325 FATAL(ep
, ebuf
, gettext("Unexpected end of command line,"
326 " was expecting a number.\n"));
331 rc
= strtoull(num
, &end
, 0);
332 if (errno
!= 0 || end
== num
|| *end
!= '\0') {
334 FATAL1(ep
, ebuf
, gettext(
335 "Expecting a number, not \"%s\"!\n"), num
);
338 * -1, while not optimal, is sufficiently out of range
339 * for most of this function's applications when
340 * we don't just bail.
342 return ((u_longlong_t
)-1);
345 handle_errors(ep
, NULL
, B_FALSE
, B_FALSE
);
350 * Parse and reverse parse a specific SA type (AH, ESP, etc.).
352 static struct typetable
{
356 {"all", SADB_SATYPE_UNSPEC
},
357 {"ah", SADB_SATYPE_AH
},
358 {"esp", SADB_SATYPE_ESP
},
359 /* PF_KEY NOTE: More to come if net/pfkeyv2.h gets updated. */
360 {NULL
, 0} /* Token value is irrelevant for this entry. */
365 parsesatype(char *type
, char *ebuf
)
367 struct typetable
*tt
= type_table
;
371 return (SADB_SATYPE_UNSPEC
);
373 while (tt
->type
!= NULL
&& strcasecmp(tt
->type
, type
) != 0)
377 * New SA types (including ones keysock maintains for user-land
378 * protocols) may be added, so parse a numeric value if possible.
380 if (tt
->type
== NULL
) {
381 tt
->token
= (int)parsenum(type
, B_FALSE
, ebuf
);
382 if (tt
->token
== -1) {
383 ERROR1(ep
, ebuf
, gettext(
384 "Unknown SA type (%s).\n"), type
);
385 tt
->token
= SADB_SATYPE_UNSPEC
;
388 handle_errors(ep
, NULL
, interactive
? B_TRUE
: B_FALSE
, B_FALSE
);
405 #define TOK_UNKNOWN 1
409 #define TOK_AUTHALG 5
410 #define TOK_ENCRALG 6
412 #define TOK_SOFT_ALLOC 8
413 #define TOK_SOFT_BYTES 9
414 #define TOK_SOFT_ADDTIME 10
415 #define TOK_SOFT_USETIME 11
416 #define TOK_HARD_ALLOC 12
417 #define TOK_HARD_BYTES 13
418 #define TOK_HARD_ADDTIME 14
419 #define TOK_HARD_USETIME 15
420 #define TOK_CURRENT_ALLOC 16
421 #define TOK_CURRENT_BYTES 17
422 #define TOK_CURRENT_ADDTIME 18
423 #define TOK_CURRENT_USETIME 19
424 #define TOK_SRCADDR 20
425 #define TOK_DSTADDR 21
426 #define TOK_PROXYADDR 22
427 #define TOK_AUTHKEY 23
428 #define TOK_ENCRKEY 24
429 #define TOK_SRCIDTYPE 25
430 #define TOK_DSTIDTYPE 26
432 #define TOK_SENS_LEVEL 28
433 #define TOK_SENS_MAP 29
434 #define TOK_INTEG_LEVEL 30
435 #define TOK_INTEG_MAP 31
436 #define TOK_SRCADDR6 32
437 #define TOK_DSTADDR6 33
438 #define TOK_PROXYADDR6 34
439 #define TOK_SRCPORT 35
440 #define TOK_DSTPORT 36
443 #define TOK_NATLOC 39
444 #define TOK_NATREM 40
445 #define TOK_NATLPORT 41
446 #define TOK_NATRPORT 42
447 #define TOK_IPROTO 43
448 #define TOK_IDSTADDR 44
449 #define TOK_IDSTADDR6 45
450 #define TOK_ISRCPORT 46
451 #define TOK_IDSTPORT 47
452 #define TOK_PAIR_SPI 48
453 #define TOK_FLAG_INBOUND 49
454 #define TOK_FLAG_OUTBOUND 50
455 #define TOK_REPLAY_VALUE 51
456 #define TOK_IDLE_ADDTIME 52
457 #define TOK_IDLE_USETIME 53
458 #define TOK_RESERVED 54
460 #define TOK_OLABEL 56
461 #define TOK_IMPLABEL 57
464 static struct toktable
{
469 /* "String", token value, next arg is */
470 {"spi", TOK_SPI
, NEXTNUM
},
471 {"pair-spi", TOK_PAIR_SPI
, NEXTNUM
},
472 {"replay", TOK_REPLAY
, NEXTNUM
},
473 {"state", TOK_STATE
, NEXTNUMSTR
},
474 {"auth_alg", TOK_AUTHALG
, NEXTNUMSTR
},
475 {"authalg", TOK_AUTHALG
, NEXTNUMSTR
},
476 {"encr_alg", TOK_ENCRALG
, NEXTNUMSTR
},
477 {"encralg", TOK_ENCRALG
, NEXTNUMSTR
},
478 {"flags", TOK_FLAGS
, NEXTNUM
},
479 {"soft_alloc", TOK_SOFT_ALLOC
, NEXTNUM
},
480 {"soft_bytes", TOK_SOFT_BYTES
, NEXTNUM
},
481 {"soft_addtime", TOK_SOFT_ADDTIME
, NEXTNUM
},
482 {"soft_usetime", TOK_SOFT_USETIME
, NEXTNUM
},
483 {"hard_alloc", TOK_HARD_ALLOC
, NEXTNUM
},
484 {"hard_bytes", TOK_HARD_BYTES
, NEXTNUM
},
485 {"hard_addtime", TOK_HARD_ADDTIME
, NEXTNUM
},
486 {"hard_usetime", TOK_HARD_USETIME
, NEXTNUM
},
487 {"current_alloc", TOK_CURRENT_ALLOC
, NEXTNUM
},
488 {"current_bytes", TOK_CURRENT_BYTES
, NEXTNUM
},
489 {"current_addtime", TOK_CURRENT_ADDTIME
, NEXTNUM
},
490 {"current_usetime", TOK_CURRENT_USETIME
, NEXTNUM
},
492 {"saddr", TOK_SRCADDR
, NEXTADDR
},
493 {"srcaddr", TOK_SRCADDR
, NEXTADDR
},
494 {"src", TOK_SRCADDR
, NEXTADDR
},
495 {"daddr", TOK_DSTADDR
, NEXTADDR
},
496 {"dstaddr", TOK_DSTADDR
, NEXTADDR
},
497 {"dst", TOK_DSTADDR
, NEXTADDR
},
498 {"proxyaddr", TOK_PROXYADDR
, NEXTADDR
},
499 {"proxy", TOK_PROXYADDR
, NEXTADDR
},
500 {"innersrc", TOK_PROXYADDR
, NEXTADDR
},
501 {"isrc", TOK_PROXYADDR
, NEXTADDR
},
502 {"innerdst", TOK_IDSTADDR
, NEXTADDR
},
503 {"idst", TOK_IDSTADDR
, NEXTADDR
},
505 {"sport", TOK_SRCPORT
, NEXTNUM
},
506 {"dport", TOK_DSTPORT
, NEXTNUM
},
507 {"innersport", TOK_ISRCPORT
, NEXTNUM
},
508 {"isport", TOK_ISRCPORT
, NEXTNUM
},
509 {"innerdport", TOK_IDSTPORT
, NEXTNUM
},
510 {"idport", TOK_IDSTPORT
, NEXTNUM
},
511 {"proto", TOK_PROTO
, NEXTNUM
},
512 {"ulp", TOK_PROTO
, NEXTNUM
},
513 {"iproto", TOK_IPROTO
, NEXTNUM
},
514 {"iulp", TOK_IPROTO
, NEXTNUM
},
516 {"saddr6", TOK_SRCADDR6
, NEXTADDR
},
517 {"srcaddr6", TOK_SRCADDR6
, NEXTADDR
},
518 {"src6", TOK_SRCADDR6
, NEXTADDR
},
519 {"daddr6", TOK_DSTADDR6
, NEXTADDR
},
520 {"dstaddr6", TOK_DSTADDR6
, NEXTADDR
},
521 {"dst6", TOK_DSTADDR6
, NEXTADDR
},
522 {"proxyaddr6", TOK_PROXYADDR6
, NEXTADDR
},
523 {"proxy6", TOK_PROXYADDR6
, NEXTADDR
},
524 {"innersrc6", TOK_PROXYADDR6
, NEXTADDR
},
525 {"isrc6", TOK_PROXYADDR6
, NEXTADDR
},
526 {"innerdst6", TOK_IDSTADDR6
, NEXTADDR
},
527 {"idst6", TOK_IDSTADDR6
, NEXTADDR
},
529 {"authkey", TOK_AUTHKEY
, NEXTHEX
},
530 {"encrkey", TOK_ENCRKEY
, NEXTHEX
},
531 {"srcidtype", TOK_SRCIDTYPE
, NEXTIDENT
},
532 {"dstidtype", TOK_DSTIDTYPE
, NEXTIDENT
},
533 {"dpd", TOK_DPD
, NEXTNUM
},
534 {"sens_level", TOK_SENS_LEVEL
, NEXTNUM
},
535 {"sens_map", TOK_SENS_MAP
, NEXTHEX
},
536 {"integ_level", TOK_INTEG_LEVEL
, NEXTNUM
},
537 {"integ_map", TOK_INTEG_MAP
, NEXTHEX
},
538 {"nat_loc", TOK_NATLOC
, NEXTADDR
},
539 {"nat_rem", TOK_NATREM
, NEXTADDR
},
540 {"nat_lport", TOK_NATLPORT
, NEXTNUM
},
541 {"nat_rport", TOK_NATRPORT
, NEXTNUM
},
542 {"encap", TOK_ENCAP
, NEXTNUMSTR
},
544 {"outbound", TOK_FLAG_OUTBOUND
, NULL
},
545 {"inbound", TOK_FLAG_INBOUND
, NULL
},
547 {"reserved_bits", TOK_RESERVED
, NEXTNUM
},
548 {"replay_value", TOK_REPLAY_VALUE
, NEXTNUM
},
549 {"idle_addtime", TOK_IDLE_ADDTIME
, NEXTNUM
},
550 {"idle_usetime", TOK_IDLE_USETIME
, NEXTNUM
},
552 {"label", TOK_LABEL
, NEXTLABEL
},
553 {"outer-label", TOK_OLABEL
, NEXTLABEL
},
554 {"implicit-label", TOK_IMPLABEL
, NEXTLABEL
},
556 {NULL
, TOK_UNKNOWN
, NEXTEOF
}
560 * Q: Do I need stuff for proposals, combinations, supported algorithms,
563 * A: Probably not, but you never know.
565 * Parse out extension header type values.
568 parseextval(char *value
, int *next
)
575 for (tp
= tokens
; tp
->string
!= NULL
; tp
++)
576 if (strcmp(value
, tp
->string
) == 0)
580 * Since the OS controls what extensions are available, we don't have
581 * to parse numeric values here.
589 * Parse possible state values.
592 parsestate(char *state
, char *ebuf
)
598 {"larval", SADB_SASTATE_LARVAL
},
599 {"mature", SADB_SASTATE_MATURE
},
600 {"dying", SADB_SASTATE_DYING
},
601 {"dead", SADB_SASTATE_DEAD
},
608 FATAL(ep
, ebuf
, "Unexpected end of command line "
609 "was expecting a state.\n");
612 for (sp
= states
; sp
->state
!= NULL
; sp
++) {
613 if (strcmp(sp
->state
, state
) == 0)
616 ERROR1(ep
, ebuf
, gettext("Unknown state type \"%s\"\n"), state
);
617 handle_errors(ep
, NULL
, B_FALSE
, B_FALSE
);
622 * Return the numerical algorithm identifier corresponding to the specified
626 parsealg(char *alg
, int proto_num
, char *ebuf
)
628 u_longlong_t invalue
;
629 struct ipsecalgent
*algent
;
633 FATAL(ep
, ebuf
, gettext("Unexpected end of command line, "
634 "was expecting an algorithm name.\n"));
637 algent
= getipsecalgbyname(alg
, proto_num
, NULL
);
638 if (algent
!= NULL
) {
641 alg_num
= algent
->a_alg_num
;
642 if (ALG_FLAG_COUNTERMODE
& algent
->a_alg_flags
)
643 WARN1(ep
, ebuf
, gettext(
644 "Using manual keying with a Counter mode algorithm "
645 "such as \"%s\" may be insecure!\n"),
647 freeipsecalgent(algent
);
653 * Since algorithms can be loaded during kernel run-time, check for
654 * numeric algorithm values too. PF_KEY can catch bad ones with EINVAL.
656 invalue
= parsenum(alg
, B_FALSE
, ebuf
);
657 if (invalue
!= (u_longlong_t
)-1 &&
658 (u_longlong_t
)(invalue
& (u_longlong_t
)0xff) == invalue
)
659 return ((uint8_t)invalue
);
661 if (proto_num
== IPSEC_PROTO_ESP
) {
662 ERROR1(ep
, ebuf
, gettext(
663 "Unknown encryption algorithm type \"%s\"\n"), alg
);
665 ERROR1(ep
, ebuf
, gettext(
666 "Unknown authentication algorithm type \"%s\"\n"), alg
);
668 handle_errors(ep
, NULL
, B_FALSE
, B_FALSE
);
673 * Parse and reverse parse out a source/destination ID type.
675 static struct idtypes
{
679 {"prefix", SADB_IDENTTYPE_PREFIX
},
680 {"fqdn", SADB_IDENTTYPE_FQDN
},
681 {"domain", SADB_IDENTTYPE_FQDN
},
682 {"domainname", SADB_IDENTTYPE_FQDN
},
683 {"user_fqdn", SADB_IDENTTYPE_USER_FQDN
},
684 {"mailbox", SADB_IDENTTYPE_USER_FQDN
},
685 {"der_dn", SADB_X_IDENTTYPE_DN
},
686 {"der_gn", SADB_X_IDENTTYPE_GN
},
691 parseidtype(char *type
, char *ebuf
)
694 u_longlong_t invalue
;
698 /* Shouldn't reach here, see callers for why. */
699 FATAL(ep
, ebuf
, gettext("Unexpected end of command line, "
700 "was expecting a type.\n"));
703 for (idp
= idtypes
; idp
->idtype
!= NULL
; idp
++) {
704 if (strcasecmp(idp
->idtype
, type
) == 0)
705 return (idp
->retval
);
708 * Since identity types are almost arbitrary, check for numeric
709 * algorithm values too. PF_KEY can catch bad ones with EINVAL.
711 invalue
= parsenum(type
, B_FALSE
, ebuf
);
712 if (invalue
!= (u_longlong_t
)-1 &&
713 (u_longlong_t
)(invalue
& (u_longlong_t
)0xffff) == invalue
)
714 return ((uint16_t)invalue
);
717 ERROR1(ep
, ebuf
, gettext("Unknown identity type \"%s\"\n"), type
);
719 handle_errors(ep
, NULL
, B_FALSE
, B_FALSE
);
724 * Parse an address off the command line. Return length of sockaddr,
725 * and either return a hostent pointer (caller frees). The new
726 * getipnodebyname() call does the Right Thing (TM), even with
727 * raw addresses (colon-separated IPv6 or dotted decimal IPv4).
735 struct in6_addr ipv6
;
741 parseaddr(char *addr
, struct hostent
**hpp
, boolean_t v6only
, char *ebuf
)
744 struct hostent
*hp
= NULL
;
748 FATAL(ep
, ebuf
, gettext("Unexpected end of command line, "
749 "was expecting an address.\n"));
754 * Try name->address first. Assume AF_INET6, and
755 * get IPv4's, plus IPv6's if and only if IPv6 is configured.
756 * This means to add IPv6 SAs, you must have IPv6
757 * up-and-running. (AI_DEFAULT works here.)
759 hp
= getipnodebyname(addr
, AF_INET6
,
760 (v6only
? AI_ADDRCONFIG
: (AI_DEFAULT
| AI_ALL
)),
764 * Try a normal address conversion only. Use "dummy"
765 * to construct a fake hostent. Caller will know not
768 if (inet_pton(AF_INET6
, addr
, &addr1
) == 1) {
769 dummy
.he
.h_addr_list
= dummy
.addtl
;
770 dummy
.addtl
[0] = (char *)&addr1
;
771 dummy
.addtl
[1] = NULL
;
773 dummy
.he
.h_addrtype
= AF_INET6
;
774 dummy
.he
.h_length
= sizeof (struct in6_addr
);
775 } else if (inet_pton(AF_INET
, addr
, &addr1
) == 1) {
777 * Remap to AF_INET6 anyway.
779 dummy
.he
.h_addr_list
= dummy
.addtl
;
780 dummy
.addtl
[0] = (char *)&addr1
;
781 dummy
.addtl
[1] = NULL
;
783 dummy
.he
.h_addrtype
= AF_INET6
;
784 dummy
.he
.h_length
= sizeof (struct in6_addr
);
786 * NOTE: If macro changes to disallow in-place
787 * conversion, rewhack this.
789 IN6_INADDR_TO_V4MAPPED(&addr1
.ipv4
, &addr1
.ipv6
);
796 WARN1(ep
, ebuf
, gettext("Unknown address %s."), addr
);
799 /* Always return sockaddr_in6 for now. */
800 handle_errors(ep
, NULL
, B_FALSE
, B_FALSE
);
801 return (sizeof (struct sockaddr_in6
));
805 * Parse a hex character for a key. A string will take the form:
808 * xxxxxxxxx == a string of hex characters ([0-9][a-f][A-F])
809 * nn == an optional decimal "mask". If it is not present, it
810 * is assumed that the hex string will be rounded to the nearest
811 * byte, where odd nibbles, like 123 will become 0x0123.
813 * NOTE:Unlike the expression of IP addresses, I will not allow an
814 * excessive "mask". For example 2112/50 is very illegal.
815 * NOTE2: This key should be in canonical order. Consult your man
816 * pages per algorithm about said order.
819 #define hd2num(hd) (((hd) >= '0' && (hd) <= '9') ? ((hd) - '0') : \
820 (((hd) >= 'a' && (hd) <= 'f') ? ((hd) - 'a' + 10) : ((hd) - 'A' + 10)))
822 static struct sadb_key
*
823 parsekey(char *input
, char *ebuf
, uint_t reserved_bits
)
825 struct sadb_key
*retval
;
826 uint_t i
, hexlen
= 0, bits
, alloclen
;
831 FATAL(ep
, ebuf
, gettext("Unexpected end of command line, "
832 "was expecting a key.\n"));
834 /* Allow hex values prepended with 0x convention */
835 if ((strnlen(input
, sizeof (hexlen
)) > 2) &&
836 (strncasecmp(input
, "0x", 2) == 0))
839 for (i
= 0; input
[i
] != '\0' && input
[i
] != '/'; i
++)
842 if (input
[i
] == '\0') {
847 if (sscanf((input
+ i
+ 1), "%u", &bits
) != 1) {
848 FATAL1(ep
, ebuf
, gettext(
849 "\"%s\" is not a bit specifier.\n"),
852 /* hexlen in nibbles */
853 if (((bits
+ 3) >> 2) > hexlen
) {
854 ERROR2(ep
, ebuf
, gettext(
855 "bit length %d is too big for %s.\n"), bits
, input
);
858 * Adjust hexlen down if user gave us too small of a bit
861 if ((hexlen
<< 2) > bits
+ 3) {
862 WARN2(ep
, ebuf
, gettext(
863 "WARNING: Lower bits will be truncated "
864 "for:\n\t%s/%d.\n"), input
, bits
);
865 hexlen
= (bits
+ 3) >> 2;
866 input
[hexlen
] = '\0';
871 * Allocate. Remember, hexlen is in nibbles.
874 alloclen
= sizeof (*retval
) + roundup((hexlen
/2 + (hexlen
& 0x1)), 8);
875 retval
= malloc(alloclen
);
878 Bail("malloc(parsekey)");
879 retval
->sadb_key_len
= SADB_8TO64(alloclen
);
881 retval
->sadb_key_reserved
= reserved_bits
;
884 retval
->sadb_key_bits
= (hexlen
+ (hexlen
& 0x1)) << 2;
886 retval
->sadb_key_bits
= bits
;
889 * Read in nibbles. Read in odd-numbered as shifted high.
890 * (e.g. 123 becomes 0x1230).
893 key
= (uint8_t *)(retval
+ 1);
894 for (i
= 0; input
[i
] != '\0'; i
+= 2) {
895 boolean_t second
= (input
[i
+ 1] != '\0');
897 if (!isxdigit(input
[i
]) ||
898 (!isxdigit(input
[i
+ 1]) && second
)) {
899 ERROR1(ep
, ebuf
, gettext(
900 "string '%s' not a hex value.\n"), input
);
905 *key
= (hd2num(input
[i
]) << 4);
907 *key
|= hd2num(input
[i
+ 1]);
909 break; /* out of for loop. */
913 /* bzero the remaining bits if we're a non-octet amount. */
915 *((input
[i
] == '\0') ? key
- 1 : key
) &=
916 0xff << (8 - (bits
& 0x7));
918 handle_errors(ep
, NULL
, B_FALSE
, B_FALSE
);
922 #include <tsol/label.h>
924 #define PARSELABEL_BAD_TOKEN ((struct sadb_sens *)-1)
926 static struct sadb_sens
*
927 parselabel(int token
, char *label
)
929 bslabel_t
*sl
= NULL
;
932 int doi
= 1; /* XXX XXX DEFAULT_DOI XXX XXX */
934 err
= str_to_label(label
, &sl
, MAC_LABEL
, L_DEFAULT
, NULL
);
938 len
= ipsec_convert_sl_to_sens(doi
, sl
, NULL
);
942 Bail("malloc parsed label");
943 /* Should exit before reaching here... */
947 (void) ipsec_convert_sl_to_sens(doi
, sl
, sens
);
954 sens
->sadb_sens_exttype
= SADB_X_EXT_OUTER_SENS
;
958 sens
->sadb_sens_exttype
= SADB_X_EXT_OUTER_SENS
;
959 sens
->sadb_x_sens_flags
= SADB_X_SENS_IMPLICIT
;
965 * Return a different return code for a bad label, but really,
966 * this would be a caller error.
968 return (PARSELABEL_BAD_TOKEN
);
975 * Write a message to the PF_KEY socket. If verbose, print the message
976 * heading into the kernel.
979 key_write(int fd
, void *msg
, size_t len
)
983 gettext("VERBOSE ON: Message to kernel looks like:\n"));
984 (void) printf("==========================================\n");
985 print_samsg(stdout
, msg
, B_FALSE
, vflag
, nflag
);
986 (void) printf("==========================================\n");
989 return (write(fd
, msg
, len
));
993 * SIGALRM handler for time_critical_enter.
996 time_critical_catch(int signal
)
998 if (signal
== SIGALRM
) {
999 errx(1, gettext("Reply message from PF_KEY timed out."));
1001 errx(1, gettext("Caught signal %d while trying to receive"
1002 "PF_KEY reply message"), signal
);
1004 /* errx() calls exit. */
1007 #define TIME_CRITICAL_TIME 10 /* In seconds */
1010 * Enter a "time critical" section where key is waiting for a return message.
1013 time_critical_enter(void)
1015 (void) signal(SIGALRM
, time_critical_catch
);
1016 (void) alarm(TIME_CRITICAL_TIME
);
1020 * Exit the "time critical" section after getting an appropriate return
1024 time_critical_exit(void)
1027 (void) signal(SIGALRM
, SIG_DFL
);
1031 * Construct a PF_KEY FLUSH message for the SA type specified.
1036 struct sadb_msg msg
;
1039 msg_init(&msg
, SADB_FLUSH
, (uint8_t)satype
);
1040 rc
= key_write(keysock
, &msg
, sizeof (msg
));
1042 Bail("write() to PF_KEY socket failed (in doflush)");
1044 time_critical_enter();
1046 rc
= read(keysock
, &msg
, sizeof (msg
));
1048 Bail("read (in doflush)");
1049 } while (msg
.sadb_msg_seq
!= seq
|| msg
.sadb_msg_pid
!= mypid
);
1050 time_critical_exit();
1053 * I should _never_ hit the following unless:
1055 * 1. There is a kernel bug.
1056 * 2. There is another process filling in its pid with mine, and
1057 * issuing a different message that would cause a different result.
1059 if (msg
.sadb_msg_type
!= SADB_FLUSH
||
1060 msg
.sadb_msg_satype
!= (uint8_t)satype
) {
1061 syslog((LOG_NOTICE
|LOG_AUTH
),
1062 gettext("doflush: Return message not of type SADB_FLUSH!"));
1063 Bail("doflush: Return message not of type SADB_FLUSH!");
1066 if (msg
.sadb_msg_errno
!= 0) {
1067 errno
= msg
.sadb_msg_errno
;
1068 if (errno
== EINVAL
) {
1069 print_diagnostic(stderr
, msg
.sadb_x_msg_diagnostic
);
1070 warnx(gettext("Cannot flush SA type %d."), satype
);
1072 Bail("return message (in doflush)");
1077 * save_XXX functions are used when "saving" the SA tables to either a
1078 * file or standard output. They use the dump_XXX functions where needed,
1079 * but mostly they use the rparseXXX functions.
1083 * Because "save" and "dump" both use the SADB_DUMP message, fold both
1084 * into the same function.
1087 dodump(int satype
, FILE *ofile
)
1089 struct sadb_msg
*msg
= (struct sadb_msg
*)get_buffer
;
1092 if (ofile
!= NULL
) {
1093 (void) fprintf(ofile
,
1094 gettext("# This key file was generated by the"));
1095 (void) fprintf(ofile
,
1096 gettext(" ipseckey(1m) command's 'save' feature.\n\n"));
1098 msg_init(msg
, SADB_DUMP
, (uint8_t)satype
);
1099 rc
= key_write(keysock
, msg
, sizeof (*msg
));
1101 Bail("write to PF_KEY socket failed (in dodump)");
1105 * For DUMP, do only the read as a time critical section.
1107 time_critical_enter();
1108 rc
= read(keysock
, get_buffer
, sizeof (get_buffer
));
1109 time_critical_exit();
1111 Bail("read (in dodump)");
1112 if (msg
->sadb_msg_pid
== mypid
&&
1113 msg
->sadb_msg_type
== SADB_DUMP
&&
1114 msg
->sadb_msg_seq
!= 0 &&
1115 msg
->sadb_msg_errno
== 0) {
1116 if (ofile
== NULL
) {
1117 print_samsg(stdout
, get_buffer
, B_FALSE
, vflag
,
1119 (void) putchar('\n');
1121 save_assoc(get_buffer
, ofile
);
1124 } while (msg
->sadb_msg_pid
!= mypid
||
1125 (msg
->sadb_msg_errno
== 0 && msg
->sadb_msg_seq
!= 0));
1127 if (ofile
!= NULL
&& ofile
!= stdout
)
1128 (void) fclose(ofile
);
1130 if (msg
->sadb_msg_errno
== 0) {
1133 gettext("Dump succeeded for SA type %d.\n"),
1136 print_diagnostic(stderr
, msg
->sadb_x_msg_diagnostic
);
1137 errno
= msg
->sadb_msg_errno
;
1138 Bail("Dump failed");
1142 #define SCOPE_UNSPEC 0
1143 #define SCOPE_LINKLOCAL 1
1144 #define SCOPE_SITELOCAL 2
1145 #define SCOPE_GLOBAL 3
1146 #define SCOPE_V4COMPAT 4
1147 #define SCOPE_LOOPBACK 5 /* Pedantic, yes, but necessary. */
1150 ipv6_addr_scope(struct in6_addr
*addr
)
1152 /* Don't return anything regarding multicast for now... */
1154 if (IN6_IS_ADDR_UNSPECIFIED(addr
))
1155 return (SCOPE_UNSPEC
);
1157 if (IN6_IS_ADDR_LINKLOCAL(addr
))
1158 return (SCOPE_LINKLOCAL
);
1160 if (IN6_IS_ADDR_SITELOCAL(addr
))
1161 return (SCOPE_SITELOCAL
);
1163 if (IN6_IS_ADDR_V4COMPAT(addr
))
1164 return (SCOPE_V4COMPAT
);
1166 if (IN6_IS_ADDR_LOOPBACK(addr
))
1167 return (SCOPE_LOOPBACK
);
1169 /* For now, return global by default. */
1170 return (SCOPE_GLOBAL
);
1176 * Used by doaddup() and dodelget() to create new SA's based on the
1177 * provided source and destination addresses hostent.
1179 * sadb_msg_type: expected PF_KEY reply message type
1180 * sadb_msg_satype: expected PF_KEY reply satype
1182 * srchp: hostent for the source address(es)
1183 * dsthp: hostent for the destination address(es)
1184 * src: points to the SADB source address extension
1185 * dst: points to the SADB destination address extension
1186 * unspec_src: indicates an unspecified source address.
1187 * buffer: pointer to the SADB buffer to use with PF_KEY
1188 * buffer_size: size of buffer
1189 * spi: spi for this message (set by caller)
1190 * srcport: source port if specified
1191 * dstport: destination port if specified
1192 * proto: IP protocol number if specified
1193 * iproto: Inner (tunnel mode) IP protocol number if specified
1194 * NATT note: we are going to assume a semi-sane world where NAT
1195 * boxen don't explode to multiple addresses.
1198 doaddresses(uint8_t sadb_msg_type
, uint8_t sadb_msg_satype
, int cmd
,
1199 struct hostent
*srchp
, struct hostent
*dsthp
,
1200 struct sadb_address
*src
, struct sadb_address
*dst
,
1201 boolean_t unspec_src
, uint64_t *buffer
, int buffer_size
, uint32_t spi
,
1205 struct sockaddr_in6
*sin6
;
1206 struct sadb_msg
*msgp
;
1208 char **walker
; /* For the SRC and PROXY walking functions. */
1210 uint64_t savebuf
[MAX_GET_SIZE
];
1211 uint16_t srcport
= 0, dstport
= 0;
1215 * Okay, now we have "src", "dst", and maybe "proxy" reassigned
1216 * to point into the buffer to be written to PF_KEY, we can do
1217 * potentially several writes based on destination address.
1219 * First, obtain port numbers from passed-in extensions.
1223 sin6
= (struct sockaddr_in6
*)(src
+ 1);
1224 srcport
= ntohs(sin6
->sin6_port
);
1227 sin6
= (struct sockaddr_in6
*)(dst
+ 1);
1228 dstport
= ntohs(sin6
->sin6_port
);
1232 * The rules for ADD, GET, and UPDATE: (NOTE: This assumes IPsec.
1233 * If other consumers of PF_KEY happen, this will have to be
1236 * Do a message for every possible DST address.
1238 * If a source or proxy address explodes, keep unspecified
1239 * (and mention unspecified).
1241 * DELETE is different, because you can leave either "src" or "dst"
1242 * blank! You need to explode if one of them is full, and not assume
1243 * that the other is set.
1246 if (dsthp
== NULL
) {
1248 * No destination address specified.
1249 * With extended diagnostics, we don't have to bail the
1250 * non-DELETE cases here. The EINVAL diagnostics will be
1251 * enough to inform the user(s) what happened.
1255 if (srchp
== &dummy
.he
) {
1256 /* Just to be sure... */
1257 srchp
->h_addr_list
[1] = NULL
;
1258 } else if (srchp
!= NULL
) {
1259 /* Degenerate case, h_addr_list[0] == NULL. */
1260 if (srchp
->h_addr_list
[i
] == NULL
)
1261 Bail("Empty source address list");
1264 * Fill in the src sockaddr.
1266 sin6
= (struct sockaddr_in6
*)(src
+ 1);
1267 bzero(sin6
, sizeof (*sin6
));
1268 bcopy(srchp
->h_addr_list
[i
], &sin6
->sin6_addr
,
1269 sizeof (struct in6_addr
));
1270 sin6
->sin6_family
= AF_INET6
;
1271 sin6
->sin6_port
= htons(srcport
);
1274 /* Save off a copy for later writing... */
1275 msgp
= (struct sadb_msg
*)buffer
;
1276 bcopy(buffer
, savebuf
, SADB_64TO8(msgp
->sadb_msg_len
));
1278 rc
= key_write(keysock
, buffer
,
1279 SADB_64TO8(msgp
->sadb_msg_len
));
1281 Bail("write() to PF_KEY socket "
1282 "(in doaddresses)");
1284 * Sends the message to the Solaris Cluster daemon
1287 if (in_cluster_mode
) {
1288 (void) sendto(cluster_socket
, buffer
,
1289 SADB_64TO8(msgp
->sadb_msg_len
), 0,
1290 (struct sockaddr
*)&cli_addr
,
1294 time_critical_enter();
1296 rc
= read(keysock
, buffer
, buffer_size
);
1298 Bail("read (in doaddresses)");
1299 } while (msgp
->sadb_msg_seq
!= seq
||
1300 msgp
->sadb_msg_pid
!= mypid
);
1301 time_critical_exit();
1303 if (msgp
->sadb_msg_type
!= sadb_msg_type
||
1304 msgp
->sadb_msg_satype
!= sadb_msg_satype
) {
1305 syslog((LOG_NOTICE
|LOG_AUTH
), gettext(
1306 "doaddresses: Unexpected returned message "
1307 "(%d exp %d)\n"), msgp
->sadb_msg_type
,
1309 Bail("doaddresses: Unexpected returned "
1313 errno
= msgp
->sadb_msg_errno
;
1315 if (errno
== EINVAL
) {
1316 WARN(ep
, ebuf
, gettext(
1317 "One of the entered "
1318 "values is incorrect."));
1319 print_diagnostic(stderr
,
1320 msgp
->sadb_x_msg_diagnostic
);
1322 Bail("return message (in doaddresses)");
1326 /* ...and then restore the saved buffer. */
1327 msgp
= (struct sadb_msg
*)savebuf
;
1328 bcopy(savebuf
, buffer
, SADB_64TO8(msgp
->sadb_msg_len
));
1329 } while (srchp
!= NULL
&& srchp
->h_addr_list
[++i
] != NULL
);
1334 * Go through the list of all dst addresses, trying to find matching
1335 * src address for each. If the first address is == dummy.he we will go
1336 * through the loop just once. If any other hp is == dummy.he, then we
1337 * don't have to apply any silly rules.
1339 for (i
= 0; dsthp
->h_addr_list
[i
] != NULL
; i
++) {
1340 if (dsthp
== &dummy
.he
) {
1341 /* Just to be sure... */
1342 dsthp
->h_addr_list
[1] = NULL
;
1345 * Fill in the dst sockaddr.
1347 sin6
= (struct sockaddr_in6
*)(dst
+ 1);
1348 bzero(sin6
, sizeof (*sin6
));
1349 bcopy(dsthp
->h_addr_list
[i
], &sin6
->sin6_addr
,
1350 sizeof (struct in6_addr
));
1351 sin6
->sin6_family
= AF_INET6
;
1352 sin6
->sin6_port
= htons(dstport
);
1355 last_dst
= (dsthp
->h_addr_list
[i
+ 1] == NULL
);
1358 * Try and assign src, if there's any ambiguity.
1360 if (!unspec_src
&& srchp
!= &dummy
.he
) {
1361 if (IN6_IS_ADDR_V4MAPPED(&sin6
->sin6_addr
)) {
1363 * IPv4 address. Find an IPv4 address, then
1364 * keep looking for a second one. If a second
1365 * exists, print a message, and fill in the
1366 * unspecified address.
1370 for (walker
= srchp
->h_addr_list
;
1371 *walker
!= NULL
; walker
++) {
1372 /* LINTED E_BAD_PTR_CAST_ALIGN */
1373 if (IN6_IS_ADDR_V4MAPPED(
1374 (struct in6_addr
*)*walker
)) {
1375 if (first_match
!= NULL
)
1378 first_match
= *walker
;
1381 sin6
= (struct sockaddr_in6
*)(src
+ 1);
1382 bzero(sin6
, sizeof (*sin6
));
1384 if (first_match
== NULL
) {
1386 * No IPv4 hits. Is this the last
1387 * destination address in the list ?
1389 ERROR1(ep
, ebuf
, gettext(
1390 "No IPv4 source address "
1391 "for name %s.\n"), srchp
->h_name
);
1393 FATAL(ep
, ebuf
, gettext(
1394 "No match for destination "
1397 /* Continue, but do I print? */
1398 continue; /* for loop */
1401 /* I should never reach here. */
1404 sin6
->sin6_family
= AF_INET6
;
1405 sin6
->sin6_port
= htons(srcport
);
1406 if (*walker
!= NULL
) {
1408 * Early loop exit. It must've been
1411 * Issue a null-source warning?
1413 WARN1(ep
, ebuf
, gettext(
1414 "Multiple IPv4 source addresses "
1415 "for %s, using unspecified source "
1416 "instead."), srchp
->h_name
);
1419 * If I reach here w/o hitting the
1420 * previous if statements, I have a
1421 * single source address for this
1424 bcopy(first_match
, &sin6
->sin6_addr
,
1425 sizeof (struct in6_addr
));
1429 * IPv6 address. Find an IPv6 address.
1430 * Unlike IPv4 addresses, things can get a
1431 * little more sticky with scopes, etc.
1433 int dst_scope
, src_scope
;
1435 dst_scope
= ipv6_addr_scope(&sin6
->sin6_addr
);
1438 for (walker
= srchp
->h_addr_list
;
1439 *walker
!= NULL
; walker
++) {
1440 /* LINTED E_BAD_PTR_CAST_ALIGN */
1441 if (!IN6_IS_ADDR_V4MAPPED(
1442 (struct in6_addr
*)*walker
)) {
1444 * Set first-match, etc.
1445 * Take into account scopes,
1446 * and other IPv6 thingies.
1448 src_scope
= ipv6_addr_scope(
1449 /* LINTED E_BAD_PTR_CAST */
1450 (struct in6_addr
*)*walker
);
1451 if (src_scope
== SCOPE_UNSPEC
||
1452 src_scope
== dst_scope
) {
1463 sin6
= (struct sockaddr_in6
*)(src
+ 1);
1464 bzero(sin6
, sizeof (*sin6
));
1465 sin6
->sin6_port
= htons(srcport
);
1466 if (first_match
== NULL
) {
1468 * No IPv6 hits. Is this the last
1469 * destination address in the list ?
1471 ERROR1(ep
, ebuf
, gettext(
1472 "No IPv6 source address of "
1473 "matching scope for name %s.\n"),
1476 FATAL(ep
, ebuf
, gettext(
1477 "No match for IPV6 "
1481 /* Continue, but do I print? */
1482 continue; /* for loop */
1485 /* I should never reach here. */
1487 sin6
->sin6_family
= AF_INET6
;
1488 if (*walker
!= NULL
) {
1490 * Early loop exit. Issue a
1491 * null-source warning?
1493 WARN1(ep
, ebuf
, gettext(
1494 "Multiple IPv6 source addresses "
1495 "for %s of the same scope, using "
1496 "unspecified source instead.\n"),
1500 * If I reach here w/o hitting the
1501 * previous if statements, I have a
1502 * single source address for this
1505 bcopy(first_match
, &sin6
->sin6_addr
,
1506 sizeof (struct in6_addr
));
1512 * If there are errors at this point there is no
1513 * point sending anything to PF_KEY.
1515 handle_errors(ep
, ebuf
, B_TRUE
, B_FALSE
);
1517 /* Save off a copy for later writing... */
1518 msgp
= (struct sadb_msg
*)buffer
;
1519 bcopy(buffer
, savebuf
, SADB_64TO8(msgp
->sadb_msg_len
));
1521 rc
= key_write(keysock
, buffer
, SADB_64TO8(msgp
->sadb_msg_len
));
1523 Bail("write() to PF_KEY socket (in doaddresses)");
1525 if (in_cluster_mode
) {
1526 (void) sendto(cluster_socket
, buffer
,
1527 SADB_64TO8(msgp
->sadb_msg_len
), 0,
1528 (struct sockaddr
*)&cli_addr
,
1531 /* Blank the key for paranoia's sake. */
1532 bzero(buffer
, buffer_size
);
1533 time_critical_enter();
1535 rc
= read(keysock
, buffer
, buffer_size
);
1537 Bail("read (in doaddresses)");
1538 } while (msgp
->sadb_msg_seq
!= seq
||
1539 msgp
->sadb_msg_pid
!= mypid
);
1540 time_critical_exit();
1543 * I should _never_ hit the following unless:
1545 * 1. There is a kernel bug.
1546 * 2. Another process is mistakenly using my pid in a PF_KEY
1549 if (msgp
->sadb_msg_type
!= sadb_msg_type
||
1550 msgp
->sadb_msg_satype
!= sadb_msg_satype
) {
1551 syslog((LOG_NOTICE
|LOG_AUTH
), gettext(
1552 "doaddresses: Unexpected returned message "
1553 "(%d exp %d)\n"), msgp
->sadb_msg_type
,
1555 Bail("doaddresses: Unexpected returned message");
1558 if (msgp
->sadb_msg_errno
!= 0) {
1559 char addrprint
[INET6_ADDRSTRLEN
];
1564 * Print different error messages depending
1565 * on the SADB message type being processed.
1566 * If we get a ESRCH error for a GET/DELETE
1567 * messages, we report that the SA does not
1568 * exist. If we get a EEXIST error for a
1569 * ADD/UPDATE message, we report that the
1570 * SA already exists.
1572 if (sadb_msg_type
== SADB_GET
||
1573 sadb_msg_type
== SADB_DELETE
) {
1575 on_errno_msg
= "does not exist";
1576 } else if (sadb_msg_type
== SADB_ADD
||
1577 sadb_msg_type
== SADB_UPDATE
) {
1579 on_errno_msg
= "already exists";
1582 errno
= msgp
->sadb_msg_errno
;
1583 if (errno
== on_errno
) {
1584 ERROR2(ep
, ebuf
, gettext(
1585 "Association (type = %s) "
1586 "with spi 0x%x and addr\n"),
1587 rparsesatype(msgp
->sadb_msg_satype
),
1589 ERROR2(ep
, ebuf
, "%s %s.\n",
1590 do_inet_ntop(dsthp
->h_addr_list
[i
],
1591 addrprint
, sizeof (addrprint
)),
1593 msgp
= (struct sadb_msg
*)savebuf
;
1594 bcopy(savebuf
, buffer
,
1595 SADB_64TO8(msgp
->sadb_msg_len
));
1598 if (errno
== EINVAL
|| errno
== ESRCH
) {
1599 ERROR2(ep
, ebuf
, gettext(
1600 "PF_KEY Diagnostic code %u: %s.\n"),
1601 msgp
->sadb_x_msg_diagnostic
,
1603 msgp
->sadb_x_msg_diagnostic
));
1605 Bail("return message (in doaddresses)");
1610 if (cmd
== CMD_GET
) {
1611 if (msgp
->sadb_msg_len
> MAX_GET_SIZE
) {
1612 WARN1(ep
, ebuf
, gettext("WARNING: "
1613 "SA information bigger than %d bytes.\n"),
1614 SADB_64TO8(MAX_GET_SIZE
));
1616 print_samsg(stdout
, buffer
, B_FALSE
, vflag
, nflag
);
1619 handle_errors(ep
, ebuf
, B_TRUE
, B_FALSE
);
1621 /* ...and then restore the saved buffer. */
1622 msgp
= (struct sadb_msg
*)savebuf
;
1623 bcopy(savebuf
, buffer
, SADB_64TO8(msgp
->sadb_msg_len
));
1627 /* Degenerate case, h_addr_list[0] == NULL. */
1629 Bail("Empty destination address list");
1632 * free(ebuf) even if there are no errors.
1633 * handle_errors() won't return here.
1635 handle_errors(ep
, ebuf
, B_TRUE
, B_TRUE
);
1639 * Perform an add or an update. ADD and UPDATE are similar in the extensions
1643 doaddup(int cmd
, int satype
, char *argv
[], char *ebuf
)
1645 uint64_t *buffer
, *nexthdr
;
1646 struct sadb_msg msg
;
1647 struct sadb_sa
*assoc
= NULL
;
1648 struct sadb_x_pair
*sadb_pair
= NULL
;
1649 struct sadb_address
*src
= NULL
, *dst
= NULL
;
1650 struct sadb_address
*isrc
= NULL
, *idst
= NULL
;
1651 struct sadb_address
*natt_local
= NULL
, *natt_remote
= NULL
;
1652 struct sadb_key
*encrypt
= NULL
, *auth
= NULL
;
1653 struct sadb_ident
*srcid
= NULL
, *dstid
= NULL
;
1654 struct sadb_lifetime
*hard
= NULL
, *soft
= NULL
; /* Current? */
1655 struct sadb_lifetime
*idle
= NULL
;
1656 struct sadb_x_replay_ctr
*replay_ctr
= NULL
;
1657 struct sadb_sens
*label
= NULL
, *olabel
= NULL
;
1658 struct sockaddr_in6
*sin6
;
1659 /* MLS TODO: Need sensitivity eventually. */
1660 int next
, token
, sa_len
, alloclen
, totallen
= sizeof (msg
), prefix
;
1662 uint_t reserved_bits
= 0;
1663 uint8_t sadb_msg_type
;
1664 char *thiscmd
, *pstr
;
1665 boolean_t readstate
= B_FALSE
, unspec_src
= B_FALSE
;
1666 boolean_t alloc_inner
= B_FALSE
, use_natt
= B_FALSE
;
1667 struct hostent
*srchp
= NULL
, *dsthp
= NULL
, *isrchp
= NULL
,
1669 struct hostent
*natt_lhp
= NULL
, *natt_rhp
= NULL
;
1670 uint16_t srcport
= 0, dstport
= 0, natt_lport
= 0, natt_rport
= 0,
1671 isrcport
= 0, idstport
= 0;
1672 uint8_t proto
= 0, iproto
= 0;
1678 sadb_msg_type
= SADB_ADD
;
1682 sadb_msg_type
= SADB_UPDATE
;
1684 case CMD_UPDATE_PAIR
:
1685 thiscmd
= "update-pair";
1686 sadb_msg_type
= SADB_X_UPDATEPAIR
;
1690 msg_init(&msg
, sadb_msg_type
, (uint8_t)satype
);
1691 /* Assume last element in argv is set to NULL. */
1693 token
= parseextval(*argv
, &next
);
1697 /* Do nothing, I'm done. */
1700 ERROR1(ep
, ebuf
, gettext(
1701 "Unknown extension field \"%s\" \n"), *(argv
- 1));
1711 * May want to place this chunk of code in a function.
1713 * This code checks for duplicate entries on a command
1717 /* Allocate the SADB_EXT_SA extension. */
1718 if (assoc
== NULL
) {
1719 assoc
= malloc(sizeof (*assoc
));
1721 Bail("malloc(assoc)");
1722 bzero(assoc
, sizeof (*assoc
));
1723 assoc
->sadb_sa_exttype
= SADB_EXT_SA
;
1724 assoc
->sadb_sa_len
=
1725 SADB_8TO64(sizeof (*assoc
));
1726 totallen
+= sizeof (*assoc
);
1731 * If some cretin types in "spi 0" then they
1732 * can type in another SPI.
1734 if (assoc
->sadb_sa_spi
!= 0) {
1735 ERROR(ep
, ebuf
, gettext(
1737 "single SPI value.\n"));
1740 /* Must convert SPI to network order! */
1741 assoc
->sadb_sa_spi
=
1742 htonl((uint32_t)parsenum(*argv
, B_TRUE
,
1744 if (assoc
->sadb_sa_spi
== 0) {
1745 ERROR(ep
, ebuf
, gettext(
1746 "Invalid SPI value \"0\" .\n"));
1750 if (cmd
== CMD_UPDATE_PAIR
) {
1751 ERROR(ep
, ebuf
, gettext(
1752 "pair-spi can not be used with the "
1753 "\"update-pair\" command.\n"));
1755 if (sadb_pair
== NULL
) {
1756 sadb_pair
= malloc(sizeof (*sadb_pair
));
1758 Bail("malloc(assoc)");
1759 bzero(sadb_pair
, sizeof (*sadb_pair
));
1760 totallen
+= sizeof (*sadb_pair
);
1762 if (sadb_pair
->sadb_x_pair_spi
!= 0) {
1763 ERROR(ep
, ebuf
, gettext(
1765 "single pair SPI value.\n"));
1768 /* Must convert SPI to network order! */
1769 sadb_pair
->sadb_x_pair_len
=
1770 SADB_8TO64(sizeof (*sadb_pair
));
1771 sadb_pair
->sadb_x_pair_exttype
=
1773 sadb_pair
->sadb_x_pair_spi
=
1774 htonl((uint32_t)parsenum(*argv
, B_TRUE
,
1776 if (sadb_pair
->sadb_x_pair_spi
== 0) {
1777 ERROR(ep
, ebuf
, gettext(
1778 "Invalid SPI value \"0\" .\n"));
1780 assoc
->sadb_sa_flags
|=
1781 SADB_X_SAFLAGS_PAIRED
;
1785 * That same cretin can do the same with
1788 if (assoc
->sadb_sa_replay
!= 0) {
1789 ERROR(ep
, ebuf
, gettext(
1791 "single replay window size.\n"));
1794 assoc
->sadb_sa_replay
=
1795 (uint8_t)parsenum(*argv
, B_TRUE
, ebuf
);
1796 if (assoc
->sadb_sa_replay
!= 0) {
1797 WARN(ep
, ebuf
, gettext(
1798 "WARNING: Replay with manual"
1799 " keying considered harmful.\n"));
1804 * 0 is an actual state value, LARVAL. This
1805 * means that one can type in the larval state
1806 * and then type in another state on the same
1809 if (assoc
->sadb_sa_state
!= 0) {
1810 ERROR(ep
, ebuf
, gettext(
1812 "single SA state.\n"));
1815 assoc
->sadb_sa_state
= parsestate(*argv
,
1820 if (assoc
->sadb_sa_auth
!= 0) {
1821 ERROR(ep
, ebuf
, gettext(
1823 "single auth algorithm.\n"));
1826 assoc
->sadb_sa_auth
= parsealg(*argv
,
1827 IPSEC_PROTO_AH
, ebuf
);
1830 if (satype
== SADB_SATYPE_AH
) {
1831 ERROR(ep
, ebuf
, gettext("Cannot specify"
1832 " encryption with SA type ah.\n"));
1835 if (assoc
->sadb_sa_encrypt
!= 0) {
1836 ERROR(ep
, ebuf
, gettext(
1838 "single encryption algorithm.\n"));
1841 assoc
->sadb_sa_encrypt
= parsealg(*argv
,
1842 IPSEC_PROTO_ESP
, ebuf
);
1846 ERROR(ep
, ebuf
, gettext(
1847 "Can only specify single"
1848 " encapsulation.\n"));
1851 if (strncmp(*argv
, "udp", 3)) {
1852 ERROR(ep
, ebuf
, gettext(
1853 "Can only specify udp"
1854 " encapsulation.\n"));
1858 /* set assoc flags later */
1865 ERROR(ep
, ebuf
, gettext("Can only specify "
1866 "single source port.\n"));
1869 srcport
= parsenum(*argv
, B_TRUE
, ebuf
);
1874 ERROR(ep
, ebuf
, gettext("Can only specify "
1875 "single destination port.\n"));
1878 dstport
= parsenum(*argv
, B_TRUE
, ebuf
);
1882 alloc_inner
= B_TRUE
;
1883 if (isrcport
!= 0) {
1884 ERROR(ep
, ebuf
, gettext(
1886 "single inner-source port.\n"));
1889 isrcport
= parsenum(*argv
, B_TRUE
, ebuf
);
1893 alloc_inner
= B_TRUE
;
1894 if (idstport
!= 0) {
1895 ERROR(ep
, ebuf
, gettext(
1897 "single inner-destination port.\n"));
1900 idstport
= parsenum(*argv
, B_TRUE
, ebuf
);
1904 if (natt_lport
!= 0) {
1905 ERROR(ep
, ebuf
, gettext(
1907 "single NAT-T local port.\n"));
1910 natt_lport
= parsenum(*argv
, B_TRUE
, ebuf
);
1914 if (natt_rport
!= 0) {
1915 ERROR(ep
, ebuf
, gettext(
1917 "single NAT-T remote port.\n"));
1920 natt_rport
= parsenum(*argv
, B_TRUE
, ebuf
);
1926 ERROR(ep
, ebuf
, gettext(
1928 "single protocol.\n"));
1931 proto
= parsenum(*argv
, B_TRUE
, ebuf
);
1935 alloc_inner
= B_TRUE
;
1937 ERROR(ep
, ebuf
, gettext(
1939 "single inner protocol.\n"));
1942 iproto
= parsenum(*argv
, B_TRUE
, ebuf
);
1948 ERROR(ep
, ebuf
, gettext(
1950 "single source address.\n"));
1953 sa_len
= parseaddr(*argv
, &srchp
,
1954 (token
== TOK_SRCADDR6
), ebuf
);
1955 if (srchp
== NULL
) {
1956 ERROR1(ep
, ebuf
, gettext(
1957 "Unknown src address \"%s\"\n"), *argv
);
1962 * Round of the sockaddr length to an 8 byte
1963 * boundary to make PF_KEY happy.
1965 alloclen
= sizeof (*src
) + roundup(sa_len
, 8);
1966 src
= malloc(alloclen
);
1968 Bail("malloc(src)");
1969 totallen
+= alloclen
;
1970 src
->sadb_address_len
= SADB_8TO64(alloclen
);
1971 src
->sadb_address_exttype
= SADB_EXT_ADDRESS_SRC
;
1972 src
->sadb_address_reserved
= 0;
1973 src
->sadb_address_prefixlen
= 0;
1974 src
->sadb_address_proto
= 0;
1975 if (srchp
== &dummy
.he
) {
1977 * Single address with -n flag.
1979 sin6
= (struct sockaddr_in6
*)(src
+ 1);
1980 bzero(sin6
, sizeof (*sin6
));
1981 sin6
->sin6_family
= AF_INET6
;
1982 bcopy(srchp
->h_addr_list
[0], &sin6
->sin6_addr
,
1983 sizeof (struct in6_addr
));
1989 ERROR(ep
, ebuf
, gettext(
1990 "Can only specify single "
1991 "destination address.\n"));
1994 sa_len
= parseaddr(*argv
, &dsthp
,
1995 (token
== TOK_DSTADDR6
), ebuf
);
1996 if (dsthp
== NULL
) {
1997 ERROR1(ep
, ebuf
, gettext(
1998 "Unknown dst address \"%s\"\n"), *argv
);
2002 alloclen
= sizeof (*dst
) + roundup(sa_len
, 8);
2003 dst
= malloc(alloclen
);
2005 Bail("malloc(dst)");
2006 totallen
+= alloclen
;
2007 dst
->sadb_address_len
= SADB_8TO64(alloclen
);
2008 dst
->sadb_address_exttype
= SADB_EXT_ADDRESS_DST
;
2009 dst
->sadb_address_reserved
= 0;
2010 dst
->sadb_address_prefixlen
= 0;
2011 dst
->sadb_address_proto
= 0;
2012 if (dsthp
== &dummy
.he
) {
2014 * Single address with -n flag.
2016 sin6
= (struct sockaddr_in6
*)(dst
+ 1);
2017 bzero(sin6
, sizeof (*sin6
));
2018 sin6
->sin6_family
= AF_INET6
;
2019 bcopy(dsthp
->h_addr_list
[0], &sin6
->sin6_addr
,
2020 sizeof (struct in6_addr
));
2024 case TOK_PROXYADDR6
:
2026 ERROR(ep
, ebuf
, gettext(
2027 "Can only specify single "
2028 "proxy/inner-source address.\n"));
2031 if ((pstr
= strchr(*argv
, '/')) != NULL
) {
2032 /* Parse out the prefix. */
2034 prefix
= strtol(pstr
+ 1, NULL
, 10);
2036 ERROR1(ep
, ebuf
, gettext(
2037 "Invalid prefix %s."), pstr
);
2041 alloclen
= (int)(pstr
- *argv
);
2042 pstr
= malloc(alloclen
+ 1);
2044 Bail("malloc(pstr)");
2046 (void) strlcpy(pstr
, *argv
, alloclen
+ 1);
2050 * Assume mapping to AF_INET6, and we're a host.
2051 * XXX some miscreants may still make classful
2052 * assumptions. If this is a problem, fix it
2057 sa_len
= parseaddr(pstr
, &isrchp
,
2058 (token
== TOK_PROXYADDR6
), ebuf
);
2059 if (isrchp
== NULL
) {
2060 ERROR1(ep
, ebuf
, gettext(
2061 "Unknown proxy/inner-source address "
2062 "\"%s\"\n"), *argv
);
2068 alloclen
= sizeof (*isrc
) + roundup(sa_len
, 8);
2069 isrc
= malloc(alloclen
);
2071 Bail("malloc(isrc)");
2072 totallen
+= alloclen
;
2073 isrc
->sadb_address_len
= SADB_8TO64(alloclen
);
2074 isrc
->sadb_address_exttype
= SADB_EXT_ADDRESS_PROXY
;
2075 isrc
->sadb_address_reserved
= 0;
2076 isrc
->sadb_address_prefixlen
= prefix
;
2077 isrc
->sadb_address_proto
= 0;
2078 if (isrchp
== &dummy
.he
||
2079 isrchp
->h_addr_list
[1] == NULL
) {
2081 * Single address with -n flag or single name.
2083 sin6
= (struct sockaddr_in6
*)(isrc
+ 1);
2084 bzero(sin6
, sizeof (*sin6
));
2085 sin6
->sin6_family
= AF_INET6
;
2086 bcopy(isrchp
->h_addr_list
[0], &sin6
->sin6_addr
,
2087 sizeof (struct in6_addr
));
2089 * normalize prefixlen for IPv4-mapped
2093 IN6_IS_ADDR_V4MAPPED(&sin6
->sin6_addr
))
2094 isrc
->sadb_address_prefixlen
+= 96;
2095 alloc_inner
= B_TRUE
;
2098 * If the proxy/isrc address is vague, don't
2101 totallen
-= alloclen
;
2104 WARN1(ep
, ebuf
, gettext(
2105 "Proxy/inner-source address %s "
2106 "is vague, not using.\n"), isrchp
->h_name
);
2107 freehostent(isrchp
);
2115 ERROR(ep
, ebuf
, gettext(
2116 "Can only specify single "
2117 "inner-destination address.\n"));
2120 if ((pstr
= strchr(*argv
, '/')) != NULL
) {
2121 /* Parse out the prefix. */
2123 prefix
= strtol(pstr
+ 1, NULL
, 10);
2125 ERROR1(ep
, ebuf
, gettext(
2126 "Invalid prefix %s.\n"), pstr
);
2130 alloclen
= (int)(pstr
- *argv
);
2131 pstr
= malloc(alloclen
+ 1);
2133 Bail("malloc(pstr)");
2135 (void) strlcpy(pstr
, *argv
, alloclen
+ 1);
2139 * Assume mapping to AF_INET6, and we're a host.
2140 * XXX some miscreants may still make classful
2141 * assumptions. If this is a problem, fix it
2146 sa_len
= parseaddr(pstr
, &idsthp
,
2147 (token
== TOK_IDSTADDR6
), ebuf
);
2148 if (idsthp
== NULL
) {
2149 ERROR1(ep
, ebuf
, gettext(
2150 "Unknown Inner Src address "
2151 " \"%s\"\n"), *argv
);
2157 alloclen
= sizeof (*idst
) + roundup(sa_len
, 8);
2158 idst
= malloc(alloclen
);
2160 Bail("malloc(idst)");
2161 totallen
+= alloclen
;
2162 idst
->sadb_address_len
= SADB_8TO64(alloclen
);
2163 idst
->sadb_address_exttype
=
2164 SADB_X_EXT_ADDRESS_INNER_DST
;
2165 idst
->sadb_address_reserved
= 0;
2166 idst
->sadb_address_prefixlen
= prefix
;
2167 idst
->sadb_address_proto
= 0;
2168 if (idsthp
== &dummy
.he
||
2169 idsthp
->h_addr_list
[1] == NULL
) {
2171 * Single address with -n flag or single name.
2173 sin6
= (struct sockaddr_in6
*)(idst
+ 1);
2174 bzero(sin6
, sizeof (*sin6
));
2175 sin6
->sin6_family
= AF_INET6
;
2176 bcopy(idsthp
->h_addr_list
[0], &sin6
->sin6_addr
,
2177 sizeof (struct in6_addr
));
2179 * normalize prefixlen for IPv4-mapped
2183 IN6_IS_ADDR_V4MAPPED(&sin6
->sin6_addr
))
2184 idst
->sadb_address_prefixlen
+= 96;
2185 alloc_inner
= B_TRUE
;
2188 * If the idst address is vague, don't bother.
2190 totallen
-= alloclen
;
2193 WARN1(ep
, ebuf
, gettext(
2194 "Inner destination address %s "
2195 "is vague, not using.\n"), idsthp
->h_name
);
2196 freehostent(idsthp
);
2202 if (natt_local
!= NULL
) {
2203 ERROR(ep
, ebuf
, gettext(
2205 "single NAT-T local address.\n"));
2208 sa_len
= parseaddr(*argv
, &natt_lhp
, 0, ebuf
);
2209 if (natt_lhp
== NULL
) {
2210 ERROR1(ep
, ebuf
, gettext(
2211 "Unknown NAT-T local address \"%s\"\n"),
2217 * Round of the sockaddr length to an 8 byte
2218 * boundary to make PF_KEY happy.
2220 alloclen
= sizeof (*natt_local
) + roundup(sa_len
, 8);
2221 natt_local
= malloc(alloclen
);
2222 if (natt_local
== NULL
)
2223 Bail("malloc(natt_local)");
2224 totallen
+= alloclen
;
2225 natt_local
->sadb_address_len
= SADB_8TO64(alloclen
);
2226 natt_local
->sadb_address_exttype
=
2227 SADB_X_EXT_ADDRESS_NATT_LOC
;
2228 natt_local
->sadb_address_reserved
= 0;
2229 natt_local
->sadb_address_prefixlen
= 0;
2230 natt_local
->sadb_address_proto
= 0;
2231 if (natt_lhp
== &dummy
.he
||
2232 natt_lhp
->h_addr_list
[1] == NULL
) {
2234 * Single address with -n flag or single name.
2236 sin6
= (struct sockaddr_in6
*)(natt_local
+ 1);
2237 bzero(sin6
, sizeof (*sin6
));
2238 sin6
->sin6_family
= AF_INET6
;
2239 bcopy(natt_lhp
->h_addr_list
[0],
2240 &sin6
->sin6_addr
, sizeof (struct in6_addr
));
2243 * If the nat-local address is vague, don't
2246 totallen
-= alloclen
;
2249 WARN1(ep
, ebuf
, gettext(
2250 "NAT-T local address %s "
2251 "is vague, not using.\n"),
2253 freehostent(natt_lhp
);
2259 if (natt_remote
!= NULL
) {
2260 ERROR(ep
, ebuf
, gettext(
2262 "single NAT-T remote address.\n"));
2265 sa_len
= parseaddr(*argv
, &natt_rhp
, 0, ebuf
);
2266 if (natt_rhp
== NULL
) {
2267 ERROR1(ep
, ebuf
, gettext(
2268 "Unknown NAT-T remote address \"%s\"\n"),
2274 * Round of the sockaddr length to an 8 byte
2275 * boundary to make PF_KEY happy.
2277 alloclen
= sizeof (*natt_remote
) + roundup(sa_len
, 8);
2278 natt_remote
= malloc(alloclen
);
2279 if (natt_remote
== NULL
)
2280 Bail("malloc(natt_remote)");
2281 totallen
+= alloclen
;
2282 natt_remote
->sadb_address_len
= SADB_8TO64(alloclen
);
2283 natt_remote
->sadb_address_exttype
=
2284 SADB_X_EXT_ADDRESS_NATT_REM
;
2285 natt_remote
->sadb_address_reserved
= 0;
2286 natt_remote
->sadb_address_prefixlen
= 0;
2287 natt_remote
->sadb_address_proto
= 0;
2288 if (natt_rhp
== &dummy
.he
||
2289 natt_rhp
->h_addr_list
[1] == NULL
) {
2291 * Single address with -n flag or single name.
2293 sin6
= (struct sockaddr_in6
*)(natt_remote
+ 1);
2294 bzero(sin6
, sizeof (*sin6
));
2295 sin6
->sin6_family
= AF_INET6
;
2296 bcopy(natt_rhp
->h_addr_list
[0],
2297 &sin6
->sin6_addr
, sizeof (struct in6_addr
));
2300 * If the nat-renote address is vague, don't
2303 totallen
-= alloclen
;
2306 WARN1(ep
, ebuf
, gettext(
2307 "NAT-T remote address %s "
2308 "is vague, not using.\n"),
2310 freehostent(natt_rhp
);
2316 if (encrypt
!= NULL
) {
2317 ERROR(ep
, ebuf
, gettext(
2319 "single encryption key.\n"));
2322 if (assoc
!= NULL
&&
2323 assoc
->sadb_sa_encrypt
== SADB_EALG_NULL
) {
2324 FATAL(ep
, ebuf
, gettext(
2325 "Cannot specify a key with NULL "
2326 "encryption algorithm.\n"));
2329 encrypt
= parsekey(*argv
, ebuf
, reserved_bits
);
2331 if (encrypt
== NULL
) {
2332 ERROR(ep
, ebuf
, gettext(
2333 "Invalid encryption key.\n"));
2336 totallen
+= SADB_64TO8(encrypt
->sadb_key_len
);
2337 encrypt
->sadb_key_exttype
= SADB_EXT_KEY_ENCRYPT
;
2341 ERROR(ep
, ebuf
, gettext(
2342 "Can only specify single"
2343 " authentication key.\n"));
2346 auth
= parsekey(*argv
, ebuf
, 0);
2349 ERROR(ep
, ebuf
, gettext(
2350 "Invalid authentication key.\n"));
2353 totallen
+= SADB_64TO8(auth
->sadb_key_len
);
2354 auth
->sadb_key_exttype
= SADB_EXT_KEY_AUTH
;
2357 if (*argv
== NULL
|| *(argv
+ 1) == NULL
) {
2358 FATAL(ep
, ebuf
, gettext(
2359 "Unexpected end of command "
2360 "line - Expecting Src Type.\n"));
2364 if (srcid
!= NULL
) {
2365 ERROR(ep
, ebuf
, gettext(
2366 "Can only specify single"
2367 " source certificate identity.\n"));
2370 alloclen
= sizeof (*srcid
) +
2371 roundup(strlen(*(argv
+ 1)) + 1, 8);
2372 srcid
= malloc(alloclen
);
2374 Bail("malloc(srcid)");
2375 totallen
+= alloclen
;
2376 srcid
->sadb_ident_type
= parseidtype(*argv
, ebuf
);
2378 srcid
->sadb_ident_len
= SADB_8TO64(alloclen
);
2379 srcid
->sadb_ident_exttype
= SADB_EXT_IDENTITY_SRC
;
2380 srcid
->sadb_ident_reserved
= 0;
2381 srcid
->sadb_ident_id
= 0; /* Not useful here. */
2382 (void) strlcpy((char *)(srcid
+ 1), *argv
, alloclen
);
2386 if (*argv
== NULL
|| *(argv
+ 1) == NULL
) {
2387 ERROR(ep
, ebuf
, gettext(
2388 "Unexpected end of command"
2389 " line - expecting dst type.\n"));
2392 if (dstid
!= NULL
) {
2393 ERROR(ep
, ebuf
, gettext(
2394 "Can only specify single destination "
2395 "certificate identity.\n"));
2398 alloclen
= sizeof (*dstid
) +
2399 roundup(strlen(*(argv
+ 1)) + 1, 8);
2400 dstid
= malloc(alloclen
);
2402 Bail("malloc(dstid)");
2403 totallen
+= alloclen
;
2404 dstid
->sadb_ident_type
= parseidtype(*argv
, ebuf
);
2406 dstid
->sadb_ident_len
= SADB_8TO64(alloclen
);
2407 dstid
->sadb_ident_exttype
= SADB_EXT_IDENTITY_DST
;
2408 dstid
->sadb_ident_reserved
= 0;
2409 dstid
->sadb_ident_id
= 0; /* Not useful here. */
2410 (void) strlcpy((char *)(dstid
+ 1), *argv
, alloclen
);
2413 case TOK_HARD_ALLOC
:
2414 case TOK_HARD_BYTES
:
2415 case TOK_HARD_ADDTIME
:
2416 case TOK_HARD_USETIME
:
2418 hard
= malloc(sizeof (*hard
));
2420 Bail("malloc(hard_lifetime)");
2421 bzero(hard
, sizeof (*hard
));
2422 hard
->sadb_lifetime_exttype
=
2423 SADB_EXT_LIFETIME_HARD
;
2424 hard
->sadb_lifetime_len
=
2425 SADB_8TO64(sizeof (*hard
));
2426 totallen
+= sizeof (*hard
);
2429 case TOK_HARD_ALLOC
:
2430 if (hard
->sadb_lifetime_allocations
!= 0) {
2431 ERROR(ep
, ebuf
, gettext(
2432 "Can only specify single"
2433 " hard allocation limit.\n"));
2436 hard
->sadb_lifetime_allocations
=
2437 (uint32_t)parsenum(*argv
, B_TRUE
, ebuf
);
2439 case TOK_HARD_BYTES
:
2440 if (hard
->sadb_lifetime_bytes
!= 0) {
2441 ERROR(ep
, ebuf
, gettext(
2443 "single hard byte limit.\n"));
2446 hard
->sadb_lifetime_bytes
= parsenum(*argv
,
2449 case TOK_HARD_ADDTIME
:
2450 if (hard
->sadb_lifetime_addtime
!= 0) {
2451 ERROR(ep
, ebuf
, gettext(
2453 "single past-add lifetime.\n"));
2456 hard
->sadb_lifetime_addtime
= parsenum(*argv
,
2459 case TOK_HARD_USETIME
:
2460 if (hard
->sadb_lifetime_usetime
!= 0) {
2461 ERROR(ep
, ebuf
, gettext(
2463 "single past-use lifetime.\n"));
2466 hard
->sadb_lifetime_usetime
= parsenum(*argv
,
2472 case TOK_SOFT_ALLOC
:
2473 case TOK_SOFT_BYTES
:
2474 case TOK_SOFT_ADDTIME
:
2475 case TOK_SOFT_USETIME
:
2477 soft
= malloc(sizeof (*soft
));
2479 Bail("malloc(soft_lifetime)");
2480 bzero(soft
, sizeof (*soft
));
2481 soft
->sadb_lifetime_exttype
=
2482 SADB_EXT_LIFETIME_SOFT
;
2483 soft
->sadb_lifetime_len
=
2484 SADB_8TO64(sizeof (*soft
));
2485 totallen
+= sizeof (*soft
);
2488 case TOK_SOFT_ALLOC
:
2489 if (soft
->sadb_lifetime_allocations
!= 0) {
2490 ERROR(ep
, ebuf
, gettext(
2491 "Can only specify single"
2492 " soft allocation limit.\n"));
2495 soft
->sadb_lifetime_allocations
=
2496 (uint32_t)parsenum(*argv
, B_TRUE
, ebuf
);
2498 case TOK_SOFT_BYTES
:
2499 if (soft
->sadb_lifetime_bytes
!= 0) {
2500 ERROR(ep
, ebuf
, gettext(
2501 "Can only specify single"
2502 " soft byte limit.\n"));
2505 soft
->sadb_lifetime_bytes
= parsenum(*argv
,
2508 case TOK_SOFT_ADDTIME
:
2509 if (soft
->sadb_lifetime_addtime
!= 0) {
2510 ERROR(ep
, ebuf
, gettext(
2511 "Can only specify single"
2512 " past-add lifetime.\n"));
2515 soft
->sadb_lifetime_addtime
= parsenum(*argv
,
2518 case TOK_SOFT_USETIME
:
2519 if (soft
->sadb_lifetime_usetime
!= 0) {
2520 ERROR(ep
, ebuf
, gettext(
2521 "Can only specify single"
2522 " past-use lifetime.\n"));
2525 soft
->sadb_lifetime_usetime
= parsenum(*argv
,
2531 case TOK_FLAG_INBOUND
:
2532 assoc
->sadb_sa_flags
|= SADB_X_SAFLAGS_INBOUND
;
2534 case TOK_FLAG_OUTBOUND
:
2535 assoc
->sadb_sa_flags
|= SADB_X_SAFLAGS_OUTBOUND
;
2537 case TOK_REPLAY_VALUE
:
2538 if (replay_ctr
!= NULL
) {
2539 ERROR(ep
, ebuf
, gettext(
2540 "Can only specify single "
2544 replay_ctr
= calloc(1, sizeof (*replay_ctr
));
2545 if (replay_ctr
== NULL
) {
2546 Bail("malloc(replay value)");
2549 * We currently do not support a 64-bit
2550 * replay value. RFC 4301 will require one,
2551 * however, and we have a field in place when
2554 replay_ctr
->sadb_x_rc_exttype
= SADB_X_EXT_REPLAY_VALUE
;
2555 replay_ctr
->sadb_x_rc_len
=
2556 SADB_8TO64(sizeof (*replay_ctr
));
2557 totallen
+= sizeof (*replay_ctr
);
2558 replay_ctr
->sadb_x_rc_replay32
= (uint32_t)parsenum(
2559 *argv
, B_TRUE
, ebuf
);
2562 case TOK_IDLE_ADDTIME
:
2563 case TOK_IDLE_USETIME
:
2565 idle
= calloc(1, sizeof (*idle
));
2567 Bail("malloc idle lifetime");
2569 idle
->sadb_lifetime_exttype
=
2570 SADB_X_EXT_LIFETIME_IDLE
;
2571 idle
->sadb_lifetime_len
=
2572 SADB_8TO64(sizeof (*idle
));
2573 totallen
+= sizeof (*idle
);
2576 case TOK_IDLE_ADDTIME
:
2577 idle
->sadb_lifetime_addtime
=
2578 (uint32_t)parsenum(*argv
,
2581 case TOK_IDLE_USETIME
:
2582 idle
->sadb_lifetime_usetime
=
2583 (uint32_t)parsenum(*argv
,
2590 if (encrypt
!= NULL
)
2591 ERROR(ep
, ebuf
, gettext(
2592 "Reserved bits need to be "
2593 "specified before key.\n"));
2594 reserved_bits
= (uint_t
)parsenum(*argv
,
2599 label
= parselabel(token
, *argv
);
2601 if (label
== NULL
) {
2603 gettext("Malformed security label\n"));
2605 } else if (label
== PARSELABEL_BAD_TOKEN
) {
2606 Bail("Internal token value error");
2608 totallen
+= SADB_64TO8(label
->sadb_sens_len
);
2613 olabel
= parselabel(token
, *argv
);
2615 if (label
== NULL
) {
2617 gettext("Malformed security label\n"));
2619 } else if (label
== PARSELABEL_BAD_TOKEN
) {
2620 Bail("Internal token value error");
2622 totallen
+= SADB_64TO8(olabel
->sadb_sens_len
);
2625 ERROR1(ep
, ebuf
, gettext(
2626 "Don't use extension %s for add/update.\n"),
2630 } while (token
!= TOK_EOF
);
2632 handle_errors(ep
, ebuf
, B_TRUE
, B_FALSE
);
2634 #define PORT_ONLY_ALLOCATE(af, socktype, exttype, extvar, port) { \
2635 alloclen = sizeof (sadb_address_t) + roundup(sizeof (socktype), 8); \
2636 (extvar) = calloc(1, alloclen); \
2637 if ((extvar) == NULL) { \
2638 Bail("malloc(implicit port)"); \
2640 totallen += alloclen; \
2641 (extvar)->sadb_address_len = SADB_8TO64(alloclen); \
2642 (extvar)->sadb_address_exttype = (exttype); \
2643 /* sin/sin6 has equivalent offsets for ports! */ \
2644 sin6 = (struct sockaddr_in6 *)((extvar) + 1); \
2645 sin6->sin6_family = (af); \
2646 sin6->sin6_port = (port); \
2650 * If we specify inner ports or NAT ports w/o addresses, we still need
2651 * to allocate. Also, if we have one inner address, we need the
2652 * other, even if we don't specify anything.
2655 if (natt_lport
!= 0 && natt_local
== NULL
) {
2656 PORT_ONLY_ALLOCATE(AF_INET
, struct sockaddr_in
,
2657 SADB_X_EXT_ADDRESS_NATT_LOC
, natt_local
,
2661 if (natt_rport
!= 0 && natt_remote
== NULL
) {
2662 PORT_ONLY_ALLOCATE(AF_INET
, struct sockaddr_in
,
2663 SADB_X_EXT_ADDRESS_NATT_REM
, natt_remote
,
2667 if (natt_lport
!= 0 || natt_rport
!= 0) {
2668 ERROR(ep
, ebuf
, gettext("Must specify 'encap udp' "
2669 "with any NAT-T port.\n"));
2670 } else if (natt_local
!= NULL
|| natt_remote
!= NULL
) {
2671 ERROR(ep
, ebuf
, gettext("Must specify 'encap udp' "
2672 "with any NAT-T address.\n"));
2676 if (alloc_inner
&& idst
== NULL
) {
2677 PORT_ONLY_ALLOCATE(AF_INET6
, struct sockaddr_in6
,
2678 SADB_X_EXT_ADDRESS_INNER_DST
, idst
, 0);
2681 if (alloc_inner
&& isrc
== NULL
) {
2682 PORT_ONLY_ALLOCATE(AF_INET6
, struct sockaddr_in6
,
2683 SADB_X_EXT_ADDRESS_INNER_SRC
, isrc
, 0);
2685 #undef PORT_ONLY_ALLOCATE
2688 * Okay, so now I have all of the potential extensions!
2689 * Allocate a single contiguous buffer. Keep in mind that it'll
2690 * be enough because the key itself will be yanked.
2693 if (src
== NULL
&& dst
!= NULL
) {
2695 * Set explicit unspecified source address.
2697 size_t lenbytes
= SADB_64TO8(dst
->sadb_address_len
);
2699 unspec_src
= B_TRUE
;
2700 totallen
+= lenbytes
;
2701 src
= malloc(lenbytes
);
2703 Bail("malloc(implicit src)");
2704 /* Confusing, but we're copying from DST to SRC. :) */
2705 bcopy(dst
, src
, lenbytes
);
2706 src
->sadb_address_exttype
= SADB_EXT_ADDRESS_SRC
;
2707 sin6
= (struct sockaddr_in6
*)(src
+ 1);
2708 bzero(sin6
, sizeof (*sin6
));
2709 sin6
->sin6_family
= AF_INET6
;
2712 msg
.sadb_msg_len
= SADB_8TO64(totallen
);
2714 buffer
= malloc(totallen
);
2716 bcopy(&msg
, nexthdr
, sizeof (msg
));
2717 nexthdr
+= SADB_8TO64(sizeof (msg
));
2718 if (assoc
!= NULL
) {
2719 if (assoc
->sadb_sa_spi
== 0) {
2720 ERROR1(ep
, ebuf
, gettext(
2721 "The SPI value is missing for "
2722 "the association you wish to %s.\n"), thiscmd
);
2724 if (assoc
->sadb_sa_auth
== 0 && assoc
->sadb_sa_encrypt
== 0 &&
2727 FATAL(ep
, ebuf
, gettext(
2728 "Select at least one algorithm "
2729 "for this add.\n"));
2732 /* Hack to let user specify NULL ESP implicitly. */
2733 if (msg
.sadb_msg_satype
== SADB_SATYPE_ESP
&&
2734 assoc
->sadb_sa_encrypt
== 0)
2735 assoc
->sadb_sa_encrypt
= SADB_EALG_NULL
;
2737 /* 0 is an actual value. Print a warning if it was entered. */
2738 if (assoc
->sadb_sa_state
== 0) {
2740 ERROR(ep
, ebuf
, gettext(
2741 "WARNING: Cannot set LARVAL SA state.\n"));
2743 assoc
->sadb_sa_state
= SADB_SASTATE_MATURE
;
2747 if (natt_remote
!= NULL
)
2748 assoc
->sadb_sa_flags
|= SADB_X_SAFLAGS_NATT_REM
;
2749 if (natt_local
!= NULL
)
2750 assoc
->sadb_sa_flags
|= SADB_X_SAFLAGS_NATT_LOC
;
2755 * For now, assume RFC 3884's dream of transport-mode
2756 * SAs with inner IP address selectors will not
2759 assoc
->sadb_sa_flags
|= SADB_X_SAFLAGS_TUNNEL
;
2760 if (proto
!= 0 && proto
!= IPPROTO_ENCAP
&&
2761 proto
!= IPPROTO_IPV6
) {
2762 ERROR1(ep
, ebuf
, gettext(
2763 "WARNING: Protocol type %d not "
2764 "for use with Tunnel-Mode SA.\n"), proto
);
2765 /* Continue and let PF_KEY scream... */
2769 bcopy(assoc
, nexthdr
, SADB_64TO8(assoc
->sadb_sa_len
));
2770 nexthdr
+= assoc
->sadb_sa_len
;
2771 /* Save the SPI for the case of an error. */
2772 spi
= assoc
->sadb_sa_spi
;
2776 ERROR1(ep
, ebuf
, gettext(
2777 "Need to define SPI for %s.\n"), thiscmd
);
2778 ERROR1(ep
, ebuf
, gettext(
2779 "Need SA parameters for %s.\n"), thiscmd
);
2782 if (sadb_pair
!= NULL
) {
2783 if (sadb_pair
->sadb_x_pair_spi
== 0) {
2784 ERROR1(ep
, ebuf
, gettext(
2785 "The SPI value is missing for the "
2786 "association you wish to %s.\n"), thiscmd
);
2788 bcopy(sadb_pair
, nexthdr
,
2789 SADB_64TO8(sadb_pair
->sadb_x_pair_len
));
2790 nexthdr
+= sadb_pair
->sadb_x_pair_len
;
2795 bcopy(hard
, nexthdr
, SADB_64TO8(hard
->sadb_lifetime_len
));
2796 nexthdr
+= hard
->sadb_lifetime_len
;
2801 bcopy(soft
, nexthdr
, SADB_64TO8(soft
->sadb_lifetime_len
));
2802 nexthdr
+= soft
->sadb_lifetime_len
;
2807 bcopy(idle
, nexthdr
, SADB_64TO8(idle
->sadb_lifetime_len
));
2808 nexthdr
+= idle
->sadb_lifetime_len
;
2812 if (encrypt
== NULL
&& auth
== NULL
&& cmd
== CMD_ADD
) {
2813 ERROR(ep
, ebuf
, gettext(
2814 "Must have at least one key for an add.\n"));
2817 if (encrypt
!= NULL
) {
2818 bcopy(encrypt
, nexthdr
, SADB_64TO8(encrypt
->sadb_key_len
));
2819 nexthdr
+= encrypt
->sadb_key_len
;
2820 bzero(encrypt
, SADB_64TO8(encrypt
->sadb_key_len
));
2825 bcopy(auth
, nexthdr
, SADB_64TO8(auth
->sadb_key_len
));
2826 nexthdr
+= auth
->sadb_key_len
;
2827 bzero(auth
, SADB_64TO8(auth
->sadb_key_len
));
2831 if (srcid
!= NULL
) {
2832 bcopy(srcid
, nexthdr
, SADB_64TO8(srcid
->sadb_ident_len
));
2833 nexthdr
+= srcid
->sadb_ident_len
;
2837 if (dstid
!= NULL
) {
2838 bcopy(dstid
, nexthdr
, SADB_64TO8(dstid
->sadb_ident_len
));
2839 nexthdr
+= dstid
->sadb_ident_len
;
2844 bcopy(dst
, nexthdr
, SADB_64TO8(dst
->sadb_address_len
));
2846 dst
= (struct sadb_address
*)nexthdr
;
2847 dst
->sadb_address_proto
= proto
;
2848 ((struct sockaddr_in6
*)(dst
+ 1))->sin6_port
= htons(dstport
);
2849 nexthdr
+= dst
->sadb_address_len
;
2851 FATAL1(ep
, ebuf
, gettext(
2852 "Need destination address for %s.\n"), thiscmd
);
2856 if (natt_remote
== NULL
&& natt_local
== NULL
) {
2857 ERROR(ep
, ebuf
, gettext(
2858 "Must specify NAT-T remote or local address "
2859 "for UDP encapsulation.\n"));
2862 if (natt_remote
!= NULL
) {
2863 bcopy(natt_remote
, nexthdr
,
2864 SADB_64TO8(natt_remote
->sadb_address_len
));
2866 natt_remote
= (struct sadb_address
*)nexthdr
;
2867 nexthdr
+= natt_remote
->sadb_address_len
;
2868 ((struct sockaddr_in6
*)(natt_remote
+ 1))->sin6_port
=
2872 if (natt_local
!= NULL
) {
2873 bcopy(natt_local
, nexthdr
,
2874 SADB_64TO8(natt_local
->sadb_address_len
));
2876 natt_local
= (struct sadb_address
*)nexthdr
;
2877 nexthdr
+= natt_local
->sadb_address_len
;
2878 ((struct sockaddr_in6
*)(natt_local
+ 1))->sin6_port
=
2883 handle_errors(ep
, ebuf
, B_TRUE
, B_FALSE
);
2886 * PF_KEY requires a source address extension, even if the source
2887 * address itself is unspecified. (See "Set explicit unspecified..."
2888 * code fragment above. Destination reality check was above.)
2890 bcopy(src
, nexthdr
, SADB_64TO8(src
->sadb_address_len
));
2892 src
= (struct sadb_address
*)nexthdr
;
2893 src
->sadb_address_proto
= proto
;
2894 ((struct sockaddr_in6
*)(src
+ 1))->sin6_port
= htons(srcport
);
2895 nexthdr
+= src
->sadb_address_len
;
2898 bcopy(isrc
, nexthdr
, SADB_64TO8(isrc
->sadb_address_len
));
2900 isrc
= (struct sadb_address
*)nexthdr
;
2901 isrc
->sadb_address_proto
= iproto
;
2902 ((struct sockaddr_in6
*)(isrc
+ 1))->sin6_port
=
2904 nexthdr
+= isrc
->sadb_address_len
;
2908 bcopy(idst
, nexthdr
, SADB_64TO8(idst
->sadb_address_len
));
2910 idst
= (struct sadb_address
*)nexthdr
;
2911 idst
->sadb_address_proto
= iproto
;
2912 ((struct sockaddr_in6
*)(idst
+ 1))->sin6_port
=
2914 nexthdr
+= idst
->sadb_address_len
;
2917 if (replay_ctr
!= NULL
) {
2918 bcopy(replay_ctr
, nexthdr
,
2919 SADB_64TO8(replay_ctr
->sadb_x_rc_len
));
2920 nexthdr
+= replay_ctr
->sadb_x_rc_len
;
2924 if (label
!= NULL
) {
2925 bcopy(label
, nexthdr
, SADB_64TO8(label
->sadb_sens_len
));
2926 nexthdr
+= label
->sadb_sens_len
;
2931 if (olabel
!= NULL
) {
2932 bcopy(olabel
, nexthdr
, SADB_64TO8(olabel
->sadb_sens_len
));
2933 nexthdr
+= olabel
->sadb_sens_len
;
2940 * Assume the checked cmd would have worked if it was actually
2941 * used. doaddresses() will increment lines_added if it
2946 doaddresses(sadb_msg_type
, satype
,
2947 cmd
, srchp
, dsthp
, src
, dst
, unspec_src
, buffer
, totallen
,
2951 if (isrchp
!= NULL
&& isrchp
!= &dummy
.he
)
2952 freehostent(isrchp
);
2953 if (idsthp
!= NULL
&& idsthp
!= &dummy
.he
)
2954 freehostent(idsthp
);
2955 if (srchp
!= NULL
&& srchp
!= &dummy
.he
)
2957 if (dsthp
!= NULL
&& dsthp
!= &dummy
.he
)
2959 if (natt_lhp
!= NULL
&& natt_lhp
!= &dummy
.he
)
2960 freehostent(natt_lhp
);
2961 if (natt_rhp
!= NULL
&& natt_rhp
!= &dummy
.he
)
2962 freehostent(natt_rhp
);
2968 * DELETE and GET are similar, in that they only need the extensions
2969 * required to _find_ an SA, and then either delete it or obtain its
2973 dodelget(int cmd
, int satype
, char *argv
[], char *ebuf
)
2975 struct sadb_msg
*msg
= (struct sadb_msg
*)get_buffer
;
2977 struct sadb_sa
*assoc
= NULL
;
2978 struct sadb_address
*src
= NULL
, *dst
= NULL
;
2979 int next
, token
, sa_len
;
2982 uint8_t sadb_msg_type
;
2983 struct hostent
*srchp
= NULL
, *dsthp
= NULL
;
2984 struct sockaddr_in6
*sin6
;
2985 boolean_t unspec_src
= B_TRUE
;
2986 uint16_t srcport
= 0, dstport
= 0;
2989 uint32_t sa_flags
= 0;
2991 /* Set the first extension header to right past the base message. */
2992 nextext
= (uint64_t *)(msg
+ 1);
2993 bzero(nextext
, sizeof (get_buffer
) - sizeof (*msg
));
2998 sadb_msg_type
= SADB_GET
;
3002 sadb_msg_type
= SADB_DELETE
;
3004 case CMD_DELETE_PAIR
:
3005 thiscmd
= "delete-pair";
3006 sadb_msg_type
= SADB_X_DELPAIR
;
3010 msg_init(msg
, sadb_msg_type
, (uint8_t)satype
);
3012 #define ALLOC_ADDR_EXT(ext, exttype) \
3013 (ext) = (struct sadb_address *)nextext; \
3014 nextext = (uint64_t *)((ext) + 1); \
3015 nextext += SADB_8TO64(roundup(sa_len, 8)); \
3016 (ext)->sadb_address_exttype = exttype; \
3017 (ext)->sadb_address_len = nextext - ((uint64_t *)ext);
3019 /* Assume last element in argv is set to NULL. */
3021 token
= parseextval(*argv
, &next
);
3025 /* Do nothing, I'm done. */
3028 ERROR1(ep
, ebuf
, gettext(
3029 "Unknown extension field \"%s\"\n"), *(argv
- 1));
3032 if (assoc
!= NULL
) {
3033 ERROR(ep
, ebuf
, gettext(
3034 "Can only specify single SPI value.\n"));
3037 assoc
= (struct sadb_sa
*)nextext
;
3038 nextext
= (uint64_t *)(assoc
+ 1);
3039 assoc
->sadb_sa_len
= SADB_8TO64(sizeof (*assoc
));
3040 assoc
->sadb_sa_exttype
= SADB_EXT_SA
;
3041 assoc
->sadb_sa_spi
= htonl((uint32_t)parsenum(*argv
,
3043 spi
= assoc
->sadb_sa_spi
;
3048 ERROR(ep
, ebuf
, gettext(
3049 "Can only specify single source port.\n"));
3052 srcport
= parsenum(*argv
, B_TRUE
, ebuf
);
3057 ERROR(ep
, ebuf
, gettext(
3059 "specify single destination port.\n"));
3062 dstport
= parsenum(*argv
, B_TRUE
, ebuf
);
3067 ERROR(ep
, ebuf
, gettext(
3068 "Can only specify single protocol.\n"));
3071 proto
= parsenum(*argv
, B_TRUE
, ebuf
);
3077 ERROR(ep
, ebuf
, gettext(
3078 "Can only specify single source addr.\n"));
3081 sa_len
= parseaddr(*argv
, &srchp
,
3082 (token
== TOK_SRCADDR6
), ebuf
);
3083 if (srchp
== NULL
) {
3084 ERROR1(ep
, ebuf
, gettext(
3085 "Unknown source address \"%s\"\n"), *argv
);
3090 unspec_src
= B_FALSE
;
3092 ALLOC_ADDR_EXT(src
, SADB_EXT_ADDRESS_SRC
);
3094 if (srchp
== &dummy
.he
) {
3096 * Single address with -n flag.
3098 sin6
= (struct sockaddr_in6
*)(src
+ 1);
3099 bzero(sin6
, sizeof (*sin6
));
3100 sin6
->sin6_family
= AF_INET6
;
3101 bcopy(srchp
->h_addr_list
[0], &sin6
->sin6_addr
,
3102 sizeof (struct in6_addr
));
3104 /* The rest is pre-bzeroed for us. */
3109 ERROR(ep
, ebuf
, gettext(
3110 "Can only specify single destination "
3114 sa_len
= parseaddr(*argv
, &dsthp
,
3115 (token
== TOK_SRCADDR6
), ebuf
);
3116 if (dsthp
== NULL
) {
3117 ERROR1(ep
, ebuf
, gettext(
3118 "Unknown destination address \"%s\"\n"),
3124 ALLOC_ADDR_EXT(dst
, SADB_EXT_ADDRESS_DST
);
3126 if (dsthp
== &dummy
.he
) {
3128 * Single address with -n flag.
3130 sin6
= (struct sockaddr_in6
*)(dst
+ 1);
3131 bzero(sin6
, sizeof (*sin6
));
3132 sin6
->sin6_family
= AF_INET6
;
3133 bcopy(dsthp
->h_addr_list
[0], &sin6
->sin6_addr
,
3134 sizeof (struct in6_addr
));
3136 /* The rest is pre-bzeroed for us. */
3138 case TOK_FLAG_INBOUND
:
3139 sa_flags
|= SADB_X_SAFLAGS_INBOUND
;
3141 case TOK_FLAG_OUTBOUND
:
3142 sa_flags
|= SADB_X_SAFLAGS_OUTBOUND
;
3145 ERROR2(ep
, ebuf
, gettext(
3146 "Don't use extension %s for '%s' command.\n"),
3147 *(argv
- 1), thiscmd
);
3150 } while (token
!= TOK_EOF
);
3152 handle_errors(ep
, ebuf
, B_TRUE
, B_FALSE
);
3154 if (assoc
== NULL
) {
3155 FATAL1(ep
, ebuf
, gettext(
3156 "Need SA parameters for %s.\n"), thiscmd
);
3159 /* We can set the flags now with valid assoc in hand. */
3160 assoc
->sadb_sa_flags
|= sa_flags
;
3162 if ((srcport
!= 0) && (src
== NULL
)) {
3163 ALLOC_ADDR_EXT(src
, SADB_EXT_ADDRESS_SRC
);
3164 sin6
= (struct sockaddr_in6
*)(src
+ 1);
3165 src
->sadb_address_proto
= proto
;
3166 bzero(sin6
, sizeof (*sin6
));
3167 sin6
->sin6_family
= AF_INET6
;
3168 sin6
->sin6_port
= htons(srcport
);
3171 if ((dstport
!= 0) && (dst
== NULL
)) {
3172 ALLOC_ADDR_EXT(dst
, SADB_EXT_ADDRESS_DST
);
3173 sin6
= (struct sockaddr_in6
*)(dst
+ 1);
3174 src
->sadb_address_proto
= proto
;
3175 bzero(sin6
, sizeof (*sin6
));
3176 sin6
->sin6_family
= AF_INET6
;
3177 sin6
->sin6_port
= htons(dstport
);
3180 /* So I have enough of the message to send it down! */
3181 msg
->sadb_msg_len
= nextext
- get_buffer
;
3185 * Assume the checked cmd would have worked if it was actually
3186 * used. doaddresses() will increment lines_added if it
3191 doaddresses(sadb_msg_type
, satype
,
3192 cmd
, srchp
, dsthp
, src
, dst
, unspec_src
, get_buffer
,
3193 sizeof (get_buffer
), spi
, NULL
);
3196 if (srchp
!= NULL
&& srchp
!= &dummy
.he
)
3198 if (dsthp
!= NULL
&& dsthp
!= &dummy
.he
)
3203 * "ipseckey monitor" should exit very gracefully if ^C is tapped provided
3204 * it is not running in interactive mode.
3207 monitor_catch(int signal
)
3210 errx(signal
, gettext("Bailing on signal %d."), signal
);
3214 * Loop forever, listening on PF_KEY messages.
3217 domonitor(boolean_t passive
)
3219 struct sadb_msg
*samsg
;
3220 struct sigaction newsig
, oldsig
;
3224 newsig
.sa_handler
= monitor_catch
;
3225 newsig
.sa_flags
= 0;
3226 (void) sigemptyset(&newsig
.sa_mask
);
3227 (void) sigaddset(&newsig
.sa_mask
, SIGINT
);
3228 (void) sigaction(SIGINT
, &newsig
, &oldsig
);
3230 samsg
= (struct sadb_msg
*)get_buffer
;
3232 (void) printf(gettext("Actively"));
3233 msg_init(samsg
, SADB_X_PROMISC
, 1); /* Turn ON promisc. */
3234 rc
= key_write(keysock
, samsg
, sizeof (*samsg
));
3236 Bail("write (SADB_X_PROMISC)");
3238 (void) printf(gettext("Passively"));
3240 (void) printf(gettext(" monitoring the PF_KEY socket.\n"));
3244 * I assume that read() is non-blocking, and will never
3247 rc
= read(keysock
, samsg
, sizeof (get_buffer
));
3249 if (errno
== EINTR
&& interactive
)
3252 Bail("read (in domonitor)");
3254 (void) printf(gettext("Read %d bytes.\n"), rc
);
3256 * Q: Should I use the same method of printing as GET does?
3259 print_samsg(stdout
, get_buffer
, B_TRUE
, vflag
, nflag
);
3260 (void) putchar('\n');
3265 /* restore SIGINT behavior */
3266 (void) sigaction(SIGINT
, &oldsig
, NULL
);
3270 * Either mask or unmask all relevant signals.
3273 mask_signals(boolean_t unmask
)
3276 static sigset_t oset
;
3279 (void) sigprocmask(SIG_SETMASK
, &oset
, NULL
);
3281 (void) sigfillset(&set
);
3282 (void) sigprocmask(SIG_SETMASK
, &set
, &oset
);
3287 * Assorted functions to print help text.
3289 #define puts_tr(s) (void) puts(gettext(s))
3296 puts_tr("\nSA attributes:");
3298 for (i
= 0; tokens
[i
].string
!= NULL
; i
++) {
3300 (void) printf("\n");
3301 (void) printf(" %-15.15s", tokens
[i
].string
);
3303 (void) printf("\n");
3307 dohelpcmd(char *cmds
)
3311 if (strcmp(cmds
, "attr") == 0) {
3316 cmd
= parsecmd(cmds
);
3319 puts_tr("update - Update an existing SA");
3321 case CMD_UPDATE_PAIR
:
3322 puts_tr("update-pair - Update an existing pair of SA's");
3325 puts_tr("add - Add a new security association (SA)");
3328 puts_tr("delete - Delete an SA");
3330 case CMD_DELETE_PAIR
:
3331 puts_tr("delete-pair - Delete a pair of SA's");
3334 puts_tr("get - Display an SA");
3337 puts_tr("flush - Delete all SAs");
3339 puts_tr("Optional arguments:");
3340 puts_tr("all delete all SAs");
3341 puts_tr("esp delete just ESP SAs");
3342 puts_tr("ah delete just AH SAs");
3343 puts_tr("<number> delete just SAs with type given by number");
3347 puts_tr("dump - Display all SAs");
3349 puts_tr("Optional arguments:");
3350 puts_tr("all display all SAs");
3351 puts_tr("esp display just ESP SAs");
3352 puts_tr("ah display just AH SAs");
3353 puts_tr("<number> display just SAs with type "
3358 puts_tr("monitor - Monitor all PF_KEY reply messages.");
3362 "pmonitor, passive_monitor - Monitor PF_KEY messages that");
3364 " reply to all PF_KEY sockets.");
3368 puts_tr("quit, exit - Exit the program");
3371 puts_tr("save - Saves all SAs to a file");
3374 puts_tr("help - Display list of commands");
3375 puts_tr("help <cmd> - Display help for command");
3376 puts_tr("help attr - Display possible SA attributes");
3379 (void) printf(gettext("%s: Unknown command\n"), cmds
);
3392 puts_tr("Commands");
3393 puts_tr("--------");
3394 puts_tr("?, help - Display this list");
3395 puts_tr("help <cmd> - Display help for command");
3396 puts_tr("help attr - Display possible SA attributes");
3397 puts_tr("quit, exit - Exit the program");
3398 puts_tr("monitor - Monitor all PF_KEY reply messages.");
3399 puts_tr("pmonitor, passive_monitor - Monitor PF_KEY messages that");
3400 puts_tr(" reply to all PF_KEY sockets.");
3402 puts_tr("The following commands are of the form:");
3403 puts_tr(" <command> {SA type} {attribute value}*");
3405 puts_tr("add (interactive only) - Add a new security association (SA)");
3406 puts_tr("update (interactive only) - Update an existing SA");
3407 puts_tr("update-pair (interactive only) - Update an existing SA pair");
3408 puts_tr("delete - Delete an SA");
3409 puts_tr("delete-pair - Delete an SA pair");
3410 puts_tr("get - Display an SA");
3411 puts_tr("flush - Delete all SAs");
3412 puts_tr("dump - Display all SAs");
3413 puts_tr("save - Saves all SAs to a file");
3417 * "Parse" a command line from argv.
3420 parseit(int argc
, char *argv
[], char *ebuf
, boolean_t read_cmdfile
)
3427 cmd
= parsecmd(*argv
++);
3430 * Some commands loop forever and should only be run from the command
3431 * line, they should never be run from a command file as this may
3432 * be used at boot time.
3437 ERROR(ep
, ebuf
, gettext("Help not appropriate in "
3444 ERROR(ep
, ebuf
, gettext("Monitor not appropriate in "
3449 * Return from the function in interactive mode to
3450 * avoid error message in the next switch statement.
3451 * Also print newline to prevent prompt clobbering.
3452 * The same is done for CMD_PMONITOR.
3455 (void) printf("\n");
3462 ERROR(ep
, ebuf
, gettext("Monitor not appropriate in "
3467 (void) printf("\n");
3476 handle_errors(ep
, ebuf
, B_FALSE
, B_FALSE
);
3478 satype
= parsesatype(*argv
, ebuf
);
3480 if (satype
!= SADB_SATYPE_UNSPEC
) {
3484 * You must specify either "all" or a specific SA type
3485 * for the "save" command.
3487 if (cmd
== CMD_SAVE
)
3488 if (*argv
== NULL
) {
3489 FATAL(ep
, ebuf
, gettext(
3490 "Must specify a specific "
3491 "SA type for save.\n"));
3500 ERROR(ep
, ebuf
, gettext("Too many arguments for "
3502 handle_errors(ep
, ebuf
,
3503 interactive
? B_TRUE
: B_FALSE
, B_FALSE
);
3508 * If this was called because of an entry in a cmd file
3509 * then this action needs to be counted to prevent
3510 * do_interactive() treating this as an error.
3516 case CMD_UPDATE_PAIR
:
3518 * NOTE: Shouldn't allow ADDs or UPDATEs with keying material
3519 * from the command line.
3523 "can't do ADD or UPDATE from the command line.\n"));
3525 if (satype
== SADB_SATYPE_UNSPEC
) {
3526 FATAL(ep
, ebuf
, gettext(
3527 "Must specify a specific SA type."));
3530 /* Parse for extensions, including keying material. */
3531 doaddup(cmd
, satype
, argv
, ebuf
);
3534 case CMD_DELETE_PAIR
:
3536 if (satype
== SADB_SATYPE_UNSPEC
) {
3537 FATAL(ep
, ebuf
, gettext(
3538 "Must specify a single SA type."));
3541 /* Parse for bare minimum to locate an SA. */
3542 dodelget(cmd
, satype
, argv
, ebuf
);
3546 ERROR(ep
, ebuf
, gettext("Dump not appropriate in "
3550 ERROR(ep
, ebuf
, gettext("Too many arguments "
3551 "for dump command"));
3552 handle_errors(ep
, ebuf
,
3553 interactive
? B_TRUE
: B_FALSE
, B_FALSE
);
3555 dodump(satype
, NULL
);
3560 ERROR(ep
, ebuf
, gettext("Save not appropriate in "
3563 mask_signals(B_FALSE
); /* Mask signals */
3564 dodump(satype
, opensavefile(argv
[0]));
3565 mask_signals(B_TRUE
); /* Unmask signals */
3569 warnx(gettext("Unknown command (%s).\n"),
3570 *(argv
- ((satype
== SADB_SATYPE_UNSPEC
) ? 1 : 2)));
3573 handle_errors(ep
, ebuf
, B_FALSE
, B_FALSE
);
3577 main(int argc
, char *argv
[])
3580 FILE *infile
= stdin
, *savefile
;
3581 boolean_t dosave
= B_FALSE
, readfile
= B_FALSE
;
3582 char *configfile
= NULL
;
3586 (void) setlocale(LC_ALL
, "");
3587 #if !defined(TEXT_DOMAIN)
3588 #define TEXT_DOMAIN "SYS_TEST"
3590 (void) textdomain(TEXT_DOMAIN
);
3593 * Check to see if the command is being run from smf(5).
3595 my_fmri
= getenv("SMF_FMRI");
3597 openlog("ipseckey", LOG_CONS
, LOG_AUTH
);
3598 if (getuid() != 0) {
3599 errx(1, "Insufficient privileges to run ipseckey.");
3602 /* umask me to paranoid, I only want to create files read-only */
3603 (void) umask((mode_t
)00377);
3605 while ((ch
= getopt(argc
, argv
, "pnvf:s:c:")) != EOF
)
3624 * Use stat() to check and see if the user inadvertently
3625 * passed in a bad pathname, or the name of a directory.
3626 * We should also check to see if the filename is a
3627 * pipe. We use stat() here because fopen() will block
3628 * unless the other end of the pipe is open. This would
3629 * be undesirable, especially if this is called at boot
3630 * time. If we ever need to support reading from a pipe
3631 * or special file, this should be revisited.
3633 if (stat(optarg
, &sbuf
) == -1) {
3634 EXIT_BADCONFIG2("Invalid pathname: %s\n",
3637 if (!(sbuf
.st_mode
& S_IFREG
)) {
3638 EXIT_BADCONFIG2("%s - Not a regular file\n",
3641 infile
= fopen(optarg
, "r");
3642 if (infile
== NULL
) {
3643 EXIT_BADCONFIG2("Unable to open configuration "
3644 "file: %s\n", optarg
);
3647 * The input file contains keying information, because
3648 * this is sensative, we should only accept data from
3649 * this file if the file is root owned and only readable
3650 * by privileged users. If the command is being run by
3651 * the administrator, issue a warning, if this is run by
3652 * smf(5) (IE: boot time) and the permissions are too
3653 * open, we will fail, the SMF service will end up in
3654 * maintenace mode. The check is made with fstat() to
3655 * eliminate any possible TOT to TOU window.
3657 if (fstat(fileno(infile
), &sbuf
) == -1) {
3658 (void) fclose(infile
);
3659 EXIT_BADCONFIG2("Unable to stat configuration "
3660 "file: %s\n", optarg
);
3662 if (INSECURE_PERMS(sbuf
)) {
3663 if (my_fmri
!= NULL
) {
3664 (void) fclose(infile
);
3665 EXIT_BADCONFIG2("Config file "
3666 "%s has insecure permissions.",
3669 (void) fprintf(stderr
, gettext(
3670 "Config file %s has insecure "
3671 "permissions, will be rejected in "
3672 "permanent config.\n"), optarg
);
3675 configfile
= strdup(optarg
);
3682 savefile
= opensavefile(optarg
);
3693 keysock
= socket(PF_KEY
, SOCK_RAW
, PF_KEY_V2
);
3695 if (keysock
== -1) {
3696 if (errno
== EPERM
) {
3697 EXIT_BADPERM("Insufficient privileges to open "
3698 "PF_KEY socket.\n");
3700 /* some other reason */
3701 EXIT_FATAL("Opening PF_KEY socket");
3705 if ((_cladm(CL_INITIALIZE
, CL_GET_BOOTFLAG
, &bootflags
) != 0) ||
3706 (bootflags
& CLUSTER_BOOTED
)) {
3707 in_cluster_mode
= B_TRUE
;
3708 cluster_socket
= socket(AF_INET
, SOCK_DGRAM
, 0);
3709 cli_addr
.sin_family
= AF_INET
;
3710 cli_addr
.sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
3711 cli_addr
.sin_port
= htons(CLUSTER_UDP_PORT
);
3715 mask_signals(B_FALSE
); /* Mask signals */
3716 dodump(SADB_SATYPE_UNSPEC
, savefile
);
3717 mask_signals(B_TRUE
); /* Unmask signals */
3722 * When run from smf(5) flush any existing SA's first
3723 * otherwise you will end up in maintenance mode.
3725 if ((my_fmri
!= NULL
) && readfile
) {
3726 (void) fprintf(stdout
, gettext(
3727 "Flushing existing SA's before adding new SA's\n"));
3728 (void) fflush(stdout
);
3729 doflush(SADB_SATYPE_UNSPEC
);
3731 if (infile
!= stdin
|| argc
== 0) {
3732 /* Go into interactive mode here. */
3733 do_interactive(infile
, configfile
, "ipseckey> ", my_fmri
,
3736 parseit(argc
, argv
, NULL
, B_FALSE
);