Annotation of embedaddon/ipsec-tools/src/setkey/parse.y, revision 1.1
1.1 ! misho 1: /* $NetBSD: parse.y,v 1.14 2010/12/03 14:32:52 tteras Exp $ */
! 2:
! 3: /* $KAME: parse.y,v 1.81 2003/07/01 04:01:48 itojun Exp $ */
! 4:
! 5: /*
! 6: * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
! 7: * All rights reserved.
! 8: *
! 9: * Redistribution and use in source and binary forms, with or without
! 10: * modification, are permitted provided that the following conditions
! 11: * are met:
! 12: * 1. Redistributions of source code must retain the above copyright
! 13: * notice, this list of conditions and the following disclaimer.
! 14: * 2. Redistributions in binary form must reproduce the above copyright
! 15: * notice, this list of conditions and the following disclaimer in the
! 16: * documentation and/or other materials provided with the distribution.
! 17: * 3. Neither the name of the project nor the names of its contributors
! 18: * may be used to endorse or promote products derived from this software
! 19: * without specific prior written permission.
! 20: *
! 21: * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 31: * SUCH DAMAGE.
! 32: */
! 33:
! 34: %{
! 35: #ifdef HAVE_CONFIG_H
! 36: #include "config.h"
! 37: #endif
! 38:
! 39: #include <sys/types.h>
! 40: #include <sys/param.h>
! 41: #include <sys/socket.h>
! 42:
! 43: #include <netinet/in.h>
! 44: #include <net/pfkeyv2.h>
! 45: #include PATH_IPSEC_H
! 46: #include <arpa/inet.h>
! 47:
! 48: #include <string.h>
! 49: #include <unistd.h>
! 50: #include <stdio.h>
! 51: #include <netdb.h>
! 52: #include <ctype.h>
! 53: #include <errno.h>
! 54: #include <stdlib.h>
! 55:
! 56: #include "libpfkey.h"
! 57: #include "vchar.h"
! 58: #include "extern.h"
! 59:
! 60: #define DEFAULT_NATT_PORT 4500
! 61:
! 62: #ifndef UDP_ENCAP_ESPINUDP
! 63: #define UDP_ENCAP_ESPINUDP 2
! 64: #endif
! 65:
! 66: #define ATOX(c) \
! 67: (isdigit((int)c) ? (c - '0') : \
! 68: (isupper((int)c) ? (c - 'A' + 10) : (c - 'a' + 10)))
! 69:
! 70: u_int32_t p_spi;
! 71: u_int p_ext, p_alg_enc, p_alg_auth, p_replay, p_mode;
! 72: u_int32_t p_reqid;
! 73: u_int p_key_enc_len, p_key_auth_len;
! 74: const char *p_key_enc;
! 75: const char *p_key_auth;
! 76: time_t p_lt_hard, p_lt_soft;
! 77: size_t p_lb_hard, p_lb_soft;
! 78:
! 79: struct security_ctx {
! 80: u_int8_t doi;
! 81: u_int8_t alg;
! 82: u_int16_t len;
! 83: char *buf;
! 84: };
! 85:
! 86: struct security_ctx sec_ctx;
! 87:
! 88: static u_int p_natt_type;
! 89: static struct addrinfo * p_natt_oa = NULL;
! 90:
! 91: static int p_aiflags = 0, p_aifamily = PF_UNSPEC;
! 92:
! 93: static struct addrinfo *parse_addr __P((char *, char *));
! 94: static int fix_portstr __P((int, vchar_t *, vchar_t *, vchar_t *));
! 95: static int setvarbuf __P((char *, int *, struct sadb_ext *, int,
! 96: const void *, int));
! 97: void parse_init __P((void));
! 98: void free_buffer __P((void));
! 99:
! 100: int setkeymsg0 __P((struct sadb_msg *, unsigned int, unsigned int, size_t));
! 101: static int setkeymsg_spdaddr __P((unsigned int, unsigned int, vchar_t *,
! 102: struct addrinfo *, int, struct addrinfo *, int));
! 103: static int setkeymsg_spdaddr_tag __P((unsigned int, char *, vchar_t *));
! 104: static int setkeymsg_addr __P((unsigned int, unsigned int,
! 105: struct addrinfo *, struct addrinfo *, int));
! 106: static int setkeymsg_add __P((unsigned int, unsigned int,
! 107: struct addrinfo *, struct addrinfo *));
! 108: %}
! 109:
! 110: %union {
! 111: int num;
! 112: unsigned long ulnum;
! 113: vchar_t val;
! 114: struct addrinfo *res;
! 115: }
! 116:
! 117: %token EOT SLASH BLCL ELCL
! 118: %token ADD GET DELETE DELETEALL FLUSH DUMP EXIT
! 119: %token PR_ESP PR_AH PR_IPCOMP PR_ESPUDP PR_TCP
! 120: %token F_PROTOCOL F_AUTH F_ENC F_REPLAY F_COMP F_RAWCPI
! 121: %token F_MODE MODE F_REQID
! 122: %token F_EXT EXTENSION NOCYCLICSEQ
! 123: %token ALG_AUTH ALG_AUTH_NOKEY
! 124: %token ALG_ENC ALG_ENC_NOKEY ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_ENC_OLD
! 125: %token ALG_COMP
! 126: %token F_LIFETIME_HARD F_LIFETIME_SOFT
! 127: %token F_LIFEBYTE_HARD F_LIFEBYTE_SOFT
! 128: %token DECSTRING QUOTEDSTRING HEXSTRING STRING ANY
! 129: /* SPD management */
! 130: %token SPDADD SPDUPDATE SPDDELETE SPDDUMP SPDFLUSH
! 131: %token F_POLICY PL_REQUESTS
! 132: %token F_AIFLAGS
! 133: %token TAGGED
! 134: %token SECURITY_CTX
! 135:
! 136: %type <num> prefix protocol_spec upper_spec
! 137: %type <num> ALG_ENC ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_ENC_OLD ALG_ENC_NOKEY
! 138: %type <num> ALG_AUTH ALG_AUTH_NOKEY
! 139: %type <num> ALG_COMP
! 140: %type <num> PR_ESP PR_AH PR_IPCOMP PR_ESPUDP PR_TCP
! 141: %type <num> EXTENSION MODE
! 142: %type <ulnum> DECSTRING
! 143: %type <val> PL_REQUESTS portstr key_string
! 144: %type <val> policy_requests
! 145: %type <val> QUOTEDSTRING HEXSTRING STRING
! 146: %type <val> F_AIFLAGS
! 147: %type <val> upper_misc_spec policy_spec
! 148: %type <res> ipaddr ipandport
! 149:
! 150: %%
! 151: commands
! 152: : /*NOTHING*/
! 153: | commands command
! 154: {
! 155: free_buffer();
! 156: parse_init();
! 157: }
! 158: ;
! 159:
! 160: command
! 161: : add_command
! 162: | get_command
! 163: | delete_command
! 164: | deleteall_command
! 165: | flush_command
! 166: | dump_command
! 167: | exit_command
! 168: | spdadd_command
! 169: | spdupdate_command
! 170: | spddelete_command
! 171: | spddump_command
! 172: | spdflush_command
! 173: ;
! 174: /* commands concerned with management, there is in tail of this file. */
! 175:
! 176: /* add command */
! 177: add_command
! 178: : ADD ipaddropts ipandport ipandport protocol_spec spi extension_spec algorithm_spec EOT
! 179: {
! 180: int status;
! 181:
! 182: status = setkeymsg_add(SADB_ADD, $5, $3, $4);
! 183: if (status < 0)
! 184: return -1;
! 185: }
! 186: ;
! 187:
! 188: /* delete */
! 189: delete_command
! 190: : DELETE ipaddropts ipandport ipandport protocol_spec spi extension_spec EOT
! 191: {
! 192: int status;
! 193:
! 194: if ($3->ai_next || $4->ai_next) {
! 195: yyerror("multiple address specified");
! 196: return -1;
! 197: }
! 198: if (p_mode != IPSEC_MODE_ANY)
! 199: yyerror("WARNING: mode is obsolete");
! 200:
! 201: status = setkeymsg_addr(SADB_DELETE, $5, $3, $4, 0);
! 202: if (status < 0)
! 203: return -1;
! 204: }
! 205: ;
! 206:
! 207: /* deleteall command */
! 208: deleteall_command
! 209: : DELETEALL ipaddropts ipaddr ipaddr protocol_spec EOT
! 210: {
! 211: #ifndef __linux__
! 212: if (setkeymsg_addr(SADB_DELETE, $5, $3, $4, 1) < 0)
! 213: return -1;
! 214: #else /* __linux__ */
! 215: /* linux strictly adheres to RFC2367, and returns
! 216: * an error if we send an SADB_DELETE request without
! 217: * an SPI. Therefore, we must first retrieve a list
! 218: * of SPIs for all matching SADB entries, and then
! 219: * delete each one separately. */
! 220: u_int32_t *spi;
! 221: int i, n;
! 222:
! 223: spi = sendkeymsg_spigrep($5, $3, $4, &n);
! 224: for (i = 0; i < n; i++) {
! 225: p_spi = spi[i];
! 226: if (setkeymsg_addr(SADB_DELETE,
! 227: $5, $3, $4, 0) < 0)
! 228: return -1;
! 229: }
! 230: free(spi);
! 231: #endif /* __linux__ */
! 232: }
! 233: ;
! 234:
! 235: /* get command */
! 236: get_command
! 237: : GET ipaddropts ipandport ipandport protocol_spec spi extension_spec EOT
! 238: {
! 239: int status;
! 240:
! 241: if (p_mode != IPSEC_MODE_ANY)
! 242: yyerror("WARNING: mode is obsolete");
! 243:
! 244: status = setkeymsg_addr(SADB_GET, $5, $3, $4, 0);
! 245: if (status < 0)
! 246: return -1;
! 247: }
! 248: ;
! 249:
! 250: /* flush */
! 251: flush_command
! 252: : FLUSH protocol_spec EOT
! 253: {
! 254: struct sadb_msg msg;
! 255: setkeymsg0(&msg, SADB_FLUSH, $2, sizeof(msg));
! 256: sendkeymsg((char *)&msg, sizeof(msg));
! 257: }
! 258: ;
! 259:
! 260: /* dump */
! 261: dump_command
! 262: : DUMP protocol_spec EOT
! 263: {
! 264: struct sadb_msg msg;
! 265: setkeymsg0(&msg, SADB_DUMP, $2, sizeof(msg));
! 266: sendkeymsg((char *)&msg, sizeof(msg));
! 267: }
! 268: ;
! 269:
! 270: protocol_spec
! 271: : /*NOTHING*/
! 272: {
! 273: $$ = SADB_SATYPE_UNSPEC;
! 274: }
! 275: | PR_ESP
! 276: {
! 277: $$ = SADB_SATYPE_ESP;
! 278: if ($1 == 1)
! 279: p_ext |= SADB_X_EXT_OLD;
! 280: else
! 281: p_ext &= ~SADB_X_EXT_OLD;
! 282: }
! 283: | PR_AH
! 284: {
! 285: $$ = SADB_SATYPE_AH;
! 286: if ($1 == 1)
! 287: p_ext |= SADB_X_EXT_OLD;
! 288: else
! 289: p_ext &= ~SADB_X_EXT_OLD;
! 290: }
! 291: | PR_IPCOMP
! 292: {
! 293: $$ = SADB_X_SATYPE_IPCOMP;
! 294: }
! 295: | PR_ESPUDP
! 296: {
! 297: $$ = SADB_SATYPE_ESP;
! 298: p_ext &= ~SADB_X_EXT_OLD;
! 299: p_natt_oa = 0;
! 300: p_natt_type = UDP_ENCAP_ESPINUDP;
! 301: }
! 302: | PR_ESPUDP ipaddr
! 303: {
! 304: $$ = SADB_SATYPE_ESP;
! 305: p_ext &= ~SADB_X_EXT_OLD;
! 306: p_natt_oa = $2;
! 307: p_natt_type = UDP_ENCAP_ESPINUDP;
! 308: }
! 309: | PR_TCP
! 310: {
! 311: #ifdef SADB_X_SATYPE_TCPSIGNATURE
! 312: $$ = SADB_X_SATYPE_TCPSIGNATURE;
! 313: #endif
! 314: }
! 315: ;
! 316:
! 317: spi
! 318: : DECSTRING { p_spi = $1; }
! 319: | HEXSTRING
! 320: {
! 321: char *ep;
! 322: unsigned long v;
! 323:
! 324: ep = NULL;
! 325: v = strtoul($1.buf, &ep, 16);
! 326: if (!ep || *ep) {
! 327: yyerror("invalid SPI");
! 328: return -1;
! 329: }
! 330: if (v & ~0xffffffff) {
! 331: yyerror("SPI too big.");
! 332: return -1;
! 333: }
! 334:
! 335: p_spi = v;
! 336: }
! 337: ;
! 338:
! 339: algorithm_spec
! 340: : esp_spec
! 341: | ah_spec
! 342: | ipcomp_spec
! 343: ;
! 344:
! 345: esp_spec
! 346: : F_ENC enc_alg F_AUTH auth_alg
! 347: | F_ENC enc_alg
! 348: ;
! 349:
! 350: ah_spec
! 351: : F_AUTH auth_alg
! 352: ;
! 353:
! 354: ipcomp_spec
! 355: : F_COMP ALG_COMP
! 356: {
! 357: if ($2 < 0) {
! 358: yyerror("unsupported algorithm");
! 359: return -1;
! 360: }
! 361: p_alg_enc = $2;
! 362: }
! 363: | F_COMP ALG_COMP F_RAWCPI
! 364: {
! 365: if ($2 < 0) {
! 366: yyerror("unsupported algorithm");
! 367: return -1;
! 368: }
! 369: p_alg_enc = $2;
! 370: p_ext |= SADB_X_EXT_RAWCPI;
! 371: }
! 372: ;
! 373:
! 374: enc_alg
! 375: : ALG_ENC_NOKEY {
! 376: if ($1 < 0) {
! 377: yyerror("unsupported algorithm");
! 378: return -1;
! 379: }
! 380: p_alg_enc = $1;
! 381:
! 382: p_key_enc_len = 0;
! 383: p_key_enc = "";
! 384: if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
! 385: p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
! 386: yyerror(ipsec_strerror());
! 387: return -1;
! 388: }
! 389: }
! 390: | ALG_ENC key_string {
! 391: if ($1 < 0) {
! 392: yyerror("unsupported algorithm");
! 393: return -1;
! 394: }
! 395: p_alg_enc = $1;
! 396:
! 397: p_key_enc_len = $2.len;
! 398: p_key_enc = $2.buf;
! 399: if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
! 400: p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
! 401: yyerror(ipsec_strerror());
! 402: return -1;
! 403: }
! 404: }
! 405: | ALG_ENC_OLD {
! 406: if ($1 < 0) {
! 407: yyerror("unsupported algorithm");
! 408: return -1;
! 409: }
! 410: yyerror("WARNING: obsolete algorithm");
! 411: p_alg_enc = $1;
! 412:
! 413: p_key_enc_len = 0;
! 414: p_key_enc = "";
! 415: if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
! 416: p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
! 417: yyerror(ipsec_strerror());
! 418: return -1;
! 419: }
! 420: }
! 421: | ALG_ENC_DESDERIV key_string
! 422: {
! 423: if ($1 < 0) {
! 424: yyerror("unsupported algorithm");
! 425: return -1;
! 426: }
! 427: p_alg_enc = $1;
! 428: if (p_ext & SADB_X_EXT_OLD) {
! 429: yyerror("algorithm mismatched");
! 430: return -1;
! 431: }
! 432: p_ext |= SADB_X_EXT_DERIV;
! 433:
! 434: p_key_enc_len = $2.len;
! 435: p_key_enc = $2.buf;
! 436: if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
! 437: p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
! 438: yyerror(ipsec_strerror());
! 439: return -1;
! 440: }
! 441: }
! 442: | ALG_ENC_DES32IV key_string
! 443: {
! 444: if ($1 < 0) {
! 445: yyerror("unsupported algorithm");
! 446: return -1;
! 447: }
! 448: p_alg_enc = $1;
! 449: if (!(p_ext & SADB_X_EXT_OLD)) {
! 450: yyerror("algorithm mismatched");
! 451: return -1;
! 452: }
! 453: p_ext |= SADB_X_EXT_IV4B;
! 454:
! 455: p_key_enc_len = $2.len;
! 456: p_key_enc = $2.buf;
! 457: if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
! 458: p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
! 459: yyerror(ipsec_strerror());
! 460: return -1;
! 461: }
! 462: }
! 463: ;
! 464:
! 465: auth_alg
! 466: : ALG_AUTH key_string {
! 467: if ($1 < 0) {
! 468: yyerror("unsupported algorithm");
! 469: return -1;
! 470: }
! 471: p_alg_auth = $1;
! 472:
! 473: p_key_auth_len = $2.len;
! 474: p_key_auth = $2.buf;
! 475: #ifdef SADB_X_AALG_TCP_MD5
! 476: if (p_alg_auth == SADB_X_AALG_TCP_MD5) {
! 477: if ((p_key_auth_len < 1) ||
! 478: (p_key_auth_len > 80))
! 479: return -1;
! 480: } else
! 481: #endif
! 482: {
! 483: if (ipsec_check_keylen(SADB_EXT_SUPPORTED_AUTH,
! 484: p_alg_auth,
! 485: PFKEY_UNUNIT64(p_key_auth_len)) < 0) {
! 486: yyerror(ipsec_strerror());
! 487: return -1;
! 488: }
! 489: }
! 490: }
! 491: | ALG_AUTH_NOKEY {
! 492: if ($1 < 0) {
! 493: yyerror("unsupported algorithm");
! 494: return -1;
! 495: }
! 496: p_alg_auth = $1;
! 497:
! 498: p_key_auth_len = 0;
! 499: p_key_auth = NULL;
! 500: }
! 501: ;
! 502:
! 503: key_string
! 504: : QUOTEDSTRING
! 505: {
! 506: $$ = $1;
! 507: }
! 508: | HEXSTRING
! 509: {
! 510: caddr_t pp_key;
! 511: caddr_t bp;
! 512: caddr_t yp = $1.buf;
! 513: int l;
! 514:
! 515: l = strlen(yp) % 2 + strlen(yp) / 2;
! 516: if ((pp_key = malloc(l)) == 0) {
! 517: yyerror("not enough core");
! 518: return -1;
! 519: }
! 520: memset(pp_key, 0, l);
! 521:
! 522: bp = pp_key;
! 523: if (strlen(yp) % 2) {
! 524: *bp = ATOX(yp[0]);
! 525: yp++, bp++;
! 526: }
! 527: while (*yp) {
! 528: *bp = (ATOX(yp[0]) << 4) | ATOX(yp[1]);
! 529: yp += 2, bp++;
! 530: }
! 531:
! 532: $$.len = l;
! 533: $$.buf = pp_key;
! 534: }
! 535: ;
! 536:
! 537: extension_spec
! 538: : /*NOTHING*/
! 539: | extension_spec extension
! 540: ;
! 541:
! 542: extension
! 543: : F_EXT EXTENSION { p_ext |= $2; }
! 544: | F_EXT NOCYCLICSEQ { p_ext &= ~SADB_X_EXT_CYCSEQ; }
! 545: | F_MODE MODE { p_mode = $2; }
! 546: | F_MODE ANY { p_mode = IPSEC_MODE_ANY; }
! 547: | F_REQID DECSTRING { p_reqid = $2; }
! 548: | F_REPLAY DECSTRING
! 549: {
! 550: if ((p_ext & SADB_X_EXT_OLD) != 0) {
! 551: yyerror("replay prevention cannot be used with "
! 552: "ah/esp-old");
! 553: return -1;
! 554: }
! 555: p_replay = $2;
! 556: }
! 557: | F_LIFETIME_HARD DECSTRING { p_lt_hard = $2; }
! 558: | F_LIFETIME_SOFT DECSTRING { p_lt_soft = $2; }
! 559: | F_LIFEBYTE_HARD DECSTRING { p_lb_hard = $2; }
! 560: | F_LIFEBYTE_SOFT DECSTRING { p_lb_soft = $2; }
! 561: | SECURITY_CTX DECSTRING DECSTRING QUOTEDSTRING {
! 562: sec_ctx.doi = $2;
! 563: sec_ctx.alg = $3;
! 564: sec_ctx.len = $4.len+1;
! 565: sec_ctx.buf = $4.buf;
! 566: }
! 567: ;
! 568:
! 569: /* definition about command for SPD management */
! 570: /* spdadd */
! 571: spdadd_command
! 572: /* XXX merge with spdupdate ??? */
! 573: : SPDADD ipaddropts STRING prefix portstr STRING prefix portstr upper_spec upper_misc_spec context_spec policy_spec EOT
! 574: {
! 575: int status;
! 576: struct addrinfo *src, *dst;
! 577:
! 578: #ifdef HAVE_PFKEY_POLICY_PRIORITY
! 579: last_msg_type = SADB_X_SPDADD;
! 580: #endif
! 581:
! 582: /* fixed port fields if ulp is icmp */
! 583: if (fix_portstr($9, &$10, &$5, &$8))
! 584: return -1;
! 585:
! 586: src = parse_addr($3.buf, $5.buf);
! 587: dst = parse_addr($6.buf, $8.buf);
! 588: if (!src || !dst) {
! 589: /* yyerror is already called */
! 590: return -1;
! 591: }
! 592: if (src->ai_next || dst->ai_next) {
! 593: yyerror("multiple address specified");
! 594: freeaddrinfo(src);
! 595: freeaddrinfo(dst);
! 596: return -1;
! 597: }
! 598:
! 599: status = setkeymsg_spdaddr(SADB_X_SPDADD, $9, &$12,
! 600: src, $4, dst, $7);
! 601: freeaddrinfo(src);
! 602: freeaddrinfo(dst);
! 603: if (status < 0)
! 604: return -1;
! 605: }
! 606: | SPDADD TAGGED QUOTEDSTRING policy_spec EOT
! 607: {
! 608: int status;
! 609:
! 610: status = setkeymsg_spdaddr_tag(SADB_X_SPDADD,
! 611: $3.buf, &$4);
! 612: if (status < 0)
! 613: return -1;
! 614: }
! 615: ;
! 616:
! 617: spdupdate_command
! 618: /* XXX merge with spdadd ??? */
! 619: : SPDUPDATE ipaddropts STRING prefix portstr STRING prefix portstr upper_spec upper_misc_spec context_spec policy_spec EOT
! 620: {
! 621: int status;
! 622: struct addrinfo *src, *dst;
! 623:
! 624: #ifdef HAVE_PFKEY_POLICY_PRIORITY
! 625: last_msg_type = SADB_X_SPDUPDATE;
! 626: #endif
! 627:
! 628: /* fixed port fields if ulp is icmp */
! 629: if (fix_portstr($9, &$10, &$5, &$8))
! 630: return -1;
! 631:
! 632: src = parse_addr($3.buf, $5.buf);
! 633: dst = parse_addr($6.buf, $8.buf);
! 634: if (!src || !dst) {
! 635: /* yyerror is already called */
! 636: return -1;
! 637: }
! 638: if (src->ai_next || dst->ai_next) {
! 639: yyerror("multiple address specified");
! 640: freeaddrinfo(src);
! 641: freeaddrinfo(dst);
! 642: return -1;
! 643: }
! 644:
! 645: status = setkeymsg_spdaddr(SADB_X_SPDUPDATE, $9, &$12,
! 646: src, $4, dst, $7);
! 647: freeaddrinfo(src);
! 648: freeaddrinfo(dst);
! 649: if (status < 0)
! 650: return -1;
! 651: }
! 652: | SPDUPDATE TAGGED QUOTEDSTRING policy_spec EOT
! 653: {
! 654: int status;
! 655:
! 656: status = setkeymsg_spdaddr_tag(SADB_X_SPDUPDATE,
! 657: $3.buf, &$4);
! 658: if (status < 0)
! 659: return -1;
! 660: }
! 661: ;
! 662:
! 663: spddelete_command
! 664: : SPDDELETE ipaddropts STRING prefix portstr STRING prefix portstr upper_spec upper_misc_spec context_spec policy_spec EOT
! 665: {
! 666: int status;
! 667: struct addrinfo *src, *dst;
! 668:
! 669: /* fixed port fields if ulp is icmp */
! 670: if (fix_portstr($9, &$10, &$5, &$8))
! 671: return -1;
! 672:
! 673: src = parse_addr($3.buf, $5.buf);
! 674: dst = parse_addr($6.buf, $8.buf);
! 675: if (!src || !dst) {
! 676: /* yyerror is already called */
! 677: return -1;
! 678: }
! 679: if (src->ai_next || dst->ai_next) {
! 680: yyerror("multiple address specified");
! 681: freeaddrinfo(src);
! 682: freeaddrinfo(dst);
! 683: return -1;
! 684: }
! 685:
! 686: status = setkeymsg_spdaddr(SADB_X_SPDDELETE, $9, &$12,
! 687: src, $4, dst, $7);
! 688: freeaddrinfo(src);
! 689: freeaddrinfo(dst);
! 690: if (status < 0)
! 691: return -1;
! 692: }
! 693: ;
! 694:
! 695: spddump_command:
! 696: SPDDUMP EOT
! 697: {
! 698: struct sadb_msg msg;
! 699: setkeymsg0(&msg, SADB_X_SPDDUMP, SADB_SATYPE_UNSPEC,
! 700: sizeof(msg));
! 701: sendkeymsg((char *)&msg, sizeof(msg));
! 702: }
! 703: ;
! 704:
! 705: spdflush_command
! 706: :
! 707: SPDFLUSH EOT
! 708: {
! 709: struct sadb_msg msg;
! 710: setkeymsg0(&msg, SADB_X_SPDFLUSH, SADB_SATYPE_UNSPEC,
! 711: sizeof(msg));
! 712: sendkeymsg((char *)&msg, sizeof(msg));
! 713: }
! 714: ;
! 715:
! 716: ipaddropts
! 717: : /* nothing */
! 718: | ipaddropts ipaddropt
! 719: ;
! 720:
! 721: ipaddropt
! 722: : F_AIFLAGS
! 723: {
! 724: char *p;
! 725:
! 726: for (p = $1.buf + 1; *p; p++)
! 727: switch (*p) {
! 728: case '4':
! 729: p_aifamily = AF_INET;
! 730: break;
! 731: #ifdef INET6
! 732: case '6':
! 733: p_aifamily = AF_INET6;
! 734: break;
! 735: #endif
! 736: case 'n':
! 737: p_aiflags = AI_NUMERICHOST;
! 738: break;
! 739: default:
! 740: yyerror("invalid flag");
! 741: return -1;
! 742: }
! 743: }
! 744: ;
! 745:
! 746: ipaddr
! 747: : STRING
! 748: {
! 749: $$ = parse_addr($1.buf, NULL);
! 750: if ($$ == NULL) {
! 751: /* yyerror already called by parse_addr */
! 752: return -1;
! 753: }
! 754: }
! 755: ;
! 756:
! 757: ipandport
! 758: : STRING
! 759: {
! 760: $$ = parse_addr($1.buf, NULL);
! 761: if ($$ == NULL) {
! 762: /* yyerror already called by parse_addr */
! 763: return -1;
! 764: }
! 765: }
! 766: | STRING portstr
! 767: {
! 768: $$ = parse_addr($1.buf, $2.buf);
! 769: if ($$ == NULL) {
! 770: /* yyerror already called by parse_addr */
! 771: return -1;
! 772: }
! 773: }
! 774: ;
! 775:
! 776: prefix
! 777: : /*NOTHING*/ { $$ = -1; }
! 778: | SLASH DECSTRING { $$ = $2; }
! 779: ;
! 780:
! 781: portstr
! 782: : /*NOTHING*/
! 783: {
! 784: $$.buf = strdup("0");
! 785: if (!$$.buf) {
! 786: yyerror("insufficient memory");
! 787: return -1;
! 788: }
! 789: $$.len = strlen($$.buf);
! 790: }
! 791: | BLCL ANY ELCL
! 792: {
! 793: $$.buf = strdup("0");
! 794: if (!$$.buf) {
! 795: yyerror("insufficient memory");
! 796: return -1;
! 797: }
! 798: $$.len = strlen($$.buf);
! 799: }
! 800: | BLCL DECSTRING ELCL
! 801: {
! 802: char buf[20];
! 803: snprintf(buf, sizeof(buf), "%lu", $2);
! 804: $$.buf = strdup(buf);
! 805: if (!$$.buf) {
! 806: yyerror("insufficient memory");
! 807: return -1;
! 808: }
! 809: $$.len = strlen($$.buf);
! 810: }
! 811: | BLCL STRING ELCL
! 812: {
! 813: $$ = $2;
! 814: }
! 815: ;
! 816:
! 817: upper_spec
! 818: : DECSTRING { $$ = $1; }
! 819: | ANY { $$ = IPSEC_ULPROTO_ANY; }
! 820: | PR_TCP {
! 821: $$ = IPPROTO_TCP;
! 822: }
! 823: | STRING
! 824: {
! 825: struct protoent *ent;
! 826:
! 827: ent = getprotobyname($1.buf);
! 828: if (ent)
! 829: $$ = ent->p_proto;
! 830: else {
! 831: if (strcmp("icmp6", $1.buf) == 0) {
! 832: $$ = IPPROTO_ICMPV6;
! 833: } else if(strcmp("ip4", $1.buf) == 0) {
! 834: $$ = IPPROTO_IPV4;
! 835: } else {
! 836: yyerror("invalid upper layer protocol");
! 837: return -1;
! 838: }
! 839: }
! 840: endprotoent();
! 841: }
! 842: ;
! 843:
! 844: upper_misc_spec
! 845: : /*NOTHING*/
! 846: {
! 847: $$.buf = NULL;
! 848: $$.len = 0;
! 849: }
! 850: | STRING
! 851: {
! 852: $$.buf = strdup($1.buf);
! 853: if (!$$.buf) {
! 854: yyerror("insufficient memory");
! 855: return -1;
! 856: }
! 857: $$.len = strlen($$.buf);
! 858: }
! 859: ;
! 860:
! 861: context_spec
! 862: : /* NOTHING */
! 863: | SECURITY_CTX DECSTRING DECSTRING QUOTEDSTRING {
! 864: sec_ctx.doi = $2;
! 865: sec_ctx.alg = $3;
! 866: sec_ctx.len = $4.len+1;
! 867: sec_ctx.buf = $4.buf;
! 868: }
! 869: ;
! 870:
! 871: policy_spec
! 872: : F_POLICY policy_requests
! 873: {
! 874: char *policy;
! 875: #ifdef HAVE_PFKEY_POLICY_PRIORITY
! 876: struct sadb_x_policy *xpl;
! 877: #endif
! 878:
! 879: policy = ipsec_set_policy($2.buf, $2.len);
! 880: if (policy == NULL) {
! 881: yyerror(ipsec_strerror());
! 882: return -1;
! 883: }
! 884:
! 885: $$.buf = policy;
! 886: $$.len = ipsec_get_policylen(policy);
! 887:
! 888: #ifdef HAVE_PFKEY_POLICY_PRIORITY
! 889: xpl = (struct sadb_x_policy *) $$.buf;
! 890: last_priority = xpl->sadb_x_policy_priority;
! 891: #endif
! 892: }
! 893: ;
! 894:
! 895: policy_requests
! 896: : PL_REQUESTS { $$ = $1; }
! 897: ;
! 898:
! 899: /* exit */
! 900: exit_command
! 901: : EXIT EOT
! 902: {
! 903: exit_now = 1;
! 904: YYACCEPT;
! 905: }
! 906: ;
! 907: %%
! 908:
! 909: int
! 910: setkeymsg0(msg, type, satype, l)
! 911: struct sadb_msg *msg;
! 912: unsigned int type;
! 913: unsigned int satype;
! 914: size_t l;
! 915: {
! 916:
! 917: msg->sadb_msg_version = PF_KEY_V2;
! 918: msg->sadb_msg_type = type;
! 919: msg->sadb_msg_errno = 0;
! 920: msg->sadb_msg_satype = satype;
! 921: msg->sadb_msg_reserved = 0;
! 922: msg->sadb_msg_seq = 0;
! 923: msg->sadb_msg_pid = getpid();
! 924: msg->sadb_msg_len = PFKEY_UNIT64(l);
! 925: return 0;
! 926: }
! 927:
! 928: /* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
! 929: static int
! 930: setkeymsg_spdaddr(type, upper, policy, srcs, splen, dsts, dplen)
! 931: unsigned int type;
! 932: unsigned int upper;
! 933: vchar_t *policy;
! 934: struct addrinfo *srcs;
! 935: int splen;
! 936: struct addrinfo *dsts;
! 937: int dplen;
! 938: {
! 939: struct sadb_msg *msg;
! 940: char buf[BUFSIZ];
! 941: int l, l0;
! 942: struct sadb_address m_addr;
! 943: struct addrinfo *s, *d;
! 944: int n;
! 945: int plen;
! 946: struct sockaddr *sa;
! 947: int salen;
! 948: struct sadb_x_policy *sp;
! 949: #ifdef HAVE_POLICY_FWD
! 950: struct sadb_x_ipsecrequest *ps = NULL;
! 951: int saved_level, saved_id = 0;
! 952: #endif
! 953:
! 954: msg = (struct sadb_msg *)buf;
! 955:
! 956: if (!srcs || !dsts)
! 957: return -1;
! 958:
! 959: /* fix up length afterwards */
! 960: setkeymsg0(msg, type, SADB_SATYPE_UNSPEC, 0);
! 961: l = sizeof(struct sadb_msg);
! 962:
! 963: sp = (struct sadb_x_policy*) (buf + l);
! 964: memcpy(buf + l, policy->buf, policy->len);
! 965: l += policy->len;
! 966:
! 967: l0 = l;
! 968: n = 0;
! 969:
! 970: /* do it for all src/dst pairs */
! 971: for (s = srcs; s; s = s->ai_next) {
! 972: for (d = dsts; d; d = d->ai_next) {
! 973: /* rewind pointer */
! 974: l = l0;
! 975:
! 976: if (s->ai_addr->sa_family != d->ai_addr->sa_family)
! 977: continue;
! 978: switch (s->ai_addr->sa_family) {
! 979: case AF_INET:
! 980: plen = sizeof(struct in_addr) << 3;
! 981: break;
! 982: #ifdef INET6
! 983: case AF_INET6:
! 984: plen = sizeof(struct in6_addr) << 3;
! 985: break;
! 986: #endif
! 987: default:
! 988: continue;
! 989: }
! 990:
! 991: /* set src */
! 992: sa = s->ai_addr;
! 993: salen = sysdep_sa_len(s->ai_addr);
! 994: m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
! 995: PFKEY_ALIGN8(salen));
! 996: m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
! 997: m_addr.sadb_address_proto = upper;
! 998: m_addr.sadb_address_prefixlen =
! 999: (splen >= 0 ? splen : plen);
! 1000: m_addr.sadb_address_reserved = 0;
! 1001:
! 1002: setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
! 1003: sizeof(m_addr), (caddr_t)sa, salen);
! 1004:
! 1005: /* set dst */
! 1006: sa = d->ai_addr;
! 1007: salen = sysdep_sa_len(d->ai_addr);
! 1008: m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
! 1009: PFKEY_ALIGN8(salen));
! 1010: m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
! 1011: m_addr.sadb_address_proto = upper;
! 1012: m_addr.sadb_address_prefixlen =
! 1013: (dplen >= 0 ? dplen : plen);
! 1014: m_addr.sadb_address_reserved = 0;
! 1015:
! 1016: setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
! 1017: sizeof(m_addr), sa, salen);
! 1018: #ifdef SADB_X_EXT_SEC_CTX
! 1019: /* Add security context label */
! 1020: if (sec_ctx.doi) {
! 1021: struct sadb_x_sec_ctx m_sec_ctx;
! 1022: u_int slen = sizeof(struct sadb_x_sec_ctx);
! 1023:
! 1024: memset(&m_sec_ctx, 0, slen);
! 1025:
! 1026: m_sec_ctx.sadb_x_sec_len =
! 1027: PFKEY_UNIT64(slen + PFKEY_ALIGN8(sec_ctx.len));
! 1028:
! 1029: m_sec_ctx.sadb_x_sec_exttype =
! 1030: SADB_X_EXT_SEC_CTX;
! 1031: m_sec_ctx.sadb_x_ctx_len = sec_ctx.len;/*bytes*/
! 1032: m_sec_ctx.sadb_x_ctx_doi = sec_ctx.doi;
! 1033: m_sec_ctx.sadb_x_ctx_alg = sec_ctx.alg;
! 1034: setvarbuf(buf, &l,
! 1035: (struct sadb_ext *)&m_sec_ctx, slen,
! 1036: (caddr_t)sec_ctx.buf, sec_ctx.len);
! 1037: }
! 1038: #endif
! 1039: msg->sadb_msg_len = PFKEY_UNIT64(l);
! 1040:
! 1041: sendkeymsg(buf, l);
! 1042:
! 1043: #ifdef HAVE_POLICY_FWD
! 1044: /* create extra call for FWD policy */
! 1045: if (f_rfcmode && sp->sadb_x_policy_dir == IPSEC_DIR_INBOUND) {
! 1046: sp->sadb_x_policy_dir = IPSEC_DIR_FWD;
! 1047: ps = (struct sadb_x_ipsecrequest*) (sp+1);
! 1048:
! 1049: /* if request level is unique, change it to
! 1050: * require for fwd policy */
! 1051: /* XXX: currently, only first policy is updated
! 1052: * only. Update following too... */
! 1053: saved_level = ps->sadb_x_ipsecrequest_level;
! 1054: if (saved_level == IPSEC_LEVEL_UNIQUE) {
! 1055: saved_id = ps->sadb_x_ipsecrequest_reqid;
! 1056: ps->sadb_x_ipsecrequest_reqid=0;
! 1057: ps->sadb_x_ipsecrequest_level=IPSEC_LEVEL_REQUIRE;
! 1058: }
! 1059:
! 1060: sendkeymsg(buf, l);
! 1061: /* restoring for next message */
! 1062: sp->sadb_x_policy_dir = IPSEC_DIR_INBOUND;
! 1063: if (saved_level == IPSEC_LEVEL_UNIQUE) {
! 1064: ps->sadb_x_ipsecrequest_reqid = saved_id;
! 1065: ps->sadb_x_ipsecrequest_level = saved_level;
! 1066: }
! 1067: }
! 1068: #endif
! 1069:
! 1070: n++;
! 1071: }
! 1072: }
! 1073:
! 1074: if (n == 0)
! 1075: return -1;
! 1076: else
! 1077: return 0;
! 1078: }
! 1079:
! 1080: static int
! 1081: setkeymsg_spdaddr_tag(type, tag, policy)
! 1082: unsigned int type;
! 1083: char *tag;
! 1084: vchar_t *policy;
! 1085: {
! 1086: struct sadb_msg *msg;
! 1087: char buf[BUFSIZ];
! 1088: int l, l0;
! 1089: #ifdef SADB_X_EXT_TAG
! 1090: struct sadb_x_tag m_tag;
! 1091: #endif
! 1092: int n;
! 1093:
! 1094: msg = (struct sadb_msg *)buf;
! 1095:
! 1096: /* fix up length afterwards */
! 1097: setkeymsg0(msg, type, SADB_SATYPE_UNSPEC, 0);
! 1098: l = sizeof(struct sadb_msg);
! 1099:
! 1100: memcpy(buf + l, policy->buf, policy->len);
! 1101: l += policy->len;
! 1102:
! 1103: l0 = l;
! 1104: n = 0;
! 1105:
! 1106: #ifdef SADB_X_EXT_TAG
! 1107: memset(&m_tag, 0, sizeof(m_tag));
! 1108: m_tag.sadb_x_tag_len = PFKEY_UNIT64(sizeof(m_tag));
! 1109: m_tag.sadb_x_tag_exttype = SADB_X_EXT_TAG;
! 1110: if (strlcpy(m_tag.sadb_x_tag_name, tag,
! 1111: sizeof(m_tag.sadb_x_tag_name)) >= sizeof(m_tag.sadb_x_tag_name))
! 1112: return -1;
! 1113: memcpy(buf + l, &m_tag, sizeof(m_tag));
! 1114: l += sizeof(m_tag);
! 1115: #endif
! 1116:
! 1117: msg->sadb_msg_len = PFKEY_UNIT64(l);
! 1118:
! 1119: sendkeymsg(buf, l);
! 1120:
! 1121: return 0;
! 1122: }
! 1123:
! 1124: /* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
! 1125: static int
! 1126: setkeymsg_addr(type, satype, srcs, dsts, no_spi)
! 1127: unsigned int type;
! 1128: unsigned int satype;
! 1129: struct addrinfo *srcs;
! 1130: struct addrinfo *dsts;
! 1131: int no_spi;
! 1132: {
! 1133: struct sadb_msg *msg;
! 1134: char buf[BUFSIZ];
! 1135: int l, l0, len;
! 1136: struct sadb_sa m_sa;
! 1137: struct sadb_x_sa2 m_sa2;
! 1138: struct sadb_address m_addr;
! 1139: struct addrinfo *s, *d;
! 1140: int n;
! 1141: int plen;
! 1142: struct sockaddr *sa;
! 1143: int salen;
! 1144:
! 1145: msg = (struct sadb_msg *)buf;
! 1146:
! 1147: if (!srcs || !dsts)
! 1148: return -1;
! 1149:
! 1150: /* fix up length afterwards */
! 1151: setkeymsg0(msg, type, satype, 0);
! 1152: l = sizeof(struct sadb_msg);
! 1153:
! 1154: if (!no_spi) {
! 1155: len = sizeof(struct sadb_sa);
! 1156: m_sa.sadb_sa_len = PFKEY_UNIT64(len);
! 1157: m_sa.sadb_sa_exttype = SADB_EXT_SA;
! 1158: m_sa.sadb_sa_spi = htonl(p_spi);
! 1159: m_sa.sadb_sa_replay = p_replay;
! 1160: m_sa.sadb_sa_state = 0;
! 1161: m_sa.sadb_sa_auth = p_alg_auth;
! 1162: m_sa.sadb_sa_encrypt = p_alg_enc;
! 1163: m_sa.sadb_sa_flags = p_ext;
! 1164:
! 1165: memcpy(buf + l, &m_sa, len);
! 1166: l += len;
! 1167:
! 1168: len = sizeof(struct sadb_x_sa2);
! 1169: m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len);
! 1170: m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
! 1171: m_sa2.sadb_x_sa2_mode = p_mode;
! 1172: m_sa2.sadb_x_sa2_reqid = p_reqid;
! 1173:
! 1174: memcpy(buf + l, &m_sa2, len);
! 1175: l += len;
! 1176: }
! 1177:
! 1178: l0 = l;
! 1179: n = 0;
! 1180:
! 1181: /* do it for all src/dst pairs */
! 1182: for (s = srcs; s; s = s->ai_next) {
! 1183: for (d = dsts; d; d = d->ai_next) {
! 1184: /* rewind pointer */
! 1185: l = l0;
! 1186:
! 1187: if (s->ai_addr->sa_family != d->ai_addr->sa_family)
! 1188: continue;
! 1189: switch (s->ai_addr->sa_family) {
! 1190: case AF_INET:
! 1191: plen = sizeof(struct in_addr) << 3;
! 1192: break;
! 1193: #ifdef INET6
! 1194: case AF_INET6:
! 1195: plen = sizeof(struct in6_addr) << 3;
! 1196: break;
! 1197: #endif
! 1198: default:
! 1199: continue;
! 1200: }
! 1201:
! 1202: /* set src */
! 1203: sa = s->ai_addr;
! 1204: salen = sysdep_sa_len(s->ai_addr);
! 1205: m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
! 1206: PFKEY_ALIGN8(salen));
! 1207: m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
! 1208: m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
! 1209: m_addr.sadb_address_prefixlen = plen;
! 1210: m_addr.sadb_address_reserved = 0;
! 1211:
! 1212: setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
! 1213: sizeof(m_addr), sa, salen);
! 1214:
! 1215: /* set dst */
! 1216: sa = d->ai_addr;
! 1217: salen = sysdep_sa_len(d->ai_addr);
! 1218: m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
! 1219: PFKEY_ALIGN8(salen));
! 1220: m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
! 1221: m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
! 1222: m_addr.sadb_address_prefixlen = plen;
! 1223: m_addr.sadb_address_reserved = 0;
! 1224:
! 1225: setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
! 1226: sizeof(m_addr), sa, salen);
! 1227:
! 1228: msg->sadb_msg_len = PFKEY_UNIT64(l);
! 1229:
! 1230: sendkeymsg(buf, l);
! 1231:
! 1232: n++;
! 1233: }
! 1234: }
! 1235:
! 1236: if (n == 0)
! 1237: return -1;
! 1238: else
! 1239: return 0;
! 1240: }
! 1241:
! 1242: #ifdef SADB_X_EXT_NAT_T_TYPE
! 1243: static u_int16_t get_port (struct addrinfo *addr)
! 1244: {
! 1245: struct sockaddr *s = addr->ai_addr;
! 1246: u_int16_t port = 0;
! 1247:
! 1248: switch (s->sa_family) {
! 1249: case AF_INET:
! 1250: {
! 1251: struct sockaddr_in *sin4 = (struct sockaddr_in *)s;
! 1252: port = ntohs(sin4->sin_port);
! 1253: break;
! 1254: }
! 1255: case AF_INET6:
! 1256: {
! 1257: struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)s;
! 1258: port = ntohs(sin6->sin6_port);
! 1259: break;
! 1260: }
! 1261: }
! 1262:
! 1263: if (port == 0)
! 1264: port = DEFAULT_NATT_PORT;
! 1265:
! 1266: return port;
! 1267: }
! 1268: #endif
! 1269:
! 1270: /* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
! 1271: static int
! 1272: setkeymsg_add(type, satype, srcs, dsts)
! 1273: unsigned int type;
! 1274: unsigned int satype;
! 1275: struct addrinfo *srcs;
! 1276: struct addrinfo *dsts;
! 1277: {
! 1278: struct sadb_msg *msg;
! 1279: char buf[BUFSIZ];
! 1280: int l, l0, len;
! 1281: struct sadb_sa m_sa;
! 1282: struct sadb_x_sa2 m_sa2;
! 1283: struct sadb_address m_addr;
! 1284: struct addrinfo *s, *d;
! 1285: int n;
! 1286: int plen;
! 1287: struct sockaddr *sa;
! 1288: int salen;
! 1289:
! 1290: msg = (struct sadb_msg *)buf;
! 1291:
! 1292: if (!srcs || !dsts)
! 1293: return -1;
! 1294:
! 1295: /* fix up length afterwards */
! 1296: setkeymsg0(msg, type, satype, 0);
! 1297: l = sizeof(struct sadb_msg);
! 1298:
! 1299: /* set encryption algorithm, if present. */
! 1300: if (satype != SADB_X_SATYPE_IPCOMP && p_key_enc) {
! 1301: union {
! 1302: struct sadb_key key;
! 1303: struct sadb_ext ext;
! 1304: } m;
! 1305:
! 1306: m.key.sadb_key_len =
! 1307: PFKEY_UNIT64(sizeof(m.key)
! 1308: + PFKEY_ALIGN8(p_key_enc_len));
! 1309: m.key.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
! 1310: m.key.sadb_key_bits = p_key_enc_len * 8;
! 1311: m.key.sadb_key_reserved = 0;
! 1312:
! 1313: setvarbuf(buf, &l, &m.ext, sizeof(m.key),
! 1314: p_key_enc, p_key_enc_len);
! 1315: }
! 1316:
! 1317: /* set authentication algorithm, if present. */
! 1318: if (p_key_auth) {
! 1319: union {
! 1320: struct sadb_key key;
! 1321: struct sadb_ext ext;
! 1322: } m;
! 1323:
! 1324: m.key.sadb_key_len =
! 1325: PFKEY_UNIT64(sizeof(m.key)
! 1326: + PFKEY_ALIGN8(p_key_auth_len));
! 1327: m.key.sadb_key_exttype = SADB_EXT_KEY_AUTH;
! 1328: m.key.sadb_key_bits = p_key_auth_len * 8;
! 1329: m.key.sadb_key_reserved = 0;
! 1330:
! 1331: setvarbuf(buf, &l, &m.ext, sizeof(m.key),
! 1332: p_key_auth, p_key_auth_len);
! 1333: }
! 1334:
! 1335: /* set lifetime for HARD */
! 1336: if (p_lt_hard != 0 || p_lb_hard != 0) {
! 1337: struct sadb_lifetime m_lt;
! 1338: u_int slen = sizeof(struct sadb_lifetime);
! 1339:
! 1340: m_lt.sadb_lifetime_len = PFKEY_UNIT64(slen);
! 1341: m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
! 1342: m_lt.sadb_lifetime_allocations = 0;
! 1343: m_lt.sadb_lifetime_bytes = p_lb_hard;
! 1344: m_lt.sadb_lifetime_addtime = p_lt_hard;
! 1345: m_lt.sadb_lifetime_usetime = 0;
! 1346:
! 1347: memcpy(buf + l, &m_lt, slen);
! 1348: l += slen;
! 1349: }
! 1350:
! 1351: /* set lifetime for SOFT */
! 1352: if (p_lt_soft != 0 || p_lb_soft != 0) {
! 1353: struct sadb_lifetime m_lt;
! 1354: u_int slen = sizeof(struct sadb_lifetime);
! 1355:
! 1356: m_lt.sadb_lifetime_len = PFKEY_UNIT64(slen);
! 1357: m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
! 1358: m_lt.sadb_lifetime_allocations = 0;
! 1359: m_lt.sadb_lifetime_bytes = p_lb_soft;
! 1360: m_lt.sadb_lifetime_addtime = p_lt_soft;
! 1361: m_lt.sadb_lifetime_usetime = 0;
! 1362:
! 1363: memcpy(buf + l, &m_lt, slen);
! 1364: l += slen;
! 1365: }
! 1366:
! 1367: #ifdef SADB_X_EXT_SEC_CTX
! 1368: /* Add security context label */
! 1369: if (sec_ctx.doi) {
! 1370: struct sadb_x_sec_ctx m_sec_ctx;
! 1371: u_int slen = sizeof(struct sadb_x_sec_ctx);
! 1372:
! 1373: memset(&m_sec_ctx, 0, slen);
! 1374:
! 1375: m_sec_ctx.sadb_x_sec_len = PFKEY_UNIT64(slen +
! 1376: PFKEY_ALIGN8(sec_ctx.len));
! 1377: m_sec_ctx.sadb_x_sec_exttype = SADB_X_EXT_SEC_CTX;
! 1378: m_sec_ctx.sadb_x_ctx_len = sec_ctx.len; /* bytes */
! 1379: m_sec_ctx.sadb_x_ctx_doi = sec_ctx.doi;
! 1380: m_sec_ctx.sadb_x_ctx_alg = sec_ctx.alg;
! 1381: setvarbuf(buf, &l, (struct sadb_ext *)&m_sec_ctx, slen,
! 1382: (caddr_t)sec_ctx.buf, sec_ctx.len);
! 1383: }
! 1384: #endif
! 1385:
! 1386: len = sizeof(struct sadb_sa);
! 1387: m_sa.sadb_sa_len = PFKEY_UNIT64(len);
! 1388: m_sa.sadb_sa_exttype = SADB_EXT_SA;
! 1389: m_sa.sadb_sa_spi = htonl(p_spi);
! 1390: m_sa.sadb_sa_replay = p_replay;
! 1391: m_sa.sadb_sa_state = 0;
! 1392: m_sa.sadb_sa_auth = p_alg_auth;
! 1393: m_sa.sadb_sa_encrypt = p_alg_enc;
! 1394: m_sa.sadb_sa_flags = p_ext;
! 1395:
! 1396: memcpy(buf + l, &m_sa, len);
! 1397: l += len;
! 1398:
! 1399: len = sizeof(struct sadb_x_sa2);
! 1400: m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len);
! 1401: m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
! 1402: m_sa2.sadb_x_sa2_mode = p_mode;
! 1403: m_sa2.sadb_x_sa2_reqid = p_reqid;
! 1404:
! 1405: memcpy(buf + l, &m_sa2, len);
! 1406: l += len;
! 1407:
! 1408: #ifdef SADB_X_EXT_NAT_T_TYPE
! 1409: if (p_natt_type) {
! 1410: struct sadb_x_nat_t_type natt_type;
! 1411:
! 1412: len = sizeof(struct sadb_x_nat_t_type);
! 1413: memset(&natt_type, 0, len);
! 1414: natt_type.sadb_x_nat_t_type_len = PFKEY_UNIT64(len);
! 1415: natt_type.sadb_x_nat_t_type_exttype = SADB_X_EXT_NAT_T_TYPE;
! 1416: natt_type.sadb_x_nat_t_type_type = p_natt_type;
! 1417:
! 1418: memcpy(buf + l, &natt_type, len);
! 1419: l += len;
! 1420:
! 1421: if (p_natt_oa) {
! 1422: sa = p_natt_oa->ai_addr;
! 1423: switch (sa->sa_family) {
! 1424: case AF_INET:
! 1425: plen = sizeof(struct in_addr) << 3;
! 1426: break;
! 1427: #ifdef INET6
! 1428: case AF_INET6:
! 1429: plen = sizeof(struct in6_addr) << 3;
! 1430: break;
! 1431: #endif
! 1432: default:
! 1433: return -1;
! 1434: }
! 1435: salen = sysdep_sa_len(sa);
! 1436: m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
! 1437: PFKEY_ALIGN8(salen));
! 1438: m_addr.sadb_address_exttype = SADB_X_EXT_NAT_T_OA;
! 1439: m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
! 1440: m_addr.sadb_address_prefixlen = plen;
! 1441: m_addr.sadb_address_reserved = 0;
! 1442:
! 1443: setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
! 1444: sizeof(m_addr), sa, salen);
! 1445: }
! 1446: }
! 1447: #endif
! 1448:
! 1449: l0 = l;
! 1450: n = 0;
! 1451:
! 1452: /* do it for all src/dst pairs */
! 1453: for (s = srcs; s; s = s->ai_next) {
! 1454: for (d = dsts; d; d = d->ai_next) {
! 1455: /* rewind pointer */
! 1456: l = l0;
! 1457:
! 1458: if (s->ai_addr->sa_family != d->ai_addr->sa_family)
! 1459: continue;
! 1460: switch (s->ai_addr->sa_family) {
! 1461: case AF_INET:
! 1462: plen = sizeof(struct in_addr) << 3;
! 1463: break;
! 1464: #ifdef INET6
! 1465: case AF_INET6:
! 1466: plen = sizeof(struct in6_addr) << 3;
! 1467: break;
! 1468: #endif
! 1469: default:
! 1470: continue;
! 1471: }
! 1472:
! 1473: /* set src */
! 1474: sa = s->ai_addr;
! 1475: salen = sysdep_sa_len(s->ai_addr);
! 1476: m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
! 1477: PFKEY_ALIGN8(salen));
! 1478: m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
! 1479: m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
! 1480: m_addr.sadb_address_prefixlen = plen;
! 1481: m_addr.sadb_address_reserved = 0;
! 1482:
! 1483: setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
! 1484: sizeof(m_addr), sa, salen);
! 1485:
! 1486: /* set dst */
! 1487: sa = d->ai_addr;
! 1488: salen = sysdep_sa_len(d->ai_addr);
! 1489: m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
! 1490: PFKEY_ALIGN8(salen));
! 1491: m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
! 1492: m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
! 1493: m_addr.sadb_address_prefixlen = plen;
! 1494: m_addr.sadb_address_reserved = 0;
! 1495:
! 1496: setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
! 1497: sizeof(m_addr), sa, salen);
! 1498:
! 1499: #ifdef SADB_X_EXT_NAT_T_TYPE
! 1500: if (p_natt_type) {
! 1501: struct sadb_x_nat_t_port natt_port;
! 1502:
! 1503: /* NATT_SPORT */
! 1504: len = sizeof(struct sadb_x_nat_t_port);
! 1505: memset(&natt_port, 0, len);
! 1506: natt_port.sadb_x_nat_t_port_len = PFKEY_UNIT64(len);
! 1507: natt_port.sadb_x_nat_t_port_exttype =
! 1508: SADB_X_EXT_NAT_T_SPORT;
! 1509: natt_port.sadb_x_nat_t_port_port = htons(get_port(s));
! 1510:
! 1511: memcpy(buf + l, &natt_port, len);
! 1512: l += len;
! 1513:
! 1514: /* NATT_DPORT */
! 1515: natt_port.sadb_x_nat_t_port_exttype =
! 1516: SADB_X_EXT_NAT_T_DPORT;
! 1517: natt_port.sadb_x_nat_t_port_port = htons(get_port(d));
! 1518:
! 1519: memcpy(buf + l, &natt_port, len);
! 1520: l += len;
! 1521: }
! 1522: #endif
! 1523: msg->sadb_msg_len = PFKEY_UNIT64(l);
! 1524:
! 1525: sendkeymsg(buf, l);
! 1526:
! 1527: n++;
! 1528: }
! 1529: }
! 1530:
! 1531: if (n == 0)
! 1532: return -1;
! 1533: else
! 1534: return 0;
! 1535: }
! 1536:
! 1537: static struct addrinfo *
! 1538: parse_addr(host, port)
! 1539: char *host;
! 1540: char *port;
! 1541: {
! 1542: struct addrinfo hints, *res = NULL;
! 1543: int error;
! 1544:
! 1545: memset(&hints, 0, sizeof(hints));
! 1546: hints.ai_family = p_aifamily;
! 1547: hints.ai_socktype = SOCK_DGRAM; /*dummy*/
! 1548: hints.ai_protocol = IPPROTO_UDP; /*dummy*/
! 1549: hints.ai_flags = p_aiflags;
! 1550: error = getaddrinfo(host, port, &hints, &res);
! 1551: if (error != 0) {
! 1552: yyerror(gai_strerror(error));
! 1553: return NULL;
! 1554: }
! 1555: return res;
! 1556: }
! 1557:
! 1558: static int
! 1559: fix_portstr(ulproto, spec, sport, dport)
! 1560: int ulproto;
! 1561: vchar_t *spec, *sport, *dport;
! 1562: {
! 1563: char sp[16], dp[16];
! 1564: int a, b, c, d;
! 1565: unsigned long u;
! 1566:
! 1567: if (spec->buf == NULL)
! 1568: return 0;
! 1569:
! 1570: switch (ulproto) {
! 1571: case IPPROTO_ICMP:
! 1572: case IPPROTO_ICMPV6:
! 1573: case IPPROTO_MH:
! 1574: if (sscanf(spec->buf, "%d,%d", &a, &b) == 2) {
! 1575: sprintf(sp, "%d", a);
! 1576: sprintf(dp, "%d", b);
! 1577: } else if (sscanf(spec->buf, "%d", &a) == 1) {
! 1578: sprintf(sp, "%d", a);
! 1579: } else {
! 1580: yyerror("invalid an upper layer protocol spec");
! 1581: return -1;
! 1582: }
! 1583: break;
! 1584: case IPPROTO_GRE:
! 1585: if (sscanf(spec->buf, "%d.%d.%d.%d", &a, &b, &c, &d) == 4) {
! 1586: sprintf(sp, "%d", (a << 8) + b);
! 1587: sprintf(dp, "%d", (c << 8) + d);
! 1588: } else if (sscanf(spec->buf, "%lu", &u) == 1) {
! 1589: sprintf(sp, "%d", (int) (u >> 16));
! 1590: sprintf(dp, "%d", (int) (u & 0xffff));
! 1591: } else {
! 1592: yyerror("invalid an upper layer protocol spec");
! 1593: return -1;
! 1594: }
! 1595: break;
! 1596: }
! 1597:
! 1598: free(sport->buf);
! 1599: sport->buf = strdup(sp);
! 1600: if (!sport->buf) {
! 1601: yyerror("insufficient memory");
! 1602: return -1;
! 1603: }
! 1604: sport->len = strlen(sport->buf);
! 1605:
! 1606: free(dport->buf);
! 1607: dport->buf = strdup(dp);
! 1608: if (!dport->buf) {
! 1609: yyerror("insufficient memory");
! 1610: return -1;
! 1611: }
! 1612: dport->len = strlen(dport->buf);
! 1613:
! 1614: return 0;
! 1615: }
! 1616:
! 1617: static int
! 1618: setvarbuf(buf, off, ebuf, elen, vbuf, vlen)
! 1619: char *buf;
! 1620: int *off;
! 1621: struct sadb_ext *ebuf;
! 1622: int elen;
! 1623: const void *vbuf;
! 1624: int vlen;
! 1625: {
! 1626: memset(buf + *off, 0, PFKEY_UNUNIT64(ebuf->sadb_ext_len));
! 1627: memcpy(buf + *off, (caddr_t)ebuf, elen);
! 1628: memcpy(buf + *off + elen, vbuf, vlen);
! 1629: (*off) += PFKEY_ALIGN8(elen + vlen);
! 1630:
! 1631: return 0;
! 1632: }
! 1633:
! 1634: void
! 1635: parse_init()
! 1636: {
! 1637: p_spi = 0;
! 1638:
! 1639: p_ext = SADB_X_EXT_CYCSEQ;
! 1640: p_alg_enc = SADB_EALG_NONE;
! 1641: p_alg_auth = SADB_AALG_NONE;
! 1642: p_mode = IPSEC_MODE_ANY;
! 1643: p_reqid = 0;
! 1644: p_replay = 0;
! 1645: p_key_enc_len = p_key_auth_len = 0;
! 1646: p_key_enc = p_key_auth = 0;
! 1647: p_lt_hard = p_lt_soft = 0;
! 1648: p_lb_hard = p_lb_soft = 0;
! 1649:
! 1650: memset(&sec_ctx, 0, sizeof(struct security_ctx));
! 1651:
! 1652: p_aiflags = 0;
! 1653: p_aifamily = PF_UNSPEC;
! 1654:
! 1655: /* Clear out any natt OA information */
! 1656: if (p_natt_oa)
! 1657: freeaddrinfo (p_natt_oa);
! 1658: p_natt_oa = NULL;
! 1659: p_natt_type = 0;
! 1660:
! 1661: return;
! 1662: }
! 1663:
! 1664: void
! 1665: free_buffer()
! 1666: {
! 1667: /* we got tons of memory leaks in the parser anyways, leave them */
! 1668:
! 1669: return;
! 1670: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>