On 22/02/17(Wed) 18:10, Alexander Bluhm wrote:
> On Wed, Feb 22, 2017 at 05:06:34PM +0100, Martin Pieuchot wrote:
> [...]
> > -ip6_ours(struct mbuf *m, int off, int nxt)
> > +ip6_ours(struct mbuf *m)
> > +{
> > +   int off, nxt;
> > +
> > +   KERNEL_ASSERT_LOCKED();
> > +
> > +   if (ip6_hbhchcheck(m, &off, &nxt, NULL))
> > +           return;
> > +
> > +   ip6_local(m, off, nxt);
> > +}
> 
> When you unlock the forwarding path, there must be a KERNEL_LOCK()
> around ip6_local().  Or do you plan to rewrite this function anyway?

I plan to rewrite the function to enqueue mbufs on ip6intrq.  See my
diff "IPv4 forwarding w/o KERNEL_LOCK()", it's the same but for legacy
IP.

Here's an updated diff that should address all your points.

Index: netinet/ipsec_input.c
===================================================================
RCS file: /cvs/src/sys/netinet/ipsec_input.c,v
retrieving revision 1.144
diff -u -p -r1.144 ipsec_input.c
--- netinet/ipsec_input.c       8 Feb 2017 12:37:43 -0000       1.144
+++ netinet/ipsec_input.c       22 Feb 2017 17:23:06 -0000
@@ -592,7 +592,7 @@ ipsec_common_input_cb(struct mbuf *m, st
                return;
 #ifdef INET6
        case AF_INET6:
-               ip6_ours(m, skip, prot);
+               ip6_local(m, skip, prot);
                return;
 #endif /* INET6 */
        default:
Index: netinet6/ip6_input.c
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_input.c,v
retrieving revision 1.179
diff -u -p -r1.179 ip6_input.c
--- netinet6/ip6_input.c        8 Feb 2017 12:37:43 -0000       1.179
+++ netinet6/ip6_input.c        22 Feb 2017 17:27:36 -0000
@@ -119,6 +119,7 @@ struct niqueue ip6intrq = NIQUEUE_INITIA
 
 struct cpumem *ip6counters;
 
+void ip6_ours(struct mbuf *);
 int ip6_check_rh0hdr(struct mbuf *, int *);
 int ip6_hbhchcheck(struct mbuf *, int *, int *, int *);
 int ip6_hopopts_input(u_int32_t *, u_int32_t *, struct mbuf **, int *);
@@ -180,8 +181,8 @@ ip6_input(struct mbuf *m)
        struct ip6_hdr *ip6;
        struct sockaddr_in6 sin6;
        struct rtentry *rt = NULL;
-       int off, nxt, ours = 0;
        u_int16_t src_scope, dst_scope;
+       int off, nxt, ours = 0;
 #if NPF > 0
        struct in6_addr odst;
 #endif
@@ -339,14 +340,14 @@ ip6_input(struct mbuf *m)
 
        if (IN6_IS_ADDR_LOOPBACK(&ip6->ip6_src) ||
            IN6_IS_ADDR_LOOPBACK(&ip6->ip6_dst)) {
-               ours = 1;
-               goto hbhcheck;
+               ip6_ours(m);
+               goto out;
        }
 
 #if NPF > 0
        if (pf_ouraddr(m) == 1) {
-               ours = 1;
-               goto hbhcheck;
+               ip6_ours(m);
+               goto out;
        }
 #endif
 
@@ -383,14 +384,16 @@ ip6_input(struct mbuf *m)
                         * ip6_mforward() returns a non-zero value, the packet
                         * must be discarded, else it may be accepted below.
                         */
+                       KERNEL_LOCK();
                        if (ip6_mforward(ip6, ifp, m)) {
                                ip6stat_inc(ip6s_cantforward);
-                               goto bad;
+                               m_freem(m);
+                       } else if (ours) {
+                               ip6_local(m, off, nxt);
+                       } else {
+                               m_freem(m);
                        }
-
-                       if (!ours)
-                               goto bad;
-                       ip6_ours(m, off, nxt);
+                       KERNEL_UNLOCK();
                        goto out;
                }
 #endif
@@ -400,7 +403,8 @@ ip6_input(struct mbuf *m)
                                ip6stat_inc(ip6s_cantforward);
                        goto bad;
                }
-               goto hbhcheck;
+               ip6_ours(m);
+               goto out;
        }
 
 
@@ -438,9 +442,8 @@ ip6_input(struct mbuf *m)
 
                        goto bad;
                } else {
-                       /* this address is ready */
-                       ours = 1;
-                       goto hbhcheck;
+                       ip6_ours(m);
+                       goto out;
                }
        }
 
@@ -459,19 +462,16 @@ ip6_input(struct mbuf *m)
                goto bad;
        }
 
-  hbhcheck:
-
        if (ip6_hbhchcheck(m, &off, &nxt, &ours))
                goto out;
 
        if (ours) {
-               ip6_ours(m, off, nxt);
+               KERNEL_LOCK();
+               ip6_local(m, off, nxt);
+               KERNEL_UNLOCK();
                goto out;
        }
 
-       /*
-        * Forward if desirable.
-        */
        ip6_forward(m, rt, srcrt);
        if_put(ifp);
        return;
@@ -483,10 +483,23 @@ ip6_input(struct mbuf *m)
 }
 
 void
-ip6_ours(struct mbuf *m, int off, int nxt)
+ip6_ours(struct mbuf *m)
+{
+       int off, nxt;
+
+       if (ip6_hbhchcheck(m, &off, &nxt, NULL))
+               return;
+
+       ip6_local(m, off, nxt);
+}
+
+void
+ip6_local(struct mbuf *m, int off, int nxt)
 {
        int nest = 0;
 
+       KERNEL_ASSERT_LOCKED();
+
        /* pf might have changed things */
        in6_proto_cksum_out(m, NULL);
 
@@ -582,7 +595,7 @@ ip6_hbhchcheck(struct mbuf *m, int *offp
                 * accept the packet if a router alert option is included
                 * and we act as an IPv6 router.
                 */
-               if (rtalert != ~0 && ip6_forwarding)
+               if (rtalert != ~0 && ip6_forwarding && oursp != NULL)
                        *oursp = 1;
        } else
                *nxtp = ip6->ip6_nxt;
Index: netinet6/ip6_var.h
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_var.h,v
retrieving revision 1.68
diff -u -p -r1.68 ip6_var.h
--- netinet6/ip6_var.h  8 Feb 2017 12:37:43 -0000       1.68
+++ netinet6/ip6_var.h  22 Feb 2017 17:25:35 -0000
@@ -304,7 +304,7 @@ int icmp6_ctloutput(int, struct socket *
 void   ip6_init(void);
 void   ip6intr(void);
 void   ip6_input(struct mbuf *);
-void   ip6_ours(struct mbuf *, int, int);
+void   ip6_local(struct mbuf *, int, int);
 void   ip6_freepcbopts(struct ip6_pktopts *);
 void   ip6_freemoptions(struct ip6_moptions *);
 int    ip6_unknown_opt(u_int8_t *, struct mbuf *, int);

Reply via email to