Return to pfkey.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / ipsec-tools / src / libipsec |
1.1 ! misho 1: /* $NetBSD: pfkey.c,v 1.21 2011/01/20 16:08:35 vanhu Exp $ */ ! 2: ! 3: /* $KAME: pfkey.c,v 1.47 2003/10/02 19:52:12 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: #ifdef HAVE_CONFIG_H ! 35: #include "config.h" ! 36: #endif ! 37: ! 38: #include <sys/types.h> ! 39: #include <sys/param.h> ! 40: #include <sys/socket.h> ! 41: #include <net/pfkeyv2.h> ! 42: #include <netinet/in.h> ! 43: #include PATH_IPSEC_H ! 44: ! 45: #include <stdlib.h> ! 46: #include <unistd.h> ! 47: #include <string.h> ! 48: #include <errno.h> ! 49: #include <stdio.h> ! 50: ! 51: #include "ipsec_strerror.h" ! 52: #include "libpfkey.h" ! 53: ! 54: #define CALLOC(size, cast) (cast)calloc(1, (size)) ! 55: ! 56: static int findsupportedmap __P((int)); ! 57: static int setsupportedmap __P((struct sadb_supported *)); ! 58: static struct sadb_alg *findsupportedalg __P((u_int, u_int)); ! 59: static int pfkey_send_x1 __P((struct pfkey_send_sa_args *)); ! 60: static int pfkey_send_x2 __P((int, u_int, u_int, u_int, ! 61: struct sockaddr *, struct sockaddr *, u_int32_t)); ! 62: static int pfkey_send_x3 __P((int, u_int, u_int)); ! 63: static int pfkey_send_x4 __P((int, u_int, struct sockaddr *, u_int, ! 64: struct sockaddr *, u_int, u_int, u_int64_t, u_int64_t, ! 65: char *, int, u_int32_t)); ! 66: static int pfkey_send_x5 __P((int, u_int, u_int32_t)); ! 67: ! 68: static caddr_t pfkey_setsadbmsg __P((caddr_t, caddr_t, u_int, u_int, ! 69: u_int, u_int32_t, pid_t)); ! 70: static caddr_t pfkey_setsadbsa __P((caddr_t, caddr_t, u_int32_t, u_int, ! 71: u_int, u_int, u_int32_t)); ! 72: static caddr_t pfkey_setsadbaddr __P((caddr_t, caddr_t, u_int, ! 73: struct sockaddr *, u_int, u_int)); ! 74: ! 75: #ifdef SADB_X_EXT_KMADDRESS ! 76: static caddr_t pfkey_setsadbkmaddr __P((caddr_t, caddr_t, struct sockaddr *, ! 77: struct sockaddr *)); ! 78: #endif ! 79: ! 80: static caddr_t pfkey_setsadbkey __P((caddr_t, caddr_t, u_int, caddr_t, u_int)); ! 81: static caddr_t pfkey_setsadblifetime __P((caddr_t, caddr_t, u_int, u_int32_t, ! 82: u_int32_t, u_int32_t, u_int32_t)); ! 83: static caddr_t pfkey_setsadbxsa2 __P((caddr_t, caddr_t, u_int32_t, u_int32_t)); ! 84: ! 85: #ifdef SADB_X_EXT_NAT_T_TYPE ! 86: static caddr_t pfkey_set_natt_type __P((caddr_t, caddr_t, u_int, u_int8_t)); ! 87: static caddr_t pfkey_set_natt_port __P((caddr_t, caddr_t, u_int, u_int16_t)); ! 88: #endif ! 89: #ifdef SADB_X_EXT_NAT_T_FRAG ! 90: static caddr_t pfkey_set_natt_frag __P((caddr_t, caddr_t, u_int, u_int16_t)); ! 91: #endif ! 92: ! 93: #ifdef SADB_X_EXT_SEC_CTX ! 94: static caddr_t pfkey_setsecctx __P((caddr_t, caddr_t, u_int, u_int8_t, u_int8_t, ! 95: caddr_t, u_int16_t)); ! 96: #endif ! 97: ! 98: int libipsec_opt = 0 ! 99: #ifdef SADB_X_EXT_NAT_T_TYPE ! 100: | LIBIPSEC_OPT_NATT ! 101: #endif ! 102: #ifdef SADB_X_EXT_NAT_T_FRAG ! 103: | LIBIPSEC_OPT_FRAG ! 104: #endif ! 105: #ifdef SADB_X_EXT_NAT_T_SEC_CTX ! 106: | LIBIPSEC_OPT_SEC_CTX ! 107: #endif ! 108: ; ! 109: ! 110: /* ! 111: * make and search supported algorithm structure. ! 112: */ ! 113: static struct sadb_supported *ipsec_supported[] = { NULL, NULL, NULL, ! 114: #ifdef SADB_X_SATYPE_TCPSIGNATURE ! 115: NULL, ! 116: #endif ! 117: }; ! 118: ! 119: static int supported_map[] = { ! 120: SADB_SATYPE_AH, ! 121: SADB_SATYPE_ESP, ! 122: SADB_X_SATYPE_IPCOMP, ! 123: #ifdef SADB_X_SATYPE_TCPSIGNATURE ! 124: SADB_X_SATYPE_TCPSIGNATURE, ! 125: #endif ! 126: }; ! 127: ! 128: static int ! 129: findsupportedmap(satype) ! 130: int satype; ! 131: { ! 132: int i; ! 133: ! 134: for (i = 0; i < sizeof(supported_map)/sizeof(supported_map[0]); i++) ! 135: if (supported_map[i] == satype) ! 136: return i; ! 137: return -1; ! 138: } ! 139: ! 140: static struct sadb_alg * ! 141: findsupportedalg(satype, alg_id) ! 142: u_int satype, alg_id; ! 143: { ! 144: int algno; ! 145: int tlen; ! 146: caddr_t p; ! 147: ! 148: /* validity check */ ! 149: algno = findsupportedmap((int)satype); ! 150: if (algno == -1) { ! 151: __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; ! 152: return NULL; ! 153: } ! 154: if (ipsec_supported[algno] == NULL) { ! 155: __ipsec_errcode = EIPSEC_DO_GET_SUPP_LIST; ! 156: return NULL; ! 157: } ! 158: ! 159: tlen = ipsec_supported[algno]->sadb_supported_len ! 160: - sizeof(struct sadb_supported); ! 161: p = (void *)(ipsec_supported[algno] + 1); ! 162: while (tlen > 0) { ! 163: if (tlen < sizeof(struct sadb_alg)) { ! 164: /* invalid format */ ! 165: break; ! 166: } ! 167: if (((struct sadb_alg *)(void *)p)->sadb_alg_id == alg_id) ! 168: return (void *)p; ! 169: ! 170: tlen -= sizeof(struct sadb_alg); ! 171: p += sizeof(struct sadb_alg); ! 172: } ! 173: ! 174: __ipsec_errcode = EIPSEC_NOT_SUPPORTED; ! 175: return NULL; ! 176: } ! 177: ! 178: static int ! 179: setsupportedmap(sup) ! 180: struct sadb_supported *sup; ! 181: { ! 182: struct sadb_supported **ipsup; ! 183: ! 184: switch (sup->sadb_supported_exttype) { ! 185: case SADB_EXT_SUPPORTED_AUTH: ! 186: ipsup = &ipsec_supported[findsupportedmap(SADB_SATYPE_AH)]; ! 187: break; ! 188: case SADB_EXT_SUPPORTED_ENCRYPT: ! 189: ipsup = &ipsec_supported[findsupportedmap(SADB_SATYPE_ESP)]; ! 190: break; ! 191: default: ! 192: __ipsec_errcode = EIPSEC_INVAL_SATYPE; ! 193: return -1; ! 194: } ! 195: ! 196: if (*ipsup) ! 197: free(*ipsup); ! 198: ! 199: *ipsup = malloc((size_t)sup->sadb_supported_len); ! 200: if (!*ipsup) { ! 201: __ipsec_set_strerror(strerror(errno)); ! 202: return -1; ! 203: } ! 204: memcpy(*ipsup, sup, (size_t)sup->sadb_supported_len); ! 205: ! 206: return 0; ! 207: } ! 208: ! 209: /* ! 210: * check key length against algorithm specified. ! 211: * This function is called with SADB_EXT_SUPPORTED_{AUTH,ENCRYPT} as the ! 212: * augument, and only calls to ipsec_check_keylen2(); ! 213: * keylen is the unit of bit. ! 214: * OUT: ! 215: * -1: invalid. ! 216: * 0: valid. ! 217: */ ! 218: int ! 219: ipsec_check_keylen(supported, alg_id, keylen) ! 220: u_int supported; ! 221: u_int alg_id; ! 222: u_int keylen; ! 223: { ! 224: u_int satype; ! 225: ! 226: /* validity check */ ! 227: switch (supported) { ! 228: case SADB_EXT_SUPPORTED_AUTH: ! 229: satype = SADB_SATYPE_AH; ! 230: break; ! 231: case SADB_EXT_SUPPORTED_ENCRYPT: ! 232: satype = SADB_SATYPE_ESP; ! 233: break; ! 234: default: ! 235: __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; ! 236: return -1; ! 237: } ! 238: ! 239: return ipsec_check_keylen2(satype, alg_id, keylen); ! 240: } ! 241: ! 242: /* ! 243: * check key length against algorithm specified. ! 244: * satype is one of satype defined at pfkeyv2.h. ! 245: * keylen is the unit of bit. ! 246: * OUT: ! 247: * -1: invalid. ! 248: * 0: valid. ! 249: */ ! 250: int ! 251: ipsec_check_keylen2(satype, alg_id, keylen) ! 252: u_int satype; ! 253: u_int alg_id; ! 254: u_int keylen; ! 255: { ! 256: struct sadb_alg *alg; ! 257: ! 258: alg = findsupportedalg(satype, alg_id); ! 259: if (!alg) ! 260: return -1; ! 261: ! 262: if (keylen < alg->sadb_alg_minbits || keylen > alg->sadb_alg_maxbits) { ! 263: fprintf(stderr, "%d %d %d\n", keylen, alg->sadb_alg_minbits, ! 264: alg->sadb_alg_maxbits); ! 265: __ipsec_errcode = EIPSEC_INVAL_KEYLEN; ! 266: return -1; ! 267: } ! 268: ! 269: __ipsec_errcode = EIPSEC_NO_ERROR; ! 270: return 0; ! 271: } ! 272: ! 273: /* ! 274: * get max/min key length against algorithm specified. ! 275: * satype is one of satype defined at pfkeyv2.h. ! 276: * keylen is the unit of bit. ! 277: * OUT: ! 278: * -1: invalid. ! 279: * 0: valid. ! 280: */ ! 281: int ! 282: ipsec_get_keylen(supported, alg_id, alg0) ! 283: u_int supported, alg_id; ! 284: struct sadb_alg *alg0; ! 285: { ! 286: struct sadb_alg *alg; ! 287: u_int satype; ! 288: ! 289: /* validity check */ ! 290: if (!alg0) { ! 291: __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; ! 292: return -1; ! 293: } ! 294: ! 295: switch (supported) { ! 296: case SADB_EXT_SUPPORTED_AUTH: ! 297: satype = SADB_SATYPE_AH; ! 298: break; ! 299: case SADB_EXT_SUPPORTED_ENCRYPT: ! 300: satype = SADB_SATYPE_ESP; ! 301: break; ! 302: default: ! 303: __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; ! 304: return -1; ! 305: } ! 306: ! 307: alg = findsupportedalg(satype, alg_id); ! 308: if (!alg) ! 309: return -1; ! 310: ! 311: memcpy(alg0, alg, sizeof(*alg0)); ! 312: ! 313: __ipsec_errcode = EIPSEC_NO_ERROR; ! 314: return 0; ! 315: } ! 316: ! 317: /* ! 318: * set the rate for SOFT lifetime against HARD one. ! 319: * If rate is more than 100 or equal to zero, then set to 100. ! 320: */ ! 321: static u_int soft_lifetime_allocations_rate = PFKEY_SOFT_LIFETIME_RATE; ! 322: static u_int soft_lifetime_bytes_rate = PFKEY_SOFT_LIFETIME_RATE; ! 323: static u_int soft_lifetime_addtime_rate = PFKEY_SOFT_LIFETIME_RATE; ! 324: static u_int soft_lifetime_usetime_rate = PFKEY_SOFT_LIFETIME_RATE; ! 325: ! 326: u_int ! 327: pfkey_set_softrate(type, rate) ! 328: u_int type, rate; ! 329: { ! 330: __ipsec_errcode = EIPSEC_NO_ERROR; ! 331: ! 332: if (rate > 100 || rate == 0) ! 333: rate = 100; ! 334: ! 335: switch (type) { ! 336: case SADB_X_LIFETIME_ALLOCATIONS: ! 337: soft_lifetime_allocations_rate = rate; ! 338: return 0; ! 339: case SADB_X_LIFETIME_BYTES: ! 340: soft_lifetime_bytes_rate = rate; ! 341: return 0; ! 342: case SADB_X_LIFETIME_ADDTIME: ! 343: soft_lifetime_addtime_rate = rate; ! 344: return 0; ! 345: case SADB_X_LIFETIME_USETIME: ! 346: soft_lifetime_usetime_rate = rate; ! 347: return 0; ! 348: } ! 349: ! 350: __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; ! 351: return 1; ! 352: } ! 353: ! 354: /* ! 355: * get current rate for SOFT lifetime against HARD one. ! 356: * ATTENTION: ~0 is returned if invalid type was passed. ! 357: */ ! 358: u_int ! 359: pfkey_get_softrate(type) ! 360: u_int type; ! 361: { ! 362: switch (type) { ! 363: case SADB_X_LIFETIME_ALLOCATIONS: ! 364: return soft_lifetime_allocations_rate; ! 365: case SADB_X_LIFETIME_BYTES: ! 366: return soft_lifetime_bytes_rate; ! 367: case SADB_X_LIFETIME_ADDTIME: ! 368: return soft_lifetime_addtime_rate; ! 369: case SADB_X_LIFETIME_USETIME: ! 370: return soft_lifetime_usetime_rate; ! 371: } ! 372: ! 373: return (u_int)~0; ! 374: } ! 375: ! 376: /* ! 377: * sending SADB_GETSPI message to the kernel. ! 378: * OUT: ! 379: * positive: success and return length sent. ! 380: * -1 : error occured, and set errno. ! 381: */ ! 382: int ! 383: pfkey_send_getspi_nat(int so, u_int satype, u_int mode, struct sockaddr *src, ! 384: struct sockaddr *dst, u_int8_t natt_type, u_int16_t sport, ! 385: u_int16_t dport, u_int32_t min, u_int32_t max, u_int32_t reqid, ! 386: u_int32_t seq) ! 387: { ! 388: struct sadb_msg *newmsg; ! 389: caddr_t ep; ! 390: int len; ! 391: int need_spirange = 0; ! 392: caddr_t p; ! 393: int plen; ! 394: ! 395: /* validity check */ ! 396: if (src == NULL || dst == NULL) { ! 397: __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; ! 398: return -1; ! 399: } ! 400: if (src->sa_family != dst->sa_family) { ! 401: __ipsec_errcode = EIPSEC_FAMILY_MISMATCH; ! 402: return -1; ! 403: } ! 404: if (min > max || (min > 0 && min <= 255)) { ! 405: __ipsec_errcode = EIPSEC_INVAL_SPI; ! 406: return -1; ! 407: } ! 408: switch (src->sa_family) { ! 409: case AF_INET: ! 410: plen = sizeof(struct in_addr) << 3; ! 411: break; ! 412: case AF_INET6: ! 413: plen = sizeof(struct in6_addr) << 3; ! 414: break; ! 415: default: ! 416: __ipsec_errcode = EIPSEC_INVAL_FAMILY; ! 417: return -1; ! 418: } ! 419: ! 420: /* create new sadb_msg to send. */ ! 421: len = sizeof(struct sadb_msg) ! 422: + sizeof(struct sadb_x_sa2) ! 423: + sizeof(struct sadb_address) ! 424: + PFKEY_ALIGN8(sysdep_sa_len(src)) ! 425: + sizeof(struct sadb_address) ! 426: + PFKEY_ALIGN8(sysdep_sa_len(dst)); ! 427: ! 428: if (min > 255 && max < (u_int)~0) { ! 429: need_spirange++; ! 430: len += sizeof(struct sadb_spirange); ! 431: } ! 432: ! 433: #ifdef SADB_X_EXT_NAT_T_TYPE ! 434: if(natt_type||sport||dport){ ! 435: len += sizeof(struct sadb_x_nat_t_type); ! 436: len += sizeof(struct sadb_x_nat_t_port); ! 437: len += sizeof(struct sadb_x_nat_t_port); ! 438: } ! 439: #endif ! 440: ! 441: if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) { ! 442: __ipsec_set_strerror(strerror(errno)); ! 443: return -1; ! 444: } ! 445: ep = ((caddr_t)(void *)newmsg) + len; ! 446: ! 447: p = pfkey_setsadbmsg((void *)newmsg, ep, SADB_GETSPI, ! 448: (u_int)len, satype, seq, getpid()); ! 449: if (!p) { ! 450: free(newmsg); ! 451: return -1; ! 452: } ! 453: ! 454: p = pfkey_setsadbxsa2(p, ep, mode, reqid); ! 455: if (!p) { ! 456: free(newmsg); ! 457: return -1; ! 458: } ! 459: ! 460: /* set sadb_address for source */ ! 461: p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, (u_int)plen, ! 462: IPSEC_ULPROTO_ANY); ! 463: if (!p) { ! 464: free(newmsg); ! 465: return -1; ! 466: } ! 467: ! 468: /* set sadb_address for destination */ ! 469: p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, (u_int)plen, ! 470: IPSEC_ULPROTO_ANY); ! 471: if (!p) { ! 472: free(newmsg); ! 473: return -1; ! 474: } ! 475: ! 476: #ifdef SADB_X_EXT_NAT_T_TYPE ! 477: /* Add nat-t messages */ ! 478: if (natt_type) { ! 479: p = pfkey_set_natt_type(p, ep, SADB_X_EXT_NAT_T_TYPE, ! 480: natt_type); ! 481: if (!p) { ! 482: free(newmsg); ! 483: return -1; ! 484: } ! 485: ! 486: p = pfkey_set_natt_port(p, ep, SADB_X_EXT_NAT_T_SPORT, ! 487: sport); ! 488: if (!p) { ! 489: free(newmsg); ! 490: return -1; ! 491: } ! 492: ! 493: p = pfkey_set_natt_port(p, ep, SADB_X_EXT_NAT_T_DPORT, ! 494: dport); ! 495: if (!p) { ! 496: free(newmsg); ! 497: return -1; ! 498: } ! 499: } ! 500: #endif ! 501: ! 502: /* proccessing spi range */ ! 503: if (need_spirange) { ! 504: struct sadb_spirange spirange; ! 505: ! 506: if (p + sizeof(spirange) > ep) { ! 507: free(newmsg); ! 508: return -1; ! 509: } ! 510: ! 511: memset(&spirange, 0, sizeof(spirange)); ! 512: spirange.sadb_spirange_len = PFKEY_UNIT64(sizeof(spirange)); ! 513: spirange.sadb_spirange_exttype = SADB_EXT_SPIRANGE; ! 514: spirange.sadb_spirange_min = min; ! 515: spirange.sadb_spirange_max = max; ! 516: ! 517: memcpy(p, &spirange, sizeof(spirange)); ! 518: ! 519: p += sizeof(spirange); ! 520: } ! 521: if (p != ep) { ! 522: free(newmsg); ! 523: return -1; ! 524: } ! 525: ! 526: /* send message */ ! 527: len = pfkey_send(so, newmsg, len); ! 528: free(newmsg); ! 529: ! 530: if (len < 0) ! 531: return -1; ! 532: ! 533: __ipsec_errcode = EIPSEC_NO_ERROR; ! 534: return len; ! 535: } ! 536: ! 537: int ! 538: pfkey_send_getspi(int so, u_int satype, u_int mode, struct sockaddr *src, ! 539: struct sockaddr *dst, u_int32_t min, u_int32_t max, u_int32_t reqid, ! 540: u_int32_t seq) ! 541: { ! 542: return pfkey_send_getspi_nat(so, satype, mode, src, dst, 0, 0, 0, ! 543: min, max, reqid, seq); ! 544: } ! 545: ! 546: /* ! 547: * sending SADB_UPDATE message to the kernel. ! 548: * The length of key material is a_keylen + e_keylen. ! 549: * OUT: ! 550: * positive: success and return length sent. ! 551: * -1 : error occured, and set errno. ! 552: */ ! 553: int ! 554: pfkey_send_update2(struct pfkey_send_sa_args *sa_parms) ! 555: { ! 556: int len; ! 557: ! 558: sa_parms->type = SADB_UPDATE; ! 559: if ((len = pfkey_send_x1(sa_parms)) < 0) ! 560: return -1; ! 561: ! 562: return len; ! 563: } ! 564: ! 565: /* ! 566: * sending SADB_ADD message to the kernel. ! 567: * The length of key material is a_keylen + e_keylen. ! 568: * OUT: ! 569: * positive: success and return length sent. ! 570: * -1 : error occured, and set errno. ! 571: */ ! 572: int ! 573: pfkey_send_add2(struct pfkey_send_sa_args *sa_parms) ! 574: { ! 575: int len; ! 576: ! 577: sa_parms->type = SADB_ADD; ! 578: if ((len = pfkey_send_x1(sa_parms)) < 0) ! 579: return -1; ! 580: ! 581: return len; ! 582: } ! 583: ! 584: /* ! 585: * sending SADB_DELETE message to the kernel. ! 586: * OUT: ! 587: * positive: success and return length sent. ! 588: * -1 : error occured, and set errno. ! 589: */ ! 590: int ! 591: pfkey_send_delete(int so, u_int satype, u_int mode, struct sockaddr *src, ! 592: struct sockaddr *dst, u_int32_t spi) ! 593: { ! 594: int len; ! 595: if ((len = pfkey_send_x2(so, SADB_DELETE, satype, mode, src, dst, spi)) < 0) ! 596: return -1; ! 597: ! 598: return len; ! 599: } ! 600: ! 601: /* ! 602: * sending SADB_DELETE without spi to the kernel. This is ! 603: * the "delete all" request (an extension also present in ! 604: * Solaris). ! 605: * ! 606: * OUT: ! 607: * positive: success and return length sent ! 608: * -1 : error occured, and set errno ! 609: */ ! 610: /*ARGSUSED*/ ! 611: int ! 612: pfkey_send_delete_all(int so, u_int satype, u_int mode, struct sockaddr *src, ! 613: struct sockaddr *dst) ! 614: { ! 615: struct sadb_msg *newmsg; ! 616: int len; ! 617: caddr_t p; ! 618: int plen; ! 619: caddr_t ep; ! 620: ! 621: /* validity check */ ! 622: if (src == NULL || dst == NULL) { ! 623: __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; ! 624: return -1; ! 625: } ! 626: if (src->sa_family != dst->sa_family) { ! 627: __ipsec_errcode = EIPSEC_FAMILY_MISMATCH; ! 628: return -1; ! 629: } ! 630: switch (src->sa_family) { ! 631: case AF_INET: ! 632: plen = sizeof(struct in_addr) << 3; ! 633: break; ! 634: case AF_INET6: ! 635: plen = sizeof(struct in6_addr) << 3; ! 636: break; ! 637: default: ! 638: __ipsec_errcode = EIPSEC_INVAL_FAMILY; ! 639: return -1; ! 640: } ! 641: ! 642: /* create new sadb_msg to reply. */ ! 643: len = sizeof(struct sadb_msg) ! 644: + sizeof(struct sadb_address) ! 645: + PFKEY_ALIGN8(sysdep_sa_len(src)) ! 646: + sizeof(struct sadb_address) ! 647: + PFKEY_ALIGN8(sysdep_sa_len(dst)); ! 648: ! 649: if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) { ! 650: __ipsec_set_strerror(strerror(errno)); ! 651: return -1; ! 652: } ! 653: ep = ((caddr_t)(void *)newmsg) + len; ! 654: ! 655: p = pfkey_setsadbmsg((void *)newmsg, ep, SADB_DELETE, (u_int)len, ! 656: satype, 0, getpid()); ! 657: if (!p) { ! 658: free(newmsg); ! 659: return -1; ! 660: } ! 661: p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, (u_int)plen, ! 662: IPSEC_ULPROTO_ANY); ! 663: if (!p) { ! 664: free(newmsg); ! 665: return -1; ! 666: } ! 667: p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, (u_int)plen, ! 668: IPSEC_ULPROTO_ANY); ! 669: if (!p || p != ep) { ! 670: free(newmsg); ! 671: return -1; ! 672: } ! 673: ! 674: /* send message */ ! 675: len = pfkey_send(so, newmsg, len); ! 676: free(newmsg); ! 677: ! 678: if (len < 0) ! 679: return -1; ! 680: ! 681: __ipsec_errcode = EIPSEC_NO_ERROR; ! 682: return len; ! 683: } ! 684: ! 685: /* ! 686: * sending SADB_GET message to the kernel. ! 687: * OUT: ! 688: * positive: success and return length sent. ! 689: * -1 : error occured, and set errno. ! 690: */ ! 691: int ! 692: pfkey_send_get(int so, u_int satype, u_int mode, struct sockaddr *src, ! 693: struct sockaddr *dst, u_int32_t spi) ! 694: { ! 695: int len; ! 696: if ((len = pfkey_send_x2(so, SADB_GET, satype, mode, src, dst, spi)) < 0) ! 697: return -1; ! 698: ! 699: return len; ! 700: } ! 701: ! 702: /* ! 703: * sending SADB_REGISTER message to the kernel. ! 704: * OUT: ! 705: * positive: success and return length sent. ! 706: * -1 : error occured, and set errno. ! 707: */ ! 708: int ! 709: pfkey_send_register(int so, u_int satype) ! 710: { ! 711: int len, algno; ! 712: ! 713: if (satype == PF_UNSPEC) { ! 714: for (algno = 0; ! 715: algno < sizeof(supported_map)/sizeof(supported_map[0]); ! 716: algno++) { ! 717: if (ipsec_supported[algno]) { ! 718: free(ipsec_supported[algno]); ! 719: ipsec_supported[algno] = NULL; ! 720: } ! 721: } ! 722: } else { ! 723: algno = findsupportedmap((int)satype); ! 724: if (algno == -1) { ! 725: __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; ! 726: return -1; ! 727: } ! 728: ! 729: if (ipsec_supported[algno]) { ! 730: free(ipsec_supported[algno]); ! 731: ipsec_supported[algno] = NULL; ! 732: } ! 733: } ! 734: ! 735: if ((len = pfkey_send_x3(so, SADB_REGISTER, satype)) < 0) ! 736: return -1; ! 737: ! 738: return len; ! 739: } ! 740: ! 741: /* ! 742: * receiving SADB_REGISTER message from the kernel, and copy buffer for ! 743: * sadb_supported returned into ipsec_supported. ! 744: * OUT: ! 745: * 0: success and return length sent. ! 746: * -1: error occured, and set errno. ! 747: */ ! 748: int ! 749: pfkey_recv_register(int so) ! 750: { ! 751: pid_t pid = getpid(); ! 752: struct sadb_msg *newmsg; ! 753: int error = -1; ! 754: ! 755: /* receive message */ ! 756: for (;;) { ! 757: if ((newmsg = pfkey_recv(so)) == NULL) ! 758: return -1; ! 759: if (newmsg->sadb_msg_type == SADB_REGISTER && ! 760: newmsg->sadb_msg_pid == pid) ! 761: break; ! 762: free(newmsg); ! 763: } ! 764: ! 765: /* check and fix */ ! 766: newmsg->sadb_msg_len = PFKEY_UNUNIT64(newmsg->sadb_msg_len); ! 767: ! 768: error = pfkey_set_supported(newmsg, newmsg->sadb_msg_len); ! 769: free(newmsg); ! 770: ! 771: if (error == 0) ! 772: __ipsec_errcode = EIPSEC_NO_ERROR; ! 773: ! 774: return error; ! 775: } ! 776: ! 777: /* ! 778: * receiving SADB_REGISTER message from the kernel, and copy buffer for ! 779: * sadb_supported returned into ipsec_supported. ! 780: * NOTE: sadb_msg_len must be host order. ! 781: * IN: ! 782: * tlen: msg length, it's to makeing sure. ! 783: * OUT: ! 784: * 0: success and return length sent. ! 785: * -1: error occured, and set errno. ! 786: */ ! 787: int ! 788: pfkey_set_supported(struct sadb_msg *msg, int tlen) ! 789: { ! 790: struct sadb_supported *sup; ! 791: caddr_t p; ! 792: caddr_t ep; ! 793: ! 794: /* validity */ ! 795: if (msg->sadb_msg_len != tlen) { ! 796: __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; ! 797: return -1; ! 798: } ! 799: ! 800: p = (void *)msg; ! 801: ep = p + tlen; ! 802: ! 803: p += sizeof(struct sadb_msg); ! 804: ! 805: while (p < ep) { ! 806: sup = (void *)p; ! 807: if (ep < p + sizeof(*sup) || ! 808: PFKEY_EXTLEN(sup) < sizeof(*sup) || ! 809: ep < p + sup->sadb_supported_len) { ! 810: /* invalid format */ ! 811: break; ! 812: } ! 813: ! 814: switch (sup->sadb_supported_exttype) { ! 815: case SADB_EXT_SUPPORTED_AUTH: ! 816: case SADB_EXT_SUPPORTED_ENCRYPT: ! 817: break; ! 818: default: ! 819: __ipsec_errcode = EIPSEC_INVAL_SATYPE; ! 820: return -1; ! 821: } ! 822: ! 823: /* fixed length */ ! 824: sup->sadb_supported_len = PFKEY_EXTLEN(sup); ! 825: ! 826: /* set supported map */ ! 827: if (setsupportedmap(sup) != 0) ! 828: return -1; ! 829: ! 830: p += sup->sadb_supported_len; ! 831: } ! 832: ! 833: if (p != ep) { ! 834: __ipsec_errcode = EIPSEC_INVAL_SATYPE; ! 835: return -1; ! 836: } ! 837: ! 838: __ipsec_errcode = EIPSEC_NO_ERROR; ! 839: ! 840: return 0; ! 841: } ! 842: ! 843: /* ! 844: * sending SADB_FLUSH message to the kernel. ! 845: * OUT: ! 846: * positive: success and return length sent. ! 847: * -1 : error occured, and set errno. ! 848: */ ! 849: int ! 850: pfkey_send_flush(int so, u_int satype) ! 851: { ! 852: int len; ! 853: ! 854: if ((len = pfkey_send_x3(so, SADB_FLUSH, satype)) < 0) ! 855: return -1; ! 856: ! 857: return len; ! 858: } ! 859: ! 860: /* ! 861: * sending SADB_DUMP message to the kernel. ! 862: * OUT: ! 863: * positive: success and return length sent. ! 864: * -1 : error occured, and set errno. ! 865: */ ! 866: int ! 867: pfkey_send_dump(int so, u_int satype) ! 868: { ! 869: int len; ! 870: ! 871: if ((len = pfkey_send_x3(so, SADB_DUMP, satype)) < 0) ! 872: return -1; ! 873: ! 874: return len; ! 875: } ! 876: ! 877: /* ! 878: * sending SADB_X_PROMISC message to the kernel. ! 879: * NOTE that this function handles promisc mode toggle only. ! 880: * IN: ! 881: * flag: set promisc off if zero, set promisc on if non-zero. ! 882: * OUT: ! 883: * positive: success and return length sent. ! 884: * -1 : error occured, and set errno. ! 885: * 0 : error occured, and set errno. ! 886: * others: a pointer to new allocated buffer in which supported ! 887: * algorithms is. ! 888: */ ! 889: int ! 890: pfkey_send_promisc_toggle(int so, int flag) ! 891: { ! 892: int len; ! 893: ! 894: if ((len = pfkey_send_x3(so, SADB_X_PROMISC, ! 895: (u_int)(flag ? 1 : 0))) < 0) ! 896: return -1; ! 897: ! 898: return len; ! 899: } ! 900: ! 901: /* ! 902: * sending SADB_X_SPDADD message to the kernel. ! 903: * OUT: ! 904: * positive: success and return length sent. ! 905: * -1 : error occured, and set errno. ! 906: */ ! 907: int ! 908: pfkey_send_spdadd(int so, struct sockaddr *src, u_int prefs, ! 909: struct sockaddr *dst, u_int prefd, u_int proto, caddr_t policy, ! 910: int policylen, u_int32_t seq) ! 911: { ! 912: int len; ! 913: ! 914: if ((len = pfkey_send_x4(so, SADB_X_SPDADD, ! 915: src, prefs, dst, prefd, proto, ! 916: (u_int64_t)0, (u_int64_t)0, ! 917: policy, policylen, seq)) < 0) ! 918: return -1; ! 919: ! 920: return len; ! 921: } ! 922: ! 923: /* ! 924: * sending SADB_X_SPDADD message to the kernel. ! 925: * OUT: ! 926: * positive: success and return length sent. ! 927: * -1 : error occured, and set errno. ! 928: */ ! 929: int ! 930: pfkey_send_spdadd2(int so, struct sockaddr *src, u_int prefs, ! 931: struct sockaddr *dst, u_int prefd, u_int proto, u_int64_t ltime, ! 932: u_int64_t vtime, caddr_t policy, int policylen, u_int32_t seq) ! 933: { ! 934: int len; ! 935: ! 936: if ((len = pfkey_send_x4(so, SADB_X_SPDADD, ! 937: src, prefs, dst, prefd, proto, ! 938: ltime, vtime, ! 939: policy, policylen, seq)) < 0) ! 940: return -1; ! 941: ! 942: return len; ! 943: } ! 944: ! 945: /* ! 946: * sending SADB_X_SPDUPDATE message to the kernel. ! 947: * OUT: ! 948: * positive: success and return length sent. ! 949: * -1 : error occured, and set errno. ! 950: */ ! 951: int ! 952: pfkey_send_spdupdate(int so, struct sockaddr *src, u_int prefs, ! 953: struct sockaddr *dst, u_int prefd, u_int proto, caddr_t policy, ! 954: int policylen, u_int32_t seq) ! 955: { ! 956: int len; ! 957: ! 958: if ((len = pfkey_send_x4(so, SADB_X_SPDUPDATE, ! 959: src, prefs, dst, prefd, proto, ! 960: (u_int64_t)0, (u_int64_t)0, ! 961: policy, policylen, seq)) < 0) ! 962: return -1; ! 963: ! 964: return len; ! 965: } ! 966: ! 967: /* ! 968: * sending SADB_X_SPDUPDATE message to the kernel. ! 969: * OUT: ! 970: * positive: success and return length sent. ! 971: * -1 : error occured, and set errno. ! 972: */ ! 973: int ! 974: pfkey_send_spdupdate2(int so, struct sockaddr *src, u_int prefs, ! 975: struct sockaddr *dst, u_int prefd, u_int proto, u_int64_t ltime, ! 976: u_int64_t vtime, caddr_t policy, int policylen, u_int32_t seq) ! 977: { ! 978: int len; ! 979: ! 980: if ((len = pfkey_send_x4(so, SADB_X_SPDUPDATE, ! 981: src, prefs, dst, prefd, proto, ! 982: ltime, vtime, ! 983: policy, policylen, seq)) < 0) ! 984: return -1; ! 985: ! 986: return len; ! 987: } ! 988: ! 989: /* ! 990: * sending SADB_X_SPDDELETE message to the kernel. ! 991: * OUT: ! 992: * positive: success and return length sent. ! 993: * -1 : error occured, and set errno. ! 994: */ ! 995: int ! 996: pfkey_send_spddelete(int so, struct sockaddr *src, u_int prefs, ! 997: struct sockaddr *dst, u_int prefd, u_int proto, caddr_t policy, ! 998: int policylen, u_int32_t seq) ! 999: { ! 1000: int len; ! 1001: ! 1002: if (policylen != sizeof(struct sadb_x_policy)) { ! 1003: __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; ! 1004: return -1; ! 1005: } ! 1006: ! 1007: if ((len = pfkey_send_x4(so, SADB_X_SPDDELETE, ! 1008: src, prefs, dst, prefd, proto, ! 1009: (u_int64_t)0, (u_int64_t)0, ! 1010: policy, policylen, seq)) < 0) ! 1011: return -1; ! 1012: ! 1013: return len; ! 1014: } ! 1015: ! 1016: /* ! 1017: * sending SADB_X_SPDDELETE message to the kernel. ! 1018: * OUT: ! 1019: * positive: success and return length sent. ! 1020: * -1 : error occured, and set errno. ! 1021: */ ! 1022: int ! 1023: pfkey_send_spddelete2(int so, u_int32_t spid) ! 1024: { ! 1025: int len; ! 1026: ! 1027: if ((len = pfkey_send_x5(so, SADB_X_SPDDELETE2, spid)) < 0) ! 1028: return -1; ! 1029: ! 1030: return len; ! 1031: } ! 1032: ! 1033: /* ! 1034: * sending SADB_X_SPDGET message to the kernel. ! 1035: * OUT: ! 1036: * positive: success and return length sent. ! 1037: * -1 : error occured, and set errno. ! 1038: */ ! 1039: int ! 1040: pfkey_send_spdget(int so, u_int32_t spid) ! 1041: { ! 1042: int len; ! 1043: ! 1044: if ((len = pfkey_send_x5(so, SADB_X_SPDGET, spid)) < 0) ! 1045: return -1; ! 1046: ! 1047: return len; ! 1048: } ! 1049: ! 1050: /* ! 1051: * sending SADB_X_SPDSETIDX message to the kernel. ! 1052: * OUT: ! 1053: * positive: success and return length sent. ! 1054: * -1 : error occured, and set errno. ! 1055: */ ! 1056: int ! 1057: pfkey_send_spdsetidx(int so, struct sockaddr *src, u_int prefs, ! 1058: struct sockaddr *dst, u_int prefd, u_int proto, caddr_t policy, ! 1059: int policylen, u_int32_t seq) ! 1060: { ! 1061: int len; ! 1062: ! 1063: if (policylen != sizeof(struct sadb_x_policy)) { ! 1064: __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; ! 1065: return -1; ! 1066: } ! 1067: ! 1068: if ((len = pfkey_send_x4(so, SADB_X_SPDSETIDX, ! 1069: src, prefs, dst, prefd, proto, ! 1070: (u_int64_t)0, (u_int64_t)0, ! 1071: policy, policylen, seq)) < 0) ! 1072: return -1; ! 1073: ! 1074: return len; ! 1075: } ! 1076: ! 1077: /* ! 1078: * sending SADB_SPDFLUSH message to the kernel. ! 1079: * OUT: ! 1080: * positive: success and return length sent. ! 1081: * -1 : error occured, and set errno. ! 1082: */ ! 1083: int ! 1084: pfkey_send_spdflush(int so) ! 1085: { ! 1086: int len; ! 1087: ! 1088: if ((len = pfkey_send_x3(so, SADB_X_SPDFLUSH, SADB_SATYPE_UNSPEC)) < 0) ! 1089: return -1; ! 1090: ! 1091: return len; ! 1092: } ! 1093: ! 1094: /* ! 1095: * sending SADB_SPDDUMP message to the kernel. ! 1096: * OUT: ! 1097: * positive: success and return length sent. ! 1098: * -1 : error occured, and set errno. ! 1099: */ ! 1100: int ! 1101: pfkey_send_spddump(int so) ! 1102: { ! 1103: int len; ! 1104: ! 1105: if ((len = pfkey_send_x3(so, SADB_X_SPDDUMP, SADB_SATYPE_UNSPEC)) < 0) ! 1106: return -1; ! 1107: ! 1108: return len; ! 1109: } ! 1110: ! 1111: ! 1112: #ifdef SADB_X_MIGRATE ! 1113: /* ! 1114: * sending SADB_X_MIGRATE message to the kernel. ! 1115: * OUT: ! 1116: * positive: success and return length sent. ! 1117: * -1 : error occured, and set errno. ! 1118: */ ! 1119: int ! 1120: pfkey_send_migrate(int so, struct sockaddr *local, struct sockaddr *remote, ! 1121: struct sockaddr *src, u_int prefs, struct sockaddr *dst, u_int prefd, ! 1122: u_int proto, caddr_t policy, int policylen, u_int32_t seq) ! 1123: { ! 1124: struct sadb_msg *newmsg; ! 1125: int len; ! 1126: caddr_t p; ! 1127: int plen; ! 1128: caddr_t ep; ! 1129: ! 1130: /* validity check */ ! 1131: if (src == NULL || dst == NULL) { ! 1132: __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; ! 1133: return -1; ! 1134: } ! 1135: if (src->sa_family != dst->sa_family) { ! 1136: __ipsec_errcode = EIPSEC_FAMILY_MISMATCH; ! 1137: return -1; ! 1138: } ! 1139: ! 1140: if (local == NULL || remote == NULL) { ! 1141: __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; ! 1142: return -1; ! 1143: } ! 1144: #ifdef SADB_X_EXT_KMADDRESS ! 1145: if (local->sa_family != remote->sa_family) { ! 1146: __ipsec_errcode = EIPSEC_FAMILY_MISMATCH; ! 1147: return -1; ! 1148: } ! 1149: #endif ! 1150: ! 1151: switch (src->sa_family) { ! 1152: case AF_INET: ! 1153: plen = sizeof(struct in_addr) << 3; ! 1154: break; ! 1155: case AF_INET6: ! 1156: plen = sizeof(struct in6_addr) << 3; ! 1157: break; ! 1158: default: ! 1159: __ipsec_errcode = EIPSEC_INVAL_FAMILY; ! 1160: return -1; ! 1161: } ! 1162: if (prefs > plen || prefd > plen) { ! 1163: __ipsec_errcode = EIPSEC_INVAL_PREFIXLEN; ! 1164: return -1; ! 1165: } ! 1166: ! 1167: /* create new sadb_msg to reply. */ ! 1168: len = sizeof(struct sadb_msg) ! 1169: #ifdef SADB_X_EXT_KMADDRESS ! 1170: + sizeof(struct sadb_x_kmaddress) ! 1171: + PFKEY_ALIGN8(2*sysdep_sa_len(local)) ! 1172: #endif ! 1173: + sizeof(struct sadb_address) ! 1174: + PFKEY_ALIGN8(sysdep_sa_len(src)) ! 1175: + sizeof(struct sadb_address) ! 1176: + PFKEY_ALIGN8(sysdep_sa_len(dst)) ! 1177: + policylen; ! 1178: ! 1179: if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) { ! 1180: __ipsec_set_strerror(strerror(errno)); ! 1181: return -1; ! 1182: } ! 1183: ep = ((caddr_t)newmsg) + len; ! 1184: ! 1185: p = pfkey_setsadbmsg((caddr_t)newmsg, ep, SADB_X_MIGRATE, (u_int)len, ! 1186: SADB_SATYPE_UNSPEC, seq, getpid()); ! 1187: if (!p) { ! 1188: free(newmsg); ! 1189: return -1; ! 1190: } ! 1191: #ifdef SADB_X_EXT_KMADDRESS ! 1192: p = pfkey_setsadbkmaddr(p, ep, local, remote); ! 1193: if (!p) { ! 1194: free(newmsg); ! 1195: return -1; ! 1196: } ! 1197: #endif ! 1198: p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, prefs, proto); ! 1199: if (!p) { ! 1200: free(newmsg); ! 1201: return -1; ! 1202: } ! 1203: p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, prefd, proto); ! 1204: if (!p || p + policylen != ep) { ! 1205: free(newmsg); ! 1206: return -1; ! 1207: } ! 1208: memcpy(p, policy, policylen); ! 1209: ! 1210: /* send message */ ! 1211: len = pfkey_send(so, newmsg, len); ! 1212: free(newmsg); ! 1213: ! 1214: if (len < 0) ! 1215: return -1; ! 1216: ! 1217: __ipsec_errcode = EIPSEC_NO_ERROR; ! 1218: return len; ! 1219: } ! 1220: #endif ! 1221: ! 1222: ! 1223: /* sending SADB_ADD or SADB_UPDATE message to the kernel */ ! 1224: static int ! 1225: pfkey_send_x1(struct pfkey_send_sa_args *sa_parms) ! 1226: { ! 1227: struct sadb_msg *newmsg; ! 1228: int len; ! 1229: caddr_t p; ! 1230: int plen; ! 1231: caddr_t ep; ! 1232: ! 1233: /* validity check */ ! 1234: if (sa_parms->src == NULL || sa_parms->dst == NULL) { ! 1235: __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; ! 1236: return -1; ! 1237: } ! 1238: if (sa_parms->src->sa_family != sa_parms->dst->sa_family) { ! 1239: __ipsec_errcode = EIPSEC_FAMILY_MISMATCH; ! 1240: return -1; ! 1241: } ! 1242: switch (sa_parms->src->sa_family) { ! 1243: case AF_INET: ! 1244: plen = sizeof(struct in_addr) << 3; ! 1245: break; ! 1246: case AF_INET6: ! 1247: plen = sizeof(struct in6_addr) << 3; ! 1248: break; ! 1249: default: ! 1250: __ipsec_errcode = EIPSEC_INVAL_FAMILY; ! 1251: return -1; ! 1252: } ! 1253: ! 1254: switch (sa_parms->satype) { ! 1255: case SADB_SATYPE_ESP: ! 1256: if (sa_parms->e_type == SADB_EALG_NONE) { ! 1257: __ipsec_errcode = EIPSEC_NO_ALGS; ! 1258: return -1; ! 1259: } ! 1260: break; ! 1261: case SADB_SATYPE_AH: ! 1262: if (sa_parms->e_type != SADB_EALG_NONE) { ! 1263: __ipsec_errcode = EIPSEC_INVAL_ALGS; ! 1264: return -1; ! 1265: } ! 1266: if (sa_parms->a_type == SADB_AALG_NONE) { ! 1267: __ipsec_errcode = EIPSEC_NO_ALGS; ! 1268: return -1; ! 1269: } ! 1270: break; ! 1271: case SADB_X_SATYPE_IPCOMP: ! 1272: if (sa_parms->e_type == SADB_X_CALG_NONE) { ! 1273: __ipsec_errcode = EIPSEC_INVAL_ALGS; ! 1274: return -1; ! 1275: } ! 1276: if (sa_parms->a_type != SADB_AALG_NONE) { ! 1277: __ipsec_errcode = EIPSEC_NO_ALGS; ! 1278: return -1; ! 1279: } ! 1280: break; ! 1281: #ifdef SADB_X_AALG_TCP_MD5 ! 1282: case SADB_X_SATYPE_TCPSIGNATURE: ! 1283: if (sa_parms->e_type != SADB_EALG_NONE) { ! 1284: __ipsec_errcode = EIPSEC_INVAL_ALGS; ! 1285: return -1; ! 1286: } ! 1287: if (sa_parms->a_type != SADB_X_AALG_TCP_MD5) { ! 1288: __ipsec_errcode = EIPSEC_INVAL_ALGS; ! 1289: return -1; ! 1290: } ! 1291: break; ! 1292: #endif ! 1293: default: ! 1294: __ipsec_errcode = EIPSEC_INVAL_SATYPE; ! 1295: return -1; ! 1296: } ! 1297: ! 1298: /* create new sadb_msg to reply. */ ! 1299: len = sizeof(struct sadb_msg) ! 1300: + sizeof(struct sadb_sa) ! 1301: + sizeof(struct sadb_x_sa2) ! 1302: + sizeof(struct sadb_address) ! 1303: + PFKEY_ALIGN8(sysdep_sa_len(sa_parms->src)) ! 1304: + sizeof(struct sadb_address) ! 1305: + PFKEY_ALIGN8(sysdep_sa_len(sa_parms->dst)) ! 1306: + sizeof(struct sadb_lifetime) ! 1307: + sizeof(struct sadb_lifetime); ! 1308: ! 1309: if (sa_parms->e_type != SADB_EALG_NONE && ! 1310: sa_parms->satype != SADB_X_SATYPE_IPCOMP) ! 1311: len += (sizeof(struct sadb_key) + ! 1312: PFKEY_ALIGN8(sa_parms->e_keylen)); ! 1313: if (sa_parms->a_type != SADB_AALG_NONE) ! 1314: len += (sizeof(struct sadb_key) + ! 1315: PFKEY_ALIGN8(sa_parms->a_keylen)); ! 1316: ! 1317: #ifdef SADB_X_EXT_SEC_CTX ! 1318: if (sa_parms->ctxstr != NULL) ! 1319: len += (sizeof(struct sadb_x_sec_ctx) ! 1320: + PFKEY_ALIGN8(sa_parms->ctxstrlen)); ! 1321: #endif ! 1322: ! 1323: #ifdef SADB_X_EXT_NAT_T_TYPE ! 1324: /* add nat-t packets */ ! 1325: if (sa_parms->l_natt_type) { ! 1326: switch(sa_parms->satype) { ! 1327: case SADB_SATYPE_ESP: ! 1328: case SADB_X_SATYPE_IPCOMP: ! 1329: break; ! 1330: default: ! 1331: __ipsec_errcode = EIPSEC_NO_ALGS; ! 1332: return -1; ! 1333: } ! 1334: ! 1335: len += sizeof(struct sadb_x_nat_t_type); ! 1336: len += sizeof(struct sadb_x_nat_t_port); ! 1337: len += sizeof(struct sadb_x_nat_t_port); ! 1338: if (sa_parms->l_natt_oa) ! 1339: len += sizeof(struct sadb_address) + ! 1340: PFKEY_ALIGN8(sysdep_sa_len(sa_parms->l_natt_oa)); ! 1341: #ifdef SADB_X_EXT_NAT_T_FRAG ! 1342: if (sa_parms->l_natt_frag) ! 1343: len += sizeof(struct sadb_x_nat_t_frag); ! 1344: #endif ! 1345: } ! 1346: #endif ! 1347: ! 1348: if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) { ! 1349: __ipsec_set_strerror(strerror(errno)); ! 1350: return -1; ! 1351: } ! 1352: ep = ((caddr_t)(void *)newmsg) + len; ! 1353: ! 1354: p = pfkey_setsadbmsg((void *)newmsg, ep, sa_parms->type, (u_int)len, ! 1355: sa_parms->satype, sa_parms->seq, getpid()); ! 1356: if (!p) { ! 1357: free(newmsg); ! 1358: return -1; ! 1359: } ! 1360: p = pfkey_setsadbsa(p, ep, sa_parms->spi, sa_parms->wsize, ! 1361: sa_parms->a_type, sa_parms->e_type, ! 1362: sa_parms->flags); ! 1363: if (!p) { ! 1364: free(newmsg); ! 1365: return -1; ! 1366: } ! 1367: p = pfkey_setsadbxsa2(p, ep, sa_parms->mode, sa_parms->reqid); ! 1368: if (!p) { ! 1369: free(newmsg); ! 1370: return -1; ! 1371: } ! 1372: p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, sa_parms->src, ! 1373: (u_int)plen, IPSEC_ULPROTO_ANY); ! 1374: if (!p) { ! 1375: free(newmsg); ! 1376: return -1; ! 1377: } ! 1378: p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, sa_parms->dst, ! 1379: (u_int)plen, IPSEC_ULPROTO_ANY); ! 1380: if (!p) { ! 1381: free(newmsg); ! 1382: return -1; ! 1383: } ! 1384: ! 1385: if (sa_parms->e_type != SADB_EALG_NONE && ! 1386: sa_parms->satype != SADB_X_SATYPE_IPCOMP) { ! 1387: p = pfkey_setsadbkey(p, ep, SADB_EXT_KEY_ENCRYPT, ! 1388: sa_parms->keymat, sa_parms->e_keylen); ! 1389: if (!p) { ! 1390: free(newmsg); ! 1391: return -1; ! 1392: } ! 1393: } ! 1394: if (sa_parms->a_type != SADB_AALG_NONE) { ! 1395: p = pfkey_setsadbkey(p, ep, SADB_EXT_KEY_AUTH, ! 1396: sa_parms->keymat + sa_parms->e_keylen, ! 1397: sa_parms->a_keylen); ! 1398: if (!p) { ! 1399: free(newmsg); ! 1400: return -1; ! 1401: } ! 1402: } ! 1403: ! 1404: /* set sadb_lifetime for destination */ ! 1405: p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_HARD, ! 1406: sa_parms->l_alloc, sa_parms->l_bytes, ! 1407: sa_parms->l_addtime, sa_parms->l_usetime); ! 1408: if (!p) { ! 1409: free(newmsg); ! 1410: return -1; ! 1411: } ! 1412: p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_SOFT, ! 1413: sa_parms->l_alloc, sa_parms->l_bytes, ! 1414: sa_parms->l_addtime, sa_parms->l_usetime); ! 1415: if (!p) { ! 1416: free(newmsg); ! 1417: return -1; ! 1418: } ! 1419: #ifdef SADB_X_EXT_SEC_CTX ! 1420: if (sa_parms->ctxstr != NULL) { ! 1421: p = pfkey_setsecctx(p, ep, SADB_X_EXT_SEC_CTX, sa_parms->ctxdoi, ! 1422: sa_parms->ctxalg, sa_parms->ctxstr, ! 1423: sa_parms->ctxstrlen); ! 1424: if (!p) { ! 1425: free(newmsg); ! 1426: return -1; ! 1427: } ! 1428: } ! 1429: #endif ! 1430: ! 1431: #ifdef SADB_X_EXT_NAT_T_TYPE ! 1432: /* Add nat-t messages */ ! 1433: if (sa_parms->l_natt_type) { ! 1434: p = pfkey_set_natt_type(p, ep, SADB_X_EXT_NAT_T_TYPE, ! 1435: sa_parms->l_natt_type); ! 1436: if (!p) { ! 1437: free(newmsg); ! 1438: return -1; ! 1439: } ! 1440: ! 1441: p = pfkey_set_natt_port(p, ep, SADB_X_EXT_NAT_T_SPORT, ! 1442: sa_parms->l_natt_sport); ! 1443: if (!p) { ! 1444: free(newmsg); ! 1445: return -1; ! 1446: } ! 1447: ! 1448: p = pfkey_set_natt_port(p, ep, SADB_X_EXT_NAT_T_DPORT, ! 1449: sa_parms->l_natt_dport); ! 1450: if (!p) { ! 1451: free(newmsg); ! 1452: return -1; ! 1453: } ! 1454: ! 1455: if (sa_parms->l_natt_oa) { ! 1456: p = pfkey_setsadbaddr(p, ep, SADB_X_EXT_NAT_T_OA, ! 1457: sa_parms->l_natt_oa, ! 1458: (u_int)PFKEY_ALIGN8(sysdep_sa_len(sa_parms->l_natt_oa)), ! 1459: IPSEC_ULPROTO_ANY); ! 1460: if (!p) { ! 1461: free(newmsg); ! 1462: return -1; ! 1463: } ! 1464: } ! 1465: ! 1466: #ifdef SADB_X_EXT_NAT_T_FRAG ! 1467: if (sa_parms->l_natt_frag) { ! 1468: p = pfkey_set_natt_frag(p, ep, SADB_X_EXT_NAT_T_FRAG, ! 1469: sa_parms->l_natt_frag); ! 1470: if (!p) { ! 1471: free(newmsg); ! 1472: return -1; ! 1473: } ! 1474: } ! 1475: #endif ! 1476: } ! 1477: #endif ! 1478: ! 1479: if (p != ep) { ! 1480: free(newmsg); ! 1481: return -1; ! 1482: } ! 1483: ! 1484: /* send message */ ! 1485: len = pfkey_send(sa_parms->so, newmsg, len); ! 1486: free(newmsg); ! 1487: ! 1488: if (len < 0) ! 1489: return -1; ! 1490: ! 1491: __ipsec_errcode = EIPSEC_NO_ERROR; ! 1492: return len; ! 1493: } ! 1494: ! 1495: /* sending SADB_DELETE or SADB_GET message to the kernel */ ! 1496: /*ARGSUSED*/ ! 1497: static int ! 1498: pfkey_send_x2(int so, u_int type, u_int satype, u_int mode, ! 1499: struct sockaddr *src, struct sockaddr *dst, u_int32_t spi) ! 1500: { ! 1501: struct sadb_msg *newmsg; ! 1502: int len; ! 1503: caddr_t p; ! 1504: int plen; ! 1505: caddr_t ep; ! 1506: ! 1507: /* validity check */ ! 1508: if (src == NULL || dst == NULL) { ! 1509: __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; ! 1510: return -1; ! 1511: } ! 1512: if (src->sa_family != dst->sa_family) { ! 1513: __ipsec_errcode = EIPSEC_FAMILY_MISMATCH; ! 1514: return -1; ! 1515: } ! 1516: switch (src->sa_family) { ! 1517: case AF_INET: ! 1518: plen = sizeof(struct in_addr) << 3; ! 1519: break; ! 1520: case AF_INET6: ! 1521: plen = sizeof(struct in6_addr) << 3; ! 1522: break; ! 1523: default: ! 1524: __ipsec_errcode = EIPSEC_INVAL_FAMILY; ! 1525: return -1; ! 1526: } ! 1527: ! 1528: /* create new sadb_msg to reply. */ ! 1529: len = sizeof(struct sadb_msg) ! 1530: + sizeof(struct sadb_sa) ! 1531: + sizeof(struct sadb_address) ! 1532: + PFKEY_ALIGN8(sysdep_sa_len(src)) ! 1533: + sizeof(struct sadb_address) ! 1534: + PFKEY_ALIGN8(sysdep_sa_len(dst)); ! 1535: ! 1536: if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) { ! 1537: __ipsec_set_strerror(strerror(errno)); ! 1538: return -1; ! 1539: } ! 1540: ep = ((caddr_t)(void *)newmsg) + len; ! 1541: ! 1542: p = pfkey_setsadbmsg((void *)newmsg, ep, type, (u_int)len, satype, 0, ! 1543: getpid()); ! 1544: if (!p) { ! 1545: free(newmsg); ! 1546: return -1; ! 1547: } ! 1548: p = pfkey_setsadbsa(p, ep, spi, 0, 0, 0, 0); ! 1549: if (!p) { ! 1550: free(newmsg); ! 1551: return -1; ! 1552: } ! 1553: p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, (u_int)plen, ! 1554: IPSEC_ULPROTO_ANY); ! 1555: if (!p) { ! 1556: free(newmsg); ! 1557: return -1; ! 1558: } ! 1559: p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, (u_int)plen, ! 1560: IPSEC_ULPROTO_ANY); ! 1561: if (!p || p != ep) { ! 1562: free(newmsg); ! 1563: return -1; ! 1564: } ! 1565: ! 1566: /* send message */ ! 1567: len = pfkey_send(so, newmsg, len); ! 1568: free(newmsg); ! 1569: ! 1570: if (len < 0) ! 1571: return -1; ! 1572: ! 1573: __ipsec_errcode = EIPSEC_NO_ERROR; ! 1574: return len; ! 1575: } ! 1576: ! 1577: /* ! 1578: * sending SADB_REGISTER, SADB_FLUSH, SADB_DUMP or SADB_X_PROMISC message ! 1579: * to the kernel ! 1580: */ ! 1581: static int ! 1582: pfkey_send_x3(int so, u_int type, u_int satype) ! 1583: { ! 1584: struct sadb_msg *newmsg; ! 1585: int len; ! 1586: caddr_t p; ! 1587: caddr_t ep; ! 1588: ! 1589: /* validity check */ ! 1590: switch (type) { ! 1591: case SADB_X_PROMISC: ! 1592: if (satype != 0 && satype != 1) { ! 1593: __ipsec_errcode = EIPSEC_INVAL_SATYPE; ! 1594: return -1; ! 1595: } ! 1596: break; ! 1597: default: ! 1598: switch (satype) { ! 1599: case SADB_SATYPE_UNSPEC: ! 1600: case SADB_SATYPE_AH: ! 1601: case SADB_SATYPE_ESP: ! 1602: case SADB_X_SATYPE_IPCOMP: ! 1603: #ifdef SADB_X_SATYPE_TCPSIGNATURE ! 1604: case SADB_X_SATYPE_TCPSIGNATURE: ! 1605: #endif ! 1606: break; ! 1607: default: ! 1608: __ipsec_errcode = EIPSEC_INVAL_SATYPE; ! 1609: return -1; ! 1610: } ! 1611: } ! 1612: ! 1613: /* create new sadb_msg to send. */ ! 1614: len = sizeof(struct sadb_msg); ! 1615: ! 1616: if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) { ! 1617: __ipsec_set_strerror(strerror(errno)); ! 1618: return -1; ! 1619: } ! 1620: ep = ((caddr_t)(void *)newmsg) + len; ! 1621: ! 1622: p = pfkey_setsadbmsg((void *)newmsg, ep, type, (u_int)len, satype, 0, ! 1623: getpid()); ! 1624: if (!p || p != ep) { ! 1625: free(newmsg); ! 1626: return -1; ! 1627: } ! 1628: ! 1629: /* send message */ ! 1630: len = pfkey_send(so, newmsg, len); ! 1631: free(newmsg); ! 1632: ! 1633: if (len < 0) ! 1634: return -1; ! 1635: ! 1636: __ipsec_errcode = EIPSEC_NO_ERROR; ! 1637: return len; ! 1638: } ! 1639: ! 1640: /* sending SADB_X_SPDADD message to the kernel */ ! 1641: static int ! 1642: pfkey_send_x4(int so, u_int type, struct sockaddr *src, u_int prefs, ! 1643: struct sockaddr *dst, u_int prefd, u_int proto, u_int64_t ltime, ! 1644: u_int64_t vtime, char *policy, int policylen, u_int32_t seq) ! 1645: { ! 1646: struct sadb_msg *newmsg; ! 1647: int len; ! 1648: caddr_t p; ! 1649: int plen; ! 1650: caddr_t ep; ! 1651: ! 1652: /* validity check */ ! 1653: if (src == NULL || dst == NULL) { ! 1654: __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; ! 1655: return -1; ! 1656: } ! 1657: if (src->sa_family != dst->sa_family) { ! 1658: __ipsec_errcode = EIPSEC_FAMILY_MISMATCH; ! 1659: return -1; ! 1660: } ! 1661: ! 1662: switch (src->sa_family) { ! 1663: case AF_INET: ! 1664: plen = sizeof(struct in_addr) << 3; ! 1665: break; ! 1666: case AF_INET6: ! 1667: plen = sizeof(struct in6_addr) << 3; ! 1668: break; ! 1669: default: ! 1670: __ipsec_errcode = EIPSEC_INVAL_FAMILY; ! 1671: return -1; ! 1672: } ! 1673: if (prefs > plen || prefd > plen) { ! 1674: __ipsec_errcode = EIPSEC_INVAL_PREFIXLEN; ! 1675: return -1; ! 1676: } ! 1677: ! 1678: /* create new sadb_msg to reply. */ ! 1679: len = sizeof(struct sadb_msg) ! 1680: + sizeof(struct sadb_address) ! 1681: + PFKEY_ALIGN8(sysdep_sa_len(src)) ! 1682: + sizeof(struct sadb_address) ! 1683: + PFKEY_ALIGN8(sysdep_sa_len(src)) ! 1684: + sizeof(struct sadb_lifetime) ! 1685: + policylen; ! 1686: ! 1687: if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) { ! 1688: __ipsec_set_strerror(strerror(errno)); ! 1689: return -1; ! 1690: } ! 1691: ep = ((caddr_t)(void *)newmsg) + len; ! 1692: ! 1693: p = pfkey_setsadbmsg((void *)newmsg, ep, type, (u_int)len, ! 1694: SADB_SATYPE_UNSPEC, seq, getpid()); ! 1695: if (!p) { ! 1696: free(newmsg); ! 1697: return -1; ! 1698: } ! 1699: p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, prefs, proto); ! 1700: if (!p) { ! 1701: free(newmsg); ! 1702: return -1; ! 1703: } ! 1704: p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, prefd, proto); ! 1705: if (!p) { ! 1706: free(newmsg); ! 1707: return -1; ! 1708: } ! 1709: p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_HARD, ! 1710: 0, 0, (u_int)ltime, (u_int)vtime); ! 1711: if (!p || p + policylen != ep) { ! 1712: free(newmsg); ! 1713: return -1; ! 1714: } ! 1715: memcpy(p, policy, (size_t)policylen); ! 1716: ! 1717: /* send message */ ! 1718: len = pfkey_send(so, newmsg, len); ! 1719: free(newmsg); ! 1720: ! 1721: if (len < 0) ! 1722: return -1; ! 1723: ! 1724: __ipsec_errcode = EIPSEC_NO_ERROR; ! 1725: return len; ! 1726: } ! 1727: ! 1728: /* sending SADB_X_SPDGET or SADB_X_SPDDELETE message to the kernel */ ! 1729: static int ! 1730: pfkey_send_x5(int so, u_int type, u_int32_t spid) ! 1731: { ! 1732: struct sadb_msg *newmsg; ! 1733: struct sadb_x_policy xpl; ! 1734: int len; ! 1735: caddr_t p; ! 1736: caddr_t ep; ! 1737: ! 1738: /* create new sadb_msg to reply. */ ! 1739: len = sizeof(struct sadb_msg) ! 1740: + sizeof(xpl); ! 1741: ! 1742: if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) { ! 1743: __ipsec_set_strerror(strerror(errno)); ! 1744: return -1; ! 1745: } ! 1746: ep = ((caddr_t)(void *)newmsg) + len; ! 1747: ! 1748: p = pfkey_setsadbmsg((void *)newmsg, ep, type, (u_int)len, ! 1749: SADB_SATYPE_UNSPEC, 0, getpid()); ! 1750: if (!p) { ! 1751: free(newmsg); ! 1752: return -1; ! 1753: } ! 1754: ! 1755: if (p + sizeof(xpl) != ep) { ! 1756: free(newmsg); ! 1757: return -1; ! 1758: } ! 1759: memset(&xpl, 0, sizeof(xpl)); ! 1760: xpl.sadb_x_policy_len = PFKEY_UNIT64(sizeof(xpl)); ! 1761: xpl.sadb_x_policy_exttype = SADB_X_EXT_POLICY; ! 1762: xpl.sadb_x_policy_id = spid; ! 1763: memcpy(p, &xpl, sizeof(xpl)); ! 1764: ! 1765: /* send message */ ! 1766: len = pfkey_send(so, newmsg, len); ! 1767: free(newmsg); ! 1768: ! 1769: if (len < 0) ! 1770: return -1; ! 1771: ! 1772: __ipsec_errcode = EIPSEC_NO_ERROR; ! 1773: return len; ! 1774: } ! 1775: ! 1776: /* ! 1777: * open a socket. ! 1778: * OUT: ! 1779: * -1: fail. ! 1780: * others : success and return value of socket. ! 1781: */ ! 1782: int ! 1783: pfkey_open(void) ! 1784: { ! 1785: int so; ! 1786: int bufsiz = 128 * 1024; /*is 128K enough?*/ ! 1787: ! 1788: if ((so = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) < 0) { ! 1789: __ipsec_set_strerror(strerror(errno)); ! 1790: return -1; ! 1791: } ! 1792: ! 1793: /* ! 1794: * This is a temporary workaround for KAME PR 154. ! 1795: * Don't really care even if it fails. ! 1796: */ ! 1797: (void)setsockopt(so, SOL_SOCKET, SO_SNDBUF, &bufsiz, sizeof(bufsiz)); ! 1798: (void)setsockopt(so, SOL_SOCKET, SO_RCVBUF, &bufsiz, sizeof(bufsiz)); ! 1799: bufsiz = 256 * 1024; ! 1800: (void)setsockopt(so, SOL_SOCKET, SO_RCVBUF, &bufsiz, sizeof(bufsiz)); ! 1801: bufsiz = 512 * 1024; ! 1802: (void)setsockopt(so, SOL_SOCKET, SO_RCVBUF, &bufsiz, sizeof(bufsiz)); ! 1803: bufsiz = 1024 * 1024; ! 1804: (void)setsockopt(so, SOL_SOCKET, SO_RCVBUF, &bufsiz, sizeof(bufsiz)); ! 1805: __ipsec_errcode = EIPSEC_NO_ERROR; ! 1806: return so; ! 1807: } ! 1808: ! 1809: int ! 1810: pfkey_set_buffer_size(int so, int size) ! 1811: { ! 1812: int newsize; ! 1813: int actual_bufsiz; ! 1814: socklen_t sizebufsiz; ! 1815: int desired_bufsiz; ! 1816: ! 1817: /* ! 1818: * on linux you may need to allow the kernel to allocate ! 1819: * more buffer space by increasing: ! 1820: * /proc/sys/net/core/rmem_max and wmem_max ! 1821: */ ! 1822: if (size > 0) { ! 1823: actual_bufsiz = 0; ! 1824: sizebufsiz = sizeof(actual_bufsiz); ! 1825: desired_bufsiz = size * 1024; ! 1826: if ((getsockopt(so, SOL_SOCKET, SO_RCVBUF, ! 1827: &actual_bufsiz, &sizebufsiz) < 0) ! 1828: || (actual_bufsiz < desired_bufsiz)) { ! 1829: if (setsockopt(so, SOL_SOCKET, SO_RCVBUF, ! 1830: &desired_bufsiz, sizeof(desired_bufsiz)) < 0) { ! 1831: __ipsec_set_strerror(strerror(errno)); ! 1832: return -1; ! 1833: } ! 1834: } ! 1835: } ! 1836: ! 1837: /* return actual buffer size */ ! 1838: actual_bufsiz = 0; ! 1839: sizebufsiz = sizeof(actual_bufsiz); ! 1840: getsockopt(so, SOL_SOCKET, SO_RCVBUF, ! 1841: &actual_bufsiz, &sizebufsiz); ! 1842: return actual_bufsiz / 1024; ! 1843: } ! 1844: ! 1845: /* ! 1846: * close a socket. ! 1847: * OUT: ! 1848: * 0: success. ! 1849: * -1: fail. ! 1850: */ ! 1851: void ! 1852: pfkey_close(int so) ! 1853: { ! 1854: (void)close(so); ! 1855: ! 1856: __ipsec_errcode = EIPSEC_NO_ERROR; ! 1857: return; ! 1858: } ! 1859: ! 1860: /* ! 1861: * receive sadb_msg data, and return pointer to new buffer allocated. ! 1862: * Must free this buffer later. ! 1863: * OUT: ! 1864: * NULL : error occured. ! 1865: * others : a pointer to sadb_msg structure. ! 1866: * ! 1867: * XXX should be rewritten to pass length explicitly ! 1868: */ ! 1869: struct sadb_msg * ! 1870: pfkey_recv(int so) ! 1871: { ! 1872: struct sadb_msg buf, *newmsg; ! 1873: int len, reallen; ! 1874: ! 1875: while ((len = recv(so, (void *)&buf, sizeof(buf), MSG_PEEK)) < 0) { ! 1876: if (errno == EINTR) ! 1877: continue; ! 1878: __ipsec_set_strerror(strerror(errno)); ! 1879: return NULL; ! 1880: } ! 1881: ! 1882: if (len < sizeof(buf)) { ! 1883: recv(so, (void *)&buf, sizeof(buf), 0); ! 1884: __ipsec_errcode = EIPSEC_MAX; ! 1885: return NULL; ! 1886: } ! 1887: ! 1888: /* read real message */ ! 1889: reallen = PFKEY_UNUNIT64(buf.sadb_msg_len); ! 1890: if ((newmsg = CALLOC((size_t)reallen, struct sadb_msg *)) == 0) { ! 1891: __ipsec_set_strerror(strerror(errno)); ! 1892: return NULL; ! 1893: } ! 1894: ! 1895: while ((len = recv(so, (void *)newmsg, (socklen_t)reallen, 0)) < 0) { ! 1896: if (errno == EINTR) ! 1897: continue; ! 1898: __ipsec_set_strerror(strerror(errno)); ! 1899: free(newmsg); ! 1900: return NULL; ! 1901: } ! 1902: ! 1903: if (len != reallen) { ! 1904: __ipsec_errcode = EIPSEC_SYSTEM_ERROR; ! 1905: free(newmsg); ! 1906: return NULL; ! 1907: } ! 1908: ! 1909: /* don't trust what the kernel says, validate! */ ! 1910: if (PFKEY_UNUNIT64(newmsg->sadb_msg_len) != len) { ! 1911: __ipsec_errcode = EIPSEC_SYSTEM_ERROR; ! 1912: free(newmsg); ! 1913: return NULL; ! 1914: } ! 1915: ! 1916: __ipsec_errcode = EIPSEC_NO_ERROR; ! 1917: return newmsg; ! 1918: } ! 1919: ! 1920: /* ! 1921: * send message to a socket. ! 1922: * OUT: ! 1923: * others: success and return length sent. ! 1924: * -1 : fail. ! 1925: */ ! 1926: int ! 1927: pfkey_send(int so, struct sadb_msg *msg, int len) ! 1928: { ! 1929: if ((len = send(so, (void *)msg, (socklen_t)len, 0)) < 0) { ! 1930: __ipsec_set_strerror(strerror(errno)); ! 1931: return -1; ! 1932: } ! 1933: ! 1934: __ipsec_errcode = EIPSEC_NO_ERROR; ! 1935: return len; ! 1936: } ! 1937: ! 1938: /* ! 1939: * %%% Utilities ! 1940: * NOTE: These functions are derived from netkey/key.c in KAME. ! 1941: */ ! 1942: /* ! 1943: * set the pointer to each header in this message buffer. ! 1944: * IN: msg: pointer to message buffer. ! 1945: * mhp: pointer to the buffer initialized like below: ! 1946: * caddr_t mhp[SADB_EXT_MAX + 1]; ! 1947: * OUT: -1: invalid. ! 1948: * 0: valid. ! 1949: * ! 1950: * XXX should be rewritten to obtain length explicitly ! 1951: */ ! 1952: int ! 1953: pfkey_align(struct sadb_msg *msg, caddr_t *mhp) ! 1954: { ! 1955: struct sadb_ext *ext; ! 1956: int i; ! 1957: caddr_t p; ! 1958: caddr_t ep; /* XXX should be passed from upper layer */ ! 1959: ! 1960: /* validity check */ ! 1961: if (msg == NULL || mhp == NULL) { ! 1962: __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; ! 1963: return -1; ! 1964: } ! 1965: ! 1966: /* initialize */ ! 1967: for (i = 0; i < SADB_EXT_MAX + 1; i++) ! 1968: mhp[i] = NULL; ! 1969: ! 1970: mhp[0] = (void *)msg; ! 1971: ! 1972: /* initialize */ ! 1973: p = (void *) msg; ! 1974: ep = p + PFKEY_UNUNIT64(msg->sadb_msg_len); ! 1975: ! 1976: /* skip base header */ ! 1977: p += sizeof(struct sadb_msg); ! 1978: ! 1979: while (p < ep) { ! 1980: ext = (void *)p; ! 1981: if (ep < p + sizeof(*ext) || PFKEY_EXTLEN(ext) < sizeof(*ext) || ! 1982: ep < p + PFKEY_EXTLEN(ext)) { ! 1983: /* invalid format */ ! 1984: break; ! 1985: } ! 1986: ! 1987: /* duplicate check */ ! 1988: /* XXX Are there duplication either KEY_AUTH or KEY_ENCRYPT ?*/ ! 1989: if (mhp[ext->sadb_ext_type] != NULL) { ! 1990: __ipsec_errcode = EIPSEC_INVAL_EXTTYPE; ! 1991: return -1; ! 1992: } ! 1993: ! 1994: /* set pointer */ ! 1995: switch (ext->sadb_ext_type) { ! 1996: case SADB_EXT_SA: ! 1997: case SADB_EXT_LIFETIME_CURRENT: ! 1998: case SADB_EXT_LIFETIME_HARD: ! 1999: case SADB_EXT_LIFETIME_SOFT: ! 2000: case SADB_EXT_ADDRESS_SRC: ! 2001: case SADB_EXT_ADDRESS_DST: ! 2002: case SADB_EXT_ADDRESS_PROXY: ! 2003: case SADB_EXT_KEY_AUTH: ! 2004: /* XXX should to be check weak keys. */ ! 2005: case SADB_EXT_KEY_ENCRYPT: ! 2006: /* XXX should to be check weak keys. */ ! 2007: case SADB_EXT_IDENTITY_SRC: ! 2008: case SADB_EXT_IDENTITY_DST: ! 2009: case SADB_EXT_SENSITIVITY: ! 2010: case SADB_EXT_PROPOSAL: ! 2011: case SADB_EXT_SUPPORTED_AUTH: ! 2012: case SADB_EXT_SUPPORTED_ENCRYPT: ! 2013: case SADB_EXT_SPIRANGE: ! 2014: case SADB_X_EXT_POLICY: ! 2015: case SADB_X_EXT_SA2: ! 2016: #ifdef SADB_X_EXT_NAT_T_TYPE ! 2017: case SADB_X_EXT_NAT_T_TYPE: ! 2018: case SADB_X_EXT_NAT_T_SPORT: ! 2019: case SADB_X_EXT_NAT_T_DPORT: ! 2020: case SADB_X_EXT_NAT_T_OA: ! 2021: #endif ! 2022: #ifdef SADB_X_EXT_TAG ! 2023: case SADB_X_EXT_TAG: ! 2024: #endif ! 2025: #ifdef SADB_X_EXT_PACKET ! 2026: case SADB_X_EXT_PACKET: ! 2027: #endif ! 2028: #ifdef SADB_X_EXT_KMADDRESS ! 2029: case SADB_X_EXT_KMADDRESS: ! 2030: #endif ! 2031: #ifdef SADB_X_EXT_SEC_CTX ! 2032: case SADB_X_EXT_SEC_CTX: ! 2033: #endif ! 2034: mhp[ext->sadb_ext_type] = (void *)ext; ! 2035: break; ! 2036: default: ! 2037: __ipsec_errcode = EIPSEC_INVAL_EXTTYPE; ! 2038: return -1; ! 2039: } ! 2040: ! 2041: p += PFKEY_EXTLEN(ext); ! 2042: } ! 2043: ! 2044: if (p != ep) { ! 2045: __ipsec_errcode = EIPSEC_INVAL_SADBMSG; ! 2046: return -1; ! 2047: } ! 2048: ! 2049: __ipsec_errcode = EIPSEC_NO_ERROR; ! 2050: return 0; ! 2051: } ! 2052: ! 2053: /* ! 2054: * check basic usage for sadb_msg, ! 2055: * NOTE: This routine is derived from netkey/key.c in KAME. ! 2056: * IN: msg: pointer to message buffer. ! 2057: * mhp: pointer to the buffer initialized like below: ! 2058: * ! 2059: * caddr_t mhp[SADB_EXT_MAX + 1]; ! 2060: * ! 2061: * OUT: -1: invalid. ! 2062: * 0: valid. ! 2063: */ ! 2064: int ! 2065: pfkey_check(caddr_t *mhp) ! 2066: { ! 2067: struct sadb_msg *msg; ! 2068: ! 2069: /* validity check */ ! 2070: if (mhp == NULL || mhp[0] == NULL) { ! 2071: __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; ! 2072: return -1; ! 2073: } ! 2074: ! 2075: msg = (void *)mhp[0]; ! 2076: ! 2077: /* check version */ ! 2078: if (msg->sadb_msg_version != PF_KEY_V2) { ! 2079: __ipsec_errcode = EIPSEC_INVAL_VERSION; ! 2080: return -1; ! 2081: } ! 2082: ! 2083: /* check type */ ! 2084: if (msg->sadb_msg_type > SADB_MAX) { ! 2085: __ipsec_errcode = EIPSEC_INVAL_MSGTYPE; ! 2086: return -1; ! 2087: } ! 2088: ! 2089: /* check SA type */ ! 2090: switch (msg->sadb_msg_satype) { ! 2091: case SADB_SATYPE_UNSPEC: ! 2092: switch (msg->sadb_msg_type) { ! 2093: case SADB_GETSPI: ! 2094: case SADB_UPDATE: ! 2095: case SADB_ADD: ! 2096: case SADB_DELETE: ! 2097: case SADB_GET: ! 2098: case SADB_ACQUIRE: ! 2099: case SADB_EXPIRE: ! 2100: #ifdef SADB_X_NAT_T_NEW_MAPPING ! 2101: case SADB_X_NAT_T_NEW_MAPPING: ! 2102: #endif ! 2103: __ipsec_errcode = EIPSEC_INVAL_SATYPE; ! 2104: return -1; ! 2105: } ! 2106: break; ! 2107: case SADB_SATYPE_ESP: ! 2108: case SADB_SATYPE_AH: ! 2109: case SADB_X_SATYPE_IPCOMP: ! 2110: #ifdef SADB_X_SATYPE_TCPSIGNATURE ! 2111: case SADB_X_SATYPE_TCPSIGNATURE: ! 2112: #endif ! 2113: switch (msg->sadb_msg_type) { ! 2114: case SADB_X_SPDADD: ! 2115: case SADB_X_SPDDELETE: ! 2116: case SADB_X_SPDGET: ! 2117: case SADB_X_SPDDUMP: ! 2118: case SADB_X_SPDFLUSH: ! 2119: __ipsec_errcode = EIPSEC_INVAL_SATYPE; ! 2120: return -1; ! 2121: } ! 2122: #ifdef SADB_X_NAT_T_NEW_MAPPING ! 2123: if (msg->sadb_msg_type == SADB_X_NAT_T_NEW_MAPPING && ! 2124: msg->sadb_msg_satype != SADB_SATYPE_ESP) { ! 2125: __ipsec_errcode = EIPSEC_INVAL_SATYPE; ! 2126: return -1; ! 2127: } ! 2128: #endif ! 2129: break; ! 2130: case SADB_SATYPE_RSVP: ! 2131: case SADB_SATYPE_OSPFV2: ! 2132: case SADB_SATYPE_RIPV2: ! 2133: case SADB_SATYPE_MIP: ! 2134: __ipsec_errcode = EIPSEC_NOT_SUPPORTED; ! 2135: return -1; ! 2136: case 1: /* XXX: What does it do ? */ ! 2137: if (msg->sadb_msg_type == SADB_X_PROMISC) ! 2138: break; ! 2139: /*FALLTHROUGH*/ ! 2140: default: ! 2141: #ifdef __linux__ ! 2142: /* Linux kernel seems to be buggy and return ! 2143: * uninitialized satype for spd flush message */ ! 2144: if (msg->sadb_msg_type == SADB_X_SPDFLUSH) ! 2145: break; ! 2146: #endif ! 2147: __ipsec_errcode = EIPSEC_INVAL_SATYPE; ! 2148: return -1; ! 2149: } ! 2150: ! 2151: /* check field of upper layer protocol and address family */ ! 2152: if (mhp[SADB_EXT_ADDRESS_SRC] != NULL ! 2153: && mhp[SADB_EXT_ADDRESS_DST] != NULL) { ! 2154: struct sadb_address *src0, *dst0; ! 2155: ! 2156: src0 = (void *)(mhp[SADB_EXT_ADDRESS_SRC]); ! 2157: dst0 = (void *)(mhp[SADB_EXT_ADDRESS_DST]); ! 2158: ! 2159: if (src0->sadb_address_proto != dst0->sadb_address_proto) { ! 2160: __ipsec_errcode = EIPSEC_PROTO_MISMATCH; ! 2161: return -1; ! 2162: } ! 2163: ! 2164: if (PFKEY_ADDR_SADDR(src0)->sa_family ! 2165: != PFKEY_ADDR_SADDR(dst0)->sa_family) { ! 2166: __ipsec_errcode = EIPSEC_FAMILY_MISMATCH; ! 2167: return -1; ! 2168: } ! 2169: ! 2170: switch (PFKEY_ADDR_SADDR(src0)->sa_family) { ! 2171: case AF_INET: ! 2172: case AF_INET6: ! 2173: break; ! 2174: default: ! 2175: __ipsec_errcode = EIPSEC_INVAL_FAMILY; ! 2176: return -1; ! 2177: } ! 2178: ! 2179: /* ! 2180: * prefixlen == 0 is valid because there must be the case ! 2181: * all addresses are matched. ! 2182: */ ! 2183: } ! 2184: ! 2185: __ipsec_errcode = EIPSEC_NO_ERROR; ! 2186: return 0; ! 2187: } ! 2188: ! 2189: /* ! 2190: * set data into sadb_msg. ! 2191: * `buf' must has been allocated sufficiently. ! 2192: */ ! 2193: static caddr_t ! 2194: pfkey_setsadbmsg(caddr_t buf, caddr_t lim, u_int type, u_int tlen, ! 2195: u_int satype, u_int32_t seq, pid_t pid) ! 2196: { ! 2197: struct sadb_msg *p; ! 2198: u_int len; ! 2199: ! 2200: p = (void *)buf; ! 2201: len = sizeof(struct sadb_msg); ! 2202: ! 2203: if (buf + len > lim) ! 2204: return NULL; ! 2205: ! 2206: memset(p, 0, len); ! 2207: p->sadb_msg_version = PF_KEY_V2; ! 2208: p->sadb_msg_type = type; ! 2209: p->sadb_msg_errno = 0; ! 2210: p->sadb_msg_satype = satype; ! 2211: p->sadb_msg_len = PFKEY_UNIT64(tlen); ! 2212: p->sadb_msg_reserved = 0; ! 2213: p->sadb_msg_seq = seq; ! 2214: p->sadb_msg_pid = (u_int32_t)pid; ! 2215: ! 2216: return(buf + len); ! 2217: } ! 2218: ! 2219: /* ! 2220: * copy secasvar data into sadb_address. ! 2221: * `buf' must has been allocated sufficiently. ! 2222: */ ! 2223: static caddr_t ! 2224: pfkey_setsadbsa(caddr_t buf, caddr_t lim, u_int32_t spi, u_int wsize, ! 2225: u_int auth, u_int enc, u_int32_t flags) ! 2226: { ! 2227: struct sadb_sa *p; ! 2228: u_int len; ! 2229: ! 2230: p = (void *)buf; ! 2231: len = sizeof(struct sadb_sa); ! 2232: ! 2233: if (buf + len > lim) ! 2234: return NULL; ! 2235: ! 2236: memset(p, 0, len); ! 2237: p->sadb_sa_len = PFKEY_UNIT64(len); ! 2238: p->sadb_sa_exttype = SADB_EXT_SA; ! 2239: p->sadb_sa_spi = spi; ! 2240: p->sadb_sa_replay = wsize; ! 2241: p->sadb_sa_state = SADB_SASTATE_LARVAL; ! 2242: p->sadb_sa_auth = auth; ! 2243: p->sadb_sa_encrypt = enc; ! 2244: p->sadb_sa_flags = flags; ! 2245: ! 2246: return(buf + len); ! 2247: } ! 2248: ! 2249: /* ! 2250: * set data into sadb_address. ! 2251: * `buf' must has been allocated sufficiently. ! 2252: * prefixlen is in bits. ! 2253: */ ! 2254: static caddr_t ! 2255: pfkey_setsadbaddr(caddr_t buf, caddr_t lim, u_int exttype, ! 2256: struct sockaddr *saddr, u_int prefixlen, u_int ul_proto) ! 2257: { ! 2258: struct sadb_address *p; ! 2259: u_int len; ! 2260: ! 2261: p = (void *)buf; ! 2262: len = sizeof(struct sadb_address) + PFKEY_ALIGN8(sysdep_sa_len(saddr)); ! 2263: ! 2264: if (buf + len > lim) ! 2265: return NULL; ! 2266: ! 2267: memset(p, 0, len); ! 2268: p->sadb_address_len = PFKEY_UNIT64(len); ! 2269: p->sadb_address_exttype = exttype & 0xffff; ! 2270: p->sadb_address_proto = ul_proto & 0xff; ! 2271: p->sadb_address_prefixlen = prefixlen; ! 2272: p->sadb_address_reserved = 0; ! 2273: ! 2274: memcpy(p + 1, saddr, (size_t)sysdep_sa_len(saddr)); ! 2275: ! 2276: return(buf + len); ! 2277: } ! 2278: ! 2279: #ifdef SADB_X_EXT_KMADDRESS ! 2280: /* ! 2281: * set data into sadb_x_kmaddress. ! 2282: * `buf' must has been allocated sufficiently. ! 2283: */ ! 2284: static caddr_t ! 2285: pfkey_setsadbkmaddr(caddr_t buf, caddr_t lim, struct sockaddr *local, ! 2286: struct sockaddr *remote) ! 2287: { ! 2288: struct sadb_x_kmaddress *p; ! 2289: struct sockaddr *sa; ! 2290: u_int salen = sysdep_sa_len(local); ! 2291: u_int len; ! 2292: ! 2293: /* sanity check */ ! 2294: if (local->sa_family != remote->sa_family) ! 2295: return NULL; ! 2296: ! 2297: p = (void *)buf; ! 2298: len = sizeof(struct sadb_x_kmaddress) + PFKEY_ALIGN8(2*salen); ! 2299: ! 2300: if (buf + len > lim) ! 2301: return NULL; ! 2302: ! 2303: memset(p, 0, len); ! 2304: p->sadb_x_kmaddress_len = PFKEY_UNIT64(len); ! 2305: p->sadb_x_kmaddress_exttype = SADB_X_EXT_KMADDRESS; ! 2306: p->sadb_x_kmaddress_reserved = 0; ! 2307: sa = (struct sockaddr *)(p + 1); ! 2308: memcpy(sa, local, salen); ! 2309: sa = (struct sockaddr *)((char *)sa + salen); ! 2310: memcpy(sa, remote, salen); ! 2311: ! 2312: return(buf + len); ! 2313: } ! 2314: #endif ! 2315: ! 2316: /* ! 2317: * set sadb_key structure after clearing buffer with zero. ! 2318: * OUT: the pointer of buf + len. ! 2319: */ ! 2320: static caddr_t ! 2321: pfkey_setsadbkey(caddr_t buf, caddr_t lim, u_int type, caddr_t key, ! 2322: u_int keylen) ! 2323: { ! 2324: struct sadb_key *p; ! 2325: u_int len; ! 2326: ! 2327: p = (void *)buf; ! 2328: len = sizeof(struct sadb_key) + PFKEY_ALIGN8(keylen); ! 2329: ! 2330: if (buf + len > lim) ! 2331: return NULL; ! 2332: ! 2333: memset(p, 0, len); ! 2334: p->sadb_key_len = PFKEY_UNIT64(len); ! 2335: p->sadb_key_exttype = type; ! 2336: p->sadb_key_bits = keylen << 3; ! 2337: p->sadb_key_reserved = 0; ! 2338: ! 2339: memcpy(p + 1, key, keylen); ! 2340: ! 2341: return buf + len; ! 2342: } ! 2343: ! 2344: /* ! 2345: * set sadb_lifetime structure after clearing buffer with zero. ! 2346: * OUT: the pointer of buf + len. ! 2347: */ ! 2348: static caddr_t ! 2349: pfkey_setsadblifetime(caddr_t buf, caddr_t lim, u_int type, u_int32_t l_alloc, ! 2350: u_int32_t l_bytes, u_int32_t l_addtime, u_int32_t l_usetime) ! 2351: { ! 2352: struct sadb_lifetime *p; ! 2353: u_int len; ! 2354: ! 2355: p = (void *)buf; ! 2356: len = sizeof(struct sadb_lifetime); ! 2357: ! 2358: if (buf + len > lim) ! 2359: return NULL; ! 2360: ! 2361: memset(p, 0, len); ! 2362: p->sadb_lifetime_len = PFKEY_UNIT64(len); ! 2363: p->sadb_lifetime_exttype = type; ! 2364: ! 2365: switch (type) { ! 2366: case SADB_EXT_LIFETIME_SOFT: ! 2367: p->sadb_lifetime_allocations ! 2368: = (l_alloc * soft_lifetime_allocations_rate) /100; ! 2369: p->sadb_lifetime_bytes ! 2370: = (l_bytes * soft_lifetime_bytes_rate) /100; ! 2371: p->sadb_lifetime_addtime ! 2372: = (l_addtime * soft_lifetime_addtime_rate) /100; ! 2373: p->sadb_lifetime_usetime ! 2374: = (l_usetime * soft_lifetime_usetime_rate) /100; ! 2375: break; ! 2376: case SADB_EXT_LIFETIME_HARD: ! 2377: p->sadb_lifetime_allocations = l_alloc; ! 2378: p->sadb_lifetime_bytes = l_bytes; ! 2379: p->sadb_lifetime_addtime = l_addtime; ! 2380: p->sadb_lifetime_usetime = l_usetime; ! 2381: break; ! 2382: } ! 2383: ! 2384: return buf + len; ! 2385: } ! 2386: ! 2387: /* ! 2388: * copy secasvar data into sadb_address. ! 2389: * `buf' must has been allocated sufficiently. ! 2390: */ ! 2391: static caddr_t ! 2392: pfkey_setsadbxsa2(caddr_t buf, caddr_t lim, u_int32_t mode0, u_int32_t reqid) ! 2393: { ! 2394: struct sadb_x_sa2 *p; ! 2395: u_int8_t mode = mode0 & 0xff; ! 2396: u_int len; ! 2397: ! 2398: p = (void *)buf; ! 2399: len = sizeof(struct sadb_x_sa2); ! 2400: ! 2401: if (buf + len > lim) ! 2402: return NULL; ! 2403: ! 2404: memset(p, 0, len); ! 2405: p->sadb_x_sa2_len = PFKEY_UNIT64(len); ! 2406: p->sadb_x_sa2_exttype = SADB_X_EXT_SA2; ! 2407: p->sadb_x_sa2_mode = mode; ! 2408: p->sadb_x_sa2_reqid = reqid; ! 2409: ! 2410: return(buf + len); ! 2411: } ! 2412: ! 2413: #ifdef SADB_X_EXT_NAT_T_TYPE ! 2414: static caddr_t ! 2415: pfkey_set_natt_type(caddr_t buf, caddr_t lim, u_int type, u_int8_t l_natt_type) ! 2416: { ! 2417: struct sadb_x_nat_t_type *p; ! 2418: u_int len; ! 2419: ! 2420: p = (void *)buf; ! 2421: len = sizeof(struct sadb_x_nat_t_type); ! 2422: ! 2423: if (buf + len > lim) ! 2424: return NULL; ! 2425: ! 2426: memset(p, 0, len); ! 2427: p->sadb_x_nat_t_type_len = PFKEY_UNIT64(len); ! 2428: p->sadb_x_nat_t_type_exttype = type; ! 2429: p->sadb_x_nat_t_type_type = l_natt_type; ! 2430: ! 2431: return(buf + len); ! 2432: } ! 2433: ! 2434: static caddr_t ! 2435: pfkey_set_natt_port(caddr_t buf, caddr_t lim, u_int type, u_int16_t l_natt_port) ! 2436: { ! 2437: struct sadb_x_nat_t_port *p; ! 2438: u_int len; ! 2439: ! 2440: p = (void *)buf; ! 2441: len = sizeof(struct sadb_x_nat_t_port); ! 2442: ! 2443: if (buf + len > lim) ! 2444: return NULL; ! 2445: ! 2446: memset(p, 0, len); ! 2447: p->sadb_x_nat_t_port_len = PFKEY_UNIT64(len); ! 2448: p->sadb_x_nat_t_port_exttype = type; ! 2449: p->sadb_x_nat_t_port_port = htons(l_natt_port); ! 2450: ! 2451: return(buf + len); ! 2452: } ! 2453: #endif ! 2454: ! 2455: #ifdef SADB_X_EXT_NAT_T_FRAG ! 2456: static caddr_t ! 2457: pfkey_set_natt_frag(caddr_t buf, caddr_t lim, u_int type, ! 2458: u_int16_t l_natt_frag) ! 2459: { ! 2460: struct sadb_x_nat_t_frag *p; ! 2461: u_int len; ! 2462: ! 2463: p = (void *)buf; ! 2464: len = sizeof(struct sadb_x_nat_t_frag); ! 2465: ! 2466: if (buf + len > lim) ! 2467: return NULL; ! 2468: ! 2469: memset(p, 0, len); ! 2470: p->sadb_x_nat_t_frag_len = PFKEY_UNIT64(len); ! 2471: p->sadb_x_nat_t_frag_exttype = type; ! 2472: p->sadb_x_nat_t_frag_fraglen = l_natt_frag; ! 2473: ! 2474: return(buf + len); ! 2475: } ! 2476: #endif ! 2477: ! 2478: #ifdef SADB_X_EXT_SEC_CTX ! 2479: static caddr_t ! 2480: pfkey_setsecctx(caddr_t buf, caddr_t lim, u_int type, u_int8_t ctx_doi, ! 2481: u_int8_t ctx_alg, caddr_t sec_ctx, u_int16_t sec_ctxlen) ! 2482: { ! 2483: struct sadb_x_sec_ctx *p; ! 2484: u_int len; ! 2485: ! 2486: p = (struct sadb_x_sec_ctx *)buf; ! 2487: len = sizeof(struct sadb_x_sec_ctx) + PFKEY_ALIGN8(sec_ctxlen); ! 2488: ! 2489: if (buf + len > lim) ! 2490: return NULL; ! 2491: ! 2492: memset(p, 0, len); ! 2493: p->sadb_x_sec_len = PFKEY_UNIT64(len); ! 2494: p->sadb_x_sec_exttype = type; ! 2495: p->sadb_x_ctx_len = sec_ctxlen; ! 2496: p->sadb_x_ctx_doi = ctx_doi; ! 2497: p->sadb_x_ctx_alg = ctx_alg; ! 2498: ! 2499: memcpy(p + 1, sec_ctx, sec_ctxlen); ! 2500: ! 2501: return buf + len; ! 2502: } ! 2503: #endif ! 2504: ! 2505: /* ! 2506: * Deprecated, available for backward compatibility with third party ! 2507: * libipsec users. Please use pfkey_send_update2 and pfkey_send_add2 instead ! 2508: */ ! 2509: int ! 2510: pfkey_send_update(int so, u_int satype, u_int mode, struct sockaddr *src, ! 2511: struct sockaddr *dst, u_int32_t spi, u_int32_t reqid, u_int wsize, ! 2512: caddr_t keymat, u_int e_type, u_int e_keylen, u_int a_type, ! 2513: u_int a_keylen, u_int flags, u_int32_t l_alloc, u_int64_t l_bytes, ! 2514: u_int64_t l_addtime, u_int64_t l_usetime, u_int32_t seq) ! 2515: { ! 2516: struct pfkey_send_sa_args psaa; ! 2517: ! 2518: memset(&psaa, 0, sizeof(psaa)); ! 2519: psaa.so = so; ! 2520: psaa.type = SADB_UPDATE; ! 2521: psaa.satype = satype; ! 2522: psaa.mode = mode; ! 2523: psaa.wsize = wsize; ! 2524: psaa.src = src; ! 2525: psaa.dst = dst; ! 2526: psaa.spi = spi; ! 2527: psaa.reqid = reqid; ! 2528: psaa.keymat = keymat; ! 2529: psaa.e_type = e_type; ! 2530: psaa.e_keylen = e_keylen; ! 2531: psaa.a_type = a_type; ! 2532: psaa.a_keylen = a_keylen; ! 2533: psaa.flags = flags; ! 2534: psaa.l_alloc = l_alloc; ! 2535: psaa.l_bytes = l_bytes; ! 2536: psaa.l_addtime = l_addtime; ! 2537: psaa.l_usetime = l_usetime; ! 2538: psaa.seq = seq; ! 2539: ! 2540: return pfkey_send_update2(&psaa); ! 2541: } ! 2542: ! 2543: int ! 2544: pfkey_send_update_nat(int so, u_int satype, u_int mode, struct sockaddr *src, ! 2545: struct sockaddr *dst, u_int32_t spi, u_int32_t reqid, u_int wsize, ! 2546: caddr_t keymat, u_int e_type, u_int e_keylen, u_int a_type, ! 2547: u_int a_keylen, u_int flags, u_int32_t l_alloc, u_int64_t l_bytes, ! 2548: u_int64_t l_addtime, u_int64_t l_usetime, u_int32_t seq, ! 2549: u_int8_t l_natt_type, u_int16_t l_natt_sport, u_int16_t l_natt_dport, ! 2550: struct sockaddr *l_natt_oa, u_int16_t l_natt_frag) ! 2551: { ! 2552: struct pfkey_send_sa_args psaa; ! 2553: ! 2554: memset(&psaa, 0, sizeof(psaa)); ! 2555: psaa.so = so; ! 2556: psaa.type = SADB_UPDATE; ! 2557: psaa.satype = satype; ! 2558: psaa.mode = mode; ! 2559: psaa.wsize = wsize; ! 2560: psaa.src = src; ! 2561: psaa.dst = dst; ! 2562: psaa.spi = spi; ! 2563: psaa.reqid = reqid; ! 2564: psaa.keymat = keymat; ! 2565: psaa.e_type = e_type; ! 2566: psaa.e_keylen = e_keylen; ! 2567: psaa.a_type = a_type; ! 2568: psaa.a_keylen = a_keylen; ! 2569: psaa.flags = flags; ! 2570: psaa.l_alloc = l_alloc; ! 2571: psaa.l_bytes = l_bytes; ! 2572: psaa.l_addtime = l_addtime; ! 2573: psaa.l_usetime = l_usetime; ! 2574: psaa.seq = seq; ! 2575: psaa.l_natt_type = l_natt_type; ! 2576: psaa.l_natt_sport = l_natt_sport; ! 2577: psaa.l_natt_dport = l_natt_dport; ! 2578: psaa.l_natt_oa = l_natt_oa; ! 2579: psaa.l_natt_frag = l_natt_frag; ! 2580: ! 2581: return pfkey_send_update2(&psaa); ! 2582: } ! 2583: ! 2584: int ! 2585: pfkey_send_add(int so, u_int satype, u_int mode, struct sockaddr *src, ! 2586: struct sockaddr *dst, u_int32_t spi, u_int32_t reqid, u_int wsize, ! 2587: caddr_t keymat, u_int e_type, u_int e_keylen, u_int a_type, ! 2588: u_int a_keylen, u_int flags, u_int32_t l_alloc, u_int64_t l_bytes, ! 2589: u_int64_t l_addtime, u_int64_t l_usetime, u_int32_t seq) ! 2590: { ! 2591: struct pfkey_send_sa_args psaa; ! 2592: ! 2593: memset(&psaa, 0, sizeof(psaa)); ! 2594: psaa.so = so; ! 2595: psaa.type = SADB_ADD; ! 2596: psaa.satype = satype; ! 2597: psaa.mode = mode; ! 2598: psaa.wsize = wsize; ! 2599: psaa.src = src; ! 2600: psaa.dst = dst; ! 2601: psaa.spi = spi; ! 2602: psaa.reqid = reqid; ! 2603: psaa.keymat = keymat; ! 2604: psaa.e_type = e_type; ! 2605: psaa.e_keylen = e_keylen; ! 2606: psaa.a_type = a_type; ! 2607: psaa.a_keylen = a_keylen; ! 2608: psaa.flags = flags; ! 2609: psaa.l_alloc = l_alloc; ! 2610: psaa.l_bytes = l_bytes; ! 2611: psaa.l_addtime = l_addtime; ! 2612: psaa.l_usetime = l_usetime; ! 2613: psaa.seq = seq; ! 2614: ! 2615: return pfkey_send_add2(&psaa); ! 2616: } ! 2617: ! 2618: int ! 2619: pfkey_send_add_nat(int so, u_int satype, u_int mode, struct sockaddr *src, ! 2620: struct sockaddr *dst, u_int32_t spi, u_int32_t reqid, u_int wsize, ! 2621: caddr_t keymat, u_int e_type, u_int e_keylen, u_int a_type, ! 2622: u_int a_keylen, u_int flags, u_int32_t l_alloc, u_int64_t l_bytes, ! 2623: u_int64_t l_addtime, u_int64_t l_usetime, u_int32_t seq, ! 2624: u_int8_t l_natt_type, u_int16_t l_natt_sport, u_int16_t l_natt_dport, ! 2625: struct sockaddr *l_natt_oa, u_int16_t l_natt_frag) ! 2626: { ! 2627: struct pfkey_send_sa_args psaa; ! 2628: ! 2629: memset(&psaa, 0, sizeof(psaa)); ! 2630: psaa.so = so; ! 2631: psaa.type = SADB_ADD; ! 2632: psaa.satype = satype; ! 2633: psaa.mode = mode; ! 2634: psaa.wsize = wsize; ! 2635: psaa.src = src; ! 2636: psaa.dst = dst; ! 2637: psaa.spi = spi; ! 2638: psaa.reqid = reqid; ! 2639: psaa.keymat = keymat; ! 2640: psaa.e_type = e_type; ! 2641: psaa.e_keylen = e_keylen; ! 2642: psaa.a_type = a_type; ! 2643: psaa.a_keylen = a_keylen; ! 2644: psaa.flags = flags; ! 2645: psaa.l_alloc = l_alloc; ! 2646: psaa.l_bytes = l_bytes; ! 2647: psaa.l_addtime = l_addtime; ! 2648: psaa.l_usetime = l_usetime; ! 2649: psaa.seq = seq; ! 2650: psaa.l_natt_type = l_natt_type; ! 2651: psaa.l_natt_sport = l_natt_sport; ! 2652: psaa.l_natt_dport = l_natt_dport; ! 2653: psaa.l_natt_oa = l_natt_oa; ! 2654: psaa.l_natt_frag = l_natt_frag; ! 2655: ! 2656: return pfkey_send_add2(&psaa); ! 2657: }