PageRenderTime 26ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/ogdi-3.2.0.beta2/external/rpc_win32/LIBRPC/clnt_tcp.c

#
C | 554 lines | 395 code | 47 blank | 112 comment | 74 complexity | e02d66277f91854663eb8ec9930c3c05 MD5 | raw file
Possible License(s): GPL-3.0, 0BSD
  1. /*********************************************************************
  2. * RPC for the Windows NT Operating System
  3. * 1993 by Martin F. Gergeleit
  4. * Users may use, copy or modify Sun RPC for the Windows NT Operating
  5. * System according to the Sun copyright below.
  6. *
  7. * RPC for the Windows NT Operating System COMES WITH ABSOLUTELY NO
  8. * WARRANTY, NOR WILL I BE LIABLE FOR ANY DAMAGES INCURRED FROM THE
  9. * USE OF. USE ENTIRELY AT YOUR OWN RISK!!!
  10. *********************************************************************/
  11. /* @(#)clnt_tcp.c 2.2 88/08/01 4.0 RPCSRC */
  12. /*
  13. * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  14. * unrestricted use provided that this legend is included on all tape
  15. * media and as a part of the software program in whole or part. Users
  16. * may copy or modify Sun RPC without charge, but are not authorized
  17. * to license or distribute it to anyone else except as part of a product or
  18. * program developed by the user.
  19. *
  20. * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  21. * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  22. * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  23. *
  24. * Sun RPC is provided with no support and without any obligation on the
  25. * part of Sun Microsystems, Inc. to assist in its use, correction,
  26. * modification or enhancement.
  27. *
  28. * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  29. * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  30. * OR ANY PART THEREOF.
  31. *
  32. * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  33. * or profits or other special, indirect and consequential damages, even if
  34. * Sun has been advised of the possibility of such damages.
  35. *
  36. * Sun Microsystems, Inc.
  37. * 2550 Garcia Avenue
  38. * Mountain View, California 94043
  39. */
  40. #if !defined(lint) && defined(SCCSIDS)
  41. static char sccsid[] = "@(#)clnt_tcp.c 1.37 87/10/05 Copyr 1984 Sun Micro";
  42. #endif
  43. /*
  44. * clnt_tcp.c, Implements a TCP/IP based, client side RPC.
  45. *
  46. * Copyright (C) 1984, Sun Microsystems, Inc.
  47. *
  48. * TCP based RPC supports 'batched calls'.
  49. * A sequence of calls may be batched-up in a send buffer. The rpc call
  50. * return immediately to the client even though the call was not necessarily
  51. * sent. The batching occurs if the results' xdr routine is NULL (0) AND
  52. * the rpc timeout value is zero (see clnt.h, rpc).
  53. *
  54. * Clients should NOT casually batch calls that in fact return results; that is,
  55. * the server side should be aware that a call is batched and not produce any
  56. * return message. Batched calls that produce many result messages can
  57. * deadlock (netlock) the client and the server....
  58. *
  59. * Now go hang yourself.
  60. */
  61. #include <stdio.h>
  62. #include <rpc/rpc.h>
  63. #ifdef WIN32
  64. #include <errno.h>
  65. #include <rpc/pmap_cln.h>
  66. #else
  67. #include <sys/socket.h>
  68. #include <netdb.h>
  69. #include <errno.h>
  70. #include <rpc/pmap_clnt.h>
  71. #endif
  72. #define MCALL_MSG_SIZE 24
  73. #ifndef WIN32
  74. extern int errno;
  75. #endif
  76. static int readtcp();
  77. static int writetcp();
  78. static enum clnt_stat clnttcp_call();
  79. static void clnttcp_abort();
  80. static void clnttcp_geterr();
  81. static bool_t clnttcp_freeres();
  82. static bool_t clnttcp_control();
  83. static void clnttcp_destroy();
  84. static struct clnt_ops tcp_ops = {
  85. clnttcp_call,
  86. clnttcp_abort,
  87. clnttcp_geterr,
  88. clnttcp_freeres,
  89. clnttcp_destroy,
  90. clnttcp_control
  91. };
  92. struct ct_data {
  93. int ct_sock;
  94. bool_t ct_closeit;
  95. struct timeval ct_wait;
  96. bool_t ct_waitset; /* wait set by clnt_control? */
  97. struct sockaddr_in ct_addr;
  98. struct rpc_err ct_error;
  99. char ct_mcall[MCALL_MSG_SIZE]; /* marshalled callmsg */
  100. u_int ct_mpos; /* pos after marshal */
  101. XDR ct_xdrs;
  102. };
  103. /*
  104. * Create a client handle for a tcp/ip connection.
  105. * If *sockp<0, *sockp is set to a newly created TCP socket and it is
  106. * connected to raddr. If *sockp non-negative then
  107. * raddr is ignored. The rpc/tcp package does buffering
  108. * similar to stdio, so the client must pick send and receive buffer sizes,];
  109. * 0 => use the default.
  110. * If raddr->sin_port is 0, then a binder on the remote machine is
  111. * consulted for the right port number.
  112. * NB: *sockp is copied into a private area.
  113. * NB: It is the clients responsibility to close *sockp.
  114. * NB: The rpch->cl_auth is set null authentication. Caller may wish to set this
  115. * something more useful.
  116. */
  117. CLIENT *
  118. clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz)
  119. struct sockaddr_in *raddr;
  120. u_long prog;
  121. u_long vers;
  122. register int *sockp;
  123. u_int sendsz;
  124. u_int recvsz;
  125. {
  126. CLIENT *h;
  127. register struct ct_data *ct;
  128. struct timeval now;
  129. struct rpc_msg call_msg;
  130. h = (CLIENT *)mem_alloc(sizeof(*h));
  131. if (h == NULL) {
  132. #ifdef WIN32
  133. nt_rpc_report("clnttcp_create: out of memory\n");
  134. rpc_createerr.cf_stat = RPC_SYSTEMERROR;
  135. rpc_createerr.cf_error.re_errno = ENOMEM;
  136. #else
  137. (void)fprintf(stderr, "clnttcp_create: out of memory\n");
  138. rpc_createerr.cf_stat = RPC_SYSTEMERROR;
  139. rpc_createerr.cf_error.re_errno = errno;
  140. #endif
  141. goto fooy;
  142. }
  143. ct = (struct ct_data *)mem_alloc(sizeof(*ct));
  144. if (ct == NULL) {
  145. #ifdef WIN32
  146. nt_rpc_report("clnttcp_create: out of memory\n");
  147. rpc_createerr.cf_stat = RPC_SYSTEMERROR;
  148. rpc_createerr.cf_error.re_errno = ENOMEM;
  149. #else
  150. (void)fprintf(stderr, "clnttcp_create: out of memory\n");
  151. rpc_createerr.cf_stat = RPC_SYSTEMERROR;
  152. rpc_createerr.cf_error.re_errno = errno;
  153. #endif
  154. goto fooy;
  155. }
  156. /*
  157. * If no port number given ask the pmap for one
  158. */
  159. if (raddr->sin_port == 0) {
  160. u_short port;
  161. if ((port = pmap_getport(raddr, prog, vers, IPPROTO_TCP)) == 0) {
  162. mem_free((caddr_t)ct, sizeof(struct ct_data));
  163. mem_free((caddr_t)h, sizeof(CLIENT));
  164. return ((CLIENT *)NULL);
  165. }
  166. raddr->sin_port = htons(port);
  167. }
  168. /*
  169. * If no socket given, open one
  170. */
  171. #ifdef WIN32
  172. if (*sockp == INVALID_SOCKET) {
  173. *sockp = socket(AF_INET, SOCK_STREAM, 0);
  174. (void)bindresvport(*sockp, (struct sockaddr_in *)0);
  175. if ((*sockp == INVALID_SOCKET)
  176. || (connect(*sockp, (struct sockaddr *)raddr,
  177. sizeof(*raddr)) < 0)) {
  178. rpc_createerr.cf_stat = RPC_SYSTEMERROR;
  179. rpc_createerr.cf_error.re_errno = WSAerrno;
  180. (void)closesocket(*sockp);
  181. #else
  182. if (*sockp < 0) {
  183. *sockp = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  184. (void)bindresvport(*sockp, (struct sockaddr_in *)0);
  185. if ((*sockp < 0)
  186. || (connect(*sockp, (struct sockaddr *)raddr,
  187. sizeof(*raddr)) < 0)) {
  188. rpc_createerr.cf_stat = RPC_SYSTEMERROR;
  189. rpc_createerr.cf_error.re_errno = errno;
  190. (void)close(*sockp);
  191. #endif
  192. goto fooy;
  193. }
  194. ct->ct_closeit = TRUE;
  195. } else {
  196. ct->ct_closeit = FALSE;
  197. }
  198. /*
  199. * Set up private data struct
  200. */
  201. ct->ct_sock = *sockp;
  202. ct->ct_wait.tv_usec = 0;
  203. ct->ct_waitset = FALSE;
  204. ct->ct_addr = *raddr;
  205. /*
  206. * Initialize call message
  207. */
  208. (void)gettimeofday(&now, (struct timezone *)0);
  209. call_msg.rm_xid = getpid() ^ now.tv_sec ^ now.tv_usec;
  210. call_msg.rm_direction = CALL;
  211. call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
  212. call_msg.rm_call.cb_prog = prog;
  213. call_msg.rm_call.cb_vers = vers;
  214. /*
  215. * pre-serialize the staic part of the call msg and stash it away
  216. */
  217. xdrmem_create(&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE,
  218. XDR_ENCODE);
  219. if (! xdr_callhdr(&(ct->ct_xdrs), &call_msg)) {
  220. if (ct->ct_closeit) {
  221. #ifdef WIN32
  222. (void)closesocket(*sockp);
  223. #else
  224. (void)close(*sockp);
  225. #endif
  226. }
  227. goto fooy;
  228. }
  229. ct->ct_mpos = XDR_GETPOS(&(ct->ct_xdrs));
  230. XDR_DESTROY(&(ct->ct_xdrs));
  231. /*
  232. * Create a client handle which uses xdrrec for serialization
  233. * and authnone for authentication.
  234. */
  235. xdrrec_create(&(ct->ct_xdrs), sendsz, recvsz,
  236. (caddr_t)ct, readtcp, writetcp);
  237. h->cl_ops = &tcp_ops;
  238. h->cl_private = (caddr_t) ct;
  239. h->cl_auth = authnone_create();
  240. return (h);
  241. fooy:
  242. /*
  243. * Something goofed, free stuff and barf
  244. */
  245. mem_free((caddr_t)ct, sizeof(struct ct_data));
  246. mem_free((caddr_t)h, sizeof(CLIENT));
  247. return ((CLIENT *)NULL);
  248. }
  249. static enum clnt_stat
  250. clnttcp_call(h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout)
  251. register CLIENT *h;
  252. u_long proc;
  253. xdrproc_t xdr_args;
  254. caddr_t args_ptr;
  255. xdrproc_t xdr_results;
  256. caddr_t results_ptr;
  257. struct timeval timeout;
  258. {
  259. register struct ct_data *ct = (struct ct_data *) h->cl_private;
  260. register XDR *xdrs = &(ct->ct_xdrs);
  261. struct rpc_msg reply_msg;
  262. u_long x_id;
  263. u_long *msg_x_id = (u_long *)(ct->ct_mcall); /* yuk */
  264. register bool_t shipnow;
  265. int refreshes = 2;
  266. if (!ct->ct_waitset) {
  267. ct->ct_wait = timeout;
  268. }
  269. shipnow =
  270. (xdr_results == (xdrproc_t)0 && timeout.tv_sec == 0
  271. && timeout.tv_usec == 0) ? FALSE : TRUE;
  272. call_again:
  273. xdrs->x_op = XDR_ENCODE;
  274. ct->ct_error.re_status = RPC_SUCCESS;
  275. x_id = ntohl(--(*msg_x_id));
  276. if ((! XDR_PUTBYTES(xdrs, ct->ct_mcall, ct->ct_mpos)) ||
  277. (! XDR_PUTLONG(xdrs, (long *)&proc)) ||
  278. (! AUTH_MARSHALL(h->cl_auth, xdrs)) ||
  279. (! (*xdr_args)(xdrs, args_ptr))) {
  280. if (ct->ct_error.re_status == RPC_SUCCESS)
  281. ct->ct_error.re_status = RPC_CANTENCODEARGS;
  282. (void)xdrrec_endofrecord(xdrs, TRUE);
  283. return (ct->ct_error.re_status);
  284. }
  285. if (! xdrrec_endofrecord(xdrs, shipnow))
  286. return (ct->ct_error.re_status = RPC_CANTSEND);
  287. if (! shipnow)
  288. return (RPC_SUCCESS);
  289. /*
  290. * Hack to provide rpc-based message passing
  291. */
  292. if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
  293. return(ct->ct_error.re_status = RPC_TIMEDOUT);
  294. }
  295. /*
  296. * Keep receiving until we get a valid transaction id
  297. */
  298. xdrs->x_op = XDR_DECODE;
  299. while (TRUE) {
  300. reply_msg.acpted_rply.ar_verf = _null_auth;
  301. reply_msg.acpted_rply.ar_results.where = NULL;
  302. reply_msg.acpted_rply.ar_results.proc = xdr_void;
  303. if (! xdrrec_skiprecord(xdrs))
  304. return (ct->ct_error.re_status);
  305. /* now decode and validate the response header */
  306. if (! xdr_replymsg(xdrs, &reply_msg)) {
  307. if (ct->ct_error.re_status == RPC_SUCCESS)
  308. continue;
  309. return (ct->ct_error.re_status);
  310. }
  311. if (reply_msg.rm_xid == x_id)
  312. break;
  313. }
  314. /*
  315. * process header
  316. */
  317. _seterr_reply(&reply_msg, &(ct->ct_error));
  318. if (ct->ct_error.re_status == RPC_SUCCESS) {
  319. if (! AUTH_VALIDATE(h->cl_auth, &reply_msg.acpted_rply.ar_verf)) {
  320. ct->ct_error.re_status = RPC_AUTHERROR;
  321. ct->ct_error.re_why = AUTH_INVALIDRESP;
  322. } else if (! (*xdr_results)(xdrs, results_ptr)) {
  323. if (ct->ct_error.re_status == RPC_SUCCESS)
  324. ct->ct_error.re_status = RPC_CANTDECODERES;
  325. }
  326. /* free verifier ... */
  327. if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) {
  328. xdrs->x_op = XDR_FREE;
  329. (void)xdr_opaque_auth(xdrs, &(reply_msg.acpted_rply.ar_verf));
  330. }
  331. } /* end successful completion */
  332. else {
  333. /* maybe our credentials need to be refreshed ... */
  334. if (refreshes-- && AUTH_REFRESH(h->cl_auth))
  335. goto call_again;
  336. } /* end of unsuccessful completion */
  337. return (ct->ct_error.re_status);
  338. }
  339. static void
  340. clnttcp_geterr(h, errp)
  341. CLIENT *h;
  342. struct rpc_err *errp;
  343. {
  344. register struct ct_data *ct =
  345. (struct ct_data *) h->cl_private;
  346. *errp = ct->ct_error;
  347. }
  348. static bool_t
  349. clnttcp_freeres(cl, xdr_res, res_ptr)
  350. CLIENT *cl;
  351. xdrproc_t xdr_res;
  352. caddr_t res_ptr;
  353. {
  354. register struct ct_data *ct = (struct ct_data *)cl->cl_private;
  355. register XDR *xdrs = &(ct->ct_xdrs);
  356. xdrs->x_op = XDR_FREE;
  357. return ((*xdr_res)(xdrs, res_ptr));
  358. }
  359. static void
  360. clnttcp_abort()
  361. {
  362. }
  363. static bool_t
  364. clnttcp_control(cl, request, info)
  365. CLIENT *cl;
  366. int request;
  367. char *info;
  368. {
  369. register struct ct_data *ct = (struct ct_data *)cl->cl_private;
  370. switch (request) {
  371. case CLSET_TIMEOUT:
  372. ct->ct_wait = *(struct timeval *)info;
  373. ct->ct_waitset = TRUE;
  374. break;
  375. case CLGET_TIMEOUT:
  376. *(struct timeval *)info = ct->ct_wait;
  377. break;
  378. case CLGET_SERVER_ADDR:
  379. *(struct sockaddr_in *)info = ct->ct_addr;
  380. break;
  381. default:
  382. return (FALSE);
  383. }
  384. return (TRUE);
  385. }
  386. static void
  387. clnttcp_destroy(h)
  388. CLIENT *h;
  389. {
  390. register struct ct_data *ct =
  391. (struct ct_data *) h->cl_private;
  392. if (ct->ct_closeit) {
  393. #ifdef WIN32
  394. (void)closesocket(ct->ct_sock);
  395. #else
  396. (void)close(ct->ct_sock);
  397. #endif
  398. }
  399. XDR_DESTROY(&(ct->ct_xdrs));
  400. mem_free((caddr_t)ct, sizeof(struct ct_data));
  401. mem_free((caddr_t)h, sizeof(CLIENT));
  402. }
  403. /*
  404. * Interface between xdr serializer and tcp connection.
  405. * Behaves like the system calls, read & write, but keeps some error state
  406. * around for the rpc level.
  407. */
  408. static int
  409. readtcp(ct, buf, len)
  410. register struct ct_data *ct;
  411. caddr_t buf;
  412. register int len;
  413. {
  414. #ifdef FD_SETSIZE
  415. fd_set mask;
  416. fd_set readfds;
  417. if (len == 0)
  418. return (0);
  419. FD_ZERO(&mask);
  420. FD_SET(ct->ct_sock, &mask);
  421. #else
  422. register int mask = 1 << (ct->ct_sock);
  423. int readfds;
  424. if (len == 0)
  425. return (0);
  426. #endif /* def FD_SETSIZE */
  427. while (TRUE) {
  428. readfds = mask;
  429. #ifdef WIN32
  430. switch (select(0 /* unused in winsock */, &readfds, (int*)NULL, (int*)NULL,
  431. &(ct->ct_wait))) {
  432. case 0:
  433. ct->ct_error.re_status = RPC_TIMEDOUT;
  434. return (-1);
  435. case -1:
  436. if (WSAerrno == EINTR)
  437. continue;
  438. ct->ct_error.re_status = RPC_CANTRECV;
  439. ct->ct_error.re_errno = WSAerrno;
  440. return (-1);
  441. }
  442. break;
  443. }
  444. switch (len = recv(ct->ct_sock, buf, len, 0)) {
  445. case 0:
  446. /* premature eof */
  447. ct->ct_error.re_errno = WSAECONNRESET;
  448. ct->ct_error.re_status = RPC_CANTRECV;
  449. len = -1; /* it's really an error */
  450. break;
  451. case -1:
  452. ct->ct_error.re_errno = WSAerrno;
  453. ct->ct_error.re_status = RPC_CANTRECV;
  454. break;
  455. }
  456. return (len);
  457. #else
  458. switch (select(_rpc_dtablesize(), &readfds, (int*)NULL, (int*)NULL,
  459. &(ct->ct_wait))) {
  460. case 0:
  461. ct->ct_error.re_status = RPC_TIMEDOUT;
  462. return (-1);
  463. case -1:
  464. if (errno == EINTR)
  465. continue;
  466. ct->ct_error.re_status = RPC_CANTRECV;
  467. ct->ct_error.re_errno = errno;
  468. return (-1);
  469. }
  470. break;
  471. }
  472. switch (len = read(ct->ct_sock, buf, len)) {
  473. case 0:
  474. /* premature eof */
  475. ct->ct_error.re_errno = ECONNRESET;
  476. ct->ct_error.re_status = RPC_CANTRECV;
  477. len = -1; /* it's really an error */
  478. break;
  479. case -1:
  480. ct->ct_error.re_errno = errno;
  481. ct->ct_error.re_status = RPC_CANTRECV;
  482. break;
  483. }
  484. return (len);
  485. #endif
  486. }
  487. static int
  488. writetcp(ct, buf, len)
  489. struct ct_data *ct;
  490. caddr_t buf;
  491. int len;
  492. {
  493. register int i, cnt;
  494. for (cnt = len; cnt > 0; cnt -= i, buf += i) {
  495. #ifdef WIN32
  496. if ((i = send(ct->ct_sock, buf, cnt, 0)) == -1) {
  497. ct->ct_error.re_errno = WSAerrno;
  498. #else
  499. if ((i = write(ct->ct_sock, buf, cnt)) == -1) {
  500. ct->ct_error.re_errno = errno;
  501. #endif
  502. ct->ct_error.re_status = RPC_CANTSEND;
  503. return (-1);
  504. }
  505. }
  506. return (len);
  507. }