Change nfsv4_getipaddr() and nfsrpc_fillsa() to not use sockaddr_storage.
This patch changes nfsv4_getipaddr() and nfsrpc_fillsa() to use a sockaddr_in * and sockaddr_in6 * instead of sockaddr_storage, to avoid allocating the latter on the stack. It also moves the nfsrpc_fillsa() call to after the completion of parsing of the DeviceInfo reply from the server. This patch is in preparation for addition of Flex File Layout support in a future commit. It only affects the "pnfs" NFSv4.1 client mount option and should not have changed its semantics.
This commit is contained in:
parent
3bc4bd5edd
commit
be3d32ad6e
@ -3938,14 +3938,13 @@ newnfs_sndunlock(int *flagp)
|
||||
}
|
||||
|
||||
APPLESTATIC int
|
||||
nfsv4_getipaddr(struct nfsrv_descript *nd, struct sockaddr_storage *sa,
|
||||
int *isudp)
|
||||
nfsv4_getipaddr(struct nfsrv_descript *nd, struct sockaddr_in *sin,
|
||||
struct sockaddr_in6 *sin6, sa_family_t *saf, int *isudp)
|
||||
{
|
||||
struct sockaddr_in *sad;
|
||||
struct sockaddr_in6 *sad6;
|
||||
struct in_addr saddr;
|
||||
uint32_t portnum, *tl;
|
||||
int af = 0, i, j, k;
|
||||
int i, j, k;
|
||||
sa_family_t af = AF_UNSPEC;
|
||||
char addr[64], protocol[5], *cp;
|
||||
int cantparse = 0, error = 0;
|
||||
uint16_t portv;
|
||||
@ -4023,20 +4022,20 @@ nfsv4_getipaddr(struct nfsrv_descript *nd, struct sockaddr_storage *sa,
|
||||
cantparse = 1;
|
||||
if (cantparse == 0) {
|
||||
if (af == AF_INET) {
|
||||
sad = (struct sockaddr_in *)sa;
|
||||
if (inet_pton(af, addr, &sad->sin_addr) == 1) {
|
||||
sad->sin_len = sizeof(*sad);
|
||||
sad->sin_family = AF_INET;
|
||||
sad->sin_port = htons(portv);
|
||||
if (inet_pton(af, addr, &sin->sin_addr) == 1) {
|
||||
sin->sin_len = sizeof(*sin);
|
||||
sin->sin_family = AF_INET;
|
||||
sin->sin_port = htons(portv);
|
||||
*saf = af;
|
||||
return (0);
|
||||
}
|
||||
} else {
|
||||
sad6 = (struct sockaddr_in6 *)sa;
|
||||
if (inet_pton(af, addr, &sad6->sin6_addr)
|
||||
if (inet_pton(af, addr, &sin6->sin6_addr)
|
||||
== 1) {
|
||||
sad6->sin6_len = sizeof(*sad6);
|
||||
sad6->sin6_family = AF_INET6;
|
||||
sad6->sin6_port = htons(portv);
|
||||
sin6->sin6_len = sizeof(*sin6);
|
||||
sin6->sin6_family = AF_INET6;
|
||||
sin6->sin6_port = htons(portv);
|
||||
*saf = af;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
@ -287,8 +287,8 @@ void nfsrv_cleanusergroup(void);
|
||||
int nfsrv_checkutf8(u_int8_t *, int);
|
||||
int newnfs_sndlock(int *);
|
||||
void newnfs_sndunlock(int *);
|
||||
int nfsv4_getipaddr(struct nfsrv_descript *, struct sockaddr_storage *,
|
||||
int *);
|
||||
int nfsv4_getipaddr(struct nfsrv_descript *, struct sockaddr_in *,
|
||||
struct sockaddr_in6 *, sa_family_t *, int *);
|
||||
int nfsv4_seqsession(uint32_t, uint32_t, uint32_t, struct nfsslot *,
|
||||
struct mbuf **, uint16_t);
|
||||
void nfsv4_seqsess_cacherep(uint32_t, struct nfsslot *, int, struct mbuf **);
|
||||
|
@ -109,8 +109,8 @@ static int nfsrpc_setaclrpc(vnode_t, struct ucred *, NFSPROC_T *,
|
||||
static int nfsrpc_getlayout(struct nfsmount *, vnode_t, struct nfsfh *, int,
|
||||
uint32_t *, nfsv4stateid_t *, uint64_t, struct nfscllayout **,
|
||||
struct ucred *, NFSPROC_T *);
|
||||
static int nfsrpc_fillsa(struct nfsmount *, struct sockaddr_storage *,
|
||||
struct nfsclds **, NFSPROC_T *);
|
||||
static int nfsrpc_fillsa(struct nfsmount *, struct sockaddr_in *,
|
||||
struct sockaddr_in6 *, sa_family_t, int, struct nfsclds **, NFSPROC_T *);
|
||||
static void nfscl_initsessionslots(struct nfsclsession *);
|
||||
static int nfscl_doflayoutio(vnode_t, struct uio *, int *, int *, int *,
|
||||
nfsv4stateid_t *, int, struct nfscldevinfo *, struct nfscllayout *,
|
||||
@ -4885,14 +4885,17 @@ nfsrpc_getdeviceinfo(struct nfsmount *nmp, uint8_t *deviceid, int layouttype,
|
||||
uint32_t cnt, *tl;
|
||||
struct nfsrv_descript nfsd;
|
||||
struct nfsrv_descript *nd = &nfsd;
|
||||
struct sockaddr_storage ss;
|
||||
struct nfsclds *dsp = NULL, **dspp;
|
||||
struct sockaddr_in sin, ssin;
|
||||
struct sockaddr_in6 sin6, ssin6;
|
||||
struct nfsclds *dsp = NULL, **dspp, **gotdspp;
|
||||
struct nfscldevinfo *ndi;
|
||||
int addrcnt, bitcnt, error, i, isudp, j, pos, safilled, stripecnt;
|
||||
int addrcnt = 0, bitcnt, error, gotvers, i, isudp, j, stripecnt;
|
||||
uint8_t stripeindex;
|
||||
sa_family_t af, safilled;
|
||||
|
||||
*ndip = NULL;
|
||||
ndi = NULL;
|
||||
gotdspp = NULL;
|
||||
nfscl_reqstart(nd, NFSPROC_GETDEVICEINFO, nmp, NULL, 0, NULL, NULL, 0,
|
||||
0);
|
||||
NFSM_BUILD(tl, uint32_t *, NFSX_V4DEVICEID + 3 * NFSX_UNSIGNED);
|
||||
@ -4960,7 +4963,7 @@ nfsrpc_getdeviceinfo(struct nfsmount *nmp, uint8_t *deviceid, int layouttype,
|
||||
}
|
||||
|
||||
/* Now, dissect the server address(es). */
|
||||
safilled = 0;
|
||||
safilled = AF_UNSPEC;
|
||||
for (i = 0; i < addrcnt; i++) {
|
||||
NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
|
||||
cnt = fxdr_unsigned(uint32_t, *tl);
|
||||
@ -4970,61 +4973,65 @@ nfsrpc_getdeviceinfo(struct nfsmount *nmp, uint8_t *deviceid, int layouttype,
|
||||
goto nfsmout;
|
||||
}
|
||||
dspp = nfsfldi_addr(ndi, i);
|
||||
pos = arc4random() % cnt; /* Choose one. */
|
||||
safilled = 0;
|
||||
safilled = AF_UNSPEC;
|
||||
for (j = 0; j < cnt; j++) {
|
||||
error = nfsv4_getipaddr(nd, &ss, &isudp);
|
||||
error = nfsv4_getipaddr(nd, &sin, &sin6, &af,
|
||||
&isudp);
|
||||
if (error != 0 && error != EPERM) {
|
||||
error = NFSERR_BADXDR;
|
||||
goto nfsmout;
|
||||
}
|
||||
if (error == 0 && isudp == 0) {
|
||||
/*
|
||||
* The algorithm is:
|
||||
* - use "pos" entry if it is of the
|
||||
* same af_family or none of them
|
||||
* is of the same af_family
|
||||
* else
|
||||
* - use the first one of the same
|
||||
* af_family.
|
||||
* The priority is:
|
||||
* - Same address family.
|
||||
* Save the address and dspp, so that
|
||||
* the connection can be done after
|
||||
* parsing is complete.
|
||||
*/
|
||||
if ((safilled == 0 && ss.ss_family ==
|
||||
nmp->nm_nam->sa_family) ||
|
||||
(j == pos &&
|
||||
(safilled == 0 || ss.ss_family ==
|
||||
nmp->nm_nam->sa_family)) ||
|
||||
(safilled == 1 && ss.ss_family ==
|
||||
nmp->nm_nam->sa_family)) {
|
||||
error = nfsrpc_fillsa(nmp, &ss,
|
||||
&dsp, p);
|
||||
if (error == 0) {
|
||||
*dspp = dsp;
|
||||
if (ss.ss_family ==
|
||||
nmp->nm_nam->sa_family)
|
||||
safilled = 2;
|
||||
else
|
||||
safilled = 1;
|
||||
}
|
||||
if (safilled == AF_UNSPEC ||
|
||||
(af == nmp->nm_nam->sa_family &&
|
||||
safilled != nmp->nm_nam->sa_family)
|
||||
) {
|
||||
if (af == AF_INET)
|
||||
ssin = sin;
|
||||
else
|
||||
ssin6 = sin6;
|
||||
safilled = af;
|
||||
gotdspp = dspp;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (safilled == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
gotvers = NFS_VER4; /* Always NFSv4 for File Layout. */
|
||||
|
||||
/* And the notify bits. */
|
||||
NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
|
||||
if (safilled != 0) {
|
||||
bitcnt = fxdr_unsigned(int, *tl);
|
||||
if (bitcnt > 0) {
|
||||
NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
|
||||
if (notifybitsp != NULL)
|
||||
*notifybitsp =
|
||||
fxdr_unsigned(uint32_t, *tl);
|
||||
}
|
||||
bitcnt = fxdr_unsigned(int, *tl);
|
||||
if (bitcnt > 0) {
|
||||
NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
|
||||
if (notifybitsp != NULL)
|
||||
*notifybitsp =
|
||||
fxdr_unsigned(uint32_t, *tl);
|
||||
}
|
||||
if (safilled != AF_UNSPEC) {
|
||||
KASSERT(ndi != NULL, ("ndi is NULL"));
|
||||
*ndip = ndi;
|
||||
} else
|
||||
error = EPERM;
|
||||
if (error == 0) {
|
||||
/*
|
||||
* Now we can do a TCP connection for the correct
|
||||
* NFS version and IP address.
|
||||
*/
|
||||
error = nfsrpc_fillsa(nmp, &ssin, &ssin6, safilled,
|
||||
gotvers, &dsp, p);
|
||||
}
|
||||
if (error == 0) {
|
||||
KASSERT(gotdspp != NULL, ("gotdspp is NULL"));
|
||||
*gotdspp = dsp;
|
||||
}
|
||||
}
|
||||
if (nd->nd_repstat != 0)
|
||||
error = nd->nd_repstat;
|
||||
@ -5213,11 +5220,12 @@ nfsrpc_getlayout(struct nfsmount *nmp, vnode_t vp, struct nfsfh *nfhp,
|
||||
* mount point and a pointer to it is returned.
|
||||
*/
|
||||
static int
|
||||
nfsrpc_fillsa(struct nfsmount *nmp, struct sockaddr_storage *ssp,
|
||||
struct nfsclds **dspp, NFSPROC_T *p)
|
||||
nfsrpc_fillsa(struct nfsmount *nmp, struct sockaddr_in *sin,
|
||||
struct sockaddr_in6 *sin6, sa_family_t af, int vers, struct nfsclds **dspp,
|
||||
NFSPROC_T *p)
|
||||
{
|
||||
struct sockaddr_in *msad, *sad, *ssd;
|
||||
struct sockaddr_in6 *msad6, *sad6, *ssd6;
|
||||
struct sockaddr_in *msad, *sad;
|
||||
struct sockaddr_in6 *msad6, *sad6;
|
||||
struct nfsclclient *clp;
|
||||
struct nfssockreq *nrp;
|
||||
struct nfsclds *dsp, *tdsp;
|
||||
@ -5232,10 +5240,8 @@ nfsrpc_fillsa(struct nfsmount *nmp, struct sockaddr_storage *ssp,
|
||||
NFSUNLOCKCLSTATE();
|
||||
if (clp == NULL)
|
||||
return (EPERM);
|
||||
if (ssp->ss_family == AF_INET) {
|
||||
ssd = (struct sockaddr_in *)ssp;
|
||||
if (af == AF_INET) {
|
||||
NFSLOCKMNT(nmp);
|
||||
|
||||
/*
|
||||
* Check to see if we already have a session for this
|
||||
* address that is usable for a DS.
|
||||
@ -5246,8 +5252,8 @@ nfsrpc_fillsa(struct nfsmount *nmp, struct sockaddr_storage *ssp,
|
||||
tdsp = TAILQ_FIRST(&nmp->nm_sess);
|
||||
while (tdsp != NULL) {
|
||||
if (msad != NULL && msad->sin_family == AF_INET &&
|
||||
ssd->sin_addr.s_addr == msad->sin_addr.s_addr &&
|
||||
ssd->sin_port == msad->sin_port &&
|
||||
sin->sin_addr.s_addr == msad->sin_addr.s_addr &&
|
||||
sin->sin_port == msad->sin_port &&
|
||||
(tdsp->nfsclds_flags & NFSCLDS_DS) != 0 &&
|
||||
tdsp->nfsclds_sess.nfsess_defunct == 0) {
|
||||
*dspp = tdsp;
|
||||
@ -5268,14 +5274,12 @@ nfsrpc_fillsa(struct nfsmount *nmp, struct sockaddr_storage *ssp,
|
||||
sad = malloc(sizeof(*sad), M_SONAME, M_WAITOK | M_ZERO);
|
||||
sad->sin_len = sizeof(*sad);
|
||||
sad->sin_family = AF_INET;
|
||||
sad->sin_port = ssd->sin_port;
|
||||
sad->sin_addr.s_addr = ssd->sin_addr.s_addr;
|
||||
sad->sin_port = sin->sin_port;
|
||||
sad->sin_addr.s_addr = sin->sin_addr.s_addr;
|
||||
nrp = malloc(sizeof(*nrp), M_NFSSOCKREQ, M_WAITOK | M_ZERO);
|
||||
nrp->nr_nam = (struct sockaddr *)sad;
|
||||
} else if (ssp->ss_family == AF_INET6) {
|
||||
ssd6 = (struct sockaddr_in6 *)ssp;
|
||||
} else if (af == AF_INET6) {
|
||||
NFSLOCKMNT(nmp);
|
||||
|
||||
/*
|
||||
* Check to see if we already have a session for this
|
||||
* address that is usable for a DS.
|
||||
@ -5286,9 +5290,9 @@ nfsrpc_fillsa(struct nfsmount *nmp, struct sockaddr_storage *ssp,
|
||||
tdsp = TAILQ_FIRST(&nmp->nm_sess);
|
||||
while (tdsp != NULL) {
|
||||
if (msad6 != NULL && msad6->sin6_family == AF_INET6 &&
|
||||
IN6_ARE_ADDR_EQUAL(&ssd6->sin6_addr,
|
||||
IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr,
|
||||
&msad6->sin6_addr) &&
|
||||
ssd6->sin6_port == msad6->sin6_port &&
|
||||
sin6->sin6_port == msad6->sin6_port &&
|
||||
(tdsp->nfsclds_flags & NFSCLDS_DS) != 0 &&
|
||||
tdsp->nfsclds_sess.nfsess_defunct == 0) {
|
||||
*dspp = tdsp;
|
||||
@ -5308,8 +5312,8 @@ nfsrpc_fillsa(struct nfsmount *nmp, struct sockaddr_storage *ssp,
|
||||
sad6 = malloc(sizeof(*sad6), M_SONAME, M_WAITOK | M_ZERO);
|
||||
sad6->sin6_len = sizeof(*sad6);
|
||||
sad6->sin6_family = AF_INET6;
|
||||
sad6->sin6_port = ssd6->sin6_port;
|
||||
NFSBCOPY(&ssd6->sin6_addr, &sad6->sin6_addr,
|
||||
sad6->sin6_port = sin6->sin6_port;
|
||||
NFSBCOPY(&sin6->sin6_addr, &sad6->sin6_addr,
|
||||
sizeof(struct in6_addr));
|
||||
nrp = malloc(sizeof(*nrp), M_NFSSOCKREQ, M_WAITOK | M_ZERO);
|
||||
nrp->nr_nam = (struct sockaddr *)sad6;
|
||||
@ -5319,7 +5323,7 @@ nfsrpc_fillsa(struct nfsmount *nmp, struct sockaddr_storage *ssp,
|
||||
nrp->nr_sotype = SOCK_STREAM;
|
||||
mtx_init(&nrp->nr_mtx, "nfssock", NULL, MTX_DEF);
|
||||
nrp->nr_prog = NFS_PROG;
|
||||
nrp->nr_vers = NFS_VER4;
|
||||
nrp->nr_vers = vers;
|
||||
|
||||
/*
|
||||
* Use the credentials that were used for the mount, which are
|
||||
|
Loading…
Reference in New Issue
Block a user