home *** CD-ROM | disk | FTP | other *** search
/ Borland Programmer's Resource / Borland_Programmers_Resource_CD_1995.iso / winsock / twnsck10 / commands.c next >
Encoding:
C/C++ Source or Header  |  1995-05-19  |  13.9 KB  |  669 lines

  1. /*
  2.  *  TwinSock - "Troy's Windows Sockets"
  3.  *
  4.  *  Copyright (C) 1994  Troy Rollo <troy@cbme.unsw.EDU.AU>
  5.  *
  6.  *  This program is free software; you can redistribute it and/or modify
  7.  *  it under the terms of the GNU General Public License as published by
  8.  *  the Free Software Foundation; either version 2 of the License, or
  9.  *  (at your option) any later version.
  10.  *
  11.  *  This program is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public License
  17.  *  along with this program; if not, write to the Free Software
  18.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20.  
  21. #include <stdio.h>
  22. #include <sys/types.h>
  23. #include <netinet/in.h>
  24. #include <netdb.h>
  25. #include <errno.h>
  26. #include <sys/socket.h>
  27. #include "twinsock.h"
  28. #include "tx.h"
  29. #include "wserror.h"
  30.  
  31. struct
  32. {
  33.     int    iErrnoHost;
  34.     int    iErrnoDos;
  35. } error_mappings[] =
  36. {
  37.     { 0,        0        },
  38.     { EINTR,    WSAEINTR    },
  39.     { EBADF,    WSAEBADF    },
  40.     { EINVAL,    WSAEINVAL    },
  41.     { EMFILE,    WSAEMFILE    },
  42.     { EWOULDBLOCK,    WSAEWOULDBLOCK    },
  43.     { EINPROGRESS,    WSAEINPROGRESS    },
  44.     { EALREADY,    WSAEALREADY    },
  45.     { ENOTSOCK,    WSAENOTSOCK    },
  46.     { EDESTADDRREQ,    WSAEDESTADDRREQ },
  47.     { EMSGSIZE,    WSAEMSGSIZE    },
  48.     { EPROTOTYPE,    WSAEPROTOTYPE    },
  49.     { ENOPROTOOPT,    WSAENOPROTOOPT    },
  50.     { EPROTONOSUPPORT, WSAEPROTONOSUPPORT },
  51.     { ESOCKTNOSUPPORT, WSAESOCKTNOSUPPORT },
  52.     { EOPNOTSUPP,    WSAEOPNOTSUPP    },
  53.     { EPFNOSUPPORT,    WSAEPFNOSUPPORT },
  54.     { EAFNOSUPPORT, WSAEAFNOSUPPORT },
  55.     { EADDRINUSE,    WSAEADDRINUSE    },
  56.     { EADDRNOTAVAIL,WSAEADDRNOTAVAIL },
  57.     { ENETDOWN,    WSAENETDOWN    },
  58.     { ENETUNREACH,    WSAENETUNREACH    },
  59.     { ENETRESET,    WSAENETRESET    },
  60.     { ECONNABORTED,    WSAECONNABORTED    },
  61.     { ECONNRESET,    WSAECONNRESET    },
  62.     { ENOBUFS,    WSAENOBUFS    },
  63.     { EISCONN,    WSAEISCONN    },
  64.     { ENOTCONN,    WSAENOTCONN    },
  65.     { ESHUTDOWN,    WSAESHUTDOWN    },
  66.     { ETOOMANYREFS,    WSAETOOMANYREFS    },
  67.     { ETIMEDOUT,    WSAETIMEDOUT    },
  68.     { ECONNREFUSED,    WSAECONNREFUSED    },
  69.     { ELOOP,    WSAELOOP,    },
  70.     { ENAMETOOLONG,    WSAENAMETOOLONG    },
  71.     { EHOSTDOWN,    WSAEHOSTDOWN    },
  72.     { EHOSTUNREACH,    WSAEHOSTUNREACH    },
  73.     { -1,        -1        }
  74. }, h_error_mappings[] =
  75.     { 0,        0        },
  76.     { HOST_NOT_FOUND, WSAHOST_NOT_FOUND },
  77.     { TRY_AGAIN,    WSATRY_AGAIN    },
  78.     { NO_RECOVERY,    WSANO_RECOVERY    },
  79.     { NO_DATA,    WSANO_DATA    },
  80.     { -1,        -1        }
  81. };
  82.  
  83. /* some functions to allow us to copy integer data
  84.  * to and from unaligned addresses
  85.  */
  86.  
  87. static short
  88. ToShort(char *pchData)
  89. {
  90.     short    n;
  91.  
  92.     memcpy(&n, pchData, sizeof(short));
  93.     return n;
  94. }
  95.  
  96. static long
  97. ToLong(char *pchData)
  98. {
  99.     long n;
  100.  
  101.     memcpy(&n, pchData, sizeof(long));
  102.     return n;
  103. }
  104.  
  105. static void
  106. FromShort(char *pchData, short n)
  107. {
  108.     memcpy(pchData, &n, sizeof(short));
  109. }
  110.  
  111. static void
  112. FromLong(char *pchData, long n)
  113. {
  114.     memcpy(pchData, &n, sizeof(long));
  115. }
  116.  
  117. static int
  118. GetIntVal(struct func_arg *pfa)
  119. {
  120.     switch(pfa->at)
  121.     {
  122.     case AT_Int16:
  123.     case AT_Int16Ptr:
  124.         return ToShort(pfa->pvData);
  125.  
  126.     case AT_Int32:
  127.     case AT_Int32Ptr:
  128.         return ToLong(pfa->pvData);
  129.     }
  130. }
  131.  
  132. void
  133. SetIntVal(struct func_arg *pfa, int iVal)
  134. {
  135.     switch(pfa->at)
  136.     {
  137.     case AT_Int16:
  138.     case AT_Int16Ptr:
  139.         FromShort(pfa->pvData,(short) iVal);
  140.         return;
  141.  
  142.     case AT_Int32:
  143.     case AT_Int32Ptr:
  144.         FromLong(pfa->pvData, iVal);
  145.         return;
  146.     }
  147. };
  148.  
  149. struct sockaddr *
  150. ConvertSA(struct func_arg *pfa, struct sockaddr_in *sin)
  151. {
  152.     memcpy(sin, pfa->pvData, sizeof(*sin));
  153.     sin->sin_family = ntohs(sin->sin_family);
  154.     return (struct sockaddr *) sin;
  155. }
  156.  
  157. int
  158. MapError(int iError)
  159. {
  160.     int    i;
  161.  
  162.     for (i = 0; error_mappings[i].iErrnoHost != -1; i++)
  163.     {
  164.         if (error_mappings[i].iErrnoHost == iError)
  165.             return error_mappings[i].iErrnoDos;
  166.     }
  167.     return WSAEFAULT;
  168. }
  169.  
  170. int
  171. MapHError(int iError)
  172. {
  173.     int    i;
  174.  
  175.     for (i = 0; h_error_mappings[i].iErrnoHost != -1; i++)
  176.     {
  177.         if (h_error_mappings[i].iErrnoHost == iError)
  178.             return h_error_mappings[i].iErrnoDos;
  179.     }
  180.     return WSAEFAULT;
  181. }
  182.  
  183. int
  184. CopyString(void *pvData, char *pchString, int iMax)
  185. {
  186.     char    *pchData;
  187.     int    iLen;
  188.  
  189.     pchData = (char *) pvData;
  190.     iLen = strlen(pchString);
  191.     if (iLen + 1 > iMax - 1)
  192.         return 0;
  193.     strcpy(pchData,    pchString);
  194.     return iLen + 1;
  195. }
  196.  
  197. void
  198. CopyHostEnt(void *pvData, struct hostent *phe)
  199. {
  200.     int    iLocation;
  201.     char    *pchData;
  202.     int    i;
  203.  
  204.     pchData = (char *) pvData;
  205.     FromShort(pchData, htons(phe->h_addrtype));
  206.     FromShort(pchData + sizeof(short), htons(phe->h_length));
  207.     for (i = 0; phe->h_addr_list[i]; i++);
  208.     FromShort(pchData + sizeof(short) * 2, htons(i));
  209.     iLocation = sizeof(short) * 3;
  210.     for (i = 0; phe->h_addr_list[i]; i++)
  211.     {
  212.         memcpy(pchData + iLocation, phe->h_addr_list[i], 4);
  213.         iLocation += 4;
  214.     }
  215.     iLocation += CopyString(pchData + iLocation,
  216.                 phe->h_name,
  217.                 MAX_HOST_ENT - iLocation);
  218.     for (i = 0; phe->h_aliases[i]; i++)
  219.     {
  220.         iLocation += CopyString(pchData + iLocation,
  221.                     phe->h_aliases[i],
  222.                     MAX_HOST_ENT - iLocation);
  223.     }
  224.     pchData[iLocation] = 0;
  225. }
  226.  
  227. void
  228. CopyNetEnt(void *pvData, struct netent *pne)
  229. {
  230.     int    iLocation;
  231.     char    *pchData;
  232.     int    i;
  233.  
  234.     pchData = (char *) pvData;
  235.     FromShort(pchData, htons(pne->n_addrtype));
  236.     FromLong(pchData + sizeof(short), pne->n_net);
  237.     iLocation = sizeof(short) + sizeof(long);
  238.     iLocation += CopyString(pchData + iLocation,
  239.                 pne->n_name,
  240.                 MAX_HOST_ENT - iLocation);
  241.     for (i = 0; pne->n_aliases[i]; i++)
  242.     {
  243.         iLocation += CopyString(pchData + iLocation,
  244.                     pne->n_aliases[i],
  245.                     MAX_HOST_ENT - iLocation);
  246.     }
  247.     pchData[iLocation] = 0;
  248. }
  249.  
  250. void
  251. CopyServEnt(void *pvData, struct servent *pse)
  252. {
  253.     int    iLocation;
  254.     char    *pchData;
  255.     int    i;
  256.  
  257.     pchData = (char *) pvData;
  258.     FromShort(pchData, pse->s_port); /* No htons - already in network order */
  259.     iLocation = sizeof(short);
  260.     iLocation += CopyString(pchData + iLocation,
  261.                 pse->s_proto,
  262.                 MAX_HOST_ENT - iLocation);
  263.     iLocation += CopyString(pchData + iLocation,
  264.                 pse->s_name,
  265.                 MAX_HOST_ENT - iLocation);
  266.     for (i = 0; pse->s_aliases[i]; i++)
  267.     {
  268.         iLocation += CopyString(pchData + iLocation,
  269.                     pse->s_aliases[i],
  270.                     MAX_HOST_ENT - iLocation);
  271.     }
  272.     pchData[iLocation] = 0;
  273. }
  274.  
  275. void
  276. CopyProtoEnt(void *pvData, struct protoent *ppe)
  277. {
  278.     int    iLocation;
  279.     char    *pchData;
  280.     int    i;
  281.  
  282.     pchData = (char *) pvData;
  283.     FromShort(pchData, htons(ppe->p_proto));
  284.     iLocation = sizeof(short);
  285.     iLocation += CopyString(pchData + iLocation,
  286.                 ppe->p_name,
  287.                 MAX_HOST_ENT - iLocation);
  288.     for (i = 0; ppe->p_aliases[i]; i++)
  289.     {
  290.         iLocation += CopyString(pchData + iLocation,
  291.                     ppe->p_aliases[i],
  292.                     MAX_HOST_ENT - iLocation);
  293.     }
  294.     pchData[iLocation] = 0;
  295. }
  296.  
  297. void
  298. SwapSockOptIn(    struct func_arg *pfa,
  299.         int    iOpt)
  300. {
  301.     int    iValue;
  302.     char    *pchData;
  303.  
  304.     pchData = (char *) pfa->pvData;
  305.     if (iOpt == SO_LINGER)
  306.     {
  307.         FromShort(pchData, ntohs(ToShort(pchData)));
  308.         FromShort(pchData + sizeof(short),
  309.                 ntohs(ToShort(pchData + sizeof(short))));
  310.     }
  311.     else
  312.     {
  313.         FromLong(pchData, ntohl(ToLong(pchData)));
  314.     }
  315. }
  316.  
  317. void
  318. SwapSockOptOut(    struct func_arg *pfa,
  319.         int    iOpt)
  320. {
  321.     int    iValue;
  322.     char    *pchData;
  323.  
  324.     pchData = (char *) pfa->pvData;
  325.     if (iOpt == SO_LINGER)
  326.     {
  327.         FromShort(pchData, htons(ToShort(pchData)));
  328.         FromShort(pchData + sizeof(short),
  329.                 htons(ToShort(pchData + sizeof(short))));
  330.     }
  331.     else
  332.     {
  333.         FromLong(pchData, htonl(ToLong(pchData)));
  334.     }
  335. }
  336.  
  337. void
  338. ResponseReceived(struct tx_request *ptxr_)
  339. {
  340.     enum Functions ft;
  341.     short    nArgs;
  342.     short    nLen;
  343.     short    id;
  344.     int    iLen;
  345.     int    iValue;
  346.     int    iSocket;
  347.     int    nOptVal;
  348.     short    nError;
  349.     struct    tx_request *ptxr;
  350.     struct    func_arg *pfaArgs;
  351.     struct    func_arg faResult;
  352.     struct    sockaddr_in sin;
  353.     char    *pchData;
  354.     int    i;
  355.     int    iErrorSent;
  356.     int    iOffset;
  357.     struct    hostent *phe;
  358.     struct    netent *pne;
  359.     struct    servent *pse;
  360.     struct    protoent *ppe;
  361.  
  362.     nLen = ntohs(ptxr_->nLen);
  363.     ptxr = (struct tx_request *) malloc(nLen);
  364.     memcpy(ptxr, ptxr_, nLen);
  365.     ft = (enum Functions) ntohs(ptxr->iType);
  366.     nArgs = ntohs(ptxr->nArgs);
  367.  
  368.     pfaArgs = (struct func_arg *) malloc(sizeof(struct func_arg) * nArgs);
  369.     pchData = ptxr->pchData;
  370.     for (i = 0; i < nArgs; i++)
  371.     {
  372.         pfaArgs[i].at = (enum arg_type) ntohs(ToShort(pchData));
  373.         pchData += sizeof(short);
  374.         pfaArgs[i].iLen = ntohs(ToShort(pchData));
  375.         pchData += sizeof(short);
  376.         pfaArgs[i].pvData = pchData;
  377.         pchData += pfaArgs[i].iLen;
  378.     }
  379.     faResult.at = (enum arg_type) ntohs(ToShort(pchData));
  380.     pchData += sizeof(short);
  381.     faResult.iLen = ntohs(ToShort(pchData));
  382.     pchData += sizeof(short);
  383.     faResult.pvData = pchData;
  384.  
  385.     iErrorSent = 0;
  386.     errno = 0;
  387.     h_errno = 0;
  388.  
  389.     switch(ft)
  390.     {
  391.     case FN_IOCtl:
  392.     case FN_Accept:
  393.     case FN_Select:
  394.     case FN_Data:
  395.         ptxr->nError = htons(WSAEOPNOTSUPP);
  396.         ptxr->nLen = htons(sizeof(short) * 5);
  397.         PacketTransmitData(ptxr, sizeof(short) * 5, -1);
  398.         iErrorSent = 1;
  399.         break;
  400.  
  401.     case FN_Send:
  402.         SetIntVal(&faResult,
  403.             send(GetIntVal(&pfaArgs[0]),
  404.                  pfaArgs[1].pvData,
  405.                  GetIntVal(&pfaArgs[2]),
  406.                  GetIntVal(&pfaArgs[3])));
  407.         break;
  408.  
  409.     case FN_SendTo:
  410.         SetIntVal(&faResult,
  411.             sendto(GetIntVal(&pfaArgs[0]),
  412.                    pfaArgs[1].pvData,
  413.                    GetIntVal(&pfaArgs[2]),
  414.                    GetIntVal(&pfaArgs[3]),
  415.                    ConvertSA(&pfaArgs[4], &sin),
  416.                    GetIntVal(&pfaArgs[5])));
  417.         break;
  418.  
  419.     case FN_Bind:
  420.         SetIntVal(&faResult,
  421.             bind(GetIntVal(&pfaArgs[0]),
  422.                  ConvertSA(&pfaArgs[1], &sin),
  423.                  GetIntVal(&pfaArgs[2])));
  424.         break;
  425.  
  426.     case FN_Connect:
  427.         iSocket = GetIntVal(&pfaArgs[0]);
  428.         iValue = connect(iSocket,
  429.                 ConvertSA(&pfaArgs[1], &sin),
  430.                 GetIntVal(&pfaArgs[2]));
  431.         SetIntVal(&faResult, iValue);
  432.         if (iValue != -1)
  433.             BumpLargestFD(iSocket);
  434.         break;
  435.  
  436.     case FN_Close:
  437.         SetIntVal(&faResult,
  438.             close(GetIntVal(&pfaArgs[0])));
  439.         FlushStream(GetIntVal(&pfaArgs[0]));
  440.         SetClosed(GetIntVal(&pfaArgs[0]));
  441.         break;
  442.  
  443.     case FN_Shutdown:
  444.         SetIntVal(&faResult,
  445.             shutdown(GetIntVal(&pfaArgs[0]),
  446.                  GetIntVal(&pfaArgs[1])));
  447.         if (GetIntVal(&pfaArgs[1]) != 1)
  448.             SetClosed(GetIntVal(&pfaArgs[0]));
  449.         break;
  450.  
  451.     case FN_Listen:
  452.         iSocket = GetIntVal(&pfaArgs[0]);
  453.         iValue = listen(iSocket,
  454.                 GetIntVal(&pfaArgs[1]));
  455.         SetIntVal(&faResult, iValue);
  456.         if (iValue != -1)
  457.         {
  458.             BumpLargestFD(iSocket);
  459.             SetListener(iSocket);
  460.         }
  461.         break;
  462.  
  463.     case FN_Socket:
  464.         iSocket = socket(GetIntVal(&pfaArgs[0]),
  465.                 GetIntVal(&pfaArgs[1]),
  466.                 GetIntVal(&pfaArgs[2]));
  467.         SetIntVal(&faResult,iSocket);
  468.         if (iSocket != -1)
  469.         {
  470.             BumpLargestFD(iSocket);
  471.             nOptVal = 1;
  472.             iLen = sizeof(nOptVal);
  473.             setsockopt(iSocket,
  474.                     SOL_SOCKET,
  475.                     SO_OOBINLINE,
  476.                     (char *) &nOptVal,
  477.                     &iLen);
  478.             errno = 0;
  479.         }
  480.         break;
  481.  
  482.     case FN_GetPeerName:
  483.         iLen = GetIntVal(&pfaArgs[2]);
  484.         iValue = getpeername(GetIntVal(&pfaArgs[0]),
  485.                      (struct sockaddr *) pfaArgs[1].pvData,
  486.                      &iLen);
  487.         if (iValue != -1)
  488.         {
  489.             SetIntVal(&faResult, iValue);
  490.             SetIntVal(&pfaArgs[2], iValue);
  491.             iValue = ((struct sockaddr *) pfaArgs[1].pvData)->
  492.                         sa_family;
  493.             iValue = htons((short) iValue);
  494.             ((struct sockaddr *) pfaArgs[1].pvData)->sa_family =
  495.                         (short) iValue;
  496.         }
  497.         break;
  498.  
  499.     case FN_GetSockName:
  500.         iLen = GetIntVal(&pfaArgs[2]);
  501.         iValue = getsockname(GetIntVal(&pfaArgs[0]),
  502.                      (struct sockaddr *) pfaArgs[1].pvData,
  503.                      &iLen);
  504.         if (iValue != -1)
  505.         {
  506.             SetIntVal(&faResult, iValue);
  507.             SetIntVal(&pfaArgs[2], iValue);
  508.             iValue = ((struct sockaddr *) pfaArgs[1].pvData)->
  509.                         sa_family;
  510.             iValue = htons((short) iValue);
  511.             ((struct sockaddr *) pfaArgs[1].pvData)->sa_family =
  512.                         (short) iValue;
  513.         }
  514.         break;
  515.  
  516.     case FN_GetSockOpt:
  517.         iLen = GetIntVal(&pfaArgs[4]);
  518.         iValue = getsockopt(    GetIntVal(&pfaArgs[0]),
  519.                     GetIntVal(&pfaArgs[1]),
  520.                     GetIntVal(&pfaArgs[2]),
  521.                     (char *) pfaArgs[3].pvData,
  522.                     &iLen);
  523.         if (iValue != -1)
  524.         {
  525.             SwapSockOptOut(&pfaArgs[3],
  526.                     GetIntVal(&pfaArgs[2]));
  527.             SetIntVal(&pfaArgs[4], iLen);
  528.         }
  529.         SetIntVal(&faResult, iValue);
  530.         break;
  531.  
  532.     case FN_SetSockOpt:
  533.         iLen = GetIntVal(&pfaArgs[4]);
  534.         SwapSockOptIn(&pfaArgs[3],
  535.                 GetIntVal(&pfaArgs[2]));
  536.         iValue = setsockopt(    GetIntVal(&pfaArgs[0]),
  537.                     SOL_SOCKET,
  538.                     GetIntVal(&pfaArgs[2]),
  539.                     (char *) pfaArgs[3].pvData,
  540.                     &iLen);
  541.         SwapSockOptOut(&pfaArgs[3],
  542.                 GetIntVal(&pfaArgs[2]));
  543.         SetIntVal(&faResult, iValue);
  544.         break;
  545.  
  546.     case FN_GetHostName:
  547.         SetIntVal(&faResult,
  548.             gethostname((char *) pfaArgs[0].pvData,
  549.                     GetIntVal(&pfaArgs[1])));
  550.         break;
  551.  
  552.     case FN_HostByAddr:
  553.         phe = gethostbyaddr((char *) pfaArgs[0].pvData,
  554.                     GetIntVal(&pfaArgs[1]),
  555.                     GetIntVal(&pfaArgs[2]));
  556.         if (phe)
  557.         {
  558.             h_errno = 0;
  559.             CopyHostEnt(faResult.pvData, phe);
  560.         }
  561.         break;
  562.  
  563.     case FN_HostByName:
  564.         phe = gethostbyname((char *) pfaArgs[0].pvData);
  565.         if (phe)
  566.         {
  567.             h_errno = 0;
  568.             CopyHostEnt(faResult.pvData, phe);
  569.         }
  570.         else if (!h_errno)
  571.         {
  572.             h_errno = TRY_AGAIN;
  573.         }
  574.         break;
  575.  
  576.     case FN_ServByPort:
  577.         pse = getservbyport(GetIntVal(&pfaArgs[0]),
  578.                     (char *) pfaArgs[1].pvData);
  579.         if (pse)
  580.         {
  581.             h_errno = 0;
  582.             CopyServEnt(faResult.pvData, pse);
  583.         }
  584.         else
  585.         {
  586.             h_errno = NO_DATA;
  587.         }
  588.         break;
  589.  
  590.     case FN_ServByName:
  591.         pse = getservbyname((char *) pfaArgs[0].pvData,
  592.                     (char *) pfaArgs[1].pvData);
  593.         if (pse)
  594.         {
  595.             h_errno = 0;
  596.             CopyServEnt(faResult.pvData, pse);
  597.         }
  598.         else
  599.         {
  600.             h_errno = NO_DATA;
  601.         }
  602.         break;
  603.  
  604.     case FN_ProtoByNumber:
  605.         ppe = getprotobynumber(GetIntVal(&pfaArgs[0]));
  606.         if (ppe)
  607.         {
  608.             h_errno = 0;
  609.             CopyProtoEnt(faResult.pvData, ppe);
  610.         }
  611.         else
  612.         {
  613.             h_errno = NO_DATA;
  614.         }
  615.         break;
  616.  
  617.     case FN_ProtoByName:
  618.         ppe = getprotobyname((char *) pfaArgs[0].pvData);
  619.         if (ppe)
  620.         {
  621.             h_errno = 0;
  622.             CopyProtoEnt(faResult.pvData, ppe);
  623.         }
  624.         else
  625.         {
  626.             h_errno = NO_DATA;
  627.         }
  628.         break;
  629.     }
  630.     if (!iErrorSent)
  631.     {
  632.         if (ft >= FN_HostByAddr || ft <= FN_ProtoByName)
  633.             ptxr->nError = htons(MapHError(h_errno));
  634.         else
  635.             ptxr->nError = htons(MapError(errno));
  636.         PacketTransmitData(ptxr, nLen, -1);
  637.     }
  638.     free(ptxr);
  639.     free(pfaArgs);
  640. }
  641.  
  642. void
  643. SendSocketData(int iSocket,
  644.         void    *pvData,
  645.         int    iLen,
  646.         struct sockaddr_in *psa,
  647.         int    iAddrLen,
  648.         enum function_type ft)
  649. {
  650.     struct    tx_request *ptxr;
  651.     int    iDataLen;
  652.     struct    sockaddr_in sa;
  653.  
  654.     iDataLen = sizeof(struct sockaddr_in) + iLen;
  655.     sa = *psa;
  656.     sa.sin_family = htons(sa.sin_family);
  657.     ptxr = (struct tx_request *) malloc(sizeof(short) * 5 + iDataLen);
  658.     ptxr->nLen = htons(iDataLen + sizeof(short) * 5);
  659.     ptxr->id = htons(iSocket);
  660.     ptxr->nArgs = 0;
  661.     ptxr->nError = 0;
  662.     ptxr->iType = htons(ft);
  663.     memcpy(ptxr->pchData, &sa, sizeof(sa));
  664.     memcpy(ptxr->pchData + sizeof(sa), pvData, iLen);
  665.     PacketTransmitData(ptxr, sizeof(short) * 5 + iDataLen, iSocket);
  666.     free(ptxr);
  667. }
  668.