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>
60 #include <ipsec_util.h>
65 static boolean_t vflag
= B_FALSE
; /* Verbose? */
66 static boolean_t cflag
= B_FALSE
; /* Check Only */
71 #define MAX_GET_SIZE 1024
73 * WARN() and ERROR() do the same thing really, with ERROR() the function
74 * that prints the error buffer needs to be called at the end of a code block
75 * This will print out all accumulated errors before bailing. The WARN()
76 * macro calls handle_errors() in such a way that it prints the message
78 * If the FATAL() macro used call handle_errors() immediately.
80 #define ERROR(x, y, z) x = record_error(x, y, z)
81 #define ERROR1(w, x, y, z) w = record_error(w, x, y, z)
82 #define ERROR2(v, w, x, y, z) v = record_error(v, w, x, y, z)
83 #define WARN(x, y, z) ERROR(x, y, z);\
84 handle_errors(x, NULL, B_FALSE, B_FALSE); x = NULL
85 #define WARN1(w, x, y, z) ERROR1(w, x, y, z);\
86 handle_errors(w, NULL, B_FALSE, B_FALSE); w = NULL
87 #define WARN2(v, w, x, y, z) ERROR2(v, w, x, y, z);\
88 handle_errors(v, NULL, B_FALSE, B_FALSE); v = NULL
89 #define FATAL(x, y, z) ERROR(x, y, z);\
90 handle_errors(x, y, B_TRUE, B_TRUE)
91 #define FATAL1(w, x, y, z) ERROR1(w, x, y, z);\
92 handle_errors(w, x, B_TRUE, B_TRUE)
94 /* Defined as a uint64_t array for alignment purposes. */
95 static uint64_t get_buffer
[MAX_GET_SIZE
];
98 * Disable default TAB completion for now (until some brave soul tackles it).
102 CPL_MATCH_FN(no_match
)
108 * Create/Grow a buffer large enough to hold error messages. If *ebuf
109 * is not NULL then it will contain a copy of the command line that
110 * triggered the error/warning, copy this into a new buffer or
111 * append new messages to the existing buffer.
115 record_error(char *ep
, char *ebuf
, char *fmt
, ...)
124 length
= vsnprintf(tmp_buff
, sizeof (tmp_buff
), fmt
, ap
);
127 /* There is a new line character */
132 length
+= strlen(ebuf
);
134 length
+= strlen(ep
);
138 err_ptr
= calloc(length
, sizeof (char));
140 err_ptr
= realloc(err_ptr
, length
);
143 Bail("realloc() failure");
146 * If (ep == NULL) then this is the first error to record,
147 * copy in the command line that triggered this error/warning.
149 if (ep
== NULL
&& ebuf
!= NULL
)
150 (void) strlcpy(err_ptr
, ebuf
, length
);
153 * Now the actual error.
155 (void) strlcat(err_ptr
, tmp_buff
, length
);
160 * If not in interactive mode print usage message and exit.
166 (void) fprintf(stderr
, gettext("Usage:\t"
167 "ipseckey [ -nvp ] | cmd [sa_type] [extfield value]*\n"));
168 (void) fprintf(stderr
,
169 gettext("\tipseckey [ -nvp ] -f infile\n"));
170 (void) fprintf(stderr
,
171 gettext("\tipseckey [ -nvp ] -s outfile\n"));
174 (void) fprintf(stderr
,
175 gettext("Type help or ? for usage info\n"));
181 * Print out any errors, tidy up as required.
182 * error pointer ep will be free()'d
185 handle_errors(char *ep
, char *ebuf
, boolean_t fatal
, boolean_t done
)
188 if (my_fmri
== NULL
) {
190 * For now suppress the errors when run from smf(5)
191 * because potentially sensitive information could
192 * end up in a publicly readable logfile.
194 (void) fprintf(stdout
, "%s\n", ep
);
195 (void) fflush(stdout
);
202 /* reset command buffer */
210 * No errors, if this is the last time that this function
211 * is called, free(ebuf) and reset command buffer.
217 /* reset command buffer */
227 * Initialize a PF_KEY base message.
230 msg_init(struct sadb_msg
*msg
, uint8_t type
, uint8_t satype
)
232 msg
->sadb_msg_version
= PF_KEY_V2
;
233 msg
->sadb_msg_type
= type
;
234 msg
->sadb_msg_errno
= 0;
235 msg
->sadb_msg_satype
= satype
;
236 /* For starters... */
237 msg
->sadb_msg_len
= SADB_8TO64(sizeof (*msg
));
238 msg
->sadb_msg_reserved
= 0;
239 msg
->sadb_msg_seq
= ++seq
;
240 msg
->sadb_msg_pid
= mypid
;
244 * parseXXX and rparseXXX commands parse input and convert them to PF_KEY
245 * field values, or do the reverse for the purposes of saving the SA tables.
246 * (See the save_XXX functions.)
251 #define CMD_UPDATE_PAIR 3
254 #define CMD_DELETE_PAIR 6
258 #define CMD_MONITOR 11
259 #define CMD_PMONITOR 12
268 parsecmd(char *cmdstr
)
270 static struct cmdtable
{
275 * Q: Do we want to do GETSPI?
276 * A: No, it's for automated key mgmt. only. Either that,
277 * or it isn't relevant until we support non IPsec SA types.
279 {"update", CMD_UPDATE
},
280 {"update-pair", CMD_UPDATE_PAIR
},
282 {"delete", CMD_DELETE
},
283 {"delete-pair", CMD_DELETE_PAIR
},
286 * Q: And ACQUIRE and REGISTER and EXPIRE?
287 * A: not until we support non IPsec SA types.
289 {"flush", CMD_FLUSH
},
291 {"monitor", CMD_MONITOR
},
292 {"passive_monitor", CMD_PMONITOR
},
293 {"pmonitor", CMD_PMONITOR
},
301 struct cmdtable
*ct
= table
;
303 while (ct
->cmd
!= NULL
&& strcmp(ct
->cmd
, cmdstr
) != 0)
309 * Convert a number from a command line. I picked "u_longlong_t" for the
310 * number because we need the largest number available. Also, the strto<num>
311 * calls don't deal in units of uintNN_t.
314 parsenum(char *num
, boolean_t bail
, char *ebuf
)
321 FATAL(ep
, ebuf
, gettext("Unexpected end of command line,"
322 " was expecting a number.\n"));
327 rc
= strtoull(num
, &end
, 0);
328 if (errno
!= 0 || end
== num
|| *end
!= '\0') {
330 FATAL1(ep
, ebuf
, gettext(
331 "Expecting a number, not \"%s\"!\n"), num
);
334 * -1, while not optimal, is sufficiently out of range
335 * for most of this function's applications when
336 * we don't just bail.
338 return ((u_longlong_t
)-1);
341 handle_errors(ep
, NULL
, B_FALSE
, B_FALSE
);
346 * Parse and reverse parse a specific SA type (AH, ESP, etc.).
348 static struct typetable
{
352 {"all", SADB_SATYPE_UNSPEC
},
353 {"ah", SADB_SATYPE_AH
},
354 {"esp", SADB_SATYPE_ESP
},
355 /* PF_KEY NOTE: More to come if net/pfkeyv2.h gets updated. */
356 {NULL
, 0} /* Token value is irrelevant for this entry. */
361 parsesatype(char *type
, char *ebuf
)
363 struct typetable
*tt
= type_table
;
367 return (SADB_SATYPE_UNSPEC
);
369 while (tt
->type
!= NULL
&& strcasecmp(tt
->type
, type
) != 0)
373 * New SA types (including ones keysock maintains for user-land
374 * protocols) may be added, so parse a numeric value if possible.
376 if (tt
->type
== NULL
) {
377 tt
->token
= (int)parsenum(type
, B_FALSE
, ebuf
);
378 if (tt
->token
== -1) {
379 ERROR1(ep
, ebuf
, gettext(
380 "Unknown SA type (%s).\n"), type
);
381 tt
->token
= SADB_SATYPE_UNSPEC
;
384 handle_errors(ep
, NULL
, interactive
? B_TRUE
: B_FALSE
, B_FALSE
);
401 #define TOK_UNKNOWN 1
405 #define TOK_AUTHALG 5
406 #define TOK_ENCRALG 6
408 #define TOK_SOFT_ALLOC 8
409 #define TOK_SOFT_BYTES 9
410 #define TOK_SOFT_ADDTIME 10
411 #define TOK_SOFT_USETIME 11
412 #define TOK_HARD_ALLOC 12
413 #define TOK_HARD_BYTES 13
414 #define TOK_HARD_ADDTIME 14
415 #define TOK_HARD_USETIME 15
416 #define TOK_CURRENT_ALLOC 16
417 #define TOK_CURRENT_BYTES 17
418 #define TOK_CURRENT_ADDTIME 18
419 #define TOK_CURRENT_USETIME 19
420 #define TOK_SRCADDR 20
421 #define TOK_DSTADDR 21
422 #define TOK_PROXYADDR 22
423 #define TOK_AUTHKEY 23
424 #define TOK_ENCRKEY 24
425 #define TOK_SRCIDTYPE 25
426 #define TOK_DSTIDTYPE 26
428 #define TOK_INTEG_LEVEL 30
429 #define TOK_INTEG_MAP 31
430 #define TOK_SRCADDR6 32
431 #define TOK_DSTADDR6 33
432 #define TOK_PROXYADDR6 34
433 #define TOK_SRCPORT 35
434 #define TOK_DSTPORT 36
437 #define TOK_NATLOC 39
438 #define TOK_NATREM 40
439 #define TOK_NATLPORT 41
440 #define TOK_NATRPORT 42
441 #define TOK_IPROTO 43
442 #define TOK_IDSTADDR 44
443 #define TOK_IDSTADDR6 45
444 #define TOK_ISRCPORT 46
445 #define TOK_IDSTPORT 47
446 #define TOK_PAIR_SPI 48
447 #define TOK_FLAG_INBOUND 49
448 #define TOK_FLAG_OUTBOUND 50
449 #define TOK_REPLAY_VALUE 51
450 #define TOK_IDLE_ADDTIME 52
451 #define TOK_IDLE_USETIME 53
452 #define TOK_RESERVED 54
454 static struct toktable
{
459 /* "String", token value, next arg is */
460 {"spi", TOK_SPI
, NEXTNUM
},
461 {"pair-spi", TOK_PAIR_SPI
, NEXTNUM
},
462 {"replay", TOK_REPLAY
, NEXTNUM
},
463 {"state", TOK_STATE
, NEXTNUMSTR
},
464 {"auth_alg", TOK_AUTHALG
, NEXTNUMSTR
},
465 {"authalg", TOK_AUTHALG
, NEXTNUMSTR
},
466 {"encr_alg", TOK_ENCRALG
, NEXTNUMSTR
},
467 {"encralg", TOK_ENCRALG
, NEXTNUMSTR
},
468 {"flags", TOK_FLAGS
, NEXTNUM
},
469 {"soft_alloc", TOK_SOFT_ALLOC
, NEXTNUM
},
470 {"soft_bytes", TOK_SOFT_BYTES
, NEXTNUM
},
471 {"soft_addtime", TOK_SOFT_ADDTIME
, NEXTNUM
},
472 {"soft_usetime", TOK_SOFT_USETIME
, NEXTNUM
},
473 {"hard_alloc", TOK_HARD_ALLOC
, NEXTNUM
},
474 {"hard_bytes", TOK_HARD_BYTES
, NEXTNUM
},
475 {"hard_addtime", TOK_HARD_ADDTIME
, NEXTNUM
},
476 {"hard_usetime", TOK_HARD_USETIME
, NEXTNUM
},
477 {"current_alloc", TOK_CURRENT_ALLOC
, NEXTNUM
},
478 {"current_bytes", TOK_CURRENT_BYTES
, NEXTNUM
},
479 {"current_addtime", TOK_CURRENT_ADDTIME
, NEXTNUM
},
480 {"current_usetime", TOK_CURRENT_USETIME
, NEXTNUM
},
482 {"saddr", TOK_SRCADDR
, NEXTADDR
},
483 {"srcaddr", TOK_SRCADDR
, NEXTADDR
},
484 {"src", TOK_SRCADDR
, NEXTADDR
},
485 {"daddr", TOK_DSTADDR
, NEXTADDR
},
486 {"dstaddr", TOK_DSTADDR
, NEXTADDR
},
487 {"dst", TOK_DSTADDR
, NEXTADDR
},
488 {"proxyaddr", TOK_PROXYADDR
, NEXTADDR
},
489 {"proxy", TOK_PROXYADDR
, NEXTADDR
},
490 {"innersrc", TOK_PROXYADDR
, NEXTADDR
},
491 {"isrc", TOK_PROXYADDR
, NEXTADDR
},
492 {"innerdst", TOK_IDSTADDR
, NEXTADDR
},
493 {"idst", TOK_IDSTADDR
, NEXTADDR
},
495 {"sport", TOK_SRCPORT
, NEXTNUM
},
496 {"dport", TOK_DSTPORT
, NEXTNUM
},
497 {"innersport", TOK_ISRCPORT
, NEXTNUM
},
498 {"isport", TOK_ISRCPORT
, NEXTNUM
},
499 {"innerdport", TOK_IDSTPORT
, NEXTNUM
},
500 {"idport", TOK_IDSTPORT
, NEXTNUM
},
501 {"proto", TOK_PROTO
, NEXTNUM
},
502 {"ulp", TOK_PROTO
, NEXTNUM
},
503 {"iproto", TOK_IPROTO
, NEXTNUM
},
504 {"iulp", TOK_IPROTO
, NEXTNUM
},
506 {"saddr6", TOK_SRCADDR6
, NEXTADDR
},
507 {"srcaddr6", TOK_SRCADDR6
, NEXTADDR
},
508 {"src6", TOK_SRCADDR6
, NEXTADDR
},
509 {"daddr6", TOK_DSTADDR6
, NEXTADDR
},
510 {"dstaddr6", TOK_DSTADDR6
, NEXTADDR
},
511 {"dst6", TOK_DSTADDR6
, NEXTADDR
},
512 {"proxyaddr6", TOK_PROXYADDR6
, NEXTADDR
},
513 {"proxy6", TOK_PROXYADDR6
, NEXTADDR
},
514 {"innersrc6", TOK_PROXYADDR6
, NEXTADDR
},
515 {"isrc6", TOK_PROXYADDR6
, NEXTADDR
},
516 {"innerdst6", TOK_IDSTADDR6
, NEXTADDR
},
517 {"idst6", TOK_IDSTADDR6
, NEXTADDR
},
519 {"authkey", TOK_AUTHKEY
, NEXTHEX
},
520 {"encrkey", TOK_ENCRKEY
, NEXTHEX
},
521 {"srcidtype", TOK_SRCIDTYPE
, NEXTIDENT
},
522 {"dstidtype", TOK_DSTIDTYPE
, NEXTIDENT
},
523 {"dpd", TOK_DPD
, NEXTNUM
},
524 {"integ_level", TOK_INTEG_LEVEL
, NEXTNUM
},
525 {"integ_map", TOK_INTEG_MAP
, NEXTHEX
},
526 {"nat_loc", TOK_NATLOC
, NEXTADDR
},
527 {"nat_rem", TOK_NATREM
, NEXTADDR
},
528 {"nat_lport", TOK_NATLPORT
, NEXTNUM
},
529 {"nat_rport", TOK_NATRPORT
, NEXTNUM
},
530 {"encap", TOK_ENCAP
, NEXTNUMSTR
},
532 {"outbound", TOK_FLAG_OUTBOUND
, 0},
533 {"inbound", TOK_FLAG_INBOUND
, 0},
535 {"reserved_bits", TOK_RESERVED
, NEXTNUM
},
536 {"replay_value", TOK_REPLAY_VALUE
, NEXTNUM
},
537 {"idle_addtime", TOK_IDLE_ADDTIME
, NEXTNUM
},
538 {"idle_usetime", TOK_IDLE_USETIME
, NEXTNUM
},
540 {NULL
, TOK_UNKNOWN
, NEXTEOF
}
544 * Q: Do I need stuff for proposals, combinations, supported algorithms,
547 * A: Probably not, but you never know.
549 * Parse out extension header type values.
552 parseextval(char *value
, int *next
)
559 for (tp
= tokens
; tp
->string
!= NULL
; tp
++)
560 if (strcmp(value
, tp
->string
) == 0)
564 * Since the OS controls what extensions are available, we don't have
565 * to parse numeric values here.
573 * Parse possible state values.
576 parsestate(char *state
, char *ebuf
)
582 {"larval", SADB_SASTATE_LARVAL
},
583 {"mature", SADB_SASTATE_MATURE
},
584 {"dying", SADB_SASTATE_DYING
},
585 {"dead", SADB_SASTATE_DEAD
},
592 FATAL(ep
, ebuf
, "Unexpected end of command line "
593 "was expecting a state.\n");
596 for (sp
= states
; sp
->state
!= NULL
; sp
++) {
597 if (strcmp(sp
->state
, state
) == 0)
600 ERROR1(ep
, ebuf
, gettext("Unknown state type \"%s\"\n"), state
);
601 handle_errors(ep
, NULL
, B_FALSE
, B_FALSE
);
606 * Return the numerical algorithm identifier corresponding to the specified
610 parsealg(char *alg
, int proto_num
, char *ebuf
)
612 u_longlong_t invalue
;
613 struct ipsecalgent
*algent
;
617 FATAL(ep
, ebuf
, gettext("Unexpected end of command line, "
618 "was expecting an algorithm name.\n"));
621 algent
= getipsecalgbyname(alg
, proto_num
, NULL
);
622 if (algent
!= NULL
) {
625 alg_num
= algent
->a_alg_num
;
626 if (ALG_FLAG_COUNTERMODE
& algent
->a_alg_flags
)
627 WARN1(ep
, ebuf
, gettext(
628 "Using manual keying with a Counter mode algorithm "
629 "such as \"%s\" may be insecure!\n"),
631 freeipsecalgent(algent
);
637 * Since algorithms can be loaded during kernel run-time, check for
638 * numeric algorithm values too. PF_KEY can catch bad ones with EINVAL.
640 invalue
= parsenum(alg
, B_FALSE
, ebuf
);
641 if (invalue
!= (u_longlong_t
)-1 &&
642 (u_longlong_t
)(invalue
& (u_longlong_t
)0xff) == invalue
)
643 return ((uint8_t)invalue
);
645 if (proto_num
== IPSEC_PROTO_ESP
) {
646 ERROR1(ep
, ebuf
, gettext(
647 "Unknown encryption algorithm type \"%s\"\n"), alg
);
649 ERROR1(ep
, ebuf
, gettext(
650 "Unknown authentication algorithm type \"%s\"\n"), alg
);
652 handle_errors(ep
, NULL
, B_FALSE
, B_FALSE
);
657 * Parse and reverse parse out a source/destination ID type.
659 static struct idtypes
{
663 {"prefix", SADB_IDENTTYPE_PREFIX
},
664 {"fqdn", SADB_IDENTTYPE_FQDN
},
665 {"domain", SADB_IDENTTYPE_FQDN
},
666 {"domainname", SADB_IDENTTYPE_FQDN
},
667 {"user_fqdn", SADB_IDENTTYPE_USER_FQDN
},
668 {"mailbox", SADB_IDENTTYPE_USER_FQDN
},
669 {"der_dn", SADB_X_IDENTTYPE_DN
},
670 {"der_gn", SADB_X_IDENTTYPE_GN
},
675 parseidtype(char *type
, char *ebuf
)
678 u_longlong_t invalue
;
682 /* Shouldn't reach here, see callers for why. */
683 FATAL(ep
, ebuf
, gettext("Unexpected end of command line, "
684 "was expecting a type.\n"));
687 for (idp
= idtypes
; idp
->idtype
!= NULL
; idp
++) {
688 if (strcasecmp(idp
->idtype
, type
) == 0)
689 return (idp
->retval
);
692 * Since identity types are almost arbitrary, check for numeric
693 * algorithm values too. PF_KEY can catch bad ones with EINVAL.
695 invalue
= parsenum(type
, B_FALSE
, ebuf
);
696 if (invalue
!= (u_longlong_t
)-1 &&
697 (u_longlong_t
)(invalue
& (u_longlong_t
)0xffff) == invalue
)
698 return ((uint16_t)invalue
);
701 ERROR1(ep
, ebuf
, gettext("Unknown identity type \"%s\"\n"), type
);
703 handle_errors(ep
, NULL
, B_FALSE
, B_FALSE
);
708 * Parse an address off the command line. Return length of sockaddr,
709 * and either return a hostent pointer (caller frees). The new
710 * getipnodebyname() call does the Right Thing (TM), even with
711 * raw addresses (colon-separated IPv6 or dotted decimal IPv4).
719 struct in6_addr ipv6
;
725 parseaddr(char *addr
, struct hostent
**hpp
, boolean_t v6only
, char *ebuf
)
728 struct hostent
*hp
= NULL
;
732 FATAL(ep
, ebuf
, gettext("Unexpected end of command line, "
733 "was expecting an address.\n"));
738 * Try name->address first. Assume AF_INET6, and
739 * get IPv4's, plus IPv6's if and only if IPv6 is configured.
740 * This means to add IPv6 SAs, you must have IPv6
741 * up-and-running. (AI_DEFAULT works here.)
743 hp
= getipnodebyname(addr
, AF_INET6
,
744 (v6only
? AI_ADDRCONFIG
: (AI_DEFAULT
| AI_ALL
)),
748 * Try a normal address conversion only. Use "dummy"
749 * to construct a fake hostent. Caller will know not
752 if (inet_pton(AF_INET6
, addr
, &addr1
) == 1) {
753 dummy
.he
.h_addr_list
= dummy
.addtl
;
754 dummy
.addtl
[0] = (char *)&addr1
;
755 dummy
.addtl
[1] = NULL
;
757 dummy
.he
.h_addrtype
= AF_INET6
;
758 dummy
.he
.h_length
= sizeof (struct in6_addr
);
759 } else if (inet_pton(AF_INET
, addr
, &addr1
) == 1) {
761 * Remap to AF_INET6 anyway.
763 dummy
.he
.h_addr_list
= dummy
.addtl
;
764 dummy
.addtl
[0] = (char *)&addr1
;
765 dummy
.addtl
[1] = NULL
;
767 dummy
.he
.h_addrtype
= AF_INET6
;
768 dummy
.he
.h_length
= sizeof (struct in6_addr
);
770 * NOTE: If macro changes to disallow in-place
771 * conversion, rewhack this.
773 IN6_INADDR_TO_V4MAPPED(&addr1
.ipv4
, &addr1
.ipv6
);
780 WARN1(ep
, ebuf
, gettext("Unknown address %s."), addr
);
783 /* Always return sockaddr_in6 for now. */
784 handle_errors(ep
, NULL
, B_FALSE
, B_FALSE
);
785 return (sizeof (struct sockaddr_in6
));
789 * Parse a hex character for a key. A string will take the form:
792 * xxxxxxxxx == a string of hex characters ([0-9][a-f][A-F])
793 * nn == an optional decimal "mask". If it is not present, it
794 * is assumed that the hex string will be rounded to the nearest
795 * byte, where odd nibbles, like 123 will become 0x0123.
797 * NOTE:Unlike the expression of IP addresses, I will not allow an
798 * excessive "mask". For example 2112/50 is very illegal.
799 * NOTE2: This key should be in canonical order. Consult your man
800 * pages per algorithm about said order.
803 #define hd2num(hd) (((hd) >= '0' && (hd) <= '9') ? ((hd) - '0') : \
804 (((hd) >= 'a' && (hd) <= 'f') ? ((hd) - 'a' + 10) : ((hd) - 'A' + 10)))
806 static struct sadb_key
*
807 parsekey(char *input
, char *ebuf
, uint_t reserved_bits
)
809 struct sadb_key
*retval
;
810 uint_t i
, hexlen
= 0, bits
, alloclen
;
815 FATAL(ep
, ebuf
, gettext("Unexpected end of command line, "
816 "was expecting a key.\n"));
818 /* Allow hex values prepended with 0x convention */
819 if ((strnlen(input
, sizeof (hexlen
)) > 2) &&
820 (strncasecmp(input
, "0x", 2) == 0))
823 for (i
= 0; input
[i
] != '\0' && input
[i
] != '/'; i
++)
826 if (input
[i
] == '\0') {
831 if (sscanf((input
+ i
+ 1), "%u", &bits
) != 1) {
832 FATAL1(ep
, ebuf
, gettext(
833 "\"%s\" is not a bit specifier.\n"),
836 /* hexlen in nibbles */
837 if (((bits
+ 3) >> 2) > hexlen
) {
838 ERROR2(ep
, ebuf
, gettext(
839 "bit length %d is too big for %s.\n"), bits
, input
);
842 * Adjust hexlen down if user gave us too small of a bit
845 if ((hexlen
<< 2) > bits
+ 3) {
846 WARN2(ep
, ebuf
, gettext(
847 "WARNING: Lower bits will be truncated "
848 "for:\n\t%s/%d.\n"), input
, bits
);
849 hexlen
= (bits
+ 3) >> 2;
850 input
[hexlen
] = '\0';
855 * Allocate. Remember, hexlen is in nibbles.
858 alloclen
= sizeof (*retval
) + roundup((hexlen
/2 + (hexlen
& 0x1)), 8);
859 retval
= malloc(alloclen
);
862 Bail("malloc(parsekey)");
863 retval
->sadb_key_len
= SADB_8TO64(alloclen
);
865 retval
->sadb_key_reserved
= reserved_bits
;
868 retval
->sadb_key_bits
= (hexlen
+ (hexlen
& 0x1)) << 2;
870 retval
->sadb_key_bits
= bits
;
873 * Read in nibbles. Read in odd-numbered as shifted high.
874 * (e.g. 123 becomes 0x1230).
877 key
= (uint8_t *)(retval
+ 1);
878 for (i
= 0; input
[i
] != '\0'; i
+= 2) {
879 boolean_t second
= (input
[i
+ 1] != '\0');
881 if (!isxdigit(input
[i
]) ||
882 (!isxdigit(input
[i
+ 1]) && second
)) {
883 ERROR1(ep
, ebuf
, gettext(
884 "string '%s' not a hex value.\n"), input
);
889 *key
= (hd2num(input
[i
]) << 4);
891 *key
|= hd2num(input
[i
+ 1]);
893 break; /* out of for loop. */
897 /* bzero the remaining bits if we're a non-octet amount. */
899 *((input
[i
] == '\0') ? key
- 1 : key
) &=
900 0xff << (8 - (bits
& 0x7));
902 handle_errors(ep
, NULL
, B_FALSE
, B_FALSE
);
906 * Write a message to the PF_KEY socket. If verbose, print the message
907 * heading into the kernel.
910 key_write(int fd
, void *msg
, size_t len
)
914 gettext("VERBOSE ON: Message to kernel looks like:\n"));
915 (void) printf("==========================================\n");
916 print_samsg(stdout
, msg
, B_FALSE
, vflag
, nflag
);
917 (void) printf("==========================================\n");
920 return (write(fd
, msg
, len
));
924 * SIGALRM handler for time_critical_enter.
927 time_critical_catch(int signal
)
929 if (signal
== SIGALRM
) {
930 errx(1, gettext("Reply message from PF_KEY timed out."));
932 errx(1, gettext("Caught signal %d while trying to receive"
933 "PF_KEY reply message"), signal
);
935 /* errx() calls exit. */
938 #define TIME_CRITICAL_TIME 10 /* In seconds */
941 * Enter a "time critical" section where key is waiting for a return message.
944 time_critical_enter(void)
946 (void) signal(SIGALRM
, time_critical_catch
);
947 (void) alarm(TIME_CRITICAL_TIME
);
951 * Exit the "time critical" section after getting an appropriate return
955 time_critical_exit(void)
958 (void) signal(SIGALRM
, SIG_DFL
);
962 * Construct a PF_KEY FLUSH message for the SA type specified.
970 msg_init(&msg
, SADB_FLUSH
, (uint8_t)satype
);
971 rc
= key_write(keysock
, &msg
, sizeof (msg
));
973 Bail("write() to PF_KEY socket failed (in doflush)");
975 time_critical_enter();
977 rc
= read(keysock
, &msg
, sizeof (msg
));
979 Bail("read (in doflush)");
980 } while (msg
.sadb_msg_seq
!= seq
|| msg
.sadb_msg_pid
!= mypid
);
981 time_critical_exit();
984 * I should _never_ hit the following unless:
986 * 1. There is a kernel bug.
987 * 2. There is another process filling in its pid with mine, and
988 * issuing a different message that would cause a different result.
990 if (msg
.sadb_msg_type
!= SADB_FLUSH
||
991 msg
.sadb_msg_satype
!= (uint8_t)satype
) {
992 syslog((LOG_NOTICE
|LOG_AUTH
),
993 gettext("doflush: Return message not of type SADB_FLUSH!"));
994 Bail("doflush: Return message not of type SADB_FLUSH!");
997 if (msg
.sadb_msg_errno
!= 0) {
998 errno
= msg
.sadb_msg_errno
;
999 if (errno
== EINVAL
) {
1000 print_diagnostic(stderr
, msg
.sadb_x_msg_diagnostic
);
1001 warnx(gettext("Cannot flush SA type %d."), satype
);
1003 Bail("return message (in doflush)");
1008 * save_XXX functions are used when "saving" the SA tables to either a
1009 * file or standard output. They use the dump_XXX functions where needed,
1010 * but mostly they use the rparseXXX functions.
1014 * Because "save" and "dump" both use the SADB_DUMP message, fold both
1015 * into the same function.
1018 dodump(int satype
, FILE *ofile
)
1020 struct sadb_msg
*msg
= (struct sadb_msg
*)get_buffer
;
1023 if (ofile
!= NULL
) {
1024 (void) fprintf(ofile
,
1025 gettext("# This key file was generated by the"));
1026 (void) fprintf(ofile
,
1027 gettext(" ipseckey(1m) command's 'save' feature.\n\n"));
1029 msg_init(msg
, SADB_DUMP
, (uint8_t)satype
);
1030 rc
= key_write(keysock
, msg
, sizeof (*msg
));
1032 Bail("write to PF_KEY socket failed (in dodump)");
1036 * For DUMP, do only the read as a time critical section.
1038 time_critical_enter();
1039 rc
= read(keysock
, get_buffer
, sizeof (get_buffer
));
1040 time_critical_exit();
1042 Bail("read (in dodump)");
1043 if (msg
->sadb_msg_pid
== mypid
&&
1044 msg
->sadb_msg_type
== SADB_DUMP
&&
1045 msg
->sadb_msg_seq
!= 0 &&
1046 msg
->sadb_msg_errno
== 0) {
1047 if (ofile
== NULL
) {
1048 print_samsg(stdout
, get_buffer
, B_FALSE
, vflag
,
1050 (void) putchar('\n');
1052 save_assoc(get_buffer
, ofile
);
1055 } while (msg
->sadb_msg_pid
!= mypid
||
1056 (msg
->sadb_msg_errno
== 0 && msg
->sadb_msg_seq
!= 0));
1058 if (ofile
!= NULL
&& ofile
!= stdout
)
1059 (void) fclose(ofile
);
1061 if (msg
->sadb_msg_errno
== 0) {
1064 gettext("Dump succeeded for SA type %d.\n"),
1067 print_diagnostic(stderr
, msg
->sadb_x_msg_diagnostic
);
1068 errno
= msg
->sadb_msg_errno
;
1069 Bail("Dump failed");
1073 #define SCOPE_UNSPEC 0
1074 #define SCOPE_LINKLOCAL 1
1075 #define SCOPE_SITELOCAL 2
1076 #define SCOPE_GLOBAL 3
1077 #define SCOPE_V4COMPAT 4
1078 #define SCOPE_LOOPBACK 5 /* Pedantic, yes, but necessary. */
1081 ipv6_addr_scope(struct in6_addr
*addr
)
1083 /* Don't return anything regarding multicast for now... */
1085 if (IN6_IS_ADDR_UNSPECIFIED(addr
))
1086 return (SCOPE_UNSPEC
);
1088 if (IN6_IS_ADDR_LINKLOCAL(addr
))
1089 return (SCOPE_LINKLOCAL
);
1091 if (IN6_IS_ADDR_SITELOCAL(addr
))
1092 return (SCOPE_SITELOCAL
);
1094 if (IN6_IS_ADDR_V4COMPAT(addr
))
1095 return (SCOPE_V4COMPAT
);
1097 if (IN6_IS_ADDR_LOOPBACK(addr
))
1098 return (SCOPE_LOOPBACK
);
1100 /* For now, return global by default. */
1101 return (SCOPE_GLOBAL
);
1107 * Used by doaddup() and dodelget() to create new SA's based on the
1108 * provided source and destination addresses hostent.
1110 * sadb_msg_type: expected PF_KEY reply message type
1111 * sadb_msg_satype: expected PF_KEY reply satype
1113 * srchp: hostent for the source address(es)
1114 * dsthp: hostent for the destination address(es)
1115 * src: points to the SADB source address extension
1116 * dst: points to the SADB destination address extension
1117 * unspec_src: indicates an unspecified source address.
1118 * buffer: pointer to the SADB buffer to use with PF_KEY
1119 * buffer_size: size of buffer
1120 * spi: spi for this message (set by caller)
1121 * srcport: source port if specified
1122 * dstport: destination port if specified
1123 * proto: IP protocol number if specified
1124 * iproto: Inner (tunnel mode) IP protocol number if specified
1125 * NATT note: we are going to assume a semi-sane world where NAT
1126 * boxen don't explode to multiple addresses.
1129 doaddresses(uint8_t sadb_msg_type
, uint8_t sadb_msg_satype
, int cmd
,
1130 struct hostent
*srchp
, struct hostent
*dsthp
,
1131 struct sadb_address
*src
, struct sadb_address
*dst
,
1132 boolean_t unspec_src
, uint64_t *buffer
, int buffer_size
, uint32_t spi
,
1136 struct sockaddr_in6
*sin6
;
1137 struct sadb_msg
*msgp
;
1139 char **walker
; /* For the SRC and PROXY walking functions. */
1141 uint64_t savebuf
[MAX_GET_SIZE
];
1142 uint16_t srcport
= 0, dstport
= 0;
1146 * Okay, now we have "src", "dst", and maybe "proxy" reassigned
1147 * to point into the buffer to be written to PF_KEY, we can do
1148 * potentially several writes based on destination address.
1150 * First, obtain port numbers from passed-in extensions.
1154 sin6
= (struct sockaddr_in6
*)(src
+ 1);
1155 srcport
= ntohs(sin6
->sin6_port
);
1158 sin6
= (struct sockaddr_in6
*)(dst
+ 1);
1159 dstport
= ntohs(sin6
->sin6_port
);
1163 * The rules for ADD, GET, and UPDATE: (NOTE: This assumes IPsec.
1164 * If other consumers of PF_KEY happen, this will have to be
1167 * Do a message for every possible DST address.
1169 * If a source or proxy address explodes, keep unspecified
1170 * (and mention unspecified).
1172 * DELETE is different, because you can leave either "src" or "dst"
1173 * blank! You need to explode if one of them is full, and not assume
1174 * that the other is set.
1177 if (dsthp
== NULL
) {
1179 * No destination address specified.
1180 * With extended diagnostics, we don't have to bail the
1181 * non-DELETE cases here. The EINVAL diagnostics will be
1182 * enough to inform the user(s) what happened.
1186 if (srchp
== &dummy
.he
) {
1187 /* Just to be sure... */
1188 srchp
->h_addr_list
[1] = NULL
;
1189 } else if (srchp
!= NULL
) {
1190 /* Degenerate case, h_addr_list[0] == NULL. */
1191 if (srchp
->h_addr_list
[i
] == NULL
)
1192 Bail("Empty source address list");
1195 * Fill in the src sockaddr.
1197 sin6
= (struct sockaddr_in6
*)(src
+ 1);
1198 bzero(sin6
, sizeof (*sin6
));
1199 bcopy(srchp
->h_addr_list
[i
], &sin6
->sin6_addr
,
1200 sizeof (struct in6_addr
));
1201 sin6
->sin6_family
= AF_INET6
;
1202 sin6
->sin6_port
= htons(srcport
);
1205 /* Save off a copy for later writing... */
1206 msgp
= (struct sadb_msg
*)buffer
;
1207 bcopy(buffer
, savebuf
, SADB_64TO8(msgp
->sadb_msg_len
));
1209 rc
= key_write(keysock
, buffer
,
1210 SADB_64TO8(msgp
->sadb_msg_len
));
1212 Bail("write() to PF_KEY socket "
1213 "(in doaddresses)");
1215 time_critical_enter();
1217 rc
= read(keysock
, buffer
, buffer_size
);
1219 Bail("read (in doaddresses)");
1220 } while (msgp
->sadb_msg_seq
!= seq
||
1221 msgp
->sadb_msg_pid
!= mypid
);
1222 time_critical_exit();
1224 if (msgp
->sadb_msg_type
!= sadb_msg_type
||
1225 msgp
->sadb_msg_satype
!= sadb_msg_satype
) {
1226 syslog((LOG_NOTICE
|LOG_AUTH
), gettext(
1227 "doaddresses: Unexpected returned message "
1228 "(%d exp %d)\n"), msgp
->sadb_msg_type
,
1230 Bail("doaddresses: Unexpected returned "
1234 errno
= msgp
->sadb_msg_errno
;
1236 if (errno
== EINVAL
) {
1237 WARN(ep
, ebuf
, gettext(
1238 "One of the entered "
1239 "values is incorrect."));
1240 print_diagnostic(stderr
,
1241 msgp
->sadb_x_msg_diagnostic
);
1243 Bail("return message (in doaddresses)");
1247 /* ...and then restore the saved buffer. */
1248 msgp
= (struct sadb_msg
*)savebuf
;
1249 bcopy(savebuf
, buffer
, SADB_64TO8(msgp
->sadb_msg_len
));
1250 } while (srchp
!= NULL
&& srchp
->h_addr_list
[++i
] != NULL
);
1255 * Go through the list of all dst addresses, trying to find matching
1256 * src address for each. If the first address is == dummy.he we will go
1257 * through the loop just once. If any other hp is == dummy.he, then we
1258 * don't have to apply any silly rules.
1260 for (i
= 0; dsthp
->h_addr_list
[i
] != NULL
; i
++) {
1261 if (dsthp
== &dummy
.he
) {
1262 /* Just to be sure... */
1263 dsthp
->h_addr_list
[1] = NULL
;
1266 * Fill in the dst sockaddr.
1268 sin6
= (struct sockaddr_in6
*)(dst
+ 1);
1269 bzero(sin6
, sizeof (*sin6
));
1270 bcopy(dsthp
->h_addr_list
[i
], &sin6
->sin6_addr
,
1271 sizeof (struct in6_addr
));
1272 sin6
->sin6_family
= AF_INET6
;
1273 sin6
->sin6_port
= htons(dstport
);
1276 last_dst
= (dsthp
->h_addr_list
[i
+ 1] == NULL
);
1279 * Try and assign src, if there's any ambiguity.
1281 if (!unspec_src
&& srchp
!= &dummy
.he
) {
1282 if (IN6_IS_ADDR_V4MAPPED(&sin6
->sin6_addr
)) {
1284 * IPv4 address. Find an IPv4 address, then
1285 * keep looking for a second one. If a second
1286 * exists, print a message, and fill in the
1287 * unspecified address.
1291 for (walker
= srchp
->h_addr_list
;
1292 *walker
!= NULL
; walker
++) {
1293 /* LINTED E_BAD_PTR_CAST_ALIGN */
1294 if (IN6_IS_ADDR_V4MAPPED(
1295 (struct in6_addr
*)*walker
)) {
1296 if (first_match
!= NULL
)
1299 first_match
= *walker
;
1302 sin6
= (struct sockaddr_in6
*)(src
+ 1);
1303 bzero(sin6
, sizeof (*sin6
));
1305 if (first_match
== NULL
) {
1307 * No IPv4 hits. Is this the last
1308 * destination address in the list ?
1310 ERROR1(ep
, ebuf
, gettext(
1311 "No IPv4 source address "
1312 "for name %s.\n"), srchp
->h_name
);
1314 FATAL(ep
, ebuf
, gettext(
1315 "No match for destination "
1318 /* Continue, but do I print? */
1319 continue; /* for loop */
1322 /* I should never reach here. */
1325 sin6
->sin6_family
= AF_INET6
;
1326 sin6
->sin6_port
= htons(srcport
);
1327 if (*walker
!= NULL
) {
1329 * Early loop exit. It must've been
1332 * Issue a null-source warning?
1334 WARN1(ep
, ebuf
, gettext(
1335 "Multiple IPv4 source addresses "
1336 "for %s, using unspecified source "
1337 "instead."), srchp
->h_name
);
1340 * If I reach here w/o hitting the
1341 * previous if statements, I have a
1342 * single source address for this
1345 bcopy(first_match
, &sin6
->sin6_addr
,
1346 sizeof (struct in6_addr
));
1350 * IPv6 address. Find an IPv6 address.
1351 * Unlike IPv4 addresses, things can get a
1352 * little more sticky with scopes, etc.
1354 int dst_scope
, src_scope
;
1356 dst_scope
= ipv6_addr_scope(&sin6
->sin6_addr
);
1359 for (walker
= srchp
->h_addr_list
;
1360 *walker
!= NULL
; walker
++) {
1361 /* LINTED E_BAD_PTR_CAST_ALIGN */
1362 if (!IN6_IS_ADDR_V4MAPPED(
1363 (struct in6_addr
*)*walker
)) {
1365 * Set first-match, etc.
1366 * Take into account scopes,
1367 * and other IPv6 thingies.
1369 src_scope
= ipv6_addr_scope(
1370 /* LINTED E_BAD_PTR_CAST */
1371 (struct in6_addr
*)*walker
);
1372 if (src_scope
== SCOPE_UNSPEC
||
1373 src_scope
== dst_scope
) {
1384 sin6
= (struct sockaddr_in6
*)(src
+ 1);
1385 bzero(sin6
, sizeof (*sin6
));
1386 sin6
->sin6_port
= htons(srcport
);
1387 if (first_match
== NULL
) {
1389 * No IPv6 hits. Is this the last
1390 * destination address in the list ?
1392 ERROR1(ep
, ebuf
, gettext(
1393 "No IPv6 source address of "
1394 "matching scope for name %s.\n"),
1397 FATAL(ep
, ebuf
, gettext(
1398 "No match for IPV6 "
1402 /* Continue, but do I print? */
1403 continue; /* for loop */
1406 /* I should never reach here. */
1408 sin6
->sin6_family
= AF_INET6
;
1409 if (*walker
!= NULL
) {
1411 * Early loop exit. Issue a
1412 * null-source warning?
1414 WARN1(ep
, ebuf
, gettext(
1415 "Multiple IPv6 source addresses "
1416 "for %s of the same scope, using "
1417 "unspecified source instead.\n"),
1421 * If I reach here w/o hitting the
1422 * previous if statements, I have a
1423 * single source address for this
1426 bcopy(first_match
, &sin6
->sin6_addr
,
1427 sizeof (struct in6_addr
));
1433 * If there are errors at this point there is no
1434 * point sending anything to PF_KEY.
1436 handle_errors(ep
, ebuf
, B_TRUE
, B_FALSE
);
1438 /* Save off a copy for later writing... */
1439 msgp
= (struct sadb_msg
*)buffer
;
1440 bcopy(buffer
, savebuf
, SADB_64TO8(msgp
->sadb_msg_len
));
1442 rc
= key_write(keysock
, buffer
, SADB_64TO8(msgp
->sadb_msg_len
));
1444 Bail("write() to PF_KEY socket (in doaddresses)");
1446 /* Blank the key for paranoia's sake. */
1447 bzero(buffer
, buffer_size
);
1448 time_critical_enter();
1450 rc
= read(keysock
, buffer
, buffer_size
);
1452 Bail("read (in doaddresses)");
1453 } while (msgp
->sadb_msg_seq
!= seq
||
1454 msgp
->sadb_msg_pid
!= mypid
);
1455 time_critical_exit();
1458 * I should _never_ hit the following unless:
1460 * 1. There is a kernel bug.
1461 * 2. Another process is mistakenly using my pid in a PF_KEY
1464 if (msgp
->sadb_msg_type
!= sadb_msg_type
||
1465 msgp
->sadb_msg_satype
!= sadb_msg_satype
) {
1466 syslog((LOG_NOTICE
|LOG_AUTH
), gettext(
1467 "doaddresses: Unexpected returned message "
1468 "(%d exp %d)\n"), msgp
->sadb_msg_type
,
1470 Bail("doaddresses: Unexpected returned message");
1473 if (msgp
->sadb_msg_errno
!= 0) {
1474 char addrprint
[INET6_ADDRSTRLEN
];
1479 * Print different error messages depending
1480 * on the SADB message type being processed.
1481 * If we get a ESRCH error for a GET/DELETE
1482 * messages, we report that the SA does not
1483 * exist. If we get a EEXIST error for a
1484 * ADD/UPDATE message, we report that the
1485 * SA already exists.
1487 if (sadb_msg_type
== SADB_GET
||
1488 sadb_msg_type
== SADB_DELETE
) {
1490 on_errno_msg
= "does not exist";
1491 } else if (sadb_msg_type
== SADB_ADD
||
1492 sadb_msg_type
== SADB_UPDATE
) {
1494 on_errno_msg
= "already exists";
1497 errno
= msgp
->sadb_msg_errno
;
1498 if (errno
== on_errno
) {
1499 ERROR2(ep
, ebuf
, gettext(
1500 "Association (type = %s) "
1501 "with spi 0x%x and addr\n"),
1502 rparsesatype(msgp
->sadb_msg_satype
),
1504 ERROR2(ep
, ebuf
, "%s %s.\n",
1505 do_inet_ntop(dsthp
->h_addr_list
[i
],
1506 addrprint
, sizeof (addrprint
)),
1508 msgp
= (struct sadb_msg
*)savebuf
;
1509 bcopy(savebuf
, buffer
,
1510 SADB_64TO8(msgp
->sadb_msg_len
));
1513 if (errno
== EINVAL
|| errno
== ESRCH
) {
1514 ERROR2(ep
, ebuf
, gettext(
1515 "PF_KEY Diagnostic code %u: %s.\n"),
1516 msgp
->sadb_x_msg_diagnostic
,
1518 msgp
->sadb_x_msg_diagnostic
));
1520 Bail("return message (in doaddresses)");
1525 if (cmd
== CMD_GET
) {
1526 if (msgp
->sadb_msg_len
> MAX_GET_SIZE
) {
1527 WARN1(ep
, ebuf
, gettext("WARNING: "
1528 "SA information bigger than %d bytes.\n"),
1529 SADB_64TO8(MAX_GET_SIZE
));
1531 print_samsg(stdout
, buffer
, B_FALSE
, vflag
, nflag
);
1534 handle_errors(ep
, ebuf
, B_TRUE
, B_FALSE
);
1536 /* ...and then restore the saved buffer. */
1537 msgp
= (struct sadb_msg
*)savebuf
;
1538 bcopy(savebuf
, buffer
, SADB_64TO8(msgp
->sadb_msg_len
));
1542 /* Degenerate case, h_addr_list[0] == NULL. */
1544 Bail("Empty destination address list");
1547 * free(ebuf) even if there are no errors.
1548 * handle_errors() won't return here.
1550 handle_errors(ep
, ebuf
, B_TRUE
, B_TRUE
);
1554 * Perform an add or an update. ADD and UPDATE are similar in the extensions
1558 doaddup(int cmd
, int satype
, char *argv
[], char *ebuf
)
1560 uint64_t *buffer
, *nexthdr
;
1561 struct sadb_msg msg
;
1562 struct sadb_sa
*assoc
= NULL
;
1563 struct sadb_x_pair
*sadb_pair
= NULL
;
1564 struct sadb_address
*src
= NULL
, *dst
= NULL
;
1565 struct sadb_address
*isrc
= NULL
, *idst
= NULL
;
1566 struct sadb_address
*natt_local
= NULL
, *natt_remote
= NULL
;
1567 struct sadb_key
*encrypt
= NULL
, *auth
= NULL
;
1568 struct sadb_ident
*srcid
= NULL
, *dstid
= NULL
;
1569 struct sadb_lifetime
*hard
= NULL
, *soft
= NULL
; /* Current? */
1570 struct sadb_lifetime
*idle
= NULL
;
1571 struct sadb_x_replay_ctr
*replay_ctr
= NULL
;
1572 struct sockaddr_in6
*sin6
;
1573 int next
, token
, sa_len
, alloclen
, totallen
= sizeof (msg
), prefix
;
1575 uint_t reserved_bits
= 0;
1576 uint8_t sadb_msg_type
;
1577 char *thiscmd
, *pstr
;
1578 boolean_t readstate
= B_FALSE
, unspec_src
= B_FALSE
;
1579 boolean_t alloc_inner
= B_FALSE
, use_natt
= B_FALSE
;
1580 struct hostent
*srchp
= NULL
, *dsthp
= NULL
, *isrchp
= NULL
,
1582 struct hostent
*natt_lhp
= NULL
, *natt_rhp
= NULL
;
1583 uint16_t srcport
= 0, dstport
= 0, natt_lport
= 0, natt_rport
= 0,
1584 isrcport
= 0, idstport
= 0;
1585 uint8_t proto
= 0, iproto
= 0;
1591 sadb_msg_type
= SADB_ADD
;
1595 sadb_msg_type
= SADB_UPDATE
;
1597 case CMD_UPDATE_PAIR
:
1598 thiscmd
= "update-pair";
1599 sadb_msg_type
= SADB_X_UPDATEPAIR
;
1603 msg_init(&msg
, sadb_msg_type
, (uint8_t)satype
);
1604 /* Assume last element in argv is set to NULL. */
1606 token
= parseextval(*argv
, &next
);
1610 /* Do nothing, I'm done. */
1613 ERROR1(ep
, ebuf
, gettext(
1614 "Unknown extension field \"%s\" \n"), *(argv
- 1));
1624 * May want to place this chunk of code in a function.
1626 * This code checks for duplicate entries on a command
1630 /* Allocate the SADB_EXT_SA extension. */
1631 if (assoc
== NULL
) {
1632 assoc
= malloc(sizeof (*assoc
));
1634 Bail("malloc(assoc)");
1635 bzero(assoc
, sizeof (*assoc
));
1636 assoc
->sadb_sa_exttype
= SADB_EXT_SA
;
1637 assoc
->sadb_sa_len
=
1638 SADB_8TO64(sizeof (*assoc
));
1639 totallen
+= sizeof (*assoc
);
1644 * If some cretin types in "spi 0" then they
1645 * can type in another SPI.
1647 if (assoc
->sadb_sa_spi
!= 0) {
1648 ERROR(ep
, ebuf
, gettext(
1650 "single SPI value.\n"));
1653 /* Must convert SPI to network order! */
1654 assoc
->sadb_sa_spi
=
1655 htonl((uint32_t)parsenum(*argv
, B_TRUE
,
1657 if (assoc
->sadb_sa_spi
== 0) {
1658 ERROR(ep
, ebuf
, gettext(
1659 "Invalid SPI value \"0\" .\n"));
1663 if (cmd
== CMD_UPDATE_PAIR
) {
1664 ERROR(ep
, ebuf
, gettext(
1665 "pair-spi can not be used with the "
1666 "\"update-pair\" command.\n"));
1668 if (sadb_pair
== NULL
) {
1669 sadb_pair
= malloc(sizeof (*sadb_pair
));
1671 Bail("malloc(assoc)");
1672 bzero(sadb_pair
, sizeof (*sadb_pair
));
1673 totallen
+= sizeof (*sadb_pair
);
1675 if (sadb_pair
->sadb_x_pair_spi
!= 0) {
1676 ERROR(ep
, ebuf
, gettext(
1678 "single pair SPI value.\n"));
1681 /* Must convert SPI to network order! */
1682 sadb_pair
->sadb_x_pair_len
=
1683 SADB_8TO64(sizeof (*sadb_pair
));
1684 sadb_pair
->sadb_x_pair_exttype
=
1686 sadb_pair
->sadb_x_pair_spi
=
1687 htonl((uint32_t)parsenum(*argv
, B_TRUE
,
1689 if (sadb_pair
->sadb_x_pair_spi
== 0) {
1690 ERROR(ep
, ebuf
, gettext(
1691 "Invalid SPI value \"0\" .\n"));
1693 assoc
->sadb_sa_flags
|=
1694 SADB_X_SAFLAGS_PAIRED
;
1698 * That same cretin can do the same with
1701 if (assoc
->sadb_sa_replay
!= 0) {
1702 ERROR(ep
, ebuf
, gettext(
1704 "single replay window size.\n"));
1707 assoc
->sadb_sa_replay
=
1708 (uint8_t)parsenum(*argv
, B_TRUE
, ebuf
);
1709 if (assoc
->sadb_sa_replay
!= 0) {
1710 WARN(ep
, ebuf
, gettext(
1711 "WARNING: Replay with manual"
1712 " keying considered harmful.\n"));
1717 * 0 is an actual state value, LARVAL. This
1718 * means that one can type in the larval state
1719 * and then type in another state on the same
1722 if (assoc
->sadb_sa_state
!= 0) {
1723 ERROR(ep
, ebuf
, gettext(
1725 "single SA state.\n"));
1728 assoc
->sadb_sa_state
= parsestate(*argv
,
1733 if (assoc
->sadb_sa_auth
!= 0) {
1734 ERROR(ep
, ebuf
, gettext(
1736 "single auth algorithm.\n"));
1739 assoc
->sadb_sa_auth
= parsealg(*argv
,
1740 IPSEC_PROTO_AH
, ebuf
);
1743 if (satype
== SADB_SATYPE_AH
) {
1744 ERROR(ep
, ebuf
, gettext("Cannot specify"
1745 " encryption with SA type ah.\n"));
1748 if (assoc
->sadb_sa_encrypt
!= 0) {
1749 ERROR(ep
, ebuf
, gettext(
1751 "single encryption algorithm.\n"));
1754 assoc
->sadb_sa_encrypt
= parsealg(*argv
,
1755 IPSEC_PROTO_ESP
, ebuf
);
1759 ERROR(ep
, ebuf
, gettext(
1760 "Can only specify single"
1761 " encapsulation.\n"));
1764 if (strncmp(*argv
, "udp", 3)) {
1765 ERROR(ep
, ebuf
, gettext(
1766 "Can only specify udp"
1767 " encapsulation.\n"));
1771 /* set assoc flags later */
1778 ERROR(ep
, ebuf
, gettext("Can only specify "
1779 "single source port.\n"));
1782 srcport
= parsenum(*argv
, B_TRUE
, ebuf
);
1787 ERROR(ep
, ebuf
, gettext("Can only specify "
1788 "single destination port.\n"));
1791 dstport
= parsenum(*argv
, B_TRUE
, ebuf
);
1795 alloc_inner
= B_TRUE
;
1796 if (isrcport
!= 0) {
1797 ERROR(ep
, ebuf
, gettext(
1799 "single inner-source port.\n"));
1802 isrcport
= parsenum(*argv
, B_TRUE
, ebuf
);
1806 alloc_inner
= B_TRUE
;
1807 if (idstport
!= 0) {
1808 ERROR(ep
, ebuf
, gettext(
1810 "single inner-destination port.\n"));
1813 idstport
= parsenum(*argv
, B_TRUE
, ebuf
);
1817 if (natt_lport
!= 0) {
1818 ERROR(ep
, ebuf
, gettext(
1820 "single NAT-T local port.\n"));
1823 natt_lport
= parsenum(*argv
, B_TRUE
, ebuf
);
1827 if (natt_rport
!= 0) {
1828 ERROR(ep
, ebuf
, gettext(
1830 "single NAT-T remote port.\n"));
1833 natt_rport
= parsenum(*argv
, B_TRUE
, ebuf
);
1839 ERROR(ep
, ebuf
, gettext(
1841 "single protocol.\n"));
1844 proto
= parsenum(*argv
, B_TRUE
, ebuf
);
1848 alloc_inner
= B_TRUE
;
1850 ERROR(ep
, ebuf
, gettext(
1852 "single inner protocol.\n"));
1855 iproto
= parsenum(*argv
, B_TRUE
, ebuf
);
1861 ERROR(ep
, ebuf
, gettext(
1863 "single source address.\n"));
1866 sa_len
= parseaddr(*argv
, &srchp
,
1867 (token
== TOK_SRCADDR6
), ebuf
);
1868 if (srchp
== NULL
) {
1869 ERROR1(ep
, ebuf
, gettext(
1870 "Unknown src address \"%s\"\n"), *argv
);
1875 * Round of the sockaddr length to an 8 byte
1876 * boundary to make PF_KEY happy.
1878 alloclen
= sizeof (*src
) + roundup(sa_len
, 8);
1879 src
= malloc(alloclen
);
1881 Bail("malloc(src)");
1882 totallen
+= alloclen
;
1883 src
->sadb_address_len
= SADB_8TO64(alloclen
);
1884 src
->sadb_address_exttype
= SADB_EXT_ADDRESS_SRC
;
1885 src
->sadb_address_reserved
= 0;
1886 src
->sadb_address_prefixlen
= 0;
1887 src
->sadb_address_proto
= 0;
1888 if (srchp
== &dummy
.he
) {
1890 * Single address with -n flag.
1892 sin6
= (struct sockaddr_in6
*)(src
+ 1);
1893 bzero(sin6
, sizeof (*sin6
));
1894 sin6
->sin6_family
= AF_INET6
;
1895 bcopy(srchp
->h_addr_list
[0], &sin6
->sin6_addr
,
1896 sizeof (struct in6_addr
));
1902 ERROR(ep
, ebuf
, gettext(
1903 "Can only specify single "
1904 "destination address.\n"));
1907 sa_len
= parseaddr(*argv
, &dsthp
,
1908 (token
== TOK_DSTADDR6
), ebuf
);
1909 if (dsthp
== NULL
) {
1910 ERROR1(ep
, ebuf
, gettext(
1911 "Unknown dst address \"%s\"\n"), *argv
);
1915 alloclen
= sizeof (*dst
) + roundup(sa_len
, 8);
1916 dst
= malloc(alloclen
);
1918 Bail("malloc(dst)");
1919 totallen
+= alloclen
;
1920 dst
->sadb_address_len
= SADB_8TO64(alloclen
);
1921 dst
->sadb_address_exttype
= SADB_EXT_ADDRESS_DST
;
1922 dst
->sadb_address_reserved
= 0;
1923 dst
->sadb_address_prefixlen
= 0;
1924 dst
->sadb_address_proto
= 0;
1925 if (dsthp
== &dummy
.he
) {
1927 * Single address with -n flag.
1929 sin6
= (struct sockaddr_in6
*)(dst
+ 1);
1930 bzero(sin6
, sizeof (*sin6
));
1931 sin6
->sin6_family
= AF_INET6
;
1932 bcopy(dsthp
->h_addr_list
[0], &sin6
->sin6_addr
,
1933 sizeof (struct in6_addr
));
1937 case TOK_PROXYADDR6
:
1939 ERROR(ep
, ebuf
, gettext(
1940 "Can only specify single "
1941 "proxy/inner-source address.\n"));
1944 if ((pstr
= strchr(*argv
, '/')) != NULL
) {
1945 /* Parse out the prefix. */
1947 prefix
= strtol(pstr
+ 1, NULL
, 10);
1949 ERROR1(ep
, ebuf
, gettext(
1950 "Invalid prefix %s."), pstr
);
1954 alloclen
= (int)(pstr
- *argv
);
1955 pstr
= malloc(alloclen
+ 1);
1957 Bail("malloc(pstr)");
1959 (void) strlcpy(pstr
, *argv
, alloclen
+ 1);
1963 * Assume mapping to AF_INET6, and we're a host.
1964 * XXX some miscreants may still make classful
1965 * assumptions. If this is a problem, fix it
1970 sa_len
= parseaddr(pstr
, &isrchp
,
1971 (token
== TOK_PROXYADDR6
), ebuf
);
1972 if (isrchp
== NULL
) {
1973 ERROR1(ep
, ebuf
, gettext(
1974 "Unknown proxy/inner-source address "
1975 "\"%s\"\n"), *argv
);
1981 alloclen
= sizeof (*isrc
) + roundup(sa_len
, 8);
1982 isrc
= malloc(alloclen
);
1984 Bail("malloc(isrc)");
1985 totallen
+= alloclen
;
1986 isrc
->sadb_address_len
= SADB_8TO64(alloclen
);
1987 isrc
->sadb_address_exttype
= SADB_EXT_ADDRESS_PROXY
;
1988 isrc
->sadb_address_reserved
= 0;
1989 isrc
->sadb_address_prefixlen
= prefix
;
1990 isrc
->sadb_address_proto
= 0;
1991 if (isrchp
== &dummy
.he
||
1992 isrchp
->h_addr_list
[1] == NULL
) {
1994 * Single address with -n flag or single name.
1996 sin6
= (struct sockaddr_in6
*)(isrc
+ 1);
1997 bzero(sin6
, sizeof (*sin6
));
1998 sin6
->sin6_family
= AF_INET6
;
1999 bcopy(isrchp
->h_addr_list
[0], &sin6
->sin6_addr
,
2000 sizeof (struct in6_addr
));
2002 * normalize prefixlen for IPv4-mapped
2006 IN6_IS_ADDR_V4MAPPED(&sin6
->sin6_addr
))
2007 isrc
->sadb_address_prefixlen
+= 96;
2008 alloc_inner
= B_TRUE
;
2011 * If the proxy/isrc address is vague, don't
2014 totallen
-= alloclen
;
2017 WARN1(ep
, ebuf
, gettext(
2018 "Proxy/inner-source address %s "
2019 "is vague, not using.\n"), isrchp
->h_name
);
2020 freehostent(isrchp
);
2028 ERROR(ep
, ebuf
, gettext(
2029 "Can only specify single "
2030 "inner-destination address.\n"));
2033 if ((pstr
= strchr(*argv
, '/')) != NULL
) {
2034 /* Parse out the prefix. */
2036 prefix
= strtol(pstr
+ 1, NULL
, 10);
2038 ERROR1(ep
, ebuf
, gettext(
2039 "Invalid prefix %s.\n"), pstr
);
2043 alloclen
= (int)(pstr
- *argv
);
2044 pstr
= malloc(alloclen
+ 1);
2046 Bail("malloc(pstr)");
2048 (void) strlcpy(pstr
, *argv
, alloclen
+ 1);
2052 * Assume mapping to AF_INET6, and we're a host.
2053 * XXX some miscreants may still make classful
2054 * assumptions. If this is a problem, fix it
2059 sa_len
= parseaddr(pstr
, &idsthp
,
2060 (token
== TOK_IDSTADDR6
), ebuf
);
2061 if (idsthp
== NULL
) {
2062 ERROR1(ep
, ebuf
, gettext(
2063 "Unknown Inner Src address "
2064 " \"%s\"\n"), *argv
);
2070 alloclen
= sizeof (*idst
) + roundup(sa_len
, 8);
2071 idst
= malloc(alloclen
);
2073 Bail("malloc(idst)");
2074 totallen
+= alloclen
;
2075 idst
->sadb_address_len
= SADB_8TO64(alloclen
);
2076 idst
->sadb_address_exttype
=
2077 SADB_X_EXT_ADDRESS_INNER_DST
;
2078 idst
->sadb_address_reserved
= 0;
2079 idst
->sadb_address_prefixlen
= prefix
;
2080 idst
->sadb_address_proto
= 0;
2081 if (idsthp
== &dummy
.he
||
2082 idsthp
->h_addr_list
[1] == NULL
) {
2084 * Single address with -n flag or single name.
2086 sin6
= (struct sockaddr_in6
*)(idst
+ 1);
2087 bzero(sin6
, sizeof (*sin6
));
2088 sin6
->sin6_family
= AF_INET6
;
2089 bcopy(idsthp
->h_addr_list
[0], &sin6
->sin6_addr
,
2090 sizeof (struct in6_addr
));
2092 * normalize prefixlen for IPv4-mapped
2096 IN6_IS_ADDR_V4MAPPED(&sin6
->sin6_addr
))
2097 idst
->sadb_address_prefixlen
+= 96;
2098 alloc_inner
= B_TRUE
;
2101 * If the idst address is vague, don't bother.
2103 totallen
-= alloclen
;
2106 WARN1(ep
, ebuf
, gettext(
2107 "Inner destination address %s "
2108 "is vague, not using.\n"), idsthp
->h_name
);
2109 freehostent(idsthp
);
2115 if (natt_local
!= NULL
) {
2116 ERROR(ep
, ebuf
, gettext(
2118 "single NAT-T local address.\n"));
2121 sa_len
= parseaddr(*argv
, &natt_lhp
, 0, ebuf
);
2122 if (natt_lhp
== NULL
) {
2123 ERROR1(ep
, ebuf
, gettext(
2124 "Unknown NAT-T local address \"%s\"\n"),
2130 * Round of the sockaddr length to an 8 byte
2131 * boundary to make PF_KEY happy.
2133 alloclen
= sizeof (*natt_local
) + roundup(sa_len
, 8);
2134 natt_local
= malloc(alloclen
);
2135 if (natt_local
== NULL
)
2136 Bail("malloc(natt_local)");
2137 totallen
+= alloclen
;
2138 natt_local
->sadb_address_len
= SADB_8TO64(alloclen
);
2139 natt_local
->sadb_address_exttype
=
2140 SADB_X_EXT_ADDRESS_NATT_LOC
;
2141 natt_local
->sadb_address_reserved
= 0;
2142 natt_local
->sadb_address_prefixlen
= 0;
2143 natt_local
->sadb_address_proto
= 0;
2144 if (natt_lhp
== &dummy
.he
||
2145 natt_lhp
->h_addr_list
[1] == NULL
) {
2147 * Single address with -n flag or single name.
2149 sin6
= (struct sockaddr_in6
*)(natt_local
+ 1);
2150 bzero(sin6
, sizeof (*sin6
));
2151 sin6
->sin6_family
= AF_INET6
;
2152 bcopy(natt_lhp
->h_addr_list
[0],
2153 &sin6
->sin6_addr
, sizeof (struct in6_addr
));
2156 * If the nat-local address is vague, don't
2159 totallen
-= alloclen
;
2162 WARN1(ep
, ebuf
, gettext(
2163 "NAT-T local address %s "
2164 "is vague, not using.\n"),
2166 freehostent(natt_lhp
);
2172 if (natt_remote
!= NULL
) {
2173 ERROR(ep
, ebuf
, gettext(
2175 "single NAT-T remote address.\n"));
2178 sa_len
= parseaddr(*argv
, &natt_rhp
, 0, ebuf
);
2179 if (natt_rhp
== NULL
) {
2180 ERROR1(ep
, ebuf
, gettext(
2181 "Unknown NAT-T remote address \"%s\"\n"),
2187 * Round of the sockaddr length to an 8 byte
2188 * boundary to make PF_KEY happy.
2190 alloclen
= sizeof (*natt_remote
) + roundup(sa_len
, 8);
2191 natt_remote
= malloc(alloclen
);
2192 if (natt_remote
== NULL
)
2193 Bail("malloc(natt_remote)");
2194 totallen
+= alloclen
;
2195 natt_remote
->sadb_address_len
= SADB_8TO64(alloclen
);
2196 natt_remote
->sadb_address_exttype
=
2197 SADB_X_EXT_ADDRESS_NATT_REM
;
2198 natt_remote
->sadb_address_reserved
= 0;
2199 natt_remote
->sadb_address_prefixlen
= 0;
2200 natt_remote
->sadb_address_proto
= 0;
2201 if (natt_rhp
== &dummy
.he
||
2202 natt_rhp
->h_addr_list
[1] == NULL
) {
2204 * Single address with -n flag or single name.
2206 sin6
= (struct sockaddr_in6
*)(natt_remote
+ 1);
2207 bzero(sin6
, sizeof (*sin6
));
2208 sin6
->sin6_family
= AF_INET6
;
2209 bcopy(natt_rhp
->h_addr_list
[0],
2210 &sin6
->sin6_addr
, sizeof (struct in6_addr
));
2213 * If the nat-renote address is vague, don't
2216 totallen
-= alloclen
;
2219 WARN1(ep
, ebuf
, gettext(
2220 "NAT-T remote address %s "
2221 "is vague, not using.\n"),
2223 freehostent(natt_rhp
);
2229 if (encrypt
!= NULL
) {
2230 ERROR(ep
, ebuf
, gettext(
2232 "single encryption key.\n"));
2235 if (assoc
!= NULL
&&
2236 assoc
->sadb_sa_encrypt
== SADB_EALG_NULL
) {
2237 FATAL(ep
, ebuf
, gettext(
2238 "Cannot specify a key with NULL "
2239 "encryption algorithm.\n"));
2242 encrypt
= parsekey(*argv
, ebuf
, reserved_bits
);
2244 if (encrypt
== NULL
) {
2245 ERROR(ep
, ebuf
, gettext(
2246 "Invalid encryption key.\n"));
2249 totallen
+= SADB_64TO8(encrypt
->sadb_key_len
);
2250 encrypt
->sadb_key_exttype
= SADB_EXT_KEY_ENCRYPT
;
2254 ERROR(ep
, ebuf
, gettext(
2255 "Can only specify single"
2256 " authentication key.\n"));
2259 auth
= parsekey(*argv
, ebuf
, 0);
2262 ERROR(ep
, ebuf
, gettext(
2263 "Invalid authentication key.\n"));
2266 totallen
+= SADB_64TO8(auth
->sadb_key_len
);
2267 auth
->sadb_key_exttype
= SADB_EXT_KEY_AUTH
;
2270 if (*argv
== NULL
|| *(argv
+ 1) == NULL
) {
2271 FATAL(ep
, ebuf
, gettext(
2272 "Unexpected end of command "
2273 "line - Expecting Src Type.\n"));
2277 if (srcid
!= NULL
) {
2278 ERROR(ep
, ebuf
, gettext(
2279 "Can only specify single"
2280 " source certificate identity.\n"));
2283 alloclen
= sizeof (*srcid
) +
2284 roundup(strlen(*(argv
+ 1)) + 1, 8);
2285 srcid
= malloc(alloclen
);
2287 Bail("malloc(srcid)");
2288 totallen
+= alloclen
;
2289 srcid
->sadb_ident_type
= parseidtype(*argv
, ebuf
);
2291 srcid
->sadb_ident_len
= SADB_8TO64(alloclen
);
2292 srcid
->sadb_ident_exttype
= SADB_EXT_IDENTITY_SRC
;
2293 srcid
->sadb_ident_reserved
= 0;
2294 srcid
->sadb_ident_id
= 0; /* Not useful here. */
2295 (void) strlcpy((char *)(srcid
+ 1), *argv
, alloclen
);
2299 if (*argv
== NULL
|| *(argv
+ 1) == NULL
) {
2300 ERROR(ep
, ebuf
, gettext(
2301 "Unexpected end of command"
2302 " line - expecting dst type.\n"));
2305 if (dstid
!= NULL
) {
2306 ERROR(ep
, ebuf
, gettext(
2307 "Can only specify single destination "
2308 "certificate identity.\n"));
2311 alloclen
= sizeof (*dstid
) +
2312 roundup(strlen(*(argv
+ 1)) + 1, 8);
2313 dstid
= malloc(alloclen
);
2315 Bail("malloc(dstid)");
2316 totallen
+= alloclen
;
2317 dstid
->sadb_ident_type
= parseidtype(*argv
, ebuf
);
2319 dstid
->sadb_ident_len
= SADB_8TO64(alloclen
);
2320 dstid
->sadb_ident_exttype
= SADB_EXT_IDENTITY_DST
;
2321 dstid
->sadb_ident_reserved
= 0;
2322 dstid
->sadb_ident_id
= 0; /* Not useful here. */
2323 (void) strlcpy((char *)(dstid
+ 1), *argv
, alloclen
);
2326 case TOK_HARD_ALLOC
:
2327 case TOK_HARD_BYTES
:
2328 case TOK_HARD_ADDTIME
:
2329 case TOK_HARD_USETIME
:
2331 hard
= malloc(sizeof (*hard
));
2333 Bail("malloc(hard_lifetime)");
2334 bzero(hard
, sizeof (*hard
));
2335 hard
->sadb_lifetime_exttype
=
2336 SADB_EXT_LIFETIME_HARD
;
2337 hard
->sadb_lifetime_len
=
2338 SADB_8TO64(sizeof (*hard
));
2339 totallen
+= sizeof (*hard
);
2342 case TOK_HARD_ALLOC
:
2343 if (hard
->sadb_lifetime_allocations
!= 0) {
2344 ERROR(ep
, ebuf
, gettext(
2345 "Can only specify single"
2346 " hard allocation limit.\n"));
2349 hard
->sadb_lifetime_allocations
=
2350 (uint32_t)parsenum(*argv
, B_TRUE
, ebuf
);
2352 case TOK_HARD_BYTES
:
2353 if (hard
->sadb_lifetime_bytes
!= 0) {
2354 ERROR(ep
, ebuf
, gettext(
2356 "single hard byte limit.\n"));
2359 hard
->sadb_lifetime_bytes
= parsenum(*argv
,
2362 case TOK_HARD_ADDTIME
:
2363 if (hard
->sadb_lifetime_addtime
!= 0) {
2364 ERROR(ep
, ebuf
, gettext(
2366 "single past-add lifetime.\n"));
2369 hard
->sadb_lifetime_addtime
= parsenum(*argv
,
2372 case TOK_HARD_USETIME
:
2373 if (hard
->sadb_lifetime_usetime
!= 0) {
2374 ERROR(ep
, ebuf
, gettext(
2376 "single past-use lifetime.\n"));
2379 hard
->sadb_lifetime_usetime
= parsenum(*argv
,
2385 case TOK_SOFT_ALLOC
:
2386 case TOK_SOFT_BYTES
:
2387 case TOK_SOFT_ADDTIME
:
2388 case TOK_SOFT_USETIME
:
2390 soft
= malloc(sizeof (*soft
));
2392 Bail("malloc(soft_lifetime)");
2393 bzero(soft
, sizeof (*soft
));
2394 soft
->sadb_lifetime_exttype
=
2395 SADB_EXT_LIFETIME_SOFT
;
2396 soft
->sadb_lifetime_len
=
2397 SADB_8TO64(sizeof (*soft
));
2398 totallen
+= sizeof (*soft
);
2401 case TOK_SOFT_ALLOC
:
2402 if (soft
->sadb_lifetime_allocations
!= 0) {
2403 ERROR(ep
, ebuf
, gettext(
2404 "Can only specify single"
2405 " soft allocation limit.\n"));
2408 soft
->sadb_lifetime_allocations
=
2409 (uint32_t)parsenum(*argv
, B_TRUE
, ebuf
);
2411 case TOK_SOFT_BYTES
:
2412 if (soft
->sadb_lifetime_bytes
!= 0) {
2413 ERROR(ep
, ebuf
, gettext(
2414 "Can only specify single"
2415 " soft byte limit.\n"));
2418 soft
->sadb_lifetime_bytes
= parsenum(*argv
,
2421 case TOK_SOFT_ADDTIME
:
2422 if (soft
->sadb_lifetime_addtime
!= 0) {
2423 ERROR(ep
, ebuf
, gettext(
2424 "Can only specify single"
2425 " past-add lifetime.\n"));
2428 soft
->sadb_lifetime_addtime
= parsenum(*argv
,
2431 case TOK_SOFT_USETIME
:
2432 if (soft
->sadb_lifetime_usetime
!= 0) {
2433 ERROR(ep
, ebuf
, gettext(
2434 "Can only specify single"
2435 " past-use lifetime.\n"));
2438 soft
->sadb_lifetime_usetime
= parsenum(*argv
,
2444 case TOK_FLAG_INBOUND
:
2445 assoc
->sadb_sa_flags
|= SADB_X_SAFLAGS_INBOUND
;
2447 case TOK_FLAG_OUTBOUND
:
2448 assoc
->sadb_sa_flags
|= SADB_X_SAFLAGS_OUTBOUND
;
2450 case TOK_REPLAY_VALUE
:
2451 if (replay_ctr
!= NULL
) {
2452 ERROR(ep
, ebuf
, gettext(
2453 "Can only specify single "
2457 replay_ctr
= calloc(1, sizeof (*replay_ctr
));
2458 if (replay_ctr
== NULL
) {
2459 Bail("malloc(replay value)");
2462 * We currently do not support a 64-bit
2463 * replay value. RFC 4301 will require one,
2464 * however, and we have a field in place when
2467 replay_ctr
->sadb_x_rc_exttype
= SADB_X_EXT_REPLAY_VALUE
;
2468 replay_ctr
->sadb_x_rc_len
=
2469 SADB_8TO64(sizeof (*replay_ctr
));
2470 totallen
+= sizeof (*replay_ctr
);
2471 replay_ctr
->sadb_x_rc_replay32
= (uint32_t)parsenum(
2472 *argv
, B_TRUE
, ebuf
);
2475 case TOK_IDLE_ADDTIME
:
2476 case TOK_IDLE_USETIME
:
2478 idle
= calloc(1, sizeof (*idle
));
2480 Bail("malloc idle lifetime");
2482 idle
->sadb_lifetime_exttype
=
2483 SADB_X_EXT_LIFETIME_IDLE
;
2484 idle
->sadb_lifetime_len
=
2485 SADB_8TO64(sizeof (*idle
));
2486 totallen
+= sizeof (*idle
);
2489 case TOK_IDLE_ADDTIME
:
2490 idle
->sadb_lifetime_addtime
=
2491 (uint32_t)parsenum(*argv
,
2494 case TOK_IDLE_USETIME
:
2495 idle
->sadb_lifetime_usetime
=
2496 (uint32_t)parsenum(*argv
,
2503 if (encrypt
!= NULL
)
2504 ERROR(ep
, ebuf
, gettext(
2505 "Reserved bits need to be "
2506 "specified before key.\n"));
2507 reserved_bits
= (uint_t
)parsenum(*argv
,
2512 ERROR1(ep
, ebuf
, gettext(
2513 "Don't use extension %s for add/update.\n"),
2517 } while (token
!= TOK_EOF
);
2519 handle_errors(ep
, ebuf
, B_TRUE
, B_FALSE
);
2521 #define PORT_ONLY_ALLOCATE(af, socktype, exttype, extvar, port) { \
2522 alloclen = sizeof (sadb_address_t) + roundup(sizeof (socktype), 8); \
2523 (extvar) = calloc(1, alloclen); \
2524 if ((extvar) == NULL) { \
2525 Bail("malloc(implicit port)"); \
2527 totallen += alloclen; \
2528 (extvar)->sadb_address_len = SADB_8TO64(alloclen); \
2529 (extvar)->sadb_address_exttype = (exttype); \
2530 /* sin/sin6 has equivalent offsets for ports! */ \
2531 sin6 = (struct sockaddr_in6 *)((extvar) + 1); \
2532 sin6->sin6_family = (af); \
2533 sin6->sin6_port = (port); \
2537 * If we specify inner ports or NAT ports w/o addresses, we still need
2538 * to allocate. Also, if we have one inner address, we need the
2539 * other, even if we don't specify anything.
2542 if (natt_lport
!= 0 && natt_local
== NULL
) {
2543 PORT_ONLY_ALLOCATE(AF_INET
, struct sockaddr_in
,
2544 SADB_X_EXT_ADDRESS_NATT_LOC
, natt_local
,
2548 if (natt_rport
!= 0 && natt_remote
== NULL
) {
2549 PORT_ONLY_ALLOCATE(AF_INET
, struct sockaddr_in
,
2550 SADB_X_EXT_ADDRESS_NATT_REM
, natt_remote
,
2554 if (natt_lport
!= 0 || natt_rport
!= 0) {
2555 ERROR(ep
, ebuf
, gettext("Must specify 'encap udp' "
2556 "with any NAT-T port.\n"));
2557 } else if (natt_local
!= NULL
|| natt_remote
!= NULL
) {
2558 ERROR(ep
, ebuf
, gettext("Must specify 'encap udp' "
2559 "with any NAT-T address.\n"));
2563 if (alloc_inner
&& idst
== NULL
) {
2564 PORT_ONLY_ALLOCATE(AF_INET6
, struct sockaddr_in6
,
2565 SADB_X_EXT_ADDRESS_INNER_DST
, idst
, 0);
2568 if (alloc_inner
&& isrc
== NULL
) {
2569 PORT_ONLY_ALLOCATE(AF_INET6
, struct sockaddr_in6
,
2570 SADB_X_EXT_ADDRESS_INNER_SRC
, isrc
, 0);
2572 #undef PORT_ONLY_ALLOCATE
2575 * Okay, so now I have all of the potential extensions!
2576 * Allocate a single contiguous buffer. Keep in mind that it'll
2577 * be enough because the key itself will be yanked.
2580 if (src
== NULL
&& dst
!= NULL
) {
2582 * Set explicit unspecified source address.
2584 size_t lenbytes
= SADB_64TO8(dst
->sadb_address_len
);
2586 unspec_src
= B_TRUE
;
2587 totallen
+= lenbytes
;
2588 src
= malloc(lenbytes
);
2590 Bail("malloc(implicit src)");
2591 /* Confusing, but we're copying from DST to SRC. :) */
2592 bcopy(dst
, src
, lenbytes
);
2593 src
->sadb_address_exttype
= SADB_EXT_ADDRESS_SRC
;
2594 sin6
= (struct sockaddr_in6
*)(src
+ 1);
2595 bzero(sin6
, sizeof (*sin6
));
2596 sin6
->sin6_family
= AF_INET6
;
2599 msg
.sadb_msg_len
= SADB_8TO64(totallen
);
2601 buffer
= malloc(totallen
);
2603 bcopy(&msg
, nexthdr
, sizeof (msg
));
2604 nexthdr
+= SADB_8TO64(sizeof (msg
));
2605 if (assoc
!= NULL
) {
2606 if (assoc
->sadb_sa_spi
== 0) {
2607 ERROR1(ep
, ebuf
, gettext(
2608 "The SPI value is missing for "
2609 "the association you wish to %s.\n"), thiscmd
);
2611 if (assoc
->sadb_sa_auth
== 0 && assoc
->sadb_sa_encrypt
== 0 &&
2614 FATAL(ep
, ebuf
, gettext(
2615 "Select at least one algorithm "
2616 "for this add.\n"));
2619 /* Hack to let user specify NULL ESP implicitly. */
2620 if (msg
.sadb_msg_satype
== SADB_SATYPE_ESP
&&
2621 assoc
->sadb_sa_encrypt
== 0)
2622 assoc
->sadb_sa_encrypt
= SADB_EALG_NULL
;
2624 /* 0 is an actual value. Print a warning if it was entered. */
2625 if (assoc
->sadb_sa_state
== 0) {
2627 ERROR(ep
, ebuf
, gettext(
2628 "WARNING: Cannot set LARVAL SA state.\n"));
2630 assoc
->sadb_sa_state
= SADB_SASTATE_MATURE
;
2634 if (natt_remote
!= NULL
)
2635 assoc
->sadb_sa_flags
|= SADB_X_SAFLAGS_NATT_REM
;
2636 if (natt_local
!= NULL
)
2637 assoc
->sadb_sa_flags
|= SADB_X_SAFLAGS_NATT_LOC
;
2642 * For now, assume RFC 3884's dream of transport-mode
2643 * SAs with inner IP address selectors will not
2646 assoc
->sadb_sa_flags
|= SADB_X_SAFLAGS_TUNNEL
;
2647 if (proto
!= 0 && proto
!= IPPROTO_ENCAP
&&
2648 proto
!= IPPROTO_IPV6
) {
2649 ERROR1(ep
, ebuf
, gettext(
2650 "WARNING: Protocol type %d not "
2651 "for use with Tunnel-Mode SA.\n"), proto
);
2652 /* Continue and let PF_KEY scream... */
2656 bcopy(assoc
, nexthdr
, SADB_64TO8(assoc
->sadb_sa_len
));
2657 nexthdr
+= assoc
->sadb_sa_len
;
2658 /* Save the SPI for the case of an error. */
2659 spi
= assoc
->sadb_sa_spi
;
2663 ERROR1(ep
, ebuf
, gettext(
2664 "Need to define SPI for %s.\n"), thiscmd
);
2665 ERROR1(ep
, ebuf
, gettext(
2666 "Need SA parameters for %s.\n"), thiscmd
);
2669 if (sadb_pair
!= NULL
) {
2670 if (sadb_pair
->sadb_x_pair_spi
== 0) {
2671 ERROR1(ep
, ebuf
, gettext(
2672 "The SPI value is missing for the "
2673 "association you wish to %s.\n"), thiscmd
);
2675 bcopy(sadb_pair
, nexthdr
,
2676 SADB_64TO8(sadb_pair
->sadb_x_pair_len
));
2677 nexthdr
+= sadb_pair
->sadb_x_pair_len
;
2682 bcopy(hard
, nexthdr
, SADB_64TO8(hard
->sadb_lifetime_len
));
2683 nexthdr
+= hard
->sadb_lifetime_len
;
2688 bcopy(soft
, nexthdr
, SADB_64TO8(soft
->sadb_lifetime_len
));
2689 nexthdr
+= soft
->sadb_lifetime_len
;
2694 bcopy(idle
, nexthdr
, SADB_64TO8(idle
->sadb_lifetime_len
));
2695 nexthdr
+= idle
->sadb_lifetime_len
;
2699 if (encrypt
== NULL
&& auth
== NULL
&& cmd
== CMD_ADD
) {
2700 ERROR(ep
, ebuf
, gettext(
2701 "Must have at least one key for an add.\n"));
2704 if (encrypt
!= NULL
) {
2705 bcopy(encrypt
, nexthdr
, SADB_64TO8(encrypt
->sadb_key_len
));
2706 nexthdr
+= encrypt
->sadb_key_len
;
2707 bzero(encrypt
, SADB_64TO8(encrypt
->sadb_key_len
));
2712 bcopy(auth
, nexthdr
, SADB_64TO8(auth
->sadb_key_len
));
2713 nexthdr
+= auth
->sadb_key_len
;
2714 bzero(auth
, SADB_64TO8(auth
->sadb_key_len
));
2718 if (srcid
!= NULL
) {
2719 bcopy(srcid
, nexthdr
, SADB_64TO8(srcid
->sadb_ident_len
));
2720 nexthdr
+= srcid
->sadb_ident_len
;
2724 if (dstid
!= NULL
) {
2725 bcopy(dstid
, nexthdr
, SADB_64TO8(dstid
->sadb_ident_len
));
2726 nexthdr
+= dstid
->sadb_ident_len
;
2731 bcopy(dst
, nexthdr
, SADB_64TO8(dst
->sadb_address_len
));
2733 dst
= (struct sadb_address
*)nexthdr
;
2734 dst
->sadb_address_proto
= proto
;
2735 ((struct sockaddr_in6
*)(dst
+ 1))->sin6_port
= htons(dstport
);
2736 nexthdr
+= dst
->sadb_address_len
;
2738 FATAL1(ep
, ebuf
, gettext(
2739 "Need destination address for %s.\n"), thiscmd
);
2743 if (natt_remote
== NULL
&& natt_local
== NULL
) {
2744 ERROR(ep
, ebuf
, gettext(
2745 "Must specify NAT-T remote or local address "
2746 "for UDP encapsulation.\n"));
2749 if (natt_remote
!= NULL
) {
2750 bcopy(natt_remote
, nexthdr
,
2751 SADB_64TO8(natt_remote
->sadb_address_len
));
2753 natt_remote
= (struct sadb_address
*)nexthdr
;
2754 nexthdr
+= natt_remote
->sadb_address_len
;
2755 ((struct sockaddr_in6
*)(natt_remote
+ 1))->sin6_port
=
2759 if (natt_local
!= NULL
) {
2760 bcopy(natt_local
, nexthdr
,
2761 SADB_64TO8(natt_local
->sadb_address_len
));
2763 natt_local
= (struct sadb_address
*)nexthdr
;
2764 nexthdr
+= natt_local
->sadb_address_len
;
2765 ((struct sockaddr_in6
*)(natt_local
+ 1))->sin6_port
=
2770 handle_errors(ep
, ebuf
, B_TRUE
, B_FALSE
);
2773 * PF_KEY requires a source address extension, even if the source
2774 * address itself is unspecified. (See "Set explicit unspecified..."
2775 * code fragment above. Destination reality check was above.)
2777 bcopy(src
, nexthdr
, SADB_64TO8(src
->sadb_address_len
));
2779 src
= (struct sadb_address
*)nexthdr
;
2780 src
->sadb_address_proto
= proto
;
2781 ((struct sockaddr_in6
*)(src
+ 1))->sin6_port
= htons(srcport
);
2782 nexthdr
+= src
->sadb_address_len
;
2785 bcopy(isrc
, nexthdr
, SADB_64TO8(isrc
->sadb_address_len
));
2787 isrc
= (struct sadb_address
*)nexthdr
;
2788 isrc
->sadb_address_proto
= iproto
;
2789 ((struct sockaddr_in6
*)(isrc
+ 1))->sin6_port
=
2791 nexthdr
+= isrc
->sadb_address_len
;
2795 bcopy(idst
, nexthdr
, SADB_64TO8(idst
->sadb_address_len
));
2797 idst
= (struct sadb_address
*)nexthdr
;
2798 idst
->sadb_address_proto
= iproto
;
2799 ((struct sockaddr_in6
*)(idst
+ 1))->sin6_port
=
2801 nexthdr
+= idst
->sadb_address_len
;
2804 if (replay_ctr
!= NULL
) {
2805 bcopy(replay_ctr
, nexthdr
,
2806 SADB_64TO8(replay_ctr
->sadb_x_rc_len
));
2807 nexthdr
+= replay_ctr
->sadb_x_rc_len
;
2813 * Assume the checked cmd would have worked if it was actually
2814 * used. doaddresses() will increment lines_added if it
2819 doaddresses(sadb_msg_type
, satype
,
2820 cmd
, srchp
, dsthp
, src
, dst
, unspec_src
, buffer
, totallen
,
2824 if (isrchp
!= NULL
&& isrchp
!= &dummy
.he
)
2825 freehostent(isrchp
);
2826 if (idsthp
!= NULL
&& idsthp
!= &dummy
.he
)
2827 freehostent(idsthp
);
2828 if (srchp
!= NULL
&& srchp
!= &dummy
.he
)
2830 if (dsthp
!= NULL
&& dsthp
!= &dummy
.he
)
2832 if (natt_lhp
!= NULL
&& natt_lhp
!= &dummy
.he
)
2833 freehostent(natt_lhp
);
2834 if (natt_rhp
!= NULL
&& natt_rhp
!= &dummy
.he
)
2835 freehostent(natt_rhp
);
2841 * DELETE and GET are similar, in that they only need the extensions
2842 * required to _find_ an SA, and then either delete it or obtain its
2846 dodelget(int cmd
, int satype
, char *argv
[], char *ebuf
)
2848 struct sadb_msg
*msg
= (struct sadb_msg
*)get_buffer
;
2850 struct sadb_sa
*assoc
= NULL
;
2851 struct sadb_address
*src
= NULL
, *dst
= NULL
;
2852 int next
, token
, sa_len
;
2855 uint8_t sadb_msg_type
;
2856 struct hostent
*srchp
= NULL
, *dsthp
= NULL
;
2857 struct sockaddr_in6
*sin6
;
2858 boolean_t unspec_src
= B_TRUE
;
2859 uint16_t srcport
= 0, dstport
= 0;
2862 uint32_t sa_flags
= 0;
2864 /* Set the first extension header to right past the base message. */
2865 nextext
= (uint64_t *)(msg
+ 1);
2866 bzero(nextext
, sizeof (get_buffer
) - sizeof (*msg
));
2871 sadb_msg_type
= SADB_GET
;
2875 sadb_msg_type
= SADB_DELETE
;
2877 case CMD_DELETE_PAIR
:
2878 thiscmd
= "delete-pair";
2879 sadb_msg_type
= SADB_X_DELPAIR
;
2883 msg_init(msg
, sadb_msg_type
, (uint8_t)satype
);
2885 #define ALLOC_ADDR_EXT(ext, exttype) \
2886 (ext) = (struct sadb_address *)nextext; \
2887 nextext = (uint64_t *)((ext) + 1); \
2888 nextext += SADB_8TO64(roundup(sa_len, 8)); \
2889 (ext)->sadb_address_exttype = exttype; \
2890 (ext)->sadb_address_len = nextext - ((uint64_t *)ext);
2892 /* Assume last element in argv is set to NULL. */
2894 token
= parseextval(*argv
, &next
);
2898 /* Do nothing, I'm done. */
2901 ERROR1(ep
, ebuf
, gettext(
2902 "Unknown extension field \"%s\"\n"), *(argv
- 1));
2905 if (assoc
!= NULL
) {
2906 ERROR(ep
, ebuf
, gettext(
2907 "Can only specify single SPI value.\n"));
2910 assoc
= (struct sadb_sa
*)nextext
;
2911 nextext
= (uint64_t *)(assoc
+ 1);
2912 assoc
->sadb_sa_len
= SADB_8TO64(sizeof (*assoc
));
2913 assoc
->sadb_sa_exttype
= SADB_EXT_SA
;
2914 assoc
->sadb_sa_spi
= htonl((uint32_t)parsenum(*argv
,
2916 spi
= assoc
->sadb_sa_spi
;
2921 ERROR(ep
, ebuf
, gettext(
2922 "Can only specify single source port.\n"));
2925 srcport
= parsenum(*argv
, B_TRUE
, ebuf
);
2930 ERROR(ep
, ebuf
, gettext(
2932 "specify single destination port.\n"));
2935 dstport
= parsenum(*argv
, B_TRUE
, ebuf
);
2940 ERROR(ep
, ebuf
, gettext(
2941 "Can only specify single protocol.\n"));
2944 proto
= parsenum(*argv
, B_TRUE
, ebuf
);
2950 ERROR(ep
, ebuf
, gettext(
2951 "Can only specify single source addr.\n"));
2954 sa_len
= parseaddr(*argv
, &srchp
,
2955 (token
== TOK_SRCADDR6
), ebuf
);
2956 if (srchp
== NULL
) {
2957 ERROR1(ep
, ebuf
, gettext(
2958 "Unknown source address \"%s\"\n"), *argv
);
2963 unspec_src
= B_FALSE
;
2965 ALLOC_ADDR_EXT(src
, SADB_EXT_ADDRESS_SRC
);
2967 if (srchp
== &dummy
.he
) {
2969 * Single address with -n flag.
2971 sin6
= (struct sockaddr_in6
*)(src
+ 1);
2972 bzero(sin6
, sizeof (*sin6
));
2973 sin6
->sin6_family
= AF_INET6
;
2974 bcopy(srchp
->h_addr_list
[0], &sin6
->sin6_addr
,
2975 sizeof (struct in6_addr
));
2977 /* The rest is pre-bzeroed for us. */
2982 ERROR(ep
, ebuf
, gettext(
2983 "Can only specify single destination "
2987 sa_len
= parseaddr(*argv
, &dsthp
,
2988 (token
== TOK_SRCADDR6
), ebuf
);
2989 if (dsthp
== NULL
) {
2990 ERROR1(ep
, ebuf
, gettext(
2991 "Unknown destination address \"%s\"\n"),
2997 ALLOC_ADDR_EXT(dst
, SADB_EXT_ADDRESS_DST
);
2999 if (dsthp
== &dummy
.he
) {
3001 * Single address with -n flag.
3003 sin6
= (struct sockaddr_in6
*)(dst
+ 1);
3004 bzero(sin6
, sizeof (*sin6
));
3005 sin6
->sin6_family
= AF_INET6
;
3006 bcopy(dsthp
->h_addr_list
[0], &sin6
->sin6_addr
,
3007 sizeof (struct in6_addr
));
3009 /* The rest is pre-bzeroed for us. */
3011 case TOK_FLAG_INBOUND
:
3012 sa_flags
|= SADB_X_SAFLAGS_INBOUND
;
3014 case TOK_FLAG_OUTBOUND
:
3015 sa_flags
|= SADB_X_SAFLAGS_OUTBOUND
;
3018 ERROR2(ep
, ebuf
, gettext(
3019 "Don't use extension %s for '%s' command.\n"),
3020 *(argv
- 1), thiscmd
);
3023 } while (token
!= TOK_EOF
);
3025 handle_errors(ep
, ebuf
, B_TRUE
, B_FALSE
);
3027 if (assoc
== NULL
) {
3028 FATAL1(ep
, ebuf
, gettext(
3029 "Need SA parameters for %s.\n"), thiscmd
);
3032 /* We can set the flags now with valid assoc in hand. */
3033 assoc
->sadb_sa_flags
|= sa_flags
;
3035 if ((srcport
!= 0) && (src
== NULL
)) {
3036 ALLOC_ADDR_EXT(src
, SADB_EXT_ADDRESS_SRC
);
3037 sin6
= (struct sockaddr_in6
*)(src
+ 1);
3038 src
->sadb_address_proto
= proto
;
3039 bzero(sin6
, sizeof (*sin6
));
3040 sin6
->sin6_family
= AF_INET6
;
3041 sin6
->sin6_port
= htons(srcport
);
3044 if ((dstport
!= 0) && (dst
== NULL
)) {
3045 ALLOC_ADDR_EXT(dst
, SADB_EXT_ADDRESS_DST
);
3046 sin6
= (struct sockaddr_in6
*)(dst
+ 1);
3047 src
->sadb_address_proto
= proto
;
3048 bzero(sin6
, sizeof (*sin6
));
3049 sin6
->sin6_family
= AF_INET6
;
3050 sin6
->sin6_port
= htons(dstport
);
3053 /* So I have enough of the message to send it down! */
3054 msg
->sadb_msg_len
= nextext
- get_buffer
;
3058 * Assume the checked cmd would have worked if it was actually
3059 * used. doaddresses() will increment lines_added if it
3064 doaddresses(sadb_msg_type
, satype
,
3065 cmd
, srchp
, dsthp
, src
, dst
, unspec_src
, get_buffer
,
3066 sizeof (get_buffer
), spi
, NULL
);
3069 if (srchp
!= NULL
&& srchp
!= &dummy
.he
)
3071 if (dsthp
!= NULL
&& dsthp
!= &dummy
.he
)
3076 * "ipseckey monitor" should exit very gracefully if ^C is tapped provided
3077 * it is not running in interactive mode.
3080 monitor_catch(int signal
)
3083 errx(signal
, gettext("Bailing on signal %d."), signal
);
3087 * Loop forever, listening on PF_KEY messages.
3090 domonitor(boolean_t passive
)
3092 struct sadb_msg
*samsg
;
3093 struct sigaction newsig
, oldsig
;
3097 newsig
.sa_handler
= monitor_catch
;
3098 newsig
.sa_flags
= 0;
3099 (void) sigemptyset(&newsig
.sa_mask
);
3100 (void) sigaddset(&newsig
.sa_mask
, SIGINT
);
3101 (void) sigaction(SIGINT
, &newsig
, &oldsig
);
3103 samsg
= (struct sadb_msg
*)get_buffer
;
3105 (void) printf(gettext("Actively"));
3106 msg_init(samsg
, SADB_X_PROMISC
, 1); /* Turn ON promisc. */
3107 rc
= key_write(keysock
, samsg
, sizeof (*samsg
));
3109 Bail("write (SADB_X_PROMISC)");
3111 (void) printf(gettext("Passively"));
3113 (void) printf(gettext(" monitoring the PF_KEY socket.\n"));
3117 * I assume that read() is non-blocking, and will never
3120 rc
= read(keysock
, samsg
, sizeof (get_buffer
));
3122 if (errno
== EINTR
&& interactive
)
3125 Bail("read (in domonitor)");
3127 (void) printf(gettext("Read %d bytes.\n"), rc
);
3129 * Q: Should I use the same method of printing as GET does?
3132 print_samsg(stdout
, get_buffer
, B_TRUE
, vflag
, nflag
);
3133 (void) putchar('\n');
3138 /* restore SIGINT behavior */
3139 (void) sigaction(SIGINT
, &oldsig
, NULL
);
3143 * Either mask or unmask all relevant signals.
3146 mask_signals(boolean_t unmask
)
3149 static sigset_t oset
;
3152 (void) sigprocmask(SIG_SETMASK
, &oset
, NULL
);
3154 (void) sigfillset(&set
);
3155 (void) sigprocmask(SIG_SETMASK
, &set
, &oset
);
3160 * Assorted functions to print help text.
3162 #define puts_tr(s) (void) puts(gettext(s))
3169 puts_tr("\nSA attributes:");
3171 for (i
= 0; tokens
[i
].string
!= NULL
; i
++) {
3173 (void) printf("\n");
3174 (void) printf(" %-15.15s", tokens
[i
].string
);
3176 (void) printf("\n");
3180 dohelpcmd(char *cmds
)
3184 if (strcmp(cmds
, "attr") == 0) {
3189 cmd
= parsecmd(cmds
);
3192 puts_tr("update - Update an existing SA");
3194 case CMD_UPDATE_PAIR
:
3195 puts_tr("update-pair - Update an existing pair of SA's");
3198 puts_tr("add - Add a new security association (SA)");
3201 puts_tr("delete - Delete an SA");
3203 case CMD_DELETE_PAIR
:
3204 puts_tr("delete-pair - Delete a pair of SA's");
3207 puts_tr("get - Display an SA");
3210 puts_tr("flush - Delete all SAs");
3212 puts_tr("Optional arguments:");
3213 puts_tr("all delete all SAs");
3214 puts_tr("esp delete just ESP SAs");
3215 puts_tr("ah delete just AH SAs");
3216 puts_tr("<number> delete just SAs with type given by number");
3220 puts_tr("dump - Display all SAs");
3222 puts_tr("Optional arguments:");
3223 puts_tr("all display all SAs");
3224 puts_tr("esp display just ESP SAs");
3225 puts_tr("ah display just AH SAs");
3226 puts_tr("<number> display just SAs with type "
3231 puts_tr("monitor - Monitor all PF_KEY reply messages.");
3235 "pmonitor, passive_monitor - Monitor PF_KEY messages that");
3237 " reply to all PF_KEY sockets.");
3241 puts_tr("quit, exit - Exit the program");
3244 puts_tr("save - Saves all SAs to a file");
3247 puts_tr("help - Display list of commands");
3248 puts_tr("help <cmd> - Display help for command");
3249 puts_tr("help attr - Display possible SA attributes");
3252 (void) printf(gettext("%s: Unknown command\n"), cmds
);
3265 puts_tr("Commands");
3266 puts_tr("--------");
3267 puts_tr("?, help - Display this list");
3268 puts_tr("help <cmd> - Display help for command");
3269 puts_tr("help attr - Display possible SA attributes");
3270 puts_tr("quit, exit - Exit the program");
3271 puts_tr("monitor - Monitor all PF_KEY reply messages.");
3272 puts_tr("pmonitor, passive_monitor - Monitor PF_KEY messages that");
3273 puts_tr(" reply to all PF_KEY sockets.");
3275 puts_tr("The following commands are of the form:");
3276 puts_tr(" <command> {SA type} {attribute value}*");
3278 puts_tr("add (interactive only) - Add a new security association (SA)");
3279 puts_tr("update (interactive only) - Update an existing SA");
3280 puts_tr("update-pair (interactive only) - Update an existing SA pair");
3281 puts_tr("delete - Delete an SA");
3282 puts_tr("delete-pair - Delete an SA pair");
3283 puts_tr("get - Display an SA");
3284 puts_tr("flush - Delete all SAs");
3285 puts_tr("dump - Display all SAs");
3286 puts_tr("save - Saves all SAs to a file");
3290 * "Parse" a command line from argv.
3293 parseit(int argc
, char *argv
[], char *ebuf
, boolean_t read_cmdfile
)
3300 cmd
= parsecmd(*argv
++);
3303 * Some commands loop forever and should only be run from the command
3304 * line, they should never be run from a command file as this may
3305 * be used at boot time.
3310 ERROR(ep
, ebuf
, gettext("Help not appropriate in "
3317 ERROR(ep
, ebuf
, gettext("Monitor not appropriate in "
3322 * Return from the function in interactive mode to
3323 * avoid error message in the next switch statement.
3324 * Also print newline to prevent prompt clobbering.
3325 * The same is done for CMD_PMONITOR.
3328 (void) printf("\n");
3335 ERROR(ep
, ebuf
, gettext("Monitor not appropriate in "
3340 (void) printf("\n");
3349 handle_errors(ep
, ebuf
, B_FALSE
, B_FALSE
);
3351 satype
= parsesatype(*argv
, ebuf
);
3353 if (satype
!= SADB_SATYPE_UNSPEC
) {
3357 * You must specify either "all" or a specific SA type
3358 * for the "save" command.
3360 if (cmd
== CMD_SAVE
)
3361 if (*argv
== NULL
) {
3362 FATAL(ep
, ebuf
, gettext(
3363 "Must specify a specific "
3364 "SA type for save.\n"));
3373 ERROR(ep
, ebuf
, gettext("Too many arguments for "
3375 handle_errors(ep
, ebuf
,
3376 interactive
? B_TRUE
: B_FALSE
, B_FALSE
);
3381 * If this was called because of an entry in a cmd file
3382 * then this action needs to be counted to prevent
3383 * do_interactive() treating this as an error.
3389 case CMD_UPDATE_PAIR
:
3391 * NOTE: Shouldn't allow ADDs or UPDATEs with keying material
3392 * from the command line.
3396 "can't do ADD or UPDATE from the command line.\n"));
3398 if (satype
== SADB_SATYPE_UNSPEC
) {
3399 FATAL(ep
, ebuf
, gettext(
3400 "Must specify a specific SA type."));
3403 /* Parse for extensions, including keying material. */
3404 doaddup(cmd
, satype
, argv
, ebuf
);
3407 case CMD_DELETE_PAIR
:
3409 if (satype
== SADB_SATYPE_UNSPEC
) {
3410 FATAL(ep
, ebuf
, gettext(
3411 "Must specify a single SA type."));
3414 /* Parse for bare minimum to locate an SA. */
3415 dodelget(cmd
, satype
, argv
, ebuf
);
3419 ERROR(ep
, ebuf
, gettext("Dump not appropriate in "
3423 ERROR(ep
, ebuf
, gettext("Too many arguments "
3424 "for dump command"));
3425 handle_errors(ep
, ebuf
,
3426 interactive
? B_TRUE
: B_FALSE
, B_FALSE
);
3428 dodump(satype
, NULL
);
3433 ERROR(ep
, ebuf
, gettext("Save not appropriate in "
3436 mask_signals(B_FALSE
); /* Mask signals */
3437 dodump(satype
, opensavefile(argv
[0]));
3438 mask_signals(B_TRUE
); /* Unmask signals */
3442 warnx(gettext("Unknown command (%s).\n"),
3443 *(argv
- ((satype
== SADB_SATYPE_UNSPEC
) ? 1 : 2)));
3446 handle_errors(ep
, ebuf
, B_FALSE
, B_FALSE
);
3450 main(int argc
, char *argv
[])
3453 FILE *infile
= stdin
, *savefile
;
3454 boolean_t dosave
= B_FALSE
, readfile
= B_FALSE
;
3455 char *configfile
= NULL
;
3461 (void) setlocale(LC_ALL
, "");
3462 #if !defined(TEXT_DOMAIN)
3463 #define TEXT_DOMAIN "SYS_TEST"
3465 (void) textdomain(TEXT_DOMAIN
);
3468 * Check to see if the command is being run from smf(5).
3470 my_fmri
= getenv("SMF_FMRI");
3472 openlog("ipseckey", LOG_CONS
, LOG_AUTH
);
3473 if (getuid() != 0) {
3474 errx(1, "Insufficient privileges to run ipseckey.");
3477 /* umask me to paranoid, I only want to create files read-only */
3478 (void) umask((mode_t
)00377);
3480 while ((ch
= getopt(argc
, argv
, "pnvf:s:c:")) != EOF
)
3499 * Use stat() to check and see if the user inadvertently
3500 * passed in a bad pathname, or the name of a directory.
3501 * We should also check to see if the filename is a
3502 * pipe. We use stat() here because fopen() will block
3503 * unless the other end of the pipe is open. This would
3504 * be undesirable, especially if this is called at boot
3505 * time. If we ever need to support reading from a pipe
3506 * or special file, this should be revisited.
3508 if (stat(optarg
, &sbuf
) == -1) {
3509 EXIT_BADCONFIG2("Invalid pathname: %s\n",
3512 if (!(sbuf
.st_mode
& S_IFREG
)) {
3513 EXIT_BADCONFIG2("%s - Not a regular file\n",
3516 infile
= fopen(optarg
, "r");
3517 if (infile
== NULL
) {
3518 EXIT_BADCONFIG2("Unable to open configuration "
3519 "file: %s\n", optarg
);
3522 * The input file contains keying information, because
3523 * this is sensative, we should only accept data from
3524 * this file if the file is root owned and only readable
3525 * by privileged users. If the command is being run by
3526 * the administrator, issue a warning, if this is run by
3527 * smf(5) (IE: boot time) and the permissions are too
3528 * open, we will fail, the SMF service will end up in
3529 * maintenace mode. The check is made with fstat() to
3530 * eliminate any possible TOT to TOU window.
3532 if (fstat(fileno(infile
), &sbuf
) == -1) {
3533 (void) fclose(infile
);
3534 EXIT_BADCONFIG2("Unable to stat configuration "
3535 "file: %s\n", optarg
);
3537 if (INSECURE_PERMS(sbuf
)) {
3538 if (my_fmri
!= NULL
) {
3539 (void) fclose(infile
);
3540 EXIT_BADCONFIG2("Config file "
3541 "%s has insecure permissions.",
3544 (void) fprintf(stderr
, gettext(
3545 "Config file %s has insecure "
3546 "permissions, will be rejected in "
3547 "permanent config.\n"), optarg
);
3550 configfile
= strdup(optarg
);
3557 savefile
= opensavefile(optarg
);
3568 keysock
= socket(PF_KEY
, SOCK_RAW
, PF_KEY_V2
);
3570 if (keysock
== -1) {
3571 if (errno
== EPERM
) {
3572 EXIT_BADPERM("Insufficient privileges to open "
3573 "PF_KEY socket.\n");
3575 /* some other reason */
3576 EXIT_FATAL("Opening PF_KEY socket");
3581 mask_signals(B_FALSE
); /* Mask signals */
3582 dodump(SADB_SATYPE_UNSPEC
, savefile
);
3583 mask_signals(B_TRUE
); /* Unmask signals */
3588 * When run from smf(5) flush any existing SA's first
3589 * otherwise you will end up in maintenance mode.
3591 if ((my_fmri
!= NULL
) && readfile
) {
3592 (void) fprintf(stdout
, gettext(
3593 "Flushing existing SA's before adding new SA's\n"));
3594 (void) fflush(stdout
);
3595 doflush(SADB_SATYPE_UNSPEC
);
3597 if (infile
!= stdin
|| argc
== 0) {
3598 /* Go into interactive mode here. */
3599 do_interactive(infile
, configfile
, "ipseckey> ", my_fmri
,
3602 parseit(argc
, argv
, NULL
, B_FALSE
);