diff options
Diffstat (limited to 'fs/lockd/host.c')
-rw-r--r-- | fs/lockd/host.c | 47 |
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 | */ |
310 | struct nlm_host * | 325 | struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp, |
311 | nlmsvc_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 | ||