diff options
Diffstat (limited to 'ipsec-tools/src/setkey/parse.y')
-rw-r--r-- | ipsec-tools/src/setkey/parse.y | 1670 |
1 files changed, 1670 insertions, 0 deletions
diff --git a/ipsec-tools/src/setkey/parse.y b/ipsec-tools/src/setkey/parse.y new file mode 100644 index 00000000..fa3c45d3 --- /dev/null +++ b/ipsec-tools/src/setkey/parse.y @@ -0,0 +1,1670 @@ +/* $NetBSD: parse.y,v 1.14 2010/12/03 14:32:52 tteras 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. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +%{ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <net/pfkeyv2.h> +#include PATH_IPSEC_H +#include <arpa/inet.h> + +#include <string.h> +#include <unistd.h> +#include <stdio.h> +#include <netdb.h> +#include <ctype.h> +#include <errno.h> +#include <stdlib.h> + +#include "libpfkey.h" +#include "vchar.h" +#include "extern.h" + +#define DEFAULT_NATT_PORT 4500 + +#ifndef UDP_ENCAP_ESPINUDP +#define UDP_ENCAP_ESPINUDP 2 +#endif + +#define ATOX(c) \ + (isdigit((int)c) ? (c - '0') : \ + (isupper((int)c) ? (c - 'A' + 10) : (c - 'a' + 10))) + +u_int32_t p_spi; +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; +const char *p_key_enc; +const char *p_key_auth; +time_t p_lt_hard, p_lt_soft; +size_t p_lb_hard, p_lb_soft; + +struct security_ctx { + u_int8_t doi; + u_int8_t alg; + u_int16_t len; + char *buf; +}; + +struct security_ctx sec_ctx; + +static u_int p_natt_type; +static struct addrinfo * p_natt_oa = NULL; + +static int p_aiflags = 0, p_aifamily = PF_UNSPEC; + +static struct addrinfo *parse_addr __P((char *, char *)); +static int fix_portstr __P((int, vchar_t *, vchar_t *, vchar_t *)); +static int setvarbuf __P((char *, int *, struct sadb_ext *, int, + const void *, int)); +void parse_init __P((void)); +void free_buffer __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_spdaddr_tag __P((unsigned int, char *, vchar_t *)); +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 *)); +%} + +%union { + int num; + unsigned long ulnum; + vchar_t val; + struct addrinfo *res; +} + +%token EOT SLASH BLCL ELCL +%token ADD GET DELETE DELETEALL FLUSH DUMP EXIT +%token PR_ESP PR_AH PR_IPCOMP PR_ESPUDP PR_TCP +%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_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 F_LIFEBYTE_HARD F_LIFEBYTE_SOFT +%token DECSTRING QUOTEDSTRING HEXSTRING STRING ANY + /* SPD management */ +%token SPDADD SPDUPDATE SPDDELETE SPDDUMP SPDFLUSH +%token F_POLICY PL_REQUESTS +%token F_AIFLAGS +%token TAGGED +%token SECURITY_CTX + +%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 PR_ESPUDP PR_TCP +%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 ipandport + +%% +commands + : /*NOTHING*/ + | commands command + { + free_buffer(); + parse_init(); + } + ; + +command + : add_command + | get_command + | delete_command + | deleteall_command + | flush_command + | dump_command + | exit_command + | spdadd_command + | spdupdate_command + | spddelete_command + | spddump_command + | spdflush_command + ; + /* commands concerned with management, there is in tail of this file. */ + + /* add command */ +add_command + : ADD ipaddropts ipandport ipandport 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 ipaddropts ipandport ipandport 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 obsolete"); + + status = setkeymsg_addr(SADB_DELETE, $5, $3, $4, 0); + if (status < 0) + return -1; + } + ; + + /* deleteall command */ +deleteall_command + : DELETEALL ipaddropts ipaddr ipaddr protocol_spec EOT + { +#ifndef __linux__ + if (setkeymsg_addr(SADB_DELETE, $5, $3, $4, 1) < 0) + return -1; +#else /* __linux__ */ + /* linux strictly adheres to RFC2367, and returns + * an error if we send an SADB_DELETE request without + * an SPI. Therefore, we must first retrieve a list + * of SPIs for all matching SADB entries, and then + * delete each one separately. */ + u_int32_t *spi; + int i, n; + + spi = sendkeymsg_spigrep($5, $3, $4, &n); + for (i = 0; i < n; i++) { + p_spi = spi[i]; + if (setkeymsg_addr(SADB_DELETE, + $5, $3, $4, 0) < 0) + return -1; + } + free(spi); +#endif /* __linux__ */ + } + ; + + /* get command */ +get_command + : GET ipaddropts ipandport ipandport protocol_spec spi extension_spec EOT + { + int status; + + if (p_mode != IPSEC_MODE_ANY) + yyerror("WARNING: mode is obsolete"); + + status = setkeymsg_addr(SADB_GET, $5, $3, $4, 0); + if (status < 0) + return -1; + } + ; + + /* flush */ +flush_command + : FLUSH protocol_spec EOT + { + struct sadb_msg msg; + setkeymsg0(&msg, SADB_FLUSH, $2, sizeof(msg)); + sendkeymsg((char *)&msg, sizeof(msg)); + } + ; + + /* dump */ +dump_command + : DUMP protocol_spec EOT + { + struct sadb_msg msg; + setkeymsg0(&msg, SADB_DUMP, $2, sizeof(msg)); + sendkeymsg((char *)&msg, sizeof(msg)); + } + ; + +protocol_spec + : /*NOTHING*/ + { + $$ = SADB_SATYPE_UNSPEC; + } + | PR_ESP + { + $$ = SADB_SATYPE_ESP; + if ($1 == 1) + p_ext |= SADB_X_EXT_OLD; + else + p_ext &= ~SADB_X_EXT_OLD; + } + | PR_AH + { + $$ = SADB_SATYPE_AH; + if ($1 == 1) + p_ext |= SADB_X_EXT_OLD; + else + p_ext &= ~SADB_X_EXT_OLD; + } + | PR_IPCOMP + { + $$ = SADB_X_SATYPE_IPCOMP; + } + | PR_ESPUDP + { + $$ = SADB_SATYPE_ESP; + p_ext &= ~SADB_X_EXT_OLD; + p_natt_oa = 0; + p_natt_type = UDP_ENCAP_ESPINUDP; + } + | PR_ESPUDP ipaddr + { + $$ = SADB_SATYPE_ESP; + p_ext &= ~SADB_X_EXT_OLD; + p_natt_oa = $2; + p_natt_type = UDP_ENCAP_ESPINUDP; + } + | PR_TCP + { +#ifdef SADB_X_SATYPE_TCPSIGNATURE + $$ = SADB_X_SATYPE_TCPSIGNATURE; +#endif + } + ; + +spi + : DECSTRING { p_spi = $1; } + | HEXSTRING + { + char *ep; + unsigned long v; + + ep = NULL; + v = strtoul($1.buf, &ep, 16); + if (!ep || *ep) { + yyerror("invalid SPI"); + return -1; + } + if (v & ~0xffffffff) { + yyerror("SPI too big."); + return -1; + } + + p_spi = v; + } + ; + +algorithm_spec + : esp_spec + | ah_spec + | ipcomp_spec + ; + +esp_spec + : F_ENC enc_alg F_AUTH auth_alg + | F_ENC enc_alg + ; + +ah_spec + : F_AUTH auth_alg + ; + +ipcomp_spec + : 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_NOKEY { + if ($1 < 0) { + yyerror("unsupported algorithm"); + return -1; + } + p_alg_enc = $1; + + p_key_enc_len = 0; + p_key_enc = ""; + if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT, + p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) { + yyerror(ipsec_strerror()); + return -1; + } + } + | ALG_ENC key_string { + if ($1 < 0) { + yyerror("unsupported algorithm"); + return -1; + } + p_alg_enc = $1; + + 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; + } + } + | ALG_ENC_OLD { + if ($1 < 0) { + yyerror("unsupported algorithm"); + return -1; + } + yyerror("WARNING: obsolete algorithm"); + p_alg_enc = $1; + + p_key_enc_len = 0; + p_key_enc = ""; + if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT, + p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) { + yyerror(ipsec_strerror()); + return -1; + } + } + | ALG_ENC_DESDERIV key_string + { + 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; + } + } + | ALG_ENC_DES32IV key_string + { + 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) { + yyerror(ipsec_strerror()); + return -1; + } + } + ; + +auth_alg + : ALG_AUTH key_string { + if ($1 < 0) { + yyerror("unsupported algorithm"); + return -1; + } + p_alg_auth = $1; + + p_key_auth_len = $2.len; + p_key_auth = $2.buf; +#ifdef SADB_X_AALG_TCP_MD5 + if (p_alg_auth == SADB_X_AALG_TCP_MD5) { + if ((p_key_auth_len < 1) || + (p_key_auth_len > 80)) + return -1; + } else +#endif + { + if (ipsec_check_keylen(SADB_EXT_SUPPORTED_AUTH, + 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 + { + $$ = $1; + } + | HEXSTRING + { + caddr_t pp_key; + caddr_t bp; + caddr_t yp = $1.buf; + int l; + + l = strlen(yp) % 2 + strlen(yp) / 2; + if ((pp_key = malloc(l)) == 0) { + yyerror("not enough core"); + return -1; + } + 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++; + } + + $$.len = l; + $$.buf = pp_key; + } + ; + +extension_spec + : /*NOTHING*/ + | extension_spec extension + ; + +extension + : F_EXT EXTENSION { p_ext |= $2; } + | F_EXT NOCYCLICSEQ { p_ext &= ~SADB_X_EXT_CYCSEQ; } + | F_MODE MODE { p_mode = $2; } + | F_MODE ANY { p_mode = IPSEC_MODE_ANY; } + | F_REQID DECSTRING { p_reqid = $2; } + | F_REPLAY DECSTRING + { + if ((p_ext & SADB_X_EXT_OLD) != 0) { + yyerror("replay prevention cannot be used with " + "ah/esp-old"); + return -1; + } + p_replay = $2; + } + | F_LIFETIME_HARD DECSTRING { p_lt_hard = $2; } + | F_LIFETIME_SOFT DECSTRING { p_lt_soft = $2; } + | F_LIFEBYTE_HARD DECSTRING { p_lb_hard = $2; } + | F_LIFEBYTE_SOFT DECSTRING { p_lb_soft = $2; } + | SECURITY_CTX DECSTRING DECSTRING QUOTEDSTRING { + sec_ctx.doi = $2; + sec_ctx.alg = $3; + sec_ctx.len = $4.len+1; + sec_ctx.buf = $4.buf; + } + ; + + /* definition about command for SPD management */ + /* spdadd */ +spdadd_command + /* XXX merge with spdupdate ??? */ + : SPDADD ipaddropts STRING prefix portstr STRING prefix portstr upper_spec upper_misc_spec context_spec policy_spec EOT + { + int status; + struct addrinfo *src, *dst; + +#ifdef HAVE_PFKEY_POLICY_PRIORITY + last_msg_type = SADB_X_SPDADD; +#endif + + /* fixed port fields if ulp is icmp */ + if (fix_portstr($9, &$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, &$12, + src, $4, dst, $7); + freeaddrinfo(src); + freeaddrinfo(dst); + if (status < 0) + return -1; + } + | SPDADD TAGGED QUOTEDSTRING policy_spec EOT + { + int status; + + status = setkeymsg_spdaddr_tag(SADB_X_SPDADD, + $3.buf, &$4); + if (status < 0) + return -1; + } + ; + +spdupdate_command + /* XXX merge with spdadd ??? */ + : SPDUPDATE ipaddropts STRING prefix portstr STRING prefix portstr upper_spec upper_misc_spec context_spec policy_spec EOT + { + int status; + struct addrinfo *src, *dst; + +#ifdef HAVE_PFKEY_POLICY_PRIORITY + last_msg_type = SADB_X_SPDUPDATE; +#endif + + /* fixed port fields if ulp is icmp */ + if (fix_portstr($9, &$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_SPDUPDATE, $9, &$12, + src, $4, dst, $7); + freeaddrinfo(src); + freeaddrinfo(dst); + if (status < 0) + return -1; + } + | SPDUPDATE TAGGED QUOTEDSTRING policy_spec EOT + { + int status; + + status = setkeymsg_spdaddr_tag(SADB_X_SPDUPDATE, + $3.buf, &$4); + if (status < 0) + return -1; + } + ; + +spddelete_command + : SPDDELETE ipaddropts STRING prefix portstr STRING prefix portstr upper_spec upper_misc_spec context_spec policy_spec EOT + { + int status; + struct addrinfo *src, *dst; + + /* fixed port fields if ulp is icmp */ + if (fix_portstr($9, &$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, &$12, + src, $4, dst, $7); + freeaddrinfo(src); + freeaddrinfo(dst); + if (status < 0) + return -1; + } + ; + +spddump_command: + SPDDUMP EOT + { + struct sadb_msg msg; + setkeymsg0(&msg, SADB_X_SPDDUMP, SADB_SATYPE_UNSPEC, + sizeof(msg)); + sendkeymsg((char *)&msg, sizeof(msg)); + } + ; + +spdflush_command + : + SPDFLUSH EOT + { + struct sadb_msg msg; + setkeymsg0(&msg, SADB_X_SPDFLUSH, SADB_SATYPE_UNSPEC, + sizeof(msg)); + sendkeymsg((char *)&msg, sizeof(msg)); + } + ; + +ipaddropts + : /* nothing */ + | ipaddropts ipaddropt + ; + +ipaddropt + : F_AIFLAGS + { + char *p; + + for (p = $1.buf + 1; *p; p++) + switch (*p) { + case '4': + p_aifamily = AF_INET; + break; +#ifdef INET6 + case '6': + p_aifamily = AF_INET6; + break; +#endif + case 'n': + p_aiflags = AI_NUMERICHOST; + break; + default: + yyerror("invalid flag"); + return -1; + } + } + ; + +ipaddr + : STRING + { + $$ = parse_addr($1.buf, NULL); + if ($$ == NULL) { + /* yyerror already called by parse_addr */ + return -1; + } + } + ; + +ipandport + : STRING + { + $$ = parse_addr($1.buf, NULL); + if ($$ == NULL) { + /* yyerror already called by parse_addr */ + return -1; + } + } + | STRING portstr + { + $$ = parse_addr($1.buf, $2.buf); + if ($$ == NULL) { + /* yyerror already called by parse_addr */ + return -1; + } + } + ; + +prefix + : /*NOTHING*/ { $$ = -1; } + | SLASH DECSTRING { $$ = $2; } + ; + +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 { $$ = $1; } + | ANY { $$ = IPSEC_ULPROTO_ANY; } + | PR_TCP { + $$ = IPPROTO_TCP; + } + | STRING + { + struct protoent *ent; + + ent = getprotobyname($1.buf); + if (ent) + $$ = ent->p_proto; + else { + if (strcmp("icmp6", $1.buf) == 0) { + $$ = IPPROTO_ICMPV6; + } else if(strcmp("ip4", $1.buf) == 0) { + $$ = IPPROTO_IPV4; + } else { + yyerror("invalid upper layer protocol"); + return -1; + } + } + endprotoent(); + } + ; + +upper_misc_spec + : /*NOTHING*/ + { + $$.buf = NULL; + $$.len = 0; + } + | STRING + { + $$.buf = strdup($1.buf); + if (!$$.buf) { + yyerror("insufficient memory"); + return -1; + } + $$.len = strlen($$.buf); + } + ; + +context_spec + : /* NOTHING */ + | SECURITY_CTX DECSTRING DECSTRING QUOTEDSTRING { + sec_ctx.doi = $2; + sec_ctx.alg = $3; + sec_ctx.len = $4.len+1; + sec_ctx.buf = $4.buf; + } + ; + +policy_spec + : F_POLICY policy_requests + { + char *policy; +#ifdef HAVE_PFKEY_POLICY_PRIORITY + struct sadb_x_policy *xpl; +#endif + + policy = ipsec_set_policy($2.buf, $2.len); + if (policy == NULL) { + yyerror(ipsec_strerror()); + return -1; + } + + $$.buf = policy; + $$.len = ipsec_get_policylen(policy); + +#ifdef HAVE_PFKEY_POLICY_PRIORITY + xpl = (struct sadb_x_policy *) $$.buf; + last_priority = xpl->sadb_x_policy_priority; +#endif + } + ; + +policy_requests + : PL_REQUESTS { $$ = $1; } + ; + + /* exit */ +exit_command + : EXIT EOT + { + exit_now = 1; + YYACCEPT; + } + ; +%% + +int +setkeymsg0(msg, type, satype, l) + struct sadb_msg *msg; + unsigned int type; + unsigned int satype; + size_t l; +{ + + 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; + struct sadb_x_policy *sp; +#ifdef HAVE_POLICY_FWD + struct sadb_x_ipsecrequest *ps = NULL; + int saved_level, saved_id = 0; +#endif + + 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); + + sp = (struct sadb_x_policy*) (buf + l); + 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: + plen = sizeof(struct in6_addr) << 3; + break; +#endif + default: + continue; + } + + /* set src */ + sa = s->ai_addr; + salen = sysdep_sa_len(s->ai_addr); + 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 = + (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 = sysdep_sa_len(d->ai_addr); + 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 = + (dplen >= 0 ? dplen : plen); + m_addr.sadb_address_reserved = 0; + + setvarbuf(buf, &l, (struct sadb_ext *)&m_addr, + sizeof(m_addr), sa, salen); +#ifdef SADB_X_EXT_SEC_CTX + /* Add security context label */ + if (sec_ctx.doi) { + struct sadb_x_sec_ctx m_sec_ctx; + u_int slen = sizeof(struct sadb_x_sec_ctx); + + memset(&m_sec_ctx, 0, slen); + + m_sec_ctx.sadb_x_sec_len = + PFKEY_UNIT64(slen + PFKEY_ALIGN8(sec_ctx.len)); + + m_sec_ctx.sadb_x_sec_exttype = + SADB_X_EXT_SEC_CTX; + m_sec_ctx.sadb_x_ctx_len = sec_ctx.len;/*bytes*/ + m_sec_ctx.sadb_x_ctx_doi = sec_ctx.doi; + m_sec_ctx.sadb_x_ctx_alg = sec_ctx.alg; + setvarbuf(buf, &l, + (struct sadb_ext *)&m_sec_ctx, slen, + (caddr_t)sec_ctx.buf, sec_ctx.len); + } +#endif + msg->sadb_msg_len = PFKEY_UNIT64(l); + + sendkeymsg(buf, l); + +#ifdef HAVE_POLICY_FWD + /* create extra call for FWD policy */ + if (f_rfcmode && sp->sadb_x_policy_dir == IPSEC_DIR_INBOUND) { + sp->sadb_x_policy_dir = IPSEC_DIR_FWD; + ps = (struct sadb_x_ipsecrequest*) (sp+1); + + /* if request level is unique, change it to + * require for fwd policy */ + /* XXX: currently, only first policy is updated + * only. Update following too... */ + saved_level = ps->sadb_x_ipsecrequest_level; + if (saved_level == IPSEC_LEVEL_UNIQUE) { + saved_id = ps->sadb_x_ipsecrequest_reqid; + ps->sadb_x_ipsecrequest_reqid=0; + ps->sadb_x_ipsecrequest_level=IPSEC_LEVEL_REQUIRE; + } + + sendkeymsg(buf, l); + /* restoring for next message */ + sp->sadb_x_policy_dir = IPSEC_DIR_INBOUND; + if (saved_level == IPSEC_LEVEL_UNIQUE) { + ps->sadb_x_ipsecrequest_reqid = saved_id; + ps->sadb_x_ipsecrequest_level = saved_level; + } + } +#endif + + n++; + } + } + + if (n == 0) + return -1; + else + return 0; +} + +static int +setkeymsg_spdaddr_tag(type, tag, policy) + unsigned int type; + char *tag; + vchar_t *policy; +{ + struct sadb_msg *msg; + char buf[BUFSIZ]; + int l, l0; +#ifdef SADB_X_EXT_TAG + struct sadb_x_tag m_tag; +#endif + int n; + + msg = (struct sadb_msg *)buf; + + /* 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; + +#ifdef SADB_X_EXT_TAG + memset(&m_tag, 0, sizeof(m_tag)); + m_tag.sadb_x_tag_len = PFKEY_UNIT64(sizeof(m_tag)); + m_tag.sadb_x_tag_exttype = SADB_X_EXT_TAG; + if (strlcpy(m_tag.sadb_x_tag_name, tag, + sizeof(m_tag.sadb_x_tag_name)) >= sizeof(m_tag.sadb_x_tag_name)) + return -1; + memcpy(buf + l, &m_tag, sizeof(m_tag)); + l += sizeof(m_tag); +#endif + + msg->sadb_msg_len = PFKEY_UNIT64(l); + + sendkeymsg(buf, l); + + 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; +#endif + default: + continue; + } + + /* set src */ + sa = s->ai_addr; + salen = sysdep_sa_len(s->ai_addr); + 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), sa, salen); + + /* set dst */ + sa = d->ai_addr; + salen = sysdep_sa_len(d->ai_addr); + 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), sa, salen); + + msg->sadb_msg_len = PFKEY_UNIT64(l); + + sendkeymsg(buf, l); + + n++; + } + } + + if (n == 0) + return -1; + else + return 0; +} + +#ifdef SADB_X_EXT_NAT_T_TYPE +static u_int16_t get_port (struct addrinfo *addr) +{ + struct sockaddr *s = addr->ai_addr; + u_int16_t port = 0; + + switch (s->sa_family) { + case AF_INET: + { + struct sockaddr_in *sin4 = (struct sockaddr_in *)s; + port = ntohs(sin4->sin_port); + break; + } + case AF_INET6: + { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)s; + port = ntohs(sin6->sin6_port); + break; + } + } + + if (port == 0) + port = DEFAULT_NATT_PORT; + + return port; +} +#endif + +/* 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) { + union { + struct sadb_key key; + struct sadb_ext ext; + } m; + + 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, &m.ext, sizeof(m.key), + p_key_enc, p_key_enc_len); + } + + /* set authentication algorithm, if present. */ + if (p_key_auth) { + union { + struct sadb_key key; + struct sadb_ext ext; + } m; + + 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, &m.ext, sizeof(m.key), + p_key_auth, p_key_auth_len); + } + + /* set lifetime for HARD */ + if (p_lt_hard != 0 || p_lb_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 = p_lb_hard; + m_lt.sadb_lifetime_addtime = p_lt_hard; + m_lt.sadb_lifetime_usetime = 0; + + memcpy(buf + l, &m_lt, slen); + l += slen; + } + + /* set lifetime for SOFT */ + if (p_lt_soft != 0 || p_lb_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 = p_lb_soft; + m_lt.sadb_lifetime_addtime = p_lt_soft; + m_lt.sadb_lifetime_usetime = 0; + + memcpy(buf + l, &m_lt, slen); + l += slen; + } + +#ifdef SADB_X_EXT_SEC_CTX + /* Add security context label */ + if (sec_ctx.doi) { + struct sadb_x_sec_ctx m_sec_ctx; + u_int slen = sizeof(struct sadb_x_sec_ctx); + + memset(&m_sec_ctx, 0, slen); + + m_sec_ctx.sadb_x_sec_len = PFKEY_UNIT64(slen + + PFKEY_ALIGN8(sec_ctx.len)); + m_sec_ctx.sadb_x_sec_exttype = SADB_X_EXT_SEC_CTX; + m_sec_ctx.sadb_x_ctx_len = sec_ctx.len; /* bytes */ + m_sec_ctx.sadb_x_ctx_doi = sec_ctx.doi; + m_sec_ctx.sadb_x_ctx_alg = sec_ctx.alg; + setvarbuf(buf, &l, (struct sadb_ext *)&m_sec_ctx, slen, + (caddr_t)sec_ctx.buf, sec_ctx.len); + } +#endif + + 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; + +#ifdef SADB_X_EXT_NAT_T_TYPE + if (p_natt_type) { + struct sadb_x_nat_t_type natt_type; + + len = sizeof(struct sadb_x_nat_t_type); + memset(&natt_type, 0, len); + natt_type.sadb_x_nat_t_type_len = PFKEY_UNIT64(len); + natt_type.sadb_x_nat_t_type_exttype = SADB_X_EXT_NAT_T_TYPE; + natt_type.sadb_x_nat_t_type_type = p_natt_type; + + memcpy(buf + l, &natt_type, len); + l += len; + + if (p_natt_oa) { + sa = p_natt_oa->ai_addr; + switch (sa->sa_family) { + case AF_INET: + plen = sizeof(struct in_addr) << 3; + break; +#ifdef INET6 + case AF_INET6: + plen = sizeof(struct in6_addr) << 3; + break; +#endif + default: + return -1; + } + salen = sysdep_sa_len(sa); + m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) + + PFKEY_ALIGN8(salen)); + m_addr.sadb_address_exttype = SADB_X_EXT_NAT_T_OA; + 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), sa, salen); + } + } +#endif + + 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; +#endif + default: + continue; + } + + /* set src */ + sa = s->ai_addr; + salen = sysdep_sa_len(s->ai_addr); + 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), sa, salen); + + /* set dst */ + sa = d->ai_addr; + salen = sysdep_sa_len(d->ai_addr); + 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), sa, salen); + +#ifdef SADB_X_EXT_NAT_T_TYPE + if (p_natt_type) { + struct sadb_x_nat_t_port natt_port; + + /* NATT_SPORT */ + len = sizeof(struct sadb_x_nat_t_port); + memset(&natt_port, 0, len); + natt_port.sadb_x_nat_t_port_len = PFKEY_UNIT64(len); + natt_port.sadb_x_nat_t_port_exttype = + SADB_X_EXT_NAT_T_SPORT; + natt_port.sadb_x_nat_t_port_port = htons(get_port(s)); + + memcpy(buf + l, &natt_port, len); + l += len; + + /* NATT_DPORT */ + natt_port.sadb_x_nat_t_port_exttype = + SADB_X_EXT_NAT_T_DPORT; + natt_port.sadb_x_nat_t_port_port = htons(get_port(d)); + + memcpy(buf + l, &natt_port, len); + l += len; + } +#endif + msg->sadb_msg_len = PFKEY_UNIT64(l); + + sendkeymsg(buf, l); + + n++; + } + } + + if (n == 0) + return -1; + else + return 0; +} + +static struct addrinfo * +parse_addr(host, port) + char *host; + char *port; +{ + struct addrinfo hints, *res = NULL; + int error; + + memset(&hints, 0, sizeof(hints)); + 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; + } + return res; +} + +static int +fix_portstr(ulproto, spec, sport, dport) + int ulproto; + vchar_t *spec, *sport, *dport; +{ + char sp[16], dp[16]; + int a, b, c, d; + unsigned long u; + + if (spec->buf == NULL) + return 0; + + switch (ulproto) { + case IPPROTO_ICMP: + case IPPROTO_ICMPV6: + case IPPROTO_MH: + if (sscanf(spec->buf, "%d,%d", &a, &b) == 2) { + sprintf(sp, "%d", a); + sprintf(dp, "%d", b); + } else if (sscanf(spec->buf, "%d", &a) == 1) { + sprintf(sp, "%d", a); + } else { + yyerror("invalid an upper layer protocol spec"); + return -1; + } + break; + case IPPROTO_GRE: + if (sscanf(spec->buf, "%d.%d.%d.%d", &a, &b, &c, &d) == 4) { + sprintf(sp, "%d", (a << 8) + b); + sprintf(dp, "%d", (c << 8) + d); + } else if (sscanf(spec->buf, "%lu", &u) == 1) { + sprintf(sp, "%d", (int) (u >> 16)); + sprintf(dp, "%d", (int) (u & 0xffff)); + } else { + yyerror("invalid an upper layer protocol spec"); + return -1; + } + break; + } + + free(sport->buf); + sport->buf = strdup(sp); + if (!sport->buf) { + yyerror("insufficient memory"); + return -1; + } + sport->len = strlen(sport->buf); + + free(dport->buf); + dport->buf = strdup(dp); + 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 elen; + const void *vbuf; + int 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; +} + +void +parse_init() +{ + p_spi = 0; + + p_ext = SADB_X_EXT_CYCSEQ; + p_alg_enc = SADB_EALG_NONE; + p_alg_auth = SADB_AALG_NONE; + p_mode = IPSEC_MODE_ANY; + p_reqid = 0; + p_replay = 0; + p_key_enc_len = p_key_auth_len = 0; + p_key_enc = p_key_auth = 0; + p_lt_hard = p_lt_soft = 0; + p_lb_hard = p_lb_soft = 0; + + memset(&sec_ctx, 0, sizeof(struct security_ctx)); + + p_aiflags = 0; + p_aifamily = PF_UNSPEC; + + /* Clear out any natt OA information */ + if (p_natt_oa) + freeaddrinfo (p_natt_oa); + p_natt_oa = NULL; + p_natt_type = 0; + + return; +} + +void +free_buffer() +{ + /* we got tons of memory leaks in the parser anyways, leave them */ + + return; +} |