aboutsummaryrefslogtreecommitdiffstats
path: root/fs/lockd/host.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/lockd/host.c')
-rw-r--r--fs/lockd/host.c47
1 files changed, 38 insertions, 9 deletions
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index cbd2398e594c..9fd8889097b7 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -304,16 +304,33 @@ struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap,
304 return nlm_lookup_host(&ni); 304 return nlm_lookup_host(&ni);
305} 305}
306 306
307/* 307/**
308 * Find an NLM client handle in the cache. If there is none, create it. 308 * nlmsvc_lookup_host - Find an NLM host handle matching a remote client
309 * @rqstp: incoming NLM request
310 * @hostname: name of client host
311 * @hostname_len: length of client hostname
312 *
313 * Returns an nlm_host structure that matches the [client address,
314 * transport protocol, NLM version, client hostname] of the passed-in
315 * NLM request. If one doesn't already exist in the host cache, a
316 * new handle is created and returned.
317 *
318 * Before possibly creating a new nlm_host, construct a sockaddr
319 * for a specific source address in case the local system has
320 * multiple network addresses. The family of the address in
321 * rq_daddr is guaranteed to be the same as the family of the
322 * address in rq_addr, so it's safe to use the same family for
323 * the source address.
309 */ 324 */
310struct nlm_host * 325struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp,
311nlmsvc_lookup_host(struct svc_rqst *rqstp, 326 const char *hostname,
312 const char *hostname, unsigned int hostname_len) 327 const size_t hostname_len)
313{ 328{
314 const struct sockaddr_in source = { 329 struct sockaddr_in sin = {
315 .sin_family = AF_INET, 330 .sin_family = AF_INET,
316 .sin_addr = rqstp->rq_daddr.addr, 331 };
332 struct sockaddr_in6 sin6 = {
333 .sin6_family = AF_INET6,
317 }; 334 };
318 struct nlm_lookup_host_info ni = { 335 struct nlm_lookup_host_info ni = {
319 .server = 1, 336 .server = 1,
@@ -323,14 +340,26 @@ nlmsvc_lookup_host(struct svc_rqst *rqstp,
323 .version = rqstp->rq_vers, 340 .version = rqstp->rq_vers,
324 .hostname = hostname, 341 .hostname = hostname,
325 .hostname_len = hostname_len, 342 .hostname_len = hostname_len,
326 .src_sap = (struct sockaddr *)&source, 343 .src_len = rqstp->rq_addrlen,
327 .src_len = sizeof(source),
328 }; 344 };
329 345
330 dprintk("lockd: %s(host='%*s', vers=%u, proto=%s)\n", __func__, 346 dprintk("lockd: %s(host='%*s', vers=%u, proto=%s)\n", __func__,
331 (int)hostname_len, hostname, rqstp->rq_vers, 347 (int)hostname_len, hostname, rqstp->rq_vers,
332 (rqstp->rq_prot == IPPROTO_UDP ? "udp" : "tcp")); 348 (rqstp->rq_prot == IPPROTO_UDP ? "udp" : "tcp"));
333 349
350 switch (ni.sap->sa_family) {
351 case AF_INET:
352 sin.sin_addr.s_addr = rqstp->rq_daddr.addr.s_addr;
353 ni.src_sap = (struct sockaddr *)&sin;
354 break;
355 case AF_INET6:
356 ipv6_addr_copy(&sin6.sin6_addr, &rqstp->rq_daddr.addr6);
357 ni.src_sap = (struct sockaddr *)&sin6;
358 break;
359 default:
360 return NULL;
361 }
362
334 return nlm_lookup_host(&ni); 363 return nlm_lookup_host(&ni);
335} 364}
336 365