diff options
Diffstat (limited to 'net/sunrpc/rpcb_clnt.c')
-rw-r--r-- | net/sunrpc/rpcb_clnt.c | 103 |
1 files changed, 60 insertions, 43 deletions
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index 03ae007641e4..beee6da33035 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c | |||
@@ -63,9 +63,16 @@ enum { | |||
63 | * r_owner | 63 | * r_owner |
64 | * | 64 | * |
65 | * The "owner" is allowed to unset a service in the rpcbind database. | 65 | * The "owner" is allowed to unset a service in the rpcbind database. |
66 | * We always use the following (arbitrary) fixed string. | 66 | * |
67 | * For AF_LOCAL SET/UNSET requests, rpcbind treats this string as a | ||
68 | * UID which it maps to a local user name via a password lookup. | ||
69 | * In all other cases it is ignored. | ||
70 | * | ||
71 | * For SET/UNSET requests, user space provides a value, even for | ||
72 | * network requests, and GETADDR uses an empty string. We follow | ||
73 | * those precedents here. | ||
67 | */ | 74 | */ |
68 | #define RPCB_OWNER_STRING "rpcb" | 75 | #define RPCB_OWNER_STRING "0" |
69 | #define RPCB_MAXOWNERLEN sizeof(RPCB_OWNER_STRING) | 76 | #define RPCB_MAXOWNERLEN sizeof(RPCB_OWNER_STRING) |
70 | 77 | ||
71 | static void rpcb_getport_done(struct rpc_task *, void *); | 78 | static void rpcb_getport_done(struct rpc_task *, void *); |
@@ -124,12 +131,6 @@ static const struct sockaddr_in rpcb_inaddr_loopback = { | |||
124 | .sin_port = htons(RPCBIND_PORT), | 131 | .sin_port = htons(RPCBIND_PORT), |
125 | }; | 132 | }; |
126 | 133 | ||
127 | static const struct sockaddr_in6 rpcb_in6addr_loopback = { | ||
128 | .sin6_family = AF_INET6, | ||
129 | .sin6_addr = IN6ADDR_LOOPBACK_INIT, | ||
130 | .sin6_port = htons(RPCBIND_PORT), | ||
131 | }; | ||
132 | |||
133 | static struct rpc_clnt *rpcb_create_local(struct sockaddr *addr, | 134 | static struct rpc_clnt *rpcb_create_local(struct sockaddr *addr, |
134 | size_t addrlen, u32 version) | 135 | size_t addrlen, u32 version) |
135 | { | 136 | { |
@@ -176,9 +177,10 @@ static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr, | |||
176 | return rpc_create(&args); | 177 | return rpc_create(&args); |
177 | } | 178 | } |
178 | 179 | ||
179 | static int rpcb_register_call(struct sockaddr *addr, size_t addrlen, | 180 | static int rpcb_register_call(const u32 version, struct rpc_message *msg) |
180 | u32 version, struct rpc_message *msg) | ||
181 | { | 181 | { |
182 | struct sockaddr *addr = (struct sockaddr *)&rpcb_inaddr_loopback; | ||
183 | size_t addrlen = sizeof(rpcb_inaddr_loopback); | ||
182 | struct rpc_clnt *rpcb_clnt; | 184 | struct rpc_clnt *rpcb_clnt; |
183 | int result, error = 0; | 185 | int result, error = 0; |
184 | 186 | ||
@@ -192,7 +194,7 @@ static int rpcb_register_call(struct sockaddr *addr, size_t addrlen, | |||
192 | error = PTR_ERR(rpcb_clnt); | 194 | error = PTR_ERR(rpcb_clnt); |
193 | 195 | ||
194 | if (error < 0) { | 196 | if (error < 0) { |
195 | printk(KERN_WARNING "RPC: failed to contact local rpcbind " | 197 | dprintk("RPC: failed to contact local rpcbind " |
196 | "server (errno %d).\n", -error); | 198 | "server (errno %d).\n", -error); |
197 | return error; | 199 | return error; |
198 | } | 200 | } |
@@ -254,25 +256,23 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port) | |||
254 | if (port) | 256 | if (port) |
255 | msg.rpc_proc = &rpcb_procedures2[RPCBPROC_SET]; | 257 | msg.rpc_proc = &rpcb_procedures2[RPCBPROC_SET]; |
256 | 258 | ||
257 | return rpcb_register_call((struct sockaddr *)&rpcb_inaddr_loopback, | 259 | return rpcb_register_call(RPCBVERS_2, &msg); |
258 | sizeof(rpcb_inaddr_loopback), | ||
259 | RPCBVERS_2, &msg); | ||
260 | } | 260 | } |
261 | 261 | ||
262 | /* | 262 | /* |
263 | * Fill in AF_INET family-specific arguments to register | 263 | * Fill in AF_INET family-specific arguments to register |
264 | */ | 264 | */ |
265 | static int rpcb_register_netid4(struct sockaddr_in *address_to_register, | 265 | static int rpcb_register_inet4(const struct sockaddr *sap, |
266 | struct rpc_message *msg) | 266 | struct rpc_message *msg) |
267 | { | 267 | { |
268 | const struct sockaddr_in *sin = (const struct sockaddr_in *)sap; | ||
268 | struct rpcbind_args *map = msg->rpc_argp; | 269 | struct rpcbind_args *map = msg->rpc_argp; |
269 | unsigned short port = ntohs(address_to_register->sin_port); | 270 | unsigned short port = ntohs(sin->sin_port); |
270 | char buf[32]; | 271 | char buf[32]; |
271 | 272 | ||
272 | /* Construct AF_INET universal address */ | 273 | /* Construct AF_INET universal address */ |
273 | snprintf(buf, sizeof(buf), "%pI4.%u.%u", | 274 | snprintf(buf, sizeof(buf), "%pI4.%u.%u", |
274 | &address_to_register->sin_addr.s_addr, | 275 | &sin->sin_addr.s_addr, port >> 8, port & 0xff); |
275 | port >> 8, port & 0xff); | ||
276 | map->r_addr = buf; | 276 | map->r_addr = buf; |
277 | 277 | ||
278 | dprintk("RPC: %sregistering [%u, %u, %s, '%s'] with " | 278 | dprintk("RPC: %sregistering [%u, %u, %s, '%s'] with " |
@@ -284,29 +284,27 @@ static int rpcb_register_netid4(struct sockaddr_in *address_to_register, | |||
284 | if (port) | 284 | if (port) |
285 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; | 285 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; |
286 | 286 | ||
287 | return rpcb_register_call((struct sockaddr *)&rpcb_inaddr_loopback, | 287 | return rpcb_register_call(RPCBVERS_4, msg); |
288 | sizeof(rpcb_inaddr_loopback), | ||
289 | RPCBVERS_4, msg); | ||
290 | } | 288 | } |
291 | 289 | ||
292 | /* | 290 | /* |
293 | * Fill in AF_INET6 family-specific arguments to register | 291 | * Fill in AF_INET6 family-specific arguments to register |
294 | */ | 292 | */ |
295 | static int rpcb_register_netid6(struct sockaddr_in6 *address_to_register, | 293 | static int rpcb_register_inet6(const struct sockaddr *sap, |
296 | struct rpc_message *msg) | 294 | struct rpc_message *msg) |
297 | { | 295 | { |
296 | const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sap; | ||
298 | struct rpcbind_args *map = msg->rpc_argp; | 297 | struct rpcbind_args *map = msg->rpc_argp; |
299 | unsigned short port = ntohs(address_to_register->sin6_port); | 298 | unsigned short port = ntohs(sin6->sin6_port); |
300 | char buf[64]; | 299 | char buf[64]; |
301 | 300 | ||
302 | /* Construct AF_INET6 universal address */ | 301 | /* Construct AF_INET6 universal address */ |
303 | if (ipv6_addr_any(&address_to_register->sin6_addr)) | 302 | if (ipv6_addr_any(&sin6->sin6_addr)) |
304 | snprintf(buf, sizeof(buf), "::.%u.%u", | 303 | snprintf(buf, sizeof(buf), "::.%u.%u", |
305 | port >> 8, port & 0xff); | 304 | port >> 8, port & 0xff); |
306 | else | 305 | else |
307 | snprintf(buf, sizeof(buf), "%pI6.%u.%u", | 306 | snprintf(buf, sizeof(buf), "%pI6.%u.%u", |
308 | &address_to_register->sin6_addr, | 307 | &sin6->sin6_addr, port >> 8, port & 0xff); |
309 | port >> 8, port & 0xff); | ||
310 | map->r_addr = buf; | 308 | map->r_addr = buf; |
311 | 309 | ||
312 | dprintk("RPC: %sregistering [%u, %u, %s, '%s'] with " | 310 | dprintk("RPC: %sregistering [%u, %u, %s, '%s'] with " |
@@ -318,9 +316,21 @@ static int rpcb_register_netid6(struct sockaddr_in6 *address_to_register, | |||
318 | if (port) | 316 | if (port) |
319 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; | 317 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; |
320 | 318 | ||
321 | return rpcb_register_call((struct sockaddr *)&rpcb_in6addr_loopback, | 319 | return rpcb_register_call(RPCBVERS_4, msg); |
322 | sizeof(rpcb_in6addr_loopback), | 320 | } |
323 | RPCBVERS_4, msg); | 321 | |
322 | static int rpcb_unregister_all_protofamilies(struct rpc_message *msg) | ||
323 | { | ||
324 | struct rpcbind_args *map = msg->rpc_argp; | ||
325 | |||
326 | dprintk("RPC: unregistering [%u, %u, '%s'] with " | ||
327 | "local rpcbind\n", | ||
328 | map->r_prog, map->r_vers, map->r_netid); | ||
329 | |||
330 | map->r_addr = ""; | ||
331 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET]; | ||
332 | |||
333 | return rpcb_register_call(RPCBVERS_4, msg); | ||
324 | } | 334 | } |
325 | 335 | ||
326 | /** | 336 | /** |
@@ -340,10 +350,11 @@ static int rpcb_register_netid6(struct sockaddr_in6 *address_to_register, | |||
340 | * invoke this function once for each [program, version, address, | 350 | * invoke this function once for each [program, version, address, |
341 | * netid] tuple they wish to advertise. | 351 | * netid] tuple they wish to advertise. |
342 | * | 352 | * |
343 | * Callers may also unregister RPC services that are no longer | 353 | * Callers may also unregister RPC services that are registered at a |
344 | * available by setting the port number in the passed-in address | 354 | * specific address by setting the port number in @address to zero. |
345 | * to zero. Callers pass a netid of "" to unregister all | 355 | * They may unregister all registered protocol families at once for |
346 | * transport netids associated with [program, version, address]. | 356 | * a service by passing a NULL @address argument. If @netid is "" |
357 | * then all netids for [program, version, address] are unregistered. | ||
347 | * | 358 | * |
348 | * This function uses rpcbind protocol version 4 to contact the | 359 | * This function uses rpcbind protocol version 4 to contact the |
349 | * local rpcbind daemon. The local rpcbind daemon must support | 360 | * local rpcbind daemon. The local rpcbind daemon must support |
@@ -378,13 +389,14 @@ int rpcb_v4_register(const u32 program, const u32 version, | |||
378 | .rpc_argp = &map, | 389 | .rpc_argp = &map, |
379 | }; | 390 | }; |
380 | 391 | ||
392 | if (address == NULL) | ||
393 | return rpcb_unregister_all_protofamilies(&msg); | ||
394 | |||
381 | switch (address->sa_family) { | 395 | switch (address->sa_family) { |
382 | case AF_INET: | 396 | case AF_INET: |
383 | return rpcb_register_netid4((struct sockaddr_in *)address, | 397 | return rpcb_register_inet4(address, &msg); |
384 | &msg); | ||
385 | case AF_INET6: | 398 | case AF_INET6: |
386 | return rpcb_register_netid6((struct sockaddr_in6 *)address, | 399 | return rpcb_register_inet6(address, &msg); |
387 | &msg); | ||
388 | } | 400 | } |
389 | 401 | ||
390 | return -EAFNOSUPPORT; | 402 | return -EAFNOSUPPORT; |
@@ -579,7 +591,7 @@ void rpcb_getport_async(struct rpc_task *task) | |||
579 | map->r_xprt = xprt_get(xprt); | 591 | map->r_xprt = xprt_get(xprt); |
580 | map->r_netid = rpc_peeraddr2str(clnt, RPC_DISPLAY_NETID); | 592 | map->r_netid = rpc_peeraddr2str(clnt, RPC_DISPLAY_NETID); |
581 | map->r_addr = rpc_peeraddr2str(rpcb_clnt, RPC_DISPLAY_UNIVERSAL_ADDR); | 593 | map->r_addr = rpc_peeraddr2str(rpcb_clnt, RPC_DISPLAY_UNIVERSAL_ADDR); |
582 | map->r_owner = RPCB_OWNER_STRING; /* ignored for GETADDR */ | 594 | map->r_owner = ""; |
583 | map->r_status = -EIO; | 595 | map->r_status = -EIO; |
584 | 596 | ||
585 | child = rpcb_call_async(rpcb_clnt, map, proc); | 597 | child = rpcb_call_async(rpcb_clnt, map, proc); |
@@ -703,11 +715,16 @@ static int rpcb_decode_getaddr(struct rpc_rqst *req, __be32 *p, | |||
703 | *portp = 0; | 715 | *portp = 0; |
704 | addr_len = ntohl(*p++); | 716 | addr_len = ntohl(*p++); |
705 | 717 | ||
718 | if (addr_len == 0) { | ||
719 | dprintk("RPC: rpcb_decode_getaddr: " | ||
720 | "service is not registered\n"); | ||
721 | return 0; | ||
722 | } | ||
723 | |||
706 | /* | 724 | /* |
707 | * Simple sanity check. The smallest possible universal | 725 | * Simple sanity check. |
708 | * address is an IPv4 address string containing 11 bytes. | ||
709 | */ | 726 | */ |
710 | if (addr_len < 11 || addr_len > RPCBIND_MAXUADDRLEN) | 727 | if (addr_len > RPCBIND_MAXUADDRLEN) |
711 | goto out_err; | 728 | goto out_err; |
712 | 729 | ||
713 | /* | 730 | /* |