/* ckoibm.c * * TCP/IP interface DLL between C-Kermit and IBM TCP/IP * * Updated by: Jeffrey Altman (jaltman@secure-endpoints.com) * Secure Endpoints Inc., New York City * SOCKS Support (thanks to David Singer, IBM (dsinger@almaden.ibm.com) * Multiple IP packages * * Original author: Kai-Uwe Rommel * Created: Wed May 25 1994 */ /* Copyright (C) 1985, 2004, Trustees of Columbia University in the City of New York. */ #define INCL_DOSEXCEPTIONS #define INCL_DOSFILEMGR #define INCL_DOSMISC #include #undef COMMENT #include #include #include #include #ifdef __IBMC__ #define off_t _dummy_off_t /* avoid warning */ #include #undef off_t #else #define far _far #define cdecl _cdecl #include #endif #ifdef __TYPES_32H #define FDPTR /* TCP/IP 2.0 */ #define PACKED #else #define FDPTR (short * _Seg16) /* TCP/IP 1.2.1 */ #define PACKED _Packed #endif #include #include #include #include #ifdef SOCKS_ENABLED #include #include #endif /* SOCKS_ENABLED */ #define BSD_SELECT #include #include #define CK_DLL #include "ckotcp.h" #ifdef SOCKS_ENABLED /* SOCKS 4.2 code derived from CSTC_RELEASE 4.2 on ftp.nec.com /pub/security */ static int usesocks = FALSE ; static int usesocksns = FALSE ; static int socks_usens = FALSE ; static struct in_addr socks_server, socks_ns, default_server ; static int server_count ; static char * username ; enum socks_action { deny, direct, sockd } ; /* Current SOCKS protocol version */ #define SOCKS_VERSION 4 #define CSTC_RELEASE "4.2" /* ** Response commands/codes */ #define SOCKS_CONNECT 1 #define SOCKS_BIND 2 #define SOCKS_RESULT 90 #define SOCKS_FAIL 91 #define SOCKS_NO_IDENTD 92 /* Failed to connect to Identd on client machine */ #define SOCKS_BAD_ID 93 /* Client's Identd reported a different user-id */ typedef unsigned long u_int32; typedef struct { u_int32 host; /* in network byte order */ unsigned short port; /* in network byte oreder */ unsigned char version; unsigned char cmd; } Socks_t; enum portcmp { e_lt, e_gt, e_eq, e_neq, e_le, e_ge, e_nil }; typedef enum portcmp Portcmp; /* structure for caching configurations. this is improves performance in * clients when VERSATILE_CLIENTS is defined or in servers * when NOT_THROUGH_INETD is defined. * Also used in the SOCKS library. */ struct config { enum socks_action action; int use_identd; Portcmp tst; char *userlist, *serverlist; struct in_addr saddr, /* source addr */ smask, /* source mask */ daddr, /* destination addr */ dmask, /* destination mask */ interface; /* interface (for route file) */ char *cmdp; unsigned short dport; }; #define CONF_INCR 100 /* step increment for realloc */ void SOCKS_mkargs(); int SOCKS_getaddr(); int SOCKS_getquad(); long SOCKS_getport(); int SOCKS_checkuser(); char socks_src_user[]; struct sockaddr_in socks_nsin; ULONG SocksHost; char *socks_def_server = NULL ; char *socks_serverlist = NULL ; static struct config *confPtr, **confNtries = NULL; static int Ntries = 0; /* ** Simple 'SOCKS_mkargs' doesn't handle \, ", or '. */ void SOCKS_mkargs(cp, argc, argv, max) char *cp; int *argc; char *argv[]; int max; { *argc = 0; while (isspace(*cp)) cp++; while (*cp != '\0') { argv[(*argc)++] = cp; if (*argc >= max) return; while (!isspace(*cp) && (*cp != '\0')) cp++; while (isspace(*cp)) *cp++ = '\0'; } } int SOCKS_getquad(dotquad, addr) char *dotquad; struct in_addr *addr; /* dotquad must be in dotted quad form. Returns -1 if not. */ { if ((addr->s_addr = inet_addr(dotquad)) != (ULONG) -1) return 0; if (strcmp(dotquad, "255.255.255.255") == 0) return 0; return -1; } /* ** Get address, must be dotted quad, or full domain name, or network name. ** Returns -1 if none of the above. */ int SOCKS_getaddr(name, addr) char *name; struct in_addr *addr; { struct hostent *hp; struct netent *np; if (SOCKS_getquad(name, addr) != -1) return 0; if ((hp = gethostbyname(name)) != NULL) { bcopy(hp->h_addr_list[0], &(addr->s_addr), hp->h_length); return 0; } if ((np = getnetbyname(name)) != NULL) { addr->s_addr = np->n_net; return 0; } return -1; } long SOCKS_getport(name) char *name; { struct servent *sp; if ((sp = getservbyname(name, "tcp")) != NULL) { return sp->s_port; } if (!isdigit(*name)) return -1; return htons(atol(name)); } /* * -1 no socks.conf file or no valid entries * 0 everything okay */ static int SOCKS_read_config( void ) { FILE *fd; static char filename[256]; static char buf[1024]; char *bp; int linenum = 0; char *argv[10]; int argc; struct in_addr daddr, dmask; int next_arg; enum socks_action action; char *userlist = NULL, *server_list = NULL; long p; unsigned short dport; char *cmdp = NULL; struct in_addr self; Portcmp tst; /* find the etc directory */ if ( DosScanEnv("ETC",&bp) ) return -1 ; /* check for the socks.conf or socks.cnf */ strcpy( filename, bp ) ; if ( bp[strlen(bp)] != '\\' ) strcat( filename, "\\" ) ; strcat( filename, "socks.conf" ) ; fd = fopen( filename, "r" ) ; if ( !fd ) { strcpy( filename, bp ) ; if ( bp[strlen(bp)] != '\\' ) strcat( filename, "\\" ) ; strcat( filename, "socks.cnf" ) ; fd = fopen( filename, "r" ) ; } if ( !fd ) return -1 ; while (fgets(buf, sizeof(buf) - 1, fd) != NULL) { linenum++; /* ** Comments start with a '#' anywhere on the line */ cmdp = (char *)0; if ((bp = index(buf, '\n')) != NULL) *bp = '\0'; for (bp = buf; *bp != '\0'; bp++) { if (*bp == ':') { *bp++ = '\0'; cmdp = bp; break; } else if (*bp == '#') { *bp = '\0'; break; } else if (*bp == '\t') *bp = ' '; } if (strlen(buf) == 0) continue; SOCKS_mkargs(buf, &argc, argv, 7); if (argc == 0) { continue; } if ((argc < 3) || (argc > 7)) { printf("Invalid entry at line %d in file %s\n",linenum, filename); continue; } /* parse the whole entry now, once. */ next_arg = 1; server_list = (char *)0; if (!strcmp(*argv, "sockd")) { server_list = socks_def_server; action = sockd; if (strncmp(*(argv +next_arg), "@=", 2) == 0) { server_list = *(argv +next_arg) + 2; if(*server_list == '\0') server_list = socks_def_server; next_arg++; } } else if (strncmp(*argv, "sockd@", 6) == 0) { action = sockd; server_list = *(argv) + 6; if (*server_list == '\0') server_list = socks_def_server; } else if (!strcmp(*argv, "direct")) { action = direct; } else if (!strcmp(*argv, "deny")) { action = deny; } else { printf("Invalid sockd/direct/deny field at line %d in file %s\n", linenum, filename); continue; } userlist = (char *)0; if (strncmp(*(argv +next_arg), "*=", 2) == 0) { if (*(argv +next_arg) +2) userlist = *(argv +next_arg) + 2; next_arg++; } if(argc <= next_arg+1) { printf("Invalid entry at line %d in file %s\n", linenum, filename); continue; } if (SOCKS_getaddr(*(argv +next_arg++), &daddr) == -1){ printf("illegal destination field at line %d in file %s\n", linenum, filename); continue; } if (SOCKS_getquad(*(argv +next_arg++), &dmask) == -1) { printf("illegal destination mask at line %d in file %s\n", linenum, filename); continue; } if (argc > next_arg + 1) { if (!strcmp(*(argv +next_arg), "eq")) tst = e_eq; else if (!strcmp(*(argv +next_arg), "neq")) tst = e_neq; else if (!strcmp(*(argv +next_arg), "lt")) tst = e_lt; else if (!strcmp(*(argv +next_arg), "gt")) tst = e_gt; else if (!strcmp(*(argv +next_arg), "le")) tst = e_le; else if (!strcmp(*(argv +next_arg), "ge")) tst = e_ge; else { printf("Invalid comparison at line %d in file %s\n", linenum, filename); continue; } if (((p = SOCKS_getport(*(argv +next_arg+1))) < 0) || (p >= (1L << 16))) { printf("Invalid port number at line %d in file %s\n", linenum, filename); continue; } else { dport = p; } } else { tst = e_nil; dport = 0; } #ifdef DEBUG { char msg[1024]; if (userlist) sprintf(msg,"%s %s 0x%08x 0x%08x %s %u", *argv, userlist, daddr.s_addr, dmask, tst == e_eq ? "==" : tst == e_neq ? "!=" : tst == e_lt ? "<" : tst == e_gt ? ">" : tst == e_le ? "<=" : tst == e_ge ? ">=" : "NIL", dport); else sprintf(msg,"%s 0x%08x 0x%08x %s %u", *argv, daddr.s_addr, dmask, tst == e_eq ? "==" : tst == e_neq ? "!=" : tst == e_lt ? "<" : tst == e_gt ? ">" : tst == e_le ? "<=" : tst == e_ge ? ">=" : "NIL", dport); printf("%s\n", msg); } #endif /* we have a parsed line. cache it. */ if (!confNtries || confPtr - *confNtries >= Ntries) { /* some systems can't be counted on to handle * realloc(NULL, ...) correctly. */ if (confNtries == NULL) confNtries = (struct config **) malloc(CONF_INCR *sizeof(struct config **)); else confNtries = (struct config **) realloc(confNtries, (Ntries +CONF_INCR) *sizeof(struct config)); } *(confNtries +Ntries) = (struct config *) malloc(sizeof(struct config)); confPtr = *(confNtries +Ntries); Ntries++; confPtr->action = action; confPtr->tst = tst; if (server_list) { confPtr->serverlist = (char *)malloc(strlen(server_list) +1); strcpy(confPtr->serverlist, server_list); } else confPtr->serverlist = NULL; if (userlist) { confPtr->userlist = (char *)malloc(strlen(userlist) +1); strcpy(confPtr->userlist, userlist); } else confPtr->userlist = NULL; confPtr->daddr.s_addr = daddr.s_addr; confPtr->dmask.s_addr = dmask.s_addr; if (cmdp) { confPtr->cmdp = (char *) malloc(strlen(cmdp) +1); strcpy(confPtr->cmdp, cmdp); } else confPtr->cmdp = NULL; confPtr->dport = dport; } fclose(fd); if (confNtries == NULL) { printf("No valid entires in file %s\n", filename); return(-1); } return 0; } int SOCKS_init( void ) { PSZ var ; struct hostent *host ; socks_server.s_addr = 0 ; socks_ns.s_addr = 0 ; /* get the resolv info */ res_init() ; server_count = _res.nscount ; default_server.s_addr = _res.nsaddr_list[0].sin_addr.s_addr ; /* get the username if any */ if ( !DosScanEnv("USER",&var) ) username = strdup(var); else username = "os2user"; /* get the SOCKS server if any */ if ( !DosScanEnv("SOCKS_SERVER",&var) ) { socks_def_server = strdup( var ) ; host = gethostbyname( var ) ; if ( host ) { memcpy( &socks_server, host->h_addr_list[0], sizeof(socks_server)); } else { socks_server.s_addr = inet_addr(var); } } /* get the SOCKS Name Server if any */ if ( socks_server.s_addr && (socks_server.s_addr != -1) ) { usesocks = TRUE ; if ( !DosScanEnv("SOCKS_NS",&var) ) { host = gethostbyname( var ) ; if ( host ) { memcpy( &socks_ns.s_addr, host->h_addr_list[0], sizeof(socks_ns.s_addr)) ; } else { socks_ns.s_addr = inet_addr( var ) ; } /* now install this name server as the default */ if ( socks_ns.s_addr && ( socks_ns.s_addr != -1 ) ) { _res.nsaddr_list[0].sin_addr.s_addr = socks_ns.s_addr ; _res.nscount = 1 ; usesocksns = TRUE ; } } } /* read socks.conf file */ if ( usesocks ) { printf( "C-Kermit is SOCKS 4.2 enabled\n" ) ; SOCKS_read_config() ; } return( usesocks ) ; } enum socks_action SOCKS_validate( struct sockaddr_in * dest ) { int i = 0 ; enum socks_action action = sockd ; for ( i = 0 ; i < Ntries ; i++ ) { if ( ( confNtries[i]->daddr.s_addr & confNtries[i]->dmask.s_addr ) == ( dest->sin_addr.s_addr & confNtries[i]->dmask.s_addr ) ) if ( confNtries[i]->tst == e_nil ) { action = confNtries[i]->action ; break; } if ((confNtries[i]->tst == e_eq) && (dest->sin_port == confNtries[i]->dport)){ action = confNtries[i]->action ; break; } if ((confNtries[i]->tst == e_neq) && (dest->sin_port != confNtries[i]->dport)){ action = confNtries[i]->action ; break; } if ((confNtries[i]->tst == e_lt) && (dest->sin_port < confNtries[i]->dport)){ action = confNtries[i]->action ; break; } if ((confNtries[i]->tst == e_gt) && (dest->sin_port > confNtries[i]->dport)){ action = confNtries[i]->action ; break; } if ((confNtries[i]->tst == e_le) && (dest->sin_port <= confNtries[i]->dport)){ action = confNtries[i]->action ; break; } if ((confNtries[i]->tst == e_ge) && (dest->sin_port >= confNtries[i]->dport)){ action = confNtries[i]->action ; break; } } return action ; } #endif /* SOCKS_ENABLED */ int ENTRY ck_sockinit(void) { #ifdef SOCKS_ENABLED SOCKS_init() ; #endif /* SOCKS_ENABLED */ return sock_init(); } /* socket calls */ int ENTRY ck_connect(int socket, struct ck_sockaddr *name, int namelen) { struct sockaddr_in addr; int rc ; #ifdef SOCKS_ENABLED char request[100]; char *next ; int packetsize ; int sockret ; if (usesocks) { memset(&addr, 0, sizeof(addr)); addr.sin_port = ((struct ck_sockaddr_in *) name) ->sin_port; addr.sin_family = ((struct ck_sockaddr_in *) name) ->sin_family; addr.sin_addr.s_addr = ((struct ck_sockaddr_in *) name) ->sin_addr.s_addr; /* Check local cached values from SOCKS.CONF */ switch ( SOCKS_validate( &addr ) ) { case deny: return -1 ; case direct: break; case sockd: addr.sin_family = AF_INET ; addr.sin_addr = socks_server ; addr.sin_port = htons(1080) ; /* The SOCKS Service */ /* Connect to the SOCKS Server */ if ( connect(socket, (struct sockaddr *) &addr, sizeof(addr)) < 0 ) { return -1 ; } /* Build the request packet */ next = request; *next++ = SOCKS_VERSION ; *next++ = SOCKS_CONNECT ; memcpy(next, &((struct ck_sockaddr_in *) name)->sin_port, sizeof(((struct ck_sockaddr_in *) name)->sin_port) ) ; next += sizeof(((struct ck_sockaddr_in *) name)->sin_port) ; memcpy(next, &((struct ck_sockaddr_in *) name)->sin_addr, sizeof(((struct ck_sockaddr_in *) name)->sin_addr) ) ; next += sizeof(((struct ck_sockaddr_in *) name)->sin_addr) ; strcpy(next,username) ; next += strlen( username ) + 1; /* Send the request */ rc = send(socket, request, next - request, 0) ; /* Now retrieve the response */ packetsize = 8 ; /* VN 1, CD 1, PORT 2, IP 4 */ next = request ; while ( rc > 0 && packetsize > (next - request) ) { rc = recv( socket, next, packetsize - (next - request), 0 ) ; next += rc ; } sockret = request[1] ; /* Get the SOCKS return value */ return ( sockret == SOCKS_RESULT ? 0 : -1 ) ; } } /* Direct connection */ #endif memset(&addr, 0, sizeof(addr)); addr.sin_port = ((struct ck_sockaddr_in *) name) ->sin_port; addr.sin_family = ((struct ck_sockaddr_in *) name) ->sin_family; addr.sin_addr.s_addr = ((struct ck_sockaddr_in *) name) ->sin_addr.s_addr; rc = connect(socket, (struct sockaddr *) &addr, sizeof(addr)); return rc ; } int ENTRY ck_bind(int socket, struct ck_sockaddr *name, int namelen) { struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_port = ((struct ck_sockaddr_in *) name) -> sin_port; addr.sin_family = ((struct ck_sockaddr_in *) name) -> sin_family; addr.sin_addr.s_addr = ((struct ck_sockaddr_in *) name) -> sin_addr.s_addr; return bind(socket, (struct sockaddr *) &addr, sizeof(addr)); } int ENTRY ck_listen(int socket, int backlog) { return listen( socket, backlog ); } int ENTRY ck_accept(int socket, struct ck_sockaddr *name, int * namelen) { struct sockaddr_in addr; #ifdef __SOCKET_32H int len ; #else short len ; #endif int rc = 0 ; memset(&addr, 0, sizeof(addr)); addr.sin_port = ((struct ck_sockaddr_in *) name) -> sin_port; addr.sin_family = ((struct ck_sockaddr_in *) name) -> sin_family; addr.sin_addr.s_addr = ((struct ck_sockaddr_in *) name) -> sin_addr.s_addr; len = sizeof(addr) ; rc = accept(socket, (struct sockaddr *) &addr, &len); ((struct ck_sockaddr_in *) name) -> sin_port = addr.sin_port ; ((struct ck_sockaddr_in *) name) -> sin_family = addr.sin_family ; ((struct ck_sockaddr_in *) name) -> sin_addr.s_addr = addr.sin_addr.s_addr; *namelen = len ; return rc ; } int ENTRY ck_ioctl(int socket, int cmd, long *data) { switch (cmd) { case CK_FIONREAD: cmd = FIONREAD; break; case CK_FIONBIO: cmd = FIONBIO; break; case CK_SIOCATMARK: cmd = SIOCATMARK; break; default: return -1; } return ioctl(socket, cmd, (char *)data, 4); } int ENTRY ck_recv(int socket, char *buffer, int length, int flags) { return recv(socket, buffer, length, flags); } int ENTRY ck_select(int *fds, int read, int write, int except, long timeout) { /* Warning: if the called select is 16-bit but the calling code is * 32-bit, only one fd can be pointed to by fds! However, calling * with one "read" socket is the only use of select() in * C-Kermit. Might change in the future, so this must be checked. */ int rc ; ULONG nestings ; /* MustComplete sections */ #ifdef BSD_SELECT fd_set rfds; struct timeval tv; int socket = *fds; #endif if ((read + write + except) != 1) return -1; #ifdef BSD_SELECT FD_ZERO(&rfds); FD_SET(socket, &rfds); tv.tv_sec = tv.tv_usec = 0L; if (timeout < 1000) tv.tv_usec = (long) timeout * 1000L; else tv.tv_sec = timeout / 1000L; rc = (read ? select(FD_SETSIZE, &rfds, NULL, NULL, &tv) : 1) && (write ? select(FD_SETSIZE, NULL, &rfds, NULL, &tv) : 1) && (except ? select(FD_SETSIZE, NULL, NULL, &rfds, &tv) : 1) && FD_ISSET(socket, &rfds); #else rc = select(FDPTR fds, read, write, except, timeout); #endif return rc ; } int ENTRY ck_send(int socket, char *buffer, int length, int flags) { return send(socket, buffer, length, flags); } int ENTRY ck_setsockopt(int socket, int level, int optname, char *optvalue, int optlength) { if (level == CK_SOL_SOCKET) level = SOL_SOCKET; else return -1; switch ( optname ) { case CK_SO_OOBINLINE: optname = SO_OOBINLINE ; break; case CK_SO_REUSEADDR: optname = SO_REUSEADDR ; break; case CK_SO_LINGER: optname = SO_LINGER ; break; case CK_SO_KEEPALIVE: optname = SO_KEEPALIVE ; break; case CK_SO_SNDBUF: optname = SO_SNDBUF ; break; case CK_SO_RCVBUF: optname = SO_RCVBUF ; break; default: return -1; } return setsockopt(socket, level, optname, optvalue, optlength); } int ENTRY ck_getsockopt(int socket, int level, int optname, char *optvalue, int * optlength) { #ifdef __SOCKET_32H int len = *optlength; #else short len = (short) *optlength ; #endif int rc = 0 ; if (level == CK_SOL_SOCKET) level = SOL_SOCKET; else return -1; switch ( optname ) { case CK_SO_OOBINLINE: optname = SO_OOBINLINE ; break; case CK_SO_REUSEADDR: optname = SO_REUSEADDR ; break; case CK_SO_LINGER: optname = SO_LINGER ; break; case CK_SO_KEEPALIVE: optname = SO_KEEPALIVE ; break; case CK_SO_SNDBUF: optname = SO_SNDBUF ; break; case CK_SO_RCVBUF: optname = SO_RCVBUF ; break; default: return -1; } rc = getsockopt(socket, level, optname, optvalue, &len); *optlength = len ; return rc; } int ENTRY ck_socket(int domain, int type, int protocol) { if (domain == CK_AF_INET) domain = AF_INET; else return -1; if (type == CK_SOCK_STREAM) type = SOCK_STREAM; else return -1; if (protocol != 0) return -1; return socket(domain, type, protocol); } int ENTRY ck_soclose(int socket) { return soclose(socket); } /* utility calls */ struct ck_hostent * ENTRY ck_gethostbyname(char *name) { struct hostent *host = gethostbyname(name); static char * h_addr_list[64] ; static struct ck_hostent ckhost = {NULL,NULL,0,0,h_addr_list}; int i = 0 ; #ifdef SOCKS_ENABLED if ( (host == NULL) && usesocksns ) { _res.nscount = server_count ; _res.nsaddr_list[0].sin_addr.s_addr = default_server.s_addr ; host = gethostbyname(name) ; _res.nscount = 1 ; _res.nsaddr_list[0].sin_addr.s_addr = socks_ns.s_addr ; } #endif /* SOCKS_ENABLED */ if (host == NULL) return NULL; ckhost.h_name = host -> h_name; ckhost.h_aliases = NULL; ckhost.h_addrtype = host -> h_addrtype; ckhost.h_length = host -> h_length; while( host->h_addr_list[i] != NULL && i < 63) { ckhost.h_addr_list[i] = host->h_addr_list[i] ; i++ ; } ckhost.h_addr_list[63] = NULL ; return &ckhost; } struct ck_servent * ENTRY ck_getservbyname(char *name, char *protocol) { PACKED struct servent *serv = getservbyname(name, protocol); static struct ck_servent ckserv; if (serv == NULL) return NULL; ckserv.s_name = serv -> s_name; ckserv.s_aliases = NULL; ckserv.s_port = serv -> s_port; ckserv.s_proto = serv -> s_proto; return &ckserv; } struct ck_hostent * ENTRY ck_gethostbyaddr(char *addr, int len, int net) { struct hostent *host = gethostbyaddr(addr, len, net); static char * h_addr_list[64] ; static struct ck_hostent ckhost = {NULL,NULL,0,0,h_addr_list}; int i = 0 ; #ifdef SOCKS_ENABLED if ( (host == NULL) && usesocksns ) { _res.nscount = server_count ; _res.nsaddr_list[0].sin_addr.s_addr = default_server.s_addr ; host = gethostbyaddr(addr, len, net) ; _res.nscount = 1 ; _res.nsaddr_list[0].sin_addr.s_addr = socks_ns.s_addr ; } #endif /* SOCKS_ENABLED */ if (host == NULL) return NULL; ckhost.h_name = host -> h_name; ckhost.h_aliases = NULL; ckhost.h_addrtype = host -> h_addrtype; ckhost.h_length = host -> h_length; while( host->h_addr_list[i] != NULL && i < 63) { ckhost.h_addr_list[i] = host->h_addr_list[i] ; i++ ; } ckhost.h_addr_list[63] = NULL ; return &ckhost; } struct ck_servent * ENTRY ck_getservbyport(int port, char * name) { PACKED struct servent *serv = getservbyport(port, name); static struct ck_servent ckserv; if (serv == NULL) return NULL; ckserv.s_name = serv -> s_name; ckserv.s_aliases = NULL; ckserv.s_port = serv -> s_port; ckserv.s_proto = serv -> s_proto; return &ckserv; } unsigned long ENTRY ck_inet_addr(char *cp) { return inet_addr(cp); } char * ENTRY ck_inet_ntoa(struct ck_in_addr in) { struct in_addr addr; addr.s_addr = in.s_addr; return inet_ntoa(addr); } int ENTRY ck_getpeername( int socket, struct ck_sockaddr * name, int * namelen ) { #ifdef __SOCKET_32H int len = *namelen; #else short len = (short) *namelen ; #endif int rc = 0 ; rc = getpeername( socket, (struct sockaddr *) name, &len ) ; *namelen = len ; return rc; } int ENTRY ck_getsockname( int socket, struct ck_sockaddr * name, int * namelen ) { #ifdef __SOCKET_32H int len = *namelen; #else short len = (short) *namelen ; #endif int rc = 0 ; rc = getsockname( socket, (struct sockaddr *) name, &len ) ; *namelen = len ; return rc; } #ifdef __SOCKET_32H int ENTRY ck_addsockettolist( int socket ) { int rc = 0 ; rc = addsockettolist( socket ) ; return rc; } #endif int ENTRY ck_gethostname( char * buf, int len ) { #ifdef __SOCKET_32H int rc = 0 ; rc = gethostname( buf, len ) ; return rc; #else if (buf) *buf = '\0'; return(-1); #endif } /* end of ckotcp.c */ .