Hi,

I have an IPsec setup that uses IPv6 with IPsec udpencap.  In udpencap
the "next protocol" field is set to UDP.  After decapsulation that
field is set to "IPIP".  Unfortunately the udp decapsulation always
uses the IPv4 offset of "next protocol".  This means the other layers
will write "IPIP" onto the wrong offset.

This is visible in tcpdump where the "next protocol" field has the old
value of 17 (UDP), while 04 (IPIP) overwrites a part of the IPv6 source
address.

Patrick

diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index ac66f0b..e27161e 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -183,7 +183,7 @@ udp_input(struct mbuf *m, ...)
        struct m_tag *mtag;
        struct tdb_ident *tdbi;
        struct tdb *tdb;
-       int error;
+       int error, protoff;
 #endif /* IPSEC */
 #if defined(IPSEC) || defined(PIPEX)
        u_int32_t ipsecflowinfo = 0;
@@ -202,12 +202,18 @@ udp_input(struct mbuf *m, ...)
                ip6 = NULL;
 #endif /* INET6 */
                srcsa.sa.sa_family = AF_INET;
+#ifdef IPSEC
+               protoff = offsetof(struct ip, ip_p);
+#endif /* IPSEC */
                break;
 #ifdef INET6
        case 6:
                ip = NULL;
                ip6 = mtod(m, struct ip6_hdr *);
                srcsa.sa.sa_family = AF_INET6;
+#ifdef IPSEC
+               protoff = offsetof(struct ip6_hdr, ip6_nxt);
+#endif /* IPSEC */
                break;
 #endif /* INET6 */
        default:
@@ -343,7 +349,7 @@ udp_input(struct mbuf *m, ...)
                        skip -= sizeof(struct udphdr);
 
                        espstat.esps_udpencin++;
-                       ipsec_common_input(m, skip, offsetof(struct ip, ip_p),
+                       ipsec_common_input(m, skip, protoff,
                            srcsa.sa.sa_family, IPPROTO_ESP, 1);
                        return;
                }

Reply via email to