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

VxWorks

开发平台:

C/C++

  1. /* remLib.c - remote command library */
  2. /* Copyright 1984 - 2001 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 02u,10may02,kbw  making man page edits
  8. 02t,15oct01,rae  merge from truestack ver 02w, base 02s (SPR #62484)
  9. 02s,11aug93,jmm  Changed ioctl.h and socket.h to sys/ioctl.h and sys/socket.h
  10. 02r,24jan93,jdi  documentation cleanup for 5.1.
  11. 02q,04sep92,jmm  changed bindresvport() to correctly check the value of port
  12.                    (spr #1469)
  13. 02p,19aug92,smb  Changed systime.h to sys/times.h.
  14. 02o,18jul92,smb  Changed errno.h to errnoLib.h.
  15. 02n,26may92,rrr  the tree shuffle
  16.   -changed includes to have absolute path from h/
  17. 02m,19nov91,rrr  shut up some ansi warnings.
  18. 02l,04oct91,rrr  passed through the ansification filter
  19.                   -changed functions to ansi style
  20.   -changed includes to have absolute path from h/
  21.   -changed VOID to void
  22.   -changed copyright notice
  23. 02k,30apr91,jdi  documentation tweaks.
  24. 02j,05apr91,jdi  documentation -- removed header parens and x-ref numbers;
  25.  doc review by dnw.
  26. 02i,11mar91,jaa  documentation cleanup.
  27. 02h,02oct90,hjb  added calls to htons() and ntohs() where needed.
  28. 02g,19jul90,dnw  mangen fix
  29. 02f,19apr90,hjb  added bindresvport(), modified rresvport()
  30. 02e,07mar90,jdi  documentation cleanup.
  31. 02d,07jun89,gae  changed SOCKADDR back to "struct sockaddr".
  32. 02c,03may89,dnw  moved iam() and whoami() here remLib.c from usrLib.c
  33.    to prevent usrLib from dragging in the network.
  34. 02b,30may88,dnw  changed to v4 names.
  35. 02a,28may88,dnw  removed host table routines to hostLib.
  36.  removed iam, whoami to usrLib.
  37.  changed call to fioStdErr to STD_ERR.
  38. 01w,04mar88,jcf  changed semaphores, and sem calls for new semLib.
  39. 01v,09jan88,gae  made hostTable a list -- no longer a fixed size.
  40. 01u,15dec87,gae  used inet_ntoa_b() instead of inet_ntoa(); misc. cleanups.
  41. 01t,14dec87,gae  documentation & checked malloc's for NULL.
  42. 01s,11nov87,jlf  documentation
  43. 01r,06nov87,dnw  changed remRcmd to take either host name or inet address.
  44. 01q,11jun87,llk  added remShowHosts() which shows all hosts in the host table
  45.    reachable from this VxWorks system.
  46.  changed remInetAddr() to call inet_addr.  remInetAddr() is
  47.    now considered obsolete.  Use inet_addr() instead.
  48.  implemented host name aliases in host table.
  49.  moved nethelp() from here to netLib.c.
  50.  added remFillHostName().
  51.  changed closeSocket() calls to close().
  52. 01p,02apr87,ecs  added include of strLib.h.
  53.  changed references to "struct sockaddr" to "SOCKADDR".
  54. 01o,24mar87,jlf  documentation.
  55. 01n,20dec86,dnw  changed iam() and remGetCurId to take password as 2nd param.
  56.  updated nethelp().
  57.  changed to not get include files from default directories.
  58. 01m,08nov86,dnw  change remRresvport to choose different port numbers
  59.    each time.  This is a TEMP (!?) fix for new net timing bug.
  60.  fixed remRcmd() not cleaning up correctly on some errors.
  61. 01l,29oct86,rdc  deleted references to exLib.h and exos.h.
  62. 01k,28oct86,rdc  lint.
  63. 01j,06oct86,gae  got rid of rcd() and rpwd()...netDrv handles it.
  64.  Moved HOST and HOSTNAME here from remLib.h for better hiding.
  65. 01i,04sep86,jlf  documentation.
  66. 01h,30jul86,rdc  fixed remRcmd to comply with (undocumented) rshd protocol.
  67. 01g,17jul86,rdc  added seperate stderr stream to remRcmd.
  68.  remRcmd now checks for recv errors correctly.
  69. 01f,11jul86,rdc  wrote nethelp.
  70. 01e,21may86,llk  moved remCat to netDrv.c, called it netGet.
  71.  changed memAllocate to malloc.
  72.     rdc  delinted.
  73. 01d,27mar86,rdc  made remCat a little less sensitive to crashed sockets.
  74.  made remCat test for write errors properly.
  75. 01c,28jan86,jlf  documentation
  76. 01b,08oct85,rdc  de-linted
  77. 01a,03oct85,rdc  written
  78. */
  79. /*
  80. This library provides routines that support remote command functions.  
  81. The rcmd() and rresvport() routines use protocols implemented in BSD 4.3; 
  82. they support remote command execution, and the opening of a socket with 
  83. a bound privileged port, respectively.  For more information, 
  84. see <Unix Network Programming> by W. Richard Stevens. This library also 
  85. includes routines that authorize network file access via 'netDrv'.
  86. To include 'remLib' in a VxWorks image, include the NETWRS_REMLIB 
  87. configuration component.  This component contains one parameter, 
  88. RSH_STDERR_SETUP_TIMEOUT.  Use this parameter to specify how  
  89. long an rcmd() call should wait for a return from its internal 
  90. call to select().  Valid values for RSH_STDERR_SETUP_TIMEOUT 
  91. are 0 (NO_WAIT), -1 (WAIT_FOREVER), or a positive integer 
  92. from 1 to 2147483647 inclusive.  This positive integer specifies 
  93. the wait in seconds.  The default value for RSH_STDERR_SETUP_TIMEOUT 
  94. is -1 (WAIT_FOREVER).
  95. INCLUDE FILES
  96. remLib.h
  97. SEE ALSO
  98. inetLib
  99. */
  100. #include "vxWorks.h"
  101. #include "sys/socket.h"
  102. #include "netinet/in.h"
  103. #include "remLib.h"
  104. #include "inetLib.h"
  105. #include "string.h"
  106. #include "errnoLib.h"
  107. #include "sys/times.h"
  108. #include "sockLib.h"
  109. #include "stdio.h"
  110. #include "unistd.h"
  111. #include "hostLib.h"
  112. #include "tickLib.h"
  113. #define MAX_RETRY_CONNECT 5
  114. LOCAL char remUser [MAX_IDENTITY_LEN];
  115. LOCAL char remPasswd [MAX_IDENTITY_LEN];
  116. int remLastResvPort = IPPORT_RESERVED - 1;
  117. long remStdErrSetupTimeout = 30; /* RSH's stderr setup timeout(sec) */
  118.          /* select() timeout for 2nd port */ 
  119. /*******************************************************************************
  120. *
  121. * remLibInit - initialize remLib
  122. *
  123. * RETURNS: N/A
  124. * NOMANUAL
  125. */
  126. void remLibInit
  127.     (
  128.     long timeout /* RSH_STDERR_SETUP_TIMEOUT */
  129.     )
  130.     {
  131.     remStdErrSetupTimeout = timeout;
  132.     }
  133. /*******************************************************************************
  134. *
  135. * rcmd - execute a shell command on a remote machine
  136. *
  137. * This routine uses a remote shell daemon, 'rshd', to execute a command 
  138. * on a remote system.  It is analogous to the BSD rcmd() routine.
  139. *
  140. * Internally, this rcmd() implementation uses a select() call to wait for 
  141. * a response from the 'rshd' daemon.  If rcmd() receives a response within  
  142. * its timeout, rcmd() calls accept() and completes by returning a socket 
  143. * descriptor for the data generated on the remote machine.
  144. *
  145. * The default timeout lets the rcmd() call wait forever.  However, 
  146. * you can change the timeout value using the RSH_STDERR_SETUP_TIMEOUT 
  147. * parameter associated with the NETWRS_REMLIB configuration component.
  148. *
  149. * RETURNS
  150. * A socket descriptor if the remote shell daemon accepts, or
  151. * ERROR if the remote command fails.
  152. *
  153. * S_remLib_RSH_ERROR, S_remLib_RSH_STDERR_SETUP_FAILED
  154. *
  155. * SEE ALSO: BSD reference entry for rcmd()
  156. */
  157. int rcmd
  158.     (
  159.     char *host,         /* host name or inet address */
  160.     int remotePort,     /* remote port to connect to (rshd) */
  161.     char *localUser,    /* local user name */
  162.     char *remoteUser,   /* remote user name */
  163.     char *cmd,          /* command */
  164.     int *fd2p           /* if this pointer is non-zero, */
  165. /* stderr socket is opened and */
  166. /* socket descriptor is filled in */
  167.     )
  168.     {
  169.     int sd;
  170.     struct sockaddr_in sin;
  171.     struct sockaddr_in mySin;
  172.     int mySinLen;
  173.     char c;
  174.     int lport = 0;
  175.     int nTries = 0;
  176.     int stdErrPort;
  177.     int stdErrSocket;
  178.     char stringBuf [20];
  179.     sin.sin_family = AF_INET;
  180.     sin.sin_port = htons (remotePort);
  181.     if (((sin.sin_addr.s_addr = hostGetByName (host)) == ERROR) &&
  182.         ((sin.sin_addr.s_addr = inet_addr (host)) == ERROR))
  183. {
  184. return (ERROR);
  185. }
  186.     do
  187. {
  188. sd = rresvport (&lport);
  189. if (sd == ERROR)
  190.     return (ERROR);
  191. if (connect (sd, (struct sockaddr *) &sin, sizeof (sin)) == ERROR)
  192.     {
  193.     close (sd);
  194.     lport--;
  195.     }
  196. else
  197.     break;
  198. }
  199.     while (++nTries <= MAX_RETRY_CONNECT);
  200.     if (nTries > MAX_RETRY_CONNECT)
  201. return (ERROR);
  202.     if (fd2p == 0)
  203.         {
  204.         if (send (sd, "", 1, 0) <= 0)
  205.     {
  206.     close (sd);
  207.     return (ERROR);
  208.     }
  209.         lport = 0;
  210.         }
  211.     else
  212.         {
  213. fd_set  readfds;
  214. struct timeval *pT, t;
  215. stdErrPort = --lport;
  216. stdErrSocket = rresvport (&stdErrPort);
  217. if (stdErrSocket == ERROR)
  218.     {
  219.     close (sd);
  220.     return (ERROR);
  221.     }
  222. listen (stdErrSocket, 1);
  223. sprintf (stringBuf, "%d", stdErrPort);
  224. if (send (sd, stringBuf, strlen (stringBuf) + 1, 0) <= 0)
  225.     {
  226.     close (sd);
  227.     close (stdErrPort);
  228.     return (ERROR);
  229.     }
  230.     
  231. /* wait for rshd to connect. vxWorks will wait the connect     */
  232.         /* by user-configurable timeout here(note: this timeout is     */
  233.         /* just policy, so user can set whatever as far as the timeout */
  234.         /* does not conflict with existing TCP timers.                 */
  235. #ifndef MAX
  236. #define MAX(a, b)  ((a) > (b)? (a): (b))
  237. #endif
  238. FD_ZERO(&readfds);
  239. FD_SET(sd, &readfds);
  240. FD_SET(stdErrSocket, &readfds);
  241.         /* setup select timeout given by user */
  242.         switch (remStdErrSetupTimeout)
  243.             {
  244.             case NO_WAIT:
  245.         bzero ((char *)&t, sizeof(struct timeval));
  246. pT = &t;
  247.                 break;
  248.             case WAIT_FOREVER:
  249.                 pT = NULL;
  250.                 break;
  251.             default:
  252.         bzero ((char *)&t, sizeof(struct timeval));
  253.                 t.tv_sec = remStdErrSetupTimeout;
  254. pT = &t;
  255.             }
  256. if (select (MAX(sd, stdErrSocket)+1, &readfds, (fd_set *)NULL,
  257.     (fd_set *)NULL, pT) < 1 ||
  258.     !FD_ISSET(stdErrSocket, &readfds))
  259.     {
  260.     close (sd);
  261.     close (stdErrSocket);     
  262.     errnoSet (S_remLib_RSH_STDERR_SETUP_FAILED);
  263.     return (ERROR);
  264.     }
  265. /* rshd got back to the secondary port */
  266. mySinLen = sizeof (mySin);
  267. *fd2p = accept (stdErrSocket, (struct sockaddr *)&mySin, &mySinLen);
  268. if (*fd2p == ERROR)
  269.     {
  270.     close (sd);
  271.     close (stdErrSocket);
  272.     return (ERROR);
  273.     }
  274. close (stdErrSocket);
  275. }
  276.     if (send (sd, localUser, strlen(localUser) + 1, 0) <= 0)
  277. {
  278. close (sd);
  279. if (fd2p != NULL)
  280.     close (*fd2p);
  281. return (ERROR);
  282. }
  283.     if (send (sd, remoteUser, strlen(remoteUser) + 1, 0) <= 0)
  284. {
  285. close (sd);
  286. if (fd2p != NULL)
  287.     close (*fd2p);
  288. return (ERROR);
  289. }
  290.     if (send (sd, cmd, strlen(cmd) + 1, 0) <= 0)
  291. {
  292. close (sd);
  293. if (fd2p != NULL)
  294.     close (*fd2p);
  295. return (ERROR);
  296. }
  297.     /* bsd documentation for rshd is incorrect - null byte is actually
  298.        received on stdin socket */
  299.     if (recv (sd, &c, 1, 0) <= 0)
  300. {
  301. close (sd);
  302. if (fd2p != NULL)
  303.     close (*fd2p);
  304. return (ERROR);
  305. }
  306.     if (c != 0)
  307. {
  308. /* error will come in on stdin socket */
  309. while (recv (sd, &c, 1, 0) == 1)
  310.     {
  311.     write (STD_ERR, &c, 1);
  312.     if (c == 'n')
  313. break;
  314.     }
  315. errnoSet (S_remLib_RSH_ERROR);
  316. close (sd);
  317. if (fd2p != NULL)
  318.     close (*fd2p);
  319. return (ERROR);
  320. }
  321.     return (sd);
  322.     }
  323. /*******************************************************************************
  324. *
  325. * rresvport - open a socket with a privileged port bound to it
  326. *
  327. * This routine opens a socket with a privileged port bound to it.
  328. * It is analogous to the UNIX routine rresvport().
  329. *
  330. * RETURNS
  331. * A socket descriptor, or ERROR if either the socket cannot be opened or all
  332. * ports are in use.
  333. *
  334. * SEE ALSO: UNIX BSD 4.3 manual entry for rresvport()
  335. */
  336. int rresvport
  337.     (
  338.     FAST int *alport    /* port number to initially try */
  339.     )
  340.     {
  341.     struct sockaddr_in sin;
  342.     int sd;
  343.     sin.sin_family  = AF_INET;
  344.     sin.sin_addr.s_addr = 0;
  345.     sin.sin_port = htons (*alport);
  346.     if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == ERROR)
  347. return (ERROR);
  348.     if (bindresvport (sd, &sin) < 0)
  349. {
  350. close (sd);
  351. return (ERROR);
  352. }
  353.     *alport = ntohs (sin.sin_port);
  354.     return (sd);
  355.     }
  356. /*******************************************************************************
  357. *
  358. * remCurIdGet - get the current user name and password
  359. *
  360. * This routine gets the user name and password currently used for remote 
  361. * host access privileges and copies them to <user> and <passwd>.  Either
  362. * parameter can be initialized to NULL, and the corresponding item will not
  363. * be passed.
  364. *
  365. * RETURNS: N/A
  366. *
  367. * SEE ALSO: iam(), whoami()
  368. */
  369. void remCurIdGet
  370.     (
  371.     char *user,         /* where to return current user name */
  372.     char *passwd        /* where to return current password */
  373.     )
  374.     {
  375.     if (user != NULL)
  376. strcpy (user, remUser);
  377.     if (passwd != NULL)
  378. strcpy (passwd, remPasswd);
  379.     }
  380. /*******************************************************************************
  381. *
  382. * remCurIdSet - set the remote user name and password
  383. *
  384. * This routine specifies the user name that will have access privileges
  385. * on the remote machine.  The user name must exist in the remote
  386. * machine's f3/etc/passwdfP, and if it has been assigned a password,
  387. * the password must be specified in <newPasswd>.
  388. *
  389. * Either parameter can be NULL, and the corresponding item will not be set.
  390. *
  391. * The maximum length of the user name and the password is MAX_IDENTITY_LEN
  392. * (defined in remLib.h).
  393. *
  394. * NOTE: A more convenient version of this routine is iam(), which is intended
  395. * to be used from the shell.
  396. *
  397. * RETURNS: OK, or ERROR if the name or password is too long.
  398. *
  399. * SEE ALSO: iam(), whoami()
  400. */
  401. STATUS remCurIdSet
  402.     (
  403.     char *newUser,      /* user name to use on remote */
  404.     char *newPasswd     /* password to use on remote (NULL = none) */
  405.     )
  406.     {
  407.     if (((newUser != NULL) && (strlen (newUser) > MAX_IDENTITY_LEN-1)) ||
  408.         ((newPasswd != NULL) && (strlen (newPasswd) > MAX_IDENTITY_LEN-1)))
  409. {
  410. errnoSet (S_remLib_IDENTITY_TOO_BIG);
  411. return (ERROR);
  412. }
  413.     if (newUser == NULL)
  414. remUser[0] = EOS;
  415.     else
  416. strcpy (remUser, newUser);
  417.     if (newPasswd == NULL)
  418. remPasswd[0] = EOS;
  419.     else
  420. strcpy (remPasswd, newPasswd);
  421.     return (OK);
  422.     }
  423. /*******************************************************************************
  424. *
  425. * iam - set the remote user name and password
  426. *
  427. * This routine specifies the user name that will have access privileges
  428. * on the remote machine.  The user name must exist in the remote
  429. * machine's f3/etc/passwdfP, and if it has been assigned a password,
  430. * the password must be specified in <newPasswd>.
  431. *
  432. * Either parameter can be NULL, and the corresponding item will not be set.
  433. *
  434. * The maximum length of the user name and the password is MAX_IDENTITY_LEN
  435. * (defined in remLib.h).
  436. *
  437. * NOTE: This routine is a more convenient version of remCurIdSet() and is
  438. * intended to be used from the shell.
  439. *
  440. * RETURNS: OK, or ERROR if the call fails.
  441. *
  442. * SEE ALSO: whoami(), remCurIdGet(), remCurIdSet()
  443. */
  444. STATUS iam
  445.     (
  446.     char *newUser,      /* user name to use on remote */
  447.     char *newPasswd     /* password to use on remote (NULL = none) */
  448.     )
  449.     {
  450.     if (remCurIdSet (newUser, newPasswd) != OK)
  451. {
  452. printErr ("User name or password too longn");
  453. return (ERROR);
  454. }
  455.     return (OK);
  456.     }
  457. /*******************************************************************************
  458. *
  459. * whoami - display the current remote identity
  460. *
  461. * This routine displays the user name currently used for remote machine
  462. * access.  The user name is set with iam() or remCurIdSet().
  463. *
  464. * RETURNS: N/A
  465. *
  466. * SEE ALSO: iam(), remCurIdGet(), remCurIdSet()
  467. */
  468. void whoami (void)
  469.     {
  470.     char user [MAX_IDENTITY_LEN];
  471.     remCurIdGet (user, (char *) NULL);
  472.     printf ("%sn", user);
  473.     }
  474. /*******************************************************************************
  475. *
  476. * bindresvport - bind a socket to a privileged IP port
  477. *
  478. * This routine picks a port number between 600 and 1023 that is not being
  479. * used by any other programs and binds the socket passed as <sd> to that
  480. * port.  Privileged IP ports (numbers between and including 0 and 1023) are
  481. * reserved for privileged programs.
  482. *
  483. * RETURNS:
  484. * OK, or ERROR if the address family specified in <sin> is not supported or
  485. * the call fails.
  486. */
  487. STATUS bindresvport
  488.     (
  489.     int                         sd,     /* socket to be bound */
  490.     FAST struct sockaddr_in     *sin    /* socket address -- value/result */
  491.     )
  492.     {
  493.     FAST int startPort;
  494.     FAST int port;
  495.     struct sockaddr_in  myaddr;
  496.     if (sin == (struct sockaddr_in *)0)
  497. {
  498. sin = &myaddr;
  499. bzero((char *) sin, sizeof (*sin));
  500. sin->sin_family = AF_INET;
  501. }
  502.     else if (sin->sin_family != AF_INET)
  503. {
  504. errnoSet (EPFNOSUPPORT);
  505. return (ERROR);
  506. }
  507.     if (ntohs (sin->sin_port) == 0)
  508. sin->sin_port = htons (remLastResvPort);
  509.     port = startPort = ntohs (sin->sin_port);
  510.     FOREVER
  511. {
  512. --port;
  513. if (port <= IPPORT_RESERVED - 400)
  514.     port = IPPORT_RESERVED - 1;
  515. if (port == startPort)
  516.     {
  517.     errnoSet (S_remLib_ALL_PORTS_IN_USE);
  518.     return (ERROR);
  519.     }
  520. sin->sin_port = htons (port);
  521. if (bind (sd, (struct sockaddr *) sin, sizeof (*sin)) != ERROR)
  522.     {
  523.     remLastResvPort = port;
  524.     return (OK);
  525.     }
  526. }
  527.     }