Index: src/libipsec/libpfkey.h =================================================================== RCS file: /cvsroot/ipsec-tools/ipsec-tools/src/libipsec/libpfkey.h,v retrieving revision 1.7 diff -U4 -r1.7 libpfkey.h --- src/libipsec/libpfkey.h 7 Jun 2004 09:18:46 -0000 1.7 +++ src/libipsec/libpfkey.h 6 Jan 2005 22:23:44 -0000 @@ -75,18 +75,18 @@ int pfkey_send_update_nat __P((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_int64_t, u_int64_t, u_int64_t, u_int32_t, - u_int8_t, u_int16_t, u_int16_t, struct sockaddr *)); + u_int8_t, u_int16_t, u_int16_t, struct sockaddr *, u_int16_t)); int pfkey_send_add __P((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_int64_t, u_int64_t, u_int64_t, u_int32_t)); int pfkey_send_add_nat __P((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_int64_t, u_int64_t, u_int64_t, u_int32_t, - u_int8_t, u_int16_t, u_int16_t, struct sockaddr *)); + u_int8_t, u_int16_t, u_int16_t, struct sockaddr *, u_int16_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 *)); Index: src/libipsec/pfkey.c =================================================================== RCS file: /cvsroot/ipsec-tools/ipsec-tools/src/libipsec/pfkey.c,v retrieving revision 1.10 diff -U4 -r1.10 pfkey.c --- src/libipsec/pfkey.c 13 Sep 2004 14:09:18 -0000 1.10 +++ src/libipsec/pfkey.c 6 Jan 2005 22:23:44 -0000 @@ -61,9 +61,9 @@ 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, u_int32_t, u_int32_t, u_int32_t, - u_int8_t, u_int16_t, u_int16_t, struct sockaddr *)); + u_int8_t, u_int16_t, u_int16_t, struct sockaddr *, u_int16_t)); 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, @@ -85,8 +85,11 @@ #ifdef SADB_X_EXT_NAT_T_TYPE static caddr_t pfkey_set_natt_type __P((caddr_t, caddr_t, u_int, u_int8_t)); static caddr_t pfkey_set_natt_port __P((caddr_t, caddr_t, u_int, u_int16_t)); #endif +#ifdef SADB_X_EXT_NAT_T_FRAG +static caddr_t pfkey_set_natt_frag __P((caddr_t, caddr_t, u_int, u_int16_t)); +#endif /* * make and search supported algorithm structure. */ @@ -499,9 +502,9 @@ 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, 0, 0, NULL)) < 0) + 0, 0, 0, NULL, 0)) < 0) return -1; return len; } @@ -510,9 +513,10 @@ int pfkey_send_update_nat(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, - l_natt_type, l_natt_sport, l_natt_dport, l_natt_oa) + l_natt_type, l_natt_sport, l_natt_dport, l_natt_oa, + l_natt_frag) int so; u_int satype, mode, wsize; struct sockaddr *src, *dst; u_int32_t spi, reqid; @@ -523,15 +527,17 @@ u_int32_t seq; u_int8_t l_natt_type; u_int16_t l_natt_sport, l_natt_dport; struct sockaddr *l_natt_oa; + u_int16_t l_natt_frag; { 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, - l_natt_type, l_natt_sport, l_natt_dport, l_natt_oa)) < 0) + l_natt_type, l_natt_sport, l_natt_dport, l_natt_oa, + l_natt_frag)) < 0) return -1; return len; } @@ -562,9 +568,9 @@ 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, 0, 0, NULL)) < 0) + 0, 0, 0, NULL, 0)) < 0) return -1; return len; } @@ -573,9 +579,10 @@ int pfkey_send_add_nat(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, - l_natt_type, l_natt_sport, l_natt_dport, l_natt_oa) + l_natt_type, l_natt_sport, l_natt_dport, l_natt_oa, + l_natt_frag) int so; u_int satype, mode, wsize; struct sockaddr *src, *dst; u_int32_t spi, reqid; @@ -586,15 +593,17 @@ u_int32_t seq; u_int8_t l_natt_type; u_int16_t l_natt_sport, l_natt_dport; struct sockaddr *l_natt_oa; + u_int16_t l_natt_frag; { 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, - l_natt_type, l_natt_sport, l_natt_dport, l_natt_oa)) < 0) + l_natt_type, l_natt_sport, l_natt_dport, l_natt_oa, + l_natt_frag)) < 0) return -1; return len; } @@ -1182,9 +1191,10 @@ 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, - l_natt_type, l_natt_sport, l_natt_dport, l_natt_oa) + l_natt_type, l_natt_sport, l_natt_dport, l_natt_oa, + l_natt_frag) int so; u_int type, satype, mode; struct sockaddr *src, *dst, *l_natt_oa; u_int32_t spi, reqid; @@ -1193,8 +1203,9 @@ u_int e_type, e_keylen, a_type, a_keylen, flags; u_int32_t l_alloc, l_bytes, l_addtime, l_usetime, seq; u_int16_t l_natt_sport, l_natt_dport; u_int8_t l_natt_type; + u_int16_t l_natt_frag; { struct sadb_msg *newmsg; int len; caddr_t p; @@ -1283,8 +1294,12 @@ len += sizeof(struct sadb_x_nat_t_port); if (l_natt_oa) len += sizeof(struct sadb_address) + PFKEY_ALIGN8(sysdep_sa_len(l_natt_oa)); +#ifdef SADB_X_EXT_NAT_T_FRAG + if (l_natt_frag) + len += sizeof(struct sadb_x_nat_t_frag); +#endif } #endif if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) { @@ -1385,8 +1400,19 @@ free(newmsg); return -1; } } + + if (l_natt_frag) { +#ifdef SADB_X_EXT_NAT_T_FRAG + p = pfkey_set_natt_frag(p, ep, SADB_X_EXT_NAT_T_FRAG, + l_natt_frag); + if (!p) { + free(newmsg); + return -1; + } +#endif + } } #endif if (p != ep) { @@ -2316,4 +2342,30 @@ return(buf + len); } #endif + +#ifdef SADB_X_EXT_NAT_T_FRAG +static caddr_t +pfkey_set_natt_frag(buf, lim, type, l_natt_frag) + caddr_t buf; + caddr_t lim; + u_int type; + u_int16_t l_natt_frag; +{ + struct sadb_x_nat_t_frag *p; + u_int len; + + p = (struct sadb_x_nat_t_frag *)buf; + len = sizeof(struct sadb_x_nat_t_frag); + + if (buf + len > lim) + return NULL; + + memset(p, 0, len); + p->sadb_x_nat_t_frag_len = PFKEY_UNIT64(len); + p->sadb_x_nat_t_frag_exttype = type; + p->sadb_x_nat_t_frag_fraglen = l_natt_frag; + + return(buf + len); +} +#endif Index: src/racoon/cfparse.y =================================================================== RCS file: /cvsroot/ipsec-tools/ipsec-tools/src/racoon/cfparse.y,v retrieving revision 1.32 diff -U4 -r1.32 cfparse.y --- src/racoon/cfparse.y 3 Jan 2005 22:18:04 -0000 1.32 +++ src/racoon/cfparse.y 6 Jan 2005 22:23:44 -0000 @@ -217,9 +217,9 @@ %token GSSAPI_ID %token COMPLEX_BUNDLE %token DPD DPD_DELAY DPD_RETRY DPD_MAXFAIL -%token PREFIX PORT PORTANY UL_PROTO ANY IKE_FRAG MODE_CFG +%token PREFIX PORT PORTANY UL_PROTO ANY IKE_FRAG ESP_FRAG MODE_CFG %token PFS_GROUP LIFETIME LIFETYPE_TIME LIFETYPE_BYTE STRENGTH %token SCRIPT PHASE1_UP PHASE1_DOWN @@ -1237,8 +1237,15 @@ } dh_group_num EOS | PASSIVE SWITCH { cur_rmconf->passive = $2; } EOS | IKE_FRAG SWITCH { cur_rmconf->ike_frag = $2; } EOS + | ESP_FRAG NUMBER { +#ifdef SADB_X_EXT_NAT_T_FRAG + cur_rmconf->esp_frag = $2; +#else + yywarn("Your kernel does not support esp_frag"); +#endif + } EOS | SCRIPT QUOTEDSTRING PHASE1_UP { cur_rmconf->script[SCRIPT_PHASE1_UP] = script_path_add(vdup($2)); } EOS Index: src/racoon/cftoken.l =================================================================== RCS file: /cvsroot/ipsec-tools/ipsec-tools/src/racoon/cftoken.l,v retrieving revision 1.28 diff -U4 -r1.28 cftoken.l --- src/racoon/cftoken.l 3 Jan 2005 22:18:04 -0000 1.28 +++ src/racoon/cftoken.l 6 Jan 2005 22:23:44 -0000 @@ -311,8 +311,9 @@ dpd_delay { YYD; return(DPD_DELAY); } dpd_retry { YYD; return(DPD_RETRY); } dpd_maxfail { YYD; return(DPD_MAXFAIL); } ike_frag { YYD; return(IKE_FRAG); } +esp_frag { YYD; return(ESP_FRAG); } script { YYD; return(SCRIPT); } phase1_up { YYD; return(PHASE1_UP); } phase1_down { YYD; return(PHASE1_DOWN); } mode_cfg { YYD; return(MODE_CFG); } Index: src/racoon/nattraversal.h =================================================================== RCS file: /cvsroot/ipsec-tools/ipsec-tools/src/racoon/nattraversal.h,v retrieving revision 1.5 diff -U4 -r1.5 nattraversal.h --- src/racoon/nattraversal.h 7 Jun 2004 09:18:47 -0000 1.5 +++ src/racoon/nattraversal.h 6 Jan 2005 22:23:44 -0000 @@ -64,8 +64,9 @@ u_int8_t type; u_int16_t sport; u_int16_t dport; struct sockaddr *oa; + u_int16_t frag; }; int natt_vendorid (int vid); vchar_t *natt_hash_addr (struct ph1handle *iph1, struct sockaddr *addr); Index: src/racoon/pfkey.c =================================================================== RCS file: /cvsroot/ipsec-tools/ipsec-tools/src/racoon/pfkey.c,v retrieving revision 1.28 diff -U4 -r1.28 pfkey.c --- src/racoon/pfkey.c 29 Dec 2004 23:11:11 -0000 1.28 +++ src/racoon/pfkey.c 6 Jan 2005 22:23:45 -0000 @@ -1055,8 +1055,9 @@ natt.type = UDP_ENCAP_ESPINUDP; natt.sport = extract_port (iph2->ph1->remote); natt.dport = extract_port (iph2->ph1->local); natt.oa = NULL; // FIXME: Here comes OA!!! + natt.frag = iph2->ph1->rmconf->esp_frag; } else memset (&natt, 0, sizeof (natt)); @@ -1072,9 +1073,10 @@ pr->keymat->v, e_type, e_keylen, a_type, a_keylen, flags, 0, lifebyte, iph2->approval->lifetime, 0, iph2->seq, - natt.type, natt.sport, natt.dport, natt.oa) < 0) { + natt.type, natt.sport, natt.dport, natt.oa, + natt.frag) < 0) { plog(LLV_ERROR, LOCATION, NULL, "libipsec failed send update (%s)\n", ipsec_strerror()); return -1; @@ -1326,8 +1328,9 @@ natt.type = UDP_ENCAP_ESPINUDP; natt.sport = extract_port (iph2->ph1->local); natt.dport = extract_port (iph2->ph1->remote); natt.oa = NULL; // FIXME: Here comes OA!!! + natt.frag = iph2->ph1->rmconf->esp_frag; } else memset (&natt, 0, sizeof (natt)); @@ -1343,9 +1346,10 @@ pr->keymat_p->v, e_type, e_keylen, a_type, a_keylen, flags, 0, lifebyte, iph2->approval->lifetime, 0, iph2->seq, - natt.type, natt.sport, natt.dport, natt.oa) < 0) { + natt.type, natt.sport, natt.dport, natt.oa, + natt.frag) < 0) { plog(LLV_ERROR, LOCATION, NULL, "libipsec failed send add (%s)\n", ipsec_strerror()); return -1; Index: src/racoon/racoon.conf.5 =================================================================== RCS file: /cvsroot/ipsec-tools/ipsec-tools/src/racoon/racoon.conf.5,v retrieving revision 1.22 diff -U4 -r1.22 racoon.conf.5 --- src/racoon/racoon.conf.5 3 Jan 2005 22:18:04 -0000 1.22 +++ src/racoon/racoon.conf.5 6 Jan 2005 22:23:45 -0000 @@ -471,8 +471,23 @@ broken firewalls that do not work with fragmented UDP packets. IKE fragmentation is always enabled on the sender-side, and it is used if the peer advertise itself as IKE fragmentation capable. .\" +.It esp_frag Ar fraglen ; +This option is only revelant if you use NAT traversal in tunnel mode. Its +purpose is to workaround broken DSL routers that reject UDP fragments, +by fragmenting the IP packets before ESP encapsulation. The result is +ESP over UDP of fragmented packets instead of fragmented ESP over +UDP packets. +.Ar fraglen +is the maximum size of the fragments. 552 should work anywhere, +but the higher +.Ar fraglen +is, the better the performances are. +.Pp +Note that because PMTU discovery is broken on many sites, you will have to +use MSS clamping if you want TCP to work correctly. +.\" .It Ic initial_contact (on \(ba off) ; enable this to send an INITIAL-CONTACT message. The default value is .Ic on . Index: src/racoon/remoteconf.c =================================================================== RCS file: /cvsroot/ipsec-tools/ipsec-tools/src/racoon/remoteconf.c,v retrieving revision 1.25 diff -U4 -r1.25 remoteconf.c --- src/racoon/remoteconf.c 29 Dec 2004 23:11:11 -0000 1.25 +++ src/racoon/remoteconf.c 6 Jan 2005 22:23:45 -0000 @@ -36,8 +36,10 @@ #include #include #include +#include +#include #ifndef HAVE_NETINET6_IPSEC #include #else @@ -185,8 +187,9 @@ new->idvl_p = genlist_init(); new->nonce_size = DEFAULT_NONCE_SIZE; new->passive = FALSE; new->ike_frag = FALSE; + new->esp_frag = IP_MAXPACKET; new->ini_contact = TRUE; new->mode_cfg = FALSE; new->pcheck_level = PROP_CHECK_STRICT; new->verify_identifier = FALSE; @@ -542,8 +545,9 @@ plog(LLV_INFO, LOCATION, NULL, "\tpassive %s;\n", s_switch (p->passive)); plog(LLV_INFO, LOCATION, NULL, "\tike_frag %s;\n", s_switch (p->ike_frag)); + plog(LLV_INFO, LOCATION, NULL, "\tesp_frag %d;\n", p->esp_frag); plog(LLV_INFO, LOCATION, NULL, "\tinitial_contact %s;\n", s_switch (p->ini_contact)); plog(LLV_INFO, LOCATION, NULL, "\tgenerate_policy %s;\n", s_switch (p->gen_policy)); Index: src/racoon/remoteconf.h =================================================================== RCS file: /cvsroot/ipsec-tools/ipsec-tools/src/racoon/remoteconf.h,v retrieving revision 1.18 diff -U4 -r1.18 remoteconf.h --- src/racoon/remoteconf.h 29 Dec 2004 23:11:12 -0000 1.18 +++ src/racoon/remoteconf.h 6 Jan 2005 22:23:45 -0000 @@ -80,8 +80,9 @@ int verify_identifier; /* vefify the peer's identifier */ int nonce_size; /* the number of bytes of nonce */ int passive; /* never initiate */ int ike_frag; /* IKE fragmentation */ + int esp_frag; /* ESP fragmentation */ int mode_cfg; /* Gets config through mode config */ int support_proxy; /* support mip6/proxy */ int gen_policy; /* generate policy if no policy found */ int ini_contact; /* initial contact */