From 76dda2b0279f3c37adf1c059c3bab4d74bc96602 Mon Sep 17 00:00:00 2001 From: friehm Date: Tue, 30 May 2017 12:09:27 +0000 Subject: [PATCH] Carp balancing ip does not work since there is a mac filter in ether_input(). Now we use mbuf tags instead of modifying the MAC address. ok mpi@ --- share/man/man9/mbuf_tags.9 | 11 ++++++-- sys/netinet/ip_carp.c | 52 ++++++++++++++++++++++++++++++-------- sys/netinet/ip_carp.h | 5 ++-- sys/netinet/ip_icmp.c | 8 +++--- sys/netinet/ip_input.c | 9 ++++--- sys/netinet6/icmp6.c | 4 +-- sys/netinet6/ip6_input.c | 8 +++--- sys/sys/mbuf.h | 5 ++-- 8 files changed, 72 insertions(+), 30 deletions(-) diff --git a/share/man/man9/mbuf_tags.9 b/share/man/man9/mbuf_tags.9 index ebcf0ea412d..c410988f007 100644 --- a/share/man/man9/mbuf_tags.9 +++ b/share/man/man9/mbuf_tags.9 @@ -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 diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c index 44e2f9493a0..97af0d33f0d 100644 --- a/sys/netinet/ip_carp.c +++ b/sys/netinet/ip_carp.c @@ -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? diff --git a/sys/netinet/ip_carp.h b/sys/netinet/ip_carp.h index 026990db18b..612b9a20952 100644 --- a/sys/netinet/ip_carp.h +++ b/sys/netinet/ip_carp.h @@ -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_ */ diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c index 8de565d1a35..1c321375fa7 100644 --- a/sys/netinet/ip_icmp.c +++ b/sys/netinet/ip_icmp.c @@ -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), diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 65c9402684f..93bc790a211 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -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 /* diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c index c7a5566076b..b3b2f5028c0 100644 --- a/sys/netinet6/icmp6.c +++ b/sys/netinet6/icmp6.c @@ -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; } diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c index b0c7b162471..8d1f2f545c7 100644 --- a/sys/netinet6/ip6_input.c +++ b/sys/netinet6/ip6_input.c @@ -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 /* diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h index 6eb5dedf302..f6607a2eead 100644 --- a/sys/sys/mbuf.h +++ b/sys/sys/mbuf.h @@ -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). -- 2.20.1