PageRenderTime 47ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

lib/libc/rpc/rpc_soc.c

http://www.minix3.org/
C | 457 lines | 335 code | 50 blank | 72 comment | 44 complexity | c578bbeed26f4f5d740c5867b2d4ec2c MD5 | raw file
Possible License(s): MIT, WTFPL, AGPL-1.0, BSD-3-Clause, GPL-3.0, LGPL-2.0, JSON, 0BSD
  1. /* $NetBSD: rpc_soc.c,v 1.13 2010/12/08 02:06:38 joerg Exp $ */
  2. /*
  3. * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  4. * unrestricted use provided that this legend is included on all tape
  5. * media and as a part of the software program in whole or part. Users
  6. * may copy or modify Sun RPC without charge, but are not authorized
  7. * to license or distribute it to anyone else except as part of a product or
  8. * program developed by the user.
  9. *
  10. * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  11. * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  12. * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  13. *
  14. * Sun RPC is provided with no support and without any obligation on the
  15. * part of Sun Microsystems, Inc. to assist in its use, correction,
  16. * modification or enhancement.
  17. *
  18. * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  19. * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  20. * OR ANY PART THEREOF.
  21. *
  22. * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  23. * or profits or other special, indirect and consequential damages, even if
  24. * Sun has been advised of the possibility of such damages.
  25. *
  26. * Sun Microsystems, Inc.
  27. * 2550 Garcia Avenue
  28. * Mountain View, California 94043
  29. */
  30. /* #ident "@(#)rpc_soc.c 1.17 94/04/24 SMI" */
  31. /*
  32. * Copyright (c) 1986-1991 by Sun Microsystems Inc.
  33. * In addition, portions of such source code were derived from Berkeley
  34. * 4.3 BSD under license from the Regents of the University of
  35. * California.
  36. */
  37. #include <sys/cdefs.h>
  38. #if defined(LIBC_SCCS) && !defined(lint)
  39. #if 0
  40. static char sccsid[] = "@(#)rpc_soc.c 1.41 89/05/02 Copyr 1988 Sun Micro";
  41. #else
  42. __RCSID("$NetBSD: rpc_soc.c,v 1.13 2010/12/08 02:06:38 joerg Exp $");
  43. #endif
  44. #endif
  45. #ifdef PORTMAP
  46. /*
  47. * rpc_soc.c
  48. *
  49. * The backward compatibility routines for the earlier implementation
  50. * of RPC, where the only transports supported were tcp/ip and udp/ip.
  51. * Based on berkeley socket abstraction, now implemented on the top
  52. * of TLI/Streams
  53. */
  54. #include "namespace.h"
  55. #include "reentrant.h"
  56. #include <sys/types.h>
  57. #include <sys/socket.h>
  58. #include <stdio.h>
  59. #include <rpc/rpc.h>
  60. #include <rpc/pmap_clnt.h>
  61. #include <rpc/pmap_prot.h>
  62. #include <rpc/nettype.h>
  63. #include <netinet/in.h>
  64. #include <assert.h>
  65. #include <errno.h>
  66. #include <netdb.h>
  67. #include <stdlib.h>
  68. #include <string.h>
  69. #include <syslog.h>
  70. #include <unistd.h>
  71. #include "rpc_internal.h"
  72. #ifdef __weak_alias
  73. __weak_alias(clntudp_bufcreate,_clntudp_bufcreate)
  74. __weak_alias(clntudp_create,_clntudp_create)
  75. __weak_alias(clnttcp_create,_clnttcp_create)
  76. __weak_alias(clntraw_create,_clntraw_create)
  77. __weak_alias(get_myaddress,_get_myaddress)
  78. __weak_alias(svcfd_create,_svcfd_create)
  79. __weak_alias(svcudp_bufcreate,_svcudp_bufcreate)
  80. __weak_alias(svcudp_create,_svcudp_create)
  81. __weak_alias(svctcp_create,_svctcp_create)
  82. __weak_alias(svcraw_create,_svcraw_create)
  83. __weak_alias(callrpc,_callrpc)
  84. __weak_alias(registerrpc,_registerrpc)
  85. __weak_alias(clnt_broadcast,_clnt_broadcast)
  86. #endif
  87. #ifdef _REENTRANT
  88. extern mutex_t rpcsoc_lock;
  89. #endif
  90. static CLIENT *clnt_com_create __P((struct sockaddr_in *, rpcprog_t, rpcvers_t,
  91. int *, u_int, u_int, const char *));
  92. static SVCXPRT *svc_com_create __P((int, u_int, u_int, const char *));
  93. static bool_t rpc_wrap_bcast __P((char *, struct netbuf *, struct netconfig *));
  94. /*
  95. * A common clnt create routine
  96. */
  97. static CLIENT *
  98. clnt_com_create(raddr, prog, vers, sockp, sendsz, recvsz, tp)
  99. struct sockaddr_in *raddr;
  100. rpcprog_t prog;
  101. rpcvers_t vers;
  102. int *sockp;
  103. u_int sendsz;
  104. u_int recvsz;
  105. const char *tp;
  106. {
  107. CLIENT *cl;
  108. int madefd = FALSE;
  109. int fd;
  110. struct netconfig *nconf;
  111. struct netbuf bindaddr;
  112. _DIAGASSERT(raddr != NULL);
  113. _DIAGASSERT(sockp != NULL);
  114. _DIAGASSERT(tp != NULL);
  115. fd = *sockp;
  116. mutex_lock(&rpcsoc_lock);
  117. if ((nconf = __rpc_getconfip(tp)) == NULL) {
  118. rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
  119. mutex_unlock(&rpcsoc_lock);
  120. return (NULL);
  121. }
  122. if (fd == RPC_ANYSOCK) {
  123. fd = __rpc_nconf2fd(nconf);
  124. if (fd == -1)
  125. goto syserror;
  126. madefd = TRUE;
  127. }
  128. if (raddr->sin_port == 0) {
  129. u_int proto;
  130. u_short sport;
  131. mutex_unlock(&rpcsoc_lock); /* pmap_getport is recursive */
  132. proto = strcmp(tp, "udp") == 0 ? IPPROTO_UDP : IPPROTO_TCP;
  133. sport = pmap_getport(raddr, (u_long)prog, (u_long)vers,
  134. proto);
  135. if (sport == 0) {
  136. goto err;
  137. }
  138. raddr->sin_port = htons(sport);
  139. mutex_lock(&rpcsoc_lock); /* pmap_getport is recursive */
  140. }
  141. /* Transform sockaddr_in to netbuf */
  142. bindaddr.maxlen = bindaddr.len = sizeof (struct sockaddr_in);
  143. bindaddr.buf = raddr;
  144. bindresvport(fd, NULL);
  145. cl = clnt_tli_create(fd, nconf, &bindaddr, prog, vers,
  146. sendsz, recvsz);
  147. if (cl) {
  148. if (madefd == TRUE) {
  149. /*
  150. * The fd should be closed while destroying the handle.
  151. */
  152. (void) CLNT_CONTROL(cl, CLSET_FD_CLOSE, NULL);
  153. *sockp = fd;
  154. }
  155. (void) freenetconfigent(nconf);
  156. mutex_unlock(&rpcsoc_lock);
  157. return (cl);
  158. }
  159. goto err;
  160. syserror:
  161. rpc_createerr.cf_stat = RPC_SYSTEMERROR;
  162. rpc_createerr.cf_error.re_errno = errno;
  163. err: if (madefd == TRUE)
  164. (void) close(fd);
  165. (void) freenetconfigent(nconf);
  166. mutex_unlock(&rpcsoc_lock);
  167. return (NULL);
  168. }
  169. CLIENT *
  170. clntudp_bufcreate(raddr, prog, vers, wait, sockp, sendsz, recvsz)
  171. struct sockaddr_in *raddr;
  172. u_long prog;
  173. u_long vers;
  174. struct timeval wait;
  175. int *sockp;
  176. u_int sendsz;
  177. u_int recvsz;
  178. {
  179. CLIENT *cl;
  180. _DIAGASSERT(raddr != NULL);
  181. _DIAGASSERT(sockp != NULL);
  182. cl = clnt_com_create(raddr, (rpcprog_t)prog, (rpcvers_t)vers, sockp,
  183. sendsz, recvsz, "udp");
  184. if (cl == NULL) {
  185. return (NULL);
  186. }
  187. (void) CLNT_CONTROL(cl, CLSET_RETRY_TIMEOUT, (char *)(void *)&wait);
  188. return (cl);
  189. }
  190. CLIENT *
  191. clntudp_create(raddr, program, version, wait, sockp)
  192. struct sockaddr_in *raddr;
  193. u_long program;
  194. u_long version;
  195. struct timeval wait;
  196. int *sockp;
  197. {
  198. return clntudp_bufcreate(raddr, program, version, wait, sockp,
  199. UDPMSGSIZE, UDPMSGSIZE);
  200. }
  201. CLIENT *
  202. clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz)
  203. struct sockaddr_in *raddr;
  204. u_long prog;
  205. u_long vers;
  206. int *sockp;
  207. u_int sendsz;
  208. u_int recvsz;
  209. {
  210. return clnt_com_create(raddr, (rpcprog_t)prog, (rpcvers_t)vers, sockp,
  211. sendsz, recvsz, "tcp");
  212. }
  213. CLIENT *
  214. clntraw_create(prog, vers)
  215. u_long prog;
  216. u_long vers;
  217. {
  218. return clnt_raw_create((rpcprog_t)prog, (rpcvers_t)vers);
  219. }
  220. /*
  221. * A common server create routine
  222. */
  223. static SVCXPRT *
  224. svc_com_create(fd, sendsize, recvsize, netid)
  225. int fd;
  226. u_int sendsize;
  227. u_int recvsize;
  228. const char *netid;
  229. {
  230. struct netconfig *nconf;
  231. SVCXPRT *svc;
  232. int madefd = FALSE;
  233. int port;
  234. struct sockaddr_in sccsin;
  235. _DIAGASSERT(netid != NULL);
  236. if ((nconf = __rpc_getconfip(netid)) == NULL) {
  237. (void) syslog(LOG_ERR, "Could not get %s transport", netid);
  238. return (NULL);
  239. }
  240. if (fd == RPC_ANYSOCK) {
  241. fd = __rpc_nconf2fd(nconf);
  242. if (fd == -1) {
  243. (void) freenetconfigent(nconf);
  244. (void) syslog(LOG_ERR,
  245. "svc%s_create: could not open connection", netid);
  246. return (NULL);
  247. }
  248. madefd = TRUE;
  249. }
  250. memset(&sccsin, 0, sizeof sccsin);
  251. sccsin.sin_family = AF_INET;
  252. bindresvport(fd, &sccsin);
  253. listen(fd, SOMAXCONN);
  254. svc = svc_tli_create(fd, nconf, NULL, sendsize, recvsize);
  255. (void) freenetconfigent(nconf);
  256. if (svc == NULL) {
  257. if (madefd)
  258. (void) close(fd);
  259. return (NULL);
  260. }
  261. port = (((struct sockaddr_in *)svc->xp_ltaddr.buf)->sin_port);
  262. svc->xp_port = ntohs(port);
  263. return (svc);
  264. }
  265. SVCXPRT *
  266. svctcp_create(fd, sendsize, recvsize)
  267. int fd;
  268. u_int sendsize;
  269. u_int recvsize;
  270. {
  271. return svc_com_create(fd, sendsize, recvsize, "tcp");
  272. }
  273. SVCXPRT *
  274. svcudp_bufcreate(fd, sendsz, recvsz)
  275. int fd;
  276. u_int sendsz, recvsz;
  277. {
  278. return svc_com_create(fd, sendsz, recvsz, "udp");
  279. }
  280. SVCXPRT *
  281. svcfd_create(fd, sendsize, recvsize)
  282. int fd;
  283. u_int sendsize;
  284. u_int recvsize;
  285. {
  286. return svc_fd_create(fd, sendsize, recvsize);
  287. }
  288. SVCXPRT *
  289. svcudp_create(fd)
  290. int fd;
  291. {
  292. return svc_com_create(fd, UDPMSGSIZE, UDPMSGSIZE, "udp");
  293. }
  294. SVCXPRT *
  295. svcraw_create()
  296. {
  297. return svc_raw_create();
  298. }
  299. int
  300. get_myaddress(addr)
  301. struct sockaddr_in *addr;
  302. {
  303. _DIAGASSERT(addr != NULL);
  304. memset((void *) addr, 0, sizeof(*addr));
  305. addr->sin_family = AF_INET;
  306. addr->sin_port = htons(PMAPPORT);
  307. addr->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  308. return (0);
  309. }
  310. /*
  311. * For connectionless "udp" transport. Obsoleted by rpc_call().
  312. */
  313. int
  314. callrpc(host, prognum, versnum, procnum, inproc, in, outproc, out)
  315. char *host;
  316. int prognum, versnum, procnum;
  317. xdrproc_t inproc, outproc;
  318. char *in, *out;
  319. {
  320. return (int)rpc_call(host, (rpcprog_t)prognum, (rpcvers_t)versnum,
  321. (rpcproc_t)procnum, inproc, in, outproc, out, "udp");
  322. }
  323. /*
  324. * For connectionless kind of transport. Obsoleted by rpc_reg()
  325. */
  326. int
  327. registerrpc(prognum, versnum, procnum, progname, inproc, outproc)
  328. int prognum, versnum, procnum;
  329. char *(*progname) __P((char [UDPMSGSIZE]));
  330. xdrproc_t inproc, outproc;
  331. {
  332. return rpc_reg((rpcprog_t)prognum, (rpcvers_t)versnum,
  333. (rpcproc_t)procnum, progname, inproc, outproc, __UNCONST("udp"));
  334. }
  335. /*
  336. * All the following clnt_broadcast stuff is convulated; it supports
  337. * the earlier calling style of the callback function
  338. */
  339. #ifdef _REENTRANT
  340. static thread_key_t clnt_broadcast_key;
  341. #endif
  342. static resultproc_t clnt_broadcast_result_main;
  343. /*
  344. * Need to translate the netbuf address into sockaddr_in address.
  345. * Dont care about netid here.
  346. */
  347. /* ARGSUSED */
  348. static bool_t
  349. rpc_wrap_bcast(resultp, addr, nconf)
  350. char *resultp; /* results of the call */
  351. struct netbuf *addr; /* address of the guy who responded */
  352. struct netconfig *nconf; /* Netconf of the transport */
  353. {
  354. resultproc_t clnt_broadcast_result;
  355. _DIAGASSERT(resultp != NULL);
  356. _DIAGASSERT(addr != NULL);
  357. _DIAGASSERT(nconf != NULL);
  358. if (strcmp(nconf->nc_netid, "udp"))
  359. return (FALSE);
  360. #ifdef _REENTRANT
  361. if (__isthreaded == 0)
  362. clnt_broadcast_result = clnt_broadcast_result_main;
  363. else
  364. clnt_broadcast_result = thr_getspecific(clnt_broadcast_key);
  365. #else
  366. clnt_broadcast_result = clnt_broadcast_result_main;
  367. #endif
  368. return (*clnt_broadcast_result)(resultp,
  369. (struct sockaddr_in *)addr->buf);
  370. }
  371. #ifdef _REENTRANT
  372. static once_t clnt_broadcast_once = ONCE_INITIALIZER;
  373. static void
  374. clnt_broadcast_setup(void)
  375. {
  376. thr_keycreate(&clnt_broadcast_key, free);
  377. }
  378. #endif
  379. /*
  380. * Broadcasts on UDP transport. Obsoleted by rpc_broadcast().
  381. */
  382. enum clnt_stat
  383. clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult)
  384. u_long prog; /* program number */
  385. u_long vers; /* version number */
  386. u_long proc; /* procedure number */
  387. xdrproc_t xargs; /* xdr routine for args */
  388. caddr_t argsp; /* pointer to args */
  389. xdrproc_t xresults; /* xdr routine for results */
  390. caddr_t resultsp; /* pointer to results */
  391. resultproc_t eachresult; /* call with each result obtained */
  392. {
  393. #ifdef _REENTRANT
  394. if (__isthreaded == 0)
  395. clnt_broadcast_result_main = eachresult;
  396. else {
  397. thr_once(&clnt_broadcast_once, clnt_broadcast_setup);
  398. thr_setspecific(clnt_broadcast_key, (void *) eachresult);
  399. }
  400. #else
  401. clnt_broadcast_result_main = eachresult;
  402. #endif
  403. return rpc_broadcast((rpcprog_t)prog, (rpcvers_t)vers,
  404. (rpcproc_t)proc, xargs, argsp, xresults, resultsp,
  405. (resultproc_t) rpc_wrap_bcast, "udp");
  406. }
  407. #endif /* PORTMAP */