pmap_clnt.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:7k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * linux/net/sunrpc/pmap.c
  3.  *
  4.  * Portmapper client.
  5.  *
  6.  * FIXME: In a secure environment, we may want to use an authentication
  7.  * flavor other than AUTH_NULL.
  8.  *
  9.  * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
  10.  */
  11. #include <linux/config.h>
  12. #include <linux/types.h>
  13. #include <linux/socket.h>
  14. #include <linux/kernel.h>
  15. #include <linux/errno.h>
  16. #include <linux/uio.h>
  17. #include <linux/in.h>
  18. #include <linux/sunrpc/clnt.h>
  19. #include <linux/sunrpc/xprt.h>
  20. #include <linux/sunrpc/sched.h>
  21. #ifdef RPC_DEBUG
  22. # define RPCDBG_FACILITY RPCDBG_PMAP
  23. #endif
  24. #define PMAP_SET 1
  25. #define PMAP_UNSET 2
  26. #define PMAP_GETPORT 3
  27. static struct rpc_clnt * pmap_create(char *, struct sockaddr_in *, int);
  28. static void pmap_getport_done(struct rpc_task *);
  29. extern struct rpc_program pmap_program;
  30. static spinlock_t pmap_lock = SPIN_LOCK_UNLOCKED;
  31. /*
  32.  * Obtain the port for a given RPC service on a given host. This one can
  33.  * be called for an ongoing RPC request.
  34.  */
  35. void
  36. rpc_getport(struct rpc_task *task, struct rpc_clnt *clnt)
  37. {
  38. struct rpc_portmap *map = &clnt->cl_pmap;
  39. struct sockaddr_in *sap = &clnt->cl_xprt->addr;
  40. struct rpc_message msg = { PMAP_GETPORT, map, &clnt->cl_port, NULL };
  41. struct rpc_clnt *pmap_clnt;
  42. struct rpc_task *child;
  43. dprintk("RPC: %4d rpc_getport(%s, %d, %d, %d)n",
  44. task->tk_pid, clnt->cl_server,
  45. map->pm_prog, map->pm_vers, map->pm_prot);
  46. spin_lock(&pmap_lock);
  47. if (clnt->cl_binding) {
  48. rpc_sleep_on(&clnt->cl_bindwait, task, NULL, 0);
  49. spin_unlock(&pmap_lock);
  50. return;
  51. }
  52. clnt->cl_binding = 1;
  53. spin_unlock(&pmap_lock);
  54. task->tk_status = -EACCES; /* why set this? returns -EIO below */
  55. if (!(pmap_clnt = pmap_create(clnt->cl_server, sap, map->pm_prot)))
  56. goto bailout;
  57. task->tk_status = 0;
  58. /*
  59.  * Note: rpc_new_child will release client after a failure.
  60.  */
  61. if (!(child = rpc_new_child(pmap_clnt, task)))
  62. goto bailout;
  63. /* Setup the call info struct */
  64. rpc_call_setup(child, &msg, 0);
  65. /* ... and run the child task */
  66. rpc_run_child(task, child, pmap_getport_done);
  67. return;
  68. bailout:
  69. spin_lock(&pmap_lock);
  70. clnt->cl_binding = 0;
  71. rpc_wake_up(&clnt->cl_bindwait);
  72. spin_unlock(&pmap_lock);
  73. task->tk_status = -EIO;
  74. task->tk_action = NULL;
  75. }
  76. #ifdef CONFIG_ROOT_NFS
  77. char *in_ntoa(__u32 in);
  78. int
  79. rpc_getport_external(struct sockaddr_in *sin, __u32 prog, __u32 vers, int prot)
  80. {
  81. struct rpc_portmap map = { prog, vers, prot, 0 };
  82. struct rpc_clnt *pmap_clnt;
  83. char hostname[32];
  84. int status;
  85. dprintk("RPC:      rpc_getport_external(%u.%u.%u.%u, %d, %d, %d)n",
  86. NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot);
  87. strcpy(hostname, in_ntoa(sin->sin_addr.s_addr));
  88. if (!(pmap_clnt = pmap_create(hostname, sin, prot)))
  89. return -EACCES;
  90. /* Setup the call info struct */
  91. status = rpc_call(pmap_clnt, PMAP_GETPORT, &map, &map.pm_port, 0);
  92. if (status >= 0) {
  93. if (map.pm_port != 0)
  94. return map.pm_port;
  95. status = -EACCES;
  96. }
  97. return status;
  98. }
  99. #endif
  100. static void
  101. pmap_getport_done(struct rpc_task *task)
  102. {
  103. struct rpc_clnt *clnt = task->tk_client;
  104. dprintk("RPC: %4d pmap_getport_done(status %d, port %d)n",
  105. task->tk_pid, task->tk_status, clnt->cl_port);
  106. if (task->tk_status < 0) {
  107. /* Make the calling task exit with an error */
  108. task->tk_action = NULL;
  109. } else if (clnt->cl_port == 0) {
  110. /* Program not registered */
  111. task->tk_status = -EACCES;
  112. task->tk_action = NULL;
  113. } else {
  114. /* byte-swap port number first */
  115. clnt->cl_port = htons(clnt->cl_port);
  116. clnt->cl_xprt->addr.sin_port = clnt->cl_port;
  117. }
  118. spin_lock(&pmap_lock);
  119. clnt->cl_binding = 0;
  120. rpc_wake_up(&clnt->cl_bindwait);
  121. spin_unlock(&pmap_lock);
  122. }
  123. /*
  124.  * Set or unset a port registration with the local portmapper.
  125.  * port == 0 means unregister, port != 0 means register.
  126.  */
  127. int
  128. rpc_register(u32 prog, u32 vers, int prot, unsigned short port, int *okay)
  129. {
  130. struct sockaddr_in sin;
  131. struct rpc_portmap map;
  132. struct rpc_clnt *pmap_clnt;
  133. unsigned int error = 0;
  134. dprintk("RPC: registering (%d, %d, %d, %d) with portmapper.n",
  135. prog, vers, prot, port);
  136. sin.sin_family = AF_INET;
  137. sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  138. if (!(pmap_clnt = pmap_create("localhost", &sin, IPPROTO_UDP))) {
  139. dprintk("RPC: couldn't create pmap clientn");
  140. return -EACCES;
  141. }
  142. map.pm_prog = prog;
  143. map.pm_vers = vers;
  144. map.pm_prot = prot;
  145. map.pm_port = port;
  146. error = rpc_call(pmap_clnt, port? PMAP_SET : PMAP_UNSET,
  147. &map, okay, 0);
  148. if (error < 0) {
  149. printk(KERN_WARNING
  150. "RPC: failed to contact portmap (errno %d).n",
  151. error);
  152. }
  153. dprintk("RPC: registration status %d/%dn", error, *okay);
  154. /* Client deleted automatically because cl_oneshot == 1 */
  155. return error;
  156. }
  157. static struct rpc_clnt *
  158. pmap_create(char *hostname, struct sockaddr_in *srvaddr, int proto)
  159. {
  160. struct rpc_xprt *xprt;
  161. struct rpc_clnt *clnt;
  162. /* printk("pmap: create xprtn"); */
  163. if (!(xprt = xprt_create_proto(proto, srvaddr, NULL)))
  164. return NULL;
  165. xprt->addr.sin_port = htons(RPC_PMAP_PORT);
  166. /* printk("pmap: create clntn"); */
  167. clnt = rpc_create_client(xprt, hostname,
  168. &pmap_program, RPC_PMAP_VERSION,
  169. RPC_AUTH_NULL);
  170. if (!clnt) {
  171. xprt_destroy(xprt);
  172. } else {
  173. clnt->cl_softrtry = 1;
  174. clnt->cl_chatty   = 1;
  175. clnt->cl_oneshot  = 1;
  176. }
  177. return clnt;
  178. }
  179. /*
  180.  * XDR encode/decode functions for PMAP
  181.  */
  182. static int
  183. xdr_error(struct rpc_rqst *req, u32 *p, void *dummy)
  184. {
  185. return -EIO;
  186. }
  187. static int
  188. xdr_encode_mapping(struct rpc_rqst *req, u32 *p, struct rpc_portmap *map)
  189. {
  190. dprintk("RPC: xdr_encode_mapping(%d, %d, %d, %d)n",
  191. map->pm_prog, map->pm_vers, map->pm_prot, map->pm_port);
  192. *p++ = htonl(map->pm_prog);
  193. *p++ = htonl(map->pm_vers);
  194. *p++ = htonl(map->pm_prot);
  195. *p++ = htonl(map->pm_port);
  196. req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
  197. return 0;
  198. }
  199. static int
  200. xdr_decode_port(struct rpc_rqst *req, u32 *p, unsigned short *portp)
  201. {
  202. *portp = (unsigned short) ntohl(*p++);
  203. return 0;
  204. }
  205. static int
  206. xdr_decode_bool(struct rpc_rqst *req, u32 *p, unsigned int *boolp)
  207. {
  208. *boolp = (unsigned int) ntohl(*p++);
  209. return 0;
  210. }
  211. static struct rpc_procinfo pmap_procedures[4] = {
  212. { "pmap_null",
  213. (kxdrproc_t) xdr_error,
  214. (kxdrproc_t) xdr_error, 0, 0 },
  215. { "pmap_set",
  216. (kxdrproc_t) xdr_encode_mapping,
  217. (kxdrproc_t) xdr_decode_bool, 4, 1 },
  218. { "pmap_unset",
  219. (kxdrproc_t) xdr_encode_mapping,
  220. (kxdrproc_t) xdr_decode_bool, 4, 1 },
  221. { "pmap_get",
  222. (kxdrproc_t) xdr_encode_mapping,
  223. (kxdrproc_t) xdr_decode_port, 4, 1 },
  224. };
  225. static struct rpc_version pmap_version2 = {
  226. 2, 4, pmap_procedures
  227. };
  228. static struct rpc_version * pmap_version[] = {
  229. NULL,
  230. NULL,
  231. &pmap_version2,
  232. };
  233. static struct rpc_stat pmap_stats;
  234. struct rpc_program pmap_program = {
  235. "portmap",
  236. RPC_PMAP_PROGRAM,
  237. sizeof(pmap_version)/sizeof(pmap_version[0]),
  238. pmap_version,
  239. &pmap_stats,
  240. };