parse.y revision 62583
162583Sitojun/* $FreeBSD: head/sbin/setkey/parse.y 62583 2000-07-04 16:22:05Z itojun $ */ 262583Sitojun/* $KAME: parse.y,v 1.29 2000/06/10 14:17:44 sakane Exp $ */ 362583Sitojun 455505Sshin/* 555505Sshin * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. 655505Sshin * All rights reserved. 762583Sitojun * 855505Sshin * Redistribution and use in source and binary forms, with or without 955505Sshin * modification, are permitted provided that the following conditions 1055505Sshin * are met: 1155505Sshin * 1. Redistributions of source code must retain the above copyright 1255505Sshin * notice, this list of conditions and the following disclaimer. 1355505Sshin * 2. Redistributions in binary form must reproduce the above copyright 1455505Sshin * notice, this list of conditions and the following disclaimer in the 1555505Sshin * documentation and/or other materials provided with the distribution. 1655505Sshin * 3. Neither the name of the project nor the names of its contributors 1755505Sshin * may be used to endorse or promote products derived from this software 1855505Sshin * without specific prior written permission. 1962583Sitojun * 2055505Sshin * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 2155505Sshin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2255505Sshin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2355505Sshin * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 2455505Sshin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2555505Sshin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2655505Sshin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2755505Sshin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2855505Sshin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2955505Sshin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3055505Sshin * SUCH DAMAGE. 3155505Sshin */ 3255505Sshin 3355505Sshin%{ 3455505Sshin#include <sys/types.h> 3555505Sshin#include <sys/param.h> 3655505Sshin#include <sys/socket.h> 3755505Sshin 3855505Sshin#include <net/route.h> 3955505Sshin#include <netinet/in.h> 4055505Sshin#include <net/pfkeyv2.h> 4155505Sshin#include <netkey/key_var.h> 4255505Sshin#include <netinet6/ipsec.h> 4355505Sshin#include <arpa/inet.h> 4455505Sshin 4555505Sshin#include <string.h> 4655505Sshin#include <unistd.h> 4755505Sshin#include <stdio.h> 4862583Sitojun#include <netdb.h> 4955505Sshin#include <ctype.h> 5055505Sshin#include <errno.h> 5155505Sshin 5262583Sitojun#include "libpfkey.h" 5355505Sshin#include "vchar.h" 5455505Sshin 5555505Sshin#define ATOX(c) \ 5655505Sshin (isdigit(c) ? (c - '0') : (isupper(c) ? (c - 'A' + 10) : (c - 'a' + 10) )) 5755505Sshin 5862583Sitojunu_int p_type; 5962583Sitojunu_int32_t p_spi; 6062583Sitojunstruct sockaddr *p_src, *p_dst; 6162583Sitojunu_int p_prefs, p_prefd, p_upper; 6262583Sitojunu_int p_satype, p_ext, p_alg_enc, p_alg_auth, p_replay, p_mode; 6362583Sitojunu_int32_t p_reqid; 6462583Sitojunu_int p_key_enc_len, p_key_auth_len; 6562583Sitojuncaddr_t p_key_enc, p_key_auth; 6662583Sitojuntime_t p_lt_hard, p_lt_soft; 6755505Sshin 6862583Sitojunu_int p_policy_len; 6962583Sitojunchar *p_policy; 7055505Sshin 7155505Sshin/* temporary buffer */ 7262583Sitojunstatic struct sockaddr *pp_addr; 7362583Sitojunstatic u_int pp_prefix; 7462583Sitojunstatic u_int pp_port; 7562583Sitojunstatic caddr_t pp_key; 7655505Sshin 7762583Sitojunextern u_char m_buf[BUFSIZ]; 7862583Sitojunextern int m_len; 7962583Sitojunextern char cmdarg[8192]; 8062583Sitojunextern int f_debug; 8155505Sshin 8262583Sitojunint setkeymsg __P((void)); 8362583Sitojunstatic struct addrinfo *parse_addr __P((char *, char *, int)); 8462583Sitojunstatic int setvarbuf __P((int *, struct sadb_ext *, int, caddr_t, int)); 8562583Sitojunvoid parse_init __P((void)); 8662583Sitojunvoid free_buffer __P((void)); 8755505Sshin 8862583Sitojunextern int setkeymsg __P((void)); 8962583Sitojunextern int sendkeymsg __P((void)); 9055505Sshin 9162583Sitojunextern int yylex __P((void)); 9262583Sitojunextern void yyfatal __P((const char *)); 9362583Sitojunextern void yyerror __P((const char *)); 9455505Sshin%} 9555505Sshin 9655505Sshin%union { 9755505Sshin unsigned long num; 9855505Sshin vchar_t val; 9955505Sshin} 10055505Sshin 10155505Sshin%token EOT 10255505Sshin%token ADD GET DELETE FLUSH DUMP 10362583Sitojun%token ADDRESS PREFIX PORT PORTANY 10455505Sshin%token UP_PROTO PR_ESP PR_AH PR_IPCOMP 10555505Sshin%token F_PROTOCOL F_AUTH F_ENC F_REPLAY F_COMP F_RAWCPI 10662583Sitojun%token F_MODE MODE F_REQID 10762583Sitojun%token F_EXT EXTENSION NOCYCLICSEQ 10855505Sshin%token ALG_AUTH ALG_ENC ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_COMP 10955505Sshin%token F_LIFETIME_HARD F_LIFETIME_SOFT 11055505Sshin%token DECSTRING QUOTEDSTRING HEXSTRING ANY 11155505Sshin /* SPD management */ 11255505Sshin%token SPDADD SPDDELETE SPDDUMP SPDFLUSH 11355505Sshin%token F_POLICY PL_REQUESTS 11455505Sshin 11562583Sitojun%type <num> PORT PREFIX EXTENSION MODE 11662583Sitojun%type <num> UP_PROTO PR_ESP PR_AH PR_IPCOMP 11762583Sitojun%type <num> ALG_AUTH ALG_ENC ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_COMP 11862583Sitojun%type <num> DECSTRING 11962583Sitojun%type <val> ADDRESS PL_REQUESTS 12062583Sitojun%type <val> key_string policy_requests 12162583Sitojun%type <val> QUOTEDSTRING HEXSTRING 12262583Sitojun 12355505Sshin%% 12455505Sshincommands 12555505Sshin : /*NOTHING*/ 12655505Sshin | commands command 12755505Sshin { 12855505Sshin if (f_debug) { 12955505Sshin printf("cmdarg:\n%s\n", cmdarg); 13055505Sshin } else { 13155505Sshin setkeymsg(); 13255505Sshin sendkeymsg(); 13355505Sshin } 13455505Sshin free_buffer(); 13555505Sshin parse_init(); 13655505Sshin } 13755505Sshin ; 13855505Sshin 13955505Sshincommand 14055505Sshin : add_command 14155505Sshin | get_command 14255505Sshin | delete_command 14355505Sshin | flush_command 14455505Sshin | dump_command 14555505Sshin | spdadd_command 14655505Sshin | spddelete_command 14755505Sshin | spddump_command 14855505Sshin | spdflush_command 14955505Sshin ; 15055505Sshin /* commands concerned with management, there is in tail of this file. */ 15155505Sshin 15255505Sshin /* add command */ 15355505Sshinadd_command 15455505Sshin : ADD { p_type = SADB_ADD; } 15555505Sshin sa_selector_spec extension_spec algorithm_spec EOT 15655505Sshin ; 15755505Sshin 15855505Sshin /* delete */ 15955505Sshindelete_command 16055505Sshin : DELETE { p_type = SADB_DELETE; } 16162583Sitojun sa_selector_spec extension_spec 16262583Sitojun { 16362583Sitojun if (p_mode != IPSEC_MODE_ANY) 16462583Sitojun yyerror("WARNING: mode is obsoleted."); 16562583Sitojun } 16662583Sitojun EOT 16755505Sshin ; 16855505Sshin 16955505Sshin /* get command */ 17055505Sshinget_command 17155505Sshin : GET { p_type = SADB_GET; } 17262583Sitojun sa_selector_spec extension_spec 17362583Sitojun { 17462583Sitojun if (p_mode != IPSEC_MODE_ANY) 17562583Sitojun yyerror("WARNING: mode is obsoleted."); 17662583Sitojun } 17762583Sitojun EOT 17855505Sshin ; 17955505Sshin 18055505Sshin /* flush */ 18155505Sshinflush_command 18255505Sshin : FLUSH { p_type = SADB_FLUSH; } 18355505Sshin protocol_spec EOT 18455505Sshin ; 18555505Sshin 18655505Sshin /* dump */ 18755505Sshindump_command 18855505Sshin : DUMP { p_type = SADB_DUMP; } 18955505Sshin protocol_spec EOT 19055505Sshin ; 19155505Sshin 19255505Sshin /* sa_selector_spec */ 19355505Sshinsa_selector_spec 19455505Sshin : ipaddress { p_src = pp_addr; } 19555505Sshin ipaddress { p_dst = pp_addr; } 19655505Sshin protocol_spec spi 19755505Sshin ; 19855505Sshin 19955505Sshinprotocol_spec 20055505Sshin : /*NOTHING*/ { p_satype = SADB_SATYPE_UNSPEC; } 20155505Sshin | PR_ESP 20255505Sshin { 20355505Sshin p_satype = SADB_SATYPE_ESP; 20462583Sitojun if ($1 == 1) 20555505Sshin p_ext |= SADB_X_EXT_OLD; 20655505Sshin else 20755505Sshin p_ext &= ~SADB_X_EXT_OLD; 20855505Sshin } 20955505Sshin | PR_AH 21055505Sshin { 21155505Sshin p_satype = SADB_SATYPE_AH; 21262583Sitojun if ($1 == 1) 21355505Sshin p_ext |= SADB_X_EXT_OLD; 21455505Sshin else 21555505Sshin p_ext &= ~SADB_X_EXT_OLD; 21655505Sshin } 21755505Sshin | PR_IPCOMP 21855505Sshin { 21955505Sshin p_satype = SADB_X_SATYPE_IPCOMP; 22055505Sshin } 22155505Sshin ; 22255505Sshin 22355505Sshinspi 22462583Sitojun : DECSTRING { p_spi = $1; } 22555505Sshin | HEXSTRING 22655505Sshin { 22755505Sshin caddr_t bp; 22862583Sitojun caddr_t yp = $1.buf; 22955505Sshin char buf0[4], buf[4]; 23055505Sshin int i, j; 23155505Sshin 23255505Sshin /* sanity check */ 23362583Sitojun if ($1.len > 4) { 23455505Sshin yyerror("SPI too big."); 23562583Sitojun free($1.buf); 23655505Sshin return -1; 23755505Sshin } 23855505Sshin 23955505Sshin bp = buf0; 24055505Sshin while (*yp) { 24155505Sshin *bp = (ATOX(yp[0]) << 4) | ATOX(yp[1]); 24255505Sshin yp += 2, bp++; 24355505Sshin } 24455505Sshin 24555505Sshin /* initialize */ 24655505Sshin for (i = 0; i < 4; i++) buf[i] = 0; 24755505Sshin 24862583Sitojun for (j = $1.len - 1, i = 3; j >= 0; j--, i--) 24955505Sshin buf[i] = buf0[j]; 25055505Sshin 25155505Sshin /* XXX: endian */ 25255505Sshin p_spi = ntohl(*(u_int32_t *)buf); 25355505Sshin 25462583Sitojun free($1.buf); 25555505Sshin } 25655505Sshin ; 25755505Sshin 25855505Sshinalgorithm_spec 25955505Sshin : esp_spec 26055505Sshin | ah_spec 26155505Sshin | ipcomp_spec 26255505Sshin ; 26355505Sshin 26455505Sshinesp_spec 26555505Sshin : F_ENC enc_alg enc_key F_AUTH auth_alg auth_key 26655505Sshin | F_ENC enc_alg enc_key 26755505Sshin ; 26855505Sshin 26955505Sshinah_spec 27055505Sshin : F_AUTH auth_alg auth_key 27155505Sshin ; 27255505Sshin 27355505Sshinipcomp_spec 27462583Sitojun : F_COMP ALG_COMP { p_alg_enc = $2; } 27562583Sitojun | F_COMP ALG_COMP { p_alg_enc = $2; } 27655505Sshin F_RAWCPI { p_ext |= SADB_X_EXT_RAWCPI; } 27755505Sshin ; 27855505Sshin 27955505Sshinenc_alg 28062583Sitojun : ALG_ENC { p_alg_enc = $1; } 28155505Sshin | ALG_ENC_DESDERIV 28255505Sshin { 28362583Sitojun p_alg_enc = $1; 28455505Sshin if (p_ext & SADB_X_EXT_OLD) { 28555505Sshin yyerror("algorithm mismatched."); 28655505Sshin return -1; 28755505Sshin } 28855505Sshin p_ext |= SADB_X_EXT_DERIV; 28955505Sshin } 29055505Sshin | ALG_ENC_DES32IV 29155505Sshin { 29262583Sitojun p_alg_enc = $1; 29355505Sshin if (!(p_ext & SADB_X_EXT_OLD)) { 29455505Sshin yyerror("algorithm mismatched."); 29555505Sshin return -1; 29655505Sshin } 29755505Sshin p_ext |= SADB_X_EXT_IV4B; 29855505Sshin } 29955505Sshin ; 30055505Sshin 30155505Sshinenc_key 30255505Sshin : /*NOTHING*/ 30355505Sshin { 30455505Sshin if (p_alg_enc != SADB_EALG_NULL) { 30555505Sshin yyerror("no key found."); 30655505Sshin return -1; 30755505Sshin } 30855505Sshin } 30955505Sshin | key_string 31055505Sshin { 31162583Sitojun p_key_enc_len = $1.len; 31255505Sshin p_key_enc = pp_key; 31355505Sshin 31455505Sshin if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT, 31555505Sshin p_alg_enc, 31655505Sshin PFKEY_UNUNIT64(p_key_enc_len)) < 0) { 31755505Sshin yyerror(ipsec_strerror()); 31855505Sshin return -1; 31955505Sshin } 32055505Sshin } 32155505Sshin ; 32255505Sshin 32355505Sshinauth_alg 32462583Sitojun : ALG_AUTH { p_alg_auth = $1; } 32555505Sshin ; 32655505Sshin 32755505Sshinauth_key 32855505Sshin : /*NOTHING*/ 32955505Sshin { 33055505Sshin if (p_alg_auth != SADB_AALG_NULL) { 33155505Sshin yyerror("no key found."); 33255505Sshin return -1; 33355505Sshin } 33455505Sshin } 33555505Sshin | key_string 33655505Sshin { 33762583Sitojun p_key_auth_len = $1.len; 33855505Sshin p_key_auth = pp_key; 33955505Sshin 34055505Sshin if (ipsec_check_keylen(SADB_EXT_SUPPORTED_AUTH, 34155505Sshin p_alg_auth, 34255505Sshin PFKEY_UNUNIT64(p_key_auth_len)) < 0) { 34355505Sshin yyerror(ipsec_strerror()); 34455505Sshin return -1; 34555505Sshin } 34655505Sshin } 34755505Sshin ; 34855505Sshin 34955505Sshinkey_string 35055505Sshin : QUOTEDSTRING 35155505Sshin { 35262583Sitojun pp_key = $1.buf; 35355505Sshin /* free pp_key later */ 35455505Sshin } 35555505Sshin | HEXSTRING 35655505Sshin { 35755505Sshin caddr_t bp; 35862583Sitojun caddr_t yp = $1.buf; 35955505Sshin 36062583Sitojun if ((pp_key = malloc($1.len)) == 0) { 36162583Sitojun free($1.buf); 36262583Sitojun yyerror("not enough core"); 36355505Sshin return -1; 36455505Sshin } 36562583Sitojun memset(pp_key, 0, $1.len); 36655505Sshin 36755505Sshin bp = pp_key; 36855505Sshin while (*yp) { 36955505Sshin *bp = (ATOX(yp[0]) << 4) | ATOX(yp[1]); 37055505Sshin yp += 2, bp++; 37155505Sshin } 37255505Sshin 37362583Sitojun free($1.buf); 37455505Sshin } 37555505Sshin ; 37655505Sshin 37755505Sshinextension_spec 37855505Sshin : /*NOTHING*/ 37955505Sshin | extension_spec extension 38055505Sshin ; 38155505Sshin 38255505Sshinextension 38362583Sitojun : F_EXT EXTENSION { p_ext |= $2; } 38462583Sitojun | F_EXT NOCYCLICSEQ { p_ext &= ~SADB_X_EXT_CYCSEQ; } 38562583Sitojun | F_MODE MODE { p_mode = $2; } 38655505Sshin | F_MODE ANY { p_mode = IPSEC_MODE_ANY; } 38762583Sitojun | F_REQID DECSTRING { p_reqid = $2; } 38855505Sshin | F_REPLAY DECSTRING 38955505Sshin { 39055505Sshin if (p_ext & SADB_X_EXT_OLD) { 39155505Sshin yyerror("replay prevention " 39255505Sshin "only use on new spec."); 39355505Sshin return -1; 39455505Sshin } 39562583Sitojun p_replay = $2; 39655505Sshin } 39762583Sitojun | F_LIFETIME_HARD DECSTRING { p_lt_hard = $2; } 39862583Sitojun | F_LIFETIME_SOFT DECSTRING { p_lt_soft = $2; } 39955505Sshin ; 40055505Sshin 40155505Sshin /* definition about command for SPD management */ 40255505Sshin /* spdadd */ 40355505Sshinspdadd_command 40455505Sshin : SPDADD 40555505Sshin { 40655505Sshin p_type = SADB_X_SPDADD; 40755505Sshin p_satype = SADB_SATYPE_UNSPEC; 40855505Sshin } 40955505Sshin sp_selector_spec policy_spec EOT 41055505Sshin ; 41155505Sshin 41255505Sshinspddelete_command: 41355505Sshin SPDDELETE 41455505Sshin { 41555505Sshin p_type = SADB_X_SPDDELETE; 41655505Sshin p_satype = SADB_SATYPE_UNSPEC; 41755505Sshin } 41862583Sitojun sp_selector_spec policy_spec EOT 41955505Sshin ; 42055505Sshin 42155505Sshinspddump_command: 42255505Sshin SPDDUMP 42355505Sshin { 42455505Sshin p_type = SADB_X_SPDDUMP; 42555505Sshin p_satype = SADB_SATYPE_UNSPEC; 42655505Sshin } 42755505Sshin EOT 42855505Sshin ; 42955505Sshin 43055505Sshinspdflush_command: 43155505Sshin SPDFLUSH 43255505Sshin { 43355505Sshin p_type = SADB_X_SPDFLUSH; 43455505Sshin p_satype = SADB_SATYPE_UNSPEC; 43555505Sshin } 43655505Sshin EOT 43755505Sshin ; 43855505Sshin 43955505Sshin /* sp_selector_spec */ 44055505Sshinsp_selector_spec 44155505Sshin : ipaddress { p_src = pp_addr; } 44255505Sshin prefix { p_prefs = pp_prefix; } 44362583Sitojun port 44462583Sitojun { 44562583Sitojun switch (p_src->sa_family) { 44662583Sitojun case AF_INET: 44762583Sitojun ((struct sockaddr_in *)p_src)->sin_port = 44862583Sitojun htons(pp_port); 44962583Sitojun break; 45062583Sitojun#ifdef INET6 45162583Sitojun case AF_INET6: 45262583Sitojun ((struct sockaddr_in6 *)p_src)->sin6_port = 45362583Sitojun htons(pp_port); 45462583Sitojun break; 45562583Sitojun#endif 45662583Sitojun default: 45762583Sitojun exit(1); /*XXX*/ 45862583Sitojun } 45962583Sitojun } 46055505Sshin ipaddress { p_dst = pp_addr; } 46155505Sshin prefix { p_prefd = pp_prefix; } 46262583Sitojun port 46362583Sitojun { 46462583Sitojun switch (p_dst->sa_family) { 46562583Sitojun case AF_INET: 46662583Sitojun ((struct sockaddr_in *)p_dst)->sin_port = 46762583Sitojun htons(pp_port); 46862583Sitojun break; 46962583Sitojun#ifdef INET6 47062583Sitojun case AF_INET6: 47162583Sitojun ((struct sockaddr_in6 *)p_dst)->sin6_port = 47262583Sitojun htons(pp_port); 47362583Sitojun break; 47462583Sitojun#endif 47562583Sitojun default: 47662583Sitojun exit(1); /*XXX*/ 47762583Sitojun } 47862583Sitojun } 47955505Sshin upper_spec 48062583Sitojun { 48162583Sitojun /* XXX is it something userland should check? */ 48262583Sitojun#if 0 48362583Sitojun switch (p_upper) { 48462583Sitojun case IPPROTO_ICMP: 48562583Sitojun case IPPROTO_ICMPV6: 48662583Sitojun if (_INPORTBYSA(p_src) != IPSEC_PORT_ANY 48762583Sitojun || _INPORTBYSA(p_dst) != IPSEC_PORT_ANY) { 48862583Sitojun yyerror("port number must be \"any\"."); 48962583Sitojun return -1; 49062583Sitojun } 49162583Sitojun if ((pp_addr->sa_family == AF_INET6 49262583Sitojun && p_upper == IPPROTO_ICMP) 49362583Sitojun || (pp_addr->sa_family == AF_INET 49462583Sitojun && p_upper == IPPROTO_ICMPV6)) { 49562583Sitojun yyerror("upper layer protocol " 49662583Sitojun "mismatched.\n"); 49762583Sitojun return -1; 49862583Sitojun } 49962583Sitojun break; 50062583Sitojun default: 50162583Sitojun break; 50262583Sitojun } 50362583Sitojun#endif 50462583Sitojun } 50555505Sshin ; 50655505Sshin 50755505Sshinipaddress 50862583Sitojun : ADDRESS 50955505Sshin { 51062583Sitojun struct addrinfo *res; 51155505Sshin 51262583Sitojun res = parse_addr($1.buf, NULL, AI_NUMERICHOST); 51362583Sitojun if (res == NULL) { 51462583Sitojun free($1.buf); 51555505Sshin return -1; 51655505Sshin } 51762583Sitojun pp_addr = (struct sockaddr *)malloc(res->ai_addrlen); 51862583Sitojun if (!pp_addr) { 51962583Sitojun yyerror("not enough core"); 52062583Sitojun goto end; 52155505Sshin } 52255505Sshin 52362583Sitojun memcpy(pp_addr, res->ai_addr, res->ai_addrlen); 52462583Sitojun end: 52555505Sshin freeaddrinfo(res); 52662583Sitojun free($1.buf); 52755505Sshin } 52855505Sshin ; 52955505Sshin 53055505Sshinprefix 53155505Sshin : /*NOTHING*/ { pp_prefix = ~0; } 53262583Sitojun | PREFIX { pp_prefix = $1; } 53355505Sshin ; 53455505Sshin 53555505Sshinport 53655505Sshin : /*NOTHING*/ { pp_port = IPSEC_PORT_ANY; } 53762583Sitojun | PORT { pp_port = $1; } 53855505Sshin | PORTANY { pp_port = IPSEC_PORT_ANY; } 53955505Sshin ; 54055505Sshin 54155505Sshinupper_spec 54262583Sitojun : DECSTRING { p_upper = $1; } 54362583Sitojun | UP_PROTO { p_upper = $1; } 54455505Sshin | PR_ESP { p_upper = IPPROTO_ESP; }; 54555505Sshin | PR_AH { p_upper = IPPROTO_AH; }; 54655505Sshin | PR_IPCOMP { p_upper = IPPROTO_IPCOMP; }; 54755505Sshin | ANY { p_upper = IPSEC_ULPROTO_ANY; } 54855505Sshin ; 54955505Sshin 55055505Sshinpolicy_spec 55155505Sshin : F_POLICY policy_requests 55255505Sshin { 55362583Sitojun p_policy = ipsec_set_policy($2.buf, $2.len); 55455505Sshin if (p_policy == NULL) { 55562583Sitojun free($2.buf); 55655505Sshin p_policy = NULL; 55755505Sshin yyerror(ipsec_strerror()); 55855505Sshin return -1; 55955505Sshin } 56055505Sshin 56155505Sshin p_policy_len = ipsec_get_policylen(p_policy); 56255505Sshin 56362583Sitojun free($2.buf); 56455505Sshin } 56555505Sshin ; 56655505Sshin 56762583Sitojunpolicy_requests 56862583Sitojun : PL_REQUESTS { $$ = $1; } 56955505Sshin ; 57055505Sshin 57155505Sshin%% 57255505Sshin 57355505Sshinint 57455505Sshinsetkeymsg() 57555505Sshin{ 57655505Sshin struct sadb_msg m_msg; 57755505Sshin 57855505Sshin m_msg.sadb_msg_version = PF_KEY_V2; 57955505Sshin m_msg.sadb_msg_type = p_type; 58055505Sshin m_msg.sadb_msg_errno = 0; 58155505Sshin m_msg.sadb_msg_satype = p_satype; 58255505Sshin m_msg.sadb_msg_reserved = 0; 58355505Sshin m_msg.sadb_msg_seq = 0; 58455505Sshin m_msg.sadb_msg_pid = getpid(); 58555505Sshin 58655505Sshin m_len = sizeof(struct sadb_msg); 58755505Sshin memcpy(m_buf, &m_msg, m_len); 58855505Sshin 58955505Sshin switch (p_type) { 59055505Sshin case SADB_FLUSH: 59155505Sshin case SADB_DUMP: 59255505Sshin break; 59355505Sshin 59455505Sshin case SADB_ADD: 59555505Sshin /* set encryption algorithm, if present. */ 59655505Sshin if (p_satype != SADB_X_SATYPE_IPCOMP && p_alg_enc != SADB_EALG_NONE) { 59755505Sshin struct sadb_key m_key; 59855505Sshin 59955505Sshin m_key.sadb_key_len = 60055505Sshin PFKEY_UNIT64(sizeof(m_key) 60155505Sshin + PFKEY_ALIGN8(p_key_enc_len)); 60255505Sshin m_key.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT; 60355505Sshin m_key.sadb_key_bits = p_key_enc_len * 8; 60455505Sshin m_key.sadb_key_reserved = 0; 60555505Sshin 60655505Sshin setvarbuf(&m_len, 60755505Sshin (struct sadb_ext *)&m_key, sizeof(m_key), 60855505Sshin (caddr_t)p_key_enc, p_key_enc_len); 60955505Sshin } 61055505Sshin 61155505Sshin /* set authentication algorithm, if present. */ 61255505Sshin if (p_alg_auth != SADB_AALG_NONE) { 61355505Sshin struct sadb_key m_key; 61455505Sshin 61555505Sshin m_key.sadb_key_len = 61655505Sshin PFKEY_UNIT64(sizeof(m_key) 61755505Sshin + PFKEY_ALIGN8(p_key_auth_len)); 61855505Sshin m_key.sadb_key_exttype = SADB_EXT_KEY_AUTH; 61955505Sshin m_key.sadb_key_bits = p_key_auth_len * 8; 62055505Sshin m_key.sadb_key_reserved = 0; 62155505Sshin 62255505Sshin setvarbuf(&m_len, 62355505Sshin (struct sadb_ext *)&m_key, sizeof(m_key), 62455505Sshin (caddr_t)p_key_auth, p_key_auth_len); 62555505Sshin } 62655505Sshin 62755505Sshin /* set lifetime for HARD */ 62855505Sshin if (p_lt_hard != 0) { 62955505Sshin struct sadb_lifetime m_lt; 63055505Sshin u_int len = sizeof(struct sadb_lifetime); 63155505Sshin 63255505Sshin m_lt.sadb_lifetime_len = PFKEY_UNIT64(len); 63355505Sshin m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD; 63455505Sshin m_lt.sadb_lifetime_allocations = 0; 63555505Sshin m_lt.sadb_lifetime_bytes = 0; 63655505Sshin m_lt.sadb_lifetime_addtime = p_lt_hard; 63755505Sshin m_lt.sadb_lifetime_usetime = 0; 63855505Sshin 63955505Sshin memcpy(m_buf + m_len, &m_lt, len); 64055505Sshin m_len += len; 64155505Sshin } 64255505Sshin 64355505Sshin /* set lifetime for SOFT */ 64455505Sshin if (p_lt_soft != 0) { 64555505Sshin struct sadb_lifetime m_lt; 64655505Sshin u_int len = sizeof(struct sadb_lifetime); 64755505Sshin 64855505Sshin m_lt.sadb_lifetime_len = PFKEY_UNIT64(len); 64955505Sshin m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT; 65055505Sshin m_lt.sadb_lifetime_allocations = 0; 65155505Sshin m_lt.sadb_lifetime_bytes = 0; 65255505Sshin m_lt.sadb_lifetime_addtime = p_lt_soft; 65355505Sshin m_lt.sadb_lifetime_usetime = 0; 65455505Sshin 65555505Sshin memcpy(m_buf + m_len, &m_lt, len); 65655505Sshin m_len += len; 65755505Sshin } 65855505Sshin /* FALLTHROUGH */ 65955505Sshin 66055505Sshin case SADB_DELETE: 66155505Sshin case SADB_GET: 66255505Sshin { 66355505Sshin struct sadb_sa m_sa; 66462583Sitojun struct sadb_x_sa2 m_sa2; 66555505Sshin struct sadb_address m_addr; 66655505Sshin u_int len; 66755505Sshin 66855505Sshin len = sizeof(struct sadb_sa); 66955505Sshin m_sa.sadb_sa_len = PFKEY_UNIT64(len); 67055505Sshin m_sa.sadb_sa_exttype = SADB_EXT_SA; 67155505Sshin m_sa.sadb_sa_spi = htonl(p_spi); 67255505Sshin m_sa.sadb_sa_replay = p_replay; 67355505Sshin m_sa.sadb_sa_state = 0; 67455505Sshin m_sa.sadb_sa_auth = p_alg_auth; 67555505Sshin m_sa.sadb_sa_encrypt = p_alg_enc; 67655505Sshin m_sa.sadb_sa_flags = p_ext; 67755505Sshin 67855505Sshin memcpy(m_buf + m_len, &m_sa, len); 67955505Sshin m_len += len; 68055505Sshin 68162583Sitojun len = sizeof(struct sadb_x_sa2); 68262583Sitojun m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len); 68362583Sitojun m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2; 68462583Sitojun m_sa2.sadb_x_sa2_mode = p_mode; 68562583Sitojun m_sa2.sadb_x_sa2_reqid = p_reqid; 68662583Sitojun 68762583Sitojun memcpy(m_buf + m_len, &m_sa2, len); 68862583Sitojun m_len += len; 68962583Sitojun 69055505Sshin /* set src */ 69155505Sshin m_addr.sadb_address_len = 69255505Sshin PFKEY_UNIT64(sizeof(m_addr) 69355505Sshin + PFKEY_ALIGN8(p_src->sa_len)); 69455505Sshin m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC; 69555505Sshin m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY; 69662583Sitojun switch (p_src->sa_family) { 69762583Sitojun case AF_INET: 69862583Sitojun m_addr.sadb_address_prefixlen = 69962583Sitojun sizeof(struct in_addr) << 3; 70062583Sitojun break; 70162583Sitojun#ifdef INET6 70262583Sitojun case AF_INET6: 70362583Sitojun m_addr.sadb_address_prefixlen = 70462583Sitojun sizeof(struct in6_addr) << 3; 70562583Sitojun break; 70662583Sitojun#endif 70762583Sitojun default: 70862583Sitojun yyerror("unsupported address family"); 70962583Sitojun exit(1); /*XXX*/ 71062583Sitojun } 71155505Sshin m_addr.sadb_address_reserved = 0; 71255505Sshin 71355505Sshin setvarbuf(&m_len, 71455505Sshin (struct sadb_ext *)&m_addr, sizeof(m_addr), 71555505Sshin (caddr_t)p_src, p_src->sa_len); 71655505Sshin 71755505Sshin /* set dst */ 71855505Sshin m_addr.sadb_address_len = 71955505Sshin PFKEY_UNIT64(sizeof(m_addr) 72055505Sshin + PFKEY_ALIGN8(p_dst->sa_len)); 72155505Sshin m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST; 72255505Sshin m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY; 72362583Sitojun switch (p_dst->sa_family) { 72462583Sitojun case AF_INET: 72562583Sitojun m_addr.sadb_address_prefixlen = 72662583Sitojun sizeof(struct in_addr) << 3; 72762583Sitojun break; 72862583Sitojun#ifdef INET6 72962583Sitojun case AF_INET6: 73062583Sitojun m_addr.sadb_address_prefixlen = 73162583Sitojun sizeof(struct in6_addr) << 3; 73262583Sitojun break; 73362583Sitojun#endif 73462583Sitojun default: 73562583Sitojun yyerror("unsupported address family"); 73662583Sitojun exit(1); /*XXX*/ 73762583Sitojun } 73855505Sshin m_addr.sadb_address_reserved = 0; 73955505Sshin 74055505Sshin setvarbuf(&m_len, 74155505Sshin (struct sadb_ext *)&m_addr, sizeof(m_addr), 74255505Sshin (caddr_t)p_dst, p_dst->sa_len); 74355505Sshin } 74455505Sshin break; 74555505Sshin 74655505Sshin /* for SPD management */ 74755505Sshin case SADB_X_SPDFLUSH: 74855505Sshin case SADB_X_SPDDUMP: 74955505Sshin break; 75055505Sshin 75155505Sshin case SADB_X_SPDADD: 75262583Sitojun case SADB_X_SPDDELETE: 75355505Sshin { 75462583Sitojun struct sadb_address m_addr; 75562583Sitojun u_int8_t plen; 75662583Sitojun 75755505Sshin memcpy(m_buf + m_len, p_policy, p_policy_len); 75855505Sshin m_len += p_policy_len; 75955505Sshin free(p_policy); 76055505Sshin p_policy = NULL; 76155505Sshin 76255505Sshin /* set src */ 76355505Sshin m_addr.sadb_address_len = 76455505Sshin PFKEY_UNIT64(sizeof(m_addr) 76555505Sshin + PFKEY_ALIGN8(p_src->sa_len)); 76655505Sshin m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC; 76755505Sshin m_addr.sadb_address_proto = p_upper; 76862583Sitojun switch (p_src->sa_family) { 76962583Sitojun case AF_INET: 77062583Sitojun plen = sizeof(struct in_addr) << 3; 77162583Sitojun break; 77262583Sitojun#ifdef INET6 77362583Sitojun case AF_INET6: 77462583Sitojun plen = sizeof(struct in6_addr) << 3; 77562583Sitojun break; 77662583Sitojun#endif 77762583Sitojun default: 77862583Sitojun yyerror("unsupported address family"); 77962583Sitojun exit(1); /*XXX*/ 78062583Sitojun } 78155505Sshin m_addr.sadb_address_prefixlen = 78262583Sitojun (p_prefs != ~0 ? p_prefs : plen); 78355505Sshin m_addr.sadb_address_reserved = 0; 78455505Sshin 78555505Sshin setvarbuf(&m_len, 78655505Sshin (struct sadb_ext *)&m_addr, sizeof(m_addr), 78755505Sshin (caddr_t)p_src, p_src->sa_len); 78855505Sshin 78955505Sshin /* set dst */ 79055505Sshin m_addr.sadb_address_len = 79155505Sshin PFKEY_UNIT64(sizeof(m_addr) 79255505Sshin + PFKEY_ALIGN8(p_dst->sa_len)); 79355505Sshin m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST; 79455505Sshin m_addr.sadb_address_proto = p_upper; 79562583Sitojun switch (p_dst->sa_family) { 79662583Sitojun case AF_INET: 79762583Sitojun plen = sizeof(struct in_addr) << 3; 79862583Sitojun break; 79962583Sitojun#ifdef INET6 80062583Sitojun case AF_INET6: 80162583Sitojun plen = sizeof(struct in6_addr) << 3; 80262583Sitojun break; 80362583Sitojun#endif 80462583Sitojun default: 80562583Sitojun yyerror("unsupported address family"); 80662583Sitojun exit(1); /*XXX*/ 80762583Sitojun } 80855505Sshin m_addr.sadb_address_prefixlen = 80962583Sitojun (p_prefd != ~0 ? p_prefd : plen); 81055505Sshin m_addr.sadb_address_reserved = 0; 81155505Sshin 81255505Sshin setvarbuf(&m_len, 81355505Sshin (struct sadb_ext *)&m_addr, sizeof(m_addr), 81455505Sshin (caddr_t)p_dst, p_dst->sa_len); 81555505Sshin } 81655505Sshin break; 81755505Sshin } 81855505Sshin 81955505Sshin ((struct sadb_msg *)m_buf)->sadb_msg_len = PFKEY_UNIT64(m_len); 82055505Sshin 82155505Sshin return 0; 82255505Sshin} 82355505Sshin 82462583Sitojunstatic struct addrinfo * 82562583Sitojunparse_addr(host, port, flag) 82662583Sitojun char *host; 82762583Sitojun char *port; 82862583Sitojun int flag; 82962583Sitojun{ 83062583Sitojun struct addrinfo hints, *res = NULL; 83162583Sitojun int error; 83262583Sitojun 83362583Sitojun memset(&hints, 0, sizeof(hints)); 83462583Sitojun hints.ai_family = PF_UNSPEC; 83562583Sitojun hints.ai_socktype = SOCK_DGRAM; 83662583Sitojun hints.ai_flags = flag; 83762583Sitojun error = getaddrinfo(host, port, &hints, &res); 83862583Sitojun if (error != 0) { 83962583Sitojun yyerror(gai_strerror(error)); 84062583Sitojun return NULL; 84162583Sitojun } 84262583Sitojun if (res->ai_next != NULL) { 84362583Sitojun yyerror(gai_strerror(error)); 84462583Sitojun } 84562583Sitojun return res; 84662583Sitojun} 84762583Sitojun 84855505Sshinstatic int 84955505Sshinsetvarbuf(off, ebuf, elen, vbuf, vlen) 85055505Sshin caddr_t vbuf; 85155505Sshin struct sadb_ext *ebuf; 85255505Sshin int *off, elen, vlen; 85355505Sshin{ 85455505Sshin memset(m_buf + *off, 0, PFKEY_UNUNIT64(ebuf->sadb_ext_len)); 85555505Sshin memcpy(m_buf + *off, (caddr_t)ebuf, elen); 85655505Sshin memcpy(m_buf + *off + elen, vbuf, vlen); 85755505Sshin (*off) += PFKEY_ALIGN8(elen + vlen); 85855505Sshin 85955505Sshin return 0; 86055505Sshin} 86155505Sshin 86255505Sshinvoid 86355505Sshinparse_init() 86455505Sshin{ 86555505Sshin p_type = 0; 86655505Sshin p_spi = 0; 86755505Sshin 86855505Sshin p_src = 0, p_dst = 0; 86955505Sshin pp_prefix = p_prefs = p_prefd = ~0; 87055505Sshin pp_port = IPSEC_PORT_ANY; 87155505Sshin p_upper = 0; 87255505Sshin 87355505Sshin p_satype = 0; 87462583Sitojun p_ext = SADB_X_EXT_CYCSEQ; 87555505Sshin p_alg_enc = SADB_EALG_NONE; 87655505Sshin p_alg_auth = SADB_AALG_NONE; 87755505Sshin p_mode = IPSEC_MODE_ANY; 87862583Sitojun p_reqid = 0; 87962583Sitojun p_replay = 0; 88055505Sshin p_key_enc_len = p_key_auth_len = 0; 88155505Sshin p_key_enc = p_key_auth = 0; 88255505Sshin p_lt_hard = p_lt_soft = 0; 88355505Sshin 88455505Sshin p_policy_len = 0; 88555505Sshin p_policy = NULL; 88655505Sshin 88755505Sshin memset(cmdarg, 0, sizeof(cmdarg)); 88855505Sshin 88955505Sshin return; 89055505Sshin} 89155505Sshin 89255505Sshinvoid 89355505Sshinfree_buffer() 89455505Sshin{ 89555505Sshin if (p_src) free(p_src); 89655505Sshin if (p_dst) free(p_dst); 89755505Sshin if (p_key_enc) free(p_key_enc); 89855505Sshin if (p_key_auth) free(p_key_auth); 89955505Sshin 90055505Sshin return; 90155505Sshin} 90255505Sshin 903