diff options
Diffstat (limited to 'freebsd/lib/libipsec/pfkey.c')
-rw-r--r-- | freebsd/lib/libipsec/pfkey.c | 2136 |
1 files changed, 0 insertions, 2136 deletions
diff --git a/freebsd/lib/libipsec/pfkey.c b/freebsd/lib/libipsec/pfkey.c deleted file mode 100644 index 87ef4113..00000000 --- a/freebsd/lib/libipsec/pfkey.c +++ /dev/null @@ -1,2136 +0,0 @@ -#include <machine/rtems-bsd-user-space.h> - -/* $KAME: pfkey.c,v 1.46 2003/08/26 03:37:06 itojun Exp $ */ - -/* - * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the project nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/types.h> -#include <sys/param.h> -#include <sys/socket.h> -#include <net/pfkeyv2.h> -#include <netipsec/key_var.h> -#include <netinet/in.h> -#include <netipsec/ipsec.h> - -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <errno.h> - -#include "ipsec_strerror.h" -#include "libpfkey.h" - -#define CALLOC(size, cast) (cast)calloc(1, (size)) - -static int findsupportedmap(int); -static int setsupportedmap(struct sadb_supported *); -static struct sadb_alg *findsupportedalg(u_int, u_int); -static int pfkey_send_x1(int, u_int, u_int, u_int, struct sockaddr *, - struct sockaddr *, u_int32_t, u_int32_t, u_int, caddr_t, - u_int, u_int, u_int, u_int, u_int, u_int32_t, u_int32_t, - u_int32_t, u_int32_t, u_int32_t); -static int pfkey_send_x2(int, u_int, u_int, u_int, - struct sockaddr *, struct sockaddr *, u_int32_t); -static int pfkey_send_x3(int, u_int, u_int); -static int pfkey_send_x4(int, u_int, struct sockaddr *, u_int, - struct sockaddr *, u_int, u_int, u_int64_t, u_int64_t, - char *, int, u_int32_t); -static int pfkey_send_x5(int, u_int, u_int32_t); - -static caddr_t pfkey_setsadbmsg(caddr_t, caddr_t, u_int, u_int, - u_int, u_int32_t, pid_t); -static caddr_t pfkey_setsadbsa(caddr_t, caddr_t, u_int32_t, u_int, - u_int, u_int, u_int32_t); -static caddr_t pfkey_setsadbaddr(caddr_t, caddr_t, u_int, - struct sockaddr *, u_int, u_int); -static caddr_t pfkey_setsadbkey(caddr_t, caddr_t, u_int, caddr_t, u_int); -static caddr_t pfkey_setsadblifetime(caddr_t, caddr_t, u_int, u_int32_t, - u_int32_t, u_int32_t, u_int32_t); -static caddr_t pfkey_setsadbxsa2(caddr_t, caddr_t, u_int32_t, u_int32_t); - -/* - * make and search supported algorithm structure. - */ -static struct sadb_supported *ipsec_supported[] = { NULL, NULL, NULL, NULL }; - -static int supported_map[] = { - SADB_SATYPE_AH, - SADB_SATYPE_ESP, - SADB_X_SATYPE_IPCOMP, - SADB_X_SATYPE_TCPSIGNATURE -}; - -static int -findsupportedmap(satype) - int satype; -{ - int i; - - for (i = 0; i < sizeof(supported_map)/sizeof(supported_map[0]); i++) - if (supported_map[i] == satype) - return i; - return -1; -} - -static struct sadb_alg * -findsupportedalg(satype, alg_id) - u_int satype, alg_id; -{ - int algno; - int tlen; - caddr_t p; - - /* validity check */ - algno = findsupportedmap(satype); - if (algno == -1) { - __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; - return NULL; - } - if (ipsec_supported[algno] == NULL) { - __ipsec_errcode = EIPSEC_DO_GET_SUPP_LIST; - return NULL; - } - - tlen = ipsec_supported[algno]->sadb_supported_len - - sizeof(struct sadb_supported); - p = (caddr_t)(ipsec_supported[algno] + 1); - while (tlen > 0) { - if (tlen < sizeof(struct sadb_alg)) { - /* invalid format */ - break; - } - if (((struct sadb_alg *)p)->sadb_alg_id == alg_id) - return (struct sadb_alg *)p; - - tlen -= sizeof(struct sadb_alg); - p += sizeof(struct sadb_alg); - } - - __ipsec_errcode = EIPSEC_NOT_SUPPORTED; - return NULL; -} - -static int -setsupportedmap(sup) - struct sadb_supported *sup; -{ - struct sadb_supported **ipsup; - - switch (sup->sadb_supported_exttype) { - case SADB_EXT_SUPPORTED_AUTH: - ipsup = &ipsec_supported[findsupportedmap(SADB_SATYPE_AH)]; - break; - case SADB_EXT_SUPPORTED_ENCRYPT: - ipsup = &ipsec_supported[findsupportedmap(SADB_SATYPE_ESP)]; - break; - default: - __ipsec_errcode = EIPSEC_INVAL_SATYPE; - return -1; - } - - if (*ipsup) - free(*ipsup); - - *ipsup = malloc(sup->sadb_supported_len); - if (!*ipsup) { - __ipsec_set_strerror(strerror(errno)); - return -1; - } - memcpy(*ipsup, sup, sup->sadb_supported_len); - - return 0; -} - -/* - * check key length against algorithm specified. - * This function is called with SADB_EXT_SUPPORTED_{AUTH,ENCRYPT} as the - * augument, and only calls to ipsec_check_keylen2(); - * keylen is the unit of bit. - * OUT: - * -1: invalid. - * 0: valid. - */ -int -ipsec_check_keylen(supported, alg_id, keylen) - u_int supported; - u_int alg_id; - u_int keylen; -{ - int satype; - - /* validity check */ - switch (supported) { - case SADB_EXT_SUPPORTED_AUTH: - satype = SADB_SATYPE_AH; - break; - case SADB_EXT_SUPPORTED_ENCRYPT: - satype = SADB_SATYPE_ESP; - break; - default: - __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; - return -1; - } - - return ipsec_check_keylen2(satype, alg_id, keylen); -} - -/* - * check key length against algorithm specified. - * satype is one of satype defined at pfkeyv2.h. - * keylen is the unit of bit. - * OUT: - * -1: invalid. - * 0: valid. - */ -int -ipsec_check_keylen2(satype, alg_id, keylen) - u_int satype; - u_int alg_id; - u_int keylen; -{ - struct sadb_alg *alg; - - alg = findsupportedalg(satype, alg_id); - if (!alg) - return -1; - - if (keylen < alg->sadb_alg_minbits || keylen > alg->sadb_alg_maxbits) { - __ipsec_errcode = EIPSEC_INVAL_KEYLEN; - return -1; - } - - __ipsec_errcode = EIPSEC_NO_ERROR; - return 0; -} - -/* - * get max/min key length against algorithm specified. - * satype is one of satype defined at pfkeyv2.h. - * keylen is the unit of bit. - * OUT: - * -1: invalid. - * 0: valid. - */ -int -ipsec_get_keylen(supported, alg_id, alg0) - u_int supported, alg_id; - struct sadb_alg *alg0; -{ - struct sadb_alg *alg; - u_int satype; - - /* validity check */ - if (!alg0) { - __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; - return -1; - } - - switch (supported) { - case SADB_EXT_SUPPORTED_AUTH: - satype = SADB_SATYPE_AH; - break; - case SADB_EXT_SUPPORTED_ENCRYPT: - satype = SADB_SATYPE_ESP; - break; - default: - __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; - return -1; - } - - alg = findsupportedalg(satype, alg_id); - if (!alg) - return -1; - - memcpy(alg0, alg, sizeof(*alg0)); - - __ipsec_errcode = EIPSEC_NO_ERROR; - return 0; -} - -/* - * set the rate for SOFT lifetime against HARD one. - * If rate is more than 100 or equal to zero, then set to 100. - */ -static u_int soft_lifetime_allocations_rate = PFKEY_SOFT_LIFETIME_RATE; -static u_int soft_lifetime_bytes_rate = PFKEY_SOFT_LIFETIME_RATE; -static u_int soft_lifetime_addtime_rate = PFKEY_SOFT_LIFETIME_RATE; -static u_int soft_lifetime_usetime_rate = PFKEY_SOFT_LIFETIME_RATE; - -u_int -pfkey_set_softrate(type, rate) - u_int type, rate; -{ - __ipsec_errcode = EIPSEC_NO_ERROR; - - if (rate > 100 || rate == 0) - rate = 100; - - switch (type) { - case SADB_X_LIFETIME_ALLOCATIONS: - soft_lifetime_allocations_rate = rate; - return 0; - case SADB_X_LIFETIME_BYTES: - soft_lifetime_bytes_rate = rate; - return 0; - case SADB_X_LIFETIME_ADDTIME: - soft_lifetime_addtime_rate = rate; - return 0; - case SADB_X_LIFETIME_USETIME: - soft_lifetime_usetime_rate = rate; - return 0; - } - - __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; - return 1; -} - -/* - * get current rate for SOFT lifetime against HARD one. - * ATTENTION: ~0 is returned if invalid type was passed. - */ -u_int -pfkey_get_softrate(type) - u_int type; -{ - switch (type) { - case SADB_X_LIFETIME_ALLOCATIONS: - return soft_lifetime_allocations_rate; - case SADB_X_LIFETIME_BYTES: - return soft_lifetime_bytes_rate; - case SADB_X_LIFETIME_ADDTIME: - return soft_lifetime_addtime_rate; - case SADB_X_LIFETIME_USETIME: - return soft_lifetime_usetime_rate; - } - - return ~0; -} - -/* - * sending SADB_GETSPI message to the kernel. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - */ -int -pfkey_send_getspi(so, satype, mode, src, dst, min, max, reqid, seq) - int so; - u_int satype, mode; - struct sockaddr *src, *dst; - u_int32_t min, max, reqid, seq; -{ - struct sadb_msg *newmsg; - caddr_t ep; - int len; - int need_spirange = 0; - caddr_t p; - int plen; - - /* validity check */ - if (src == NULL || dst == NULL) { - __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; - return -1; - } - if (src->sa_family != dst->sa_family) { - __ipsec_errcode = EIPSEC_FAMILY_MISMATCH; - return -1; - } - if (min > max || (min > 0 && min <= 255)) { - __ipsec_errcode = EIPSEC_INVAL_SPI; - return -1; - } - switch (src->sa_family) { - case AF_INET: - plen = sizeof(struct in_addr) << 3; - break; - case AF_INET6: - plen = sizeof(struct in6_addr) << 3; - break; - default: - __ipsec_errcode = EIPSEC_INVAL_FAMILY; - return -1; - } - - /* create new sadb_msg to send. */ - len = sizeof(struct sadb_msg) - + sizeof(struct sadb_x_sa2) - + sizeof(struct sadb_address) - + PFKEY_ALIGN8(src->sa_len) - + sizeof(struct sadb_address) - + PFKEY_ALIGN8(dst->sa_len); - - if (min > 255 && max < ~0) { - need_spirange++; - len += sizeof(struct sadb_spirange); - } - - if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) { - __ipsec_set_strerror(strerror(errno)); - return -1; - } - ep = ((caddr_t)newmsg) + len; - - p = pfkey_setsadbmsg((caddr_t)newmsg, ep, SADB_GETSPI, - len, satype, seq, getpid()); - if (!p) { - free(newmsg); - return -1; - } - - p = pfkey_setsadbxsa2(p, ep, mode, reqid); - if (!p) { - free(newmsg); - return -1; - } - - /* set sadb_address for source */ - p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, plen, - IPSEC_ULPROTO_ANY); - if (!p) { - free(newmsg); - return -1; - } - - /* set sadb_address for destination */ - p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, plen, - IPSEC_ULPROTO_ANY); - if (!p) { - free(newmsg); - return -1; - } - - /* proccessing spi range */ - if (need_spirange) { - struct sadb_spirange spirange; - - if (p + sizeof(spirange) > ep) { - free(newmsg); - return -1; - } - - memset(&spirange, 0, sizeof(spirange)); - spirange.sadb_spirange_len = PFKEY_UNIT64(sizeof(spirange)); - spirange.sadb_spirange_exttype = SADB_EXT_SPIRANGE; - spirange.sadb_spirange_min = min; - spirange.sadb_spirange_max = max; - - memcpy(p, &spirange, sizeof(spirange)); - - p += sizeof(spirange); - } - if (p != ep) { - free(newmsg); - return -1; - } - - /* send message */ - len = pfkey_send(so, newmsg, len); - free(newmsg); - - if (len < 0) - return -1; - - __ipsec_errcode = EIPSEC_NO_ERROR; - return len; -} - -/* - * sending SADB_UPDATE message to the kernel. - * The length of key material is a_keylen + e_keylen. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - */ -int -pfkey_send_update(so, satype, mode, src, dst, spi, reqid, wsize, - keymat, e_type, e_keylen, a_type, a_keylen, flags, - l_alloc, l_bytes, l_addtime, l_usetime, seq) - int so; - u_int satype, mode, wsize; - struct sockaddr *src, *dst; - u_int32_t spi, reqid; - caddr_t keymat; - u_int e_type, e_keylen, a_type, a_keylen, flags; - u_int32_t l_alloc; - u_int64_t l_bytes, l_addtime, l_usetime; - u_int32_t seq; -{ - int len; - if ((len = pfkey_send_x1(so, SADB_UPDATE, satype, mode, src, dst, spi, - reqid, wsize, - keymat, e_type, e_keylen, a_type, a_keylen, flags, - l_alloc, l_bytes, l_addtime, l_usetime, seq)) < 0) - return -1; - - return len; -} - -/* - * sending SADB_ADD message to the kernel. - * The length of key material is a_keylen + e_keylen. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - */ -int -pfkey_send_add(so, satype, mode, src, dst, spi, reqid, wsize, - keymat, e_type, e_keylen, a_type, a_keylen, flags, - l_alloc, l_bytes, l_addtime, l_usetime, seq) - int so; - u_int satype, mode, wsize; - struct sockaddr *src, *dst; - u_int32_t spi, reqid; - caddr_t keymat; - u_int e_type, e_keylen, a_type, a_keylen, flags; - u_int32_t l_alloc; - u_int64_t l_bytes, l_addtime, l_usetime; - u_int32_t seq; -{ - int len; - if ((len = pfkey_send_x1(so, SADB_ADD, satype, mode, src, dst, spi, - reqid, wsize, - keymat, e_type, e_keylen, a_type, a_keylen, flags, - l_alloc, l_bytes, l_addtime, l_usetime, seq)) < 0) - return -1; - - return len; -} - -/* - * sending SADB_DELETE message to the kernel. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - */ -int -pfkey_send_delete(so, satype, mode, src, dst, spi) - int so; - u_int satype, mode; - struct sockaddr *src, *dst; - u_int32_t spi; -{ - int len; - if ((len = pfkey_send_x2(so, SADB_DELETE, satype, mode, src, dst, spi)) < 0) - return -1; - - return len; -} - -/* - * sending SADB_DELETE without spi to the kernel. This is - * the "delete all" request (an extension also present in - * Solaris). - * - * OUT: - * positive: success and return length sent - * -1 : error occured, and set errno - */ -int -pfkey_send_delete_all(so, satype, mode, src, dst) - int so; - u_int satype, mode; - struct sockaddr *src, *dst; -{ - struct sadb_msg *newmsg; - int len; - caddr_t p; - int plen; - caddr_t ep; - - /* validity check */ - if (src == NULL || dst == NULL) { - __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; - return -1; - } - if (src->sa_family != dst->sa_family) { - __ipsec_errcode = EIPSEC_FAMILY_MISMATCH; - return -1; - } - switch (src->sa_family) { - case AF_INET: - plen = sizeof(struct in_addr) << 3; - break; - case AF_INET6: - plen = sizeof(struct in6_addr) << 3; - break; - default: - __ipsec_errcode = EIPSEC_INVAL_FAMILY; - return -1; - } - - /* create new sadb_msg to reply. */ - len = sizeof(struct sadb_msg) - + sizeof(struct sadb_address) - + PFKEY_ALIGN8(src->sa_len) - + sizeof(struct sadb_address) - + PFKEY_ALIGN8(dst->sa_len); - - if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) { - __ipsec_set_strerror(strerror(errno)); - return -1; - } - ep = ((caddr_t)newmsg) + len; - - p = pfkey_setsadbmsg((caddr_t)newmsg, ep, SADB_DELETE, len, satype, 0, - getpid()); - if (!p) { - free(newmsg); - return -1; - } - p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, plen, - IPSEC_ULPROTO_ANY); - if (!p) { - free(newmsg); - return -1; - } - p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, plen, - IPSEC_ULPROTO_ANY); - if (!p || p != ep) { - free(newmsg); - return -1; - } - - /* send message */ - len = pfkey_send(so, newmsg, len); - free(newmsg); - - if (len < 0) - return -1; - - __ipsec_errcode = EIPSEC_NO_ERROR; - return len; -} - -/* - * sending SADB_GET message to the kernel. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - */ -int -pfkey_send_get(so, satype, mode, src, dst, spi) - int so; - u_int satype, mode; - struct sockaddr *src, *dst; - u_int32_t spi; -{ - int len; - if ((len = pfkey_send_x2(so, SADB_GET, satype, mode, src, dst, spi)) < 0) - return -1; - - return len; -} - -/* - * sending SADB_REGISTER message to the kernel. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - */ -int -pfkey_send_register(so, satype) - int so; - u_int satype; -{ - int len, algno; - - if (satype == SADB_SATYPE_UNSPEC) { - for (algno = 0; - algno < sizeof(supported_map)/sizeof(supported_map[0]); - algno++) { - if (ipsec_supported[algno]) { - free(ipsec_supported[algno]); - ipsec_supported[algno] = NULL; - } - } - } else { - algno = findsupportedmap(satype); - if (algno == -1) { - __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; - return -1; - } - - if (ipsec_supported[algno]) { - free(ipsec_supported[algno]); - ipsec_supported[algno] = NULL; - } - } - - if ((len = pfkey_send_x3(so, SADB_REGISTER, satype)) < 0) - return -1; - - return len; -} - -/* - * receiving SADB_REGISTER message from the kernel, and copy buffer for - * sadb_supported returned into ipsec_supported. - * OUT: - * 0: success and return length sent. - * -1: error occured, and set errno. - */ -int -pfkey_recv_register(so) - int so; -{ - pid_t pid = getpid(); - struct sadb_msg *newmsg; - int error = -1; - - /* receive message */ - for (;;) { - if ((newmsg = pfkey_recv(so)) == NULL) - return -1; - if (newmsg->sadb_msg_type == SADB_REGISTER && - newmsg->sadb_msg_pid == pid) - break; - free(newmsg); - } - - /* check and fix */ - newmsg->sadb_msg_len = PFKEY_UNUNIT64(newmsg->sadb_msg_len); - - error = pfkey_set_supported(newmsg, newmsg->sadb_msg_len); - free(newmsg); - - if (error == 0) - __ipsec_errcode = EIPSEC_NO_ERROR; - - return error; -} - -/* - * receiving SADB_REGISTER message from the kernel, and copy buffer for - * sadb_supported returned into ipsec_supported. - * NOTE: sadb_msg_len must be host order. - * IN: - * tlen: msg length, it's to makeing sure. - * OUT: - * 0: success and return length sent. - * -1: error occured, and set errno. - */ -int -pfkey_set_supported(msg, tlen) - struct sadb_msg *msg; - int tlen; -{ - struct sadb_supported *sup; - caddr_t p; - caddr_t ep; - - /* validity */ - if (msg->sadb_msg_len != tlen) { - __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; - return -1; - } - - p = (caddr_t)msg; - ep = p + tlen; - - p += sizeof(struct sadb_msg); - - while (p < ep) { - sup = (struct sadb_supported *)p; - if (ep < p + sizeof(*sup) || - PFKEY_EXTLEN(sup) < sizeof(*sup) || - ep < p + sup->sadb_supported_len) { - /* invalid format */ - break; - } - - switch (sup->sadb_supported_exttype) { - case SADB_EXT_SUPPORTED_AUTH: - case SADB_EXT_SUPPORTED_ENCRYPT: - break; - default: - __ipsec_errcode = EIPSEC_INVAL_SATYPE; - return -1; - } - - /* fixed length */ - sup->sadb_supported_len = PFKEY_EXTLEN(sup); - - /* set supported map */ - if (setsupportedmap(sup) != 0) - return -1; - - p += sup->sadb_supported_len; - } - - if (p != ep) { - __ipsec_errcode = EIPSEC_INVAL_SATYPE; - return -1; - } - - __ipsec_errcode = EIPSEC_NO_ERROR; - - return 0; -} - -/* - * sending SADB_FLUSH message to the kernel. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - */ -int -pfkey_send_flush(so, satype) - int so; - u_int satype; -{ - int len; - - if ((len = pfkey_send_x3(so, SADB_FLUSH, satype)) < 0) - return -1; - - return len; -} - -/* - * sending SADB_DUMP message to the kernel. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - */ -int -pfkey_send_dump(so, satype) - int so; - u_int satype; -{ - int len; - - if ((len = pfkey_send_x3(so, SADB_DUMP, satype)) < 0) - return -1; - - return len; -} - -/* - * sending SADB_X_PROMISC message to the kernel. - * NOTE that this function handles promisc mode toggle only. - * IN: - * flag: set promisc off if zero, set promisc on if non-zero. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - * 0 : error occured, and set errno. - * others: a pointer to new allocated buffer in which supported - * algorithms is. - */ -int -pfkey_send_promisc_toggle(so, flag) - int so; - int flag; -{ - int len; - - if ((len = pfkey_send_x3(so, SADB_X_PROMISC, (flag ? 1 : 0))) < 0) - return -1; - - return len; -} - -/* - * sending SADB_X_SPDADD message to the kernel. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - */ -int -pfkey_send_spdadd(so, src, prefs, dst, prefd, proto, policy, policylen, seq) - int so; - struct sockaddr *src, *dst; - u_int prefs, prefd, proto; - caddr_t policy; - int policylen; - u_int32_t seq; -{ - int len; - - if ((len = pfkey_send_x4(so, SADB_X_SPDADD, - src, prefs, dst, prefd, proto, - 0, 0, - policy, policylen, seq)) < 0) - return -1; - - return len; -} - -/* - * sending SADB_X_SPDADD message to the kernel. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - */ -int -pfkey_send_spdadd2(so, src, prefs, dst, prefd, proto, ltime, vtime, - policy, policylen, seq) - int so; - struct sockaddr *src, *dst; - u_int prefs, prefd, proto; - u_int64_t ltime, vtime; - caddr_t policy; - int policylen; - u_int32_t seq; -{ - int len; - - if ((len = pfkey_send_x4(so, SADB_X_SPDADD, - src, prefs, dst, prefd, proto, - ltime, vtime, - policy, policylen, seq)) < 0) - return -1; - - return len; -} - -/* - * sending SADB_X_SPDUPDATE message to the kernel. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - */ -int -pfkey_send_spdupdate(so, src, prefs, dst, prefd, proto, policy, policylen, seq) - int so; - struct sockaddr *src, *dst; - u_int prefs, prefd, proto; - caddr_t policy; - int policylen; - u_int32_t seq; -{ - int len; - - if ((len = pfkey_send_x4(so, SADB_X_SPDUPDATE, - src, prefs, dst, prefd, proto, - 0, 0, - policy, policylen, seq)) < 0) - return -1; - - return len; -} - -/* - * sending SADB_X_SPDUPDATE message to the kernel. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - */ -int -pfkey_send_spdupdate2(so, src, prefs, dst, prefd, proto, ltime, vtime, - policy, policylen, seq) - int so; - struct sockaddr *src, *dst; - u_int prefs, prefd, proto; - u_int64_t ltime, vtime; - caddr_t policy; - int policylen; - u_int32_t seq; -{ - int len; - - if ((len = pfkey_send_x4(so, SADB_X_SPDUPDATE, - src, prefs, dst, prefd, proto, - ltime, vtime, - policy, policylen, seq)) < 0) - return -1; - - return len; -} - -/* - * sending SADB_X_SPDDELETE message to the kernel. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - */ -int -pfkey_send_spddelete(so, src, prefs, dst, prefd, proto, policy, policylen, seq) - int so; - struct sockaddr *src, *dst; - u_int prefs, prefd, proto; - caddr_t policy; - int policylen; - u_int32_t seq; -{ - int len; - - if (policylen != sizeof(struct sadb_x_policy)) { - __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; - return -1; - } - - if ((len = pfkey_send_x4(so, SADB_X_SPDDELETE, - src, prefs, dst, prefd, proto, - 0, 0, - policy, policylen, seq)) < 0) - return -1; - - return len; -} - -/* - * sending SADB_X_SPDDELETE message to the kernel. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - */ -int -pfkey_send_spddelete2(so, spid) - int so; - u_int32_t spid; -{ - int len; - - if ((len = pfkey_send_x5(so, SADB_X_SPDDELETE2, spid)) < 0) - return -1; - - return len; -} - -/* - * sending SADB_X_SPDGET message to the kernel. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - */ -int -pfkey_send_spdget(so, spid) - int so; - u_int32_t spid; -{ - int len; - - if ((len = pfkey_send_x5(so, SADB_X_SPDGET, spid)) < 0) - return -1; - - return len; -} - -/* - * sending SADB_X_SPDSETIDX message to the kernel. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - */ -int -pfkey_send_spdsetidx(so, src, prefs, dst, prefd, proto, policy, policylen, seq) - int so; - struct sockaddr *src, *dst; - u_int prefs, prefd, proto; - caddr_t policy; - int policylen; - u_int32_t seq; -{ - int len; - - if (policylen != sizeof(struct sadb_x_policy)) { - __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; - return -1; - } - - if ((len = pfkey_send_x4(so, SADB_X_SPDSETIDX, - src, prefs, dst, prefd, proto, - 0, 0, - policy, policylen, seq)) < 0) - return -1; - - return len; -} - -/* - * sending SADB_SPDFLUSH message to the kernel. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - */ -int -pfkey_send_spdflush(so) - int so; -{ - int len; - - if ((len = pfkey_send_x3(so, SADB_X_SPDFLUSH, SADB_SATYPE_UNSPEC)) < 0) - return -1; - - return len; -} - -/* - * sending SADB_SPDDUMP message to the kernel. - * OUT: - * positive: success and return length sent. - * -1 : error occured, and set errno. - */ -int -pfkey_send_spddump(so) - int so; -{ - int len; - - if ((len = pfkey_send_x3(so, SADB_X_SPDDUMP, SADB_SATYPE_UNSPEC)) < 0) - return -1; - - return len; -} - -/* sending SADB_ADD or SADB_UPDATE message to the kernel */ -static int -pfkey_send_x1(so, type, satype, mode, src, dst, spi, reqid, wsize, - keymat, e_type, e_keylen, a_type, a_keylen, flags, - l_alloc, l_bytes, l_addtime, l_usetime, seq) - int so; - u_int type, satype, mode; - struct sockaddr *src, *dst; - u_int32_t spi, reqid; - u_int wsize; - caddr_t keymat; - u_int e_type, e_keylen, a_type, a_keylen, flags; - u_int32_t l_alloc, l_bytes, l_addtime, l_usetime, seq; -{ - struct sadb_msg *newmsg; - int len; - caddr_t p; - int plen; - caddr_t ep; - - /* validity check */ - if (src == NULL || dst == NULL) { - __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; - return -1; - } - if (src->sa_family != dst->sa_family) { - __ipsec_errcode = EIPSEC_FAMILY_MISMATCH; - return -1; - } - switch (src->sa_family) { - case AF_INET: - plen = sizeof(struct in_addr) << 3; - break; - case AF_INET6: - plen = sizeof(struct in6_addr) << 3; - break; - default: - __ipsec_errcode = EIPSEC_INVAL_FAMILY; - return -1; - } - - switch (satype) { - case SADB_SATYPE_ESP: - if (e_type == SADB_EALG_NONE) { - __ipsec_errcode = EIPSEC_NO_ALGS; - return -1; - } - break; - case SADB_SATYPE_AH: - if (e_type != SADB_EALG_NONE) { - __ipsec_errcode = EIPSEC_INVAL_ALGS; - return -1; - } - if (a_type == SADB_AALG_NONE) { - __ipsec_errcode = EIPSEC_NO_ALGS; - return -1; - } - break; - case SADB_X_SATYPE_IPCOMP: - if (e_type == SADB_X_CALG_NONE) { - __ipsec_errcode = EIPSEC_INVAL_ALGS; - return -1; - } - if (a_type != SADB_AALG_NONE) { - __ipsec_errcode = EIPSEC_NO_ALGS; - return -1; - } - break; - case SADB_X_SATYPE_TCPSIGNATURE: - if (e_type != SADB_EALG_NONE) { - __ipsec_errcode = EIPSEC_INVAL_ALGS; - return -1; - } - if (a_type != SADB_X_AALG_TCP_MD5) { - __ipsec_errcode = EIPSEC_INVAL_ALGS; - return -1; - } - break; - default: - __ipsec_errcode = EIPSEC_INVAL_SATYPE; - return -1; - } - - /* create new sadb_msg to reply. */ - len = sizeof(struct sadb_msg) - + sizeof(struct sadb_sa) - + sizeof(struct sadb_x_sa2) - + sizeof(struct sadb_address) - + PFKEY_ALIGN8(src->sa_len) - + sizeof(struct sadb_address) - + PFKEY_ALIGN8(dst->sa_len) - + sizeof(struct sadb_lifetime) - + sizeof(struct sadb_lifetime); - - if (e_type != SADB_EALG_NONE) - len += (sizeof(struct sadb_key) + PFKEY_ALIGN8(e_keylen)); - if (a_type != SADB_AALG_NONE) - len += (sizeof(struct sadb_key) + PFKEY_ALIGN8(a_keylen)); - - if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) { - __ipsec_set_strerror(strerror(errno)); - return -1; - } - ep = ((caddr_t)newmsg) + len; - - p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len, - satype, seq, getpid()); - if (!p) { - free(newmsg); - return -1; - } - p = pfkey_setsadbsa(p, ep, spi, wsize, a_type, e_type, flags); - if (!p) { - free(newmsg); - return -1; - } - p = pfkey_setsadbxsa2(p, ep, mode, reqid); - if (!p) { - free(newmsg); - return -1; - } - p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, plen, - IPSEC_ULPROTO_ANY); - if (!p) { - free(newmsg); - return -1; - } - p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, plen, - IPSEC_ULPROTO_ANY); - if (!p) { - free(newmsg); - return -1; - } - - if (e_type != SADB_EALG_NONE) { - p = pfkey_setsadbkey(p, ep, SADB_EXT_KEY_ENCRYPT, - keymat, e_keylen); - if (!p) { - free(newmsg); - return -1; - } - } - if (a_type != SADB_AALG_NONE) { - p = pfkey_setsadbkey(p, ep, SADB_EXT_KEY_AUTH, - keymat + e_keylen, a_keylen); - if (!p) { - free(newmsg); - return -1; - } - } - - /* set sadb_lifetime for destination */ - p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_HARD, - l_alloc, l_bytes, l_addtime, l_usetime); - if (!p) { - free(newmsg); - return -1; - } - p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_SOFT, - l_alloc, l_bytes, l_addtime, l_usetime); - if (!p || p != ep) { - free(newmsg); - return -1; - } - - /* send message */ - len = pfkey_send(so, newmsg, len); - free(newmsg); - - if (len < 0) - return -1; - - __ipsec_errcode = EIPSEC_NO_ERROR; - return len; -} - -/* sending SADB_DELETE or SADB_GET message to the kernel */ -static int -pfkey_send_x2(so, type, satype, mode, src, dst, spi) - int so; - u_int type, satype, mode; - struct sockaddr *src, *dst; - u_int32_t spi; -{ - struct sadb_msg *newmsg; - int len; - caddr_t p; - int plen; - caddr_t ep; - - /* validity check */ - if (src == NULL || dst == NULL) { - __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; - return -1; - } - if (src->sa_family != dst->sa_family) { - __ipsec_errcode = EIPSEC_FAMILY_MISMATCH; - return -1; - } - switch (src->sa_family) { - case AF_INET: - plen = sizeof(struct in_addr) << 3; - break; - case AF_INET6: - plen = sizeof(struct in6_addr) << 3; - break; - default: - __ipsec_errcode = EIPSEC_INVAL_FAMILY; - return -1; - } - - /* create new sadb_msg to reply. */ - len = sizeof(struct sadb_msg) - + sizeof(struct sadb_sa) - + sizeof(struct sadb_address) - + PFKEY_ALIGN8(src->sa_len) - + sizeof(struct sadb_address) - + PFKEY_ALIGN8(dst->sa_len); - - if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) { - __ipsec_set_strerror(strerror(errno)); - return -1; - } - ep = ((caddr_t)newmsg) + len; - - p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len, satype, 0, - getpid()); - if (!p) { - free(newmsg); - return -1; - } - p = pfkey_setsadbsa(p, ep, spi, 0, 0, 0, 0); - if (!p) { - free(newmsg); - return -1; - } - p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, plen, - IPSEC_ULPROTO_ANY); - if (!p) { - free(newmsg); - return -1; - } - p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, plen, - IPSEC_ULPROTO_ANY); - if (!p || p != ep) { - free(newmsg); - return -1; - } - - /* send message */ - len = pfkey_send(so, newmsg, len); - free(newmsg); - - if (len < 0) - return -1; - - __ipsec_errcode = EIPSEC_NO_ERROR; - return len; -} - -/* - * sending SADB_REGISTER, SADB_FLUSH, SADB_DUMP or SADB_X_PROMISC message - * to the kernel - */ -static int -pfkey_send_x3(so, type, satype) - int so; - u_int type, satype; -{ - struct sadb_msg *newmsg; - int len; - caddr_t p; - caddr_t ep; - - /* validity check */ - switch (type) { - case SADB_X_PROMISC: - if (satype != 0 && satype != 1) { - __ipsec_errcode = EIPSEC_INVAL_SATYPE; - return -1; - } - break; - default: - switch (satype) { - case SADB_SATYPE_UNSPEC: - case SADB_SATYPE_AH: - case SADB_SATYPE_ESP: - case SADB_X_SATYPE_IPCOMP: - case SADB_X_SATYPE_TCPSIGNATURE: - break; - default: - __ipsec_errcode = EIPSEC_INVAL_SATYPE; - return -1; - } - } - - /* create new sadb_msg to send. */ - len = sizeof(struct sadb_msg); - - if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) { - __ipsec_set_strerror(strerror(errno)); - return -1; - } - ep = ((caddr_t)newmsg) + len; - - p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len, satype, 0, - getpid()); - if (!p || p != ep) { - free(newmsg); - return -1; - } - - /* send message */ - len = pfkey_send(so, newmsg, len); - free(newmsg); - - if (len < 0) - return -1; - - __ipsec_errcode = EIPSEC_NO_ERROR; - return len; -} - -/* sending SADB_X_SPDADD message to the kernel */ -static int -pfkey_send_x4(so, type, src, prefs, dst, prefd, proto, - ltime, vtime, policy, policylen, seq) - int so; - struct sockaddr *src, *dst; - u_int type, prefs, prefd, proto; - u_int64_t ltime, vtime; - char *policy; - int policylen; - u_int32_t seq; -{ - struct sadb_msg *newmsg; - int len; - caddr_t p; - int plen; - caddr_t ep; - - /* validity check */ - if (src == NULL || dst == NULL) { - __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; - return -1; - } - if (src->sa_family != dst->sa_family) { - __ipsec_errcode = EIPSEC_FAMILY_MISMATCH; - return -1; - } - - switch (src->sa_family) { - case AF_INET: - plen = sizeof(struct in_addr) << 3; - break; - case AF_INET6: - plen = sizeof(struct in6_addr) << 3; - break; - default: - __ipsec_errcode = EIPSEC_INVAL_FAMILY; - return -1; - } - if (prefs > plen || prefd > plen) { - __ipsec_errcode = EIPSEC_INVAL_PREFIXLEN; - return -1; - } - - /* create new sadb_msg to reply. */ - len = sizeof(struct sadb_msg) - + sizeof(struct sadb_address) - + PFKEY_ALIGN8(src->sa_len) - + sizeof(struct sadb_address) - + PFKEY_ALIGN8(src->sa_len) - + sizeof(struct sadb_lifetime) - + policylen; - - if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) { - __ipsec_set_strerror(strerror(errno)); - return -1; - } - ep = ((caddr_t)newmsg) + len; - - p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len, - SADB_SATYPE_UNSPEC, seq, getpid()); - if (!p) { - free(newmsg); - return -1; - } - p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, prefs, proto); - if (!p) { - free(newmsg); - return -1; - } - p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, prefd, proto); - if (!p) { - free(newmsg); - return -1; - } - p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_HARD, - 0, 0, ltime, vtime); - if (!p || p + policylen != ep) { - free(newmsg); - return -1; - } - memcpy(p, policy, policylen); - - /* send message */ - len = pfkey_send(so, newmsg, len); - free(newmsg); - - if (len < 0) - return -1; - - __ipsec_errcode = EIPSEC_NO_ERROR; - return len; -} - -/* sending SADB_X_SPDGET or SADB_X_SPDDELETE message to the kernel */ -static int -pfkey_send_x5(so, type, spid) - int so; - u_int type; - u_int32_t spid; -{ - struct sadb_msg *newmsg; - struct sadb_x_policy xpl; - int len; - caddr_t p; - caddr_t ep; - - /* create new sadb_msg to reply. */ - len = sizeof(struct sadb_msg) - + sizeof(xpl); - - if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) { - __ipsec_set_strerror(strerror(errno)); - return -1; - } - ep = ((caddr_t)newmsg) + len; - - p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len, - SADB_SATYPE_UNSPEC, 0, getpid()); - if (!p) { - free(newmsg); - return -1; - } - - if (p + sizeof(xpl) != ep) { - free(newmsg); - return -1; - } - memset(&xpl, 0, sizeof(xpl)); - xpl.sadb_x_policy_len = PFKEY_UNIT64(sizeof(xpl)); - xpl.sadb_x_policy_exttype = SADB_X_EXT_POLICY; - xpl.sadb_x_policy_id = spid; - memcpy(p, &xpl, sizeof(xpl)); - - /* send message */ - len = pfkey_send(so, newmsg, len); - free(newmsg); - - if (len < 0) - return -1; - - __ipsec_errcode = EIPSEC_NO_ERROR; - return len; -} - -/* - * open a socket. - * OUT: - * -1: fail. - * others : success and return value of socket. - */ -int -pfkey_open() -{ - int so; - const int bufsiz = 128 * 1024; /*is 128K enough?*/ - - if ((so = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) < 0) { - __ipsec_set_strerror(strerror(errno)); - return -1; - } - - /* - * This is a temporary workaround for KAME PR 154. - * Don't really care even if it fails. - */ - (void)setsockopt(so, SOL_SOCKET, SO_SNDBUF, &bufsiz, sizeof(bufsiz)); - (void)setsockopt(so, SOL_SOCKET, SO_RCVBUF, &bufsiz, sizeof(bufsiz)); - - __ipsec_errcode = EIPSEC_NO_ERROR; - return so; -} - -/* - * close a socket. - * OUT: - * 0: success. - * -1: fail. - */ -void -pfkey_close(so) - int so; -{ - (void)close(so); - - __ipsec_errcode = EIPSEC_NO_ERROR; - return; -} - -/* - * receive sadb_msg data, and return pointer to new buffer allocated. - * Must free this buffer later. - * OUT: - * NULL : error occured. - * others : a pointer to sadb_msg structure. - * - * XXX should be rewritten to pass length explicitly - */ -struct sadb_msg * -pfkey_recv(so) - int so; -{ - struct sadb_msg buf, *newmsg; - int len, reallen; - - while ((len = recv(so, (caddr_t)&buf, sizeof(buf), MSG_PEEK)) < 0) { - if (errno == EINTR) - continue; - __ipsec_set_strerror(strerror(errno)); - return NULL; - } - - if (len < sizeof(buf)) { - recv(so, (caddr_t)&buf, sizeof(buf), 0); - __ipsec_errcode = EIPSEC_MAX; - return NULL; - } - - /* read real message */ - reallen = PFKEY_UNUNIT64(buf.sadb_msg_len); - if ((newmsg = CALLOC(reallen, struct sadb_msg *)) == NULL) { - __ipsec_set_strerror(strerror(errno)); - return NULL; - } - - while ((len = recv(so, (caddr_t)newmsg, reallen, 0)) < 0) { - if (errno == EINTR) - continue; - __ipsec_set_strerror(strerror(errno)); - free(newmsg); - return NULL; - } - - if (len != reallen) { - __ipsec_errcode = EIPSEC_SYSTEM_ERROR; - free(newmsg); - return NULL; - } - - /* don't trust what the kernel says, validate! */ - if (PFKEY_UNUNIT64(newmsg->sadb_msg_len) != len) { - __ipsec_errcode = EIPSEC_SYSTEM_ERROR; - free(newmsg); - return NULL; - } - - __ipsec_errcode = EIPSEC_NO_ERROR; - return newmsg; -} - -/* - * send message to a socket. - * OUT: - * others: success and return length sent. - * -1 : fail. - */ -int -pfkey_send(so, msg, len) - int so; - struct sadb_msg *msg; - int len; -{ - if ((len = send(so, (caddr_t)msg, len, 0)) < 0) { - __ipsec_set_strerror(strerror(errno)); - return -1; - } - - __ipsec_errcode = EIPSEC_NO_ERROR; - return len; -} - -/* - * %%% Utilities - * NOTE: These functions are derived from netkey/key.c in KAME. - */ -/* - * set the pointer to each header in this message buffer. - * IN: msg: pointer to message buffer. - * mhp: pointer to the buffer initialized like below: - * caddr_t mhp[SADB_EXT_MAX + 1]; - * OUT: -1: invalid. - * 0: valid. - * - * XXX should be rewritten to obtain length explicitly - */ -int -pfkey_align(msg, mhp) - struct sadb_msg *msg; - caddr_t *mhp; -{ - struct sadb_ext *ext; - int i; - caddr_t p; - caddr_t ep; /* XXX should be passed from upper layer */ - - /* validity check */ - if (msg == NULL || mhp == NULL) { - __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; - return -1; - } - - /* initialize */ - for (i = 0; i < SADB_EXT_MAX + 1; i++) - mhp[i] = NULL; - - mhp[0] = (caddr_t)msg; - - /* initialize */ - p = (caddr_t) msg; - ep = p + PFKEY_UNUNIT64(msg->sadb_msg_len); - - /* skip base header */ - p += sizeof(struct sadb_msg); - - while (p < ep) { - ext = (struct sadb_ext *)p; - if (ep < p + sizeof(*ext) || PFKEY_EXTLEN(ext) < sizeof(*ext) || - ep < p + PFKEY_EXTLEN(ext)) { - /* invalid format */ - break; - } - - /* duplicate check */ - /* XXX Are there duplication either KEY_AUTH or KEY_ENCRYPT ?*/ - if (mhp[ext->sadb_ext_type] != NULL) { - __ipsec_errcode = EIPSEC_INVAL_EXTTYPE; - return -1; - } - - /* set pointer */ - switch (ext->sadb_ext_type) { - case SADB_EXT_SA: - case SADB_EXT_LIFETIME_CURRENT: - case SADB_EXT_LIFETIME_HARD: - case SADB_EXT_LIFETIME_SOFT: - case SADB_EXT_ADDRESS_SRC: - case SADB_EXT_ADDRESS_DST: - case SADB_EXT_ADDRESS_PROXY: - case SADB_EXT_KEY_AUTH: - /* XXX should to be check weak keys. */ - case SADB_EXT_KEY_ENCRYPT: - /* XXX should to be check weak keys. */ - case SADB_EXT_IDENTITY_SRC: - case SADB_EXT_IDENTITY_DST: - case SADB_EXT_SENSITIVITY: - case SADB_EXT_PROPOSAL: - case SADB_EXT_SUPPORTED_AUTH: - case SADB_EXT_SUPPORTED_ENCRYPT: - case SADB_EXT_SPIRANGE: - case SADB_X_EXT_POLICY: - case SADB_X_EXT_SA2: - case SADB_X_EXT_NAT_T_TYPE: - case SADB_X_EXT_NAT_T_SPORT: - case SADB_X_EXT_NAT_T_DPORT: - case SADB_X_EXT_NAT_T_OAI: - case SADB_X_EXT_NAT_T_OAR: - case SADB_X_EXT_NAT_T_FRAG: - case SADB_X_EXT_SA_REPLAY: - case SADB_X_EXT_NEW_ADDRESS_SRC: - case SADB_X_EXT_NEW_ADDRESS_DST: - mhp[ext->sadb_ext_type] = (caddr_t)ext; - break; - default: - __ipsec_errcode = EIPSEC_INVAL_EXTTYPE; - return -1; - } - - p += PFKEY_EXTLEN(ext); - } - - if (p != ep) { - __ipsec_errcode = EIPSEC_INVAL_SADBMSG; - return -1; - } - - __ipsec_errcode = EIPSEC_NO_ERROR; - return 0; -} - -/* - * check basic usage for sadb_msg, - * NOTE: This routine is derived from netkey/key.c in KAME. - * IN: msg: pointer to message buffer. - * mhp: pointer to the buffer initialized like below: - * - * caddr_t mhp[SADB_EXT_MAX + 1]; - * - * OUT: -1: invalid. - * 0: valid. - */ -int -pfkey_check(mhp) - caddr_t *mhp; -{ - struct sadb_msg *msg; - - /* validity check */ - if (mhp == NULL || mhp[0] == NULL) { - __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; - return -1; - } - - msg = (struct sadb_msg *)mhp[0]; - - /* check version */ - if (msg->sadb_msg_version != PF_KEY_V2) { - __ipsec_errcode = EIPSEC_INVAL_VERSION; - return -1; - } - - /* check type */ - if (msg->sadb_msg_type > SADB_MAX) { - __ipsec_errcode = EIPSEC_INVAL_MSGTYPE; - return -1; - } - - /* check SA type */ - switch (msg->sadb_msg_satype) { - case SADB_SATYPE_UNSPEC: - switch (msg->sadb_msg_type) { - case SADB_GETSPI: - case SADB_UPDATE: - case SADB_ADD: - case SADB_DELETE: - case SADB_GET: - case SADB_ACQUIRE: - case SADB_EXPIRE: - __ipsec_errcode = EIPSEC_INVAL_SATYPE; - return -1; - } - break; - case SADB_SATYPE_ESP: - case SADB_SATYPE_AH: - case SADB_X_SATYPE_IPCOMP: - case SADB_X_SATYPE_TCPSIGNATURE: - switch (msg->sadb_msg_type) { - case SADB_X_SPDADD: - case SADB_X_SPDDELETE: - case SADB_X_SPDGET: - case SADB_X_SPDDUMP: - case SADB_X_SPDFLUSH: - __ipsec_errcode = EIPSEC_INVAL_SATYPE; - return -1; - } - break; - case SADB_SATYPE_RSVP: - case SADB_SATYPE_OSPFV2: - case SADB_SATYPE_RIPV2: - case SADB_SATYPE_MIP: - __ipsec_errcode = EIPSEC_NOT_SUPPORTED; - return -1; - case 1: /* XXX: What does it do ? */ - if (msg->sadb_msg_type == SADB_X_PROMISC) - break; - /*FALLTHROUGH*/ - default: - __ipsec_errcode = EIPSEC_INVAL_SATYPE; - return -1; - } - - /* check field of upper layer protocol and address family */ - if (mhp[SADB_EXT_ADDRESS_SRC] != NULL - && mhp[SADB_EXT_ADDRESS_DST] != NULL) { - struct sadb_address *src0, *dst0; - - src0 = (struct sadb_address *)(mhp[SADB_EXT_ADDRESS_SRC]); - dst0 = (struct sadb_address *)(mhp[SADB_EXT_ADDRESS_DST]); - - if (src0->sadb_address_proto != dst0->sadb_address_proto) { - __ipsec_errcode = EIPSEC_PROTO_MISMATCH; - return -1; - } - - if (PFKEY_ADDR_SADDR(src0)->sa_family - != PFKEY_ADDR_SADDR(dst0)->sa_family) { - __ipsec_errcode = EIPSEC_FAMILY_MISMATCH; - return -1; - } - - switch (PFKEY_ADDR_SADDR(src0)->sa_family) { - case AF_INET: - case AF_INET6: - break; - default: - __ipsec_errcode = EIPSEC_INVAL_FAMILY; - return -1; - } - - /* - * prefixlen == 0 is valid because there must be the case - * all addresses are matched. - */ - } - - __ipsec_errcode = EIPSEC_NO_ERROR; - return 0; -} - -/* - * set data into sadb_msg. - * `buf' must has been allocated sufficiently. - */ -static caddr_t -pfkey_setsadbmsg(buf, lim, type, tlen, satype, seq, pid) - caddr_t buf; - caddr_t lim; - u_int type, satype; - u_int tlen; - u_int32_t seq; - pid_t pid; -{ - struct sadb_msg *p; - u_int len; - - p = (struct sadb_msg *)buf; - len = sizeof(struct sadb_msg); - - if (buf + len > lim) - return NULL; - - memset(p, 0, len); - p->sadb_msg_version = PF_KEY_V2; - p->sadb_msg_type = type; - p->sadb_msg_errno = 0; - p->sadb_msg_satype = satype; - p->sadb_msg_len = PFKEY_UNIT64(tlen); - p->sadb_msg_reserved = 0; - p->sadb_msg_seq = seq; - p->sadb_msg_pid = (u_int32_t)pid; - - return(buf + len); -} - -/* - * copy secasvar data into sadb_address. - * `buf' must has been allocated sufficiently. - */ -static caddr_t -pfkey_setsadbsa(buf, lim, spi, wsize, auth, enc, flags) - caddr_t buf; - caddr_t lim; - u_int32_t spi, flags; - u_int wsize, auth, enc; -{ - struct sadb_sa *p; - u_int len; - - p = (struct sadb_sa *)buf; - len = sizeof(struct sadb_sa); - - if (buf + len > lim) - return NULL; - - memset(p, 0, len); - p->sadb_sa_len = PFKEY_UNIT64(len); - p->sadb_sa_exttype = SADB_EXT_SA; - p->sadb_sa_spi = spi; - p->sadb_sa_replay = wsize; - p->sadb_sa_state = SADB_SASTATE_LARVAL; - p->sadb_sa_auth = auth; - p->sadb_sa_encrypt = enc; - p->sadb_sa_flags = flags; - - return(buf + len); -} - -/* - * set data into sadb_address. - * `buf' must has been allocated sufficiently. - * prefixlen is in bits. - */ -static caddr_t -pfkey_setsadbaddr(buf, lim, exttype, saddr, prefixlen, ul_proto) - caddr_t buf; - caddr_t lim; - u_int exttype; - struct sockaddr *saddr; - u_int prefixlen; - u_int ul_proto; -{ - struct sadb_address *p; - u_int len; - - p = (struct sadb_address *)buf; - len = sizeof(struct sadb_address) + PFKEY_ALIGN8(saddr->sa_len); - - if (buf + len > lim) - return NULL; - - memset(p, 0, len); - p->sadb_address_len = PFKEY_UNIT64(len); - p->sadb_address_exttype = exttype & 0xffff; - p->sadb_address_proto = ul_proto & 0xff; - p->sadb_address_prefixlen = prefixlen; - p->sadb_address_reserved = 0; - - memcpy(p + 1, saddr, saddr->sa_len); - - return(buf + len); -} - -/* - * set sadb_key structure after clearing buffer with zero. - * OUT: the pointer of buf + len. - */ -static caddr_t -pfkey_setsadbkey(buf, lim, type, key, keylen) - caddr_t buf; - caddr_t lim; - caddr_t key; - u_int type, keylen; -{ - struct sadb_key *p; - u_int len; - - p = (struct sadb_key *)buf; - len = sizeof(struct sadb_key) + PFKEY_ALIGN8(keylen); - - if (buf + len > lim) - return NULL; - - memset(p, 0, len); - p->sadb_key_len = PFKEY_UNIT64(len); - p->sadb_key_exttype = type; - p->sadb_key_bits = keylen << 3; - p->sadb_key_reserved = 0; - - memcpy(p + 1, key, keylen); - - return buf + len; -} - -/* - * set sadb_lifetime structure after clearing buffer with zero. - * OUT: the pointer of buf + len. - */ -static caddr_t -pfkey_setsadblifetime(buf, lim, type, l_alloc, l_bytes, l_addtime, l_usetime) - caddr_t buf; - caddr_t lim; - u_int type; - u_int32_t l_alloc, l_bytes, l_addtime, l_usetime; -{ - struct sadb_lifetime *p; - u_int len; - - p = (struct sadb_lifetime *)buf; - len = sizeof(struct sadb_lifetime); - - if (buf + len > lim) - return NULL; - - memset(p, 0, len); - p->sadb_lifetime_len = PFKEY_UNIT64(len); - p->sadb_lifetime_exttype = type; - - switch (type) { - case SADB_EXT_LIFETIME_SOFT: - p->sadb_lifetime_allocations - = (l_alloc * soft_lifetime_allocations_rate) /100; - p->sadb_lifetime_bytes - = (l_bytes * soft_lifetime_bytes_rate) /100; - p->sadb_lifetime_addtime - = (l_addtime * soft_lifetime_addtime_rate) /100; - p->sadb_lifetime_usetime - = (l_usetime * soft_lifetime_usetime_rate) /100; - break; - case SADB_EXT_LIFETIME_HARD: - p->sadb_lifetime_allocations = l_alloc; - p->sadb_lifetime_bytes = l_bytes; - p->sadb_lifetime_addtime = l_addtime; - p->sadb_lifetime_usetime = l_usetime; - break; - } - - return buf + len; -} - -/* - * copy secasvar data into sadb_address. - * `buf' must has been allocated sufficiently. - */ -static caddr_t -pfkey_setsadbxsa2(buf, lim, mode0, reqid) - caddr_t buf; - caddr_t lim; - u_int32_t mode0; - u_int32_t reqid; -{ - struct sadb_x_sa2 *p; - u_int8_t mode = mode0 & 0xff; - u_int len; - - p = (struct sadb_x_sa2 *)buf; - len = sizeof(struct sadb_x_sa2); - - if (buf + len > lim) - return NULL; - - memset(p, 0, len); - p->sadb_x_sa2_len = PFKEY_UNIT64(len); - p->sadb_x_sa2_exttype = SADB_X_EXT_SA2; - p->sadb_x_sa2_mode = mode; - p->sadb_x_sa2_reqid = reqid; - - return(buf + len); -} |