On 05/28/17 16:09, Martin Pieuchot wrote:
> On 28/05/17(Sun) 16:02, Florian Riehm wrote:
>> [...] 
>> Ok, new diff below.
> 
> I overlooked something!  See below:

Good catch!
I also forgot SRPL_LEAVE.
fixed.


Index: share/man/man9/mbuf_tags.9
===================================================================
RCS file: /cvs/src/share/man/man9/mbuf_tags.9,v
retrieving revision 1.37
diff -u -p -r1.37 mbuf_tags.9
--- share/man/man9/mbuf_tags.9  24 Nov 2015 19:58:48 -0000      1.37
+++ share/man/man9/mbuf_tags.9  28 May 2017 15:16:09 -0000
@@ -170,6 +170,13 @@ Used by the IPv4 stack to keep track of 
 IP packet, in case a protocol wants to respond over the same route.
 The tag contains a
 .Va struct ip_srcrt .
+.It PACKET_TAG_CARP_BAL_IP
+Used by
+.Xr carp 4
+to mark packets received in mode 
+.Va balancing ip .
+This packets need some special treatment since they contain layer 3 unicast
+inside layer 2 multicast. The tag contains no data.
 .El
 .Pp
 .Fn m_tag_find
Index: sys/netinet/ip_carp.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_carp.c,v
retrieving revision 1.310
diff -u -p -r1.310 ip_carp.c
--- sys/netinet/ip_carp.c       27 May 2017 21:55:52 -0000      1.310
+++ sys/netinet/ip_carp.c       28 May 2017 15:16:10 -0000
@@ -1422,8 +1422,25 @@ carp_input(struct ifnet *ifp0, struct mb
                    (IFF_UP|IFF_RUNNING))
                        continue;
 
-               if (carp_vhe_match(sc, eh->ether_dhost))
+               if (carp_vhe_match(sc, eh->ether_dhost)) {
+                       /*
+                        * These packets look like layer 2 multicast but they
+                        * are unicast at layer 3. With help of the tag the
+                        * mbuf's M_MCAST flag can be removed by carp_lsdrop()
+                        * after we have passed layer 2.
+                        */
+                       if (sc->sc_balancing == CARP_BAL_IP) {
+                               struct m_tag *mtag;
+                               mtag = m_tag_get(PACKET_TAG_CARP_BAL_IP, 0,
+                                   M_NOWAIT);
+                               if (mtag == NULL) {
+                                       m_freem(m);
+                                       goto out;
+                               }
+                               m_tag_prepend(m, mtag);
+                       }
                        break;
+               }
        }
 
        if (sc == NULL) {
@@ -1456,27 +1473,23 @@ carp_input(struct ifnet *ifp0, struct mb
                return (0);
        }
 
-       /*
-        * Clear mcast if received on a carp IP balanced address.
-        */
-       if (sc->sc_balancing == CARP_BAL_IP &&
-           ETHER_IS_MULTICAST(eh->ether_dhost))
-               *(eh->ether_dhost) &= ~0x01;
-
        ml_enqueue(&ml, m);
        if_input(&sc->sc_if, &ml);
+out:
        SRPL_LEAVE(&sr);
 
        return (1);
 }
 
 int
-carp_lsdrop(struct mbuf *m, sa_family_t af, u_int32_t *src, u_int32_t *dst)
+carp_lsdrop(struct mbuf *m, sa_family_t af, u_int32_t *src, u_int32_t *dst,
+   int drop)
 {
        struct ifnet *ifp;
        struct carp_softc *sc;
        int match = 1;
        u_int32_t fold;
+       struct m_tag *mtag;
 
        ifp = if_get(m->m_pkthdr.ph_ifidx);
        KASSERT(ifp != NULL);
@@ -1484,6 +1497,25 @@ carp_lsdrop(struct mbuf *m, sa_family_t 
        sc = ifp->if_softc;
        if (sc->sc_balancing == CARP_BAL_NONE)
                goto done;
+
+       /*
+        * Remove M_MCAST flag from mbuf of balancing ip traffic, since the fact
+        * that it is layer 2 multicast does not implicate that it is also layer
+        * 3 multicast.
+        */
+       if (m->m_flags & M_MCAST &&
+           (mtag = m_tag_find(m, PACKET_TAG_CARP_BAL_IP, NULL))) {
+               m_tag_delete(m, mtag);
+               m->m_flags &= ~M_MCAST;
+       }
+       
+       /*
+        * Return without making a drop decision. This allows to clear the
+        * M_MCAST flag and do nothing else.
+        */
+       if (!drop)
+               goto done;
+
        /*
         * Never drop carp advertisements.
         * XXX Bad idea to pass all broadcast / multicast traffic?
Index: sys/netinet/ip_carp.h
===================================================================
RCS file: /cvs/src/sys/netinet/ip_carp.h,v
retrieving revision 1.42
diff -u -p -r1.42 ip_carp.h
--- sys/netinet/ip_carp.h       14 Apr 2017 20:46:31 -0000      1.42
+++ sys/netinet/ip_carp.h       28 May 2017 15:16:10 -0000
@@ -204,6 +204,7 @@ struct ifnet        *carp_ourether(void *, u_in
 int             carp_output(struct ifnet *, struct mbuf *, struct sockaddr *,
                     struct rtentry *);
 int             carp_sysctl(int *, u_int,  void *, size_t *, void *, size_t);
-int             carp_lsdrop(struct mbuf *, sa_family_t, u_int32_t *, u_int32_t 
*);
+int             carp_lsdrop(struct mbuf *, sa_family_t, u_int32_t *,
+                    u_int32_t *, int);
 #endif /* _KERNEL */
 #endif /* _NETINET_IP_CARP_H_ */
Index: sys/netinet/ip_icmp.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_icmp.c,v
retrieving revision 1.168
diff -u -p -r1.168 ip_icmp.c
--- sys/netinet/ip_icmp.c       22 May 2017 14:26:08 -0000      1.168
+++ sys/netinet/ip_icmp.c       28 May 2017 15:16:10 -0000
@@ -498,7 +498,7 @@ icmp_input_if(struct ifnet *ifp, struct 
 #if NCARP > 0
                if (ifp->if_type == IFT_CARP &&
                    carp_lsdrop(m, AF_INET, &sin.sin_addr.s_addr,
-                   &ip->ip_dst.s_addr))
+                   &ip->ip_dst.s_addr, 1))
                        goto freeit;
 #endif
                /*
@@ -582,7 +582,7 @@ reflect:
 #if NCARP > 0
                if (ifp->if_type == IFT_CARP &&
                    carp_lsdrop(m, AF_INET, &ip->ip_src.s_addr,
-                   &ip->ip_dst.s_addr))
+                   &ip->ip_dst.s_addr, 1))
                        goto freeit;
 #endif
                /* Free packet atttributes */
@@ -650,7 +650,7 @@ reflect:
 #if NCARP > 0
                if (ifp->if_type == IFT_CARP &&
                    carp_lsdrop(m, AF_INET, &sdst.sin_addr.s_addr,
-                   &ip->ip_dst.s_addr))
+                   &ip->ip_dst.s_addr, 1))
                        goto freeit;
 #endif
                rtredirect(sintosa(&sdst), sintosa(&sgw),
Index: sys/netinet/ip_input.c
===================================================================
RCS file: /cvs/src/sys/netinet/ip_input.c,v
retrieving revision 1.304
diff -u -p -r1.304 ip_input.c
--- sys/netinet/ip_input.c      22 May 2017 22:23:11 -0000      1.304
+++ sys/netinet/ip_input.c      28 May 2017 15:16:10 -0000
@@ -319,8 +319,9 @@ ipv4_input(struct mbuf *m)
        }
 
 #if NCARP > 0
-       if (ifp->if_type == IFT_CARP && ip->ip_p != IPPROTO_ICMP &&
-           carp_lsdrop(m, AF_INET, &ip->ip_src.s_addr, &ip->ip_dst.s_addr))
+       if (ifp->if_type == IFT_CARP &&
+           carp_lsdrop(m, AF_INET, &ip->ip_src.s_addr, &ip->ip_dst.s_addr,
+           (ip->ip_p == IPPROTO_ICMP ? 0 : 1)))
                goto bad;
 #endif
 
@@ -427,7 +428,7 @@ ipv4_input(struct mbuf *m)
 
 #if NCARP > 0
        if (ifp->if_type == IFT_CARP && ip->ip_p == IPPROTO_ICMP &&
-           carp_lsdrop(m, AF_INET, &ip->ip_src.s_addr, &ip->ip_dst.s_addr))
+           carp_lsdrop(m, AF_INET, &ip->ip_src.s_addr, &ip->ip_dst.s_addr, 1))
                goto bad;
 #endif
        /*
Index: sys/netinet6/icmp6.c
===================================================================
RCS file: /cvs/src/sys/netinet6/icmp6.c,v
retrieving revision 1.210
diff -u -p -r1.210 icmp6.c
--- sys/netinet6/icmp6.c        8 May 2017 16:14:47 -0000       1.210
+++ sys/netinet6/icmp6.c        28 May 2017 15:16:10 -0000
@@ -446,7 +446,7 @@ icmp6_input(struct mbuf **mp, int *offp,
        if (ifp->if_type == IFT_CARP &&
            icmp6->icmp6_type == ICMP6_ECHO_REQUEST &&
            carp_lsdrop(m, AF_INET6, ip6->ip6_src.s6_addr32,
-           ip6->ip6_dst.s6_addr32)) {
+           ip6->ip6_dst.s6_addr32, 1)) {
                if_put(ifp);
                goto freeit;
        }
Index: sys/netinet6/ip6_input.c
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_input.c,v
retrieving revision 1.189
diff -u -p -r1.189 ip6_input.c
--- sys/netinet6/ip6_input.c    23 May 2017 08:13:10 -0000      1.189
+++ sys/netinet6/ip6_input.c    28 May 2017 15:16:10 -0000
@@ -207,9 +207,9 @@ ip6_input(struct mbuf *m)
        }
 
 #if NCARP > 0
-       if (ifp->if_type == IFT_CARP && ip6->ip6_nxt != IPPROTO_ICMPV6 &&
+       if (ifp->if_type == IFT_CARP &&
            carp_lsdrop(m, AF_INET6, ip6->ip6_src.s6_addr32,
-           ip6->ip6_dst.s6_addr32))
+           ip6->ip6_dst.s6_addr32, (ip6->ip6_nxt == IPPROTO_ICMPV6 ? 0 : 1)))
                goto bad;
 #endif
        ip6stat_inc(ip6s_nxthist + ip6->ip6_nxt);
@@ -448,7 +448,7 @@ ip6_input(struct mbuf *m)
 #if NCARP > 0
        if (ifp->if_type == IFT_CARP && ip6->ip6_nxt == IPPROTO_ICMPV6 &&
            carp_lsdrop(m, AF_INET6, ip6->ip6_src.s6_addr32,
-           ip6->ip6_dst.s6_addr32))
+           ip6->ip6_dst.s6_addr32, 1))
                goto bad;
 #endif
        /*
Index: sys/sys/mbuf.h
===================================================================
RCS file: /cvs/src/sys/sys/mbuf.h,v
retrieving revision 1.228
diff -u -p -r1.228 mbuf.h
--- sys/sys/mbuf.h      16 May 2017 15:57:03 -0000      1.228
+++ sys/sys/mbuf.h      28 May 2017 15:16:10 -0000
@@ -485,11 +485,12 @@ struct m_tag *m_tag_next(struct mbuf *, 
 #define PACKET_TAG_PF_REASSEMBLED      0x0800 /* pf reassembled ipv6 packet */
 #define PACKET_TAG_SRCROUTE            0x1000 /* IPv4 source routing options */
 #define PACKET_TAG_TUNNEL              0x2000  /* Tunnel endpoint address */
+#define PACKET_TAG_CARP_BAL_IP         0x4000  /* carp(4) ip balanced marker */
 
 #define MTAG_BITS \
     ("\20\1IPSEC_IN_DONE\2IPSEC_OUT_DONE\3IPSEC_IN_CRYPTO_DONE" \
     "\4IPSEC_OUT_CRYPTO_NEEDED\5IPSEC_PENDING_TDB\6BRIDGE\7GIF\10GRE\11DLT" \
-    "\12PF_DIVERT\14PF_REASSEMBLED\15SRCROUTE\16TUNNEL")
+    "\12PF_DIVERT\14PF_REASSEMBLED\15SRCROUTE\16TUNNEL\17CARP_BAL_IP")
 
 /*
  * Maximum tag payload length (that is excluding the m_tag structure).

Reply via email to