Carp balancing ip does not work since there is a mac filter in
authorfriehm <friehm@openbsd.org>
Tue, 30 May 2017 12:09:27 +0000 (12:09 +0000)
committerfriehm <friehm@openbsd.org>
Tue, 30 May 2017 12:09:27 +0000 (12:09 +0000)
ether_input(). Now we use mbuf tags instead of modifying the MAC
address.

ok mpi@

share/man/man9/mbuf_tags.9
sys/netinet/ip_carp.c
sys/netinet/ip_carp.h
sys/netinet/ip_icmp.c
sys/netinet/ip_input.c
sys/netinet6/icmp6.c
sys/netinet6/ip6_input.c
sys/sys/mbuf.h

index ebcf0ea..c410988 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $OpenBSD: mbuf_tags.9,v 1.37 2015/11/24 19:58:48 jmc Exp $
+.\"    $OpenBSD: mbuf_tags.9,v 1.38 2017/05/30 12:09:27 friehm Exp $
 .\"
 .\" The author of this man page is Angelos D. Keromytis (angelos@cis.upenn.edu)
 .\"
@@ -15,7 +15,7 @@
 .\" MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
 .\" PURPOSE.
 .\"
-.Dd $Mdocdate: November 24 2015 $
+.Dd $Mdocdate: May 30 2017 $
 .Dt M_TAG_GET 9
 .Os
 .Sh NAME
@@ -170,6 +170,13 @@ Used by the IPv4 stack to keep track of the source route of an incoming
 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 44e2f94..97af0d3 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip_carp.c,v 1.311 2017/05/28 12:47:24 mpi Exp $       */
+/*     $OpenBSD: ip_carp.c,v 1.312 2017/05/30 12:09:27 friehm Exp $    */
 
 /*
  * Copyright (c) 2002 Michael Shalayeff. All rights reserved.
@@ -1426,8 +1426,25 @@ carp_input(struct ifnet *ifp0, struct mbuf *m, void *cookie)
                    (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) {
@@ -1460,27 +1477,23 @@ carp_input(struct ifnet *ifp0, struct mbuf *m, void *cookie)
                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);
@@ -1488,6 +1501,25 @@ carp_lsdrop(struct mbuf *m, sa_family_t af, u_int32_t *src, u_int32_t *dst)
        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 026990d..612b9a2 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip_carp.h,v 1.42 2017/04/14 20:46:31 bluhm Exp $      */
+/*     $OpenBSD: ip_carp.h,v 1.43 2017/05/30 12:09:27 friehm Exp $     */
 
 /*
  * Copyright (c) 2002 Michael Shalayeff. All rights reserved.
@@ -204,6 +204,7 @@ struct ifnet        *carp_ourether(void *, u_int8_t *);
 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 8de565d..1c32137 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip_icmp.c,v 1.168 2017/05/22 14:26:08 bluhm Exp $     */
+/*     $OpenBSD: ip_icmp.c,v 1.169 2017/05/30 12:09:27 friehm Exp $    */
 /*     $NetBSD: ip_icmp.c,v 1.19 1996/02/13 23:42:22 christos Exp $    */
 
 /*
@@ -498,7 +498,7 @@ icmp_input_if(struct ifnet *ifp, struct mbuf **mp, int *offp, int proto, int af)
 #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 65c9402..93bc790 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip_input.c,v 1.308 2017/05/30 07:50:37 mpi Exp $      */
+/*     $OpenBSD: ip_input.c,v 1.309 2017/05/30 12:09:27 friehm Exp $   */
 /*     $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $   */
 
 /*
@@ -325,8 +325,9 @@ ip_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
 
@@ -433,7 +434,7 @@ ip_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 c7a5566..b3b2f50 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: icmp6.c,v 1.210 2017/05/08 16:14:47 rzalamena Exp $   */
+/*     $OpenBSD: icmp6.c,v 1.211 2017/05/30 12:09:27 friehm Exp $      */
 /*     $KAME: icmp6.c,v 1.217 2001/06/20 15:03:29 jinmei Exp $ */
 
 /*
@@ -446,7 +446,7 @@ icmp6_input(struct mbuf **mp, int *offp, int proto, int af)
        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 b0c7b16..8d1f2f5 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip6_input.c,v 1.192 2017/05/30 07:50:37 mpi Exp $     */
+/*     $OpenBSD: ip6_input.c,v 1.193 2017/05/30 12:09:27 friehm Exp $  */
 /*     $KAME: ip6_input.c,v 1.188 2001/03/29 05:34:31 itojun Exp $     */
 
 /*
@@ -213,9 +213,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);
@@ -454,7 +454,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 6eb5ded..f6607a2 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: mbuf.h,v 1.228 2017/05/16 15:57:03 kettenis Exp $     */
+/*     $OpenBSD: mbuf.h,v 1.229 2017/05/30 12:09:27 friehm Exp $       */
 /*     $NetBSD: mbuf.h,v 1.19 1996/02/09 18:25:14 christos Exp $       */
 
 /*
@@ -485,11 +485,12 @@ struct m_tag *m_tag_next(struct mbuf *, struct m_tag *);
 #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).