Source-Changes-HG archive

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

src: Pull up following revision(s) (requested by knakahara in ti...



details:   https://anonhg.NetBSD.org/src/rev/6b255c4fbed8
branches:  netbsd-8
changeset: 317980:6b255c4fbed8
user:      martin <martin%NetBSD.org@localhost>
date:      Mon Apr 09 17:01:20 2018 +0000
description:
Pull up following revision(s) (requested by knakahara in ticket #714):

        sys/net/if_ipsec.c: revision 1.8 - 1.11
        sys/netipsec/ipsecif.h: revision 1.2
        sys/netipsec/ipsecif.c: revision 1.6,1.7

fix ipsec(4) encap_lock leak.

fix ipsecif(4) unmatch curlwp_bind.

fix ipsecif(4) stack overflow.

Add IPv4 ID when the ipsecif(4) packet can be fragmented. Implemented by hsuenaga@IIJ and ohishi@IIJ, thanks.
This modification reduces packet loss of fragmented packets on a
network where reordering occurs.

Alghough this modification has been applied, IPv4 ID is not set for
the packet smaller then IP_MINFRAGSIZE. According to RFC 6864, that
must not cause problems.

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     |  48 ++++++++++++++++++++++++++++--------
 sys/netipsec/ipsecif.c |  64 +++++++++++++++++++++++++++++++++++++++++++++----
 sys/netipsec/ipsecif.h |   3 +-
 3 files changed, 97 insertions(+), 18 deletions(-)

diffs (235 lines):

diff -r 660a847bde45 -r 6b255c4fbed8 sys/net/if_ipsec.c
--- a/sys/net/if_ipsec.c        Mon Apr 09 16:46:34 2018 +0000
+++ b/sys/net/if_ipsec.c        Mon Apr 09 17:01:20 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_ipsec.c,v 1.3.2.4 2018/03/13 15:34:33 martin Exp $  */
+/*     $NetBSD: if_ipsec.c,v 1.3.2.5 2018/04/09 17:01:20 martin 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.3.2.4 2018/03/13 15:34:33 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_ipsec.c,v 1.3.2.5 2018/04/09 17:01:20 martin Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -76,6 +76,7 @@
 #include <net/pfkeyv2.h>
 
 #include <netipsec/key.h>
+#include <netipsec/keydb.h> /* for union sockaddr_union */
 #include <netipsec/ipsec.h>
 #include <netipsec/ipsecif.h>
 
@@ -279,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;
@@ -303,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;
@@ -637,6 +659,7 @@
                error = if_ipsec_set_tunnel(&sc->ipsec_if, src, dst);
                if (error)
                        goto bad;
+               curlwp_bindx(bound);
                break;
 
        case SIOCDIFPHYADDR:
@@ -769,6 +792,7 @@
                        error = if_ipsec_ensure_flags(&sc->ipsec_if, oflags);
                        if (error)
                                goto bad;
+                       curlwp_bindx(bound);
                }
                break;
        }
@@ -1166,6 +1190,7 @@
        if (if_ipsec_variant_is_unconfigured(ovar)) {
                /* nothing to do */
                mutex_exit(&sc->ipsec_lock);
+               encap_lock_exit();
                return 0;
        }
 
@@ -1337,10 +1362,11 @@
        if (port == 0) {
                if_ipsec_add_mbuf_optalign(m0, addr, addr->sa_len, align);
        } else {
-               struct sockaddr addrport;
+               union sockaddr_union addrport_u;
+               struct sockaddr *addrport = &addrport_u.sa;
 
-               if_ipsec_set_addr_port(&addrport, addr, port);
-               if_ipsec_add_mbuf_optalign(m0, &addrport, addrport.sa_len, align);
+               if_ipsec_set_addr_port(addrport, addr, port);
+               if_ipsec_add_mbuf_optalign(m0, addrport, addrport->sa_len, align);
        }
 }
 
diff -r 660a847bde45 -r 6b255c4fbed8 sys/netipsec/ipsecif.c
--- a/sys/netipsec/ipsecif.c    Mon Apr 09 16:46:34 2018 +0000
+++ b/sys/netipsec/ipsecif.c    Mon Apr 09 17:01:20 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ipsecif.c,v 1.1.2.5 2018/03/13 15:34:33 martin Exp $  */
+/*     $NetBSD: ipsecif.c,v 1.1.2.6 2018/04/09 17:01:20 martin Exp $  */
 
 /*
  * Copyright (c) 2017 Internet Initiative Japan Inc.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ipsecif.c,v 1.1.2.5 2018/03/13 15:34:33 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ipsecif.c,v 1.1.2.6 2018/04/09 17:01:20 martin Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -135,7 +135,10 @@
        ip = mtod(m, struct ip *);
        ip->ip_v = IPVERSION;
        ip->ip_off = htons(0);
-       ip->ip_id = 0;
+       if (m->m_pkthdr.len < IP_MINFRAGSIZE)
+               ip->ip_id = 0;
+       else
+               ip->ip_id = ip_newid(NULL);
        ip->ip_hl = sizeof(*ip) >> 2;
        if (ip_ipsec_copy_tos)
                ip->ip_tos = tos;
@@ -410,6 +413,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)
 {
@@ -844,9 +898,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 660a847bde45 -r 6b255c4fbed8 sys/netipsec/ipsecif.h
--- a/sys/netipsec/ipsecif.h    Mon Apr 09 16:46:34 2018 +0000
+++ b/sys/netipsec/ipsecif.h    Mon Apr 09 17:01:20 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ipsecif.h,v 1.1.2.2 2018/02/11 21:17:34 snj Exp $  */
+/*     $NetBSD: ipsecif.h,v 1.1.2.3 2018/04/09 17:01:20 martin 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