home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / k95source / ckoibm.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  29KB  |  1,008 lines

  1. /* ckoibm.c
  2.  *
  3.  * TCP/IP interface DLL between C-Kermit and IBM TCP/IP
  4.  *
  5.  * Updated by: Jeffrey Altman (jaltman@secure-endpoints.com)
  6.  *               Secure Endpoints Inc., New York City
  7.  *    SOCKS Support (thanks to David Singer, IBM (dsinger@almaden.ibm.com)
  8.  *    Multiple IP packages
  9.  *
  10.  * Original author:  Kai-Uwe Rommel <rommel@ars.muc.de>
  11.  * Created: Wed May 25 1994
  12.  */
  13.  
  14. /*
  15.   Copyright (C) 1985, 2004, Trustees of Columbia University in the City of New
  16.   York.
  17. */
  18.  
  19. #define INCL_DOSEXCEPTIONS
  20. #define INCL_DOSFILEMGR
  21. #define INCL_DOSMISC
  22. #include <os2.h>
  23. #undef COMMENT
  24.  
  25. #include <stdlib.h>
  26. #include <stdio.h>
  27. #include <memory.h>
  28. #include <sys/types.h>
  29.  
  30. #ifdef __IBMC__
  31. #define off_t _dummy_off_t  /* avoid warning */
  32. #include <types.h>
  33. #undef off_t
  34. #else
  35. #define far _far
  36. #define cdecl _cdecl
  37. #include <types.h>
  38. #endif
  39.  
  40. #ifdef __TYPES_32H
  41. #define FDPTR                                  /* TCP/IP 2.0 */
  42. #define PACKED
  43. #else
  44. #define FDPTR (short * _Seg16)                 /* TCP/IP 1.2.1 */
  45. #define PACKED _Packed
  46. #endif
  47.  
  48. #include <netinet/in.h>
  49. #include <netdb.h>
  50. #include <sys/ioctl.h>
  51. #include <sys/socket.h>
  52.  
  53. #ifdef SOCKS_ENABLED
  54. #include <arpa/nameser.h>
  55. #include <resolv.h>
  56. #endif /* SOCKS_ENABLED */
  57.  
  58. #define BSD_SELECT
  59. #include <sys/time.h>
  60. #include <sys/select.h>
  61.  
  62. #define CK_DLL
  63. #include "ckotcp.h"
  64.  
  65. #ifdef SOCKS_ENABLED
  66. /* SOCKS 4.2 code derived from CSTC_RELEASE 4.2 on ftp.nec.com /pub/security */
  67.  
  68. static int usesocks = FALSE ;
  69. static int usesocksns = FALSE ;
  70. static int socks_usens = FALSE ;
  71. static struct in_addr socks_server, socks_ns, default_server ;
  72. static int server_count ;
  73. static char * username ;
  74. enum socks_action { deny, direct, sockd } ;
  75.  
  76. /* Current SOCKS protocol version */
  77. #define SOCKS_VERSION   4
  78.  
  79. #define CSTC_RELEASE    "4.2"
  80.  
  81. /*
  82.  **  Response commands/codes
  83.  */
  84. #define SOCKS_CONNECT   1
  85. #define SOCKS_BIND      2
  86. #define SOCKS_RESULT    90
  87. #define SOCKS_FAIL      91
  88. #define SOCKS_NO_IDENTD 92 /* Failed to connect to Identd on client machine */
  89. #define SOCKS_BAD_ID    93 /* Client's Identd reported a different user-id */
  90.  
  91. typedef unsigned long u_int32;
  92.  
  93. typedef struct {
  94.     u_int32  host; /* in network byte order */
  95.     unsigned short          port; /* in network byte oreder */
  96.     unsigned char           version;
  97.     unsigned char           cmd;
  98.     } Socks_t;
  99.  
  100. enum portcmp { e_lt, e_gt, e_eq, e_neq, e_le, e_ge, e_nil };
  101. typedef enum portcmp Portcmp;
  102.  
  103. /* structure for caching configurations.  this is improves performance in
  104.  * clients when VERSATILE_CLIENTS is defined or in servers
  105.  * when NOT_THROUGH_INETD is defined.
  106.  * Also used in the SOCKS library.
  107.  */
  108.  
  109. struct config {
  110.     enum socks_action action;
  111.     int use_identd;
  112.     Portcmp tst;
  113.     char *userlist, *serverlist;
  114.     struct in_addr saddr,   /* source addr */
  115.     smask,              /* source mask */
  116.     daddr,          /* destination addr */
  117.     dmask,          /* destination mask */
  118.     interface;      /* interface (for route file) */
  119.     char *cmdp;
  120.     unsigned short dport;
  121.     };
  122.  
  123. #define CONF_INCR       100     /* step increment for realloc */
  124. void    SOCKS_mkargs();
  125. int     SOCKS_getaddr();
  126. int     SOCKS_getquad();
  127. long    SOCKS_getport();
  128. int     SOCKS_checkuser();
  129. char    socks_src_user[];
  130. struct sockaddr_in       socks_nsin;
  131. ULONG SocksHost;
  132. char *socks_def_server = NULL ;
  133. char *socks_serverlist = NULL ;
  134.  
  135. static struct config *confPtr, **confNtries = NULL;
  136. static int Ntries = 0;
  137.  
  138. /*
  139. **  Simple 'SOCKS_mkargs' doesn't handle \, ", or '.
  140. */
  141. void SOCKS_mkargs(cp, argc, argv, max)
  142. char    *cp;
  143. int     *argc;
  144. char    *argv[];
  145. int     max;
  146. {
  147.         *argc = 0;
  148.         while (isspace(*cp))
  149.                 cp++;
  150.  
  151.         while (*cp != '\0') {
  152.                 argv[(*argc)++] = cp;
  153.                 if (*argc >= max)
  154.                         return;
  155.  
  156.                 while (!isspace(*cp) && (*cp != '\0'))
  157.                         cp++;
  158.                 while (isspace(*cp))
  159.                         *cp++ = '\0';
  160.         }
  161. }
  162.  
  163.  
  164. int SOCKS_getquad(dotquad, addr)
  165. char            *dotquad;
  166. struct in_addr  *addr;
  167. /* dotquad must be in dotted quad form. Returns -1 if not. */
  168. {
  169.         if ((addr->s_addr = inet_addr(dotquad)) != (ULONG) -1)
  170.                 return 0;
  171.         if (strcmp(dotquad, "255.255.255.255") == 0)
  172.                 return 0;
  173.         return -1;
  174. }
  175.  
  176. /*
  177. **  Get address, must be dotted quad, or full domain name, or network name.
  178. **  Returns -1 if none of the above.
  179. */
  180. int SOCKS_getaddr(name, addr)
  181. char            *name;
  182. struct in_addr  *addr;
  183. {
  184.         struct hostent  *hp;
  185.         struct netent   *np;
  186.  
  187.         if (SOCKS_getquad(name, addr) != -1)
  188.                 return 0;
  189.         if ((hp = gethostbyname(name)) != NULL) {
  190.                 bcopy(hp->h_addr_list[0], &(addr->s_addr), hp->h_length);
  191.                 return 0;
  192.         }
  193.         if ((np = getnetbyname(name)) != NULL) {
  194.                 addr->s_addr = np->n_net;
  195.                 return 0;
  196.         }
  197.         return -1;
  198. }
  199.  
  200. long SOCKS_getport(name)
  201. char            *name;
  202. {
  203.         struct servent  *sp;
  204.  
  205.         if ((sp = getservbyname(name, "tcp")) != NULL) {
  206.                 return sp->s_port;
  207.         }
  208.         if (!isdigit(*name))
  209.                 return -1;
  210.         return htons(atol(name));
  211. }
  212.  
  213. /*
  214.  *   -1 no socks.conf file or no valid entries
  215.  *    0 everything okay
  216.  */
  217. static int
  218. SOCKS_read_config( void )
  219. {
  220.         FILE            *fd;
  221.         static char     filename[256];
  222.         static char     buf[1024];
  223.         char            *bp;
  224.         int             linenum = 0;
  225.         char    *argv[10];
  226.         int     argc;
  227.         struct in_addr  daddr, dmask;
  228.         int     next_arg;
  229.         enum socks_action  action;
  230.         char    *userlist = NULL, *server_list = NULL;
  231.         long    p;
  232.         unsigned short dport;
  233.         char    *cmdp = NULL;
  234.         struct  in_addr self;
  235.         Portcmp tst;
  236.  
  237.     /* find the etc directory */
  238.     if ( DosScanEnv("ETC",&bp) )
  239.         return -1 ;
  240.  
  241.     /* check for the socks.conf or socks.cnf */
  242.     strcpy( filename, bp ) ;
  243.     if ( bp[strlen(bp)] != '\\' )
  244.         strcat( filename, "\\" ) ;
  245.     strcat( filename, "socks.conf" ) ;
  246.     fd = fopen( filename, "r" ) ;
  247.  
  248.     if ( !fd ) {
  249.         strcpy( filename, bp ) ;
  250.         if ( bp[strlen(bp)] != '\\' )
  251.             strcat( filename, "\\" ) ;
  252.         strcat( filename, "socks.cnf" ) ;
  253.         fd = fopen( filename, "r" ) ;
  254.         }
  255.  
  256.     if ( !fd )
  257.         return -1 ;
  258.  
  259.         while (fgets(buf, sizeof(buf) - 1, fd) != NULL) {
  260.                 linenum++;
  261.                 /*
  262.                 **  Comments start with a '#' anywhere on the line
  263.                 */
  264.                 cmdp = (char *)0;
  265.                 if ((bp = index(buf, '\n')) != NULL)
  266.                         *bp = '\0';
  267.                 for (bp = buf; *bp != '\0'; bp++) {
  268.                         if (*bp == ':') {
  269.                                 *bp++ = '\0';
  270.                                 cmdp = bp;
  271.                                 break;
  272.                         } else if (*bp == '#') {
  273.                                 *bp = '\0';
  274.                                 break;
  275.                         } else if (*bp == '\t')
  276.                                 *bp = ' ';
  277.                 }
  278.                 if (strlen(buf) == 0) continue;
  279.                 SOCKS_mkargs(buf, &argc, argv, 7);
  280.                 if (argc == 0) {
  281.                         continue;
  282.                 }
  283.  
  284.                 if ((argc < 3) || (argc > 7)) {
  285.                         printf("Invalid entry at line %d in file %s\n",linenum, filename);
  286.                         continue;
  287.                 }
  288.  
  289.                 /* parse the whole entry now, once. */
  290.                 next_arg = 1;
  291.                 server_list = (char *)0;
  292.  
  293.                 if (!strcmp(*argv, "sockd")) {
  294.                         server_list = socks_def_server;
  295.                         action = sockd;
  296.                         if (strncmp(*(argv +next_arg), "@=", 2) == 0) {
  297.                                 server_list = *(argv +next_arg) + 2;
  298.                                 if(*server_list == '\0')
  299.                                         server_list = socks_def_server;
  300.                                 next_arg++;
  301.                         }
  302.                 } else if (strncmp(*argv, "sockd@", 6) == 0) {
  303.                         action = sockd;
  304.                         server_list = *(argv) + 6;
  305.                         if (*server_list == '\0')
  306.                                 server_list = socks_def_server;
  307.                 } else if (!strcmp(*argv, "direct")) {
  308.                         action = direct;
  309.                 } else if (!strcmp(*argv, "deny")) {
  310.                         action = deny;
  311.                 } else {
  312.                         printf("Invalid sockd/direct/deny field at line %d in file %s\n", linenum, filename);
  313.                         continue;
  314.                 }
  315.  
  316.                 userlist = (char *)0;
  317.                 if (strncmp(*(argv +next_arg), "*=", 2) == 0) {
  318.                         if (*(argv +next_arg) +2) userlist = *(argv +next_arg) + 2;
  319.                         next_arg++;
  320.                 }
  321.                 if(argc <= next_arg+1) {
  322.                         printf("Invalid entry at line %d in file %s\n", linenum, filename);
  323.                         continue;
  324.                 }
  325.                 if (SOCKS_getaddr(*(argv +next_arg++), &daddr) == -1){
  326.                         printf("illegal destination field at line %d in file %s\n", linenum, filename);
  327.                         continue;
  328.                 }
  329.                 if (SOCKS_getquad(*(argv +next_arg++), &dmask) == -1) {
  330.                         printf("illegal destination mask at line %d in file %s\n", linenum, filename);
  331.                         continue;
  332.                 }
  333.                 if (argc > next_arg + 1) {
  334.                         if (!strcmp(*(argv +next_arg), "eq"))
  335.                                 tst = e_eq;
  336.                         else if (!strcmp(*(argv +next_arg), "neq"))
  337.                                 tst = e_neq;
  338.                         else if (!strcmp(*(argv +next_arg), "lt"))
  339.                                 tst = e_lt;
  340.                         else if (!strcmp(*(argv +next_arg), "gt"))
  341.                                 tst = e_gt;
  342.                         else if (!strcmp(*(argv +next_arg), "le"))
  343.                                 tst = e_le;
  344.                         else if (!strcmp(*(argv +next_arg), "ge"))
  345.                                 tst = e_ge;
  346.                         else {
  347.                                 printf("Invalid comparison at line %d in file %s\n", linenum, filename);
  348.                                 continue;
  349.                         }
  350.  
  351.                         if (((p = SOCKS_getport(*(argv +next_arg+1))) < 0) ||
  352.                                 (p >= (1L << 16))) {
  353.                                 printf("Invalid port number at line %d in file %s\n", linenum, filename);
  354.                                 continue;
  355.                         } else {
  356.                                 dport = p;
  357.                         }
  358.                 } else {
  359.                         tst = e_nil;
  360.                         dport = 0;
  361.                 }
  362.  
  363. #ifdef DEBUG
  364.                 {
  365.                         char msg[1024];
  366.                         if (userlist)
  367.                                 sprintf(msg,"%s %s 0x%08x 0x%08x %s %u",
  368.                                         *argv, userlist, daddr.s_addr, dmask,
  369.                                                 tst == e_eq ? "==" :
  370.                                                 tst == e_neq ? "!=" :
  371.                                                 tst == e_lt ? "<" :
  372.                                                 tst == e_gt ? ">" :
  373.                                                 tst == e_le ? "<=" :
  374.                                                 tst == e_ge ? ">=" : "NIL",
  375.                                                 dport);
  376.                         else
  377.                                 sprintf(msg,"%s 0x%08x 0x%08x %s %u",
  378.                                         *argv, daddr.s_addr, dmask,
  379.                                                 tst == e_eq ? "==" :
  380.                                                 tst == e_neq ? "!=" :
  381.                                                 tst == e_lt ? "<" :
  382.                                                 tst == e_gt ? ">" :
  383.                                                 tst == e_le ? "<=" :
  384.                                                 tst == e_ge ? ">=" : "NIL",
  385.                                                 dport);
  386.                         printf("%s\n", msg);
  387.                 }
  388. #endif
  389.                 /* we have a parsed line.  cache it. */
  390.                 if (!confNtries || confPtr - *confNtries >= Ntries) {
  391.                         /* some systems can't be counted on to handle
  392.                          * realloc(NULL, ...) correctly.
  393.                          */
  394.                         if (confNtries == NULL)
  395.                             confNtries =
  396.                           (struct config **) malloc(CONF_INCR *sizeof(struct config **));
  397.                         else confNtries = (struct config **)
  398.                           realloc(confNtries, (Ntries +CONF_INCR) *sizeof(struct config));
  399.                 }
  400.                 *(confNtries +Ntries) = (struct config *) malloc(sizeof(struct config));
  401.                 confPtr = *(confNtries +Ntries);
  402.                 Ntries++;
  403.                 confPtr->action = action;
  404.                 confPtr->tst = tst;
  405.                 if (server_list) {
  406.                         confPtr->serverlist = (char *)malloc(strlen(server_list) +1);
  407.                         strcpy(confPtr->serverlist, server_list);
  408.                 }
  409.                 else confPtr->serverlist = NULL;
  410.                 if (userlist) {
  411.                         confPtr->userlist = (char *)malloc(strlen(userlist) +1);
  412.                         strcpy(confPtr->userlist, userlist);
  413.                 }
  414.                 else confPtr->userlist = NULL;
  415.                 confPtr->daddr.s_addr = daddr.s_addr;
  416.                 confPtr->dmask.s_addr = dmask.s_addr;
  417.                 if (cmdp) {
  418.                         confPtr->cmdp = (char *) malloc(strlen(cmdp) +1);
  419.                         strcpy(confPtr->cmdp, cmdp);
  420.                 }
  421.                 else confPtr->cmdp = NULL;
  422.                 confPtr->dport = dport;
  423.  
  424.         }
  425.         fclose(fd);
  426.         if (confNtries == NULL) {
  427.                 printf("No valid entires in file %s\n", filename);
  428.                 return(-1);
  429.         }
  430.         return 0;
  431. }
  432.  
  433. int
  434. SOCKS_init( void )
  435. {
  436.     PSZ var ;
  437.     struct hostent *host ;
  438.  
  439.     socks_server.s_addr = 0 ;
  440.     socks_ns.s_addr = 0 ;
  441.  
  442.     /* get the resolv info */
  443.     res_init() ;
  444.     server_count = _res.nscount ;
  445.     default_server.s_addr = _res.nsaddr_list[0].sin_addr.s_addr ;
  446.  
  447.     /* get the username if any */
  448.     if ( !DosScanEnv("USER",&var) )
  449.         username = strdup(var);
  450.     else
  451.         username = "os2user";
  452.  
  453.     /* get the SOCKS server if any */
  454.     if ( !DosScanEnv("SOCKS_SERVER",&var) ) {
  455.         socks_def_server = strdup( var ) ;
  456.         host = gethostbyname( var ) ;
  457.         if ( host ) {
  458.             memcpy( &socks_server, host->h_addr_list[0],
  459.                 sizeof(socks_server));
  460.             }
  461.         else {
  462.             socks_server.s_addr = inet_addr(var);
  463.             }
  464.         }
  465.  
  466.     /* get the SOCKS Name Server if any */
  467.     if ( socks_server.s_addr && (socks_server.s_addr != -1) ) {
  468.         usesocks = TRUE ;
  469.         if ( !DosScanEnv("SOCKS_NS",&var) ) {
  470.             host = gethostbyname( var ) ;
  471.             if ( host ) {
  472.                 memcpy( &socks_ns.s_addr, host->h_addr_list[0],
  473.                     sizeof(socks_ns.s_addr)) ;
  474.                 }
  475.             else {
  476.                 socks_ns.s_addr = inet_addr( var ) ;
  477.                 }
  478.  
  479.             /* now install this name server as the default */
  480.             if ( socks_ns.s_addr && ( socks_ns.s_addr != -1 ) ) {
  481.                 _res.nsaddr_list[0].sin_addr.s_addr = socks_ns.s_addr ;
  482.                 _res.nscount = 1 ;
  483.                 usesocksns = TRUE ;
  484.                 }
  485.             }
  486.         }
  487.  
  488.     /* read socks.conf file */
  489.     if ( usesocks ) {
  490.         printf( "C-Kermit is SOCKS 4.2 enabled\n" ) ;
  491.         SOCKS_read_config() ;
  492.         }
  493.  
  494.     return( usesocks ) ;
  495. }
  496.  
  497. enum socks_action
  498. SOCKS_validate( struct sockaddr_in * dest )
  499. {
  500.     int i = 0 ;
  501.     enum socks_action action = sockd ;
  502.  
  503.     for ( i = 0 ; i < Ntries ; i++ ) {
  504.         if ( ( confNtries[i]->daddr.s_addr & confNtries[i]->dmask.s_addr ) ==
  505.             ( dest->sin_addr.s_addr & confNtries[i]->dmask.s_addr ) )
  506.             if ( confNtries[i]->tst == e_nil ) {
  507.                 action = confNtries[i]->action ;
  508.                 break;
  509.                 }
  510.             if ((confNtries[i]->tst == e_eq) && (dest->sin_port == confNtries[i]->dport)){
  511.                 action = confNtries[i]->action ;
  512.                 break;
  513.                 }
  514.             if ((confNtries[i]->tst == e_neq) && (dest->sin_port != confNtries[i]->dport)){
  515.                 action = confNtries[i]->action ;
  516.                 break;
  517.                 }
  518.             if ((confNtries[i]->tst == e_lt) && (dest->sin_port < confNtries[i]->dport)){
  519.                 action = confNtries[i]->action ;
  520.                 break;
  521.                 }
  522.             if ((confNtries[i]->tst == e_gt) && (dest->sin_port > confNtries[i]->dport)){
  523.                 action = confNtries[i]->action ;
  524.                 break;
  525.                 }
  526.             if ((confNtries[i]->tst == e_le) && (dest->sin_port <= confNtries[i]->dport)){
  527.                 action = confNtries[i]->action ;
  528.                 break;
  529.                 }
  530.             if ((confNtries[i]->tst == e_ge) && (dest->sin_port >= confNtries[i]->dport)){
  531.                 action = confNtries[i]->action ;
  532.                 break;
  533.                 }
  534.         }
  535.     return action ;
  536. }
  537. #endif /* SOCKS_ENABLED */
  538.  
  539. int ENTRY ck_sockinit(void)
  540. {
  541. #ifdef SOCKS_ENABLED
  542.     SOCKS_init() ;
  543. #endif /* SOCKS_ENABLED */
  544.     return sock_init();
  545. }
  546.  
  547. /* socket calls */
  548.  
  549. int ENTRY ck_connect(int socket, struct ck_sockaddr *name, int namelen)
  550. {
  551.     struct sockaddr_in addr;
  552.     int rc ;
  553.  
  554. #ifdef SOCKS_ENABLED
  555.     char request[100];
  556.     char *next ;
  557.     int packetsize ;
  558.     int sockret ;
  559.  
  560.     if (usesocks) {
  561.  
  562.         memset(&addr, 0, sizeof(addr));
  563.         addr.sin_port        = ((struct ck_sockaddr_in *) name)
  564.             ->sin_port;
  565.         addr.sin_family      = ((struct ck_sockaddr_in *) name)
  566.             ->sin_family;
  567.         addr.sin_addr.s_addr = ((struct ck_sockaddr_in *) name)
  568.             ->sin_addr.s_addr;
  569.  
  570.         /* Check local cached values from SOCKS.CONF */
  571.         switch ( SOCKS_validate( &addr ) ) {
  572.             case deny:
  573.                 return -1 ;
  574.  
  575.             case direct:
  576.                 break;
  577.  
  578.             case sockd:
  579.                 addr.sin_family = AF_INET ;
  580.                 addr.sin_addr = socks_server ;
  581.                 addr.sin_port = htons(1080) ;      /* The SOCKS Service */
  582.  
  583.                 /* Connect to the SOCKS Server */
  584.                 if ( connect(socket, (struct sockaddr *) &addr, sizeof(addr)) < 0 ) {
  585.                     return -1 ;
  586.                 }
  587.  
  588.                 /* Build the request packet */
  589.                 next = request;
  590.                 *next++ = SOCKS_VERSION ;
  591.                 *next++ = SOCKS_CONNECT ;
  592.                 memcpy(next, &((struct ck_sockaddr_in *) name)->sin_port,
  593.                         sizeof(((struct ck_sockaddr_in *) name)->sin_port) ) ;
  594.                 next += sizeof(((struct ck_sockaddr_in *) name)->sin_port) ;
  595.                 memcpy(next, &((struct ck_sockaddr_in *) name)->sin_addr,
  596.                         sizeof(((struct ck_sockaddr_in *) name)->sin_addr) ) ;
  597.                 next += sizeof(((struct ck_sockaddr_in *) name)->sin_addr) ;
  598.                 strcpy(next,username) ;
  599.                 next += strlen( username ) + 1;
  600.  
  601.                 /* Send the request */
  602.                 rc = send(socket, request, next - request, 0) ;
  603.  
  604.                 /* Now retrieve the response */
  605.                 packetsize = 8 ; /* VN 1, CD 1, PORT 2, IP 4 */
  606.                 next = request ;
  607.                 while ( rc > 0 && packetsize > (next - request) ) {
  608.                     rc = recv( socket, next, packetsize - (next - request), 0 ) ;
  609.                     next += rc ;
  610.                 }
  611.                 sockret = request[1] ;    /* Get the SOCKS return value */
  612.                 return ( sockret == SOCKS_RESULT ? 0 : -1 ) ;
  613.             }
  614.     }
  615.  
  616.     /* Direct connection */
  617. #endif
  618.  
  619.     memset(&addr, 0, sizeof(addr));
  620.     addr.sin_port        = ((struct ck_sockaddr_in *) name)
  621.         ->sin_port;
  622.     addr.sin_family      = ((struct ck_sockaddr_in *) name)
  623.         ->sin_family;
  624.     addr.sin_addr.s_addr = ((struct ck_sockaddr_in *) name)
  625.         ->sin_addr.s_addr;
  626.     rc = connect(socket, (struct sockaddr *) &addr, sizeof(addr));
  627.  
  628.     return rc  ;
  629. }
  630.  
  631. int ENTRY ck_bind(int socket, struct ck_sockaddr *name, int namelen)
  632. {
  633.   struct sockaddr_in addr;
  634.  
  635.   memset(&addr, 0, sizeof(addr));
  636.   addr.sin_port        = ((struct ck_sockaddr_in *) name) -> sin_port;
  637.   addr.sin_family      = ((struct ck_sockaddr_in *) name) -> sin_family;
  638.   addr.sin_addr.s_addr = ((struct ck_sockaddr_in *) name) -> sin_addr.s_addr;
  639.  
  640.   return bind(socket, (struct sockaddr *) &addr, sizeof(addr));
  641. }
  642.  
  643. int ENTRY ck_listen(int socket, int backlog)
  644. {
  645.     return listen( socket, backlog );
  646. }
  647.  
  648. int ENTRY ck_accept(int socket, struct ck_sockaddr *name, int * namelen)
  649. {
  650.   struct sockaddr_in addr;
  651. #ifdef __SOCKET_32H
  652.   int len ;
  653. #else
  654. short len ;
  655. #endif
  656.   int rc = 0 ;
  657.  
  658.   memset(&addr, 0, sizeof(addr));
  659.   addr.sin_port        = ((struct ck_sockaddr_in *) name) -> sin_port;
  660.   addr.sin_family      = ((struct ck_sockaddr_in *) name) -> sin_family;
  661.   addr.sin_addr.s_addr = ((struct ck_sockaddr_in *) name) -> sin_addr.s_addr;
  662.   len = sizeof(addr) ;
  663.  
  664.   rc = accept(socket, (struct sockaddr *) &addr, &len);
  665.   ((struct ck_sockaddr_in *) name) -> sin_port = addr.sin_port ;
  666.   ((struct ck_sockaddr_in *) name) -> sin_family = addr.sin_family ;
  667.   ((struct ck_sockaddr_in *) name) -> sin_addr.s_addr = addr.sin_addr.s_addr;
  668.   *namelen = len ;
  669.  
  670.   return rc ;
  671. }
  672.  
  673. int ENTRY ck_ioctl(int socket, int cmd, long *data)
  674. {
  675.   switch (cmd)
  676.   {
  677.   case CK_FIONREAD:
  678.     cmd = FIONREAD;
  679.     break;
  680.   case CK_FIONBIO:
  681.     cmd = FIONBIO;
  682.     break;
  683.   case CK_SIOCATMARK:
  684.      cmd = SIOCATMARK;
  685.      break;
  686.   default:
  687.     return -1;
  688.   }
  689.  
  690.   return ioctl(socket, cmd, (char *)data, 4);
  691. }
  692.  
  693. int ENTRY ck_recv(int socket, char *buffer, int length, int flags)
  694. {
  695.   return recv(socket, buffer, length, flags);
  696. }
  697.  
  698. int ENTRY ck_select(int *fds, int read, int write, int except, long timeout)
  699. {
  700.   /* Warning: if the called select is 16-bit but the calling code is
  701.    * 32-bit, only one fd can be pointed to by fds! However, calling
  702.    * with one "read" socket is the only use of select() in
  703.    * C-Kermit. Might change in the future, so this must be checked. */
  704.  
  705.   int rc ;
  706.   ULONG nestings ;  /* MustComplete sections */
  707. #ifdef BSD_SELECT
  708.   fd_set rfds;
  709.   struct timeval tv;
  710.   int socket = *fds;
  711. #endif
  712.  
  713.   if ((read + write + except) != 1)
  714.     return -1;
  715.  
  716. #ifdef BSD_SELECT
  717.   FD_ZERO(&rfds);
  718.   FD_SET(socket, &rfds);
  719.   tv.tv_sec = tv.tv_usec = 0L;
  720.  
  721.   if (timeout < 1000)
  722.     tv.tv_usec = (long) timeout * 1000L;
  723.   else
  724.     tv.tv_sec = timeout / 1000L;
  725.  
  726.   rc =  (read ? select(FD_SETSIZE, &rfds, NULL, NULL, &tv) : 1) &&
  727.         (write ? select(FD_SETSIZE, NULL, &rfds, NULL, &tv) : 1) &&
  728.         (except ? select(FD_SETSIZE, NULL, NULL, &rfds, &tv) : 1) &&
  729.             FD_ISSET(socket, &rfds);
  730. #else
  731.   rc = select(FDPTR fds, read, write, except, timeout);
  732. #endif
  733.     return rc ;
  734. }
  735.  
  736. int ENTRY ck_send(int socket, char *buffer, int length, int flags)
  737. {
  738.   return send(socket, buffer, length, flags);
  739. }
  740.  
  741. int ENTRY ck_setsockopt(int socket, int level, int optname,
  742.                   char *optvalue, int optlength)
  743. {
  744.   if (level == CK_SOL_SOCKET)
  745.     level = SOL_SOCKET;
  746.   else
  747.     return -1;
  748.  
  749.    switch ( optname )
  750.    {
  751.    case CK_SO_OOBINLINE:
  752.       optname = SO_OOBINLINE ;
  753.       break;
  754.    case CK_SO_REUSEADDR:
  755.       optname = SO_REUSEADDR ;
  756.       break;
  757.    case CK_SO_LINGER:
  758.       optname = SO_LINGER ;
  759.       break;
  760.    case CK_SO_KEEPALIVE:
  761.       optname = SO_KEEPALIVE ;
  762.       break;
  763.    case CK_SO_SNDBUF:
  764.       optname = SO_SNDBUF ;
  765.       break;
  766.    case CK_SO_RCVBUF:
  767.       optname = SO_RCVBUF ;
  768.       break;
  769.    default:
  770.       return -1;
  771.    }
  772.  
  773.   return setsockopt(socket, level, optname, optvalue, optlength);
  774. }
  775.  
  776. int ENTRY ck_getsockopt(int socket, int level, int optname,
  777.                   char *optvalue, int * optlength)
  778. {
  779. #ifdef __SOCKET_32H
  780.     int len = *optlength;
  781. #else
  782.     short len = (short) *optlength ;
  783. #endif
  784.     int rc = 0 ;
  785.  
  786.   if (level == CK_SOL_SOCKET)
  787.     level = SOL_SOCKET;
  788.   else
  789.     return -1;
  790.  
  791.    switch ( optname )
  792.    {
  793.    case CK_SO_OOBINLINE:
  794.       optname = SO_OOBINLINE ;
  795.       break;
  796.    case CK_SO_REUSEADDR:
  797.       optname = SO_REUSEADDR ;
  798.       break;
  799.    case CK_SO_LINGER:
  800.       optname = SO_LINGER ;
  801.       break;
  802.    case CK_SO_KEEPALIVE:
  803.       optname = SO_KEEPALIVE ;
  804.       break;
  805.    case CK_SO_SNDBUF:
  806.       optname = SO_SNDBUF ;
  807.       break;
  808.    case CK_SO_RCVBUF:
  809.       optname = SO_RCVBUF ;
  810.       break;
  811.    default:
  812.       return -1;
  813.    }
  814.  
  815.   rc = getsockopt(socket, level, optname, optvalue, &len);
  816.     *optlength = len ;
  817.     return rc;
  818. }
  819.  
  820. int ENTRY ck_socket(int domain, int type, int protocol)
  821. {
  822.   if (domain == CK_AF_INET)
  823.     domain = AF_INET;
  824.   else
  825.     return -1;
  826.  
  827.   if (type == CK_SOCK_STREAM)
  828.     type = SOCK_STREAM;
  829.   else
  830.     return -1;
  831.  
  832.   if (protocol != 0)
  833.     return -1;
  834.  
  835.   return socket(domain, type, protocol);
  836. }
  837.  
  838. int ENTRY ck_soclose(int socket)
  839. {
  840.   return soclose(socket);
  841. }
  842.  
  843. /* utility calls */
  844.  
  845. struct ck_hostent * ENTRY ck_gethostbyname(char *name)
  846. {
  847.   struct hostent *host = gethostbyname(name);
  848.   static char * h_addr_list[64] ;
  849.   static struct ck_hostent ckhost = {NULL,NULL,0,0,h_addr_list};
  850.   int i = 0 ;
  851.  
  852. #ifdef SOCKS_ENABLED
  853.   if ( (host == NULL) && usesocksns ) {
  854.     _res.nscount = server_count ;
  855.     _res.nsaddr_list[0].sin_addr.s_addr = default_server.s_addr ;
  856.     host = gethostbyname(name) ;
  857.     _res.nscount = 1 ;
  858.     _res.nsaddr_list[0].sin_addr.s_addr = socks_ns.s_addr ;
  859.     }
  860. #endif /* SOCKS_ENABLED */
  861.  
  862.   if (host == NULL)
  863.     return NULL;
  864.  
  865.   ckhost.h_name     = host -> h_name;
  866.   ckhost.h_aliases  = NULL;
  867.   ckhost.h_addrtype = host -> h_addrtype;
  868.   ckhost.h_length   = host -> h_length;
  869.  
  870.   while( host->h_addr_list[i] != NULL && i < 63) {
  871.     ckhost.h_addr_list[i] = host->h_addr_list[i] ;
  872.     i++ ;
  873.     }
  874.   ckhost.h_addr_list[63] = NULL ;
  875.  
  876.   return &ckhost;
  877. }
  878.  
  879. struct ck_servent * ENTRY ck_getservbyname(char *name, char *protocol)
  880. {
  881.   PACKED struct servent *serv = getservbyname(name, protocol);
  882.   static struct ck_servent ckserv;
  883.  
  884.   if (serv == NULL)
  885.     return NULL;
  886.  
  887.   ckserv.s_name    = serv -> s_name;
  888.   ckserv.s_aliases = NULL;
  889.   ckserv.s_port    = serv -> s_port;
  890.   ckserv.s_proto   = serv -> s_proto;
  891.  
  892.   return &ckserv;
  893. }
  894.  
  895. struct ck_hostent * ENTRY ck_gethostbyaddr(char *addr, int len, int net)
  896. {
  897.   struct hostent *host = gethostbyaddr(addr, len, net);
  898.   static char * h_addr_list[64] ;
  899.   static struct ck_hostent ckhost = {NULL,NULL,0,0,h_addr_list};
  900.   int i = 0 ;
  901.  
  902. #ifdef SOCKS_ENABLED
  903.   if ( (host == NULL) && usesocksns ) {
  904.     _res.nscount = server_count ;
  905.     _res.nsaddr_list[0].sin_addr.s_addr = default_server.s_addr ;
  906.     host = gethostbyaddr(addr, len, net) ;
  907.     _res.nscount = 1 ;
  908.     _res.nsaddr_list[0].sin_addr.s_addr = socks_ns.s_addr ;
  909.     }
  910. #endif /* SOCKS_ENABLED */
  911.  
  912.   if (host == NULL)
  913.     return NULL;
  914.  
  915.   ckhost.h_name     = host -> h_name;
  916.   ckhost.h_aliases  = NULL;
  917.   ckhost.h_addrtype = host -> h_addrtype;
  918.   ckhost.h_length   = host -> h_length;
  919.  
  920.   while( host->h_addr_list[i] != NULL && i < 63) {
  921.     ckhost.h_addr_list[i] = host->h_addr_list[i] ;
  922.     i++ ;
  923.     }
  924.   ckhost.h_addr_list[63] = NULL ;
  925.  
  926.   return &ckhost;
  927. }
  928.  
  929. struct ck_servent * ENTRY ck_getservbyport(int port, char * name)
  930. {
  931.   PACKED struct servent *serv = getservbyport(port, name);
  932.   static struct ck_servent ckserv;
  933.  
  934.   if (serv == NULL)
  935.     return NULL;
  936.  
  937.   ckserv.s_name    = serv -> s_name;
  938.   ckserv.s_aliases = NULL;
  939.   ckserv.s_port    = serv -> s_port;
  940.   ckserv.s_proto   = serv -> s_proto;
  941.  
  942.   return &ckserv;
  943. }
  944.  
  945. unsigned long ENTRY ck_inet_addr(char *cp)
  946. {
  947.   return inet_addr(cp);
  948. }
  949.  
  950. char * ENTRY ck_inet_ntoa(struct ck_in_addr in)
  951. {
  952.   struct in_addr addr;
  953.  
  954.   addr.s_addr = in.s_addr;
  955.  
  956.   return inet_ntoa(addr);
  957. }
  958.  
  959. int ENTRY ck_getpeername( int socket, struct ck_sockaddr * name, int * namelen )
  960. {
  961. #ifdef __SOCKET_32H
  962.     int len = *namelen;
  963. #else
  964.     short len = (short) *namelen ;
  965. #endif
  966.     int rc = 0 ;
  967.  
  968.     rc = getpeername( socket, (struct sockaddr *) name, &len ) ;
  969.     *namelen = len ;
  970.     return rc;
  971. }
  972.  
  973. int ENTRY ck_getsockname( int socket, struct ck_sockaddr * name, int * namelen )
  974. {
  975. #ifdef __SOCKET_32H
  976.     int len = *namelen;
  977. #else
  978.     short len = (short) *namelen ;
  979. #endif
  980.     int rc = 0 ;
  981.  
  982.     rc = getsockname( socket, (struct sockaddr *) name, &len ) ;
  983.     *namelen = len ;
  984.     return rc;
  985. }
  986.  
  987. #ifdef __SOCKET_32H
  988. int ENTRY ck_addsockettolist( int socket )
  989. {
  990.     int rc = 0 ;
  991.     rc = addsockettolist( socket ) ;
  992.     return rc;
  993. }
  994. #endif
  995.  
  996. int ENTRY ck_gethostname( char * buf, int len )
  997. {
  998. #ifdef __SOCKET_32H
  999.     int rc = 0 ;
  1000.     rc = gethostname( buf, len ) ;
  1001.     return rc;
  1002. #else
  1003.     if (buf) *buf = '\0';
  1004.     return(-1);
  1005. #endif
  1006. }
  1007. /* end of ckotcp.c */
  1008.