Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

SUNRPC: Replace svc_addr_u by sockaddr_storage

For IPv6 local address, lockd can not callback to client for
missing scope id when binding address at inet6_bind:

324 if (addr_type & IPV6_ADDR_LINKLOCAL) {
325 if (addr_len >= sizeof(struct sockaddr_in6) &&
326 addr->sin6_scope_id) {
327 /* Override any existing binding, if another one
328 * is supplied by user.
329 */
330 sk->sk_bound_dev_if = addr->sin6_scope_id;
331 }
332
333 /* Binding to link-local address requires an interface */
334 if (!sk->sk_bound_dev_if) {
335 err = -EINVAL;
336 goto out_unlock;
337 }

Replacing svc_addr_u by sockaddr_storage, let rqstp->rq_daddr contains more info
besides address.

Reviewed-by: Jeff Layton <jlayton@redhat.com>
Reviewed-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Mi Jinlong <mijinlong@cn.fujitsu.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>

authored by

Mi Jinlong and committed by
J. Bruce Fields
849a1cf1 11fcee02

+43 -64
+2 -23
fs/lockd/host.c
··· 316 316 struct hlist_node *pos; 317 317 struct nlm_host *host = NULL; 318 318 struct nsm_handle *nsm = NULL; 319 - struct sockaddr_in sin = { 320 - .sin_family = AF_INET, 321 - }; 322 - struct sockaddr_in6 sin6 = { 323 - .sin6_family = AF_INET6, 324 - }; 325 - struct sockaddr *src_sap; 326 - size_t src_len = rqstp->rq_addrlen; 319 + struct sockaddr *src_sap = svc_daddr(rqstp); 320 + size_t src_len = rqstp->rq_daddrlen; 327 321 struct nlm_lookup_host_info ni = { 328 322 .server = 1, 329 323 .sap = svc_addr(rqstp), ··· 333 339 (rqstp->rq_prot == IPPROTO_UDP ? "udp" : "tcp")); 334 340 335 341 mutex_lock(&nlm_host_mutex); 336 - 337 - switch (ni.sap->sa_family) { 338 - case AF_INET: 339 - sin.sin_addr.s_addr = rqstp->rq_daddr.addr.s_addr; 340 - src_sap = (struct sockaddr *)&sin; 341 - break; 342 - case AF_INET6: 343 - ipv6_addr_copy(&sin6.sin6_addr, &rqstp->rq_daddr.addr6); 344 - src_sap = (struct sockaddr *)&sin6; 345 - break; 346 - default: 347 - dprintk("lockd: %s failed; unrecognized address family\n", 348 - __func__); 349 - goto out; 350 - } 351 342 352 343 if (time_after_eq(jiffies, next_gc)) 353 344 nlm_gc_hosts();
+1 -15
fs/nfsd/nfs4state.c
··· 1257 1257 return NULL; 1258 1258 } 1259 1259 1260 - static void rpc_svcaddr2sockaddr(struct sockaddr *sa, unsigned short family, union svc_addr_u *svcaddr) 1261 - { 1262 - switch (family) { 1263 - case AF_INET: 1264 - ((struct sockaddr_in *)sa)->sin_family = AF_INET; 1265 - ((struct sockaddr_in *)sa)->sin_addr = svcaddr->addr; 1266 - return; 1267 - case AF_INET6: 1268 - ((struct sockaddr_in6 *)sa)->sin6_family = AF_INET6; 1269 - ((struct sockaddr_in6 *)sa)->sin6_addr = svcaddr->addr6; 1270 - return; 1271 - } 1272 - } 1273 - 1274 1260 static void 1275 1261 gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se, struct svc_rqst *rqstp) 1276 1262 { ··· 1288 1302 1289 1303 conn->cb_prog = se->se_callback_prog; 1290 1304 conn->cb_ident = se->se_callback_ident; 1291 - rpc_svcaddr2sockaddr((struct sockaddr *)&conn->cb_saddr, expected_family, &rqstp->rq_daddr); 1305 + memcpy(&conn->cb_saddr, &rqstp->rq_daddr, rqstp->rq_daddrlen); 1292 1306 return; 1293 1307 out_err: 1294 1308 conn->cb_addr.ss_family = AF_UNSPEC;
+21 -9
include/linux/sunrpc/svc.h
··· 212 212 iov->iov_len += sizeof(__be32); 213 213 } 214 214 215 - union svc_addr_u { 216 - struct in_addr addr; 217 - struct in6_addr addr6; 218 - }; 219 - 220 215 /* 221 216 * The context of a single thread, including the request currently being 222 217 * processed. ··· 220 225 struct list_head rq_list; /* idle list */ 221 226 struct list_head rq_all; /* all threads list */ 222 227 struct svc_xprt * rq_xprt; /* transport ptr */ 228 + 223 229 struct sockaddr_storage rq_addr; /* peer address */ 224 230 size_t rq_addrlen; 231 + struct sockaddr_storage rq_daddr; /* dest addr of request 232 + * - reply from here */ 233 + size_t rq_daddrlen; 225 234 226 235 struct svc_serv * rq_server; /* RPC service definition */ 227 236 struct svc_pool * rq_pool; /* thread pool */ ··· 253 254 u32 rq_prot; /* IP protocol */ 254 255 unsigned short 255 256 rq_secure : 1; /* secure port */ 256 - 257 - union svc_addr_u rq_daddr; /* dest addr of request 258 - * - reply from here */ 259 257 260 258 void * rq_argp; /* decoded arguments */ 261 259 void * rq_resp; /* xdr'd results */ ··· 296 300 return (struct sockaddr *) &rqst->rq_addr; 297 301 } 298 302 303 + static inline struct sockaddr_in *svc_daddr_in(const struct svc_rqst *rqst) 304 + { 305 + return (struct sockaddr_in *) &rqst->rq_daddr; 306 + } 307 + 308 + static inline struct sockaddr_in6 *svc_daddr_in6(const struct svc_rqst *rqst) 309 + { 310 + return (struct sockaddr_in6 *) &rqst->rq_daddr; 311 + } 312 + 313 + static inline struct sockaddr *svc_daddr(const struct svc_rqst *rqst) 314 + { 315 + return (struct sockaddr *) &rqst->rq_daddr; 316 + } 317 + 299 318 /* 300 319 * Check buffer bounds after decoding arguments 301 320 */ ··· 351 340 struct svc_xprt *xprt; 352 341 struct sockaddr_storage addr; /* where reply must go */ 353 342 size_t addrlen; 354 - union svc_addr_u daddr; /* where reply must come from */ 343 + struct sockaddr_storage daddr; /* where reply must come from */ 344 + size_t daddrlen; 355 345 struct cache_deferred_req handle; 356 346 size_t xprt_hlen; 357 347 int argslen;
+2 -11
net/sunrpc/svc_xprt.c
··· 254 254 */ 255 255 void svc_xprt_copy_addrs(struct svc_rqst *rqstp, struct svc_xprt *xprt) 256 256 { 257 - struct sockaddr *sin; 258 - 259 257 memcpy(&rqstp->rq_addr, &xprt->xpt_remote, xprt->xpt_remotelen); 260 258 rqstp->rq_addrlen = xprt->xpt_remotelen; 261 259 ··· 261 263 * Destination address in request is needed for binding the 262 264 * source address in RPC replies/callbacks later. 263 265 */ 264 - sin = (struct sockaddr *)&xprt->xpt_local; 265 - switch (sin->sa_family) { 266 - case AF_INET: 267 - rqstp->rq_daddr.addr = ((struct sockaddr_in *)sin)->sin_addr; 268 - break; 269 - case AF_INET6: 270 - rqstp->rq_daddr.addr6 = ((struct sockaddr_in6 *)sin)->sin6_addr; 271 - break; 272 - } 266 + memcpy(&rqstp->rq_daddr, &xprt->xpt_local, xprt->xpt_locallen); 267 + rqstp->rq_daddrlen = xprt->xpt_locallen; 273 268 } 274 269 EXPORT_SYMBOL_GPL(svc_xprt_copy_addrs); 275 270
+17 -6
net/sunrpc/svcsock.c
··· 143 143 cmh->cmsg_level = SOL_IP; 144 144 cmh->cmsg_type = IP_PKTINFO; 145 145 pki->ipi_ifindex = 0; 146 - pki->ipi_spec_dst.s_addr = rqstp->rq_daddr.addr.s_addr; 146 + pki->ipi_spec_dst.s_addr = 147 + svc_daddr_in(rqstp)->sin_addr.s_addr; 147 148 cmh->cmsg_len = CMSG_LEN(sizeof(*pki)); 148 149 } 149 150 break; 150 151 151 152 case AF_INET6: { 152 153 struct in6_pktinfo *pki = CMSG_DATA(cmh); 154 + struct sockaddr_in6 *daddr = svc_daddr_in6(rqstp); 153 155 154 156 cmh->cmsg_level = SOL_IPV6; 155 157 cmh->cmsg_type = IPV6_PKTINFO; 156 - pki->ipi6_ifindex = 0; 157 - ipv6_addr_copy(&pki->ipi6_addr, 158 - &rqstp->rq_daddr.addr6); 158 + pki->ipi6_ifindex = daddr->sin6_scope_id; 159 + ipv6_addr_copy(&pki->ipi6_addr, &daddr->sin6_addr); 159 160 cmh->cmsg_len = CMSG_LEN(sizeof(*pki)); 160 161 } 161 162 break; ··· 499 498 struct cmsghdr *cmh) 500 499 { 501 500 struct in_pktinfo *pki = CMSG_DATA(cmh); 501 + struct sockaddr_in *daddr = svc_daddr_in(rqstp); 502 + 502 503 if (cmh->cmsg_type != IP_PKTINFO) 503 504 return 0; 504 - rqstp->rq_daddr.addr.s_addr = pki->ipi_spec_dst.s_addr; 505 + 506 + daddr->sin_family = AF_INET; 507 + daddr->sin_addr.s_addr = pki->ipi_spec_dst.s_addr; 505 508 return 1; 506 509 } 507 510 ··· 516 511 struct cmsghdr *cmh) 517 512 { 518 513 struct in6_pktinfo *pki = CMSG_DATA(cmh); 514 + struct sockaddr_in6 *daddr = svc_daddr_in6(rqstp); 515 + 519 516 if (cmh->cmsg_type != IPV6_PKTINFO) 520 517 return 0; 521 - ipv6_addr_copy(&rqstp->rq_daddr.addr6, &pki->ipi6_addr); 518 + 519 + daddr->sin6_family = AF_INET6; 520 + ipv6_addr_copy(&daddr->sin6_addr, &pki->ipi6_addr); 521 + daddr->sin6_scope_id = pki->ipi6_ifindex; 522 522 return 1; 523 523 } 524 524 ··· 624 614 skb_free_datagram_locked(svsk->sk_sk, skb); 625 615 return 0; 626 616 } 617 + rqstp->rq_daddrlen = svc_addr_len(svc_daddr(rqstp)); 627 618 628 619 if (skb_is_nonlinear(skb)) { 629 620 /* we have to copy */