"Fossies" - the Fresh Open Source Software Archive

Member "tlswrap-1.04/network.c" (25 Nov 2006, 10742 Bytes) of package /linux/privat/old/tlswrap-1.04.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "network.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Copyright (c) 2002-2006 Tomas Svensson <ts@codepix.com>
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 3. The name of the author may not be used to endorse or promote products
   14  *    derived from this software without specific prior written permission.
   15  *
   16  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
   17  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
   18  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
   19  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
   22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
   24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
   25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   26  */
   27 
   28 #include "conf.h"
   29 
   30 #define _POSIX_PII_SOCKET /* for Tru64 UNIX 5.1 */
   31 
   32 #include <sys/types.h>
   33 #ifdef WIN32
   34 #include <Winsock2.h>
   35 #include <process.h>
   36 #define snprintf _snprintf
   37 #define strcasecmp _stricmp
   38 #define strncasecmp _strnicmp
   39 typedef   __int32 ssize_t;
   40 typedef int socklen_t;
   41 #define ECONNREFUSED WSAECONNREFUSED
   42 #define EINPROGRESS WSAEWOULDBLOCK
   43 #else
   44 #include <sys/socket.h>
   45 #include <netdb.h>
   46 #include <sys/uio.h>
   47 #include <unistd.h>
   48 #include <netinet/in.h>
   49 #include <arpa/inet.h>
   50 #include <netinet/in_systm.h>
   51 #include <netinet/ip.h>
   52 #endif
   53 #include <fcntl.h>
   54 #include <sys/types.h>
   55 
   56 
   57 #include <string.h>
   58 #include <stdio.h>
   59 #include <stdlib.h>
   60 #include <errno.h>
   61 
   62 extern int debug;
   63 
   64 #include "tlswrap.h"
   65 #include "network.h"
   66 #include "misc.h"
   67 
   68 #ifdef WIN32
   69 
   70 int write(SOCKET s, void *buf, int len) {
   71     return send(s, (char*)buf, len, 0);
   72 }
   73 
   74 int read(SOCKET s, void *buf, int len) {
   75     return recv(s, (char*)buf, len, 0);
   76 }
   77 
   78 #endif
   79 
   80 void setup_connect_1(struct user_data *ud, int index, char *serv,
   81              char *port, int write_pipe) {
   82     struct dns_msg dns;
   83 
   84     dns.ud = index;
   85     strlcpy(dns.port, port, sizeof(dns.port));
   86     strlcpy(dns.hostname, serv, sizeof(dns.hostname));
   87     if (write(write_pipe, &dns, sizeof(dns)) != sizeof(dns)) {
   88             fprintf(stderr, "Error: Too many hostname lookups\n");
   89             return;
   90     }
   91     ud->connected = CONN_DNS;
   92     if (debug)
   93         printf("Resolving %s on %d...\n",serv, index);
   94 }
   95 
   96 void
   97 setup_connect_2(struct user_data *ud, struct dns_msg *dns, int data)
   98 {
   99     char    *ep;
  100     int     result, tos = 0;
  101 
  102     if (strlen(dns->hostname) == 0) {
  103     if (debug)
  104             printf("Error: Could not resolve hostname\n");
  105         if (!(data)) {
  106             ud->connected = CONN_NO;
  107             print_to_ud(ud, "530 Could not resolve hostname.\r\n");
  108         }
  109         return;
  110     }
  111     ud->ssl_data = NULL; /* Could be data left from other session, which would crash dataclose */
  112     ud->rport = strtol(dns->port, &ep, 10);
  113         if (debug)
  114             printf("Connecting to %s on port %s, please wait...\n", dns->hostname, dns->port);
  115 
  116         if (data) {
  117             ud->serv_data_fd = setup_connect(dns->hostname, dns->port, &ud->lport, &result);
  118 #ifndef WIN32
  119             tos = IPTOS_THROUGHPUT;
  120             if ((setsockopt(ud->serv_data_fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) == -1) && debug)
  121                 printf("Unable to set TOS=Throughput for data channel.\n");
  122 #endif
  123         } else {
  124             ud->serv_fd = setup_connect(dns->hostname, dns->port,
  125             &ud->lport, &result);
  126 #ifndef WIN32
  127             tos = IPTOS_THROUGHPUT;
  128             if ((setsockopt(ud->serv_fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) == -1) && debug)
  129                 printf("Unable to set TOS=Lowdelay for control channel.\n");
  130 #endif
  131         }
  132 
  133     if (result == 0) {
  134             if (data) {
  135             if (debug)
  136                 printf("data connected\n");
  137             ud->data_connected = CONN_YES;
  138             } else {
  139                 ud->connected = CONN_YES;
  140                 ud->serv_status = SERV_CONN;
  141             }
  142     } else if (result == 2) {
  143             print_to_ud(ud, "Can't find hostname, should not happen!");
  144             ud->connected = CONN_CMD;
  145     } else if (result == 3) {
  146         print_to_ud(ud,"421 Connection refused by server.\r\n");
  147         user_close(ud);
  148     } else if (result == 4) {
  149         print_to_ud(ud,"421 Software caused connection abort.\r\n");
  150         user_close(ud);
  151     } else {
  152         if (debug)
  153             printf("connection in progress\n");
  154         if (!data)
  155             ud->connected = CONN_IN_PROG;  
  156         else
  157             ud->data_connected = CONN_IN_PROG;
  158     } 
  159 }
  160 
  161 #ifdef WIN32
  162 SOCKET
  163 #else
  164 int
  165 #endif
  166 setup_connect(const char *host, const char *port,
  167     unsigned int *lport, int *result)
  168 {
  169 
  170     int  flags,  sockopt;
  171     char *ep;
  172 
  173     struct sockaddr_in sin, *sin2;
  174     unsigned short  nport;
  175     struct sockaddr sa;
  176     socklen_t sa_len;
  177 #ifdef WIN32
  178   SOCKET conn_fd;
  179     unsigned long nonblockopt = 1;
  180 #else
  181   int conn_fd;
  182 #endif
  183  
  184     conn_fd = socket(PF_INET, SOCK_STREAM, 0);
  185 
  186 #ifdef WIN32
  187     if (conn_fd == INVALID_SOCKET)
  188 #else
  189     if (conn_fd < 0)
  190 #endif
  191         sys_err("setup_connect_socket");
  192 
  193 #ifdef WIN32
  194     ioctlsocket(conn_fd, FIONBIO, &nonblockopt);
  195 #else
  196     flags = fcntl(conn_fd,F_GETFL);
  197     fcntl(conn_fd, F_SETFL, flags | O_NONBLOCK);
  198 #endif
  199 
  200     sockopt = 1;
  201 #ifdef WIN32
  202     if (setsockopt(conn_fd, SOL_SOCKET, SO_KEEPALIVE, (char*)&sockopt, sizeof(sockopt)))
  203             sys_err("setsockopt-keepalive");
  204 #else
  205     if (setsockopt(conn_fd, SOL_SOCKET, SO_KEEPALIVE, &sockopt, sizeof(sockopt)))
  206             sys_err("setsockopt-keepalive");
  207 #endif
  208 
  209     memset(&sa,0,sizeof(sa));
  210     sa.sa_family = PF_INET;
  211     if (bind(conn_fd, &sa, sizeof(sa)) < 0)
  212         perror("bind");
  213 
  214     sa_len = sizeof(sa);
  215     if (getsockname(conn_fd, &sa, &sa_len))
  216         sys_err("getsockname");
  217 
  218 
  219     memset(&sin, 0, sizeof(sin));
  220     sin2 = (struct sockaddr_in *)&sa;
  221     if (debug)
  222         printf("host = %s, port = %s\n", host, port);
  223 #if defined(HAVE_INET_ATON) || defined(HAVE_LIBRESOLV)
  224     if (inet_aton(host, &sin.sin_addr) != 1)
  225         sys_err(host);
  226 #else
  227     if ( (sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE)
  228         sys_err("inet_addr");
  229 #endif
  230     *lport = ntohs(sin2->sin_port);
  231     nport = (unsigned short)strtol(port, &ep, 10);
  232     sin.sin_port = htons(nport);
  233     sin.sin_family = PF_INET;
  234     if (connect(conn_fd, (struct sockaddr *)&sin, sizeof(sin)) != 0) {
  235 #ifdef WIN32
  236         errno = WSAGetLastError();
  237 #endif
  238             if (errno == ECONNREFUSED) {
  239                 *result = 3;
  240 #ifdef WIN32
  241             } else if (errno == WSAECONNABORTED) { // i.e. blocked by firewall or such
  242                 *result = 4; 
  243 #endif
  244             } else {
  245                 if (errno != EINPROGRESS) {
  246                     if (debug) printf("socket error is %d", errno);
  247                     sys_err("connect");
  248                 }
  249                 *result = 1; /* Nonblocking operation */
  250             }
  251     } else
  252         *result = 0; /* Connected */
  253 
  254     return conn_fd;
  255 }
  256 
  257 #ifdef WIN32
  258 
  259 extern int in_service;
  260 
  261 void dns_helper(void *arg) { // __cdecl 
  262     SOCKET *sarg = (SOCKET*)arg;
  263     SOCKET read_fd = sarg[0];
  264     SOCKET write_fd = sarg[1];  
  265 #else
  266 void dns_helper(int read_fd, int write_fd) {
  267 #endif
  268     struct dns_msg dns;
  269     ssize_t bytes;
  270 
  271     struct sockaddr_in saddr;
  272     struct hostent *hptr;
  273 
  274 #ifdef HAVE_SETPROCTITLE
  275     char sp[40];
  276     unsigned int serv = 0;
  277 #endif
  278     for(;;) {
  279 #ifdef HAVE_SETPROCTITLE
  280             snprintf(sp, sizeof(sp), "tlswrap-dns (serviced %u reqs)",
  281             serv++);
  282             setproctitle(sp);
  283 #endif
  284             bytes = read(read_fd, &dns, sizeof(dns));
  285             if (bytes == 0) {
  286                 if (debug)
  287                     printf("Parent died, exiting...\n");
  288 #ifdef WIN32
  289 //              if  (in_service)
  290 //                  closesocket(pipe1[1]);
  291 //x         closesocket(pipe1[0]);
  292 //x         closesocket(pipe2[0]);
  293 //x         closesocket(pipe2[1]);
  294                 closesocket(write_fd);
  295                 _endthread();
  296 //              else
  297 #endif
  298                     exit(0);
  299             }
  300 
  301         memset(&saddr, 0, sizeof(saddr));
  302         if ((hptr = gethostbyname(dns.hostname)) == NULL)
  303             dns.hostname[0] = '\0';
  304         else    {
  305             memcpy(&saddr.sin_addr, hptr->h_addr,
  306                 sizeof(saddr.sin_addr));
  307             strlcpy(dns.hostname, inet_ntoa(saddr.sin_addr),
  308                 sizeof(dns.hostname));
  309         }
  310             bytes = write(write_fd, &dns, sizeof(dns));
  311     }
  312   
  313 }
  314 
  315 #ifdef WIN32
  316 SOCKET
  317 #else
  318 int
  319 #endif
  320 setup_listen(int max_users, const char *host, char *port, int portlen)
  321 {
  322     /* IP V4 only version */
  323 
  324     /* Returns a non-blocking listening socket on the specified port.
  325      Listen backlog is set to max_users. if portlen != 0 then blah */
  326        
  327     int flags, sockopt;
  328     unsigned short rport;
  329     socklen_t slen;
  330 
  331     struct sockaddr_in sin;
  332     char *ep;
  333     struct hostent *hptr;
  334 #ifdef WIN32
  335     unsigned long nonblockopt = 1;
  336     SOCKET listen_socket;
  337 #else
  338   int listen_socket;
  339 #endif
  340 
  341             
  342     rport = (unsigned short)strtol(port, &ep, 10);
  343 
  344     memset(&sin, 0, sizeof(sin));
  345     sin.sin_family = PF_INET;
  346     sin.sin_port = htons(rport); 
  347     
  348     if (host == NULL)
  349         sin.sin_addr.s_addr = htonl(INADDR_ANY);
  350     else {
  351         if ((hptr = gethostbyname(host)) == NULL) {
  352             printf("hostname = %s\n", host);
  353             sys_err("can't resolve specified local hostname");
  354         } else
  355                 memcpy(&sin.sin_addr, hptr->h_addr, sizeof(sin.sin_addr));
  356     }
  357     listen_socket = socket(PF_INET, SOCK_STREAM, 0);
  358 
  359 #ifdef WIN32
  360     if (listen_socket == INVALID_SOCKET)
  361 #else
  362   if (listen_socket < 0) 
  363 #endif
  364         sys_err("socket_listen_ipv4");
  365 
  366     sockopt = 1;
  367 #ifdef WIN32
  368     if (setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&sockopt,
  369         sizeof(sockopt)))
  370         sys_err("setsockopt-reuseaddr");
  371 #else
  372     if (setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &sockopt,
  373         sizeof(sockopt)))
  374         sys_err("setsockopt-reuseaddr");
  375 #endif
  376 
  377     if (bind(listen_socket, (struct sockaddr *)&sin, sizeof(sin)))
  378         sys_err("bind");
  379 
  380     slen = sizeof(struct sockaddr_in);
  381         if (getsockname(listen_socket, (struct sockaddr*)&sin, &slen) < 0)
  382         sys_err("getsockname");
  383 
  384     if (listen(listen_socket, max_users))
  385         sys_err("listen");
  386 
  387 
  388 #ifdef WIN32
  389     ioctlsocket(listen_socket, FIONBIO, &nonblockopt);
  390 #else
  391     flags = fcntl(listen_socket, F_GETFL);
  392     fcntl(listen_socket, F_SETFL, flags | O_NONBLOCK);
  393 #endif
  394     if (portlen > 0)
  395         snprintf(port, portlen, "%u", ntohs(sin.sin_port));
  396 
  397     return listen_socket;
  398 }
  399 
  400 
  401 int get_local_ip(int fd, char *ip, int iplen)
  402 {
  403     socklen_t slen;
  404     struct sockaddr_in sin;
  405 
  406     slen = sizeof(struct sockaddr_in); 
  407     if (getsockname(fd, (struct sockaddr*)&sin, &slen) < 0)
  408         sys_err("getsockname");
  409 
  410     strlcpy(ip, inet_ntoa(sin.sin_addr), iplen);
  411     return 0;
  412 }
  413 
  414 int get_remote_ip(int fd, char *ip, int iplen)
  415 {
  416     socklen_t slen;
  417     struct sockaddr_in sin;
  418 
  419     slen = sizeof(struct sockaddr_in); 
  420     if (getpeername(fd, (struct sockaddr*)&sin, &slen) < 0)
  421         sys_err("getsockname");
  422 
  423     strlcpy(ip, inet_ntoa(sin.sin_addr), iplen);
  424     return 0;
  425 }