diff options
Diffstat (limited to 'net/sunrpc')
-rw-r--r-- | net/sunrpc/clnt.c | 2 | ||||
-rw-r--r-- | net/sunrpc/rpcb_clnt.c | 81 | ||||
-rw-r--r-- | net/sunrpc/svc.c | 251 | ||||
-rw-r--r-- | net/sunrpc/svc_xprt.c | 39 | ||||
-rw-r--r-- | net/sunrpc/svcsock.c | 17 |
5 files changed, 305 insertions, 85 deletions
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 76739e928d0d..da0789fa1b88 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -174,7 +174,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru | |||
174 | clnt->cl_procinfo = version->procs; | 174 | clnt->cl_procinfo = version->procs; |
175 | clnt->cl_maxproc = version->nrprocs; | 175 | clnt->cl_maxproc = version->nrprocs; |
176 | clnt->cl_protname = program->name; | 176 | clnt->cl_protname = program->name; |
177 | clnt->cl_prog = program->number; | 177 | clnt->cl_prog = args->prognumber ? : program->number; |
178 | clnt->cl_vers = version->number; | 178 | clnt->cl_vers = version->number; |
179 | clnt->cl_stats = program->stats; | 179 | clnt->cl_stats = program->stats; |
180 | clnt->cl_metrics = rpc_alloc_iostats(clnt); | 180 | clnt->cl_metrics = rpc_alloc_iostats(clnt); |
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index 24db2b4d12d3..34abc91058d8 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/in6.h> | 20 | #include <linux/in6.h> |
21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
22 | #include <linux/errno.h> | 22 | #include <linux/errno.h> |
23 | #include <net/ipv6.h> | ||
23 | 24 | ||
24 | #include <linux/sunrpc/clnt.h> | 25 | #include <linux/sunrpc/clnt.h> |
25 | #include <linux/sunrpc/sched.h> | 26 | #include <linux/sunrpc/sched.h> |
@@ -176,13 +177,12 @@ static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr, | |||
176 | } | 177 | } |
177 | 178 | ||
178 | static int rpcb_register_call(struct sockaddr *addr, size_t addrlen, | 179 | static int rpcb_register_call(struct sockaddr *addr, size_t addrlen, |
179 | u32 version, struct rpc_message *msg, | 180 | u32 version, struct rpc_message *msg) |
180 | int *result) | ||
181 | { | 181 | { |
182 | struct rpc_clnt *rpcb_clnt; | 182 | struct rpc_clnt *rpcb_clnt; |
183 | int error = 0; | 183 | int result, error = 0; |
184 | 184 | ||
185 | *result = 0; | 185 | msg->rpc_resp = &result; |
186 | 186 | ||
187 | rpcb_clnt = rpcb_create_local(addr, addrlen, version); | 187 | rpcb_clnt = rpcb_create_local(addr, addrlen, version); |
188 | if (!IS_ERR(rpcb_clnt)) { | 188 | if (!IS_ERR(rpcb_clnt)) { |
@@ -191,12 +191,15 @@ static int rpcb_register_call(struct sockaddr *addr, size_t addrlen, | |||
191 | } else | 191 | } else |
192 | error = PTR_ERR(rpcb_clnt); | 192 | error = PTR_ERR(rpcb_clnt); |
193 | 193 | ||
194 | if (error < 0) | 194 | if (error < 0) { |
195 | printk(KERN_WARNING "RPC: failed to contact local rpcbind " | 195 | printk(KERN_WARNING "RPC: failed to contact local rpcbind " |
196 | "server (errno %d).\n", -error); | 196 | "server (errno %d).\n", -error); |
197 | dprintk("RPC: registration status %d/%d\n", error, *result); | 197 | return error; |
198 | } | ||
198 | 199 | ||
199 | return error; | 200 | if (!result) |
201 | return -EACCES; | ||
202 | return 0; | ||
200 | } | 203 | } |
201 | 204 | ||
202 | /** | 205 | /** |
@@ -205,7 +208,11 @@ static int rpcb_register_call(struct sockaddr *addr, size_t addrlen, | |||
205 | * @vers: RPC version number to bind | 208 | * @vers: RPC version number to bind |
206 | * @prot: transport protocol to register | 209 | * @prot: transport protocol to register |
207 | * @port: port value to register | 210 | * @port: port value to register |
208 | * @okay: OUT: result code | 211 | * |
212 | * Returns zero if the registration request was dispatched successfully | ||
213 | * and the rpcbind daemon returned success. Otherwise, returns an errno | ||
214 | * value that reflects the nature of the error (request could not be | ||
215 | * dispatched, timed out, or rpcbind returned an error). | ||
209 | * | 216 | * |
210 | * RPC services invoke this function to advertise their contact | 217 | * RPC services invoke this function to advertise their contact |
211 | * information via the system's rpcbind daemon. RPC services | 218 | * information via the system's rpcbind daemon. RPC services |
@@ -217,15 +224,6 @@ static int rpcb_register_call(struct sockaddr *addr, size_t addrlen, | |||
217 | * all registered transports for [program, version] from the local | 224 | * all registered transports for [program, version] from the local |
218 | * rpcbind database. | 225 | * rpcbind database. |
219 | * | 226 | * |
220 | * Returns zero if the registration request was dispatched | ||
221 | * successfully and a reply was received. The rpcbind daemon's | ||
222 | * boolean result code is stored in *okay. | ||
223 | * | ||
224 | * Returns an errno value and sets *result to zero if there was | ||
225 | * some problem that prevented the rpcbind request from being | ||
226 | * dispatched, or if the rpcbind daemon did not respond within | ||
227 | * the timeout. | ||
228 | * | ||
229 | * This function uses rpcbind protocol version 2 to contact the | 227 | * This function uses rpcbind protocol version 2 to contact the |
230 | * local rpcbind daemon. | 228 | * local rpcbind daemon. |
231 | * | 229 | * |
@@ -236,7 +234,7 @@ static int rpcb_register_call(struct sockaddr *addr, size_t addrlen, | |||
236 | * IN6ADDR_ANY (ie available for all AF_INET and AF_INET6 | 234 | * IN6ADDR_ANY (ie available for all AF_INET and AF_INET6 |
237 | * addresses). | 235 | * addresses). |
238 | */ | 236 | */ |
239 | int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay) | 237 | int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port) |
240 | { | 238 | { |
241 | struct rpcbind_args map = { | 239 | struct rpcbind_args map = { |
242 | .r_prog = prog, | 240 | .r_prog = prog, |
@@ -246,7 +244,6 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay) | |||
246 | }; | 244 | }; |
247 | struct rpc_message msg = { | 245 | struct rpc_message msg = { |
248 | .rpc_argp = &map, | 246 | .rpc_argp = &map, |
249 | .rpc_resp = okay, | ||
250 | }; | 247 | }; |
251 | 248 | ||
252 | dprintk("RPC: %sregistering (%u, %u, %d, %u) with local " | 249 | dprintk("RPC: %sregistering (%u, %u, %d, %u) with local " |
@@ -259,7 +256,7 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay) | |||
259 | 256 | ||
260 | return rpcb_register_call((struct sockaddr *)&rpcb_inaddr_loopback, | 257 | return rpcb_register_call((struct sockaddr *)&rpcb_inaddr_loopback, |
261 | sizeof(rpcb_inaddr_loopback), | 258 | sizeof(rpcb_inaddr_loopback), |
262 | RPCBVERS_2, &msg, okay); | 259 | RPCBVERS_2, &msg); |
263 | } | 260 | } |
264 | 261 | ||
265 | /* | 262 | /* |
@@ -290,7 +287,7 @@ static int rpcb_register_netid4(struct sockaddr_in *address_to_register, | |||
290 | 287 | ||
291 | return rpcb_register_call((struct sockaddr *)&rpcb_inaddr_loopback, | 288 | return rpcb_register_call((struct sockaddr *)&rpcb_inaddr_loopback, |
292 | sizeof(rpcb_inaddr_loopback), | 289 | sizeof(rpcb_inaddr_loopback), |
293 | RPCBVERS_4, msg, msg->rpc_resp); | 290 | RPCBVERS_4, msg); |
294 | } | 291 | } |
295 | 292 | ||
296 | /* | 293 | /* |
@@ -304,10 +301,13 @@ static int rpcb_register_netid6(struct sockaddr_in6 *address_to_register, | |||
304 | char buf[64]; | 301 | char buf[64]; |
305 | 302 | ||
306 | /* Construct AF_INET6 universal address */ | 303 | /* Construct AF_INET6 universal address */ |
307 | snprintf(buf, sizeof(buf), | 304 | if (ipv6_addr_any(&address_to_register->sin6_addr)) |
308 | NIP6_FMT".%u.%u", | 305 | snprintf(buf, sizeof(buf), "::.%u.%u", |
309 | NIP6(address_to_register->sin6_addr), | 306 | port >> 8, port & 0xff); |
310 | port >> 8, port & 0xff); | 307 | else |
308 | snprintf(buf, sizeof(buf), NIP6_FMT".%u.%u", | ||
309 | NIP6(address_to_register->sin6_addr), | ||
310 | port >> 8, port & 0xff); | ||
311 | map->r_addr = buf; | 311 | map->r_addr = buf; |
312 | 312 | ||
313 | dprintk("RPC: %sregistering [%u, %u, %s, '%s'] with " | 313 | dprintk("RPC: %sregistering [%u, %u, %s, '%s'] with " |
@@ -321,7 +321,7 @@ static int rpcb_register_netid6(struct sockaddr_in6 *address_to_register, | |||
321 | 321 | ||
322 | return rpcb_register_call((struct sockaddr *)&rpcb_in6addr_loopback, | 322 | return rpcb_register_call((struct sockaddr *)&rpcb_in6addr_loopback, |
323 | sizeof(rpcb_in6addr_loopback), | 323 | sizeof(rpcb_in6addr_loopback), |
324 | RPCBVERS_4, msg, msg->rpc_resp); | 324 | RPCBVERS_4, msg); |
325 | } | 325 | } |
326 | 326 | ||
327 | /** | 327 | /** |
@@ -330,7 +330,11 @@ static int rpcb_register_netid6(struct sockaddr_in6 *address_to_register, | |||
330 | * @version: RPC version number of service to (un)register | 330 | * @version: RPC version number of service to (un)register |
331 | * @address: address family, IP address, and port to (un)register | 331 | * @address: address family, IP address, and port to (un)register |
332 | * @netid: netid of transport protocol to (un)register | 332 | * @netid: netid of transport protocol to (un)register |
333 | * @result: result code from rpcbind RPC call | 333 | * |
334 | * Returns zero if the registration request was dispatched successfully | ||
335 | * and the rpcbind daemon returned success. Otherwise, returns an errno | ||
336 | * value that reflects the nature of the error (request could not be | ||
337 | * dispatched, timed out, or rpcbind returned an error). | ||
334 | * | 338 | * |
335 | * RPC services invoke this function to advertise their contact | 339 | * RPC services invoke this function to advertise their contact |
336 | * information via the system's rpcbind daemon. RPC services | 340 | * information via the system's rpcbind daemon. RPC services |
@@ -342,15 +346,6 @@ static int rpcb_register_netid6(struct sockaddr_in6 *address_to_register, | |||
342 | * to zero. Callers pass a netid of "" to unregister all | 346 | * to zero. Callers pass a netid of "" to unregister all |
343 | * transport netids associated with [program, version, address]. | 347 | * transport netids associated with [program, version, address]. |
344 | * | 348 | * |
345 | * Returns zero if the registration request was dispatched | ||
346 | * successfully and a reply was received. The rpcbind daemon's | ||
347 | * result code is stored in *result. | ||
348 | * | ||
349 | * Returns an errno value and sets *result to zero if there was | ||
350 | * some problem that prevented the rpcbind request from being | ||
351 | * dispatched, or if the rpcbind daemon did not respond within | ||
352 | * the timeout. | ||
353 | * | ||
354 | * This function uses rpcbind protocol version 4 to contact the | 349 | * This function uses rpcbind protocol version 4 to contact the |
355 | * local rpcbind daemon. The local rpcbind daemon must support | 350 | * local rpcbind daemon. The local rpcbind daemon must support |
356 | * version 4 of the rpcbind protocol in order for these functions | 351 | * version 4 of the rpcbind protocol in order for these functions |
@@ -372,8 +367,7 @@ static int rpcb_register_netid6(struct sockaddr_in6 *address_to_register, | |||
372 | * advertises the service on all IPv4 and IPv6 addresses. | 367 | * advertises the service on all IPv4 and IPv6 addresses. |
373 | */ | 368 | */ |
374 | int rpcb_v4_register(const u32 program, const u32 version, | 369 | int rpcb_v4_register(const u32 program, const u32 version, |
375 | const struct sockaddr *address, const char *netid, | 370 | const struct sockaddr *address, const char *netid) |
376 | int *result) | ||
377 | { | 371 | { |
378 | struct rpcbind_args map = { | 372 | struct rpcbind_args map = { |
379 | .r_prog = program, | 373 | .r_prog = program, |
@@ -383,11 +377,8 @@ int rpcb_v4_register(const u32 program, const u32 version, | |||
383 | }; | 377 | }; |
384 | struct rpc_message msg = { | 378 | struct rpc_message msg = { |
385 | .rpc_argp = &map, | 379 | .rpc_argp = &map, |
386 | .rpc_resp = result, | ||
387 | }; | 380 | }; |
388 | 381 | ||
389 | *result = 0; | ||
390 | |||
391 | switch (address->sa_family) { | 382 | switch (address->sa_family) { |
392 | case AF_INET: | 383 | case AF_INET: |
393 | return rpcb_register_netid4((struct sockaddr_in *)address, | 384 | return rpcb_register_netid4((struct sockaddr_in *)address, |
@@ -633,7 +624,7 @@ static void rpcb_getport_done(struct rpc_task *child, void *data) | |||
633 | static int rpcb_encode_mapping(struct rpc_rqst *req, __be32 *p, | 624 | static int rpcb_encode_mapping(struct rpc_rqst *req, __be32 *p, |
634 | struct rpcbind_args *rpcb) | 625 | struct rpcbind_args *rpcb) |
635 | { | 626 | { |
636 | dprintk("RPC: rpcb_encode_mapping(%u, %u, %d, %u)\n", | 627 | dprintk("RPC: encoding rpcb request (%u, %u, %d, %u)\n", |
637 | rpcb->r_prog, rpcb->r_vers, rpcb->r_prot, rpcb->r_port); | 628 | rpcb->r_prog, rpcb->r_vers, rpcb->r_prot, rpcb->r_port); |
638 | *p++ = htonl(rpcb->r_prog); | 629 | *p++ = htonl(rpcb->r_prog); |
639 | *p++ = htonl(rpcb->r_vers); | 630 | *p++ = htonl(rpcb->r_vers); |
@@ -648,7 +639,7 @@ static int rpcb_decode_getport(struct rpc_rqst *req, __be32 *p, | |||
648 | unsigned short *portp) | 639 | unsigned short *portp) |
649 | { | 640 | { |
650 | *portp = (unsigned short) ntohl(*p++); | 641 | *portp = (unsigned short) ntohl(*p++); |
651 | dprintk("RPC: rpcb_decode_getport result %u\n", | 642 | dprintk("RPC: rpcb getport result: %u\n", |
652 | *portp); | 643 | *portp); |
653 | return 0; | 644 | return 0; |
654 | } | 645 | } |
@@ -657,7 +648,7 @@ static int rpcb_decode_set(struct rpc_rqst *req, __be32 *p, | |||
657 | unsigned int *boolp) | 648 | unsigned int *boolp) |
658 | { | 649 | { |
659 | *boolp = (unsigned int) ntohl(*p++); | 650 | *boolp = (unsigned int) ntohl(*p++); |
660 | dprintk("RPC: rpcb_decode_set: call %s\n", | 651 | dprintk("RPC: rpcb set/unset call %s\n", |
661 | (*boolp ? "succeeded" : "failed")); | 652 | (*boolp ? "succeeded" : "failed")); |
662 | return 0; | 653 | return 0; |
663 | } | 654 | } |
@@ -665,7 +656,7 @@ static int rpcb_decode_set(struct rpc_rqst *req, __be32 *p, | |||
665 | static int rpcb_encode_getaddr(struct rpc_rqst *req, __be32 *p, | 656 | static int rpcb_encode_getaddr(struct rpc_rqst *req, __be32 *p, |
666 | struct rpcbind_args *rpcb) | 657 | struct rpcbind_args *rpcb) |
667 | { | 658 | { |
668 | dprintk("RPC: rpcb_encode_getaddr(%u, %u, %s)\n", | 659 | dprintk("RPC: encoding rpcb request (%u, %u, %s)\n", |
669 | rpcb->r_prog, rpcb->r_vers, rpcb->r_addr); | 660 | rpcb->r_prog, rpcb->r_vers, rpcb->r_addr); |
670 | *p++ = htonl(rpcb->r_prog); | 661 | *p++ = htonl(rpcb->r_prog); |
671 | *p++ = htonl(rpcb->r_vers); | 662 | *p++ = htonl(rpcb->r_vers); |
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 5a32cb7c4bb4..54c98d876847 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c | |||
@@ -28,6 +28,8 @@ | |||
28 | 28 | ||
29 | #define RPCDBG_FACILITY RPCDBG_SVCDSP | 29 | #define RPCDBG_FACILITY RPCDBG_SVCDSP |
30 | 30 | ||
31 | static void svc_unregister(const struct svc_serv *serv); | ||
32 | |||
31 | #define svc_serv_is_pooled(serv) ((serv)->sv_function) | 33 | #define svc_serv_is_pooled(serv) ((serv)->sv_function) |
32 | 34 | ||
33 | /* | 35 | /* |
@@ -357,7 +359,7 @@ svc_pool_for_cpu(struct svc_serv *serv, int cpu) | |||
357 | */ | 359 | */ |
358 | static struct svc_serv * | 360 | static struct svc_serv * |
359 | __svc_create(struct svc_program *prog, unsigned int bufsize, int npools, | 361 | __svc_create(struct svc_program *prog, unsigned int bufsize, int npools, |
360 | void (*shutdown)(struct svc_serv *serv)) | 362 | sa_family_t family, void (*shutdown)(struct svc_serv *serv)) |
361 | { | 363 | { |
362 | struct svc_serv *serv; | 364 | struct svc_serv *serv; |
363 | unsigned int vers; | 365 | unsigned int vers; |
@@ -366,6 +368,7 @@ __svc_create(struct svc_program *prog, unsigned int bufsize, int npools, | |||
366 | 368 | ||
367 | if (!(serv = kzalloc(sizeof(*serv), GFP_KERNEL))) | 369 | if (!(serv = kzalloc(sizeof(*serv), GFP_KERNEL))) |
368 | return NULL; | 370 | return NULL; |
371 | serv->sv_family = family; | ||
369 | serv->sv_name = prog->pg_name; | 372 | serv->sv_name = prog->pg_name; |
370 | serv->sv_program = prog; | 373 | serv->sv_program = prog; |
371 | serv->sv_nrthreads = 1; | 374 | serv->sv_nrthreads = 1; |
@@ -416,30 +419,29 @@ __svc_create(struct svc_program *prog, unsigned int bufsize, int npools, | |||
416 | spin_lock_init(&pool->sp_lock); | 419 | spin_lock_init(&pool->sp_lock); |
417 | } | 420 | } |
418 | 421 | ||
419 | |||
420 | /* Remove any stale portmap registrations */ | 422 | /* Remove any stale portmap registrations */ |
421 | svc_register(serv, 0, 0); | 423 | svc_unregister(serv); |
422 | 424 | ||
423 | return serv; | 425 | return serv; |
424 | } | 426 | } |
425 | 427 | ||
426 | struct svc_serv * | 428 | struct svc_serv * |
427 | svc_create(struct svc_program *prog, unsigned int bufsize, | 429 | svc_create(struct svc_program *prog, unsigned int bufsize, |
428 | void (*shutdown)(struct svc_serv *serv)) | 430 | sa_family_t family, void (*shutdown)(struct svc_serv *serv)) |
429 | { | 431 | { |
430 | return __svc_create(prog, bufsize, /*npools*/1, shutdown); | 432 | return __svc_create(prog, bufsize, /*npools*/1, family, shutdown); |
431 | } | 433 | } |
432 | EXPORT_SYMBOL(svc_create); | 434 | EXPORT_SYMBOL(svc_create); |
433 | 435 | ||
434 | struct svc_serv * | 436 | struct svc_serv * |
435 | svc_create_pooled(struct svc_program *prog, unsigned int bufsize, | 437 | svc_create_pooled(struct svc_program *prog, unsigned int bufsize, |
436 | void (*shutdown)(struct svc_serv *serv), | 438 | sa_family_t family, void (*shutdown)(struct svc_serv *serv), |
437 | svc_thread_fn func, struct module *mod) | 439 | svc_thread_fn func, struct module *mod) |
438 | { | 440 | { |
439 | struct svc_serv *serv; | 441 | struct svc_serv *serv; |
440 | unsigned int npools = svc_pool_map_get(); | 442 | unsigned int npools = svc_pool_map_get(); |
441 | 443 | ||
442 | serv = __svc_create(prog, bufsize, npools, shutdown); | 444 | serv = __svc_create(prog, bufsize, npools, family, shutdown); |
443 | 445 | ||
444 | if (serv != NULL) { | 446 | if (serv != NULL) { |
445 | serv->sv_function = func; | 447 | serv->sv_function = func; |
@@ -486,8 +488,7 @@ svc_destroy(struct svc_serv *serv) | |||
486 | if (svc_serv_is_pooled(serv)) | 488 | if (svc_serv_is_pooled(serv)) |
487 | svc_pool_map_put(); | 489 | svc_pool_map_put(); |
488 | 490 | ||
489 | /* Unregister service with the portmapper */ | 491 | svc_unregister(serv); |
490 | svc_register(serv, 0, 0); | ||
491 | kfree(serv->sv_pools); | 492 | kfree(serv->sv_pools); |
492 | kfree(serv); | 493 | kfree(serv); |
493 | } | 494 | } |
@@ -718,55 +719,245 @@ svc_exit_thread(struct svc_rqst *rqstp) | |||
718 | } | 719 | } |
719 | EXPORT_SYMBOL(svc_exit_thread); | 720 | EXPORT_SYMBOL(svc_exit_thread); |
720 | 721 | ||
722 | #ifdef CONFIG_SUNRPC_REGISTER_V4 | ||
723 | |||
721 | /* | 724 | /* |
722 | * Register an RPC service with the local portmapper. | 725 | * Register an "inet" protocol family netid with the local |
723 | * To unregister a service, call this routine with | 726 | * rpcbind daemon via an rpcbind v4 SET request. |
724 | * proto and port == 0. | 727 | * |
728 | * No netconfig infrastructure is available in the kernel, so | ||
729 | * we map IP_ protocol numbers to netids by hand. | ||
730 | * | ||
731 | * Returns zero on success; a negative errno value is returned | ||
732 | * if any error occurs. | ||
725 | */ | 733 | */ |
726 | int | 734 | static int __svc_rpcb_register4(const u32 program, const u32 version, |
727 | svc_register(struct svc_serv *serv, int proto, unsigned short port) | 735 | const unsigned short protocol, |
736 | const unsigned short port) | ||
737 | { | ||
738 | struct sockaddr_in sin = { | ||
739 | .sin_family = AF_INET, | ||
740 | .sin_addr.s_addr = htonl(INADDR_ANY), | ||
741 | .sin_port = htons(port), | ||
742 | }; | ||
743 | char *netid; | ||
744 | |||
745 | switch (protocol) { | ||
746 | case IPPROTO_UDP: | ||
747 | netid = RPCBIND_NETID_UDP; | ||
748 | break; | ||
749 | case IPPROTO_TCP: | ||
750 | netid = RPCBIND_NETID_TCP; | ||
751 | break; | ||
752 | default: | ||
753 | return -EPROTONOSUPPORT; | ||
754 | } | ||
755 | |||
756 | return rpcb_v4_register(program, version, | ||
757 | (struct sockaddr *)&sin, netid); | ||
758 | } | ||
759 | |||
760 | /* | ||
761 | * Register an "inet6" protocol family netid with the local | ||
762 | * rpcbind daemon via an rpcbind v4 SET request. | ||
763 | * | ||
764 | * No netconfig infrastructure is available in the kernel, so | ||
765 | * we map IP_ protocol numbers to netids by hand. | ||
766 | * | ||
767 | * Returns zero on success; a negative errno value is returned | ||
768 | * if any error occurs. | ||
769 | */ | ||
770 | static int __svc_rpcb_register6(const u32 program, const u32 version, | ||
771 | const unsigned short protocol, | ||
772 | const unsigned short port) | ||
773 | { | ||
774 | struct sockaddr_in6 sin6 = { | ||
775 | .sin6_family = AF_INET6, | ||
776 | .sin6_addr = IN6ADDR_ANY_INIT, | ||
777 | .sin6_port = htons(port), | ||
778 | }; | ||
779 | char *netid; | ||
780 | |||
781 | switch (protocol) { | ||
782 | case IPPROTO_UDP: | ||
783 | netid = RPCBIND_NETID_UDP6; | ||
784 | break; | ||
785 | case IPPROTO_TCP: | ||
786 | netid = RPCBIND_NETID_TCP6; | ||
787 | break; | ||
788 | default: | ||
789 | return -EPROTONOSUPPORT; | ||
790 | } | ||
791 | |||
792 | return rpcb_v4_register(program, version, | ||
793 | (struct sockaddr *)&sin6, netid); | ||
794 | } | ||
795 | |||
796 | /* | ||
797 | * Register a kernel RPC service via rpcbind version 4. | ||
798 | * | ||
799 | * Returns zero on success; a negative errno value is returned | ||
800 | * if any error occurs. | ||
801 | */ | ||
802 | static int __svc_register(const u32 program, const u32 version, | ||
803 | const sa_family_t family, | ||
804 | const unsigned short protocol, | ||
805 | const unsigned short port) | ||
806 | { | ||
807 | int error; | ||
808 | |||
809 | switch (family) { | ||
810 | case AF_INET: | ||
811 | return __svc_rpcb_register4(program, version, | ||
812 | protocol, port); | ||
813 | case AF_INET6: | ||
814 | error = __svc_rpcb_register6(program, version, | ||
815 | protocol, port); | ||
816 | if (error < 0) | ||
817 | return error; | ||
818 | |||
819 | /* | ||
820 | * Work around bug in some versions of Linux rpcbind | ||
821 | * which don't allow registration of both inet and | ||
822 | * inet6 netids. | ||
823 | * | ||
824 | * Error return ignored for now. | ||
825 | */ | ||
826 | __svc_rpcb_register4(program, version, | ||
827 | protocol, port); | ||
828 | return 0; | ||
829 | } | ||
830 | |||
831 | return -EAFNOSUPPORT; | ||
832 | } | ||
833 | |||
834 | #else /* CONFIG_SUNRPC_REGISTER_V4 */ | ||
835 | |||
836 | /* | ||
837 | * Register a kernel RPC service via rpcbind version 2. | ||
838 | * | ||
839 | * Returns zero on success; a negative errno value is returned | ||
840 | * if any error occurs. | ||
841 | */ | ||
842 | static int __svc_register(const u32 program, const u32 version, | ||
843 | sa_family_t family, | ||
844 | const unsigned short protocol, | ||
845 | const unsigned short port) | ||
846 | { | ||
847 | if (family != AF_INET) | ||
848 | return -EAFNOSUPPORT; | ||
849 | |||
850 | return rpcb_register(program, version, protocol, port); | ||
851 | } | ||
852 | |||
853 | #endif /* CONFIG_SUNRPC_REGISTER_V4 */ | ||
854 | |||
855 | /** | ||
856 | * svc_register - register an RPC service with the local portmapper | ||
857 | * @serv: svc_serv struct for the service to register | ||
858 | * @proto: transport protocol number to advertise | ||
859 | * @port: port to advertise | ||
860 | * | ||
861 | * Service is registered for any address in serv's address family | ||
862 | */ | ||
863 | int svc_register(const struct svc_serv *serv, const unsigned short proto, | ||
864 | const unsigned short port) | ||
728 | { | 865 | { |
729 | struct svc_program *progp; | 866 | struct svc_program *progp; |
730 | unsigned long flags; | ||
731 | unsigned int i; | 867 | unsigned int i; |
732 | int error = 0, dummy; | 868 | int error = 0; |
733 | 869 | ||
734 | if (!port) | 870 | BUG_ON(proto == 0 && port == 0); |
735 | clear_thread_flag(TIF_SIGPENDING); | ||
736 | 871 | ||
737 | for (progp = serv->sv_program; progp; progp = progp->pg_next) { | 872 | for (progp = serv->sv_program; progp; progp = progp->pg_next) { |
738 | for (i = 0; i < progp->pg_nvers; i++) { | 873 | for (i = 0; i < progp->pg_nvers; i++) { |
739 | if (progp->pg_vers[i] == NULL) | 874 | if (progp->pg_vers[i] == NULL) |
740 | continue; | 875 | continue; |
741 | 876 | ||
742 | dprintk("svc: svc_register(%s, %s, %d, %d)%s\n", | 877 | dprintk("svc: svc_register(%sv%d, %s, %u, %u)%s\n", |
743 | progp->pg_name, | 878 | progp->pg_name, |
879 | i, | ||
744 | proto == IPPROTO_UDP? "udp" : "tcp", | 880 | proto == IPPROTO_UDP? "udp" : "tcp", |
745 | port, | 881 | port, |
746 | i, | 882 | serv->sv_family, |
747 | progp->pg_vers[i]->vs_hidden? | 883 | progp->pg_vers[i]->vs_hidden? |
748 | " (but not telling portmap)" : ""); | 884 | " (but not telling portmap)" : ""); |
749 | 885 | ||
750 | if (progp->pg_vers[i]->vs_hidden) | 886 | if (progp->pg_vers[i]->vs_hidden) |
751 | continue; | 887 | continue; |
752 | 888 | ||
753 | error = rpcb_register(progp->pg_prog, i, proto, port, &dummy); | 889 | error = __svc_register(progp->pg_prog, i, |
890 | serv->sv_family, proto, port); | ||
754 | if (error < 0) | 891 | if (error < 0) |
755 | break; | 892 | break; |
756 | if (port && !dummy) { | ||
757 | error = -EACCES; | ||
758 | break; | ||
759 | } | ||
760 | } | 893 | } |
761 | } | 894 | } |
762 | 895 | ||
763 | if (!port) { | 896 | return error; |
764 | spin_lock_irqsave(¤t->sighand->siglock, flags); | 897 | } |
765 | recalc_sigpending(); | 898 | |
766 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); | 899 | #ifdef CONFIG_SUNRPC_REGISTER_V4 |
900 | |||
901 | static void __svc_unregister(const u32 program, const u32 version, | ||
902 | const char *progname) | ||
903 | { | ||
904 | struct sockaddr_in6 sin6 = { | ||
905 | .sin6_family = AF_INET6, | ||
906 | .sin6_addr = IN6ADDR_ANY_INIT, | ||
907 | .sin6_port = 0, | ||
908 | }; | ||
909 | int error; | ||
910 | |||
911 | error = rpcb_v4_register(program, version, | ||
912 | (struct sockaddr *)&sin6, ""); | ||
913 | dprintk("svc: %s(%sv%u), error %d\n", | ||
914 | __func__, progname, version, error); | ||
915 | } | ||
916 | |||
917 | #else /* CONFIG_SUNRPC_REGISTER_V4 */ | ||
918 | |||
919 | static void __svc_unregister(const u32 program, const u32 version, | ||
920 | const char *progname) | ||
921 | { | ||
922 | int error; | ||
923 | |||
924 | error = rpcb_register(program, version, 0, 0); | ||
925 | dprintk("svc: %s(%sv%u), error %d\n", | ||
926 | __func__, progname, version, error); | ||
927 | } | ||
928 | |||
929 | #endif /* CONFIG_SUNRPC_REGISTER_V4 */ | ||
930 | |||
931 | /* | ||
932 | * All netids, bind addresses and ports registered for [program, version] | ||
933 | * are removed from the local rpcbind database (if the service is not | ||
934 | * hidden) to make way for a new instance of the service. | ||
935 | * | ||
936 | * The result of unregistration is reported via dprintk for those who want | ||
937 | * verification of the result, but is otherwise not important. | ||
938 | */ | ||
939 | static void svc_unregister(const struct svc_serv *serv) | ||
940 | { | ||
941 | struct svc_program *progp; | ||
942 | unsigned long flags; | ||
943 | unsigned int i; | ||
944 | |||
945 | clear_thread_flag(TIF_SIGPENDING); | ||
946 | |||
947 | for (progp = serv->sv_program; progp; progp = progp->pg_next) { | ||
948 | for (i = 0; i < progp->pg_nvers; i++) { | ||
949 | if (progp->pg_vers[i] == NULL) | ||
950 | continue; | ||
951 | if (progp->pg_vers[i]->vs_hidden) | ||
952 | continue; | ||
953 | |||
954 | __svc_unregister(progp->pg_prog, i, progp->pg_name); | ||
955 | } | ||
767 | } | 956 | } |
768 | 957 | ||
769 | return error; | 958 | spin_lock_irqsave(¤t->sighand->siglock, flags); |
959 | recalc_sigpending(); | ||
960 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); | ||
770 | } | 961 | } |
771 | 962 | ||
772 | /* | 963 | /* |
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index e46c825f4954..bf5b5cdafebf 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c | |||
@@ -159,15 +159,44 @@ void svc_xprt_init(struct svc_xprt_class *xcl, struct svc_xprt *xprt, | |||
159 | } | 159 | } |
160 | EXPORT_SYMBOL_GPL(svc_xprt_init); | 160 | EXPORT_SYMBOL_GPL(svc_xprt_init); |
161 | 161 | ||
162 | int svc_create_xprt(struct svc_serv *serv, char *xprt_name, unsigned short port, | 162 | static struct svc_xprt *__svc_xpo_create(struct svc_xprt_class *xcl, |
163 | int flags) | 163 | struct svc_serv *serv, |
164 | unsigned short port, int flags) | ||
164 | { | 165 | { |
165 | struct svc_xprt_class *xcl; | ||
166 | struct sockaddr_in sin = { | 166 | struct sockaddr_in sin = { |
167 | .sin_family = AF_INET, | 167 | .sin_family = AF_INET, |
168 | .sin_addr.s_addr = htonl(INADDR_ANY), | 168 | .sin_addr.s_addr = htonl(INADDR_ANY), |
169 | .sin_port = htons(port), | 169 | .sin_port = htons(port), |
170 | }; | 170 | }; |
171 | struct sockaddr_in6 sin6 = { | ||
172 | .sin6_family = AF_INET6, | ||
173 | .sin6_addr = IN6ADDR_ANY_INIT, | ||
174 | .sin6_port = htons(port), | ||
175 | }; | ||
176 | struct sockaddr *sap; | ||
177 | size_t len; | ||
178 | |||
179 | switch (serv->sv_family) { | ||
180 | case AF_INET: | ||
181 | sap = (struct sockaddr *)&sin; | ||
182 | len = sizeof(sin); | ||
183 | break; | ||
184 | case AF_INET6: | ||
185 | sap = (struct sockaddr *)&sin6; | ||
186 | len = sizeof(sin6); | ||
187 | break; | ||
188 | default: | ||
189 | return ERR_PTR(-EAFNOSUPPORT); | ||
190 | } | ||
191 | |||
192 | return xcl->xcl_ops->xpo_create(serv, sap, len, flags); | ||
193 | } | ||
194 | |||
195 | int svc_create_xprt(struct svc_serv *serv, char *xprt_name, unsigned short port, | ||
196 | int flags) | ||
197 | { | ||
198 | struct svc_xprt_class *xcl; | ||
199 | |||
171 | dprintk("svc: creating transport %s[%d]\n", xprt_name, port); | 200 | dprintk("svc: creating transport %s[%d]\n", xprt_name, port); |
172 | spin_lock(&svc_xprt_class_lock); | 201 | spin_lock(&svc_xprt_class_lock); |
173 | list_for_each_entry(xcl, &svc_xprt_class_list, xcl_list) { | 202 | list_for_each_entry(xcl, &svc_xprt_class_list, xcl_list) { |
@@ -180,9 +209,7 @@ int svc_create_xprt(struct svc_serv *serv, char *xprt_name, unsigned short port, | |||
180 | goto err; | 209 | goto err; |
181 | 210 | ||
182 | spin_unlock(&svc_xprt_class_lock); | 211 | spin_unlock(&svc_xprt_class_lock); |
183 | newxprt = xcl->xcl_ops-> | 212 | newxprt = __svc_xpo_create(xcl, serv, port, flags); |
184 | xpo_create(serv, (struct sockaddr *)&sin, sizeof(sin), | ||
185 | flags); | ||
186 | if (IS_ERR(newxprt)) { | 213 | if (IS_ERR(newxprt)) { |
187 | module_put(xcl->xcl_owner); | 214 | module_put(xcl->xcl_owner); |
188 | return PTR_ERR(newxprt); | 215 | return PTR_ERR(newxprt); |
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 3e65719f1ef6..95293f549e9c 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
@@ -1114,6 +1114,7 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv, | |||
1114 | struct svc_sock *svsk; | 1114 | struct svc_sock *svsk; |
1115 | struct sock *inet; | 1115 | struct sock *inet; |
1116 | int pmap_register = !(flags & SVC_SOCK_ANONYMOUS); | 1116 | int pmap_register = !(flags & SVC_SOCK_ANONYMOUS); |
1117 | int val; | ||
1117 | 1118 | ||
1118 | dprintk("svc: svc_setup_socket %p\n", sock); | 1119 | dprintk("svc: svc_setup_socket %p\n", sock); |
1119 | if (!(svsk = kzalloc(sizeof(*svsk), GFP_KERNEL))) { | 1120 | if (!(svsk = kzalloc(sizeof(*svsk), GFP_KERNEL))) { |
@@ -1146,6 +1147,18 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv, | |||
1146 | else | 1147 | else |
1147 | svc_tcp_init(svsk, serv); | 1148 | svc_tcp_init(svsk, serv); |
1148 | 1149 | ||
1150 | /* | ||
1151 | * We start one listener per sv_serv. We want AF_INET | ||
1152 | * requests to be automatically shunted to our AF_INET6 | ||
1153 | * listener using a mapped IPv4 address. Make sure | ||
1154 | * no-one starts an equivalent IPv4 listener, which | ||
1155 | * would steal our incoming connections. | ||
1156 | */ | ||
1157 | val = 0; | ||
1158 | if (serv->sv_family == AF_INET6) | ||
1159 | kernel_setsockopt(sock, SOL_IPV6, IPV6_V6ONLY, | ||
1160 | (char *)&val, sizeof(val)); | ||
1161 | |||
1149 | dprintk("svc: svc_setup_socket created %p (inet %p)\n", | 1162 | dprintk("svc: svc_setup_socket created %p (inet %p)\n", |
1150 | svsk, svsk->sk_sk); | 1163 | svsk, svsk->sk_sk); |
1151 | 1164 | ||
@@ -1154,8 +1167,7 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv, | |||
1154 | 1167 | ||
1155 | int svc_addsock(struct svc_serv *serv, | 1168 | int svc_addsock(struct svc_serv *serv, |
1156 | int fd, | 1169 | int fd, |
1157 | char *name_return, | 1170 | char *name_return) |
1158 | int *proto) | ||
1159 | { | 1171 | { |
1160 | int err = 0; | 1172 | int err = 0; |
1161 | struct socket *so = sockfd_lookup(fd, &err); | 1173 | struct socket *so = sockfd_lookup(fd, &err); |
@@ -1190,7 +1202,6 @@ int svc_addsock(struct svc_serv *serv, | |||
1190 | sockfd_put(so); | 1202 | sockfd_put(so); |
1191 | return err; | 1203 | return err; |
1192 | } | 1204 | } |
1193 | if (proto) *proto = so->sk->sk_protocol; | ||
1194 | return one_sock_name(name_return, svsk); | 1205 | return one_sock_name(name_return, svsk); |
1195 | } | 1206 | } |
1196 | EXPORT_SYMBOL_GPL(svc_addsock); | 1207 | EXPORT_SYMBOL_GPL(svc_addsock); |