pmap_rmt.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:14k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* pmap_rmt.c - client interface to pmap rpc service */
  2. /* Copyright 1984-2001 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5.  * Copyright (C) 1984, Sun Microsystems, Inc.
  6.  *
  7.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  8.  * unrestricted use provided that this legend is included on all tape
  9.  * media and as a part of the software program in whole or part.  Users
  10.  * may copy or modify Sun RPC without charge, but are not authorized
  11.  * to license or distribute it to anyone else except as part of a product or
  12.  * program developed by the user.
  13.  *
  14.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  15.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  16.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  17.  *
  18.  * Sun RPC is provided with no support and without any obligation on the
  19.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  20.  * modification or enhancement.
  21.  *
  22.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  23.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  24.  * OR ANY PART THEREOF.
  25.  *
  26.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  27.  * or profits or other special, indirect and consequential damages, even if
  28.  * Sun has been advised of the possibility of such damages.
  29.  *
  30.  * Sun Microsystems, Inc.
  31.  * 2550 Garcia Avenue
  32.  * Mountain View, California  94043
  33.  */
  34. /*
  35. modification history
  36. --------------------
  37. 01r,15oct01,rae  merge from truestack ver 01m, base 01h(p) (SPR #70325, etc.)
  38. 01q,23oct00,cn   replaced inet_makeaddr with inet_makeaddr_b (SPR #8797).
  39. 01h,20feb97,jank removed comment in comment L:239
  40. 01o,11aug93,jmm  Changed ioctl.h and socket.h to sys/ioctl.h and sys/socket.h
  41. 01n,26may92,rrr  the tree shuffle
  42.   -changed includes to have absolute path from h/
  43. 01m,04oct91,rrr  passed through the ansification filter
  44.   -changed includes to have absolute path from h/
  45.   -fixed #else and #endif
  46.   -changed copyright notice
  47. 01l,25oct90,dnw   removed include of utime.h.
  48. 01k,10may90,dnw   changed to use rpcErrnoGet instead of errnoGet
  49. 01j,11may90,yao   added missing modification history (01i) for the last checkin.
  50. 01i,09may90,yao   typecasted malloc to (char *).
  51. 01h,19apr90,hjb   de-linted.
  52. 01g,27oct89,hjb   upgraded to 4.0
  53. 01f,22jun88,dnw   name tweaks.
  54. 01e,30may88,dnw   changed to v4 names.
  55. 01d,05apr88,gae   updated select() to BSD4.3, i.e. used "fd_set".
  56.   changed fprintf() to printErr().
  57. 01c,22feb88,jcf   made kernel independent.
  58. 01b,11nov87,jlf   added wrs copyright, title, mod history, etc.
  59. 01a,01nov87,rdc   first VxWorks version
  60. */
  61. #ifndef lint
  62. /* static char sccsid[] = "@(#)pmap_rmt.c 1.1 86/02/03 Copyr 1984 Sun Micro"; */
  63. #endif
  64. /*
  65.  * pmap_rmt.c
  66.  * Client interface to pmap rpc service.
  67.  * remote call and broadcast service
  68.  *
  69.  */
  70. #include "vxWorks.h"
  71. #include "stdio.h"
  72. #include "rpc/rpctypes.h"
  73. #include "netinet/in.h"
  74. #include "rpc/xdr.h"
  75. #include "rpc/auth.h"
  76. #include "rpc/clnt.h"
  77. #include "rpc/rpc_msg.h"
  78. #include "rpc/pmap_prot.h"
  79. #include "rpc/pmap_clnt.h"
  80. #include "rpc/pmap_rmt.h" /* 4.0 */
  81. #include "sys/socket.h"
  82. #include "sockLib.h"
  83. #include "taskLib.h"
  84. #include "errno.h"
  85. #include "net/if.h"
  86. #include "sys/ioctl.h"
  87. #include "net/inet.h"
  88. #include "memLib.h"
  89. #include "ioLib.h"
  90. #include "tickLib.h"
  91. #include "rpcLib.h"
  92. #include "inetLib.h"
  93. #include "memPartLib.h"
  94. #define MAX_BROADCAST_SIZE 1400
  95. #define SOCKSIZ 40
  96. static struct timeval timeout = { 3, 0 };
  97. /* struct rmtcallargs and struct rmtcallres are defined in pmap_rmt.h - 4.0 */
  98. /*
  99.  * pmapper remote-call-service interface.
  100.  * This routine is used to call the pmapper remote call service
  101.  * which will look up a service program in the port maps, and then
  102.  * remotely call that routine with the given parameters.  This allows
  103.  * programs to do a lookup and call in one step.
  104.  */
  105. enum clnt_stat
  106. pmap_rmtcall(addr, prog, vers, proc, xdrargs, argsp, xdrres, resp, tout, port_ptr)
  107. struct sockaddr_in *addr;
  108. u_long prog, vers, proc;
  109. xdrproc_t xdrargs, xdrres;
  110. caddr_t argsp, resp;
  111. struct timeval tout;
  112. u_long *port_ptr;
  113. {
  114. int socket = -1;
  115. register CLIENT *client;
  116. struct rmtcallargs a;
  117. struct rmtcallres r;
  118. enum clnt_stat stat;
  119. addr->sin_port = htons((u_short) PMAPPORT);
  120. client = clntudp_create(addr, PMAPPROG, PMAPVERS, timeout, &socket);
  121. if (client != (CLIENT *)NULL) {
  122. a.prog = prog;
  123. a.vers = vers;
  124. a.proc = proc;
  125. a.args_ptr = argsp;
  126. a.xdr_args = xdrargs;
  127. r.port_ptr = port_ptr;
  128. r.results_ptr = resp;
  129. r.xdr_results = xdrres;
  130. stat = CLNT_CALL(client, PMAPPROC_CALLIT, xdr_rmtcall_args, &a,
  131.     xdr_rmtcallres, &r, tout);
  132. CLNT_DESTROY(client);
  133. } else {
  134. stat = RPC_FAILED;
  135. }
  136. (void)close(socket);
  137. addr->sin_port = 0;
  138. return (stat);
  139. }
  140. /*
  141.  * XDR remote call arguments
  142.  * written for XDR_ENCODE direction only
  143.  */
  144. bool_t
  145. xdr_rmtcall_args(xdrs, cap)
  146. register XDR *xdrs;
  147. register struct rmtcallargs *cap;
  148. {
  149. u_int lenposition, argposition, position;
  150. if (xdr_u_long(xdrs, &(cap->prog)) &&
  151.     xdr_u_long(xdrs, &(cap->vers)) &&
  152.     xdr_u_long(xdrs, &(cap->proc))) {
  153. lenposition = XDR_GETPOS(xdrs);
  154. if (! xdr_u_long(xdrs, &(cap->arglen)))
  155.     return (FALSE);
  156. argposition = XDR_GETPOS(xdrs);
  157. if (! (*(cap->xdr_args))(xdrs, cap->args_ptr))
  158.     return (FALSE);
  159. position = XDR_GETPOS(xdrs);
  160. cap->arglen = (u_long)position - (u_long)argposition;
  161. XDR_SETPOS(xdrs, lenposition);
  162. if (! xdr_u_long(xdrs, &(cap->arglen)))
  163.     return (FALSE);
  164. XDR_SETPOS(xdrs, position);
  165. return (TRUE);
  166. }
  167. return (FALSE);
  168. }
  169. /*
  170.  * XDR remote call results
  171.  * written for XDR_DECODE direction only
  172.  */
  173. bool_t
  174. xdr_rmtcallres(xdrs, crp)
  175. register XDR *xdrs;
  176. register struct rmtcallres *crp;
  177. {
  178. caddr_t port_ptr; /* 4.0 */
  179. port_ptr = (caddr_t) crp->port_ptr; /* 4.0 */
  180. if (xdr_reference(xdrs, &port_ptr, sizeof (u_long),  /* 4.0 */
  181. xdr_u_long) && xdr_u_long(xdrs, &crp->resultslen)) { /* 4.0 */
  182. crp->port_ptr = (u_long *) port_ptr; /* 4.0 */
  183. return ((*(crp->xdr_results))(xdrs, crp->results_ptr));
  184. }
  185. return (FALSE);
  186. }
  187. /*
  188.  * The following is kludged-up support for simple rpc broadcasts.
  189.  * Someday a large, complicated system will replace these trivial
  190.  * routines which only support udp/ip .
  191.  */
  192. LOCAL int /* 4.0 */
  193. getbroadcastnets(addrs, sock, buf)
  194. struct in_addr *addrs;
  195. int sock;  /* any valid socket will do */
  196. char *buf;  /* why allocxate more when we can use existing... */
  197. {
  198. char ifreqBuf [SOCKSIZ]; 
  199. struct ifconf ifc;
  200.         struct ifreq  *ifr;
  201. struct sockaddr_in *sin;
  202.         int i, len;
  203. ifc.ifc_len = UDPMSGSIZE;  /* changed from MAX_BROADCAST_SIZE - 4.0 */
  204.         ifc.ifc_buf = buf;
  205.         if (ioctl(sock, SIOCGIFCONF, (int)&ifc) < 0) 
  206.     {
  207.     perror("broadcast: ioctl (get interface configuration)");
  208.     return (0);
  209.     }
  210.         ifr = ifc.ifc_req;
  211.         for (i = 0, len = ifc.ifc_len; len; len -= (sizeof(ifr->ifr_name) + 
  212.     ifr->ifr_addr.sa_len))
  213.     {
  214.     bcopy ((caddr_t)ifr, ifreqBuf, (sizeof(ifr->ifr_name) + 
  215.     ifr->ifr_addr.sa_len)); 
  216.     if (ioctl(sock, SIOCGIFFLAGS, (int)ifreqBuf) < 0) 
  217. {
  218. perror("broadcast: ioctl (get interface flags)");
  219. continue;
  220. }
  221.     if ((((struct ifreq *)ifreqBuf)->ifr_flags & IFF_BROADCAST) &&
  222. (((struct ifreq *)ifreqBuf)->ifr_flags & IFF_UP) &&
  223. ifr->ifr_addr.sa_family == AF_INET) 
  224. {
  225. sin = (struct sockaddr_in *)&ifr->ifr_addr;
  226. #ifdef SIOCGIFBRDADDR /* 4.3 BSD */ /* 4.0 */
  227. /* 4.0 */ if (ioctl (sock, SIOCGIFBRDADDR, (int)ifreqBuf) < 0) {
  228. /* 4.0 */ inet_makeaddr_b (inet_netof
  229. /* 4.0 */ (sin->sin_addr),
  230. /* 4.0 */ (int) INADDR_ANY,
  231. &addrs [i]);
  232. i++;
  233. /* 4.0 */ } else {
  234. /* 4.0 */ addrs [ i++] =
  235.     ((struct sockaddr_in *)
  236.      &((struct ifreq *)ifreqBuf)->ifr_addr)
  237.     ->sin_addr;
  238. /* 4.0 */ }
  239. #else /* 4.2 BSD */  /* 4.0 */
  240. inet_makeaddr_b (inet_netof (sin->sin_addr.s_addr), 
  241.  INADDR_ANY,
  242.  &addrs [i]);
  243. i++;
  244. #endif /* SIOCGIFBRDADDR */
  245. }
  246.     ifr = (struct ifreq *)((char *)ifr + (sizeof(ifr->ifr_name) + 
  247.   ifr->ifr_addr.sa_len));
  248.     }
  249. return (i);
  250. }
  251. typedef bool_t (*resultproc_t)();
  252. enum clnt_stat
  253. clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult)
  254. u_long prog; /* program number */
  255. u_long vers; /* version number */
  256. u_long proc; /* procedure number */
  257. xdrproc_t xargs; /* xdr routine for args */
  258. caddr_t argsp; /* pointer to args */
  259. xdrproc_t xresults; /* xdr routine for results */
  260. caddr_t resultsp; /* pointer to results */
  261. resultproc_t eachresult; /* call with each result obtained */
  262. {
  263. enum clnt_stat stat;
  264. AUTH *unix_auth = authunix_create_default();
  265. XDR xdr_stream;
  266. register XDR *xdrs = &xdr_stream;
  267. int outlen, inlen, fromlen, nets;
  268. fd_set mask; /* 4.0 */
  269. fd_set readFds; /* 4.0 */
  270. int on = 1; /* 4.0 */
  271. /* XXX int fd;    4.0 */
  272. register int sock = 0, i;
  273. bool_t done = FALSE;
  274. register u_long xid;
  275. u_long port;
  276. struct in_addr addrs[20];
  277. struct sockaddr_in baddr, raddr; /* broadcast and response addresses */
  278. struct rmtcallargs a;
  279. struct rmtcallres r;
  280. struct rpc_msg msg;
  281. struct timeval t;
  282. /* XXX char outbuf[MAX_BROADCAST_SIZE], inbuf[MAX_BROADCAST_SIZE]; */
  283. /*
  284.  * XXX Hmmmm... is this done to save local stack space?
  285.  * Interesting...
  286.  */
  287. char *outbuf = (char *) KHEAP_ALLOC(MAX_BROADCAST_SIZE);
  288. char *inbuf =  (char *) KHEAP_ALLOC(MAX_BROADCAST_SIZE);
  289. if ((outbuf == NULL) || (inbuf == NULL))
  290.     {
  291.     panic ("rpc:clnt_broadcast: out of memory!n");
  292.     stat = RPC_CANTSEND;
  293.     goto done_broad;
  294.     }
  295.         if (unix_auth == NULL)
  296.     {
  297.     stat = RPC_CANTSEND;
  298.     goto done_broad;
  299.     }
  300. /*
  301.  * initialization: create a socket, a broadcast address, and
  302.  * preserialize the arguments into a send buffer.
  303.  */
  304. if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
  305. perror("Cannot create socket for broadcast rpc");
  306. stat = RPC_CANTSEND;
  307. goto done_broad;
  308. }
  309. #ifdef SO_BROADCAST /* 4.0 */
  310. /* 4.0*/ if (setsockopt (sock, SOL_SOCKET, SO_BROADCAST, (char *) &on,
  311. /* 4.0 */ sizeof (on)) < 0)
  312. /* 4.0 */    {
  313. /* 4.0 */    perror ("Cannot set socket option SO_BROADCAST");
  314. /* 4.0 */    stat = RPC_CANTSEND;
  315. /* 4.0 */    goto done_broad;
  316. /* 4.0 */    }
  317. #endif /* SO_BROADCAST */ /* 4.0 */
  318. FD_ZERO (&mask); /* 4.0 */
  319. FD_SET (sock, &mask); /* 4.0 */
  320. nets = getbroadcastnets(addrs, sock, inbuf);
  321. bzero((char *) &baddr, sizeof (baddr));
  322. baddr.sin_family = AF_INET;
  323. baddr.sin_port = htons((u_short) PMAPPORT);
  324. baddr.sin_addr.s_addr = htonl(INADDR_ANY);
  325. /* XXX (void)gettimeofday(&t, (struct timezone *)0); */
  326. /* msg.rm_xid = xid = getpid() ^ t.tv_sec ^ t.tv_usec; */
  327. msg.rm_xid = xid = taskIdSelf () ^ tickGet ();
  328. t.tv_usec = 0;
  329. msg.rm_direction = CALL;
  330. msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
  331. msg.rm_call.cb_prog = PMAPPROG;
  332. msg.rm_call.cb_vers = PMAPVERS;
  333. msg.rm_call.cb_proc = PMAPPROC_CALLIT;
  334. msg.rm_call.cb_cred = unix_auth->ah_cred;
  335. msg.rm_call.cb_verf = unix_auth->ah_verf;
  336. a.prog = prog;
  337. a.vers = vers;
  338. a.proc = proc;
  339. a.xdr_args = xargs;
  340. a.args_ptr = argsp;
  341. r.port_ptr = &port;
  342. r.xdr_results = xresults;
  343. r.results_ptr = resultsp;
  344. xdrmem_create(xdrs, outbuf, MAX_BROADCAST_SIZE, XDR_ENCODE);
  345. if ((! xdr_callmsg(xdrs, &msg)) || (! xdr_rmtcall_args(xdrs, &a))) {
  346. stat = RPC_CANTENCODEARGS;
  347. goto done_broad;
  348. }
  349. outlen = (int)xdr_getpos(xdrs);
  350. xdr_destroy(xdrs);
  351. /*
  352.  * Basic loop: broadcast a packet and wait a while for response(s).
  353.  * The response timeout grows larger per iteration.
  354.  */
  355. for (t.tv_sec = 4; t.tv_sec <= 14; t.tv_sec += 2) {
  356. for (i = 0; i < nets; i++) {
  357. baddr.sin_addr = addrs[i];
  358. if (sendto(sock, outbuf, outlen, 0,
  359. (struct sockaddr *)&baddr,
  360. sizeof (struct sockaddr)) != outlen) {
  361. perror("Cannot send broadcast packet");
  362. stat = RPC_CANTSEND;
  363. goto done_broad;
  364. }
  365. }
  366. if (eachresult == NULL) { /* 4.0 */
  367. stat = RPC_SUCCESS; /* 4.0 */
  368. goto done_broad; /* 4.0 */
  369. } /* 4.0 */
  370. recv_again:
  371. msg.acpted_rply.ar_verf = _null_auth;
  372. msg.acpted_rply.ar_results.where = (caddr_t)&r;
  373.                 msg.acpted_rply.ar_results.proc = xdr_rmtcallres;
  374. readFds = mask; /* 4.0 */
  375. /* XXX why keep resetting? */
  376. /* XXX FD_ZERO (&readFds);    4.0 */
  377. /* XXX FD_SET (fd, &readFds);    4.0 */
  378. /* 4.0 RPC uses getdtablesize () instead of FD_SETSIZE */
  379. switch (select (FD_SETSIZE, &readFds, (fd_set *)NULL,
  380. (fd_set *)NULL, &t))
  381. {
  382. case 0:  /* timed out */
  383. stat = RPC_TIMEDOUT;
  384. continue;
  385. case -1:  /* some kind of error */
  386. if (rpcErrnoGet () == EINTR)
  387. goto recv_again;
  388. perror("Broadcast select problem");
  389. stat = RPC_CANTRECV;
  390. goto done_broad;
  391. }  /* end of select results switch */
  392. /* XXX if (!FD_ISSET (fd, &readFds)) 4.0 */
  393. /* XXX goto recv_again; 4.0 */
  394. try_again:
  395. fromlen = sizeof(struct sockaddr);
  396. inlen = recvfrom(sock, inbuf, MAX_BROADCAST_SIZE, 0,
  397. (struct sockaddr *)&raddr, &fromlen);
  398. if (inlen < 0) {
  399. if (rpcErrnoGet () == EINTR)
  400. goto try_again;
  401. perror("Cannot receive reply to broadcast");
  402. stat = RPC_CANTRECV;
  403. goto done_broad;
  404. }
  405. if (inlen < sizeof(u_long))
  406. goto recv_again;
  407. /*
  408.  * see if reply transaction id matches sent id.
  409.  * If so, decode the results.
  410.  */
  411. xdrmem_create(xdrs, inbuf, (u_int) inlen, XDR_DECODE);
  412. if (xdr_replymsg(xdrs, &msg)) {
  413. if ((msg.rm_xid == xid) &&
  414. (msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
  415. (msg.acpted_rply.ar_stat == SUCCESS)) {
  416. raddr.sin_port = htons((u_short)port);
  417. done = (*eachresult)(resultsp, &raddr);
  418. }
  419. /* otherwise, we just ignore the errors ... */
  420. } else {
  421. #ifdef notdef
  422. /* some kind of deserialization problem ... */
  423. if (msg.rm_xid == xid)
  424. printErr("Broadcast deserialization problem");
  425. /* otherwise, just random garbage */
  426. #endif
  427. }
  428. xdrs->x_op = XDR_FREE;
  429. msg.acpted_rply.ar_results.proc = xdr_void;
  430. (void)xdr_replymsg(xdrs, &msg);
  431. (void)(*xresults)(xdrs, resultsp);
  432. xdr_destroy(xdrs);
  433. if (done) {
  434. stat = RPC_SUCCESS;
  435. goto done_broad;
  436. } else {
  437. goto recv_again;
  438. }
  439. }
  440. done_broad:
  441.         if (sock > 0)
  442.     (void)close(sock);
  443.         if (unix_auth != NULL)
  444.     AUTH_DESTROY(unix_auth);
  445. if (inbuf != NULL)
  446.     KHEAP_FREE(inbuf);
  447. if (outbuf != NULL)
  448.     KHEAP_FREE(outbuf);
  449. return (stat);
  450. }