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

VxWorks

开发平台:

C/C++

  1. /* portmap.c - rpc portmap daemon */
  2. /* Copyright 1984-2001 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5.  * Copyright (c) 1984 by Sun Microsystems, Inc.
  6.  */
  7. /*
  8.  * portmap.c, Implements the program,version to port number mapping for rpc.
  9.  */
  10. /*
  11.  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
  12.  * unrestricted use provided that this legend is included on all tape
  13.  * media and as a part of the software program in whole or part.  Users
  14.  * may copy or modify Sun RPC without charge, but are not authorized
  15.  * to license or distribute it to anyone else except as part of a product or
  16.  * program developed by the user.
  17.  *
  18.  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  19.  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  20.  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  21.  *
  22.  * Sun RPC is provided with no support and without any obligation on the
  23.  * part of Sun Microsystems, Inc. to assist in its use, correction,
  24.  * modification or enhancement.
  25.  *
  26.  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  27.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
  28.  * OR ANY PART THEREOF.
  29.  *
  30.  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
  31.  * or profits or other special, indirect and consequential damages, even if
  32.  * Sun has been advised of the possibility of such damages.
  33.  *
  34.  * Sun Microsystems, Inc.
  35.  * 2550 Garcia Avenue
  36.  * Mountain View, California  94043
  37.  */
  38. /*
  39. modification history
  40. --------------------
  41. 01q,05nov01,vvv  fixed compilation warning
  42. 01p,15oct01,rae  merge from truestack ver 01q, base 01o (AE / 5_X)
  43. 01o,15sep93,kdl  changed svcudp_create() call to only pass one param (SPR #2427)
  44. 01n,11aug93,jmm  Changed ioctl.h and socket.h to sys/ioctl.h and sys/socket.h
  45. 01m,04jun92,wmd  added forward declarations required for gcc960 v2.0.
  46. 01l,26may92,rrr  the tree shuffle
  47. 01k,04oct91,rrr  passed through the ansification filter
  48.   -changed includes to have absolute path from h/
  49.   -changed VOID to void
  50.   -changed copyright notice
  51. 01j,11jan91,shl  added keyword ENCAP_PARMS and RMTCALLARGS
  52. 01i,25oct90,dnw  removed include of utime.h.
  53. 01h,11may90,yao  added missing modification history (01g) for the last checkin.
  54. 01g,09may90,yao  typecasted malloc to (char *).
  55. 01f,19apr90,hjb  de-linted.
  56. 01e,27oct89,hjb  changed exit (1) to taskSuspend (0).
  57. 01d,05apr88,gae  changed fprintf() to printErr().
  58. 01c,24nov87,gae  removed include of netdb.h.
  59. 01b,24oct87,dnw  changed call to rpcInit() to rpcTaskInit().
  60. */
  61. #include "rpc/rpc.h"
  62. #include "rpc/pmap_prot.h"
  63. #include "sys/socket.h"
  64. #include "sys/ioctl.h"
  65. #include "vxWorks.h"
  66. #include "memLib.h"
  67. #include "memPartLib.h"
  68. #include "rpcLib.h"
  69. #include "sockLib.h"
  70. #include "stdio.h"
  71. #include "unistd.h"
  72. #include "taskLib.h"
  73. #include "stdlib.h"
  74. #include "rpc/get_myaddr.h"
  75. void reg_service();
  76. void pmapRegister ();
  77. LOCAL void  callit();
  78. static int debugging = 0;
  79. void
  80. portmapd ()
  81. {
  82. SVCXPRT *xprt;
  83. int sock;
  84. struct sockaddr_in addr;
  85. int len = sizeof(struct sockaddr_in);
  86. rpcTaskInit ();
  87. if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
  88. perror("portmap cannot create socket");
  89. taskSuspend (0);
  90. }
  91. addr.sin_addr.s_addr = 0;
  92. addr.sin_family = AF_INET;
  93. addr.sin_port = htons((u_short) PMAPPORT);
  94. if (bind(sock, (struct sockaddr *)&addr, len) != 0) {
  95. perror("portmap cannot bind");
  96. taskSuspend (0);
  97. }
  98. if ((xprt = svcudp_create(sock)) == (SVCXPRT *)NULL) {
  99. printErr ("couldn't do udp_createn");
  100. taskSuspend (0);
  101. }
  102. if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
  103. perror("portmap cannot create socket");
  104. taskSuspend (0);
  105. }
  106. if (bind(sock, (struct sockaddr *)&addr, len) != 0) {
  107. perror("portmap cannot bind");
  108. taskSuspend (0);
  109. }
  110. if ((xprt = svctcp_create(sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE))
  111.     == (SVCXPRT *)NULL) {
  112. printErr ("couldn't do tcp_createn");
  113. taskSuspend (0);
  114. }
  115.         (void) svc_register (xprt, PMAPPROG, PMAPVERS, reg_service, (int)NULL);
  116. svc_run();
  117. printErr ("run_svc returned unexpectedlyn");
  118. abort();
  119. }
  120. struct pmaplist *pmaplist;
  121. static struct pmaplist *
  122. find_service(prog, vers, prot)
  123. u_long prog;
  124. u_long vers;
  125. {
  126. register struct pmaplist *hit = NULL;
  127. register struct pmaplist *pml;
  128. for (pml = pmaplist; pml != NULL; pml = pml->pml_next) {
  129. if ((pml->pml_map.pm_prog != prog) ||
  130. (pml->pml_map.pm_prot != prot))
  131. continue;
  132. hit = pml;
  133. if (pml->pml_map.pm_vers == vers)
  134.     break;
  135. }
  136. return (hit);
  137. }
  138. /*
  139.  * 1 OK, 0 not
  140.  */
  141. void reg_service(rqstp, xprt)
  142. struct svc_req *rqstp;
  143. SVCXPRT *xprt;
  144. {
  145. struct pmap reg;
  146. struct pmaplist *pml, *prevpml, *fnd;
  147. int ans, port;
  148. caddr_t t;
  149. switch ((int)rqstp->rq_proc) {
  150. case PMAPPROC_NULL:
  151. /*
  152.  * Null proc call
  153.  */
  154. if ((!svc_sendreply(xprt, xdr_void, (char *)NULL)) &&
  155.     debugging) {
  156. abort();
  157. }
  158. break;
  159. case PMAPPROC_SET:
  160. /*
  161.  * Set a program,version to port mapping
  162.  */
  163. if (!svc_getargs(xprt, xdr_pmap, &reg))
  164. svcerr_decode(xprt);
  165. else {
  166. /*
  167.  * check to see if already used
  168.  * find_service returns a hit even if
  169.  * the versions don't match, so check for it
  170.  */
  171. fnd = find_service(reg.pm_prog, reg.pm_vers,
  172. (int) reg.pm_prot);
  173. if (fnd && fnd->pml_map.pm_vers == reg.pm_vers) {
  174. if (fnd->pml_map.pm_port == reg.pm_port) {
  175. ans = 1;
  176. goto done;
  177. }
  178. else {
  179. ans = 0;
  180. goto done;
  181. }
  182. } else {
  183. /*
  184.  * add to END of list
  185.  */
  186. pml = (struct pmaplist *)
  187.       KHEAP_ALLOC((u_int)sizeof(struct pmaplist));
  188. pml->pml_map = reg;
  189. pml->pml_next = 0;
  190. if (pmaplist == 0) {
  191. pmaplist = pml;
  192. } else {
  193. for (fnd= pmaplist; fnd->pml_next != 0;
  194.     fnd = fnd->pml_next);
  195. fnd->pml_next = pml;
  196. }
  197. ans = 1;
  198. }
  199. done:
  200. if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&ans)) &&
  201.     debugging) {
  202. printErr ("svc_sendreplyn");
  203. abort();
  204. }
  205. }
  206. break;
  207. case PMAPPROC_UNSET:
  208. /*
  209.  * Remove a program,version to port mapping.
  210.  */
  211. if (!svc_getargs(xprt, xdr_pmap, &reg))
  212. svcerr_decode(xprt);
  213. else {
  214. ans = 0;
  215. for (prevpml = NULL, pml = pmaplist; pml != NULL; ) {
  216. if ((pml->pml_map.pm_prog != reg.pm_prog) ||
  217. (pml->pml_map.pm_vers != reg.pm_vers)) {
  218. /* both pml & prevpml move forwards */
  219. prevpml = pml;
  220. pml = pml->pml_next;
  221. continue;
  222. }
  223. /* found it; pml moves forward, prevpml stays */
  224. ans = 1;
  225. t = (caddr_t)pml;
  226. pml = pml->pml_next;
  227. if (prevpml == NULL)
  228. pmaplist = pml;
  229. else
  230. prevpml->pml_next = pml;
  231. KHEAP_FREE(t);
  232. }
  233. if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&ans)) &&
  234.     debugging) {
  235. printErr ("svc_sendreplyn");
  236. abort();
  237. }
  238. }
  239. break;
  240. case PMAPPROC_GETPORT:
  241. /*
  242.  * Lookup the mapping for a program,version and return its port
  243.  */
  244. if (!svc_getargs(xprt, xdr_pmap, &reg))
  245. svcerr_decode(xprt);
  246. else {
  247. fnd = find_service(reg.pm_prog, reg.pm_vers,
  248. (int)reg.pm_prot);
  249. if (fnd)
  250. port = fnd->pml_map.pm_port;
  251. else
  252. port = 0;
  253. if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&port)) &&
  254.     debugging) {
  255. printErr ("svc_sendreplyn");
  256. abort();
  257. }
  258. }
  259. break;
  260. case PMAPPROC_DUMP:
  261. /*
  262.  * Return the current set of mapped program,version
  263.  */
  264. if (!svc_getargs(xprt, xdr_void, NULL))
  265. svcerr_decode(xprt);
  266. else {
  267. if ((!svc_sendreply(xprt, xdr_pmaplist,
  268.     (caddr_t)&pmaplist)) && debugging) {
  269. printErr ("svc_sendreplyn");
  270. abort();
  271. }
  272. }
  273. break;
  274. case PMAPPROC_CALLIT:
  275. /*
  276.  * Calls a procedure on the local machine.  If the requested
  277.  * procedure is not registered this procedure does not return
  278.  * error information!!
  279.  * This procedure is only supported on rpc/udp and calls via
  280.  * rpc/udp.  It passes null authentication parameters.
  281.  */
  282. callit(rqstp, xprt);
  283. break;
  284. default:
  285. svcerr_noproc(xprt);
  286. break;
  287. }
  288. }
  289. /*
  290.  * Stuff for the rmtcall service
  291.  */
  292. #define ARGSIZE 9000
  293. typedef struct encap_parms {
  294. u_long arglen;
  295. char *args;
  296. } ENCAP_PARMS;
  297. static bool_t
  298. xdr_encap_parms(xdrs, epp)
  299. XDR *xdrs;
  300. struct encap_parms *epp;
  301. {
  302. return (xdr_bytes(xdrs, &(epp->args), (u_int *) &(epp->arglen),
  303. (u_int) ARGSIZE));
  304. }
  305. typedef struct rmtcallargs {
  306. u_long rmt_prog;
  307. u_long rmt_vers;
  308. u_long rmt_port;
  309. u_long rmt_proc;
  310. struct encap_parms rmt_args;
  311. } RMTCALLARGS;
  312. static bool_t
  313. xdr_rmtcall_args(xdrs, cap)
  314. register XDR *xdrs;
  315. register struct rmtcallargs *cap;
  316. {
  317. /* does not get a port number */
  318. if (xdr_u_long(xdrs, &(cap->rmt_prog)) &&
  319.     xdr_u_long(xdrs, &(cap->rmt_vers)) &&
  320.     xdr_u_long(xdrs, &(cap->rmt_proc))) {
  321. return (xdr_encap_parms(xdrs, &(cap->rmt_args)));
  322. }
  323. return (FALSE);
  324. }
  325. static bool_t
  326. xdr_rmtcall_result(xdrs, cap)
  327. register XDR *xdrs;
  328. register struct rmtcallargs *cap;
  329. {
  330. if (xdr_u_long(xdrs, &(cap->rmt_port)))
  331. return (xdr_encap_parms(xdrs, &(cap->rmt_args)));
  332. return (FALSE);
  333. }
  334. /*
  335.  * only worries about the struct encap_parms part of struct rmtcallargs.
  336.  * The arglen must already be set!!
  337.  */
  338. static bool_t
  339. xdr_opaque_parms(xdrs, cap)
  340. XDR *xdrs;
  341. struct rmtcallargs *cap;
  342. {
  343. return (xdr_opaque(xdrs, cap->rmt_args.args,
  344. (u_int)cap->rmt_args.arglen));
  345. }
  346. /*
  347.  * This routine finds and sets the length of incoming opaque paraters
  348.  * and then calls xdr_opaque_parms.
  349.  */
  350. static bool_t
  351. xdr_len_opaque_parms(xdrs, cap)
  352. register XDR *xdrs;
  353. struct rmtcallargs *cap;
  354. {
  355. register u_int beginpos, lowpos, highpos, currpos, pos;
  356. beginpos = lowpos = pos = xdr_getpos(xdrs);
  357. highpos = lowpos + ARGSIZE;
  358. while ((int)(highpos - lowpos) >= 0) {
  359. currpos = (lowpos + highpos) / 2;
  360. if (xdr_setpos(xdrs, currpos)) {
  361. pos = currpos;
  362. lowpos = currpos + 1;
  363. } else {
  364. highpos = currpos - 1;
  365. }
  366. }
  367. xdr_setpos(xdrs, beginpos);
  368. cap->rmt_args.arglen = pos - beginpos;
  369. return (xdr_opaque_parms(xdrs, cap));
  370. }
  371. /*
  372.  * Call a remote procedure service
  373.  * This procedure is very quiet when things go wrong.
  374.  * The proc is written to support broadcast rpc.  In the broadcast case,
  375.  * a machine should shut-up instead of complain, less the requestor be
  376.  * overrun with complaints at the expense of not hearing a valid reply ...
  377.  */
  378. static void
  379. callit(rqstp, xprt)
  380. struct svc_req *rqstp;
  381. SVCXPRT *xprt;
  382. {
  383. char buf[2000];
  384. struct rmtcallargs a;
  385. struct pmaplist *pml;
  386. u_short port;
  387. struct sockaddr_in me;
  388. int socket = -1;
  389. CLIENT *client;
  390. struct authunix_parms *au = (struct authunix_parms *)rqstp->rq_clntcred;
  391. struct timeval timeout;
  392. timeout.tv_sec = 5;
  393. timeout.tv_usec = 0;
  394. a.rmt_args.args = buf;
  395. if (!svc_getargs(xprt, xdr_rmtcall_args, &a))
  396.     return;
  397. if ((pml = find_service(a.rmt_prog, a.rmt_vers, IPPROTO_UDP)) == NULL)
  398.     return;
  399. port = pml->pml_map.pm_port;
  400. get_myaddress(&me);
  401. me.sin_port = htons(port);
  402. client = clntudp_create(&me, a.rmt_prog, a.rmt_vers, timeout, &socket);
  403. if (client != (CLIENT *)NULL) {
  404. if (rqstp->rq_cred.oa_flavor == AUTH_UNIX) {
  405. client->cl_auth = authunix_create(au->aup_machname,
  406.    au->aup_uid, au->aup_gid, (int) au->aup_len,
  407.    au->aup_gids);
  408. }
  409. a.rmt_port = (u_long)port;
  410. if (clnt_call(client, a.rmt_proc, xdr_opaque_parms, &a,
  411.     xdr_len_opaque_parms, &a, timeout) == RPC_SUCCESS) {
  412. svc_sendreply(xprt, xdr_rmtcall_result, (char *) &a);
  413. }
  414. AUTH_DESTROY(client->cl_auth);
  415. clnt_destroy(client);
  416. }
  417. (void)close(socket);
  418. }