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
This commit is contained in:
Dmitry Ovsyannikov 2022-06-13 08:34:44 -05:00 committed by Eric van Gyzen
parent 5ea3094e6a
commit 9f48eea366
3 changed files with 17 additions and 14 deletions

View file

@ -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

View file

@ -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));

View file

@ -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;
}