From 103ec7fadeee907ef46c9f17d8eaf370210ca50c Mon Sep 17 00:00:00 2001 From: roy Date: Tue, 11 Oct 2016 12:32:30 +0000 Subject: [PATCH] Mark arprequest static and introduce arpannounce so that gratuitous ARP requests are only send from valid addresses. --- sys/net/if_llatbl.c | 21 ++++++++---- sys/netinet/if_arp.c | 74 ++++++++++++++++++++---------------------- sys/netinet/if_inarp.h | 5 ++- sys/netinet/ip_carp.c | 7 ++-- 4 files changed, 56 insertions(+), 51 deletions(-) diff --git a/sys/net/if_llatbl.c b/sys/net/if_llatbl.c index 4521ab8cf0be..c38acca6910b 100644 --- a/sys/net/if_llatbl.c +++ b/sys/net/if_llatbl.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_llatbl.c,v 1.14 2016/06/16 03:03:33 ozaki-r Exp $ */ +/* $NetBSD: if_llatbl.c,v 1.15 2016/10/11 12:32:30 roy Exp $ */ /* * Copyright (c) 2004 Luigi Rizzo, Alessandro Cerri. All rights reserved. * Copyright (c) 2004-2008 Qing Li. All rights reserved. @@ -60,6 +60,7 @@ #include #include #include +#include #include #include @@ -671,11 +672,19 @@ lla_rt_output(const u_char rtm_type, const int rtm_flags, const time_t rtm_expir IF_AFDATA_WUNLOCK(ifp); #if defined(INET) && NARP > 0 /* gratuitous ARP */ - if ((laflags & LLE_PUB) && dst->sa_family == AF_INET) - arprequest(ifp, - &((const struct sockaddr_in *)dst)->sin_addr, - &((const struct sockaddr_in *)dst)->sin_addr, - CLLADDR(dl)); + if ((laflags & LLE_PUB) && dst->sa_family == AF_INET) { + const struct sockaddr_in *sin; + struct in_ifaddr *ia; + struct psref _psref; + + sin = satocsin(dst); + ia = in_get_ia_on_iface_psref(sin->sin_addr, + ifp, &_psref); + if (ia != NULL) { + arpannounce(ifp, &ia->ia_ifa, CLLADDR(dl)); + ia4_release(ia, &_psref); + } + } #else (void)laflags; #endif diff --git a/sys/netinet/if_arp.c b/sys/netinet/if_arp.c index a356b071e615..dd3fc85770dc 100644 --- a/sys/netinet/if_arp.c +++ b/sys/netinet/if_arp.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_arp.c,v 1.228 2016/10/03 11:06:06 ozaki-r Exp $ */ +/* $NetBSD: if_arp.c,v 1.229 2016/10/11 12:32:30 roy Exp $ */ /*- * Copyright (c) 1998, 2000, 2008 The NetBSD Foundation, Inc. @@ -68,7 +68,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.228 2016/10/03 11:06:06 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.229 2016/10/11 12:32:30 roy Exp $"); #ifdef _KERNEL_OPT #include "opt_ddb.h" @@ -157,6 +157,10 @@ int arp_debug = 0; static void arp_init(void); +static void arprequest(struct ifnet *, + const struct in_addr *, const struct in_addr *, + const u_int8_t *); +static void arpannounce1(struct ifaddr *); static struct sockaddr *arp_setgate(struct rtentry *, struct sockaddr *, const struct sockaddr *); static void arptimer(void *); @@ -452,22 +456,8 @@ arp_rtrequest(int req, struct rtentry *rt, const struct rt_addrinfo *info) int s; if (req == RTM_LLINFO_UPD) { - struct in_addr *in; - - if ((ifa = info->rti_ifa) == NULL) - return; - - in = &ifatoia(ifa)->ia_addr.sin_addr; - - if (ifatoia(ifa)->ia4_flags & - (IN_IFF_NOTREADY | IN_IFF_DETACHED)) - { - arplog(LOG_DEBUG, "%s not ready\n", in_fmtaddr(*in)); - return; - } - - arprequest(ifa->ifa_ifp, in, in, - CLLADDR(ifa->ifa_ifp->if_sadl)); + if ((ifa = info->rti_ifa) != NULL) + arpannounce1(ifa); return; } @@ -563,16 +553,11 @@ arp_rtrequest(int req, struct rtentry *rt, const struct rt_addrinfo *info) struct psref psref; ia = in_get_ia_on_iface_psref( satocsin(rt_getkey(rt))->sin_addr, ifp, &psref); - if (ia == NULL || - ia->ia4_flags & (IN_IFF_NOTREADY | IN_IFF_DETACHED)) - ; - else - arprequest(ifp, - &satocsin(rt_getkey(rt))->sin_addr, - &satocsin(rt_getkey(rt))->sin_addr, + if (ia != NULL) { + arpannounce(ifp, &ia->ia_ifa, CLLADDR(satocsdl(gate))); - if (ia != NULL) ia4_release(ia, &psref); + } } if (gate->sa_family != AF_LINK || @@ -645,7 +630,7 @@ arp_rtrequest(int req, struct rtentry *rt, const struct rt_addrinfo *info) * - arp header target ip address * - arp header source ethernet address */ -void +static void arprequest(struct ifnet *ifp, const struct in_addr *sip, const struct in_addr *tip, const u_int8_t *enaddr) @@ -702,6 +687,26 @@ arprequest(struct ifnet *ifp, if_output_lock(ifp, ifp, m, &sa, NULL); } +void +arpannounce(struct ifnet *ifp, struct ifaddr *ifa, const uint8_t *enaddr) +{ + struct in_ifaddr *ia = ifatoia(ifa); + struct in_addr *ip = &IA_SIN(ifa)->sin_addr; + + if (ia->ia4_flags & (IN_IFF_NOTREADY | IN_IFF_DETACHED)) { + arplog(LOG_DEBUG, "%s not ready\n", in_fmtaddr(*ip)); + return; + } + arprequest(ifp, ip, ip, enaddr); +} + +static void +arpannounce1(struct ifaddr *ifa) +{ + + arpannounce(ifa->ifa_ifp, ifa, CLLADDR(ifa->ifa_ifp->if_sadl)); +} + /* * Resolve an IP address into an ethernet address. If success, * desten is filled in. If there is no entry in arptab, @@ -1353,7 +1358,6 @@ reply: m->m_flags |= M_BCAST; m->m_len = sizeof(*ah) + (2 * ah->ar_pln) + ah->ar_hln; break; - default: m->m_flags &= ~(M_BCAST|M_MCAST); /* never reply by broadcast */ m->m_len = sizeof(*ah) + (2 * ah->ar_pln) + (2 * ah->ar_hln); @@ -1457,8 +1461,6 @@ arp_ifinit(struct ifnet *ifp, struct ifaddr *ifa) (ia->ia4_flags & (IN_IFF_NOTREADY | IN_IFF_DETACHED)) == 0) { struct llentry *lle; - arprequest(ifp, ip, ip, CLLADDR(ifp->if_sadl)); - /* * interface address is considered static entry * because the output of the arp utility shows @@ -1492,6 +1494,8 @@ arp_ifinit(struct ifnet *ifp, struct ifaddr *ifa) ia->ia_dad_stop = arp_dad_stop; if (ia->ia4_flags & IN_IFF_TRYTENTATIVE) ia->ia4_flags |= IN_IFF_TENTATIVE; + else + arpannounce1(ifa); } } @@ -1590,12 +1594,9 @@ arp_dad_start(struct ifaddr *ifa) return; } if (!ip_dad_count) { - struct in_addr *ip = &IA_SIN(ifa)->sin_addr; - ia->ia4_flags &= ~IN_IFF_TENTATIVE; rt_newaddrmsg(RTM_NEWADDR, ifa, 0, NULL); - arprequest(ifa->ifa_ifp, ip, ip, - CLLADDR(ifa->ifa_ifp->if_sadl)); + arpannounce1(ifa); return; } KASSERT(ifa->ifa_ifp != NULL); @@ -1674,7 +1675,6 @@ arp_dad_timer(struct ifaddr *ifa) { struct in_ifaddr *ia = (struct in_ifaddr *)ifa; struct dadq *dp; - struct in_addr *ip; mutex_enter(softnet_lock); KERNEL_LOCK(1, NULL); @@ -1750,9 +1750,7 @@ announce: /* * Announce the address. */ - ip = &IA_SIN(ifa)->sin_addr; - arprequest(ifa->ifa_ifp, ip, ip, - CLLADDR(ifa->ifa_ifp->if_sadl)); + arpannounce1(ifa); dp->dad_arp_acount++; if (dp->dad_arp_acount < dp->dad_arp_announce) { arp_dad_starttimer(dp, ANNOUNCE_INTERVAL * hz); diff --git a/sys/netinet/if_inarp.h b/sys/netinet/if_inarp.h index bffa92fb7d20..531a80703916 100644 --- a/sys/netinet/if_inarp.h +++ b/sys/netinet/if_inarp.h @@ -1,4 +1,4 @@ -/* $NetBSD: if_inarp.h,v 1.49 2016/04/19 04:13:56 ozaki-r Exp $ */ +/* $NetBSD: if_inarp.h,v 1.50 2016/10/11 12:32:30 roy Exp $ */ /* * Copyright (c) 1982, 1986, 1993 @@ -78,8 +78,7 @@ void arp_rtrequest(int, struct rtentry *, const struct rt_addrinfo *); int arpresolve(struct ifnet *, const struct rtentry *, struct mbuf *, const struct sockaddr *, void *, size_t); void arpintr(void); -void arprequest(struct ifnet *, const struct in_addr *, const struct in_addr *, - const u_int8_t *); +void arpannounce(struct ifnet *, struct ifaddr *, const uint8_t *); void arp_drain(void); int arpioctl(u_long, void *); void arpwhohas(struct ifnet *, struct in_addr *); diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c index 08adda290bde..9df6117701f3 100644 --- a/sys/netinet/ip_carp.c +++ b/sys/netinet/ip_carp.c @@ -1,4 +1,4 @@ -/* $NetBSD: ip_carp.c,v 1.77 2016/08/01 03:15:30 ozaki-r Exp $ */ +/* $NetBSD: ip_carp.c,v 1.78 2016/10/11 12:32:30 roy Exp $ */ /* $OpenBSD: ip_carp.c,v 1.113 2005/11/04 08:11:54 mcbride Exp $ */ /* @@ -33,7 +33,7 @@ #endif #include -__KERNEL_RCSID(0, "$NetBSD: ip_carp.c,v 1.77 2016/08/01 03:15:30 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ip_carp.c,v 1.78 2016/10/11 12:32:30 roy Exp $"); /* * TODO: @@ -1231,8 +1231,7 @@ carp_send_arp(struct carp_softc *sc) if (ifa->ifa_addr->sa_family != AF_INET) continue; - in = &ifatoia(ifa)->ia_addr.sin_addr; - arprequest(sc->sc_carpdev, in, in, CLLADDR(sc->sc_if.if_sadl)); + arpannounce(sc->sc_carpdev, ifa, CLLADDR(sc->sc_if.if_sadl)); } splx(s); KERNEL_UNLOCK_ONE(NULL);