svc_xprt.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /*
  2. * linux/net/sunrpc/svc_xprt.c
  3. *
  4. * Author: Tom Tucker <tom@opengridcomputing.com>
  5. */
  6. #include <linux/sched.h>
  7. #include <linux/errno.h>
  8. #include <linux/fcntl.h>
  9. #include <linux/net.h>
  10. #include <linux/in.h>
  11. #include <linux/inet.h>
  12. #include <linux/udp.h>
  13. #include <linux/tcp.h>
  14. #include <linux/unistd.h>
  15. #include <linux/slab.h>
  16. #include <linux/netdevice.h>
  17. #include <linux/skbuff.h>
  18. #include <linux/file.h>
  19. #include <linux/freezer.h>
  20. #include <net/sock.h>
  21. #include <net/checksum.h>
  22. #include <net/ip.h>
  23. #include <net/ipv6.h>
  24. #include <net/tcp_states.h>
  25. #include <linux/uaccess.h>
  26. #include <asm/ioctls.h>
  27. #include <linux/sunrpc/types.h>
  28. #include <linux/sunrpc/clnt.h>
  29. #include <linux/sunrpc/xdr.h>
  30. #include <linux/sunrpc/svcsock.h>
  31. #include <linux/sunrpc/stats.h>
  32. #include <linux/sunrpc/svc_xprt.h>
  33. #define RPCDBG_FACILITY RPCDBG_SVCXPRT
  34. /* List of registered transport classes */
  35. static DEFINE_SPINLOCK(svc_xprt_class_lock);
  36. static LIST_HEAD(svc_xprt_class_list);
  37. int svc_reg_xprt_class(struct svc_xprt_class *xcl)
  38. {
  39. struct svc_xprt_class *cl;
  40. int res = -EEXIST;
  41. dprintk("svc: Adding svc transport class '%s'\n", xcl->xcl_name);
  42. INIT_LIST_HEAD(&xcl->xcl_list);
  43. spin_lock(&svc_xprt_class_lock);
  44. /* Make sure there isn't already a class with the same name */
  45. list_for_each_entry(cl, &svc_xprt_class_list, xcl_list) {
  46. if (strcmp(xcl->xcl_name, cl->xcl_name) == 0)
  47. goto out;
  48. }
  49. list_add_tail(&xcl->xcl_list, &svc_xprt_class_list);
  50. res = 0;
  51. out:
  52. spin_unlock(&svc_xprt_class_lock);
  53. return res;
  54. }
  55. EXPORT_SYMBOL_GPL(svc_reg_xprt_class);
  56. void svc_unreg_xprt_class(struct svc_xprt_class *xcl)
  57. {
  58. dprintk("svc: Removing svc transport class '%s'\n", xcl->xcl_name);
  59. spin_lock(&svc_xprt_class_lock);
  60. list_del_init(&xcl->xcl_list);
  61. spin_unlock(&svc_xprt_class_lock);
  62. }
  63. EXPORT_SYMBOL_GPL(svc_unreg_xprt_class);
  64. static void svc_xprt_free(struct kref *kref)
  65. {
  66. struct svc_xprt *xprt =
  67. container_of(kref, struct svc_xprt, xpt_ref);
  68. struct module *owner = xprt->xpt_class->xcl_owner;
  69. if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags)
  70. && xprt->xpt_auth_cache != NULL)
  71. svcauth_unix_info_release(xprt->xpt_auth_cache);
  72. xprt->xpt_ops->xpo_free(xprt);
  73. module_put(owner);
  74. }
  75. void svc_xprt_put(struct svc_xprt *xprt)
  76. {
  77. kref_put(&xprt->xpt_ref, svc_xprt_free);
  78. }
  79. EXPORT_SYMBOL_GPL(svc_xprt_put);
  80. /*
  81. * Called by transport drivers to initialize the transport independent
  82. * portion of the transport instance.
  83. */
  84. void svc_xprt_init(struct svc_xprt_class *xcl, struct svc_xprt *xprt,
  85. struct svc_serv *serv)
  86. {
  87. memset(xprt, 0, sizeof(*xprt));
  88. xprt->xpt_class = xcl;
  89. xprt->xpt_ops = xcl->xcl_ops;
  90. kref_init(&xprt->xpt_ref);
  91. xprt->xpt_server = serv;
  92. INIT_LIST_HEAD(&xprt->xpt_list);
  93. INIT_LIST_HEAD(&xprt->xpt_ready);
  94. INIT_LIST_HEAD(&xprt->xpt_deferred);
  95. mutex_init(&xprt->xpt_mutex);
  96. spin_lock_init(&xprt->xpt_lock);
  97. set_bit(XPT_BUSY, &xprt->xpt_flags);
  98. }
  99. EXPORT_SYMBOL_GPL(svc_xprt_init);
  100. int svc_create_xprt(struct svc_serv *serv, char *xprt_name, unsigned short port,
  101. int flags)
  102. {
  103. struct svc_xprt_class *xcl;
  104. struct sockaddr_in sin = {
  105. .sin_family = AF_INET,
  106. .sin_addr.s_addr = INADDR_ANY,
  107. .sin_port = htons(port),
  108. };
  109. dprintk("svc: creating transport %s[%d]\n", xprt_name, port);
  110. spin_lock(&svc_xprt_class_lock);
  111. list_for_each_entry(xcl, &svc_xprt_class_list, xcl_list) {
  112. struct svc_xprt *newxprt;
  113. if (strcmp(xprt_name, xcl->xcl_name))
  114. continue;
  115. if (!try_module_get(xcl->xcl_owner))
  116. goto err;
  117. spin_unlock(&svc_xprt_class_lock);
  118. newxprt = xcl->xcl_ops->
  119. xpo_create(serv, (struct sockaddr *)&sin, sizeof(sin),
  120. flags);
  121. if (IS_ERR(newxprt)) {
  122. module_put(xcl->xcl_owner);
  123. return PTR_ERR(newxprt);
  124. }
  125. clear_bit(XPT_TEMP, &newxprt->xpt_flags);
  126. spin_lock_bh(&serv->sv_lock);
  127. list_add(&newxprt->xpt_list, &serv->sv_permsocks);
  128. spin_unlock_bh(&serv->sv_lock);
  129. clear_bit(XPT_BUSY, &newxprt->xpt_flags);
  130. return svc_xprt_local_port(newxprt);
  131. }
  132. err:
  133. spin_unlock(&svc_xprt_class_lock);
  134. dprintk("svc: transport %s not found\n", xprt_name);
  135. return -ENOENT;
  136. }
  137. EXPORT_SYMBOL_GPL(svc_create_xprt);
  138. /*
  139. * Copy the local and remote xprt addresses to the rqstp structure
  140. */
  141. void svc_xprt_copy_addrs(struct svc_rqst *rqstp, struct svc_xprt *xprt)
  142. {
  143. struct sockaddr *sin;
  144. memcpy(&rqstp->rq_addr, &xprt->xpt_remote, xprt->xpt_remotelen);
  145. rqstp->rq_addrlen = xprt->xpt_remotelen;
  146. /*
  147. * Destination address in request is needed for binding the
  148. * source address in RPC replies/callbacks later.
  149. */
  150. sin = (struct sockaddr *)&xprt->xpt_local;
  151. switch (sin->sa_family) {
  152. case AF_INET:
  153. rqstp->rq_daddr.addr = ((struct sockaddr_in *)sin)->sin_addr;
  154. break;
  155. case AF_INET6:
  156. rqstp->rq_daddr.addr6 = ((struct sockaddr_in6 *)sin)->sin6_addr;
  157. break;
  158. }
  159. }
  160. EXPORT_SYMBOL_GPL(svc_xprt_copy_addrs);