diff --git a/lib/libipsec/libpfkey.h b/lib/libipsec/libpfkey.h index 5dbdaa06e8dd..81f714bbbab6 100644 --- a/lib/libipsec/libpfkey.h +++ b/lib/libipsec/libpfkey.h @@ -1,5 +1,5 @@ -/* $NetBSD: libpfkey.h,v 1.1 2000/06/12 10:40:52 itojun Exp $ */ -/* $KAME: libpfkey.h,v 1.1 2000/06/08 21:28:32 itojun Exp $ */ +/* $NetBSD: libpfkey.h,v 1.2 2002/05/14 11:24:21 itojun Exp $ */ +/* $KAME: libpfkey.h,v 1.6 2001/03/05 18:22:17 thorpej Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -30,11 +30,15 @@ * SUCH DAMAGE. */ +struct sadb_msg; extern void pfkey_sadump __P((struct sadb_msg *)); extern void pfkey_spdump __P((struct sadb_msg *)); struct sockaddr; +struct sadb_alg; int ipsec_check_keylen __P((u_int, u_int, u_int)); +int ipsec_check_keylen2 __P((u_int, u_int, u_int)); +int ipsec_get_keylen __P((u_int, u_int, struct sadb_alg *)); u_int pfkey_set_softrate __P((u_int, u_int)); u_int pfkey_get_softrate __P((u_int)); int pfkey_send_getspi __P((int, u_int, u_int, struct sockaddr *, @@ -49,17 +53,26 @@ int pfkey_send_add __P((int, u_int, u_int, struct sockaddr *, u_int64_t, u_int64_t, u_int32_t)); int pfkey_send_delete __P((int, u_int, u_int, struct sockaddr *, struct sockaddr *, u_int32_t)); +int pfkey_send_delete_all __P((int, u_int, u_int, + struct sockaddr *, struct sockaddr *)); int pfkey_send_get __P((int, u_int, u_int, struct sockaddr *, struct sockaddr *, u_int32_t)); int pfkey_send_register __P((int, u_int)); int pfkey_recv_register __P((int)); +int pfkey_set_supported __P((struct sadb_msg *, int)); int pfkey_send_flush __P((int, u_int)); int pfkey_send_dump __P((int, u_int)); int pfkey_send_promisc_toggle __P((int, int)); int pfkey_send_spdadd __P((int, struct sockaddr *, u_int, struct sockaddr *, u_int, u_int, caddr_t, int, u_int32_t)); +int pfkey_send_spdadd2 __P((int, struct sockaddr *, u_int, + struct sockaddr *, u_int, u_int, u_int64_t, u_int64_t, + caddr_t, int, u_int32_t)); int pfkey_send_spdupdate __P((int, struct sockaddr *, u_int, struct sockaddr *, u_int, u_int, caddr_t, int, u_int32_t)); +int pfkey_send_spdupdate2 __P((int, struct sockaddr *, u_int, + struct sockaddr *, u_int, u_int, u_int64_t, u_int64_t, + caddr_t, int, u_int32_t)); int pfkey_send_spddelete __P((int, struct sockaddr *, u_int, struct sockaddr *, u_int, u_int, caddr_t, int, u_int32_t)); int pfkey_send_spddelete2 __P((int, u_int32_t)); diff --git a/lib/libipsec/pfkey.c b/lib/libipsec/pfkey.c index a03d9e438b7f..259d2defbf72 100644 --- a/lib/libipsec/pfkey.c +++ b/lib/libipsec/pfkey.c @@ -1,5 +1,5 @@ -/* $NetBSD: pfkey.c,v 1.12 2001/09/16 16:34:26 wiz Exp $ */ -/* $KAME: pfkey.c,v 1.31 2000/06/10 14:17:43 sakane Exp $ */ +/* $NetBSD: pfkey.c,v 1.13 2002/05/14 11:24:21 itojun Exp $ */ +/* $KAME: pfkey.c,v 1.41 2002/05/14 10:59:09 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. @@ -48,6 +48,9 @@ #define CALLOC(size, cast) (cast)calloc(1, (size)) +static int findsupportedmap __P((int)); +static int setsupportedmap __P((struct sadb_supported *)); +static struct sadb_alg *findsupportedalg __P((u_int, u_int)); static int pfkey_send_x1 __P((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, @@ -56,90 +59,167 @@ static int pfkey_send_x2 __P((int, u_int, u_int, u_int, struct sockaddr *, struct sockaddr *, u_int32_t)); static int pfkey_send_x3 __P((int, u_int, u_int)); static int pfkey_send_x4 __P((int, u_int, struct sockaddr *, u_int, - struct sockaddr *, u_int, u_int, char *, int, u_int32_t)); + struct sockaddr *, u_int, u_int, u_int64_t, u_int64_t, + char *, int, u_int32_t)); static int pfkey_send_x5 __P((int, u_int, u_int32_t)); -static caddr_t pfkey_setsadbmsg __P((caddr_t, u_int, u_int, +static caddr_t pfkey_setsadbmsg __P((caddr_t, caddr_t, u_int, u_int, u_int, u_int32_t, pid_t)); -static caddr_t pfkey_setsadbsa __P((caddr_t, u_int32_t, u_int, +static caddr_t pfkey_setsadbsa __P((caddr_t, caddr_t, u_int32_t, u_int, u_int, u_int, u_int32_t)); -static caddr_t pfkey_setsadbaddr __P((caddr_t, u_int, +static caddr_t pfkey_setsadbaddr __P((caddr_t, caddr_t, u_int, struct sockaddr *, u_int, u_int)); -static caddr_t pfkey_setsadbkey __P((caddr_t, u_int, caddr_t, u_int)); -static caddr_t pfkey_setsadblifetime __P((caddr_t, u_int, u_int32_t, u_int32_t, - u_int32_t, u_int32_t)); -static caddr_t pfkey_setsadbxsa2 __P((caddr_t, u_int32_t, u_int32_t)); +static caddr_t pfkey_setsadbkey __P((caddr_t, caddr_t, u_int, caddr_t, u_int)); +static caddr_t pfkey_setsadblifetime __P((caddr_t, caddr_t, u_int, u_int32_t, + u_int32_t, u_int32_t, u_int32_t)); +static caddr_t pfkey_setsadbxsa2 __P((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, }; + +static int supported_map[] = { + SADB_SATYPE_AH, + SADB_SATYPE_ESP, + SADB_X_SATYPE_IPCOMP, +}; + +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. - * supported is either SADB_EXT_SUPPORTED_ENCRYPT or SADB_EXT_SUPPORTED_AUTH. - * Refer to keyv2.h to get more info. + * 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. */ -struct sadb_msg *ipsec_supported = NULL; - int ipsec_check_keylen(supported, alg_id, keylen) u_int supported; u_int alg_id; u_int keylen; { - u_int tlen; - caddr_t p; - struct sadb_supported *sup; - struct sadb_alg *alg; + int satype; /* validity check */ - if (ipsec_supported == NULL) { - __ipsec_errcode = EIPSEC_DO_GET_SUPP_LIST; - 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; } - tlen = ipsec_supported->sadb_msg_len - sizeof(struct sadb_msg); - p = (caddr_t)ipsec_supported + sizeof(struct sadb_msg); + return ipsec_check_keylen2(satype, alg_id, keylen); +} - for (; - tlen > 0; - tlen -= sup->sadb_supported_len, p += sup->sadb_supported_len) { +/* + * 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; - sup = (struct sadb_supported *)p; + alg = findsupportedalg(satype, alg_id); + if (!alg) + return -1; - if (sup->sadb_supported_exttype != supported) - continue; - - { - u_int ttlen = sup->sadb_supported_len; - caddr_t pp = p + sizeof(*sup); - - for (; - ttlen > 0; - ttlen -= sizeof(*alg), pp += sizeof(*alg)) { - alg = (struct sadb_alg *)pp; - - if (alg->sadb_alg_id == alg_id) - goto found; - } - } - } - - __ipsec_errcode = EIPSEC_NOT_SUPPORTED; - return -1; - /* NOTREACHED */ - - found: - if (keylen < alg->sadb_alg_minbits - || keylen > alg->sadb_alg_maxbits) { + if (keylen < alg->sadb_alg_minbits || keylen > alg->sadb_alg_maxbits) { __ipsec_errcode = EIPSEC_INVAL_KEYLEN; return -1; } @@ -148,6 +228,50 @@ ipsec_check_keylen(supported, alg_id, keylen) 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. @@ -221,6 +345,7 @@ pfkey_send_getspi(so, satype, mode, src, dst, min, max, reqid, seq) u_int32_t min, max, reqid, seq; { struct sadb_msg *newmsg; + caddr_t ep; int len; int need_spirange = 0; caddr_t p; @@ -268,31 +393,59 @@ pfkey_send_getspi(so, satype, mode, src, dst, min, max, reqid, seq) __ipsec_set_strerror(strerror(errno)); return -1; } + ep = ((caddr_t)newmsg) + len; - p = pfkey_setsadbmsg((caddr_t)newmsg, SADB_GETSPI, - len, satype, seq, getpid()); + p = pfkey_setsadbmsg((caddr_t)newmsg, ep, SADB_GETSPI, + len, satype, seq, getpid()); + if (!p) { + free(newmsg); + return -1; + } - p = pfkey_setsadbxsa2(p, mode, reqid); + p = pfkey_setsadbxsa2(p, ep, mode, reqid); + if (!p) { + free(newmsg); + return -1; + } /* set sadb_address for source */ - p = pfkey_setsadbaddr(p, SADB_EXT_ADDRESS_SRC, src, plen, + 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, SADB_EXT_ADDRESS_DST, dst, plen, + 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) { - int _len = sizeof(struct sadb_spirange); + struct sadb_spirange spirange; -#define _SADB_SPIRANGE(p) ((struct sadb_spirange *)(p)) - _SADB_SPIRANGE(p)->sadb_spirange_len = PFKEY_UNIT64(_len); - _SADB_SPIRANGE(p)->sadb_spirange_exttype = SADB_EXT_SPIRANGE; - _SADB_SPIRANGE(p)->sadb_spirange_min = min; - _SADB_SPIRANGE(p)->sadb_spirange_max = max; -#undef _SADB_SPIRANGE - p += _len; + 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 */ @@ -388,6 +541,91 @@ pfkey_send_delete(so, satype, mode, src, dst, spi) 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 occurred, 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: @@ -419,7 +657,29 @@ pfkey_send_register(so, satype) int so; u_int satype; { - int len; + int len, algno; + + if (satype == PF_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; @@ -440,51 +700,92 @@ pfkey_recv_register(so) { pid_t pid = getpid(); struct sadb_msg *newmsg; - struct sadb_supported *sup; - caddr_t p; - int tlen; + int error = -1; /* receive message */ do { if ((newmsg = pfkey_recv(so)) == NULL) return -1; - } while (newmsg->sadb_msg_type != SADB_REGISTER || newmsg->sadb_msg_pid != pid); /* check and fix */ newmsg->sadb_msg_len = PFKEY_UNUNIT64(newmsg->sadb_msg_len); - tlen = newmsg->sadb_msg_len - sizeof(struct sadb_msg); - p = (caddr_t)newmsg + sizeof(struct sadb_msg); - while (tlen > 0) { + 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 occurred, 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: - sup->sadb_supported_len = PFKEY_EXTLEN(sup); break; default: __ipsec_errcode = EIPSEC_INVAL_SATYPE; - free(newmsg); return -1; } - tlen -= sup->sadb_supported_len; + /* fixed length */ + sup->sadb_supported_len = PFKEY_EXTLEN(sup); + + /* set supported map */ + if (setsupportedmap(sup) != 0) + return -1; + p += sup->sadb_supported_len; } - if (tlen < 0) { + if (p != ep) { __ipsec_errcode = EIPSEC_INVAL_SATYPE; return -1; } - if (ipsec_supported != NULL) - free(ipsec_supported); - - ipsec_supported = newmsg; - __ipsec_errcode = EIPSEC_NO_ERROR; + return 0; } @@ -570,6 +871,35 @@ pfkey_send_spdadd(so, src, prefs, dst, prefd, proto, policy, policylen, seq) 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 occurred, 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; @@ -595,6 +925,35 @@ pfkey_send_spdupdate(so, src, prefs, dst, prefd, proto, policy, policylen, seq) 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 occurred, 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; @@ -625,6 +984,7 @@ pfkey_send_spddelete(so, src, prefs, dst, prefd, proto, policy, policylen, seq) if ((len = pfkey_send_x4(so, SADB_X_SPDDELETE, src, prefs, dst, prefd, proto, + 0, 0, policy, policylen, seq)) < 0) return -1; @@ -693,6 +1053,7 @@ pfkey_send_spdsetidx(so, src, prefs, dst, prefd, proto, policy, policylen, seq) if ((len = pfkey_send_x4(so, SADB_X_SPDSETIDX, src, prefs, dst, prefd, proto, + 0, 0, policy, policylen, seq)) < 0) return -1; @@ -753,6 +1114,7 @@ pfkey_send_x1(so, type, satype, mode, src, dst, spi, reqid, wsize, int len; caddr_t p; int plen; + caddr_t ep; /* validity check */ if (src == NULL || dst == NULL) { @@ -793,6 +1155,14 @@ pfkey_send_x1(so, type, satype, mode, src, dst, spi, reqid, wsize, } 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; default: __ipsec_errcode = EIPSEC_INVAL_SATYPE; @@ -819,28 +1189,67 @@ pfkey_send_x1(so, type, satype, mode, src, dst, spi, reqid, wsize, __ipsec_set_strerror(strerror(errno)); return -1; } + ep = ((caddr_t)newmsg) + len; - p = pfkey_setsadbmsg((caddr_t)newmsg, type, len, + p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len, satype, seq, getpid()); - p = pfkey_setsadbsa(p, spi, wsize, a_type, e_type, flags); - p = pfkey_setsadbxsa2(p, mode, reqid); - p = pfkey_setsadbaddr(p, SADB_EXT_ADDRESS_SRC, src, plen, + 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); - p = pfkey_setsadbaddr(p, SADB_EXT_ADDRESS_DST, dst, plen, + 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, SADB_EXT_KEY_ENCRYPT, + if (e_type != SADB_EALG_NONE) { + p = pfkey_setsadbkey(p, ep, SADB_EXT_KEY_ENCRYPT, keymat, e_keylen); - if (a_type != SADB_AALG_NONE) - p = pfkey_setsadbkey(p, SADB_EXT_KEY_AUTH, + 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, SADB_EXT_LIFETIME_HARD, + p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_HARD, l_alloc, l_bytes, l_addtime, l_usetime); - p = pfkey_setsadblifetime(p, SADB_EXT_LIFETIME_SOFT, + 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); @@ -865,6 +1274,7 @@ pfkey_send_x2(so, type, satype, mode, src, dst, spi) int len; caddr_t p; int plen; + caddr_t ep; /* validity check */ if (src == NULL || dst == NULL) { @@ -899,13 +1309,31 @@ pfkey_send_x2(so, type, satype, mode, src, dst, spi) __ipsec_set_strerror(strerror(errno)); return -1; } + ep = ((caddr_t)newmsg) + len; - p = pfkey_setsadbmsg((caddr_t)newmsg, type, len, satype, 0, getpid()); - p = pfkey_setsadbsa(p, spi, 0, 0, 0, 0); - p = pfkey_setsadbaddr(p, SADB_EXT_ADDRESS_SRC, src, plen, + 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); - p = pfkey_setsadbaddr(p, SADB_EXT_ADDRESS_DST, dst, plen, + 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); @@ -929,6 +1357,8 @@ pfkey_send_x3(so, type, satype) { struct sadb_msg *newmsg; int len; + caddr_t p; + caddr_t ep; /* validity check */ switch (type) { @@ -958,8 +1388,14 @@ pfkey_send_x3(so, type, satype) __ipsec_set_strerror(strerror(errno)); return -1; } + ep = ((caddr_t)newmsg) + len; - (void)pfkey_setsadbmsg((caddr_t)newmsg, type, len, satype, 0, getpid()); + 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); @@ -974,10 +1410,12 @@ pfkey_send_x3(so, type, satype) /* sending SADB_X_SPDADD message to the kernel */ static int -pfkey_send_x4(so, type, src, prefs, dst, prefd, proto, policy, policylen, seq) +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; @@ -986,6 +1424,7 @@ pfkey_send_x4(so, type, src, prefs, dst, prefd, proto, policy, policylen, seq) int len; caddr_t p; int plen; + caddr_t ep; /* validity check */ if (src == NULL || dst == NULL) { @@ -1019,25 +1458,37 @@ pfkey_send_x4(so, type, src, prefs, dst, prefd, proto, policy, policylen, seq) + 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, type, len, - SADB_SATYPE_UNSPEC, seq, getpid()); - p = pfkey_setsadbaddr(p, - SADB_EXT_ADDRESS_SRC, - src, - prefs, - proto); - p = pfkey_setsadbaddr(p, - SADB_EXT_ADDRESS_DST, - dst, - prefd, - proto); + 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 */ @@ -1062,6 +1513,7 @@ pfkey_send_x5(so, type, spid) struct sadb_x_policy xpl; int len; caddr_t p; + caddr_t ep; /* create new sadb_msg to reply. */ len = sizeof(struct sadb_msg) @@ -1071,15 +1523,23 @@ pfkey_send_x5(so, type, spid) __ipsec_set_strerror(strerror(errno)); return -1; } + ep = ((caddr_t)newmsg) + len; - p = pfkey_setsadbmsg((caddr_t)newmsg, type, len, - SADB_SATYPE_UNSPEC, 0, getpid()); + 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_UNUNIT64(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 */ @@ -1143,6 +1603,8 @@ pfkey_close(so) * OUT: * NULL : error occurred. * others : a pointer to sadb_msg structure. + * + * XXX should be rewritten to pass length explicitly */ struct sadb_msg * pfkey_recv(so) @@ -1152,7 +1614,8 @@ pfkey_recv(so) int len, reallen; while ((len = recv(so, (caddr_t)&buf, sizeof(buf), MSG_PEEK)) < 0) { - if (errno == EINTR) continue; + if (errno == EINTR) + continue; __ipsec_set_strerror(strerror(errno)); return NULL; } @@ -1171,7 +1634,8 @@ pfkey_recv(so) } while ((len = recv(so, (caddr_t)newmsg, reallen, 0)) < 0) { - if (errno == EINTR) continue; + if (errno == EINTR) + continue; __ipsec_set_strerror(strerror(errno)); free(newmsg); return NULL; @@ -1183,6 +1647,13 @@ pfkey_recv(so) 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; } @@ -1219,6 +1690,8 @@ pfkey_send(so, msg, len) * 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) @@ -1226,8 +1699,9 @@ pfkey_align(msg, mhp) caddr_t *mhp; { struct sadb_ext *ext; - int tlen, extlen; int i; + caddr_t p; + caddr_t ep; /* XXX should be passed from upper layer */ /* validity check */ if (msg == NULL || mhp == NULL) { @@ -1241,10 +1715,21 @@ pfkey_align(msg, mhp) mhp[0] = (caddr_t)msg; - tlen = PFKEY_UNUNIT64(msg->sadb_msg_len) - sizeof(struct sadb_msg); - ext = (struct sadb_ext *)((caddr_t)msg + sizeof(struct sadb_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; + } - while (tlen > 0) { /* duplicate check */ /* XXX Are there duplication either KEY_AUTH or KEY_ENCRYPT ?*/ if (mhp[ext->sadb_ext_type] != NULL) { @@ -1281,9 +1766,12 @@ pfkey_align(msg, mhp) return -1; } - extlen = PFKEY_EXTLEN(ext); - tlen -= extlen; - ext = (struct sadb_ext *)((caddr_t)ext + extlen); + p += PFKEY_EXTLEN(ext); + } + + if (p != ep) { + __ipsec_errcode = EIPSEC_INVAL_SADBMSG; + return -1; } __ipsec_errcode = EIPSEC_NO_ERROR; @@ -1413,8 +1901,9 @@ pfkey_check(mhp) * `buf' must has been allocated sufficiently. */ static caddr_t -pfkey_setsadbmsg(buf, type, tlen, satype, seq, pid) +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; @@ -1426,6 +1915,9 @@ pfkey_setsadbmsg(buf, type, tlen, satype, seq, pid) 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; @@ -1444,8 +1936,9 @@ pfkey_setsadbmsg(buf, type, tlen, satype, seq, pid) * `buf' must has been allocated sufficiently. */ static caddr_t -pfkey_setsadbsa(buf, spi, wsize, auth, enc, flags) +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; { @@ -1455,6 +1948,9 @@ pfkey_setsadbsa(buf, spi, wsize, auth, enc, flags) 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; @@ -1474,8 +1970,9 @@ pfkey_setsadbsa(buf, spi, wsize, auth, enc, flags) * prefixlen is in bits. */ static caddr_t -pfkey_setsadbaddr(buf, exttype, saddr, prefixlen, ul_proto) +pfkey_setsadbaddr(buf, lim, exttype, saddr, prefixlen, ul_proto) caddr_t buf; + caddr_t lim; u_int exttype; struct sockaddr *saddr; u_int prefixlen; @@ -1487,6 +1984,9 @@ pfkey_setsadbaddr(buf, exttype, saddr, prefixlen, ul_proto) 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; @@ -1504,8 +2004,10 @@ pfkey_setsadbaddr(buf, exttype, saddr, prefixlen, ul_proto) * OUT: the pointer of buf + len. */ static caddr_t -pfkey_setsadbkey(buf, type, key, keylen) - caddr_t buf, key; +pfkey_setsadbkey(buf, lim, type, key, keylen) + caddr_t buf; + caddr_t lim; + caddr_t key; u_int type, keylen; { struct sadb_key *p; @@ -1514,6 +2016,9 @@ pfkey_setsadbkey(buf, type, key, keylen) 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; @@ -1530,8 +2035,9 @@ pfkey_setsadbkey(buf, type, key, keylen) * OUT: the pointer of buf + len. */ static caddr_t -pfkey_setsadblifetime(buf, type, l_alloc, l_bytes, l_addtime, l_usetime) +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; { @@ -1541,6 +2047,9 @@ pfkey_setsadblifetime(buf, type, l_alloc, l_bytes, l_addtime, l_usetime) 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; @@ -1572,8 +2081,9 @@ pfkey_setsadblifetime(buf, type, l_alloc, l_bytes, l_addtime, l_usetime) * `buf' must has been allocated sufficiently. */ static caddr_t -pfkey_setsadbxsa2(buf, mode0, reqid) +pfkey_setsadbxsa2(buf, lim, mode0, reqid) caddr_t buf; + caddr_t lim; u_int32_t mode0; u_int32_t reqid; { @@ -1584,6 +2094,9 @@ pfkey_setsadbxsa2(buf, mode0, reqid) 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; @@ -1592,4 +2105,3 @@ pfkey_setsadbxsa2(buf, mode0, reqid) return(buf + len); } - diff --git a/lib/libipsec/pfkey_dump.c b/lib/libipsec/pfkey_dump.c index 59f64cf8f488..a2ac3e855aa5 100644 --- a/lib/libipsec/pfkey_dump.c +++ b/lib/libipsec/pfkey_dump.c @@ -1,5 +1,5 @@ -/* $NetBSD: pfkey_dump.c,v 1.9 2000/10/03 23:00:54 itojun Exp $ */ -/* $KAME: pfkey_dump.c,v 1.22 2000/09/12 07:10:53 itojun Exp $ */ +/* $NetBSD: pfkey_dump.c,v 1.10 2002/05/14 11:24:21 itojun Exp $ */ +/* $KAME: pfkey_dump.c,v 1.36 2002/05/13 05:30:08 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. @@ -77,7 +77,8 @@ do { \ } while (0) static char *str_ipaddr __P((struct sockaddr *)); -static char *str_prefport __P((u_int, u_int, u_int)); +static char *str_prefport __P((u_int, u_int, u_int, u_int)); +static void str_upperspec __P((u_int, u_int, u_int)); static char *str_time __P((time_t)); static void str_lifetime_byte __P((struct sadb_lifetime *, char *)); @@ -108,22 +109,6 @@ static char *str_mode[] = { "tunnel", }; -static char *str_upper[] = { -/*0*/ "ip", "icmp", "igmp", "ggp", "ip4", - "", "tcp", "", "egp", "", -/*10*/ "", "", "", "", "", - "", "", "udp", "", "", -/*20*/ "", "", "idp", "", "", - "", "", "", "", "tp", -/*30*/ "", "", "", "", "", - "", "", "", "", "", -/*40*/ "", "ip6", "", "rt6", "frag6", - "", "rsvp", "gre", "", "", -/*50*/ "esp", "ah", "", "", "", - "", "", "", "icmp6", "none", -/*60*/ "dst6", -}; - static char *str_state[] = { "larval", "mature", @@ -265,17 +250,15 @@ pfkey_sadump(m) } /* replay windoe size & flags */ - printf("\treplay=%u flags=0x%08x ", + printf("\tseq=0x%08x replay=%u flags=0x%08x ", + m_sa2->sadb_x_sa2_sequence, m_sa->sadb_sa_replay, m_sa->sadb_sa_flags); /* state */ printf("state="); GETMSGSTR(str_state, m_sa->sadb_sa_state); - - printf("seq=%lu pid=%lu\n", - (u_long)m->sadb_msg_seq, - (u_long)m->sadb_msg_pid); + printf("\n"); /* lifetime */ if (m_lftc != NULL) { @@ -319,8 +302,12 @@ pfkey_sadump(m) 0 : m_lfts->sadb_lifetime_allocations)); } + printf("\tsadb_seq=%lu pid=%lu ", + (u_long)m->sadb_msg_seq, + (u_long)m->sadb_msg_pid); + /* XXX DEBUG */ - printf("\trefcnt=%u\n", m->sadb_msg_reserved); + printf("refcnt=%u\n", m->sadb_msg_reserved); return; } @@ -333,8 +320,9 @@ pfkey_spdump(m) caddr_t mhp[SADB_EXT_MAX + 1]; struct sadb_address *m_saddr, *m_daddr; struct sadb_x_policy *m_xpl; + struct sadb_lifetime *m_lftc = NULL, *m_lfth = NULL; struct sockaddr *sa; - u_int16_t port; + u_int16_t sport = 0, dport = 0; /* check pfkey message. */ if (pfkey_align(m, mhp)) { @@ -349,6 +337,8 @@ pfkey_spdump(m) m_saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]; m_daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]; m_xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY]; + m_lftc = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_CURRENT]; + m_lfth = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_HARD]; /* source address */ if (m_saddr == NULL) { @@ -361,12 +351,13 @@ pfkey_spdump(m) case AF_INET6: if (getnameinfo(sa, sa->sa_len, NULL, 0, pbuf, sizeof(pbuf), NI_NUMERICSERV) != 0) - port = 0; /*XXX*/ + sport = 0; /*XXX*/ else - port = atoi(pbuf); + sport = atoi(pbuf); printf("%s%s ", str_ipaddr(sa), str_prefport(sa->sa_family, - m_saddr->sadb_address_prefixlen, port)); + m_saddr->sadb_address_prefixlen, sport, + m_saddr->sadb_address_proto)); break; default: printf("unknown-af "); @@ -384,12 +375,13 @@ pfkey_spdump(m) case AF_INET6: if (getnameinfo(sa, sa->sa_len, NULL, 0, pbuf, sizeof(pbuf), NI_NUMERICSERV) != 0) - port = 0; /*XXX*/ + dport = 0; /*XXX*/ else - port = atoi(pbuf); + dport = atoi(pbuf); printf("%s%s ", str_ipaddr(sa), str_prefport(sa->sa_family, - m_daddr->sadb_address_prefixlen, port)); + m_daddr->sadb_address_prefixlen, dport, + m_saddr->sadb_address_proto)); break; default: printf("unknown-af "); @@ -401,10 +393,7 @@ pfkey_spdump(m) printf("upper layer protocol mismatched.\n"); return; } - if (m_saddr->sadb_address_proto == IPSEC_ULPROTO_ANY) - printf("any"); - else - GETMSGSTR(str_upper, m_saddr->sadb_address_proto); + str_upperspec(m_saddr->sadb_address_proto, sport, dport); /* policy */ { @@ -421,6 +410,21 @@ pfkey_spdump(m) free(d_xpl); } + /* lifetime */ + if (m_lftc) { + printf("\tcreated: %s ", + str_time(m_lftc->sadb_lifetime_addtime)); + printf("lastused: %s\n", + str_time(m_lftc->sadb_lifetime_usetime)); + } + if (m_lfth) { + printf("\tlifetime: %lu(s) ", + (u_long)m_lfth->sadb_lifetime_addtime); + printf("validtime: %lu(s)\n", + (u_long)m_lfth->sadb_lifetime_usetime); + } + + printf("\tspid=%ld seq=%ld pid=%ld\n", (u_long)m_xpl->sadb_x_policy_id, (u_long)m->sadb_msg_seq, @@ -458,8 +462,8 @@ str_ipaddr(sa) * set "/prefix[port number]" to buffer. */ static char * -str_prefport(family, pref, port) - u_int family, pref, port; +str_prefport(family, pref, port, ulp) + u_int family, pref, port, ulp; { static char buf[128]; char prefbuf[10]; @@ -492,6 +496,32 @@ str_prefport(family, pref, port) return buf; } +static void +str_upperspec(ulp, p1, p2) + u_int ulp, p1, p2; +{ + if (ulp == IPSEC_ULPROTO_ANY) + printf("any"); + else { + struct protoent *ent; + + switch (ulp) { + case IPPROTO_IPV4: + printf("ip4"); + break; + default: + ent = getprotobynumber(ulp); + if (ent) + printf("%s", ent->p_name); + else + printf("%d", ulp); + + endprotoent(); + break; + } + } +} + /* * set "Mon Day Time Year" to buffer */ diff --git a/sbin/setkey/parse.y b/sbin/setkey/parse.y index dd8013dce42d..a969b160101e 100644 --- a/sbin/setkey/parse.y +++ b/sbin/setkey/parse.y @@ -1,5 +1,5 @@ -/* $NetBSD: parse.y,v 1.7 2001/11/02 03:57:25 lukem Exp $ */ -/* $KAME: parse.y,v 1.63 2001/08/17 06:28:49 itojun Exp $ */ +/* $NetBSD: parse.y,v 1.8 2002/05/14 11:24:20 itojun Exp $ */ +/* $KAME: parse.y,v 1.69 2002/05/14 11:16:10 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. @@ -457,10 +457,25 @@ spdadd_command : SPDADD ipaddropts STRING prefix portstr STRING prefix portstr upper_spec policy_spec EOT { int status; + struct addrinfo *src, *dst; + + src = parse_addr($3.buf, $5.buf); + dst = parse_addr($6.buf, $8.buf); + if (!src || !dst) { + /* yyerror is already called */ + return -1; + } + if (src->ai_next || dst->ai_next) { + yyerror("multiple address specified"); + freeaddrinfo(src); + freeaddrinfo(dst); + return -1; + } status = setkeymsg_spdaddr(SADB_X_SPDADD, $9, &$10, - parse_addr($3.buf, $5.buf), $4, - parse_addr($6.buf, $8.buf), $7); + src, $4, dst, $7); + freeaddrinfo(src); + freeaddrinfo(dst); if (status < 0) return -1; } @@ -487,10 +502,10 @@ spddelete_command status = setkeymsg_spdaddr(SADB_X_SPDDELETE, $9, &$10, src, $4, dst, $7); - if (status < 0) - return -1; freeaddrinfo(src); freeaddrinfo(dst); + if (status < 0) + return -1; } ; diff --git a/sbin/setkey/setkey.8 b/sbin/setkey/setkey.8 index 3ff7aa3f2914..b9e4c62ac547 100644 --- a/sbin/setkey/setkey.8 +++ b/sbin/setkey/setkey.8 @@ -1,5 +1,5 @@ -.\" $NetBSD: setkey.8,v 1.13 2001/11/16 12:10:06 wiz Exp $ -.\" $KAME: setkey.8,v 1.66 2001/09/04 10:05:07 jinmei Exp $ +.\" $NetBSD: setkey.8,v 1.14 2002/05/14 11:24:20 itojun Exp $ +.\" $KAME: setkey.8,v 1.73 2002/05/14 11:05:35 itojun Exp $ .\" .\" Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. .\" All rights reserved. @@ -419,23 +419,12 @@ You have to consider and be careful to use them. .Pp .It Ar policy .Ar policy -is the one of following: -.Bd -literal -offset -.Xo -.Fl P -.Ar direction -.Li discard -.Xc -.Xo -.Fl P -.Ar direction -.Li none -.Xc -.Xo -.Fl P -.Ar direction -.Li ipsec -.Ar protocol/mode/src-dst/level +is the one of the following three formats: +.Bd -literal -offset indent +.It Fl P Ar direction Li discard +.It Fl P Ar direction Li none +.It Xo Fl P Ar direction Li ipsec +.Ar protocol/mode/src-dst/level Op ... .Xc .Ed .Pp @@ -452,6 +441,9 @@ means the packet matching indexes will be discarded. means that IPsec operation will not take place onto the packet. .Li ipsec means that IPsec operation will take place onto the packet. +The part of +.Ar protocol/mode/src-dst/level +specifies the rule how to process the packet . Either .Li ah , .Li esp @@ -503,19 +495,31 @@ otherwise the kernel keeps normal operation. means SA is required whenever the kernel sends a packet matched with the policy. .Li unique -is the same to require. -In addition, it allows the policy to bind with the unique out-bound SA. -If you use the SA by manual keying, +is the same to require, +in addition, it allows the policy to bind with the unique out-bound SA. +You just specify the policy level +.Li unique , +.Xr racoon 8 +will configure the SA for the policy. +If you configure the SA by manual keying for that policy, you can put the decimal number as the policy identifier after .Li unique separated by colon .Sq \&: like the following; .Li unique:number . +in order to bind this policy to the SA . .Li number must be between 1 and 32767. It corresponds to -.Ar extensions Fl u . +.Ar extensions Fl u +of the manual SA configuration. +When you want to use SA bundle, you can define multiple rules. +For example, if an IP header was followed by AH header followed by ESP header +followed by an upper layer protocol header, the rule +would be: +.Dl esp/transport//require ah/transport//require ; +The rule order is very important. .Pp Note that .Dq Li discard @@ -591,7 +595,7 @@ algorithm deflate rfc2394 .Ed .\" -.Sh RETURN VALUES +.Sh EXIT STATUS The command exits with 0 on success, and non-zero on errors. .\" .Sh EXAMPLES diff --git a/sbin/setkey/token.l b/sbin/setkey/token.l index 19366f0ec4c8..8938070591ab 100644 --- a/sbin/setkey/token.l +++ b/sbin/setkey/token.l @@ -1,5 +1,5 @@ -/* $NetBSD: token.l,v 1.6 2001/09/07 04:12:10 itojun Exp $ */ -/* $KAME: token.l,v 1.33 2001/08/17 06:21:57 itojun Exp $ */ +/* $NetBSD: token.l,v 1.7 2002/05/14 11:24:20 itojun Exp $ */ +/* $KAME: token.l,v 1.34 2001/09/25 14:15:24 sakane Exp $ */ /* * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.