Return to parse.y CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / ipsec-tools / src / setkey |
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: }