From Yvan Vanhullebus: Use SADB_X_EXT_NAT_T_* consistently for passing the From: Timo Teras NAT-T port information. --- src/libipsec/libpfkey.h | 12 ++++++++ src/libipsec/pfkey.c | 49 +++++++++++++++++++++++++++++++++ src/racoon/isakmp.c | 11 +++++++ src/racoon/isakmp_inf.c | 37 +++++++++++++------------ src/racoon/pfkey.c | 69 +++++++++++++++++++++++++++++++++-------------- src/racoon/pfkey.h | 1 + 6 files changed, 140 insertions(+), 39 deletions(-) diff --git a/src/libipsec/libpfkey.h b/src/libipsec/libpfkey.h index 8a503dd..c9b228b 100644 --- a/src/libipsec/libpfkey.h +++ b/src/libipsec/libpfkey.h @@ -117,6 +117,10 @@ 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 *, struct sockaddr *, u_int32_t, u_int32_t, u_int32_t, u_int32_t)); +int pfkey_send_getspi_nat __P((int, u_int, u_int, + struct sockaddr *, struct sockaddr *, u_int8_t, u_int16_t, u_int16_t, + u_int32_t, u_int32_t, u_int32_t, u_int32_t)); + int pfkey_send_update2 __P((struct pfkey_send_sa_args *)); int pfkey_send_add2 __P((struct pfkey_send_sa_args *)); int pfkey_send_delete __P((int, u_int, u_int, @@ -155,6 +159,14 @@ int pfkey_send_migrate __P((int, struct sockaddr *, struct sockaddr *, caddr_t, int, u_int32_t)); #endif +/* XXX should be somewhere else !!! + */ +#ifdef SADB_X_NAT_T_NEW_MAPPING +#define PFKEY_ADDR_X_PORT(ext) (ntohs(((struct sadb_x_nat_t_port *)ext)->sadb_x_nat_t_port_port)) +#define PFKEY_ADDR_X_NATTYPE(ext) ( ext != NULL && ((struct sadb_x_nat_t_type *)ext)->sadb_x_nat_t_type_type ) +#endif + + int pfkey_open __P((void)); void pfkey_close __P((int)); int pfkey_set_buffer_size __P((int, int)); diff --git a/src/libipsec/pfkey.c b/src/libipsec/pfkey.c index 0a944c2..b39ffca 100644 --- a/src/libipsec/pfkey.c +++ b/src/libipsec/pfkey.c @@ -380,10 +380,12 @@ pfkey_get_softrate(type) * -1 : error occured, and set errno. */ int -pfkey_send_getspi(so, satype, mode, src, dst, min, max, reqid, seq) +pfkey_send_getspi_nat(so, satype, mode, src, dst, natt_type, sport, dport, min, max, reqid, seq) int so; u_int satype, mode; struct sockaddr *src, *dst; + u_int8_t natt_type; + u_int16_t sport, dport; u_int32_t min, max, reqid, seq; { struct sadb_msg *newmsg; @@ -431,6 +433,14 @@ pfkey_send_getspi(so, satype, mode, src, dst, min, max, reqid, seq) len += sizeof(struct sadb_spirange); } +#ifdef SADB_X_EXT_NAT_T_TYPE + if(natt_type||sport||dport){ + len += sizeof(struct sadb_x_nat_t_type); + len += sizeof(struct sadb_x_nat_t_port); + len += sizeof(struct sadb_x_nat_t_port); + } +#endif + if ((newmsg = CALLOC((size_t)len, struct sadb_msg *)) == NULL) { __ipsec_set_strerror(strerror(errno)); return -1; @@ -466,6 +476,32 @@ pfkey_send_getspi(so, satype, mode, src, dst, min, max, reqid, seq) return -1; } +#ifdef SADB_X_EXT_NAT_T_TYPE + /* Add nat-t messages */ + if (natt_type) { + p = pfkey_set_natt_type(p, ep, SADB_X_EXT_NAT_T_TYPE, + natt_type); + if (!p) { + free(newmsg); + return -1; + } + + p = pfkey_set_natt_port(p, ep, SADB_X_EXT_NAT_T_SPORT, + sport); + if (!p) { + free(newmsg); + return -1; + } + + p = pfkey_set_natt_port(p, ep, SADB_X_EXT_NAT_T_DPORT, + dport); + if (!p) { + free(newmsg); + return -1; + } + } +#endif + /* proccessing spi range */ if (need_spirange) { struct sadb_spirange spirange; @@ -501,6 +537,17 @@ pfkey_send_getspi(so, satype, mode, src, dst, min, max, reqid, seq) return len; } +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; +{ + return pfkey_send_getspi_nat(so, satype, mode, src, dst, 0, 0, 0, + min, max, reqid, seq); +} + /* * sending SADB_UPDATE message to the kernel. * The length of key material is a_keylen + e_keylen. diff --git a/src/racoon/isakmp.c b/src/racoon/isakmp.c index c8670f6..fe51653 100644 --- a/src/racoon/isakmp.c +++ b/src/racoon/isakmp.c @@ -3324,6 +3324,17 @@ purge_remote(iph1) src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]); dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]); +#ifdef SADB_X_NAT_T_NEW_MAPPING + if (PFKEY_ADDR_X_NATTYPE(mhp[SADB_X_EXT_NAT_T_TYPE])) { + /* NAT-T is enabled for this SADB entry; copy + * the ports from NAT-T extensions */ + if(mhp[SADB_X_EXT_NAT_T_SPORT] != NULL) + set_port(src, PFKEY_ADDR_X_PORT(mhp[SADB_X_EXT_NAT_T_SPORT])); + if(mhp[SADB_X_EXT_NAT_T_DPORT] != NULL) + set_port(dst, PFKEY_ADDR_X_PORT(mhp[SADB_X_EXT_NAT_T_DPORT])); + } +#endif + if (sa->sadb_sa_state != SADB_SASTATE_LARVAL && sa->sadb_sa_state != SADB_SASTATE_MATURE && sa->sadb_sa_state != SADB_SASTATE_DYING) { diff --git a/src/racoon/isakmp_inf.c b/src/racoon/isakmp_inf.c index 1ada07f..a712825 100644 --- a/src/racoon/isakmp_inf.c +++ b/src/racoon/isakmp_inf.c @@ -1128,8 +1128,7 @@ purge_ipsec_spi(dst0, proto, spi, n) size_t i; caddr_t mhp[SADB_EXT_MAX + 1]; #ifdef ENABLE_NATT - struct sadb_x_nat_t_type *natt_type; - struct sadb_x_nat_t_port *natt_port; + int natt_port_forced; #endif plog(LLV_DEBUG2, LOCATION, NULL, @@ -1184,22 +1183,25 @@ purge_ipsec_spi(dst0, proto, spi, n) continue; } #ifdef ENABLE_NATT - natt_type = (void *)mhp[SADB_X_EXT_NAT_T_TYPE]; - if (natt_type && natt_type->sadb_x_nat_t_type_type) { + if (PFKEY_ADDR_X_NATTYPE(mhp[SADB_X_EXT_NAT_T_TYPE])) { /* NAT-T is enabled for this SADB entry; copy * the ports from NAT-T extensions */ - natt_port = (void *)mhp[SADB_X_EXT_NAT_T_SPORT]; - if (extract_port(src) == 0 && natt_port != NULL) - set_port(src, ntohs(natt_port->sadb_x_nat_t_port_port)); - - natt_port = (void *)mhp[SADB_X_EXT_NAT_T_DPORT]; - if (extract_port(dst) == 0 && natt_port != NULL) - set_port(dst, ntohs(natt_port->sadb_x_nat_t_port_port)); - }else{ - /* Force default UDP ports, so CMPSADDR will match SAs with NO encapsulation - */ + if (extract_port(src) == 0 && + mhp[SADB_X_EXT_NAT_T_SPORT] != NULL) { + set_port(src, PFKEY_ADDR_X_PORT(mhp[SADB_X_EXT_NAT_T_SPORT])); + } + + if (extract_port(dst) == 0 && + mhp[SADB_X_EXT_NAT_T_DPORT] != NULL) { + set_port(dst, PFKEY_ADDR_X_PORT(mhp[SADB_X_EXT_NAT_T_DPORT])); + } + natt_port_forced = 0; + } else { + /* Force default UDP ports, so + * CMPSADDR will match SAs with NO encapsulation */ set_port(src, PORT_ISAKMP); set_port(dst, PORT_ISAKMP); + natt_port_forced = 1; } #endif plog(LLV_DEBUG2, LOCATION, NULL, "src: %s\n", saddr2str(src)); @@ -1215,10 +1217,9 @@ purge_ipsec_spi(dst0, proto, spi, n) } #ifdef ENABLE_NATT - if (natt_type == NULL || - ! natt_type->sadb_x_nat_t_type_type) { - /* Set back port to 0 if it was forced to default UDP port - */ + if (natt_port_forced) { + /* Set back port to 0 if it was forced + * to default UDP port */ set_port(src, 0); set_port(dst, 0); } diff --git a/src/racoon/pfkey.c b/src/racoon/pfkey.c index 610cc09..c210c5e 100644 --- a/src/racoon/pfkey.c +++ b/src/racoon/pfkey.c @@ -769,6 +769,28 @@ keylen_ealg(enctype, encklen) return res; } +void +pk_fixup_sa_addresses(mhp) + caddr_t *mhp; +{ + struct sockaddr *src, *dst; + src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]); + dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]); +#ifdef ENABLE_NATT + if (PFKEY_ADDR_X_NATTYPE(mhp[SADB_X_EXT_NAT_T_TYPE])) { + /* NAT-T is enabled for this SADB entry; copy + * the ports from NAT-T extensions */ + if(mhp[SADB_X_EXT_NAT_T_SPORT] != NULL) + set_port(src, PFKEY_ADDR_X_PORT(mhp[SADB_X_EXT_NAT_T_SPORT])); + if(mhp[SADB_X_EXT_NAT_T_DPORT] != NULL) + set_port(dst, PFKEY_ADDR_X_PORT(mhp[SADB_X_EXT_NAT_T_DPORT])); + } +#else + set_port(src, 0); + set_port(dst, 0); +#endif +} + int pfkey_convertfromipsecdoi(proto_id, t_id, hashtype, e_type, e_keylen, a_type, a_keylen, flags) @@ -866,6 +888,8 @@ pk_sendgetspi(iph2) struct saprop *pp; struct saproto *pr; u_int32_t minspi, maxspi; + u_int8_t natt_type = 0; + u_int16_t sport = 0, dport = 0; if (iph2->side == INITIATOR) pp = iph2->proposal; @@ -919,19 +943,27 @@ pk_sendgetspi(iph2) } #ifdef ENABLE_NATT - if (! pr->udp_encap) { - /* Remove port information, that SA doesn't use it */ - set_port(iph2->src, 0); - set_port(iph2->dst, 0); + if (pr->udp_encap) { + natt_type = iph2->ph1->natt_options->encaps_type; + sport=extract_port(src); + dport=extract_port(dst); } #endif + /* Always remove port information, it will be sent in + * SADB_X_EXT_NAT_T_[S|D]PORT if needed */ + set_port(src, 0); + set_port(dst, 0); + plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_getspi\n"); - if (pfkey_send_getspi( + if (pfkey_send_getspi_nat( lcconf->sock_pfkey, satype, mode, dst, /* src of SA */ src, /* dst of SA */ + natt_type, + dport, + sport, minspi, maxspi, pr->reqid_in, iph2->seq) < 0) { plog(LLV_ERROR, LOCATION, NULL, @@ -1157,13 +1189,13 @@ pk_sendupdate(iph2) #ifdef SADB_X_EXT_NAT_T_FRAG sa_args.l_natt_frag = iph2->ph1->rmconf->esp_frag; #endif - } else { - /* Remove port information, that SA doesn't use it */ - set_port(sa_args.src, 0); - set_port(sa_args.dst, 0); } - #endif + /* Always remove port information, it will be sent in + * SADB_X_EXT_NAT_T_[S|D]PORT if needed */ + set_port(sa_args.src, 0); + set_port(sa_args.dst, 0); + /* more info to fill in */ sa_args.spi = pr->spi; sa_args.reqid = pr->reqid_in; @@ -1236,6 +1268,7 @@ pk_recvupdate(mhp) return -1; } msg = (struct sadb_msg *)mhp[0]; + pk_fixup_sa_addresses(mhp); src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]); dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]); sa = (struct sadb_sa *)mhp[SADB_EXT_SA]; @@ -1328,7 +1361,6 @@ pk_recvupdate(mhp) /* Force the update of ph2's ports, as there is at least one * situation where they'll mismatch with ph1's values */ - #ifdef ENABLE_NATT set_port(iph2->src, extract_port(iph2->ph1->local)); set_port(iph2->dst, extract_port(iph2->ph1->remote)); @@ -1456,17 +1488,12 @@ pk_sendadd(iph2) #ifdef SADB_X_EXT_NAT_T_FRAG sa_args.l_natt_frag = iph2->ph1->rmconf->esp_frag; #endif - } else { - /* Remove port information, that SA doesn't use it */ - set_port(sa_args.src, 0); - set_port(sa_args.dst, 0); } - -#else - /* Remove port information, it is not used without NAT-T */ +#endif + /* Always remove port information, it will be sent in + * SADB_X_EXT_NAT_T_[S|D]PORT if needed */ set_port(sa_args.src, 0); set_port(sa_args.dst, 0); -#endif /* more info to fill in */ sa_args.spi = pr->spi_p; @@ -1596,6 +1623,7 @@ pk_recvexpire(mhp) } msg = (struct sadb_msg *)mhp[0]; sa = (struct sadb_sa *)mhp[SADB_EXT_SA]; + pk_fixup_sa_addresses(mhp); src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]); dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]); @@ -1721,6 +1749,7 @@ pk_recvacquire(mhp) } msg = (struct sadb_msg *)mhp[0]; xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY]; + pk_fixup_sa_addresses(mhp); sp_src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]); sp_dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]); @@ -1971,6 +2000,7 @@ pk_recvdelete(mhp) } msg = (struct sadb_msg *)mhp[0]; sa = (struct sadb_sa *)mhp[SADB_EXT_SA]; + pk_fixup_sa_addresses(mhp); src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]); dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]); @@ -2709,7 +2739,6 @@ pk_recvspddump(mhp) return -1; } msg = (struct sadb_msg *)mhp[0]; - saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC]; daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST]; xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY]; diff --git a/src/racoon/pfkey.h b/src/racoon/pfkey.h index a3acd1c..f1b037d 100644 --- a/src/racoon/pfkey.h +++ b/src/racoon/pfkey.h @@ -52,6 +52,7 @@ extern struct pfkey_st *pfkey_getpst __P((caddr_t *, int, int)); extern int pk_checkalg __P((int, int, int)); struct ph2handle; +extern void pk_fixup_sa_addresses __P((caddr_t *mhp)); extern int pk_sendgetspi __P((struct ph2handle *)); extern int pk_sendupdate __P((struct ph2handle *)); extern int pk_sendadd __P((struct ph2handle *));