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

VxWorks

开发平台:

C/C++

  1. /* wtxrpc.c - tornado rpc transport library */
  2. /* Copyright 1984-1996 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 02w,28sep01,fle  SPR#28684 : added usePMap parameter to ExchangeCreate ()
  8.                  routines
  9. 02v,15jun01,pch  Add new WTX_TS_INFO_GET_V2 service to handle WTX_RT_INFO
  10.                  change (from BOOL32 hasFpp to UINT32 hasCoprocessor) without
  11.                  breaking existing clients.
  12. 02u,19apr00,fle  SPR#28684 : Win32 port
  13. 02t,29mar00,fle  SPR#28684 : HPUX port
  14. 02s,24nov99,fle  SPR#28684 fix : multiple adapters in target server connection
  15. 02r,10may99,fle  made wtxRpcExchangeFree not use CLIENT anymore
  16. 02q,24mar99,fle  made WIN32 code also use auth_destroy mechanism (SPR#26002)
  17. 02p,07jan99,c_c  Let the target use the hard-coded Registry port number (SPR
  18.                  #23681 and #23449).
  19. 02o,21oct98,c_c  replaced a getenv by a wpwrGetEnv to be sure that
  20.                  WIND_REGISTRY is set.
  21. 02n,18aug98,pcn  Re-use xdr_WTX_MSG_EVTPT_LIST_2.
  22. 02m,11jun98,pcn  Added an input parameter at wtxEventListGet.
  23. 02l,26may98,pcn  Changed WTX_MSG_EVTPT_LIST_2 in WTX_MSG_EVTPT_LIST_GET.
  24. 02k,25mar98,dbt  added WTX_CONTEXT_STATUS_GET.
  25. 02j,24mar98,fle  Adapted wtxrpcKey to NULL transport handle mangement.
  26. 02i,24mar98,c_c  Get rid of portmapper.
  27. 02h,17mar98,jmb  merge HPSIM patch by jmb from 19aug97:
  28.  added socket option call to prevent target server sync task
  29.  from hanging when retrieving symbols from host. (SPR 8708)
  30. 02g,03mar98,fle  got rid of WTX_REGISTRY_PING service
  31.  + got rid of regex uses
  32. 02f,02mar98,pcn  WTX 2: Removed WTX_UN_REGIS_FOR_EVENT. Added
  33.                  WTX_UNREGISTER_FOR_EVENT, WTX_CACHE_TEXT_UPDATE,
  34.                  WTX_MEM_WIDTH_READ, WTX_MEM_WIDTH_WRITE, WTX_COMMAND_SEND,
  35.                  WTX_OBJ_MODULE_CHECKSUM, WTX_EVENT_LIST_GET,
  36.                  WTX_OBJ_MODULE_LOAD_2, WTX_EVENTPOINT_ADD_2,
  37.                  WTX_EVENTPOINT_LIST_2, WTX_OBJ_MODULE_UNLOAD_2.
  38. 02e,06feb98,c_c  Undo the last remove.
  39. 02d,05feb98,c_c  Removed an extra include "regex.h".
  40. 02c,04feb98,lcs  relocate #ifdef to repair damages
  41. 02b,03feb98,lcs  remove static variable declarations
  42. 02a,03feb98,lcs  use regex.h for WIN32 & </usr/include/regex.h> for UNIX
  43. 01z,26jan98,fle  added WTX_REGISTRY_PING routine
  44. 01y,20nov97,fle  added WTX_MEM_DISASSEMBLE service
  45. 01x,25feb97,elp  added valid machname in authunix_create() call (SPR# 7959).
  46. 01w,30sep96,elp  put in share, adapted to be compiled on target side SPR# 6775.
  47. 01v,28jun96,c_s  tweaks for AIX.
  48. 01u,09dec95,wmd  used authunix_create() call to pass uid explicity for WIN32,
  49.                  to fix SPR# 5609.
  50. 01t,27oct95,p_m  fixed SPR# 5196 by using the pid to generate the base
  51.  RPC program number (Unix only).
  52. 01s,26oct95,p_m  added WTX_AGENT_MODE_GET and WTX_DIRECT_CALL.
  53. 01r,24oct95,wmd  fixed so that processing delays caused by timeout in call
  54.                  to hostbyname() is eliminated, spr #5084, 
  55. 01q,14jun95,s_w  return WTX_ERR_EXCHANGE_NO_SERVER if client create fails.
  56. 01p,08jun95,c_s  added WTX_TARGET_ATTACH to rpc function list.
  57. 01o,01jun95,p_m  changed WTX_FUNC_CALL to use xdr_WTX_MSG_CONTEXT_DESC.
  58. 01n,30may95,p_m  completed WTX_MEM_SCAN and WTX_MEM_MOVE implementation.
  59. 01m,30may95,c_s  portablity tweak: use struct in_addr with inet_ntoa().
  60. 01l,30may95,c_s  added dotted-decimal IP address to key
  61. 01k,23may95,s_w  don't setup or destroy authentication for WIN32
  62. 01j,23may95,p_m  made missing name changes.
  63. 01i,22may95,s_w  update RPC server table for new WTX_MSG_OBJ_KILL in args
  64.  and add WTX_MSG_VIO_CHAN_GET/RELEASE messages.
  65. 01h,22may95,jcf  name revision.
  66. 01g,19may95,jcf  changed over to WIND_REGISTRY.
  67. 01g,18may95,jcf  changed over to TORNADO_REGISTRY.
  68. 01f,14may95,s_w  add in exchange functions for use by C API (wtx.c). Tidy
  69.  up rouintes to use types from host.h and make all routines
  70.  use status and error codes rather than print error messages.
  71. 01e,23feb95,p_m  took care of WIN32 platform.
  72. 01d,14feb95,p_m  changed S_wtx_ to WTX_ERR_ .
  73. 01c,22jan95,c_s  fixed memory leak.
  74. 01b,20jan95.jcf  made more portable.
  75. 01a,24dec94,c_s  written.
  76. */
  77. /* includes */
  78. #ifdef HOST
  79. #include "wpwrutil.h"
  80. #include "wtxrpc.h"
  81. #include "private/wtxexchp.h"
  82. #include "wtxmsg.h"
  83. #include "wtxxdr.h"
  84. #if defined(RS6000_AIX4) || defined (RS6000_AIX3)
  85. #undef malloc
  86. #endif
  87. #include <stdlib.h>
  88. #include <stdio.h>
  89. #include <string.h>
  90. #include <errno.h>
  91. #include <sys/param.h>
  92. #include <sys/socket.h>
  93. #include <sys/ioctl.h>
  94. #include <netdb.h>
  95. #include <arpa/inet.h>
  96. #ifdef SUN4_SOLARIS2
  97. #   include <sys/sockio.h>
  98. #endif /* SUN4_SOLARIS2 */
  99. #ifndef WIN32
  100. #   include <net/if.h>
  101. #endif /* ! WIN32 */
  102. #include <netinet/in.h>
  103. #include <unistd.h>
  104. #else
  105. #include "hostLib.h"
  106. #include "arpa/inet.h"
  107. #include "socket.h"
  108. #include "string.h"
  109. #include "stdio.h"
  110. #include "stdlib.h"
  111. #include "errno.h"
  112. #include "wtx.h"
  113. #include "wtxrpc.h"
  114. #include "private/wtxexchp.h"
  115. #include "wtxmsg.h"
  116. #include "wtxxdr.h"
  117. #if (CPU==SIMHPPA)
  118. #include "wdb/wdbLibP.h"
  119. #include "sockLib.h"
  120. #endif /* (CPU==SIMHPPA) */
  121. #endif /* HOST */
  122. /* typedefs */
  123. typedef struct rpc_service
  124.     {
  125.     xdrproc_t xdrIn;
  126.     xdrproc_t xdrOut;
  127.     } RPC_SERVICE;
  128. #ifndef HOST
  129. /* globals */
  130. UINT32 syncRegistry; /* inet registry address */
  131. struct opaque_auth  authCred; /* address of the authentication info */
  132. #endif /* HOST */
  133. #ifndef MCALL_MSG_SIZE
  134. #define MCALL_MSG_SIZE 24 /* marshalled call message */
  135. #endif /* MCALL_MSG_SIZE */
  136. /* locals */
  137. LOCAL RPC_SERVICE * (*rpcSvcTable)[] = NULL;
  138. LOCAL UINT32 rpcSvcTableSize = 0;
  139. LOCAL XDR svrXdrs; /* server XDR struct  */
  140. LOCAL char svrXdrsMCall[MCALL_MSG_SIZE]; /* marshalled callmsg */
  141. /* This is the UDP retry timeout used when creating a UDP service connection */
  142. LOCAL struct timeval rpcDefaultUdpTimeout = { 5, 0 };
  143. /* forward declarations */
  144. LOCAL WTX_ERROR_T rpcStatToError /* convert RPC status to WTX err code */
  145.     (
  146.     enum clnt_stat rpcStat /* status from call */
  147.     );
  148. LOCAL STATUS rpcSvcTableInstall (void); /* install initial service table */
  149. LOCAL STATUS rpcSvcAdd /* add new key in exchange svc table */
  150.     (
  151.     UINT32 svcNum, /* service number */
  152.     xdrproc_t xdrIn, /* XDR input procedure */
  153.     xdrproc_t xdrOut /* XDR output procedure */
  154.     );
  155. LOCAL char * wtxRpcKeyFromRpcKeySplitGet /* get rpc key from structure */
  156.     (
  157.     WTX_RPC_SPLIT_KEY * pSplitKey /* splitted key to create key from    */
  158.     );
  159. LOCAL int wtxRpcKeyIPListSizeGet /* get the number of IP adapters      */
  160.     (
  161.     WTX_RPC_SPLIT_KEY * pSplitKey /* splitted RPC key desc              */
  162.     );
  163. /******************************************************************************
  164. *
  165. * wtxRpcSvcUnregister - perform svc_unregister using RPC key string
  166. *
  167. * This routine will unregister the specified RPC service with svc_unregister.
  168. * This routine will not destroy the service.
  169. *
  170. * RETURNS: WTX_OK, or WTX_ERROR if invalid key.
  171. */
  172. STATUS wtxRpcSvcUnregister
  173.     (
  174.     const char * rpcKey /* service key for service to unregister */
  175.     )
  176.     {
  177.     WTX_RPC_SPLIT_KEY splitKey;
  178.     if (wtxRpcKeySplit (rpcKey, &splitKey) != WTX_OK) /* split the key */
  179. return (WTX_ERROR);
  180.     svc_unregister (splitKey.progNum, splitKey.version);
  181.     wtxRpcKeySplitFree (&splitKey);
  182.     return (WTX_OK);
  183.     }
  184. /******************************************************************************
  185. *
  186. * wtxRpcKey - construct an RPC key string given RPC parameters.
  187. *
  188. * An RPC key string is built from the given progNum, version, and protocol
  189. * code.  The format of the string is
  190. *     rpc/<hostname>/<ip-addr>/<progNum>/<version>|<tcp|udp>/<port#>
  191. *
  192. * The hostname is found from the OS.
  193. *
  194. * RETURNS:
  195. * The constructed RPC key string, or NULL if the input data does not represent
  196. * a valid RPC server address or memory for the string could not be allocated.
  197. * The storage for the string should be freed with free() when it is no longer
  198. * needed.
  199. */
  200. char *wtxRpcKey
  201.     (
  202.     UINT32 progNum, /* rpc prog number, or NULL TBA */
  203.     UINT32 version, /* rpc version number */
  204.     UINT32 protocol, /* IPPROTO_TCP or IPPROTO_UDP */
  205.     void (* dispatch)  /* rpc dispatch routine */
  206. (struct svc_req *, SVCXPRT *),
  207.     BOOL register2pmap, /* Do we register to the local portmapper ? */
  208.     SVCXPRT ** ppNewXprt /* where to return transport */
  209.     )
  210.     {
  211. #if (!defined SUN4_SOLARIS2)
  212.     struct in_addr ina; /* inet address               */
  213. #endif /* ! SUN4_SOLARIS2 */
  214.     SVCXPRT * newXprt = NULL; /* transport we make          */
  215.     UINT32  rpcProgNum; /* hunted rpc program num     */
  216.     UINT32 svc_protocol; /* protocol sent to the       */
  217. /* svc_register ()            */
  218.     char *  ipAddrStr = NULL; /* string IP addr (a.b.c.d)   */
  219.     char * newKey = NULL; /* final key (malloc'd)       */
  220.     char hostName [MAXHOSTNAMELEN]; /* our host name              */
  221.     char buf [256]; /* accumulates key string     */
  222.     int newKeyLen = 0; /* new key string length      */
  223. #ifdef HOST
  224.     BOOL firstAddress = TRUE; /* first inet address ?       */
  225.     int inetLen = 0; /* iet address string length  */
  226.     #ifdef WIN32
  227.     struct hostent * pHostEnt; /* contains our IP addr       */
  228.     char ** addrList = NULL; /* address list               */
  229.     char * inetAddr = NULL; /* address from inet_ntoa()   */
  230.     #else
  231.     struct sockaddr_in addr; /* socket address definition  */
  232.     struct ifconf ifc; /* if config result           */
  233.     struct ifreq ifReq; /* current if config request  */
  234.     struct ifreq * ifr = NULL; /* if config request result   */
  235.     char ifBuf [BUFSIZ]; /* if config container        */
  236.     char ipAddr [16]; /* current IP string          */
  237.     int addrLen = 0; /* current address length     */
  238.     int len = 0; /* adress counter for loop    */
  239.     int s = 0; /* connection socket          */
  240.     #endif /* WIN32 */
  241. #endif /* HOST */
  242.     /* sanity check progNum >= 0, version > 0, and IPPROTO_TCP or IPPROTO_UDP */
  243.     if (((protocol != IPPROTO_TCP) && (protocol != IPPROTO_UDP)) ||
  244. ((progNum == 0) && (dispatch == NULL)))
  245. goto error1;
  246.     if (progNum == 0) /* hunt for prog num */
  247. {
  248. if (protocol == IPPROTO_TCP)
  249.     newXprt = svctcp_create (RPC_ANYSOCK, 0, 0);
  250. else
  251.     newXprt = svcudp_create (RPC_ANYSOCK);
  252. if (! newXprt) /* service kaput! */
  253.     goto error1;
  254. /*
  255.  * In order to limit the number of times a Target Server can
  256.  * get the RPC program number of a just killed (with kill -9)
  257.  * Target Server we introduce a little bit of random here (SPR# 5196).
  258.  */
  259. #if defined(WIN32) || !defined(HOST)
  260. rpcProgNum = WTX_SVC_BASE;
  261. #else /* WIN32 */
  262. rpcProgNum = WTX_SVC_BASE + ((int) getpid () & 0xff);
  263. #endif /* WIN32 */
  264. /*
  265.  * If we don't want to register ourself to the local portmapper, set the
  266.  * protocol to 0 before calling svc_register ().
  267.  */
  268. svc_protocol = register2pmap?protocol:0;
  269. while (!svc_register (newXprt, ++rpcProgNum, version, dispatch,
  270.       svc_protocol))
  271.     if (rpcProgNum >= WTX_SVC_BASE + WTX_MAX_SERVICE_CNT)
  272. goto error1;
  273. if (ppNewXprt) /* return transport? */
  274.     *ppNewXprt = newXprt;
  275. progNum = rpcProgNum; /* store prog num */
  276. }
  277.     /* Key format: "rpc/host/ip/port/prog/version/{tcp,udp}" */
  278.     gethostname (hostName, sizeof (hostName)); /* where are we? */
  279. #ifdef HOST
  280.     #ifdef WIN32
  281.     if ((pHostEnt = gethostbyname (hostName))) /* know our IP addr? */
  282. {
  283. /* get the size of the cumulative adapters string */
  284. for (addrList = pHostEnt->h_addr_list ; *addrList != NULL ; addrList ++)
  285.     {
  286.     memcpy (&ina.s_addr, *addrList, sizeof (ina.s_addr));
  287.     if ( (inetAddr = inet_ntoa (ina)) != NULL)
  288. inetLen += strlen (inetAddr) + 1;
  289.     }
  290. /* allocate memory for the IP addresses string */
  291. if ( (ipAddrStr = (char *) calloc (inetLen, sizeof (char))) == NULL)
  292.     goto error1;
  293. /* now concat all the IP addresses in one string separeted with ',' */
  294. firstAddress = TRUE;
  295. for (addrList = pHostEnt->h_addr_list ; *addrList != NULL ; addrList ++)
  296.     {
  297.     memcpy (&ina.s_addr, *addrList, sizeof (ina.s_addr));
  298.     if (firstAddress)
  299. {
  300. strcpy (ipAddrStr, inet_ntoa (ina));
  301. firstAddress = FALSE;
  302. }
  303.     else
  304.         {
  305. sprintf (ipAddrStr, "%s,%s", ipAddrStr, inet_ntoa (ina));
  306. }
  307.     }
  308. }
  309.     else
  310. if ( (ipAddrStr = strdup ("")) == NULL)
  311.     goto error1;
  312.     #else /* WIN32 */
  313.     /* init some variables */
  314.     memset (&addr, 0, sizeof (struct sockaddr_in));
  315.     memset (ifBuf, 0, sizeof (ifBuf));
  316.     memset (&ifc, 0, sizeof (struct ifconf));
  317.     memset (&ifReq, 0, sizeof (struct ifreq));
  318.     /*
  319.      * On UNIX hosts, the gethostbyname() routine may not return all the
  320.      * available IP addresses for the local host. We use a part of the
  321.      * RPC 4.0 get_myaddress.c code to retrieve the list of all IPs registered
  322.      * for the local host
  323.      */
  324.     if ( (s = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
  325. goto error1;
  326.     ifc.ifc_len = sizeof (ifBuf);
  327.     ifc.ifc_buf = ifBuf;
  328.     /* get the if config */
  329.     if (ioctl (s, SIOCGIFCONF, (char *)&ifc) < 0)
  330. goto error2;
  331.     ifr = ifc.ifc_req;
  332.     /* get the list of all the IP addresses */
  333.     for (len = ifc.ifc_len; len; len -= sizeof (ifReq))
  334. {
  335. /* first take to get the length of the ip addr list length */
  336. ifReq = *ifr;
  337. if (ioctl (s, SIOCGIFFLAGS, (char *)&ifReq) < 0)
  338.     goto error2;
  339. if ( (ifReq.ifr_flags & IFF_UP) &&
  340.      (ifr->ifr_addr.sa_family == AF_INET))
  341.     {
  342.     memcpy (&addr, &ifr->ifr_addr, sizeof (struct sockaddr_in));
  343. #ifdef PARISC_HPUX10
  344.     strcpy (ipAddr, inet_ntoa (addr.sin_addr));
  345. #else
  346.     sprintf (ipAddr, "%i.%i.%i.%i", addr.sin_addr.S_un.S_un_b.s_b1,
  347.     addr.sin_addr.S_un.S_un_b.s_b2,
  348.     addr.sin_addr.S_un.S_un_b.s_b3,
  349.     addr.sin_addr.S_un.S_un_b.s_b4);
  350. #endif /* PARISC_HPUX10 */
  351.     addrLen = strlen (ipAddr);
  352.     if ( (addrLen >= 4) && (strncmp (ipAddr, "127.", 4) == 0))
  353. {
  354. /* this is the local host address 127.0.0.1, don't add it */
  355. }
  356.     else
  357. {
  358. inetLen += addrLen + 1;
  359. }
  360.     }
  361. ifr++;
  362. }
  363.     close (s);
  364.     /* do that again */
  365.     if ( (s = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
  366. goto error1;
  367.     ifc.ifc_len = sizeof (ifBuf);
  368.     ifc.ifc_buf = ifBuf;
  369.     /* get the if config */
  370.     if (ioctl (s, SIOCGIFCONF, (char *)&ifc) < 0)
  371. goto error2;
  372.     ifr = ifc.ifc_req;
  373.     /* get the list of all the IP addresses */
  374.     /* allocate the string for the IP addresses list */
  375.     if ( (ipAddrStr = (char *) calloc (inetLen, sizeof (char))) == NULL)
  376. goto error2;
  377.     for (len = ifc.ifc_len; len; len -= sizeof (ifReq))
  378. {
  379. /* first take to get the length of the ip addr list length */
  380. ifReq = *ifr;
  381. if (ioctl (s, SIOCGIFFLAGS, (char *)&ifReq) < 0)
  382.     goto error2;
  383. if ( (ifReq.ifr_flags & IFF_UP) &&
  384.      (ifr->ifr_addr.sa_family == AF_INET))
  385.     {
  386.     memcpy (&addr, &ifr->ifr_addr, sizeof (struct sockaddr_in));
  387. #ifdef PARISC_HPUX10
  388.     strcpy (ipAddr, inet_ntoa (addr.sin_addr));
  389. #else
  390.     sprintf (ipAddr, "%i.%i.%i.%i", addr.sin_addr.S_un.S_un_b.s_b1,
  391.     addr.sin_addr.S_un.S_un_b.s_b2,
  392.     addr.sin_addr.S_un.S_un_b.s_b3,
  393.     addr.sin_addr.S_un.S_un_b.s_b4);
  394. #endif /* PARISC_HPUX10 */
  395.     addrLen = strlen (ipAddr);
  396.     if (firstAddress)
  397. {
  398. if ( (addrLen >= 4) && (strncmp (ipAddr, "127.", 4) == 0))
  399.     {
  400.     /* this is the local host address 127.0.01, do not add it */
  401.     }
  402. else
  403.     {
  404.     strcpy (ipAddrStr, ipAddr);
  405.     firstAddress = FALSE;
  406.     }
  407. }
  408.     else
  409.         {
  410. addrLen = strlen (ipAddr);
  411. if ( (addrLen >= 4) && (strncmp (ipAddr, "127.", 4) == 0))
  412.     {
  413.     /* this is the local host address 127.0.0.1, don't add it */
  414.     }
  415. else
  416.     {
  417.     sprintf (ipAddrStr, "%s,%s", ipAddrStr, ipAddr);
  418.     }
  419. }
  420.     }
  421. ifr++;
  422. }
  423.      #endif /* WIN32 */
  424. #else /* HOST */
  425.     ina.s_addr = hostGetByName (hostName);
  426.     strcpy (ipAddrStr, inet_ntoa (ina));
  427. #endif /* HOST */
  428.     /* calculate the new key length */
  429.     newKeyLen = strlen (hostName) + strlen (ipAddrStr) + 10;
  430.     sprintf (buf, "%d", progNum);
  431.     newKeyLen += strlen (buf) + 1;
  432.     sprintf (buf, "%d", version);
  433.     newKeyLen += strlen (buf) + 1;
  434.     /* If we cannot get the port used, don't write it. */
  435.     if(ppNewXprt == NULL)
  436. {
  437. /* allocate room for the new key string */
  438. if ( (newKey = (char *) calloc (newKeyLen + 1, sizeof (char))) == NULL)
  439.     goto error2;
  440. sprintf (newKey, "rpc/%s/%s/%d/%d/%s", hostName, ipAddrStr,
  441.  progNum, version, (protocol == IPPROTO_TCP) ? "tcp" : "udp");
  442. }
  443.     else
  444. {
  445. sprintf (buf, "%d", (*ppNewXprt)->xp_port);
  446. newKeyLen += strlen (buf) + 1;
  447. /* allocate room for the new key string */
  448. if ( (newKey = (char *) calloc (newKeyLen + 1, sizeof (char))) == NULL)
  449.     goto error2;
  450. sprintf (newKey, "rpc/%s/%s/%d/%d/%s/%d", hostName, ipAddrStr,
  451.  progNum, version, (protocol == IPPROTO_TCP) ? "tcp" : "udp",
  452.  (*ppNewXprt)->xp_port);
  453. }
  454.     /* free the ip address string now */
  455. error2:
  456.     if (ipAddrStr != NULL)
  457. free (ipAddrStr);
  458. #if (defined HOST) && (!defined WIN32)
  459.     close (s); 
  460. #endif /* ! WIN32 */
  461. error1:
  462.     return (newKey); /* return key */
  463.     }
  464. /*******************************************************************************
  465. *
  466. * wtxRpcKeyIPListUpdate - updates IP address list of the given RPC key
  467. *
  468. * This routine uses the given <rpcKeyStr> RPC key string to update the
  469. * IP address list with the given <ipNum>. It takes the IP address <ipNum> in the
  470. * <rpcKeyStr> (if there are several), and set it first in the IP address list.
  471. *
  472. * This allows to put the given <ipNum> as the first address in the list
  473. * of addresses to use to connect to the target server
  474. *
  475. * If <ipNum> is negative, or if the <rpcKeyStr> is NULL, the routine will exit,
  476. * returning NULL.
  477. *
  478. * RETURNS: a string with updated RPC key, or NULL on error.
  479. *
  480. * ERRORS:
  481. * ibs
  482. * ibe
  483. *
  484. * SEE ALSO: wtxRpcKey(), wtxRpcKeySplit()
  485. */
  486. char * wtxRpcKeyIPListUpdate
  487.     (
  488.     const char * rpcKeyStr, /* rpc Key string to update with IP   */
  489.     int ipNum /* IP address num to set as default   */
  490.     )
  491.     {
  492.     WTX_RPC_SPLIT_KEY splitKey; /* splitted key output struct */
  493.     char * newKey = NULL; /* new updated RPC key string */
  494.     char * tmpIP = NULL; /* temp address IP holder     */
  495.     int nAddr = 0; /* address number in list     */
  496.     /* first of all, check the imput parameters */
  497.     if ((rpcKeyStr == NULL) || (ipNum < 0))
  498. goto error1;
  499.     /* split the key and look for <withIP> in this key */
  500.     memset (&splitKey, 0, sizeof (WTX_RPC_SPLIT_KEY));
  501.     if (wtxRpcKeySplit (rpcKeyStr, &splitKey) != WTX_OK)
  502. goto error1;
  503.     if ( ( (nAddr = wtxRpcKeyIPListSizeGet (&splitKey)) == 0) ||
  504.  (nAddr < ipNum))
  505. goto error2;
  506.     tmpIP = splitKey.ipAddrList [0];
  507.     splitKey.ipAddrList [0] = splitKey.ipAddrList [ipNum];
  508.     splitKey.ipAddrList [ipNum] = tmpIP;
  509.     /* we have an updated split key structure. Build new key string with it */
  510.     newKey = wtxRpcKeyFromRpcKeySplitGet (&splitKey);
  511. error2:
  512.     wtxRpcKeySplitFree (&splitKey);
  513. error1:
  514.     return (newKey);
  515.     }
  516. /*******************************************************************************
  517. *
  518. * wtxRpcKeyIPListSizeGet - get the number of IP addresses of a splitted RPC key
  519. *
  520. * This routine returns the number of IP addresses from a splitted RPC key
  521. * structure, where the WTX_RPC_SPLIT_KEY structure has the following
  522. * description :
  523. *
  524. * EXPAND ../../../include/wtxrpc.h WTX_RPC_SPLIT_KEY
  525. *
  526. * The <ipAddrList> contains the list of several IP adapters for the given
  527. * address
  528. *
  529. * RETURNS: the number of IP adapters or 0 if there was no adapters
  530. *
  531. * ERRROS: N/A
  532. *
  533. * SEE ALSO: wtxRpcKeySplit(), wtxRpcKey()
  534. *
  535. * NOMANUAL
  536. */
  537. LOCAL int wtxRpcKeyIPListSizeGet
  538.     (
  539.     WTX_RPC_SPLIT_KEY * pSplitKey /* splitted RPC key desc              */
  540.     )
  541.     {
  542.     int nIpAddr = 0; /* number of adapters for this IP     */
  543.     if ( (pSplitKey == 0) || (pSplitKey->ipAddrList == NULL))
  544. goto error1;
  545.     while (pSplitKey->ipAddrList [nIpAddr] != NULL)
  546. nIpAddr++;
  547. error1:
  548.     return (nIpAddr);
  549.     }
  550. /*******************************************************************************
  551. *
  552. * wtxRpcKeySplitFree - free the freeable members of an RPC key structure
  553. *
  554. * This routine frees the freeable members of an RPC splitted structure which
  555. * definition is :
  556. *
  557. * EXPAND ../../../include/wtxrpc.h WTX_RPC_SPLIT_KEY
  558. *
  559. * The RPC key structure itself is not freed, and it is up to the user to know
  560. * if he has to free it calling free() or not.
  561. *
  562. * RETURNS: WTX_OK
  563. *
  564. * ERRORS: N/A
  565. *
  566. * SEE ALSO: wtxRpcKeySplit(), wtxRpcKeyIPListUpdate()
  567. */
  568. STATUS wtxRpcKeySplitFree
  569.     (
  570.     WTX_RPC_SPLIT_KEY * pRpcSplitKey /* RPC key to free members of         */
  571.     )
  572.     {
  573.     int addrNum = 0; /* address number in address list     */
  574.     /* first of all, check the input parameters */
  575.     if ( (pRpcSplitKey == NULL) || (pRpcSplitKey->ipAddrList == NULL))
  576. goto error1;
  577.     /* free all the IP addressed from the IP address list */
  578.     while (pRpcSplitKey->ipAddrList [addrNum] != NULL)
  579. {
  580. free (pRpcSplitKey->ipAddrList [addrNum]);
  581. addrNum ++;
  582. }
  583.     free (pRpcSplitKey->ipAddrList);
  584. error1:
  585.     return (WTX_OK);
  586.     }
  587. /******************************************************************************
  588. *
  589. * wtxRpcKeySplit - split an RPC key string into its component parts
  590. *
  591. * The given RPC key string is decoded and the various fields are placed
  592. * into the WTX_RPC_SPLIT_KEY structure provided (by reference).
  593. *
  594. * RETURNS:
  595. * WTX_OK, if the key was split successfully and pSplitKey is filled, or
  596. * WTX_ERROR if the key could not be decoded.
  597. */
  598. STATUS wtxRpcKeySplit
  599.     (
  600.     const char * rpcKey, /* rpc key string to split            */
  601.     WTX_RPC_SPLIT_KEY * pSplitKey /* splitted key output structure      */
  602.     )
  603.     {
  604.     STATUS status = WTX_ERROR; /* routine returned status            */
  605.     char * ipAddrList = NULL; /* list of IP addressed for key       */
  606.     char * keyStart = NULL; /* key start in string                */
  607.     char * ptr = NULL; /* address list cursor                */
  608.     char * curIPAddr = NULL; /* current IP address string          */
  609.     char  progNum[10]; /* program number in string format    */
  610.     char version[10]; /* transport version in string format */
  611.     char protocol[10]; /* tcp or udp                         */
  612.     char portNum[10] = "     0"; /* port number in string format       */
  613.     char keyPat[] = "rpc/%[^/]/%[.,0-9a-fA-F]/%[0-9a-fA-F]/%[0-9a-fA-F]/%[tcpudp]/%[0-9a-fA-F]";
  614.     int nPatternsToMatch = 6; /* number of patterns to match        */
  615.     int nMatchedPatterns; /* number of matched patterns         */
  616.     int nAddr = 1; /* number of addresses in key         */
  617.     /* check arguments */
  618.     if ( (rpcKey == NULL) || (pSplitKey == NULL))
  619. goto error1;
  620.     /*
  621.      * allocate memory for the IP adresses list, default it to the length of the
  622.      * RPC key ... the list of IP addresses should not be longer
  623.      */
  624.     if ( (ipAddrList = (char *) calloc (strlen (rpcKey) + 1, sizeof (char)))
  625.  == NULL)
  626. goto error1;
  627.     /* type/host/ipaddr/prognum/vers/protocol/portnum */
  628.     memset (pSplitKey, 0, sizeof (*pSplitKey));
  629.     nMatchedPatterns = sscanf (rpcKey, keyPat, pSplitKey->host,
  630.        ipAddrList, progNum,
  631.        version, protocol, portNum);
  632.     /*
  633.      * The port number may not be present in the key. Lets' examine if we got
  634.      * all the elements or not.
  635.      */
  636.     if (nMatchedPatterns == nPatternsToMatch)
  637. {
  638.      pSplitKey->port = (unsigned short) atoi (portNum);
  639. }
  640.     else
  641. {
  642. if (nMatchedPatterns == (nPatternsToMatch-1))
  643.     { /* port number not present. Use the portmapper */
  644.     pSplitKey->port = 0; /* use portmapper */
  645.     }
  646. else /* something wrong in the key! */
  647.     goto error2;
  648. }
  649.     pSplitKey->progNum = atoi (progNum);
  650.     pSplitKey->version = atoi (version);
  651.     if (! strcmp (protocol, "udp"))
  652. pSplitKey->protocol = IPPROTO_UDP;
  653.     else if (! strcmp (protocol, "tcp"))
  654. pSplitKey->protocol = IPPROTO_TCP;
  655.     else
  656. goto error2;
  657.     /* allocate and store the list of IP addresses */
  658.     ptr = ipAddrList;
  659.     nAddr = 1;
  660.     while ( (ptr != NULL) && (*ptr != ''))
  661. {
  662. /* count the number of ',' in the address list */
  663. if ( (*ptr) == ',')
  664.     nAddr++;
  665. ptr++;
  666. }
  667.     /* allocate <nAddr> + 1 strings */
  668.     if ( (pSplitKey->ipAddrList = (char **) calloc (nAddr + 1, sizeof (char *)))
  669.  == NULL)
  670. goto error2;
  671.     keyStart = ipAddrList;
  672.     ptr = ipAddrList;
  673.     nAddr = 0;
  674.     while ((ptr != NULL) && (*ptr != ''))
  675. {
  676. if ( (*ptr) == ',')
  677.     {
  678.     /* there is an IP address list separator, copy this address */
  679.     if ( (curIPAddr = (char *) calloc ( (int) (ptr - keyStart) + 1,
  680. sizeof (char))) == NULL)
  681. goto error3;
  682.     strncpy (curIPAddr, keyStart, (int) (ptr - keyStart));
  683.     pSplitKey->ipAddrList [nAddr] = curIPAddr;
  684.     nAddr ++;
  685.     keyStart = ptr + 1;
  686.     }
  687. ptr ++;
  688. }
  689.     /* we need to also copy the last address form the key */
  690.     if ( (pSplitKey->ipAddrList [nAddr] = (char *)
  691.   calloc ( (int) (ptr - keyStart) + 1, sizeof (char))) == NULL)
  692. goto error3;
  693.     strcpy (pSplitKey->ipAddrList [nAddr], keyStart);
  694.     status = WTX_OK;
  695. error3:
  696.     if (status != WTX_OK)
  697. wtxRpcKeySplitFree (pSplitKey);
  698. error2:
  699.     if (ipAddrList != NULL)
  700. free (ipAddrList);
  701. error1:
  702.     return (status);
  703.     }
  704. /*******************************************************************************
  705. *
  706. * wtxRpcKeyFromRpcKeySplitGet - get an RPC key from a splitted RPC key structure
  707. *
  708. * This routines takes the input <pSplitKey> RPC splitted key structure, to
  709. * build an RPC key string.
  710. *
  711. * RETURNS: The RPC key string or NULL on error
  712. *
  713. * ERRORS: N/A
  714. *
  715. * SEE ALSO: wtxRpcKey(), wtxRpcKeySplit(), wtxRpcKeyIPListUpdate()
  716. * wtxRpcKeySplitFree()
  717. *
  718. * NOMANUAL
  719. */
  720. LOCAL char * wtxRpcKeyFromRpcKeySplitGet
  721.     (
  722.     WTX_RPC_SPLIT_KEY * pSplitKey /* splitted key to create key from    */
  723.     )
  724.     {
  725.     char * ipList = NULL; /* IP address list, ',' separated     */
  726.     char * rpcKey = NULL; /* extracted RPC ey string            */
  727.     char buf [256]; /* formatting buffer                  */
  728.     int addrNum = 0; /* address number in list             */
  729.     int keyLen = 0; /* RPC key string length              */
  730.     int ipListLen = 0; /* IP addresses list length           */
  731.     /* first of all, check the routines' arguments */
  732.     if ( (pSplitKey == NULL) || (pSplitKey->host == NULL) ||
  733.  (pSplitKey->ipAddrList == NULL))
  734. goto error1;
  735.     /* calculate the RPC ey string length */
  736.     memset (&buf, 0, 256);
  737.     keyLen += strlen (pSplitKey->host) + 1;
  738.     sprintf (buf, "%d", pSplitKey->progNum);
  739.     keyLen += strlen (buf) + 1;
  740.     sprintf (buf, "%d", pSplitKey->version);
  741.     keyLen += strlen (buf) + 1;
  742.     /* add the rpc/ + the (udp)|(rpc)/? */
  743.     keyLen += 7;
  744.     /* allocate and store the list of IP addresses */
  745.     addrNum = 0;
  746.     while (pSplitKey->ipAddrList [addrNum] != NULL)
  747. {
  748. ipListLen += strlen (pSplitKey->ipAddrList [addrNum]) + 1;
  749. addrNum ++;
  750. }
  751.     keyLen += ipListLen;
  752.     /* we have the key cumulated IP list length, allocate the string for it */
  753.     if ( (ipList = (char *) calloc (ipListLen, sizeof (char))) == NULL)
  754. goto error1;
  755.     addrNum = 0;
  756.     while (pSplitKey->ipAddrList [addrNum] != NULL)
  757. {
  758. if (addrNum == 0)
  759.     strcpy (ipList, pSplitKey->ipAddrList [addrNum]);
  760. else
  761.     sprintf (ipList, "%s,%s", ipList, pSplitKey->ipAddrList [addrNum]);
  762. addrNum ++;
  763. }
  764.     if (pSplitKey->port == 0)
  765. {
  766. /* allocate room for the new key string */
  767. if ( (rpcKey = (char *) calloc (keyLen + 1, sizeof (char))) == NULL)
  768.     goto error2;
  769. sprintf (rpcKey, "rpc/%s/%s/%d/%d/%s", pSplitKey->host,
  770.  ipList, pSplitKey->progNum, pSplitKey->version,
  771.  (pSplitKey->protocol == IPPROTO_TCP) ? "tcp" : "udp");
  772. }
  773.     else
  774. {
  775. sprintf (buf, "%u", pSplitKey->port);
  776. keyLen += strlen (buf) + 1;
  777. /* allocate room for the new key string */
  778. if ( (rpcKey = (char *) calloc (keyLen + 1, sizeof (char))) == NULL)
  779.     goto error2;
  780. sprintf (rpcKey, "rpc/%s/%s/%d/%d/%s/%u", pSplitKey->host,
  781.  ipList, pSplitKey->progNum, pSplitKey->version,
  782.  (pSplitKey->protocol == IPPROTO_TCP) ? "tcp" : "udp",
  783.  pSplitKey->port);
  784. }
  785. error2:
  786.     if (ipList != NULL)
  787. free (ipList);
  788. error1:
  789.     return (rpcKey);
  790.     }
  791. /*******************************************************************************
  792. *
  793. * wtxRpcExchangeCreate - create a new exchange client using the RPC transport
  794. *
  795. * This routine takes a wpwr key string and creates a new exchange client
  796. * RETURNS: WTX_OK, or WTX_ERROR
  797. *
  798. * NOMANUAL
  799. */
  800. STATUS wtxRpcExchangeCreate
  801.     (
  802.     WTX_XID xid, /* Exchange handle                    */
  803.     const char * key, /* Key for server to connect to       */
  804.     BOOL usePMap /* use port mapper to connect ?       */
  805.     )
  806.     {
  807.     struct sockaddr_in addr; /* socket address             */
  808.     WTX_RPC_SPLIT_KEY split; /* split key                  */
  809.     CLIENT * pClient = NULL; /* rpc client handle          */
  810.     int rpcSock = 0; /* rpc socket                 */
  811. #ifdef HOST
  812.     struct hostent * pHostEnt = NULL; /* host entry                 */
  813.     char *              registryHost = NULL; /* registry host name         */
  814. #endif /* HOST */
  815.     if (key != NULL)
  816. {
  817. if (wtxRpcKeySplit (key, &split) != WTX_OK)
  818.     WTX_EXCHANGE_RETURN (xid, WTX_ERR_EXCHANGE_BAD_KEY, WTX_ERROR);
  819. }
  820.     else 
  821. {
  822. /*
  823.  * NULL key => contact the registry service so fill in the split key
  824.  * with the Tornado registry particulars 
  825.  */
  826. #ifdef HOST
  827. if ((registryHost = wpwrGetEnv ("WIND_REGISTRY")) == NULL)
  828.     registryHost = "127.0.0.1"; /* its probably local */
  829. strncpy (split.host, registryHost, sizeof (split.host));
  830. split.host [sizeof (split.host) - 1] = '';
  831. #endif
  832. if (usePMap)
  833.     split.port = 0;
  834. else
  835.     split.port = REGISTRY_PORT;
  836. /*
  837.  * Set ipAddrList to NULL.  That will cause the address lookup logic
  838.  * below to use gethostbyname for us.
  839.  */
  840. split.ipAddrList = NULL;
  841. split.progNum = WTX_SVC_BASE;
  842. split.version = 1;
  843. split.protocol = IPPROTO_TCP;
  844. }
  845.     /* 
  846.      * Get the internet address for the given host.  Parse hostname
  847.      * as host name or alternatively in the `xx.xx.xx.xx' notation. 
  848.      */
  849.     memset ((void *) &addr, 0, sizeof (addr));
  850.     /*
  851.      * Get the IP address. First use the dotted decimal part of the
  852.      * split key if that is comprehensible.  Otherwise use
  853.      * gethostbyname to look up the address.  If that fails try to
  854.      * parse the hostname itself as a dotted decimal.  Otherwise
  855.      * complain. 
  856.      */
  857.     if ( (split.ipAddrList != NULL) &&
  858.  (int) (addr.sin_addr.s_addr = inet_addr (split.ipAddrList [0])) != -1)
  859. ;
  860. #ifdef HOST
  861. #   ifdef WIN32
  862.     else if ((addr.sin_addr.s_addr = inet_addr (split.host)) != INADDR_NONE)
  863. ;
  864.     else if ((pHostEnt = (struct hostent *)gethostbyname (split.host)) != NULL)
  865. addr.sin_addr.s_addr = * ((u_long *) pHostEnt->h_addr_list[0]);
  866.     else
  867. {
  868. wtxRpcKeySplitFree (&split);
  869. WTX_EXCHANGE_RETURN (xid, WTX_ERR_EXCHANGE_NO_SERVER, WTX_ERROR);
  870. }
  871. #   else /* WIN32 */
  872.     else if ((pHostEnt = (struct hostent *)gethostbyname (split.host)) != NULL)
  873. addr.sin_addr.s_addr = * ((u_long *) pHostEnt->h_addr_list[0]);
  874.     else if ( (int) (addr.sin_addr.s_addr = inet_addr (split.host)) == -1)
  875. {
  876. wtxRpcKeySplitFree (&split);
  877. WTX_EXCHANGE_RETURN (xid, WTX_ERR_EXCHANGE_NO_SERVER, WTX_ERROR);
  878. }
  879. #   endif /* WIN32 */
  880. #else
  881.     else
  882. addr.sin_addr.s_addr = syncRegistry;
  883. #endif /* HOST */
  884.     addr.sin_family = AF_INET;
  885.     addr.sin_port = htons(split.port); /* given by registry/portmapper */
  886.     rpcSock = RPC_ANYSOCK; /* any old socket */
  887.     if (split.protocol == IPPROTO_TCP)
  888. pClient = clnttcp_create (&addr, split.progNum, split.version,
  889.   &rpcSock, 0, 0);
  890.     else
  891. pClient = clntudp_create (&addr, split.progNum, split.version,
  892.   rpcDefaultUdpTimeout, &rpcSock);
  893.     if (pClient == NULL) /* transport failed? */
  894. {
  895. wtxRpcKeySplitFree (&split);
  896. WTX_EXCHANGE_RETURN (xid, WTX_ERR_EXCHANGE_NO_SERVER, WTX_ERROR);
  897. }
  898.     /* Set up the authorization mechanism */
  899. #ifdef HOST
  900. #   ifndef WIN32
  901.     pClient->cl_auth = authunix_create_default();
  902. #   else
  903.     pClient->cl_auth = authunix_create("WIN32", wpwrGetUid(), NULL, NULL, NULL);
  904. #   endif /* WIN32 */
  905. #else
  906.     /* authentication */
  907.     pClient->cl_auth = authunix_create ("", 0, 0, 0, NULL);
  908.     /* set the real value computed on host and stored on target */
  909.     pClient->cl_auth->ah_cred.oa_flavor = authCred.oa_flavor;
  910.     pClient->cl_auth->ah_cred.oa_base = authCred.oa_base;
  911.     pClient->cl_auth->ah_cred.oa_length = authCred.oa_length;
  912. #endif  /* HOST */
  913.     xid->transport = pClient;
  914. #ifndef HOST
  915. #if (CPU==SIMHPPA)
  916.     /*
  917.      *  Set RPC receive buffer for HPSIM when using SLIP.  This is needed for
  918.      *  target symbol synchronization, since the target server can send
  919.      *  messages larger than the target MTU when not communicating thru WDB.
  920.      */
  921.     {
  922.     WDB_AGENT_INFO agentInfo;
  923.     int blen;
  924.     wdbInfoGet (&agentInfo);
  925.     blen = agentInfo.mtu;
  926.     if ( blen < 1000 ) /* Must be using SLIP */
  927. setsockopt (rpcSock, SOL_SOCKET, SO_RCVBUF, 
  928.     (void *) &blen, sizeof (blen));
  929.     }
  930. #endif /* CPU=SIMHPPA */
  931. #endif /* ! HOST */
  932.     wtxRpcKeySplitFree (&split);
  933.     return WTX_OK;
  934.     }
  935. /*******************************************************************************
  936. *
  937. * wtxRpcExchangeControl - perform a miscellaneous exchange control function.
  938. *
  939. * This routine performs a miscellaneous control function on the exchange 
  940. * handle <xid>. 
  941. *
  942. * RETURNS: WTX_OK, or WTX_ERROR.
  943. *
  944. * ERRORS: WTX_ERR_EXCHANGE_INVALID_HANDLE, WTX_ERR_EXCHANGE_INVALID_ARG
  945. *
  946. * NOMANUAL
  947. */
  948. STATUS wtxRpcExchangeControl
  949.     (
  950.     WTX_XID xid, /* Exchange handle */
  951.     UINT32 request, /* Exchange control request number */
  952.     void * arg /* Pointer to request argument */
  953.     )
  954.     {
  955.     CLIENT * pClient;
  956.     pClient = (CLIENT *) xid->transport;
  957.     switch (request) 
  958. {
  959. case WTX_EXCHANGE_CTL_TIMEOUT_SET:
  960.     xid->timeout = *(UINT32 *) arg;
  961.     break;
  962.     
  963. case WTX_EXCHANGE_CTL_TIMEOUT_GET:
  964.     *(UINT32 *) arg = xid->timeout;
  965.     break;
  966.     
  967. default:
  968.     WTX_EXCHANGE_RETURN (xid, WTX_ERR_EXCHANGE_REQUEST_UNSUPPORTED, 
  969.  WTX_ERROR);
  970. }
  971.     return WTX_OK;
  972.     }
  973. /*******************************************************************************
  974. *
  975. * wxRpcDelete - delete the exchange handle and any transport connection.
  976. *
  977. * This routine deletes the exchange mechanism specified by the exchange 
  978. * handle <xid>. <xid> should not be used again in any further exchange
  979. * calls as the underlying transport mechanism is closed also.
  980. *
  981. * RETURNS: WTX_OK, or WTX_ERROR
  982. *
  983. * NOMANUAL
  984. */
  985. STATUS wtxRpcExchangeDelete
  986.     (
  987.     WTX_XID xid /* Exchange handle */
  988.     )
  989.     {
  990.     CLIENT *pClient;
  991.     pClient = (CLIENT *) xid->transport;
  992.     if (pClient == NULL)
  993. /* Nothing to do */
  994. return WTX_OK;
  995.     if (pClient->cl_auth != NULL)
  996. auth_destroy (pClient->cl_auth);
  997.     clnt_destroy (pClient);
  998.     xid->transport = NULL;
  999.     return (WTX_OK);
  1000.     }
  1001. /*******************************************************************************
  1002. *
  1003. * wtxRpcExchangeFree - free a exchange call result message
  1004. *
  1005. * This routine frees the memory allocated internally to the result message
  1006. * <pMsg> used in making the exchange service call <svcNum>.
  1007. *
  1008. * RETURNS: WTX_OK, or WTX_ERROR
  1009. *
  1010. * NOMANUAL
  1011. */
  1012. WTX_ERROR_T wtxRpcExchangeFree
  1013.     (
  1014.     WTX_REQUEST svcNum, /* number of server service result to free */
  1015.     void * pMsg /* pointer to result message to free */
  1016.     )
  1017.     {
  1018.     if (svcNum > rpcSvcTableSize || (*rpcSvcTable)[svcNum] == NULL)
  1019. return (WTX_ERR_EXCHANGE_REQUEST_UNSUPPORTED);
  1020.     (*rpcSvcTable)[svcNum]->xdrOut (&svrXdrs, pMsg);
  1021.  
  1022.     return (WTX_ERR_NONE);
  1023.     }
  1024. /*******************************************************************************
  1025. *
  1026. * wtxRpcExchange - do a WTX API call via the exchange mechanism
  1027. *
  1028. * This routine performs the exchange service call <svcNum> with in parameters
  1029. * pointed to by <pIn> and result (out) parameters pointed to by <pOut>. The
  1030. * status of the call is represented by the error code returned.  The result
  1031. * <pOut> may have memory allocated to it internally which can be freed by
  1032. * using wtxRpcExchangeFree().
  1033. *
  1034. * RETURNS: WTX_OK, or WTX_ERROR
  1035. *
  1036. * NOMANUAL
  1037. */
  1038. STATUS wtxRpcExchange
  1039.     (
  1040.     WTX_XID xid, /* exchange handle */
  1041.     WTX_REQUEST svcNum, /* exchange service number */
  1042.     void * pIn, /* exchange service in args */
  1043.     void * pOut /* exchange service out args */
  1044.     )
  1045.     {
  1046.     enum clnt_stat rpcStat; 
  1047.     WTX_ERROR_T wtxStat;
  1048.     WTX_MSG_RESULT * pMsgOut;
  1049.     CLIENT * pClient;
  1050.     RPC_SERVICE * pService;
  1051.     struct timeval timeout;
  1052.     pClient = (CLIENT *) xid->transport;
  1053.     if (pClient == NULL)
  1054. WTX_EXCHANGE_RETURN (xid, WTX_ERR_EXCHANGE_NO_TRANSPORT, WTX_ERROR);
  1055.     /* Make sure the table has been initialized */
  1056.     if (rpcSvcTable == NULL)
  1057. rpcSvcTableInstall ();
  1058.     if (svcNum > rpcSvcTableSize || (*rpcSvcTable)[svcNum] == NULL)
  1059. WTX_EXCHANGE_RETURN (xid, WTX_ERR_EXCHANGE_REQUEST_UNSUPPORTED, 
  1060.      WTX_ERROR);
  1061.     pService = (*rpcSvcTable)[svcNum];
  1062.     /* Construct a timeout struct on the fly for service request */
  1063.     timeout.tv_sec = xid->timeout / 1000;
  1064.     timeout.tv_usec = xid->timeout * 1000 - timeout.tv_sec * 1000000;
  1065.     rpcStat = clnt_call (pClient,
  1066.  svcNum, 
  1067.  pService->xdrIn, pIn,  
  1068.  pService->xdrOut, pOut,  
  1069.  timeout);
  1070.     wtxStat = rpcStatToError (rpcStat);
  1071.     if (wtxStat != WTX_ERR_NONE)
  1072. {
  1073. /* An RPC error occured. Free the result and return */
  1074. clnt_freeres (pClient, pService->xdrOut, pOut);
  1075. /* Handle case of RPC failing so badly we must disconnect */
  1076. if (wtxStat == WTX_ERR_EXCHANGE_TRANSPORT_DISCONNECT)
  1077.     wtxRpcExchangeDelete (xid);
  1078. WTX_EXCHANGE_RETURN (xid, wtxStat, WTX_ERROR);
  1079. }
  1080.     /* Sort cut for NULLPROC that doesn't return a proper WTX message result. */
  1081.     if (svcNum == NULLPROC)
  1082. return WTX_OK;
  1083.     pMsgOut = (WTX_MSG_RESULT *) pOut;
  1084.     if (pMsgOut->wtxCore.errCode != OK)
  1085. {
  1086. UINT32 errCode;
  1087. /* A service specific error occured. Free the result and return */
  1088. errCode = pMsgOut->wtxCore.errCode;
  1089. clnt_freeres (pClient, pService->xdrOut, pOut);
  1090. WTX_EXCHANGE_RETURN (xid, errCode, WTX_ERROR);
  1091. }
  1092.     return WTX_ERR_NONE;
  1093.     }
  1094. /*******************************************************************************
  1095. *
  1096. * rpcStatToError - convert an RPC status to a WTX error code.
  1097. * This routine converts an RPC error status <callStat> to a WTX error code.
  1098. *
  1099. * RETURNS: the WTX error code or WTX_ERR_NONE if no error occured.
  1100. *
  1101. * NOMANUAL
  1102. */
  1103. LOCAL WTX_ERROR_T rpcStatToError
  1104.     (
  1105.     enum clnt_stat rpcStat /* status from call */
  1106.     )
  1107.     {
  1108.     switch (rpcStat) 
  1109. {
  1110. case RPC_SUCCESS:
  1111.     return WTX_ERR_NONE; /* call succeeded */
  1112. case RPC_CANTENCODEARGS: /* can't encode arguments */
  1113. case RPC_CANTDECODERES: /* can't decode results */
  1114. case RPC_CANTDECODEARGS: /* decode arguments error */
  1115. case RPC_SYSTEMERROR: /* generic "other problem" */
  1116. case RPC_UNKNOWNHOST: /* unknown host name */
  1117. case RPC_UNKNOWNPROTO: /* unknown protocol -- 4.0 */
  1118. case RPC_PMAPFAILURE: /* the pmapper failed in its call */
  1119. case RPC_PROGNOTREGISTERED: /* remote program is not registered */
  1120. case RPC_FAILED:
  1121.     return WTX_ERR_EXCHANGE_TRANSPORT_ERROR;
  1122. case RPC_PROCUNAVAIL: /* procedure unavailable */
  1123.     return WTX_ERR_EXCHANGE_REQUEST_UNSUPPORTED;
  1124. case RPC_CANTSEND: /* failure in sending call */
  1125. case RPC_CANTRECV: /* failure in receiving result */
  1126. case RPC_VERSMISMATCH: /* rpc versions not compatible */
  1127. case RPC_AUTHERROR: /* authentication error */
  1128. case RPC_PROGUNAVAIL: /* program not available */
  1129. case RPC_PROGVERSMISMATCH: /* program version mismatched */
  1130.     return WTX_ERR_EXCHANGE_TRANSPORT_DISCONNECT;
  1131. case RPC_TIMEDOUT: /* call timed out */
  1132.     return WTX_ERR_EXCHANGE_TIMEOUT;
  1133. default:
  1134.     return WTX_ERR_EXCHANGE;
  1135. }
  1136.     
  1137.     }
  1138. /*******************************************************************************
  1139. *
  1140. * rpcSvcAdd - add a new service into the exchange service table
  1141. *
  1142. * This routine adds a new service with service number <svcNum> into the
  1143. * exchange service table.  The in and out XDR routines <xdrIn> and <xdrOut>
  1144. * are recorded in the table.
  1145. *
  1146. * RETURNS: OK, or ERROR.
  1147. */
  1148. LOCAL STATUS rpcSvcAdd
  1149.     (
  1150.     UINT32 svcNum,
  1151.     xdrproc_t xdrIn,
  1152.     xdrproc_t xdrOut
  1153.     )
  1154.     {
  1155.     if (svcNum + 1 > rpcSvcTableSize)
  1156. {
  1157. RPC_SERVICE *(*newTable)[];
  1158. /* Current table not big enough */
  1159. newTable = calloc (svcNum + 1, sizeof (RPC_SERVICE *));
  1160. if (newTable == NULL)
  1161.     return ERROR;
  1162. /* Copy and free the old one */
  1163. if (rpcSvcTable != NULL)
  1164.     {
  1165.     memcpy (newTable, rpcSvcTable, 
  1166.     rpcSvcTableSize * sizeof (RPC_SERVICE *));
  1167.     free (rpcSvcTable);
  1168.     }
  1169. rpcSvcTable = newTable;
  1170. rpcSvcTableSize = svcNum + 1;
  1171. }
  1172.     
  1173.     (*rpcSvcTable)[svcNum] = malloc (sizeof (RPC_SERVICE));
  1174.     if  ((*rpcSvcTable)[svcNum] == NULL)
  1175. /* No space for the new service description */
  1176. return ERROR;
  1177.     (*rpcSvcTable)[svcNum]->xdrIn = xdrIn;
  1178.     (*rpcSvcTable)[svcNum]->xdrOut = xdrOut;
  1179.     return OK;
  1180.     }
  1181.     
  1182. /*******************************************************************************
  1183. *
  1184. * rpcSvcTableInstall - install initial table of service definitions
  1185. *
  1186. * This routine sets a the table that defines the XDR conversion functions
  1187. * for each available exchange service. No action is taken if this function
  1188. * is called more than once.
  1189. *
  1190. * RETURNS: OK, or ERROR
  1191. */
  1192. LOCAL STATUS rpcSvcTableInstall (void)
  1193.     {
  1194.     if (rpcSvcTable != NULL)
  1195. /* Already initialized */
  1196. return (OK);
  1197.     /* Add the services to the table of available services */
  1198.     /* store the client XDRs */
  1199.     xdrmem_create (&svrXdrs, svrXdrsMCall, MCALL_MSG_SIZE, XDR_FREE);
  1200.     /* Ping or no-op service */
  1201.     rpcSvcAdd (NULLPROC, xdr_void, xdr_void);
  1202.     /* Registry services */
  1203.     rpcSvcAdd (WTX_INFO_Q_GET, 
  1204.        xdr_WTX_MSG_WTXREGD_PATTERN, xdr_WTX_MSG_SVR_DESC_Q); 
  1205.     rpcSvcAdd (WTX_INFO_GET, xdr_WTX_MSG_PARAM, xdr_WTX_MSG_SVR_DESC); 
  1206.     rpcSvcAdd (WTX_REGISTER, xdr_WTX_MSG_SVR_DESC, xdr_WTX_MSG_SVR_DESC); 
  1207.     rpcSvcAdd (WTX_UNREGISTER, xdr_WTX_MSG_PARAM, xdr_WTX_MSG_RESULT); 
  1208.     /* Target server services */
  1209.     rpcSvcAdd (WTX_TOOL_ATTACH, xdr_WTX_MSG_TOOL_DESC, xdr_WTX_MSG_TOOL_DESC);
  1210.     rpcSvcAdd (WTX_TOOL_DETACH, xdr_WTX_MSG_TOOL_ID, xdr_WTX_MSG_RESULT);
  1211.     rpcSvcAdd (WTX_TS_INFO_GET_V1, xdr_WTX_MSG_TOOL_ID, xdr_WTX_MSG_TS_INFO_V1);
  1212.     rpcSvcAdd (WTX_TS_INFO_GET_V2, xdr_WTX_MSG_TOOL_ID, xdr_WTX_MSG_TS_INFO_V2);
  1213.     rpcSvcAdd (WTX_TS_LOCK, xdr_WTX_MSG_TS_LOCK, xdr_WTX_MSG_RESULT);
  1214.     rpcSvcAdd (WTX_TS_UNLOCK, xdr_WTX_MSG_TS_UNLOCK, xdr_WTX_MSG_RESULT);
  1215.     rpcSvcAdd (WTX_TARGET_RESET, xdr_WTX_MSG_TOOL_ID, xdr_WTX_MSG_RESULT);
  1216.     rpcSvcAdd (WTX_TARGET_ATTACH, xdr_WTX_MSG_TOOL_ID, xdr_WTX_MSG_RESULT);
  1217. #if 0 /* ELP */
  1218.     rpcSvcAdd (WTX_TARGET_PING, xdr_WTX_MSG_TOOL_ID, xdr_WTX_MSG_RESULT);
  1219. #endif
  1220.     rpcSvcAdd (WTX_CONTEXT_CREATE,
  1221.        xdr_WTX_MSG_CONTEXT_DESC, xdr_WTX_MSG_CONTEXT);
  1222.     rpcSvcAdd (WTX_CONTEXT_KILL, xdr_WTX_MSG_CONTEXT, xdr_WTX_MSG_RESULT);
  1223.     rpcSvcAdd (WTX_CONTEXT_SUSPEND, xdr_WTX_MSG_CONTEXT, xdr_WTX_MSG_RESULT);
  1224.     rpcSvcAdd (WTX_CONTEXT_CONT, xdr_WTX_MSG_CONTEXT, xdr_WTX_MSG_RESULT);
  1225.     rpcSvcAdd (WTX_CONTEXT_RESUME, xdr_WTX_MSG_CONTEXT, xdr_WTX_MSG_RESULT);
  1226.     rpcSvcAdd (WTX_CONTEXT_STATUS_GET, xdr_WTX_MSG_CONTEXT, xdr_WTX_MSG_RESULT);
  1227.     rpcSvcAdd (WTX_CONTEXT_STEP,
  1228.        xdr_WTX_MSG_CONTEXT_STEP_DESC, xdr_WTX_MSG_RESULT);
  1229.     rpcSvcAdd (WTX_EVENTPOINT_ADD, xdr_WTX_MSG_EVTPT_DESC, xdr_WTX_MSG_RESULT);
  1230.     rpcSvcAdd (WTX_EVENTPOINT_DELETE, xdr_WTX_MSG_PARAM, xdr_WTX_MSG_RESULT);
  1231.     rpcSvcAdd (WTX_EVENTPOINT_LIST, 
  1232.        xdr_WTX_MSG_TOOL_ID, xdr_WTX_MSG_EVTPT_LIST);
  1233.     rpcSvcAdd (WTX_MEM_CHECKSUM, xdr_WTX_MSG_MEM_SET_DESC, xdr_WTX_MSG_RESULT);
  1234.     rpcSvcAdd (WTX_MEM_DISASSEMBLE, xdr_WTX_MSG_DASM_DESC,
  1235.                xdr_WTX_MSG_DASM_INST_LIST);
  1236.     rpcSvcAdd (WTX_MEM_READ, 
  1237.        xdr_WTX_MSG_MEM_READ_DESC, xdr_WTX_MSG_MEM_COPY_DESC);
  1238.     rpcSvcAdd (WTX_MEM_WRITE, xdr_WTX_MSG_MEM_COPY_DESC, xdr_WTX_MSG_RESULT);
  1239.     rpcSvcAdd (WTX_MEM_SET, xdr_WTX_MSG_MEM_SET_DESC, xdr_WTX_MSG_RESULT);
  1240.     rpcSvcAdd (WTX_MEM_SCAN, xdr_WTX_MSG_MEM_SCAN_DESC, xdr_WTX_MSG_RESULT);
  1241.     rpcSvcAdd (WTX_MEM_MOVE, xdr_WTX_MSG_MEM_MOVE_DESC, xdr_WTX_MSG_RESULT);
  1242.     rpcSvcAdd (WTX_MEM_ALLOC, xdr_WTX_MSG_PARAM, xdr_WTX_MSG_RESULT);
  1243.     rpcSvcAdd (WTX_MEM_REALLOC, xdr_WTX_MSG_MEM_BLOCK_DESC, xdr_WTX_MSG_RESULT);
  1244.     rpcSvcAdd (WTX_MEM_ALIGN, xdr_WTX_MSG_MEM_BLOCK_DESC, xdr_WTX_MSG_RESULT);
  1245.     rpcSvcAdd (WTX_MEM_ADD_TO_POOL,
  1246.        xdr_WTX_MSG_MEM_BLOCK_DESC, xdr_WTX_MSG_RESULT);
  1247.     rpcSvcAdd (WTX_MEM_FREE, xdr_WTX_MSG_PARAM, xdr_WTX_MSG_RESULT);
  1248.     rpcSvcAdd (WTX_MEM_INFO_GET, xdr_WTX_MSG_TOOL_ID, xdr_WTX_MSG_MEM_INFO);
  1249.     rpcSvcAdd (WTX_REGS_GET, xdr_WTX_MSG_REG_READ, xdr_WTX_MSG_MEM_XFER_DESC);
  1250.     rpcSvcAdd (WTX_REGS_SET, xdr_WTX_MSG_REG_WRITE, xdr_WTX_MSG_RESULT);
  1251.     rpcSvcAdd (WTX_OPEN, xdr_WTX_MSG_OPEN_DESC, xdr_WTX_MSG_RESULT);
  1252.     rpcSvcAdd (WTX_VIO_READ, 
  1253.        xdr_WTX_MSG_VIO_COPY_DESC, xdr_WTX_MSG_VIO_COPY_DESC);
  1254.     rpcSvcAdd (WTX_VIO_WRITE, xdr_WTX_MSG_VIO_COPY_DESC, xdr_WTX_MSG_RESULT);
  1255.     rpcSvcAdd (WTX_CLOSE, xdr_WTX_MSG_PARAM, xdr_WTX_MSG_RESULT);
  1256.     rpcSvcAdd (WTX_VIO_CTL, xdr_WTX_MSG_VIO_CTL_DESC, xdr_WTX_MSG_RESULT);
  1257.     rpcSvcAdd (WTX_VIO_FILE_LIST, 
  1258.        xdr_WTX_MSG_TOOL_ID, xdr_WTX_MSG_VIO_FILE_LIST);
  1259.     rpcSvcAdd (WTX_OBJ_MODULE_LOAD, 
  1260.        xdr_WTX_MSG_LD_M_FILE_DESC, xdr_WTX_MSG_LD_M_FILE_DESC);
  1261.     rpcSvcAdd (WTX_OBJ_MODULE_UNLOAD, xdr_WTX_MSG_PARAM, xdr_WTX_MSG_RESULT);
  1262.     rpcSvcAdd (WTX_OBJ_MODULE_LIST, 
  1263.        xdr_WTX_MSG_TOOL_ID, xdr_WTX_MSG_MODULE_LIST);
  1264.     rpcSvcAdd (WTX_OBJ_MODULE_INFO_GET, 
  1265.        xdr_WTX_MSG_MOD_NAME_OR_ID, xdr_WTX_MSG_MODULE_INFO);
  1266.     rpcSvcAdd (WTX_OBJ_MODULE_FIND, 
  1267.        xdr_WTX_MSG_MOD_NAME_OR_ID, xdr_WTX_MSG_MOD_NAME_OR_ID);
  1268.     rpcSvcAdd (WTX_SYM_TBL_INFO_GET, 
  1269.        xdr_WTX_MSG_PARAM, xdr_WTX_MSG_SYM_TBL_INFO);
  1270.     rpcSvcAdd (WTX_SYM_LIST_GET, 
  1271.        xdr_WTX_MSG_SYM_MATCH_DESC, xdr_WTX_MSG_SYM_LIST);
  1272.     rpcSvcAdd (WTX_SYM_FIND, xdr_WTX_MSG_SYMBOL_DESC, xdr_WTX_MSG_SYMBOL_DESC);
  1273.     rpcSvcAdd (WTX_SYM_ADD, xdr_WTX_MSG_SYMBOL_DESC, xdr_WTX_MSG_RESULT);
  1274.     rpcSvcAdd (WTX_SYM_REMOVE, xdr_WTX_MSG_SYMBOL_DESC, xdr_WTX_MSG_RESULT);
  1275.     rpcSvcAdd (WTX_EVENT_GET, xdr_WTX_MSG_TOOL_ID, xdr_WTX_MSG_EVENT_DESC);
  1276.     rpcSvcAdd (WTX_REGISTER_FOR_EVENT, 
  1277.        xdr_WTX_MSG_EVENT_REG_DESC, xdr_WTX_MSG_RESULT);
  1278.     rpcSvcAdd (WTX_EVENT_ADD, xdr_WTX_MSG_EVENT_DESC, xdr_WTX_MSG_RESULT);
  1279.     rpcSvcAdd (WTX_GOPHER_EVAL, xdr_WTX_MSG_PARAM, xdr_WTX_MSG_GOPHER_TAPE);
  1280.     rpcSvcAdd (WTX_FUNC_CALL, xdr_WTX_MSG_CONTEXT_DESC, xdr_WTX_MSG_RESULT);
  1281.     rpcSvcAdd (WTX_DIRECT_CALL, xdr_WTX_MSG_CONTEXT_DESC, xdr_WTX_MSG_RESULT);
  1282.     rpcSvcAdd (WTX_SERVICE_ADD, xdr_WTX_MSG_SERVICE_DESC, xdr_WTX_MSG_RESULT);
  1283.     rpcSvcAdd (WTX_AGENT_MODE_SET, xdr_WTX_MSG_PARAM, xdr_WTX_MSG_RESULT);
  1284.     rpcSvcAdd (WTX_AGENT_MODE_GET, xdr_WTX_MSG_TOOL_ID, xdr_WTX_MSG_RESULT);
  1285.     rpcSvcAdd (WTX_CONSOLE_CREATE, 
  1286.        xdr_WTX_MSG_CONSOLE_DESC, xdr_WTX_MSG_CONSOLE_DESC);
  1287.     rpcSvcAdd (WTX_CONSOLE_KILL, xdr_WTX_MSG_PARAM, xdr_WTX_MSG_RESULT);
  1288.     rpcSvcAdd (WTX_OBJ_KILL, xdr_WTX_MSG_KILL_DESC, xdr_WTX_MSG_RESULT);
  1289.     rpcSvcAdd (WTX_VIO_CHAN_GET, xdr_WTX_MSG_TOOL_ID, xdr_WTX_MSG_RESULT);
  1290.     rpcSvcAdd (WTX_VIO_CHAN_RELEASE, xdr_WTX_MSG_PARAM, xdr_WTX_MSG_RESULT);
  1291.     /* WTX 2: new services */
  1292.     rpcSvcAdd (WTX_UNREGISTER_FOR_EVENT,
  1293.                xdr_WTX_MSG_EVENT_REG_DESC, xdr_WTX_MSG_RESULT);
  1294.     rpcSvcAdd (WTX_CACHE_TEXT_UPDATE,
  1295.                xdr_WTX_MSG_MEM_BLOCK_DESC, xdr_WTX_MSG_RESULT);
  1296.     rpcSvcAdd (WTX_MEM_WIDTH_READ,
  1297.                xdr_WTX_MSG_MEM_WIDTH_READ_DESC, xdr_WTX_MSG_MEM_WIDTH_COPY_DESC);
  1298.     rpcSvcAdd (WTX_MEM_WIDTH_WRITE,
  1299.                xdr_WTX_MSG_MEM_WIDTH_COPY_DESC, xdr_WTX_MSG_RESULT);
  1300.     rpcSvcAdd (WTX_COMMAND_SEND,
  1301.                xdr_WTX_MSG_PARAM, xdr_WTX_MSG_RESULT);
  1302.     rpcSvcAdd (WTX_OBJ_MODULE_CHECKSUM,
  1303.                xdr_WTX_MSG_MOD_NAME_OR_ID, xdr_WTX_MSG_RESULT);
  1304.     rpcSvcAdd (WTX_EVENT_LIST_GET,
  1305.                xdr_WTX_MSG_PARAM, xdr_WTX_MSG_EVENT_LIST);
  1306.     rpcSvcAdd (WTX_OBJ_MODULE_LOAD_2,
  1307.                xdr_WTX_MSG_FILE_LOAD_DESC, xdr_WTX_MSG_LD_M_FILE_DESC);
  1308.     rpcSvcAdd (WTX_EVENTPOINT_ADD_2,
  1309.                xdr_WTX_MSG_EVTPT_DESC_2, xdr_WTX_MSG_RESULT);
  1310.     rpcSvcAdd (WTX_EVENTPOINT_LIST_GET,
  1311.                xdr_WTX_MSG_TOOL_ID, xdr_WTX_MSG_EVTPT_LIST_2);
  1312.     rpcSvcAdd (WTX_OBJ_MODULE_UNLOAD_2, xdr_WTX_MSG_MOD_NAME_OR_ID,
  1313.                xdr_WTX_MSG_RESULT);
  1314.     return (OK);
  1315.     }