From 9f48eea36607cd89a88a38d4efa9f3b81d5e6e54 Mon Sep 17 00:00:00 2001 From: Dmitry Ovsyannikov Date: Mon, 13 Jun 2022 08:34:44 -0500 Subject: [PATCH] rpcbind: get contact addr from xprt members Addition to D31491 in order to actually resolve the top root cause. Currently rpcbind gets contact address from connectionless xprt->xp_p2 member of a transport and will fail to get it when working over connection oriented transport, leading to a guess game in terms of contact address on rpcinfo requests like RPCBPROC_GETVERSADDR or RPCBPROC_GETADDRLIST and poor returns which may influence a user of a call and specifically reported on OSX clients, which tend to not provide address hint from rpcinfo request to a server. MFC after: 1 week Sponsored by: Dell EMC Isilon Differential Revision: https://reviews.freebsd.org/D35220 --- include/rpc/svc.h | 4 ++++ usr.sbin/rpcbind/check_bound.c | 11 +++++------ usr.sbin/rpcbind/util.c | 16 ++++++++-------- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/include/rpc/svc.h b/include/rpc/svc.h index 912d26ba4461..4cffd4070817 100644 --- a/include/rpc/svc.h +++ b/include/rpc/svc.h @@ -165,6 +165,10 @@ struct svc_req { * Approved way of getting address of caller */ #define svc_getrpccaller(x) (&(x)->xp_rtaddr) +/* + * Approved way of getting address of callee + */ +#define svc_getrpccallee(x) (&(x)->xp_ltaddr) /* * Operations defined on an SVCXPRT handle diff --git a/usr.sbin/rpcbind/check_bound.c b/usr.sbin/rpcbind/check_bound.c index cf0a029dad72..1f9382d33730 100644 --- a/usr.sbin/rpcbind/check_bound.c +++ b/usr.sbin/rpcbind/check_bound.c @@ -161,7 +161,7 @@ char * mergeaddr(SVCXPRT *xprt, char *netid, char *uaddr, char *saddr) { struct fdlist *fdl; - struct svc_dg_data *dg_data; + struct netbuf *callee; char *c_uaddr, *s_uaddr, *m_uaddr, *allocated_uaddr = NULL; for (fdl = fdhead; fdl; fdl = fdl->next) @@ -182,12 +182,11 @@ mergeaddr(SVCXPRT *xprt, char *netid, char *uaddr, char *saddr) * address by which it contacted us. Use that for the "client" uaddr, * otherwise use the info from the SVCXPRT. */ - dg_data = (struct svc_dg_data*)xprt->xp_p2; - if (dg_data != NULL && dg_data->su_srcaddr.buf != NULL) { - c_uaddr = taddr2uaddr(fdl->nconf, &dg_data->su_srcaddr); + callee = svc_getrpccallee(xprt); + if (callee != NULL && callee->buf != NULL) { + c_uaddr = taddr2uaddr(fdl->nconf, callee); allocated_uaddr = c_uaddr; - } - else if (saddr != NULL) { + } else if (saddr != NULL) { c_uaddr = saddr; } else { c_uaddr = taddr2uaddr(fdl->nconf, svc_getrpccaller(xprt)); diff --git a/usr.sbin/rpcbind/util.c b/usr.sbin/rpcbind/util.c index e497e9227690..7662f2357d48 100644 --- a/usr.sbin/rpcbind/util.c +++ b/usr.sbin/rpcbind/util.c @@ -101,7 +101,7 @@ bitmaskcmp(struct sockaddr *dst, struct sockaddr *src, struct sockaddr *mask) /* * Find a server address that can be used by `caller' to contact - * the local service specified by `serv_uaddr'. If `clnt_uaddr' is + * the local service specified by `serv_uaddr'. If `contct_uaddr' is * non-NULL, it is used instead of `caller' as a hint suggesting * the best address (e.g. the `r_addr' field of an rpc, which * contains the rpcbind server address that the caller used). @@ -110,8 +110,8 @@ bitmaskcmp(struct sockaddr *dst, struct sockaddr *src, struct sockaddr *mask) * string which should be freed by the caller. On error, returns NULL. */ char * -addrmerge(struct netbuf *caller, const char *serv_uaddr, const char *clnt_uaddr, - const char *netid) +addrmerge(struct netbuf *caller, const char *serv_uaddr, + const char *contct_uaddr, const char *netid) { struct ifaddrs *ifap, *ifp = NULL, *bestif; struct netbuf *serv_nbp = NULL, *hint_nbp = NULL, tbuf; @@ -128,7 +128,7 @@ addrmerge(struct netbuf *caller, const char *serv_uaddr, const char *clnt_uaddr, #ifdef ND_DEBUG if (debugging) fprintf(stderr, "addrmerge(caller, %s, %s, %s\n", serv_uaddr, - clnt_uaddr == NULL ? "NULL" : clnt_uaddr, netid); + contct_uaddr == NULL ? "NULL" : contct_uaddr, netid); #endif caller_sa = caller->buf; if ((nconf = rpcbind_get_conf(netid)) == NULL) @@ -137,15 +137,15 @@ addrmerge(struct netbuf *caller, const char *serv_uaddr, const char *clnt_uaddr, goto freeit; /* - * Use `clnt_uaddr' as the hint if non-NULL, but ignore it if its + * Use `contct_uaddr' as the hint if non-NULL, but ignore it if its * address family is different from that of the caller. */ hint_sa = NULL; - if (clnt_uaddr != NULL) { + if (contct_uaddr != NULL) { #ifdef ND_DEBUG - hint_uaddr = clnt_uaddr; + hint_uaddr = contct_uaddr; #endif - if ((hint_nbp = uaddr2taddr(nconf, clnt_uaddr)) == NULL) + if ((hint_nbp = uaddr2taddr(nconf, contct_uaddr)) == NULL) goto freeit; hint_sa = hint_nbp->buf; }