diff options
Diffstat (limited to 'usr.sbin/setkey')
-rw-r--r-- | usr.sbin/setkey/Makefile | 2 | ||||
-rw-r--r-- | usr.sbin/setkey/parse.y | 1382 | ||||
-rw-r--r-- | usr.sbin/setkey/sample.cf | 36 | ||||
-rw-r--r-- | usr.sbin/setkey/setkey.8 | 320 | ||||
-rw-r--r-- | usr.sbin/setkey/setkey.c | 131 | ||||
-rw-r--r-- | usr.sbin/setkey/token.l | 269 |
6 files changed, 1220 insertions, 920 deletions
diff --git a/usr.sbin/setkey/Makefile b/usr.sbin/setkey/Makefile index 782b478..91977e0 100644 --- a/usr.sbin/setkey/Makefile +++ b/usr.sbin/setkey/Makefile @@ -39,7 +39,7 @@ LDADD= -ll -ly CLEANFILES= y.tab.c y.tab.h key_test.o keytest -# libpfkey. +# libpfkey # ipsec_strerror.c is for avoiding shlib reference to non-exported function. .PATH: ${.CURDIR}/../../lib/libipsec ${.CURDIR}/../../sys/netkey SRCS+= pfkey.c pfkey_dump.c key_debug.c ipsec_strerror.c diff --git a/usr.sbin/setkey/parse.y b/usr.sbin/setkey/parse.y index 1d43dc4..80b9d17 100644 --- a/usr.sbin/setkey/parse.y +++ b/usr.sbin/setkey/parse.y @@ -1,5 +1,5 @@ /* $FreeBSD$ */ -/* $KAME: kame/kame/kame/setkey/parse.y,v 1.36 2001/06/07 15:53:12 sakane Exp $ */ +/* $KAME: parse.y,v 1.81 2003/07/01 04:01:48 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. @@ -53,40 +53,32 @@ #include "vchar.h" #define ATOX(c) \ - (isdigit(c) ? (c - '0') : (isupper(c) ? (c - 'A' + 10) : (c - 'a' + 10) )) + (isdigit(c) ? (c - '0') : (isupper(c) ? (c - 'A' + 10) : (c - 'a' + 10))) -u_int p_type; u_int32_t p_spi; -int p_no_spi; -struct sockaddr *p_src, *p_dst; -u_int p_prefs, p_prefd, p_upper; -u_int p_satype, p_ext, p_alg_enc, p_alg_auth, p_replay, p_mode; +u_int p_ext, p_alg_enc, p_alg_auth, p_replay, p_mode; u_int32_t p_reqid; u_int p_key_enc_len, p_key_auth_len; caddr_t p_key_enc, p_key_auth; time_t p_lt_hard, p_lt_soft; -u_int p_policy_len; -char *p_policy; +static int p_aiflags = 0, p_aifamily = PF_UNSPEC; -/* temporary buffer */ -static struct sockaddr *pp_addr; -static u_int pp_prefix; -static u_int pp_port; -static caddr_t pp_key; - -extern u_char m_buf[BUFSIZ]; -extern int m_len; -extern char cmdarg[8192]; -extern int f_debug; - -static struct addrinfo *parse_addr __P((char *, char *, int)); -static int setvarbuf __P((int *, struct sadb_ext *, int, caddr_t, int)); +static struct addrinfo *parse_addr __P((char *, char *)); +static int fix_portstr __P((vchar_t *, vchar_t *, vchar_t *)); +static int setvarbuf __P((char *, int *, struct sadb_ext *, int, caddr_t, int)); void parse_init __P((void)); void free_buffer __P((void)); -extern int setkeymsg __P((void)); -extern int sendkeymsg __P((void)); +int setkeymsg0 __P((struct sadb_msg *, unsigned int, unsigned int, size_t)); +static int setkeymsg_spdaddr __P((unsigned int, unsigned int, vchar_t *, + struct addrinfo *, int, struct addrinfo *, int)); +static int setkeymsg_addr __P((unsigned int, unsigned int, + struct addrinfo *, struct addrinfo *, int)); +static int setkeymsg_add __P((unsigned int, unsigned int, + struct addrinfo *, struct addrinfo *)); +extern int setkeymsg __P((char *, size_t *)); +extern int sendkeymsg __P((char *, size_t)); extern int yylex __P((void)); extern void yyfatal __P((const char *)); @@ -94,43 +86,48 @@ extern void yyerror __P((const char *)); %} %union { - unsigned long num; + int num; + unsigned long ulnum; vchar_t val; + struct addrinfo *res; } -%token EOT -%token ADD GET DELETE FLUSH DUMP -%token ADDRESS PREFIX PORT PORTANY -%token UP_PROTO PR_ESP PR_AH PR_IPCOMP +%token EOT SLASH BLCL ELCL +%token ADD GET DELETE DELETEALL FLUSH DUMP +%token PR_ESP PR_AH PR_IPCOMP %token F_PROTOCOL F_AUTH F_ENC F_REPLAY F_COMP F_RAWCPI %token F_MODE MODE F_REQID %token F_EXT EXTENSION NOCYCLICSEQ -%token ALG_AUTH ALG_ENC ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_COMP +%token ALG_AUTH ALG_AUTH_NOKEY +%token ALG_ENC ALG_ENC_NOKEY ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_ENC_OLD +%token ALG_COMP %token F_LIFETIME_HARD F_LIFETIME_SOFT %token DECSTRING QUOTEDSTRING HEXSTRING STRING ANY /* SPD management */ %token SPDADD SPDDELETE SPDDUMP SPDFLUSH %token F_POLICY PL_REQUESTS - -%type <num> PORT PREFIX EXTENSION MODE -%type <num> UP_PROTO PR_ESP PR_AH PR_IPCOMP -%type <num> ALG_AUTH ALG_ENC ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_COMP -%type <num> DECSTRING -%type <val> ADDRESS PL_REQUESTS -%type <val> key_string policy_requests +%token F_AIFLAGS +%token TAGGED + +%type <num> prefix protocol_spec upper_spec +%type <num> ALG_ENC ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_ENC_OLD ALG_ENC_NOKEY +%type <num> ALG_AUTH ALG_AUTH_NOKEY +%type <num> ALG_COMP +%type <num> PR_ESP PR_AH PR_IPCOMP +%type <num> EXTENSION MODE +%type <ulnum> DECSTRING +%type <val> PL_REQUESTS portstr key_string +%type <val> policy_requests %type <val> QUOTEDSTRING HEXSTRING STRING +%type <val> F_AIFLAGS +%type <val> upper_misc_spec policy_spec +%type <res> ipaddr %% commands : /*NOTHING*/ | commands command { - if (f_debug) { - printf("cmdarg:\n%s\n", cmdarg); - } else { - setkeymsg(); - sendkeymsg(); - } free_buffer(); parse_init(); } @@ -152,66 +149,90 @@ command /* add command */ add_command - : ADD { p_type = SADB_ADD; } - sa_selector_spec extension_spec algorithm_spec EOT + : ADD ipaddropts ipaddr ipaddr protocol_spec spi extension_spec algorithm_spec EOT + { + int status; + + status = setkeymsg_add(SADB_ADD, $5, $3, $4); + if (status < 0) + return -1; + } ; /* delete */ delete_command - : DELETE { p_type = SADB_DELETE; } - sa_selector_spec extension_spec + : DELETE ipaddropts ipaddr ipaddr protocol_spec spi extension_spec EOT { + int status; + + if ($3->ai_next || $4->ai_next) { + yyerror("multiple address specified"); + return -1; + } if (p_mode != IPSEC_MODE_ANY) - yyerror("WARNING: mode is obsoleted."); + yyerror("WARNING: mode is obsolete"); + + status = setkeymsg_addr(SADB_DELETE, $5, $3, $4, 0); + if (status < 0) + return -1; } - EOT ; /* deleteall command */ deleteall_command - : DELETEALL { p_type = SADB_DELETE; } - ipaddress { p_src = pp_addr; } - ipaddress { p_dst = pp_addr; } - protocol_spec - { p_no_spi = 1; } - EOT + : DELETEALL ipaddropts ipaddr ipaddr protocol_spec EOT + { + int status; + + status = setkeymsg_addr(SADB_DELETE, $5, $3, $4, 1); + if (status < 0) + return -1; + } ; /* get command */ get_command - : GET { p_type = SADB_GET; } - sa_selector_spec extension_spec + : GET ipaddropts ipaddr ipaddr protocol_spec spi extension_spec EOT { + int status; + if (p_mode != IPSEC_MODE_ANY) - yyerror("WARNING: mode is obsoleted."); + yyerror("WARNING: mode is obsolete"); + + status = setkeymsg_addr(SADB_GET, $5, $3, $4, 0); + if (status < 0) + return -1; } - EOT ; /* flush */ flush_command - : FLUSH { p_type = SADB_FLUSH; } - protocol_spec EOT + : FLUSH protocol_spec EOT + { + struct sadb_msg msg; + setkeymsg0(&msg, SADB_FLUSH, $2, sizeof(msg)); + sendkeymsg((char *)&msg, sizeof(msg)); + } ; /* dump */ dump_command - : DUMP { p_type = SADB_DUMP; } - protocol_spec EOT - ; - - /* sa_selector_spec */ -sa_selector_spec - : ipaddress { p_src = pp_addr; } - ipaddress { p_dst = pp_addr; } - protocol_spec spi + : DUMP protocol_spec EOT + { + struct sadb_msg msg; + setkeymsg0(&msg, SADB_DUMP, $2, sizeof(msg)); + sendkeymsg((char *)&msg, sizeof(msg)); + } ; protocol_spec - : /*NOTHING*/ { p_satype = SADB_SATYPE_UNSPEC; } + : /*NOTHING*/ + { + $$ = SADB_SATYPE_UNSPEC; + } | PR_ESP { - p_satype = SADB_SATYPE_ESP; + $$ = SADB_SATYPE_ESP; if ($1 == 1) p_ext |= SADB_X_EXT_OLD; else @@ -219,7 +240,7 @@ protocol_spec } | PR_AH { - p_satype = SADB_SATYPE_AH; + $$ = SADB_SATYPE_AH; if ($1 == 1) p_ext |= SADB_X_EXT_OLD; else @@ -227,7 +248,7 @@ protocol_spec } | PR_IPCOMP { - p_satype = SADB_X_SATYPE_IPCOMP; + $$ = SADB_X_SATYPE_IPCOMP; } ; @@ -235,34 +256,21 @@ spi : DECSTRING { p_spi = $1; } | HEXSTRING { - caddr_t bp; - caddr_t yp = $1.buf; - char buf0[4], buf[4]; - int i, j; + char *ep; + unsigned long v; - /* sanity check */ - if ($1.len > 4) { - yyerror("SPI too big."); - free($1.buf); + ep = NULL; + v = strtoul($1.buf, &ep, 16); + if (!ep || *ep) { + yyerror("invalid SPI"); return -1; } - - bp = buf0; - while (*yp) { - *bp = (ATOX(yp[0]) << 4) | ATOX(yp[1]); - yp += 2, bp++; + if (v & ~0xffffffff) { + yyerror("SPI too big."); + return -1; } - /* initialize */ - for (i = 0; i < 4; i++) buf[i] = 0; - - for (j = $1.len - 1, i = 3; j >= 0; j--, i--) - buf[i] = buf0[j]; - - /* XXX: endian */ - p_spi = ntohl(*(u_int32_t *)buf); - - free($1.buf); + p_spi = v; } ; @@ -273,58 +281,109 @@ algorithm_spec ; esp_spec - : F_ENC enc_alg enc_key F_AUTH auth_alg auth_key - | F_ENC enc_alg enc_key + : F_ENC enc_alg F_AUTH auth_alg + | F_ENC enc_alg ; ah_spec - : F_AUTH auth_alg auth_key + : F_AUTH auth_alg ; ipcomp_spec - : F_COMP ALG_COMP { p_alg_enc = $2; } - | F_COMP ALG_COMP { p_alg_enc = $2; } - F_RAWCPI { p_ext |= SADB_X_EXT_RAWCPI; } + : F_COMP ALG_COMP + { + if ($2 < 0) { + yyerror("unsupported algorithm"); + return -1; + } + p_alg_enc = $2; + } + | F_COMP ALG_COMP F_RAWCPI + { + if ($2 < 0) { + yyerror("unsupported algorithm"); + return -1; + } + p_alg_enc = $2; + p_ext |= SADB_X_EXT_RAWCPI; + } ; enc_alg - : ALG_ENC { p_alg_enc = $1; } - | ALG_ENC_DESDERIV - { - p_alg_enc = $1; - if (p_ext & SADB_X_EXT_OLD) { - yyerror("algorithm mismatched."); + : ALG_ENC_NOKEY { + if ($1 < 0) { + yyerror("unsupported algorithm"); return -1; } - p_ext |= SADB_X_EXT_DERIV; + p_alg_enc = $1; + + p_key_enc_len = 0; + p_key_enc = NULL; } - | ALG_ENC_DES32IV - { + | ALG_ENC key_string { + if ($1 < 0) { + yyerror("unsupported algorithm"); + return -1; + } p_alg_enc = $1; - if (!(p_ext & SADB_X_EXT_OLD)) { - yyerror("algorithm mismatched."); + + p_key_enc_len = $2.len; + p_key_enc = $2.buf; + if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT, + p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) { + yyerror(ipsec_strerror()); return -1; } - p_ext |= SADB_X_EXT_IV4B; } - ; + | ALG_ENC_OLD { + if ($1 < 0) { + yyerror("unsupported algorithm"); + return -1; + } + yyerror("WARNING: obsolete algorithm"); + p_alg_enc = $1; -enc_key - : /*NOTHING*/ + p_key_enc_len = 0; + p_key_enc = NULL; + } + | ALG_ENC_DESDERIV key_string { - if (p_alg_enc != SADB_EALG_NULL) { - yyerror("no key found."); + if ($1 < 0) { + yyerror("unsupported algorithm"); + return -1; + } + p_alg_enc = $1; + if (p_ext & SADB_X_EXT_OLD) { + yyerror("algorithm mismatched"); + return -1; + } + p_ext |= SADB_X_EXT_DERIV; + + p_key_enc_len = $2.len; + p_key_enc = $2.buf; + if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT, + p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) { + yyerror(ipsec_strerror()); return -1; } } - | key_string + | ALG_ENC_DES32IV key_string { - p_key_enc_len = $1.len; - p_key_enc = pp_key; + if ($1 < 0) { + yyerror("unsupported algorithm"); + return -1; + } + p_alg_enc = $1; + if (!(p_ext & SADB_X_EXT_OLD)) { + yyerror("algorithm mismatched"); + return -1; + } + p_ext |= SADB_X_EXT_IV4B; + p_key_enc_len = $2.len; + p_key_enc = $2.buf; if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT, - p_alg_enc, - PFKEY_UNUNIT64(p_key_enc_len)) < 0) { + p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) { yyerror(ipsec_strerror()); return -1; } @@ -332,56 +391,64 @@ enc_key ; auth_alg - : ALG_AUTH { p_alg_auth = $1; } - ; - -auth_key - : /*NOTHING*/ - { - if (p_alg_auth != SADB_X_AALG_NULL) { - yyerror("no key found."); + : ALG_AUTH key_string { + if ($1 < 0) { + yyerror("unsupported algorithm"); return -1; } - } - | key_string - { - p_key_auth_len = $1.len; - p_key_auth = pp_key; + p_alg_auth = $1; + p_key_auth_len = $2.len; + p_key_auth = $2.buf; if (ipsec_check_keylen(SADB_EXT_SUPPORTED_AUTH, - p_alg_auth, - PFKEY_UNUNIT64(p_key_auth_len)) < 0) { + p_alg_auth, PFKEY_UNUNIT64(p_key_auth_len)) < 0) { yyerror(ipsec_strerror()); return -1; } } + | ALG_AUTH_NOKEY { + if ($1 < 0) { + yyerror("unsupported algorithm"); + return -1; + } + p_alg_auth = $1; + + p_key_auth_len = 0; + p_key_auth = NULL; + } ; key_string : QUOTEDSTRING { - pp_key = $1.buf; - /* free pp_key later */ + $$ = $1; } | HEXSTRING { + caddr_t pp_key; caddr_t bp; caddr_t yp = $1.buf; + int l; - if ((pp_key = malloc($1.len)) == 0) { - free($1.buf); + l = strlen(yp) % 2 + strlen(yp) / 2; + if ((pp_key = malloc(l)) == 0) { yyerror("not enough core"); return -1; } - memset(pp_key, 0, $1.len); + memset(pp_key, 0, l); bp = pp_key; + if (strlen(yp) % 2) { + *bp = ATOX(yp[0]); + yp++, bp++; + } while (*yp) { *bp = (ATOX(yp[0]) << 4) | ATOX(yp[1]); yp += 2, bp++; } - free($1.buf); + $$.len = l; + $$.buf = pp_key; } ; @@ -398,9 +465,9 @@ extension | F_REQID DECSTRING { p_reqid = $2; } | F_REPLAY DECSTRING { - if (p_ext & SADB_X_EXT_OLD) { - yyerror("replay prevention " - "only use on new spec."); + if ((p_ext & SADB_X_EXT_OLD) != 0) { + yyerror("replay prevention cannot be used with " + "ah/esp-old"); return -1; } p_replay = $2; @@ -412,183 +479,241 @@ extension /* definition about command for SPD management */ /* spdadd */ spdadd_command - : SPDADD + : SPDADD ipaddropts STRING prefix portstr STRING prefix portstr upper_spec upper_misc_spec policy_spec EOT { - p_type = SADB_X_SPDADD; - p_satype = SADB_SATYPE_UNSPEC; + int status; + struct addrinfo *src, *dst; + + /* fixed port fields if ulp is icmpv6 */ + if ($10.buf != NULL) { + if ($9 != IPPROTO_ICMPV6) + return -1; + free($5.buf); + free($8.buf); + if (fix_portstr(&$10, &$5, &$8)) + return -1; + } + + src = parse_addr($3.buf, $5.buf); + dst = parse_addr($6.buf, $8.buf); + if (!src || !dst) { + /* yyerror is already called */ + return -1; + } + if (src->ai_next || dst->ai_next) { + yyerror("multiple address specified"); + freeaddrinfo(src); + freeaddrinfo(dst); + return -1; + } + + status = setkeymsg_spdaddr(SADB_X_SPDADD, $9, &$11, + src, $4, dst, $7); + freeaddrinfo(src); + freeaddrinfo(dst); + if (status < 0) + return -1; + } + | SPDADD TAGGED QUOTEDSTRING policy_spec EOT + { + return -1; } - sp_selector_spec policy_spec EOT ; -spddelete_command: - SPDDELETE +spddelete_command + : SPDDELETE ipaddropts STRING prefix portstr STRING prefix portstr upper_spec upper_misc_spec policy_spec EOT { - p_type = SADB_X_SPDDELETE; - p_satype = SADB_SATYPE_UNSPEC; + int status; + struct addrinfo *src, *dst; + + /* fixed port fields if ulp is icmpv6 */ + if ($10.buf != NULL) { + if ($9 != IPPROTO_ICMPV6) + return -1; + free($5.buf); + free($8.buf); + if (fix_portstr(&$10, &$5, &$8)) + return -1; + } + + src = parse_addr($3.buf, $5.buf); + dst = parse_addr($6.buf, $8.buf); + if (!src || !dst) { + /* yyerror is already called */ + return -1; + } + if (src->ai_next || dst->ai_next) { + yyerror("multiple address specified"); + freeaddrinfo(src); + freeaddrinfo(dst); + return -1; + } + + status = setkeymsg_spdaddr(SADB_X_SPDDELETE, $9, &$11, + src, $4, dst, $7); + freeaddrinfo(src); + freeaddrinfo(dst); + if (status < 0) + return -1; } - sp_selector_spec policy_spec EOT ; spddump_command: - SPDDUMP + SPDDUMP EOT { - p_type = SADB_X_SPDDUMP; - p_satype = SADB_SATYPE_UNSPEC; + struct sadb_msg msg; + setkeymsg0(&msg, SADB_X_SPDDUMP, SADB_SATYPE_UNSPEC, + sizeof(msg)); + sendkeymsg((char *)&msg, sizeof(msg)); } - EOT ; spdflush_command: - SPDFLUSH + SPDFLUSH EOT { - p_type = SADB_X_SPDFLUSH; - p_satype = SADB_SATYPE_UNSPEC; + struct sadb_msg msg; + setkeymsg0(&msg, SADB_X_SPDFLUSH, SADB_SATYPE_UNSPEC, + sizeof(msg)); + sendkeymsg((char *)&msg, sizeof(msg)); } - EOT ; - /* sp_selector_spec */ -sp_selector_spec - : ipaddress { p_src = pp_addr; } - prefix { p_prefs = pp_prefix; } - port - { - switch (p_src->sa_family) { - case AF_INET: - ((struct sockaddr_in *)p_src)->sin_port = - htons(pp_port); - break; -#ifdef INET6 - case AF_INET6: - ((struct sockaddr_in6 *)p_src)->sin6_port = - htons(pp_port); - break; -#endif - default: - exit(1); /*XXX*/ - } - } - ipaddress { p_dst = pp_addr; } - prefix { p_prefd = pp_prefix; } - port +ipaddropts + : /* nothing */ + | ipaddropts ipaddropt + ; + +ipaddropt + : F_AIFLAGS { - switch (p_dst->sa_family) { - case AF_INET: - ((struct sockaddr_in *)p_dst)->sin_port = - htons(pp_port); - break; + char *p; + + for (p = $1.buf + 1; *p; p++) + switch (*p) { + case '4': + p_aifamily = AF_INET; + break; #ifdef INET6 - case AF_INET6: - ((struct sockaddr_in6 *)p_dst)->sin6_port = - htons(pp_port); - break; + case '6': + p_aifamily = AF_INET6; + break; #endif - default: - exit(1); /*XXX*/ - } - } - upper_spec - { - /* XXX is it something userland should check? */ -#if 0 - switch (p_upper) { - case IPPROTO_ICMP: - case IPPROTO_ICMPV6: - if (_INPORTBYSA(p_src) != IPSEC_PORT_ANY - || _INPORTBYSA(p_dst) != IPSEC_PORT_ANY) { - yyerror("port number must be \"any\"."); + case 'n': + p_aiflags = AI_NUMERICHOST; + break; + default: + yyerror("invalid flag"); return -1; } - if ((pp_addr->sa_family == AF_INET6 - && p_upper == IPPROTO_ICMP) - || (pp_addr->sa_family == AF_INET - && p_upper == IPPROTO_ICMPV6)) { - yyerror("upper layer protocol " - "mismatched.\n"); - return -1; - } - break; - default: - break; - } -#endif } ; -ipaddress - : ADDRESS +ipaddr + : STRING { - struct addrinfo *res; - - res = parse_addr($1.buf, NULL, AI_NUMERICHOST); - if (res == NULL) { - free($1.buf); + $$ = parse_addr($1.buf, NULL); + if ($$ == NULL) { + /* yyerror already called by parse_addr */ return -1; } - pp_addr = (struct sockaddr *)malloc(res->ai_addrlen); - if (!pp_addr) { - yyerror("not enough core"); - goto end; - } - - memcpy(pp_addr, res->ai_addr, res->ai_addrlen); - end: - freeaddrinfo(res); - free($1.buf); } ; prefix - : /*NOTHING*/ { pp_prefix = ~0; } - | PREFIX { pp_prefix = $1; } + : /*NOTHING*/ { $$ = -1; } + | SLASH DECSTRING { $$ = $2; } ; -port - : /*NOTHING*/ { pp_port = IPSEC_PORT_ANY; } - | PORT { pp_port = $1; } - | PORTANY { pp_port = IPSEC_PORT_ANY; } +portstr + : /*NOTHING*/ + { + $$.buf = strdup("0"); + if (!$$.buf) { + yyerror("insufficient memory"); + return -1; + } + $$.len = strlen($$.buf); + } + | BLCL ANY ELCL + { + $$.buf = strdup("0"); + if (!$$.buf) { + yyerror("insufficient memory"); + return -1; + } + $$.len = strlen($$.buf); + } + | BLCL DECSTRING ELCL + { + char buf[20]; + snprintf(buf, sizeof(buf), "%lu", $2); + $$.buf = strdup(buf); + if (!$$.buf) { + yyerror("insufficient memory"); + return -1; + } + $$.len = strlen($$.buf); + } + | BLCL STRING ELCL + { + $$ = $2; + } ; upper_spec - : DECSTRING { p_upper = $1; } - | UP_PROTO { p_upper = $1; } - | ANY { p_upper = IPSEC_ULPROTO_ANY; } + : DECSTRING { $$ = $1; } + | ANY { $$ = IPSEC_ULPROTO_ANY; } | STRING { struct protoent *ent; ent = getprotobyname($1.buf); if (ent) - p_upper = ent->p_proto; + $$ = ent->p_proto; else { if (strcmp("icmp6", $1.buf) == 0) { - p_upper = IPPROTO_ICMPV6; + $$ = IPPROTO_ICMPV6; } else if(strcmp("ip4", $1.buf) == 0) { - p_upper = IPPROTO_IPV4; + $$ = IPPROTO_IPV4; } else { yyerror("invalid upper layer protocol"); - free($1.buf); return -1; } } - free($1.buf); + endprotoent(); + } + ; + +upper_misc_spec + : /*NOTHING*/ + { + $$.buf = NULL; + $$.len = 0; + } + | STRING + { + $$.buf = strdup($1.buf); + if (!$$.buf) { + yyerror("insufficient memory"); + return -1; + } + $$.len = strlen($$.buf); } ; policy_spec : F_POLICY policy_requests { - p_policy = ipsec_set_policy($2.buf, $2.len); - if (p_policy == NULL) { - free($2.buf); - p_policy = NULL; + char *policy; + + policy = ipsec_set_policy($2.buf, $2.len); + if (policy == NULL) { yyerror(ipsec_strerror()); return -1; } - p_policy_len = ipsec_get_policylen(p_policy); - - free($2.buf); + $$.buf = policy; + $$.len = ipsec_get_policylen(policy); } ; @@ -599,291 +724,494 @@ policy_requests %% int -setkeymsg() +setkeymsg0(msg, type, satype, l) + struct sadb_msg *msg; + unsigned int type; + unsigned int satype; + size_t l; { - struct sadb_msg m_msg; - - m_msg.sadb_msg_version = PF_KEY_V2; - m_msg.sadb_msg_type = p_type; - m_msg.sadb_msg_errno = 0; - m_msg.sadb_msg_satype = p_satype; - m_msg.sadb_msg_reserved = 0; - m_msg.sadb_msg_seq = 0; - m_msg.sadb_msg_pid = getpid(); - - m_len = sizeof(struct sadb_msg); - memcpy(m_buf, &m_msg, m_len); - - switch (p_type) { - case SADB_FLUSH: - case SADB_DUMP: - break; - - case SADB_ADD: - /* set encryption algorithm, if present. */ - if (p_satype != SADB_X_SATYPE_IPCOMP && p_alg_enc != SADB_EALG_NONE) { - struct sadb_key m_key; - - m_key.sadb_key_len = - PFKEY_UNIT64(sizeof(m_key) - + PFKEY_ALIGN8(p_key_enc_len)); - m_key.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT; - m_key.sadb_key_bits = p_key_enc_len * 8; - m_key.sadb_key_reserved = 0; - - setvarbuf(&m_len, - (struct sadb_ext *)&m_key, sizeof(m_key), - (caddr_t)p_key_enc, p_key_enc_len); - } - - /* set authentication algorithm, if present. */ - if (p_alg_auth != SADB_AALG_NONE) { - struct sadb_key m_key; - - m_key.sadb_key_len = - PFKEY_UNIT64(sizeof(m_key) - + PFKEY_ALIGN8(p_key_auth_len)); - m_key.sadb_key_exttype = SADB_EXT_KEY_AUTH; - m_key.sadb_key_bits = p_key_auth_len * 8; - m_key.sadb_key_reserved = 0; - - setvarbuf(&m_len, - (struct sadb_ext *)&m_key, sizeof(m_key), - (caddr_t)p_key_auth, p_key_auth_len); - } - - /* set lifetime for HARD */ - if (p_lt_hard != 0) { - struct sadb_lifetime m_lt; - u_int len = sizeof(struct sadb_lifetime); - - m_lt.sadb_lifetime_len = PFKEY_UNIT64(len); - m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD; - m_lt.sadb_lifetime_allocations = 0; - m_lt.sadb_lifetime_bytes = 0; - m_lt.sadb_lifetime_addtime = p_lt_hard; - m_lt.sadb_lifetime_usetime = 0; - - memcpy(m_buf + m_len, &m_lt, len); - m_len += len; - } - - /* set lifetime for SOFT */ - if (p_lt_soft != 0) { - struct sadb_lifetime m_lt; - u_int len = sizeof(struct sadb_lifetime); - - m_lt.sadb_lifetime_len = PFKEY_UNIT64(len); - m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT; - m_lt.sadb_lifetime_allocations = 0; - m_lt.sadb_lifetime_bytes = 0; - m_lt.sadb_lifetime_addtime = p_lt_soft; - m_lt.sadb_lifetime_usetime = 0; - - memcpy(m_buf + m_len, &m_lt, len); - m_len += len; - } - /* FALLTHROUGH */ - - case SADB_DELETE: - case SADB_GET: - { - struct sadb_sa m_sa; - struct sadb_x_sa2 m_sa2; - struct sadb_address m_addr; - u_int len; - - if (p_no_spi == 0) { - len = sizeof(struct sadb_sa); - m_sa.sadb_sa_len = PFKEY_UNIT64(len); - m_sa.sadb_sa_exttype = SADB_EXT_SA; - m_sa.sadb_sa_spi = htonl(p_spi); - m_sa.sadb_sa_replay = p_replay; - m_sa.sadb_sa_state = 0; - m_sa.sadb_sa_auth = p_alg_auth; - m_sa.sadb_sa_encrypt = p_alg_enc; - m_sa.sadb_sa_flags = p_ext; - - memcpy(m_buf + m_len, &m_sa, len); - m_len += len; - - len = sizeof(struct sadb_x_sa2); - m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len); - m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2; - m_sa2.sadb_x_sa2_mode = p_mode; - m_sa2.sadb_x_sa2_reqid = p_reqid; - - memcpy(m_buf + m_len, &m_sa2, len); - m_len += len; - } - - /* set src */ - m_addr.sadb_address_len = - PFKEY_UNIT64(sizeof(m_addr) - + PFKEY_ALIGN8(p_src->sa_len)); - m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC; - m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY; - switch (p_src->sa_family) { - case AF_INET: - m_addr.sadb_address_prefixlen = - sizeof(struct in_addr) << 3; - break; + + msg->sadb_msg_version = PF_KEY_V2; + msg->sadb_msg_type = type; + msg->sadb_msg_errno = 0; + msg->sadb_msg_satype = satype; + msg->sadb_msg_reserved = 0; + msg->sadb_msg_seq = 0; + msg->sadb_msg_pid = getpid(); + msg->sadb_msg_len = PFKEY_UNIT64(l); + return 0; +} + +/* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */ +static int +setkeymsg_spdaddr(type, upper, policy, srcs, splen, dsts, dplen) + unsigned int type; + unsigned int upper; + vchar_t *policy; + struct addrinfo *srcs; + int splen; + struct addrinfo *dsts; + int dplen; +{ + struct sadb_msg *msg; + char buf[BUFSIZ]; + int l, l0; + struct sadb_address m_addr; + struct addrinfo *s, *d; + int n; + int plen; + struct sockaddr *sa; + int salen; + + msg = (struct sadb_msg *)buf; + + if (!srcs || !dsts) + return -1; + + /* fix up length afterwards */ + setkeymsg0(msg, type, SADB_SATYPE_UNSPEC, 0); + l = sizeof(struct sadb_msg); + + memcpy(buf + l, policy->buf, policy->len); + l += policy->len; + + l0 = l; + n = 0; + + /* do it for all src/dst pairs */ + for (s = srcs; s; s = s->ai_next) { + for (d = dsts; d; d = d->ai_next) { + /* rewind pointer */ + l = l0; + + if (s->ai_addr->sa_family != d->ai_addr->sa_family) + continue; + switch (s->ai_addr->sa_family) { + case AF_INET: + plen = sizeof(struct in_addr) << 3; + break; #ifdef INET6 - case AF_INET6: - m_addr.sadb_address_prefixlen = - sizeof(struct in6_addr) << 3; - break; + case AF_INET6: + plen = sizeof(struct in6_addr) << 3; + break; #endif - default: - yyerror("unsupported address family"); - exit(1); /*XXX*/ - } - m_addr.sadb_address_reserved = 0; - - setvarbuf(&m_len, - (struct sadb_ext *)&m_addr, sizeof(m_addr), - (caddr_t)p_src, p_src->sa_len); - - /* set dst */ - m_addr.sadb_address_len = - PFKEY_UNIT64(sizeof(m_addr) - + PFKEY_ALIGN8(p_dst->sa_len)); - m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST; - m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY; - switch (p_dst->sa_family) { - case AF_INET: + default: + continue; + } + + /* set src */ + sa = s->ai_addr; + salen = s->ai_addr->sa_len; + m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) + + PFKEY_ALIGN8(salen)); + m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC; + m_addr.sadb_address_proto = upper; m_addr.sadb_address_prefixlen = - sizeof(struct in_addr) << 3; - break; -#ifdef INET6 - case AF_INET6: + (splen >= 0 ? splen : plen); + m_addr.sadb_address_reserved = 0; + + setvarbuf(buf, &l, (struct sadb_ext *)&m_addr, + sizeof(m_addr), (caddr_t)sa, salen); + + /* set dst */ + sa = d->ai_addr; + salen = d->ai_addr->sa_len; + m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) + + PFKEY_ALIGN8(salen)); + m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST; + m_addr.sadb_address_proto = upper; m_addr.sadb_address_prefixlen = - sizeof(struct in6_addr) << 3; - break; -#endif - default: - yyerror("unsupported address family"); - exit(1); /*XXX*/ - } - m_addr.sadb_address_reserved = 0; - - setvarbuf(&m_len, - (struct sadb_ext *)&m_addr, sizeof(m_addr), - (caddr_t)p_dst, p_dst->sa_len); - } - break; - - /* for SPD management */ - case SADB_X_SPDFLUSH: - case SADB_X_SPDDUMP: - break; - - case SADB_X_SPDADD: - case SADB_X_SPDDELETE: - { - struct sadb_address m_addr; - u_int8_t plen; - - memcpy(m_buf + m_len, p_policy, p_policy_len); - m_len += p_policy_len; - free(p_policy); - p_policy = NULL; - - /* set src */ - m_addr.sadb_address_len = - PFKEY_UNIT64(sizeof(m_addr) - + PFKEY_ALIGN8(p_src->sa_len)); - m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC; - m_addr.sadb_address_proto = p_upper; - switch (p_src->sa_family) { - case AF_INET: - plen = sizeof(struct in_addr) << 3; - break; + (dplen >= 0 ? dplen : plen); + m_addr.sadb_address_reserved = 0; + + setvarbuf(buf, &l, (struct sadb_ext *)&m_addr, + sizeof(m_addr), (caddr_t)sa, salen); + + msg->sadb_msg_len = PFKEY_UNIT64(l); + + sendkeymsg(buf, l); + + n++; + } + } + + if (n == 0) + return -1; + else + return 0; +} + +/* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */ +static int +setkeymsg_addr(type, satype, srcs, dsts, no_spi) + unsigned int type; + unsigned int satype; + struct addrinfo *srcs; + struct addrinfo *dsts; + int no_spi; +{ + struct sadb_msg *msg; + char buf[BUFSIZ]; + int l, l0, len; + struct sadb_sa m_sa; + struct sadb_x_sa2 m_sa2; + struct sadb_address m_addr; + struct addrinfo *s, *d; + int n; + int plen; + struct sockaddr *sa; + int salen; + + msg = (struct sadb_msg *)buf; + + if (!srcs || !dsts) + return -1; + + /* fix up length afterwards */ + setkeymsg0(msg, type, satype, 0); + l = sizeof(struct sadb_msg); + + if (!no_spi) { + len = sizeof(struct sadb_sa); + m_sa.sadb_sa_len = PFKEY_UNIT64(len); + m_sa.sadb_sa_exttype = SADB_EXT_SA; + m_sa.sadb_sa_spi = htonl(p_spi); + m_sa.sadb_sa_replay = p_replay; + m_sa.sadb_sa_state = 0; + m_sa.sadb_sa_auth = p_alg_auth; + m_sa.sadb_sa_encrypt = p_alg_enc; + m_sa.sadb_sa_flags = p_ext; + + memcpy(buf + l, &m_sa, len); + l += len; + + len = sizeof(struct sadb_x_sa2); + m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len); + m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2; + m_sa2.sadb_x_sa2_mode = p_mode; + m_sa2.sadb_x_sa2_reqid = p_reqid; + + memcpy(buf + l, &m_sa2, len); + l += len; + } + + l0 = l; + n = 0; + + /* do it for all src/dst pairs */ + for (s = srcs; s; s = s->ai_next) { + for (d = dsts; d; d = d->ai_next) { + /* rewind pointer */ + l = l0; + + if (s->ai_addr->sa_family != d->ai_addr->sa_family) + continue; + switch (s->ai_addr->sa_family) { + case AF_INET: + plen = sizeof(struct in_addr) << 3; + break; #ifdef INET6 - case AF_INET6: - plen = sizeof(struct in6_addr) << 3; - break; + case AF_INET6: + plen = sizeof(struct in6_addr) << 3; + break; #endif - default: - yyerror("unsupported address family"); - exit(1); /*XXX*/ - } - m_addr.sadb_address_prefixlen = - (p_prefs != ~0 ? p_prefs : plen); - m_addr.sadb_address_reserved = 0; - - setvarbuf(&m_len, - (struct sadb_ext *)&m_addr, sizeof(m_addr), - (caddr_t)p_src, p_src->sa_len); - - /* set dst */ - m_addr.sadb_address_len = - PFKEY_UNIT64(sizeof(m_addr) - + PFKEY_ALIGN8(p_dst->sa_len)); - m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST; - m_addr.sadb_address_proto = p_upper; - switch (p_dst->sa_family) { - case AF_INET: - plen = sizeof(struct in_addr) << 3; - break; + default: + continue; + } + + /* set src */ + sa = s->ai_addr; + salen = s->ai_addr->sa_len; + m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) + + PFKEY_ALIGN8(salen)); + m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC; + m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY; + m_addr.sadb_address_prefixlen = plen; + m_addr.sadb_address_reserved = 0; + + setvarbuf(buf, &l, (struct sadb_ext *)&m_addr, + sizeof(m_addr), (caddr_t)sa, salen); + + /* set dst */ + sa = d->ai_addr; + salen = d->ai_addr->sa_len; + m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) + + PFKEY_ALIGN8(salen)); + m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST; + m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY; + m_addr.sadb_address_prefixlen = plen; + m_addr.sadb_address_reserved = 0; + + setvarbuf(buf, &l, (struct sadb_ext *)&m_addr, + sizeof(m_addr), (caddr_t)sa, salen); + + msg->sadb_msg_len = PFKEY_UNIT64(l); + + sendkeymsg(buf, l); + + n++; + } + } + + if (n == 0) + return -1; + else + return 0; +} + +/* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */ +static int +setkeymsg_add(type, satype, srcs, dsts) + unsigned int type; + unsigned int satype; + struct addrinfo *srcs; + struct addrinfo *dsts; +{ + struct sadb_msg *msg; + char buf[BUFSIZ]; + int l, l0, len; + struct sadb_sa m_sa; + struct sadb_x_sa2 m_sa2; + struct sadb_address m_addr; + struct addrinfo *s, *d; + int n; + int plen; + struct sockaddr *sa; + int salen; + + msg = (struct sadb_msg *)buf; + + if (!srcs || !dsts) + return -1; + + /* fix up length afterwards */ + setkeymsg0(msg, type, satype, 0); + l = sizeof(struct sadb_msg); + + /* set encryption algorithm, if present. */ + if (satype != SADB_X_SATYPE_IPCOMP && p_key_enc) { + struct sadb_key m_key; + + m_key.sadb_key_len = + PFKEY_UNIT64(sizeof(m_key) + + PFKEY_ALIGN8(p_key_enc_len)); + m_key.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT; + m_key.sadb_key_bits = p_key_enc_len * 8; + m_key.sadb_key_reserved = 0; + + setvarbuf(buf, &l, + (struct sadb_ext *)&m_key, sizeof(m_key), + (caddr_t)p_key_enc, p_key_enc_len); + } + + /* set authentication algorithm, if present. */ + if (p_key_auth) { + struct sadb_key m_key; + + m_key.sadb_key_len = + PFKEY_UNIT64(sizeof(m_key) + + PFKEY_ALIGN8(p_key_auth_len)); + m_key.sadb_key_exttype = SADB_EXT_KEY_AUTH; + m_key.sadb_key_bits = p_key_auth_len * 8; + m_key.sadb_key_reserved = 0; + + setvarbuf(buf, &l, + (struct sadb_ext *)&m_key, sizeof(m_key), + (caddr_t)p_key_auth, p_key_auth_len); + } + + /* set lifetime for HARD */ + if (p_lt_hard != 0) { + struct sadb_lifetime m_lt; + u_int slen = sizeof(struct sadb_lifetime); + + m_lt.sadb_lifetime_len = PFKEY_UNIT64(slen); + m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD; + m_lt.sadb_lifetime_allocations = 0; + m_lt.sadb_lifetime_bytes = 0; + m_lt.sadb_lifetime_addtime = p_lt_hard; + m_lt.sadb_lifetime_usetime = 0; + + memcpy(buf + l, &m_lt, slen); + l += len; + } + + /* set lifetime for SOFT */ + if (p_lt_soft != 0) { + struct sadb_lifetime m_lt; + u_int slen = sizeof(struct sadb_lifetime); + + m_lt.sadb_lifetime_len = PFKEY_UNIT64(slen); + m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT; + m_lt.sadb_lifetime_allocations = 0; + m_lt.sadb_lifetime_bytes = 0; + m_lt.sadb_lifetime_addtime = p_lt_soft; + m_lt.sadb_lifetime_usetime = 0; + + memcpy(buf + l, &m_lt, slen); + l += len; + } + + len = sizeof(struct sadb_sa); + m_sa.sadb_sa_len = PFKEY_UNIT64(len); + m_sa.sadb_sa_exttype = SADB_EXT_SA; + m_sa.sadb_sa_spi = htonl(p_spi); + m_sa.sadb_sa_replay = p_replay; + m_sa.sadb_sa_state = 0; + m_sa.sadb_sa_auth = p_alg_auth; + m_sa.sadb_sa_encrypt = p_alg_enc; + m_sa.sadb_sa_flags = p_ext; + + memcpy(buf + l, &m_sa, len); + l += len; + + len = sizeof(struct sadb_x_sa2); + m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len); + m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2; + m_sa2.sadb_x_sa2_mode = p_mode; + m_sa2.sadb_x_sa2_reqid = p_reqid; + + memcpy(buf + l, &m_sa2, len); + l += len; + + l0 = l; + n = 0; + + /* do it for all src/dst pairs */ + for (s = srcs; s; s = s->ai_next) { + for (d = dsts; d; d = d->ai_next) { + /* rewind pointer */ + l = l0; + + if (s->ai_addr->sa_family != d->ai_addr->sa_family) + continue; + switch (s->ai_addr->sa_family) { + case AF_INET: + plen = sizeof(struct in_addr) << 3; + break; #ifdef INET6 - case AF_INET6: - plen = sizeof(struct in6_addr) << 3; - break; + case AF_INET6: + plen = sizeof(struct in6_addr) << 3; + break; #endif - default: - yyerror("unsupported address family"); - exit(1); /*XXX*/ - } - m_addr.sadb_address_prefixlen = - (p_prefd != ~0 ? p_prefd : plen); - m_addr.sadb_address_reserved = 0; - - setvarbuf(&m_len, - (struct sadb_ext *)&m_addr, sizeof(m_addr), - (caddr_t)p_dst, p_dst->sa_len); - } - break; - } + default: + continue; + } - ((struct sadb_msg *)m_buf)->sadb_msg_len = PFKEY_UNIT64(m_len); + /* set src */ + sa = s->ai_addr; + salen = s->ai_addr->sa_len; + m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) + + PFKEY_ALIGN8(salen)); + m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC; + m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY; + m_addr.sadb_address_prefixlen = plen; + m_addr.sadb_address_reserved = 0; + + setvarbuf(buf, &l, (struct sadb_ext *)&m_addr, + sizeof(m_addr), (caddr_t)sa, salen); + + /* set dst */ + sa = d->ai_addr; + salen = d->ai_addr->sa_len; + m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) + + PFKEY_ALIGN8(salen)); + m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST; + m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY; + m_addr.sadb_address_prefixlen = plen; + m_addr.sadb_address_reserved = 0; + + setvarbuf(buf, &l, (struct sadb_ext *)&m_addr, + sizeof(m_addr), (caddr_t)sa, salen); + + msg->sadb_msg_len = PFKEY_UNIT64(l); + + sendkeymsg(buf, l); + + n++; + } + } - return 0; + if (n == 0) + return -1; + else + return 0; } static struct addrinfo * -parse_addr(host, port, flag) +parse_addr(host, port) char *host; char *port; - int flag; { struct addrinfo hints, *res = NULL; int error; memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_DGRAM; - hints.ai_flags = flag; + hints.ai_family = p_aifamily; + hints.ai_socktype = SOCK_DGRAM; /*dummy*/ + hints.ai_protocol = IPPROTO_UDP; /*dummy*/ + hints.ai_flags = p_aiflags; error = getaddrinfo(host, port, &hints, &res); if (error != 0) { yyerror(gai_strerror(error)); return NULL; } - if (res->ai_next != NULL) { - yyerror(gai_strerror(error)); - } return res; } static int -setvarbuf(off, ebuf, elen, vbuf, vlen) - caddr_t vbuf; +fix_portstr(spec, sport, dport) + vchar_t *spec, *sport, *dport; +{ + char *p, *p2; + u_int l; + + l = 0; + for (p = spec->buf; *p != ',' && *p != '\0' && l < spec->len; p++, l++) + ; + if (*p == '\0') { + p2 = "0"; + } else { + if (*p == ',') { + *p = '\0'; + p2 = ++p; + } + for (p = p2; *p != '\0' && l < spec->len; p++, l++) + ; + if (*p != '\0' || *p2 == '\0') { + yyerror("invalid an upper layer protocol spec"); + return -1; + } + } + + sport->buf = strdup(spec->buf); + if (!sport->buf) { + yyerror("insufficient memory"); + return -1; + } + sport->len = strlen(sport->buf); + dport->buf = strdup(p2); + if (!dport->buf) { + yyerror("insufficient memory"); + return -1; + } + dport->len = strlen(dport->buf); + + return 0; +} + +static int +setvarbuf(buf, off, ebuf, elen, vbuf, vlen) + char *buf; + int *off; struct sadb_ext *ebuf; - int *off, elen, vlen; + int elen; + caddr_t vbuf; + int vlen; { - memset(m_buf + *off, 0, PFKEY_UNUNIT64(ebuf->sadb_ext_len)); - memcpy(m_buf + *off, (caddr_t)ebuf, elen); - memcpy(m_buf + *off + elen, vbuf, vlen); + memset(buf + *off, 0, PFKEY_UNUNIT64(ebuf->sadb_ext_len)); + memcpy(buf + *off, (caddr_t)ebuf, elen); + memcpy(buf + *off + elen, vbuf, vlen); (*off) += PFKEY_ALIGN8(elen + vlen); return 0; @@ -892,16 +1220,8 @@ setvarbuf(off, ebuf, elen, vbuf, vlen) void parse_init() { - p_type = 0; p_spi = 0; - p_no_spi = 0; - - p_src = 0, p_dst = 0; - pp_prefix = p_prefs = p_prefd = ~0; - pp_port = IPSEC_PORT_ANY; - p_upper = 0; - p_satype = 0; p_ext = SADB_X_EXT_CYCSEQ; p_alg_enc = SADB_EALG_NONE; p_alg_auth = SADB_AALG_NONE; @@ -912,10 +1232,8 @@ parse_init() p_key_enc = p_key_auth = 0; p_lt_hard = p_lt_soft = 0; - p_policy_len = 0; - p_policy = NULL; - - memset(cmdarg, 0, sizeof(cmdarg)); + p_aiflags = 0; + p_aifamily = PF_UNSPEC; return; } @@ -923,11 +1241,7 @@ parse_init() void free_buffer() { - if (p_src) free(p_src); - if (p_dst) free(p_dst); - if (p_key_enc) free(p_key_enc); - if (p_key_auth) free(p_key_auth); + /* we got tons of memory leaks in the parser anyways, leave them */ return; } - diff --git a/usr.sbin/setkey/sample.cf b/usr.sbin/setkey/sample.cf index 3318f9b..c534fa1 100644 --- a/usr.sbin/setkey/sample.cf +++ b/usr.sbin/setkey/sample.cf @@ -45,9 +45,9 @@ # # At Host-A and Host-B, spdadd fec0::10[any] fec0::11[110] tcp -P out ipsec - esp/transport/fec0::10-fec0::11/use ; + esp/transport//use ; spdadd fec0::11[110] fec0::10[any] tcp -P in ipsec - esp/transport/fec0::11-fec0::10/use ; + esp/transport//use ; add fec0::10 fec0::11 esp 0x10001 -m transport -E blowfish-cbc "kamekame" @@ -112,10 +112,10 @@ add 172.16.0.2 172.16.0.1 ah-old 0x10004 # At Gateway-A: spdadd fec0:0:0:1::/64 fec0:0:0:2::/64 any -P out ipsec esp/tunnel/fec0:0:0:1::1-fec0:0:0:2::1/require - ah/transport/fec0:0:0:1::1-fec0:0:0:2::1/require ; + ah/transport//require ; spdadd fec0:0:0:2::/64 fec0:0:0:1::/64 any -P in ipsec esp/tunnel/fec0:0:0:2::1-fec0:0:0:1::1/require - ah/transport/fec0:0:0:2::1-fec0:0:0:1::1/require ; + ah/transport//require ; add fec0:0:0:1::1 fec0:0:0:2::1 esp 0x10001 -m tunnel -E 3des-cbc "kamekame12341234kame1234" @@ -146,10 +146,10 @@ add fec0:0:0:2::1 fec0:0:0:1::1 ah 0x10001 # # At Host-A: spdadd fec0:0:0:1::1[any] fec0:0:0:2::2[80] tcp -P out ipsec - esp/transport/fec0:0:0:1::1-fec0:0:0:2::2/use + esp/transport//use esp/tunnel/fec0:0:0:1::1-fec0:0:0:2::1/require ; spdadd fec0:0:0:2::1[80] fec0:0:0:1::1[any] tcp -P in ipsec - esp/transport/fec0:0:0:2::2-fec0:0:0:1::1/use + esp/transport//use esp/tunnel/fec0:0:0:2::1-fec0:0:0:1::1/require ; add fec0:0:0:1::1 fec0:0:0:2::2 esp 0x10001 -m transport @@ -166,10 +166,10 @@ add fec0:0:0:2::1 fec0:0:0:1::1 esp 0x10004 -E rc5-cbc "kamekame" -A hmac-md5 "this is the test" ; -# By "get" command, you can get an entry of either SP or SA. +# By "get" command, you can get a entry of either SP or SA. get fec0:0:0:1::1 fec0:0:0:2::2 ah 0x10004 ; -# Also delete command, you can delete an entry of either SP or SA. +# Also delete command, you can delete a entry of either SP or SA. spddelete fec0:0:0:1::/64 fec0:0:0:2::/64 any -P out; delete fec0:0:0:1::1 fec0:0:0:2::2 ah 0x10004 ; @@ -188,24 +188,24 @@ dump esp ; flush ah ; # XXX -add ::1 ::1 esp 10001 -m transport -E simple ; +add ::1 ::1 esp 10001 -m transport -E null ; add ::1 ::1 esp 10002 -m transport -E des-deriv "12341234" ; add ::1 ::1 esp-old 10003 -m transport -E des-32iv "12341234" ; -add ::1 ::1 esp 10004 -m transport -E simple -A null ; -add ::1 ::1 esp 10005 -m transport -E simple -A hmac-md5 "1234123412341234" ; -add ::1 ::1 esp 10006 -m tunnel -E simple -A hmac-sha1 "12341234123412341234" ; -add ::1 ::1 esp 10007 -m transport -E simple -A keyed-md5 "1234123412341234" ; -add ::1 ::1 esp 10008 -m any -E simple -A keyed-sha1 "12341234123412341234" ; +add ::1 ::1 esp 10004 -m transport -E null -A null ; +add ::1 ::1 esp 10005 -m transport -E null -A hmac-md5 "1234123412341234" ; +add ::1 ::1 esp 10006 -m tunnel -E null -A hmac-sha1 "12341234123412341234" ; +add ::1 ::1 esp 10007 -m transport -E null -A keyed-md5 "1234123412341234" ; +add ::1 ::1 esp 10008 -m any -E null -A keyed-sha1 "12341234123412341234" ; add ::1 ::1 esp 10009 -m transport -E des-cbc "testtest" ; add ::1 ::1 esp 10010 -m transport -E 3des-cbc "testtest12341234testtest" ; add ::1 ::1 esp 10011 -m tunnel -E cast128-cbc "testtest1234" ; add ::1 ::1 esp 10012 -m tunnel -E blowfish-cbc "testtest1234" ; add ::1 ::1 esp 10013 -m tunnel -E rc5-cbc "testtest1234" ; add ::1 ::1 esp 10014 -m any -E rc5-cbc "testtest1234" ; -add ::1 ::1 esp 10015 -m transport -f zero-pad -E simple ; -add ::1 ::1 esp 10016 -m tunnel -f random-pad -r 8 -lh 100 -ls 80 -E simple ; -add ::1 ::1 esp 10017 -m transport -f seq-pad -f nocyclic-seq -E simple ; -add ::1 ::1 esp 10018 -m transport -E simple ; +add ::1 ::1 esp 10015 -m transport -f zero-pad -E null ; +add ::1 ::1 esp 10016 -m tunnel -f random-pad -r 8 -lh 100 -ls 80 -E null ; +add ::1 ::1 esp 10017 -m transport -f seq-pad -f nocyclic-seq -E null ; +add ::1 ::1 esp 10018 -m transport -E null ; #add ::1 ::1 ah 20000 -m transport -A null ; add ::1 ::1 ah 20001 -m any -A hmac-md5 "1234123412341234"; add ::1 ::1 ah 20002 -m tunnel -A hmac-sha1 "12341234123412341234"; diff --git a/usr.sbin/setkey/setkey.8 b/usr.sbin/setkey/setkey.8 index 4ab8927..ebe28e2 100644 --- a/usr.sbin/setkey/setkey.8 +++ b/usr.sbin/setkey/setkey.8 @@ -1,4 +1,4 @@ -.\" $KAME: setkey.8,v 1.49 2001/05/18 05:49:51 sakane Exp $ +.\" $KAME: setkey.8,v 1.89 2003/09/07 22:17:41 itojun Exp $ .\" $FreeBSD$ .\" .\" Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. @@ -34,20 +34,20 @@ .\" .Sh NAME .Nm setkey -.Nd "manually manipulate the IPsec SA/SP database" +.Nd manually manipulate the IPsec SA/SP database .\" .Sh SYNOPSIS .Nm -.Op Fl dv +.Op Fl v .Fl c .Nm -.Op Fl dv +.Op Fl v .Fl f Ar filename .Nm -.Op Fl adPlv +.Op Fl aPlv .Fl D .Nm -.Op Fl dPv +.Op Fl Pv .Fl F .Nm .Op Fl h @@ -56,19 +56,23 @@ .Sh DESCRIPTION The .Nm -utility adds, updates, dumps, or flushes +command adds, updates, dumps, or flushes Security Association Database (SAD) entries as well as Security Policy Database (SPD) entries in the kernel. .Pp The .Nm -utility takes a series of operations from the standard input -(if invoked with -.Fl c ) +command takes a series of operations from the standard input +.Po +if invoked with +.Fl c +.Pc or the file named .Ar filename -(if invoked with -.Fl f Ar filename ) . +.Po +if invoked with +.Fl f Ar filename +.Pc . .Bl -tag -width Ds .It Fl D Dump the SAD entries. @@ -81,24 +85,15 @@ If with .Fl P , the SPD entries are flushed. .It Fl a -Dead SAD entries are usually not displayed with +.Nm +usually does not display dead SAD entries with .Fl D . If with .Fl a , the dead SAD entries will be displayed as well. A dead SAD entry means that -it has been expired but remains -because it is referenced by SPD entries. -.It Fl d -Enable to print debugging messages for command parser, -without talking to kernel. -It is not used usually. -.It Fl x -Loop forever and dump all the messages transmitted to -.Dv PF_KEY -socket. -.Fl xx -makes each timestamps unformatted. +it has been expired but remains in the system +because it is referenced by some SPD entries. .It Fl h Add hexadecimal dump on .Fl x @@ -111,23 +106,39 @@ Be verbose. The program will dump messages exchanged on .Dv PF_KEY socket, including messages sent from other processes to the kernel. +.It Fl x +Loop forever and dump all the messages transmitted to +.Dv PF_KEY +socket. +.Fl xx +makes each timestamps unformatted. .El -.Pp -Operations have the following grammar. -Note that lines starting with -hashmarks ('#') are treated as comment lines. +.Ss Configuration syntax +With +.Fl c +or +.Fl f +on the command line, +.Nm +accepts the following configuration syntax. +Lines starting with hash signs ('#') are treated as comment lines. .Bl -tag -width Ds .It Xo .Li add +.Op Fl 46n .Ar src Ar dst Ar protocol Ar spi .Op Ar extensions -.Ar algorithm... +.Ar algorithm ... .Li ; .Xc Add an SAD entry. +.Li add +can fail with multiple reasons, +including when the key length does not match the specified algorithm. .\" .It Xo .Li get +.Op Fl 46n .Ar src Ar dst Ar protocol Ar spi .Li ; .Xc @@ -135,6 +146,7 @@ Show an SAD entry. .\" .It Xo .Li delete +.Op Fl 46n .Ar src Ar dst Ar protocol Ar spi .Li ; .Xc @@ -142,6 +154,7 @@ Remove an SAD entry. .\" .It Xo .Li deleteall +.Op Fl 46n .Ar src Ar dst Ar protocol .Li ; .Xc @@ -153,6 +166,8 @@ Remove all SAD entries that match the specification. .Li ; .Xc Clear all SAD entries matched by the options. +.Fl F +on the command line achieves the same functionality. .\" .It Xo .Li dump @@ -160,9 +175,12 @@ Clear all SAD entries matched by the options. .Li ; .Xc Dumps all SAD entries matched by the options. +.Fl D +on the command line achieves the same functionality. .\" .It Xo .Li spdadd +.Op Fl 46n .Ar src_range Ar dst_range Ar upperspec Ar policy .Li ; .Xc @@ -170,6 +188,7 @@ Add an SPD entry. .\" .It Xo .Li spddelete +.Op Fl 46n .Ar src_range Ar dst_range Ar upperspec Fl P Ar direction .Li ; .Xc @@ -180,12 +199,16 @@ Delete an SPD entry. .Li ; .Xc Clear all SPD entries. +.Fl FP +on the command line achieves the same functionality. .\" .It Xo .Li spddump .Li ; .Xc Dumps all SPD entries. +.Fl DP +on the command line achieves the same functionality. .El .\" .Pp @@ -196,13 +219,23 @@ Meta-arguments are as follows: .It Ar dst Source/destination of the secure communication is specified as IPv4/v6 address. -The .Nm -utility does not consult hostname-to-address for arguments -.Ar src +can resolve a FQDN into numeric addresses. +If the FQDN resolves into multiple addresses, +.Nm +will install multiple SAD/SPD entries into the kernel +by trying all possible combinations. +.Fl 4 , +.Fl 6 and -.Ar dst . -They must be in numeric form. +.Fl n +restricts the address resolution of FQDN in certain ways. +.Fl 4 +and +.Fl 6 +restrict results into IPv4/v6 addresses only, respectively. +.Fl n +avoids FQDN resolution and requires addresses to be numeric addresses. .\" .Pp .It Ar protocol @@ -210,7 +243,7 @@ They must be in numeric form. is one of following: .Bl -tag -width Fl -compact .It Li esp -ESP based on rfc2405 +ESP based on rfc2406 .It Li esp-old ESP based on rfc1827 .It Li ah @@ -218,21 +251,24 @@ AH based on rfc2402 .It Li ah-old AH based on rfc1826 .It Li ipcomp -IPCOMP +IPComp .El .\" .Pp .It Ar spi -Security Parameter Index (SPI) for the SAD and the SPD. -It must be decimal number or hexadecimal number -You cannot use the set of SPI values in the range 0 through 255. -(with -.Li 0x -attached). +Security Parameter Index +.Pq SPI +for the SAD and the SPD. +.Ar spi +must be a decimal number, or a hexadecimal number with +.Dq Li 0x +prefix. +SPI values between 0 and 255 are reserved for future use by IANA +and they cannot be used. .\" .Pp .It Ar extensions -takes some of the following: +take some of the following: .Bl -tag -width Fl -compact .\" .It Fl m Ar mode @@ -283,62 +319,41 @@ Specify hard/soft life time duration of the SA. .It Ar algorithm .Bl -tag -width Fl -compact .It Fl E Ar ealgo Ar key -Specify an encryption algorithm. +Specify an encryption algorithm +.Ar ealgo +for ESP. +.It Xo +.Fl E Ar ealgo Ar key +.Fl A Ar aalgo Ar key +.Xc +Specify a encryption algorithm +.Ar ealgo , +as well as a payload authentication algorithm +.Ar aalgo , +for ESP. .It Fl A Ar aalgo Ar key -Specify an authentication algorithm. -If -.Fl A -is used with -.Ar protocol Li esp , -it will be treated as ESP payload authentication algorithm. +Specify an authentication algorithm for AH. .It Fl C Ar calgo Op Fl R -Specify compression algorithm. +Specify a compression algorithm for IPComp. If .Fl R -is not specified with -.Li ipcomp -line, the kernel will use well-known IPComp CPI -(compression parameter index) -on IPComp CPI field on packets, and -.Ar spi -field will be ignored. +is specified, .Ar spi -field is only for kernel internal use in this case. -.\"Therefore, compression protocol number will appear on IPComp CPI field. +field value will be used as the IPComp CPI +.Pq compression parameter index +on wire as is. If .Fl R -is used, -the value on -.Ar spi -field will appear on IPComp CPI field on outgoing packets. +is not specified, +the kernel will use well-known CPI on wire, and .Ar spi -field needs to be smaller than -.Li 0x10000 -in this case. +field will be used only as an index for kernel internal usage. .El .Pp -.Ar protocol Li esp -accepts -.Fl E -and -.Fl A . -.Ar protocol Li esp-old -accepts -.Fl E -only. -.Ar protocol Li ah -and -.Li ah-old -accept -.Fl A -only. -.Ar protocol Li ipcomp -accepts -.Fl C -only. -.Pp .Ar key -must be double-quoted character string or series of hexadecimal digits. +must be double-quoted character string, or a series of hexadecimal digits +preceded by +.Dq Li 0x . .Pp Possible values for .Ar ealgo , @@ -369,14 +384,11 @@ The square bracket around .Ar port is really necessary. They are not manpage metacharacters. -.Pp -The -.Nm -utility does not consult hostname-to-address for arguments +For FQDN resolution, the rules applicable to .Ar src and -.Ar dst . -They must be in numeric form. +.Ar dst +apply here as well. .\" .Pp .It Ar upperspec @@ -395,34 +407,38 @@ can be specified. stands for .Dq any protocol . Also you can use the protocol number. +You can specify a type and/or a code of ICMPv6 when +Upper-layer protocol is ICMPv6. +the specification can be placed after +.Li icmp6 . +A type is separated with a code by single comma. +A code must be specified anytime. +When a zero is specified, the kernel deals with it as a wildcard. +Note that the kernel can not distinguish a wildcard from that a type +of ICMPv6 is zero. +For example, the following means the policy doesn't require IPsec +for any inbound Neighbor Solicitation. +.Dl spdadd ::/0 ::/0 icmp6 135,0 -P in none ; .Pp NOTE: .Ar upperspec does not work against forwarding case at this moment, as it requires extra reassembly at forwarding node -(not implemented at this moment). +.Pq not implemented at this moment . We have many protocols in .Pa /etc/protocols , but protocols except of TCP, UDP and ICMP may not be suitable to use with IPsec. You have to consider and be careful to use them. -.Li icmp -.Li tcp -.Li udp -all protocols .\" .Pp .It Ar policy .Ar policy -is the one of following: -.Bd -literal -offset -.Xo -.Fl P Ar direction Li discard -.Xc -.Xo -.Fl P Ar direction Li none -.Xc -.Xo -.Fl P Ar direction Li ipsec Ar protocol/mode/src-dst/level +is the one of the following three formats: +.Bd -literal -offset indent +.It Fl P Ar direction Li discard +.It Fl P Ar direction Li none +.It Xo Fl P Ar direction Li ipsec +.Ar protocol/mode/src-dst/level Op ... .Xc .Ed .Pp @@ -439,6 +455,9 @@ means the packet matching indexes will be discarded. means that IPsec operation will not take place onto the packet. .Li ipsec means that IPsec operation will take place onto the packet. +The part of +.Ar protocol/mode/src-dst/level +specifies the rule how to process the packet. Either .Li ah , .Li esp @@ -480,7 +499,7 @@ If the SA is not available in every level, the kernel will request getting SA to the key exchange daemon. .Li default means the kernel consults to the system wide default against protocol you -specified, e.g.\& +specified, e.g. .Li esp_trans_deflev sysctl variable, when the kernel processes the packet. .Li use @@ -492,17 +511,29 @@ with the policy. .Li unique is the same to require. In addition, it allows the policy to bind with the unique out-bound SA. -If you use the SA by manual keying, +You just specify the policy level +.Li unique , +.Xr racoon 8 +will configure the SA for the policy. +If you configure the SA by manual keying for that policy, you can put the decimal number as the policy identifier after .Li unique separated by colon -.Sq \: +.Sq \&: like the following; .Li unique:number . +in order to bind this policy to the SA. .Li number must be between 1 and 32767. It corresponds to -.Ar extensions Fl u . +.Ar extensions Fl u +of the manual SA configuration. +When you want to use SA bundle, you can define multiple rules. +For example, if an IP header was followed by AH header followed by ESP header +followed by an upper layer protocol header, the rule +would be: +.Dl esp/transport//require ah/transport//require ; +The rule order is very important. .Pp Note that .Dq Li discard @@ -543,7 +574,8 @@ keyed-md5 128 ah: 96bit ICV (no document) keyed-sha1 160 ah: 96bit ICV (no document) 160 ah-old: 128bit ICV (no document) null 0 to 2048 for debugging -hmac-sha2-256 256 ah: 96bit ICV (no document) +hmac-sha2-256 256 ah: 96bit ICV + (draft-ietf-ipsec-ciph-sha-256-00) 256 ah-old: 128bit ICV (no document) hmac-sha2-384 384 ah: 96bit ICV (no document) 384 ah-old: 128bit ICV (no document) @@ -551,8 +583,8 @@ hmac-sha2-512 512 ah: 96bit ICV (no document) 512 ah-old: 128bit ICV (no document) hmac-ripemd160 160 ah: 96bit ICV (RFC2857) ah-old: 128bit ICV (no document) -aes-xcbc-mac 128 ah: 96bit ICV (RFC3566) - 128 ah-old: 128bit ICV (no document) +.\"aes-xcbc-mac 128 ah: 96bit ICV (RFC3566) +.\" 128 ah-old: 128bit ICV (no document) .Ed .Pp Followings are the list of encryption algorithms that can be used as @@ -567,13 +599,13 @@ parameter: algorithm keylen (bits) comment des-cbc 64 esp-old: rfc1829, esp: rfc2405 3des-cbc 192 rfc2451 -simple 0 to 2048 rfc2410 +null 0 to 2048 rfc2410 blowfish-cbc 40 to 448 rfc2451 cast128-cbc 40 to 128 rfc2451 -des-deriv 64 ipsec-ciph-des-derived-01 (expired) +des-deriv 64 ipsec-ciph-des-derived-01 3des-deriv 192 no document -rijndael-cbc 128/192/256 draft-ietf-ipsec-ciph-aes-cbc-00 -aes-ctr 160/224/288 draft-ietf-ipsec-ciph-aes-ctr-03 +rijndael-cbc 128/192/256 rfc3602 +.\"aes-ctr 160/224/288 draft-ietf-ipsec-ciph-aes-ctr-03 .Ed .Pp Note that the first 128 bits of a key for @@ -591,44 +623,58 @@ parameter: .Bd -literal -offset indent algorithm comment deflate rfc2394 -lzs rfc2395 .Ed .\" +.Sh RETURN VALUES +The command exits with 0 on success, and non-zero on errors. +.\" .Sh EXAMPLES .Bd -literal -offset -add 3ffe:501:4819::1 3ffe:501:481d::1 esp 123457 - -E des-cbc "ESP SA!!" ; +add 3ffe:501:4819::1 3ffe:501:481d::1 esp 123457 + -E des-cbc 0x3ffe05014819ffff ; -add 3ffe:501:4819::1 3ffe:501:481d::1 ah 123456 - -A hmac-sha1 "AH SA configuration!" ; +add -6 myhost.example.com yourhost.example.com ah 123456 + -A hmac-sha1 "AH SA configuration!" ; -add 10.0.11.41 10.0.11.33 esp 0x10001 - -E des-cbc "ESP with" - -A hmac-md5 "authentication!!" ; +add 10.0.11.41 10.0.11.33 esp 0x10001 + -E des-cbc 0x3ffe05014819ffff + -A hmac-md5 "authentication!!" ; -get 3ffe:501:4819::1 3ffe:501:481d::1 ah 123456 ; +get 3ffe:501:4819::1 3ffe:501:481d::1 ah 123456 ; flush ; dump esp ; -spdadd 10.0.11.41/32[21] 10.0.11.33/32[any] any - -P out ipsec esp/tunnel/192.168.0.1-192.168.1.2/require ; +spdadd 10.0.11.41/32[21] 10.0.11.33/32[any] any + -P out ipsec esp/tunnel/192.168.0.1-192.168.1.2/require ; .Ed .\" -.Sh RETURN VALUES -The command exits with 0 on success, and non-zero on errors. -.\" .Sh SEE ALSO .Xr ipsec_set_policy 3 , .Xr racoon 8 , .Xr sysctl 8 +.Rs +.%T "Changed manual key configuration for IPsec" +.%O "http://www.kame.net/newsletter/19991007/" +.%D "October 1999" +.Re .\" .Sh HISTORY The .Nm -utility first appeared in WIDE Hydrangea IPv6 protocol stack kit. +command first appeared in WIDE Hydrangea IPv6 protocol stack kit. The command was completely re-designed in June 1998. .\" -.\" .Sh BUGS +.Sh BUGS +.Nm +should report and handle syntax errors better. +.Pp +For IPsec gateway configuration, +.Ar src_range +and +.Ar dst_range +with TCP/UDP port number do not work, as the gateway does not reassemble +packets +.Pq cannot inspect upper-layer headers . diff --git a/usr.sbin/setkey/setkey.c b/usr.sbin/setkey/setkey.c index b0d7596..5bdd6df 100644 --- a/usr.sbin/setkey/setkey.c +++ b/usr.sbin/setkey/setkey.c @@ -1,5 +1,5 @@ /* $FreeBSD$ */ -/* $KAME: setkey.c,v 1.18 2001/05/08 04:36:39 itojun Exp $ */ +/* $KAME: setkey.c,v 1.28 2003/06/27 07:15:45 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. @@ -58,7 +58,7 @@ int main __P((int, char **)); int get_supported __P((void)); void sendkeyshort __P((u_int)); void promisc __P((void)); -int sendkeymsg __P((void)); +int sendkeymsg __P((char *, size_t)); int postproc __P((struct sadb_msg *, int)); const char *numstr __P((int)); void shortdump_hdr __P((void)); @@ -75,18 +75,12 @@ int so; int f_forever = 0; int f_all = 0; -int f_debug = 0; int f_verbose = 0; int f_mode = 0; int f_cmddump = 0; int f_policy = 0; int f_hexdump = 0; int f_tflag = 0; -char *pname; - -u_char m_buf[BUFSIZ]; -u_int m_len; - static time_t thiszone; extern int lineno; @@ -96,12 +90,12 @@ extern int parse __P((FILE **)); void usage() { - printf("usage:\t%s [-dv] -c\n", pname); - printf("\t%s [-dv] -f (file)\n", pname); - printf("\t%s [-Padlv] -D\n", pname); - printf("\t%s [-Pdv] -F\n", pname); - printf("\t%s [-h] -x\n", pname); - pfkey_close(so); + + printf("usage: setkey [-v] -c\n"); + printf(" setkey [-v] -f filename\n"); + printf(" setkey [-Palv] -D\n"); + printf(" setkey [-Pv] -F\n"); + printf(" setkey [-h] -x\n"); exit(1); } @@ -113,8 +107,6 @@ main(ac, av) FILE *fp = stdin; int c; - pname = *av; - if (ac == 1) { usage(); /* NOTREACHED */ @@ -157,9 +149,6 @@ main(ac, av) case 'P': f_policy = 1; break; - case 'd': - f_debug = 1; - break; case 'v': f_verbose = 1; break; @@ -169,13 +158,18 @@ main(ac, av) } } + so = pfkey_open(); + if (so < 0) { + perror("pfkey_open"); + exit(1); + } + switch (f_mode) { case MODE_CMDDUMP: sendkeyshort(f_policy ? SADB_X_SPDDUMP: SADB_DUMP); break; case MODE_CMDFLUSH: sendkeyshort(f_policy ? SADB_X_SPDFLUSH: SADB_FLUSH); - pfkey_close(so); break; case MODE_SCRIPT: if (get_supported() < 0) { @@ -199,16 +193,6 @@ main(ac, av) int get_supported() { - int so; - - if ((so = pfkey_open()) < 0) { - perror("pfkey_open"); - return -1; - } - - /* debug mode ? */ - if (f_debug) - return 0; if (pfkey_send_register(so, SADB_SATYPE_UNSPEC) < 0) return -1; @@ -223,20 +207,18 @@ void sendkeyshort(type) u_int type; { - struct sadb_msg *m_msg = (struct sadb_msg *)m_buf; - - m_len = sizeof(struct sadb_msg); + struct sadb_msg msg; - m_msg->sadb_msg_version = PF_KEY_V2; - m_msg->sadb_msg_type = type; - m_msg->sadb_msg_errno = 0; - m_msg->sadb_msg_satype = SADB_SATYPE_UNSPEC; - m_msg->sadb_msg_len = PFKEY_UNIT64(m_len); - m_msg->sadb_msg_reserved = 0; - m_msg->sadb_msg_seq = 0; - m_msg->sadb_msg_pid = getpid(); + msg.sadb_msg_version = PF_KEY_V2; + msg.sadb_msg_type = type; + msg.sadb_msg_errno = 0; + msg.sadb_msg_satype = SADB_SATYPE_UNSPEC; + msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg)); + msg.sadb_msg_reserved = 0; + msg.sadb_msg_seq = 0; + msg.sadb_msg_pid = getpid(); - sendkeymsg(); + sendkeymsg((char *)&msg, sizeof(msg)); return; } @@ -244,27 +226,20 @@ sendkeyshort(type) void promisc() { - struct sadb_msg *m_msg = (struct sadb_msg *)m_buf; + struct sadb_msg msg; u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */ - int so, l; - - m_len = sizeof(struct sadb_msg); - - m_msg->sadb_msg_version = PF_KEY_V2; - m_msg->sadb_msg_type = SADB_X_PROMISC; - m_msg->sadb_msg_errno = 0; - m_msg->sadb_msg_satype = 1; - m_msg->sadb_msg_len = PFKEY_UNIT64(m_len); - m_msg->sadb_msg_reserved = 0; - m_msg->sadb_msg_seq = 0; - m_msg->sadb_msg_pid = getpid(); - - if ((so = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) < 0) { - err(1, "socket(PF_KEY)"); - /*NOTREACHED*/ - } - - if ((l = send(so, m_buf, m_len, 0)) < 0) { + ssize_t l; + + msg.sadb_msg_version = PF_KEY_V2; + msg.sadb_msg_type = SADB_X_PROMISC; + msg.sadb_msg_errno = 0; + msg.sadb_msg_satype = 1; + msg.sadb_msg_len = PFKEY_UNIT64(sizeof(msg)); + msg.sadb_msg_reserved = 0; + msg.sadb_msg_seq = 0; + msg.sadb_msg_pid = getpid(); + + if ((l = send(so, &msg, sizeof(msg), 0)) < 0) { err(1, "send"); /*NOTREACHED*/ } @@ -301,7 +276,7 @@ promisc() } /* adjust base pointer for promisc mode */ if (base->sadb_msg_type == SADB_X_PROMISC) { - if (sizeof(*base) < l) + if ((ssize_t)sizeof(*base) < l) base++; else base = NULL; @@ -315,19 +290,14 @@ promisc() } int -sendkeymsg() +sendkeymsg(buf, len) + char *buf; + size_t len; { - int so; - u_char rbuf[1024 * 32]; /* XXX: Enough ? Should I do MSG_PEEK ? */ - int l; + ssize_t l; struct sadb_msg *msg; - if ((so = pfkey_open()) < 0) { - perror("pfkey_open"); - return -1; - } - { struct timeval tv; tv.tv_sec = 1; @@ -342,11 +312,23 @@ sendkeymsg() shortdump_hdr(); again: if (f_verbose) { - kdebug_sadb((struct sadb_msg *)m_buf); + kdebug_sadb((struct sadb_msg *)buf); printf("\n"); } + if (f_hexdump) { + int i; + for (i = 0; i < len; i++) { + if (i % 16 == 0) + printf("%08x: ", i); + printf("%02x ", buf[i] & 0xff); + if (i % 16 == 15) + printf("\n"); + } + if (len % 16) + printf("\n"); + } - if ((l = send(so, m_buf, m_len, 0)) < 0) { + if ((l = send(so, buf, len, 0)) < 0) { perror("send"); goto end; } @@ -378,7 +360,6 @@ again: } end: - pfkey_close(so); return(0); } diff --git a/usr.sbin/setkey/token.l b/usr.sbin/setkey/token.l index 5f73594..f065fd3 100644 --- a/usr.sbin/setkey/token.l +++ b/usr.sbin/setkey/token.l @@ -1,5 +1,5 @@ /* $FreeBSD$ */ -/* $KAME: token.l,v 1.21 2001/05/18 05:35:01 sakane Exp $ */ +/* $KAME: token.l,v 1.43 2003/07/25 09:35:28 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. @@ -46,30 +46,12 @@ #include <string.h> #include <unistd.h> #include <errno.h> +#include <netdb.h> + #include "vchar.h" -#ifdef __NetBSD__ -#include "parse.h" -#else #include "y.tab.h" -#endif - -#define DECHO \ - if (f_debug) {printf("<%d>", yy_start); ECHO ; printf("\n"); } - -#define CMDARG \ -{ \ - char *__buf__ = strdup(yytext), *__p__; \ - for (__p__ = __buf__; *__p__ != NULL; __p__++) \ - if (*__p__ == '\n' || *__p__ == '\t') \ - *__p__ = ' '; \ - strcat(cmdarg, __buf__); \ - free(__buf__); \ -} - -#define PREPROC DECHO CMDARG int lineno = 1; -char cmdarg[8192]; /* XXX: BUFSIZ is the better ? */ extern u_char m_buf[BUFSIZ]; extern u_int m_len; @@ -81,7 +63,6 @@ void yyerror __P((const char *s)); extern void parse_init __P((void)); int parse __P((FILE **)); int yyparse __P((void)); - %} /* common section */ @@ -90,199 +71,177 @@ ws [ \t]+ digit [0-9] letter [0-9A-Za-z] hexdigit [0-9A-Fa-f] -/*octet (([01]?{digit}?{digit})|((2([0-4]{digit}))|(25[0-5])))*/ -special [()+\|\?\*,] dot \. -comma \, hyphen \- -colon \: slash \/ -bcl \{ -ecl \} blcl \[ elcl \] -percent \% semi \; -usec {dot}{digit}{1,6} comment \#.* -ccomment "/*" -bracketstring \<[^>]*\> quotedstring \"[^"]*\" decstring {digit}+ -hexpair {hexdigit}{hexdigit} hexstring 0[xX]{hexdigit}+ -octetstring {octet}({dot}{octet})+ ipaddress [a-fA-F0-9:]([a-fA-F0-9:\.]*|[a-fA-F0-9:\.]*%[a-zA-Z0-9]*) ipaddrmask {slash}{digit}{1,3} -ipaddrport {blcl}{decstring}{elcl} -keyword {letter}{letter}+ name {letter}(({letter}|{digit}|{hyphen})*({letter}|{digit}))* hostname {name}(({dot}{name})+{dot}?)? -%s S_PL +%s S_PL S_AUTHALG S_ENCALG %% -add { PREPROC; return(ADD); } -delete { PREPROC; return(DELETE); } -deleteall { PREPROC; return(DELETEALL); } -get { PREPROC; return(GET); } -flush { PREPROC; return(FLUSH); } -dump { PREPROC; return(DUMP); } +add { return(ADD); } +delete { return(DELETE); } +deleteall { return(DELETEALL); } +get { return(GET); } +flush { return(FLUSH); } +dump { return(DUMP); } /* for management SPD */ -spdadd { PREPROC; return(SPDADD); } -spddelete { PREPROC; return(SPDDELETE); } -spddump { PREPROC; return(SPDDUMP); } -spdflush { PREPROC; return(SPDFLUSH); } -{hyphen}P { BEGIN S_PL; PREPROC; return(F_POLICY); } -<S_PL>[a-zA-Z0-9:\.\-_/ \n\t][a-zA-Z0-9:\.\-_/ \n\t]* { - yymore(); - - /* count up for nl */ - { - char *p; - for (p = yytext; *p != NULL; p++) - if (*p == '\n') - lineno++; - } - - yylval.val.len = strlen(yytext); - yylval.val.buf = strdup(yytext); - - return(PL_REQUESTS); -} -<S_PL>{semi} { PREPROC; BEGIN INITIAL; return(EOT); } +spdadd { return(SPDADD); } +spddelete { return(SPDDELETE); } +spddump { return(SPDDUMP); } +spdflush { return(SPDFLUSH); } +tagged { return(TAGGED); } +{hyphen}P { BEGIN S_PL; return(F_POLICY); } +<S_PL>[a-zA-Z0-9:\.\-_/ \n\t][a-zA-Z0-9:\.%\-_/ \n\t]* { + yymore(); + + /* count up for nl */ + { + char *p; + for (p = yytext; *p != NULL; p++) + if (*p == '\n') + lineno++; + } + + yylval.val.len = strlen(yytext); + yylval.val.buf = strdup(yytext); + if (!yylval.val.buf) + yyfatal("insufficient memory"); + + return(PL_REQUESTS); + } +<S_PL>{semi} { BEGIN INITIAL; return(EOT); } + + /* address resolution flags */ +{hyphen}[n46][n46]* { + yylval.val.len = strlen(yytext); + yylval.val.buf = strdup(yytext); + if (!yylval.val.buf) + yyfatal("insufficient memory"); + return(F_AIFLAGS); + } /* security protocols */ -ah { PREPROC; yylval.num = 0; return(PR_AH); } -esp { PREPROC; yylval.num = 0; return(PR_ESP); } -ah-old { PREPROC; yylval.num = 1; return(PR_AH); } -esp-old { PREPROC; yylval.num = 1; return(PR_ESP); } -ipcomp { PREPROC; yylval.num = 0; return(PR_IPCOMP); } +ah { yylval.num = 0; return(PR_AH); } +esp { yylval.num = 0; return(PR_ESP); } +ah-old { yylval.num = 1; return(PR_AH); } +esp-old { yylval.num = 1; return(PR_ESP); } +ipcomp { yylval.num = 0; return(PR_IPCOMP); } /* authentication alogorithm */ -{hyphen}A { PREPROC; return(F_AUTH); } -hmac-md5 { PREPROC; yylval.num = SADB_AALG_MD5HMAC; return(ALG_AUTH); } -hmac-sha1 { PREPROC; yylval.num = SADB_AALG_SHA1HMAC; return(ALG_AUTH); } -keyed-md5 { PREPROC; yylval.num = SADB_X_AALG_MD5; return(ALG_AUTH); } -keyed-sha1 { PREPROC; yylval.num = SADB_X_AALG_SHA; return(ALG_AUTH); } -hmac-sha2-256 { PREPROC; yylval.num = SADB_X_AALG_SHA2_256; return(ALG_AUTH); } -hmac-sha2-384 { PREPROC; yylval.num = SADB_X_AALG_SHA2_384; return(ALG_AUTH); } -hmac-sha2-512 { PREPROC; yylval.num = SADB_X_AALG_SHA2_512; return(ALG_AUTH); } -hmac-ripemd160 { PREPROC; yylval.num = SADB_X_AALG_RIPEMD160HMAC; return(ALG_AUTH); } -aes-xcbc-mac { PREPROC; yylval.num = SADB_X_AALG_AES_XCBC_MAC; return(ALG_AUTH); } -null { PREPROC; yylval.num = SADB_X_AALG_NULL; return(ALG_AUTH); } +{hyphen}A { BEGIN S_AUTHALG; return(F_AUTH); } +<S_AUTHALG>hmac-md5 { yylval.num = SADB_AALG_MD5HMAC; BEGIN INITIAL; return(ALG_AUTH); } +<S_AUTHALG>hmac-sha1 { yylval.num = SADB_AALG_SHA1HMAC; BEGIN INITIAL; return(ALG_AUTH); } +<S_AUTHALG>keyed-md5 { yylval.num = SADB_X_AALG_MD5; BEGIN INITIAL; return(ALG_AUTH); } +<S_AUTHALG>keyed-sha1 { yylval.num = SADB_X_AALG_SHA; BEGIN INITIAL; return(ALG_AUTH); } +<S_AUTHALG>hmac-sha2-256 { yylval.num = SADB_X_AALG_SHA2_256; BEGIN INITIAL; return(ALG_AUTH); } +<S_AUTHALG>hmac-sha2-384 { yylval.num = SADB_X_AALG_SHA2_384; BEGIN INITIAL; return(ALG_AUTH); } +<S_AUTHALG>hmac-sha2-512 { yylval.num = SADB_X_AALG_SHA2_512; BEGIN INITIAL; return(ALG_AUTH); } +<S_AUTHALG>hmac-ripemd160 { yylval.num = SADB_X_AALG_RIPEMD160HMAC; BEGIN INITIAL; return(ALG_AUTH); } +<S_AUTHALG>aes-xcbc-mac { yylval.num = SADB_X_AALG_AES_XCBC_MAC; BEGIN INITIAL; return(ALG_AUTH); } +<S_AUTHALG>null { yylval.num = SADB_X_AALG_NULL; BEGIN INITIAL; return(ALG_AUTH_NOKEY); } /* encryption alogorithm */ -{hyphen}E { PREPROC; return(F_ENC); } -des-cbc { PREPROC; yylval.num = SADB_EALG_DESCBC; return(ALG_ENC); } -3des-cbc { PREPROC; yylval.num = SADB_EALG_3DESCBC; return(ALG_ENC); } -simple { PREPROC; yylval.num = SADB_EALG_NULL; return(ALG_ENC); } -blowfish-cbc { PREPROC; yylval.num = SADB_X_EALG_BLOWFISHCBC; return(ALG_ENC); } -cast128-cbc { PREPROC; yylval.num = SADB_X_EALG_CAST128CBC; return(ALG_ENC); } -des-deriv { PREPROC; yylval.num = SADB_EALG_DESCBC; return(ALG_ENC_DESDERIV); } -des-32iv { PREPROC; yylval.num = SADB_EALG_DESCBC; return(ALG_ENC_DES32IV); } -rijndael-cbc { PREPROC; yylval.num = SADB_X_EALG_RIJNDAELCBC; return(ALG_ENC); } -aes-ctr { PREPROC; yylval.num = SADB_X_EALG_AESCTR; return(ALG_ENC); } +{hyphen}E { BEGIN S_ENCALG; return(F_ENC); } +<S_ENCALG>des-cbc { yylval.num = SADB_EALG_DESCBC; BEGIN INITIAL; return(ALG_ENC); } +<S_ENCALG>3des-cbc { yylval.num = SADB_EALG_3DESCBC; BEGIN INITIAL; return(ALG_ENC); } +<S_ENCALG>null { yylval.num = SADB_EALG_NULL; BEGIN INITIAL; return(ALG_ENC_NOKEY); } +<S_ENCALG>simple { yylval.num = SADB_EALG_NULL; BEGIN INITIAL; return(ALG_ENC_OLD); } +<S_ENCALG>blowfish-cbc { yylval.num = SADB_X_EALG_BLOWFISHCBC; BEGIN INITIAL; return(ALG_ENC); } +<S_ENCALG>cast128-cbc { yylval.num = SADB_X_EALG_CAST128CBC; BEGIN INITIAL; return(ALG_ENC); } +<S_ENCALG>des-deriv { yylval.num = SADB_EALG_DESCBC; BEGIN INITIAL; return(ALG_ENC_DESDERIV); } +<S_ENCALG>des-32iv { yylval.num = SADB_EALG_DESCBC; BEGIN INITIAL; return(ALG_ENC_DES32IV); } +<S_ENCALG>rijndael-cbc { yylval.num = SADB_X_EALG_RIJNDAELCBC; BEGIN INITIAL; return(ALG_ENC); } +<S_ENCALG>aes-ctr { yylval.num = SADB_X_EALG_AESCTR; BEGIN INITIAL; return(ALG_ENC); } /* compression algorithms */ -{hyphen}C { PREPROC; return(F_COMP); } -oui { PREPROC; yylval.num = SADB_X_CALG_OUI; return(ALG_COMP); } -deflate { PREPROC; yylval.num = SADB_X_CALG_DEFLATE; return(ALG_COMP); } -lzs { PREPROC; yylval.num = SADB_X_CALG_LZS; return(ALG_COMP); } -{hyphen}R { PREPROC; return(F_RAWCPI); } +{hyphen}C { return(F_COMP); } +oui { yylval.num = SADB_X_CALG_OUI; return(ALG_COMP); } +deflate { yylval.num = SADB_X_CALG_DEFLATE; return(ALG_COMP); } +lzs { yylval.num = SADB_X_CALG_LZS; return(ALG_COMP); } +{hyphen}R { return(F_RAWCPI); } /* extension */ -{hyphen}m { PREPROC; return(F_MODE); } -transport { PREPROC; yylval.num = IPSEC_MODE_TRANSPORT; return(MODE); } -tunnel { PREPROC; yylval.num = IPSEC_MODE_TUNNEL; return(MODE); } -{hyphen}u { PREPROC; return(F_REQID); } -{hyphen}f { PREPROC; return(F_EXT); } -random-pad { PREPROC; yylval.num = SADB_X_EXT_PRAND; return(EXTENSION); } -seq-pad { PREPROC; yylval.num = SADB_X_EXT_PSEQ; return(EXTENSION); } -zero-pad { PREPROC; yylval.num = SADB_X_EXT_PZERO; return(EXTENSION); } -nocyclic-seq { PREPROC; return(NOCYCLICSEQ); } -{hyphen}r { PREPROC; return(F_REPLAY); } -{hyphen}lh { PREPROC; return(F_LIFETIME_HARD); } -{hyphen}ls { PREPROC; return(F_LIFETIME_SOFT); } +{hyphen}m { return(F_MODE); } +transport { yylval.num = IPSEC_MODE_TRANSPORT; return(MODE); } +tunnel { yylval.num = IPSEC_MODE_TUNNEL; return(MODE); } +{hyphen}u { return(F_REQID); } +{hyphen}f { return(F_EXT); } +random-pad { yylval.num = SADB_X_EXT_PRAND; return(EXTENSION); } +seq-pad { yylval.num = SADB_X_EXT_PSEQ; return(EXTENSION); } +zero-pad { yylval.num = SADB_X_EXT_PZERO; return(EXTENSION); } +nocyclic-seq { return(NOCYCLICSEQ); } +{hyphen}r { return(F_REPLAY); } +{hyphen}lh { return(F_LIFETIME_HARD); } +{hyphen}ls { return(F_LIFETIME_SOFT); } /* ... */ -any { PREPROC; return(ANY); } -{ws} { PREPROC; } +any { return(ANY); } +{ws} { } {nl} { lineno++; } {comment} -{semi} { PREPROC; return(EOT); } +{semi} { return(EOT); } + + /* for address parameters: /prefix, [port] */ +{slash} { return SLASH; } +{blcl} { return BLCL; } +{elcl} { return ELCL; } /* parameter */ {decstring} { char *bp; - PREPROC; - yylval.num = strtoul(yytext, &bp, 10); + yylval.ulnum = strtoul(yytext, &bp, 10); return(DECSTRING); } -{ipaddress} { - PREPROC; - - yylval.val.len = yyleng; - yylval.val.buf = strdup(yytext); - - return(ADDRESS); - } - -{ipaddrmask} { - PREPROC; - yytext++; - yylval.num = atoi(yytext); - return(PREFIX); - } - -{ipaddrport} { - char *p = yytext; - PREPROC; - while (*++p != ']') ; - *p = NULL; - yytext++; - yylval.num = atoi(yytext); - return(PORT); - } - -{blcl}any{elcl} { - PREPROC; - return(PORTANY); - } - {hexstring} { - int len = yyleng - 2; /* (str - "0x") */ - PREPROC; - yylval.val.len = (len & 1) + (len / 2); - /* fixed string if length is odd. */ - if (len & 1) { - yytext[1] = '0'; - yylval.val.buf = strdup(yytext + 1); - } else - yylval.val.buf = strdup(yytext + 2); + yylval.val.buf = strdup(yytext + 2); + if (!yylval.val.buf) + yyfatal("insufficient memory"); + yylval.val.len = strlen(yylval.val.buf); return(HEXSTRING); } {quotedstring} { char *p = yytext; - PREPROC; while (*++p != '"') ; *p = NULL; yytext++; yylval.val.len = yyleng - 2; yylval.val.buf = strdup(yytext); + if (!yylval.val.buf) + yyfatal("insufficient memory"); return(QUOTEDSTRING); } -[a-z0-9.\-]* { +[A-Za-z0-9:][A-Za-z0-9:%\.-]* { + yylval.val.len = yyleng; + yylval.val.buf = strdup(yytext); + if (!yylval.val.buf) + yyfatal("insufficient memory"); + return(STRING); + } + +[0-9,]+ { yylval.val.len = yyleng; yylval.val.buf = strdup(yytext); + if (!yylval.val.buf) + yyfatal("insufficient memory"); return(STRING); } |