Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Fix unexpected failure when ipsecif(4) over IPv6 is chan...



details:   https://anonhg.NetBSD.org/src/rev/e51927d71d5f
branches:  trunk
changeset: 321796:e51927d71d5f
user:      knakahara <knakahara%NetBSD.org@localhost>
date:      Fri Apr 06 10:38:53 2018 +0000

description:
Fix unexpected failure when ipsecif(4) over IPv6 is changed port number only.

Here is an example of the operation which causes this problem.
    # ifconfig ipsec0 create link0
    # ifconfig ipsec0 tunnel fc00:1001::2,4500 fc00:1001::1,4501
    # ifconfig ipsec0 tunnel fc00:1001::2,4500 fc00:1001::1,4502

diffstat:

 sys/net/if_ipsec.c     |  37 ++++++++++++++++++++++++------
 sys/netipsec/ipsecif.c |  59 +++++++++++++++++++++++++++++++++++++++++++++----
 sys/netipsec/ipsecif.h |   3 +-
 3 files changed, 85 insertions(+), 14 deletions(-)

diffs (176 lines):

diff -r dd7f6186c3b3 -r e51927d71d5f sys/net/if_ipsec.c
--- a/sys/net/if_ipsec.c        Fri Apr 06 10:31:35 2018 +0000
+++ b/sys/net/if_ipsec.c        Fri Apr 06 10:38:53 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_ipsec.c,v 1.10 2018/04/06 09:30:09 knakahara Exp $  */
+/*     $NetBSD: if_ipsec.c,v 1.11 2018/04/06 10:38:53 knakahara Exp $  */
 
 /*
  * Copyright (c) 2017 Internet Initiative Japan Inc.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_ipsec.c,v 1.10 2018/04/06 09:30:09 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_ipsec.c,v 1.11 2018/04/06 10:38:53 knakahara Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -280,7 +280,7 @@
 int
 if_ipsec_encap_func(struct mbuf *m, int off, int proto, void *arg)
 {
-       struct ip ip;
+       uint8_t v;
        struct ipsec_softc *sc;
        struct ipsec_variant *var = NULL;
        struct psref psref;
@@ -304,18 +304,39 @@
                goto out;
        }
 
-       if (m->m_pkthdr.len < sizeof(ip))
-               goto out;
+       m_copydata(m, 0, sizeof(v), &v);
+       v = (v >> 4) & 0xff;  /* Get the IP version number. */
 
-       m_copydata(m, 0, sizeof(ip), &ip);
-       switch (ip.ip_v) {
+       switch (v) {
 #ifdef INET
-       case IPVERSION:
+       case IPVERSION: {
+               struct ip ip;
+
+               if (m->m_pkthdr.len < sizeof(ip))
+                       goto out;
+
+               m_copydata(m, 0, sizeof(ip), &ip);
                if (var->iv_psrc->sa_family != AF_INET ||
                    var->iv_pdst->sa_family != AF_INET)
                        goto out;
                ret = ipsecif4_encap_func(m, &ip, var);
                break;
+       }
+#endif
+#ifdef INET6
+       case (IPV6_VERSION >> 4): {
+               struct ip6_hdr ip6;
+
+               if (m->m_pkthdr.len < sizeof(ip6))
+                       goto out;
+
+               m_copydata(m, 0, sizeof(ip6), &ip6);
+               if (var->iv_psrc->sa_family != AF_INET6 ||
+                   var->iv_pdst->sa_family != AF_INET6)
+                       goto out;
+               ret = ipsecif6_encap_func(m, &ip6, var);
+               break;
+       }
 #endif
        default:
                goto out;
diff -r dd7f6186c3b3 -r e51927d71d5f sys/netipsec/ipsecif.c
--- a/sys/netipsec/ipsecif.c    Fri Apr 06 10:31:35 2018 +0000
+++ b/sys/netipsec/ipsecif.c    Fri Apr 06 10:38:53 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ipsecif.c,v 1.6 2018/04/06 10:31:35 knakahara Exp $  */
+/*     $NetBSD: ipsecif.c,v 1.7 2018/04/06 10:38:53 knakahara Exp $  */
 
 /*
  * Copyright (c) 2017 Internet Initiative Japan Inc.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ipsecif.c,v 1.6 2018/04/06 10:31:35 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ipsecif.c,v 1.7 2018/04/06 10:38:53 knakahara Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -412,6 +412,57 @@
 }
 
 #ifdef INET6
+int
+ipsecif6_encap_func(struct mbuf *m, struct ip6_hdr *ip6, struct ipsec_variant *var)
+{
+       struct m_tag *mtag;
+       struct sockaddr_in6 *src, *dst;
+       u_int16_t src_port = 0;
+       u_int16_t dst_port = 0;
+
+       KASSERT(var != NULL);
+
+       src = satosin6(var->iv_psrc);
+       dst = satosin6(var->iv_pdst);
+       mtag = m_tag_find(m, PACKET_TAG_IPSEC_NAT_T_PORTS, NULL);
+       if (mtag) {
+               u_int16_t *ports;
+
+               ports = (u_int16_t *)(mtag + 1);
+               src_port = ports[0];
+               dst_port = ports[1];
+       }
+
+       /* address match */
+       if (!IN6_ARE_ADDR_EQUAL(&src->sin6_addr, &ip6->ip6_dst) ||
+           !IN6_ARE_ADDR_EQUAL(&dst->sin6_addr, &ip6->ip6_src))
+               return 0;
+
+       /* UDP encap? */
+       if (mtag == NULL && var->iv_sport == 0 && var->iv_dport == 0)
+               goto match;
+
+       /* port match */
+       if (src_port != var->iv_dport ||
+           dst_port != var->iv_sport) {
+#ifdef DEBUG
+               printf("%s: port mismatch: pkt(%u, %u), if(%u, %u)\n",
+                   __func__, ntohs(src_port), ntohs(dst_port),
+                   ntohs(var->iv_sport), ntohs(var->iv_dport));
+#endif
+               return 0;
+       }
+
+match:
+       /*
+        * hide NAT-T information from encapsulated traffics.
+        * they don't know about IPsec.
+        */
+       if (mtag)
+               m_tag_delete(m, mtag);
+       return sizeof(src->sin6_addr) + sizeof(dst->sin6_addr);
+}
+
 static int
 ipsecif6_output(struct ipsec_variant *var, int family, struct mbuf *m)
 {
@@ -841,9 +892,7 @@
        mask6.sin6_addr.s6_addr32[0] = mask6.sin6_addr.s6_addr32[1] =
        mask6.sin6_addr.s6_addr32[2] = mask6.sin6_addr.s6_addr32[3] = ~0;
 
-       var->iv_encap_cookie6 = encap_attach(AF_INET6, -1,
-           var->iv_psrc, (struct sockaddr *)&mask6,
-           var->iv_pdst, (struct sockaddr *)&mask6,
+       var->iv_encap_cookie6 = encap_attach_func(AF_INET6, -1, if_ipsec_encap_func,
            &ipsecif6_encapsw, sc);
        if (var->iv_encap_cookie6 == NULL)
                return EEXIST;
diff -r dd7f6186c3b3 -r e51927d71d5f sys/netipsec/ipsecif.h
--- a/sys/netipsec/ipsecif.h    Fri Apr 06 10:31:35 2018 +0000
+++ b/sys/netipsec/ipsecif.h    Fri Apr 06 10:38:53 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ipsecif.h,v 1.1 2018/01/10 10:56:30 knakahara Exp $  */
+/*     $NetBSD: ipsecif.h,v 1.2 2018/04/06 10:38:53 knakahara Exp $  */
 
 /*
  * Copyright (c) 2017 Internet Initiative Japan Inc.
@@ -39,6 +39,7 @@
 int ipsecif4_attach(struct ipsec_variant *);
 int ipsecif4_detach(struct ipsec_variant *);
 
+int ipsecif6_encap_func(struct mbuf *, struct ip6_hdr *, struct ipsec_variant *);
 int ipsecif6_attach(struct ipsec_variant *);
 int ipsecif6_detach(struct ipsec_variant *);
 void *ipsecif6_ctlinput(int, const struct sockaddr *, void *, void *);



Home | Main Index | Thread Index | Old Index