Annotation of embedaddon/ipsec-tools/src/libipsec/pfkey.c, revision 1.1
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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>