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
This commit is contained in:
Bjoern A. Zeeb 2019-02-24 22:49:56 +00:00
parent 4f560b016f
commit a4c69b8bc0
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=344504

View File

@ -341,8 +341,8 @@ arp_fillheader(struct ifnet *ifp, struct arphdr *ah, int bcast, u_char *buf,
* - 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 *sip,
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 *sip,
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,10 +426,21 @@ arprequest(struct ifnet *ifp, const struct in_addr *sip,
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.
@ -557,7 +568,7 @@ arpresolve_full(struct ifnet *ifp, int is_gw, int flags, struct mbuf *m,
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 flags, struct mbuf *m,
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);
}