Date: Sun, 24 Feb 2019 22:49:56 +0000 (UTC) From: "Bjoern A. Zeeb" <bz@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r344504 - head/sys/netinet Message-ID: <201902242249.x1OMnuqN094107@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: bz Date: Sun Feb 24 22:49:56 2019 New Revision: 344504 URL: https://svnweb.freebsd.org/changeset/base/344504 Log: Make arp code return (more) errors. arprequest() is a void function and in case of error we simply return without any feedback. In case of any local operation or *if_output() failing no feedback is send up the stack for the packet which triggered the arp request to be sent. arpresolve_full() has three pre-canned possible errors returned (if we have not yet sent enough arp requests or if we tried often enough without success) otherwise "no error" is returned. Make arprequest() an "internal" function arprequest_internal() which does return a possible error to the caller. Preserve arprequest() as a void wrapper function for external consumers. In arpresolve_full() add an extra error checking. Use the arprequest_internal() function and only return an error if non of the three ones (mentioend above) are already set. This will return possible errors all the way up the stack and allows functions and programs to react on the send errors rather than leaving them in the dark. Also they might get more detailed feedback of why packets cannot be sent and they will receive it quicker. Reviewed by: karels, hselasky Differential Revision: https://reviews.freebsd.org/D18904 Modified: head/sys/netinet/if_ether.c Modified: head/sys/netinet/if_ether.c ============================================================================== --- head/sys/netinet/if_ether.c Sun Feb 24 21:22:16 2019 (r344503) +++ head/sys/netinet/if_ether.c Sun Feb 24 22:49:56 2019 (r344504) @@ -341,8 +341,8 @@ arp_fillheader(struct ifnet *ifp, struct arphdr *ah, i * - arp header target ip address * - arp header source ethernet address */ -void -arprequest(struct ifnet *ifp, const struct in_addr *sip, +static int +arprequest_internal(struct ifnet *ifp, const struct in_addr *sip, const struct in_addr *tip, u_char *enaddr) { struct mbuf *m; @@ -383,14 +383,14 @@ arprequest(struct ifnet *ifp, const struct in_addr *si NET_EPOCH_EXIT(et); if (sip == NULL) { printf("%s: cannot find matching address\n", __func__); - return; + return (EADDRNOTAVAIL); } } if (enaddr == NULL) enaddr = carpaddr ? carpaddr : (u_char *)IF_LLADDR(ifp); if ((m = m_gethdr(M_NOWAIT, MT_DATA)) == NULL) - return; + return (ENOMEM); m->m_len = sizeof(*ah) + 2 * sizeof(struct in_addr) + 2 * ifp->if_addrlen; m->m_pkthdr.len = m->m_len; @@ -417,7 +417,7 @@ arprequest(struct ifnet *ifp, const struct in_addr *si if (error != 0 && error != EAFNOSUPPORT) { ARP_LOG(LOG_ERR, "Failed to calculate ARP header on %s: %d\n", if_name(ifp), error); - return; + return (error); } ro.ro_prepend = linkhdr; @@ -426,11 +426,22 @@ arprequest(struct ifnet *ifp, const struct in_addr *si m->m_flags |= M_BCAST; m_clrprotoflags(m); /* Avoid confusing lower layers. */ - (*ifp->if_output)(ifp, m, &sa, &ro); + error = (*ifp->if_output)(ifp, m, &sa, &ro); ARPSTAT_INC(txrequests); + if (error) + ARP_LOG(LOG_DEBUG, "Failed to send ARP packet on %s: %d\n", + if_name(ifp), error); + return (error); } +void +arprequest(struct ifnet *ifp, const struct in_addr *sip, + const struct in_addr *tip, u_char *enaddr) +{ + (void) arprequest_internal(ifp, sip, tip, enaddr); +} + /* * Resolve an IP address into an ethernet address - heavy version. * Used internally by arpresolve(). @@ -557,7 +568,7 @@ arpresolve_full(struct ifnet *ifp, int is_gw, int flag error = is_gw != 0 ? EHOSTUNREACH : EHOSTDOWN; if (renew) { - int canceled; + int canceled, e; LLE_ADDREF(la); la->la_expire = time_uptime; @@ -567,7 +578,13 @@ arpresolve_full(struct ifnet *ifp, int is_gw, int flag LLE_REMREF(la); la->la_asked++; LLE_WUNLOCK(la); - arprequest(ifp, NULL, &SIN(dst)->sin_addr, NULL); + e = arprequest_internal(ifp, NULL, &SIN(dst)->sin_addr, NULL); + /* + * Only overwrite 'error' in case of error; in case of success + * the proper return value was already set above. + */ + if (e != 0) + return (e); return (error); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201902242249.x1OMnuqN094107>