/[cvs]/eggdrop1.8/src/net.c
ViewVC logotype

Diff of /eggdrop1.8/src/net.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph | View Patch Patch

revision 1.1.1.1 by simple, Mon Jul 26 21:11:06 2010 UTC revision 1.11 by pseudo, Tue Feb 15 23:55:17 2011 UTC
# Line 44  Line 44 
44  #endif  #endif
45  #include <setjmp.h>  #include <setjmp.h>
46    
47    #ifdef TLS
48    #  include <openssl/err.h>
49    #endif
50    
51  #ifndef HAVE_GETDTABLESIZE  #ifndef HAVE_GETDTABLESIZE
52  #  ifdef FD_SETSIZE  #  ifdef FD_SETSIZE
53  #    define getdtablesize() FD_SETSIZE  #    define getdtablesize() FD_SETSIZE
# Line 58  extern unsigned long otraffic_irc_today, Line 62  extern unsigned long otraffic_irc_today,
62                       otraffic_filesys_today, otraffic_trans_today,                       otraffic_filesys_today, otraffic_trans_today,
63                       otraffic_unknown_today;                       otraffic_unknown_today;
64    
65  char hostname[121] = "";      /* Hostname can be specified in the config file.*/  char natip[121] = "";         /* Public IPv4 to report for systems behind NAT */
66  char myip[121] = "";          /* IP can be specified in the config file.      */  char listen_ip[121] = "";     /* IP (or hostname) for listening sockets       */
67    char vhost[121] = "";         /* IPv4 vhost for outgoing connections          */
68    #ifdef IPV6
69    char vhost6[121] = "";        /* IPv6 vhost for outgoing connections          */
70    int pref_af = 0;              /* Prefer IPv6 over IPv4?                       */
71    #endif
72  char firewall[121] = "";      /* Socks server for firewall.                   */  char firewall[121] = "";      /* Socks server for firewall.                   */
73  int firewallport = 1080;      /* Default port of socks 4/5 firewalls.         */  int firewallport = 1080;      /* Default port of socks 4/5 firewalls.         */
74  char botuser[21] = "eggdrop"; /* Username of the user running the bot.        */  char botuser[21] = "eggdrop"; /* Username of the user running the bot.        */
# Line 103  int expmem_net() Line 112  int expmem_net()
112    return tot;    return tot;
113  }  }
114    
115  /* Get my ip number  /* Extract the IP address from a sockaddr struct and convert it
116     * to presentation format.
117     */
118    char *iptostr(struct sockaddr *sa)
119    {
120    #ifdef IPV6
121      static char s[INET6_ADDRSTRLEN] = "";
122      if (sa->sa_family == AF_INET6)
123        inet_ntop(AF_INET6, &((struct sockaddr_in6 *)sa)->sin6_addr,
124                  s, sizeof s);
125      else
126    #else
127      static char s[sizeof "255.255.255.255"] = "";
128    #endif
129        inet_ntop(AF_INET, &((struct sockaddr_in *)sa)->sin_addr.s_addr, s,
130                  sizeof s);
131      return s;
132    }
133    
134    /* Fills in a sockname struct with the given server and port. If the string
135     * pointed by src isn't an IP address and allowres is not null, the function
136     * will assume it's a hostname and will attempt to resolve it. This is
137     * convenient, but you should use the async dns functions where possible, to
138     * avoid blocking the bot while the lookup is performed.
139   */   */
140  IP getmyip()  int setsockname(sockname_t *addr, char *src, int port, int allowres)
141  {  {
142    struct hostent *hp;    struct hostent *hp;
143    char s[121];    int af = AF_UNSPEC;
144    IP ip;  #ifdef IPV6
145    struct in_addr *in;    int pref;
146    if (myip[0]) {  
147      if ((myip[strlen(myip) - 1] >= '0') && (myip[strlen(myip) - 1] <= '9'))    /* Clean start */
148        return (IP) inet_addr(myip);    egg_bzero(addr, sizeof(sockname_t));
149    }    af = pref = pref_af ? AF_INET6 : AF_INET;
150    /* Also could be pre-defined */    if (pref == AF_INET) {
151    if (hostname[0])      if (!egg_inet_aton(src, &addr->addr.s4.sin_addr))
152      hp = gethostbyname(hostname);        af = AF_INET6;
153    else {    } else {
154      gethostname(s, 120);      if (inet_pton(af, src, &addr->addr.s6.sin6_addr) != 1)
155      hp = gethostbyname(s);        af = AF_INET;
156    }    }
157    if (hp == NULL)    if (af != pref)
158      fatal("Hostname self-lookup failed. Please set 'my-ip' in the config "      if (((af == AF_INET6) &&
159            "file.", 0);           (inet_pton(af, src, &addr->addr.s6.sin6_addr) != 1)) ||
160    in = (struct in_addr *) (hp->h_addr_list[0]);          ((af == AF_INET)  &&
161    ip = (IP) (in->s_addr);           !egg_inet_aton(src, &addr->addr.s4.sin_addr)))
162    return ip;        af = AF_UNSPEC;
163  }  
164      if (af == AF_UNSPEC && allowres) {
165  void neterror(char *s)      /* src is a hostname. Attempt to resolve it.. */
166  {      if (!sigsetjmp(alarmret, 1)) {
167    switch (errno) {        alarm(resolve_timeout);
168    case EADDRINUSE:        hp = gethostbyname2(src, pref_af ? AF_INET6 : AF_INET);
169      strcpy(s, "Address already in use");        if (!hp)
170      break;          hp = gethostbyname2(src, pref_af ? AF_INET : AF_INET6);
171    case EADDRNOTAVAIL:        alarm(0);
172      strcpy(s, "Cannot assign requested address");      } else
173      break;        hp = NULL;
174    case EAFNOSUPPORT:      if (hp) {
175      strcpy(s, "Address family not supported");        if (hp->h_addrtype == AF_INET)
176      break;          egg_memcpy(&addr->addr.s4.sin_addr, hp->h_addr, hp->h_length);
177    case EALREADY:        else
178      strcpy(s, "Socket already in use");          egg_memcpy(&addr->addr.s6.sin6_addr, hp->h_addr, hp->h_length);
179      break;        af = hp->h_addrtype;
180    case EBADF:      }
181      strcpy(s, "Socket descriptor is bad");    }
182      break;    
183    case ECONNREFUSED:    addr->family = (af == AF_UNSPEC) ? pref : af;
184      strcpy(s, "Connection refused");    addr->addr.sa.sa_family = addr->family;
185      break;    if (addr->family == AF_INET6) {
186    case EFAULT:      addr->addrlen = sizeof(struct sockaddr_in6);
187      strcpy(s, "Bad address");      addr->addr.s6.sin6_port = htons(port);
188      break;      addr->addr.s6.sin6_family = AF_INET6;
189    case EINPROGRESS:    } else {
190      strcpy(s, "Operation in progress");      addr->addrlen = sizeof(struct sockaddr_in);
191      break;      addr->addr.s4.sin_port = htons(port);
192    case EINTR:      addr->addr.s4.sin_family = AF_INET;
193      strcpy(s, "Timeout");    }
194      break;  #else
195    case EINVAL:    egg_bzero(addr, sizeof(sockname_t));
196      strcpy(s, "Invalid argument");    if (!egg_inet_aton(src, &addr->addr.s4.sin_addr) && allowres) {
197      break;      /* src is a hostname. Attempt to resolve it.. */
198    case EISCONN:      if (!sigsetjmp(alarmret, 1)) {
199      strcpy(s, "Socket already connected");        alarm(resolve_timeout);
200      break;        hp = gethostbyname(src);
201    case ENETUNREACH:        alarm(0);
202      strcpy(s, "Network unreachable");      } else
203      break;        hp = NULL;
204    case ENOTSOCK:      if (hp) {
205      strcpy(s, "Socket operation on non-socket");        egg_memcpy(&addr->addr.s4.sin_addr, hp->h_addr, hp->h_length);
206      break;        af = hp->h_addrtype;
207    case ETIMEDOUT:      }
208      strcpy(s, "Connection timed out");    } else
209      break;      af = AF_INET;
210    case ENOTCONN:    
211      strcpy(s, "Socket is not connected");    addr->family = addr->addr.s4.sin_family = AF_INET;
212      break;    addr->addr.sa.sa_family = addr->family;
213    case EHOSTUNREACH:    addr->addrlen = sizeof(struct sockaddr_in);
214      strcpy(s, "No route to host");    addr->addr.s4.sin_port = htons(port);
     break;  
   case EPIPE:  
     strcpy(s, "Broken pipe");  
     break;  
 #ifdef ECONNRESET  
   case ECONNRESET:  
     strcpy(s, "Connection reset by peer");  
     break;  
 #endif  
 #ifdef EACCES  
   case EACCES:  
     strcpy(s, "Permission denied");  
     break;  
 #endif  
 #ifdef EMFILE  
   case EMFILE:  
     strcpy(s, "Too many open files");  
     break;  
215  #endif  #endif
216    case 0:    return af;
     strcpy(s, "Error 0");  
     break;  
   default:  
     sprintf(s, "Unforseen error %d", errno);  
     break;  
217    }    }
218    
219    /* Get socket address to bind to for outbound connections
220     */
221    void getvhost(sockname_t *addr, int af)
222    {
223      char *h;
224      
225      if (af == AF_INET)
226        h = vhost;
227    #ifdef IPV6
228      else
229        h = vhost6;
230    #endif
231      if (setsockname(addr, h, 0, 1) != af)
232        setsockname(addr, (af == AF_INET ? "0" : "::"), 0, 0);
233      /* Remember this 'self-lookup failed' thingie?
234         I have good news - you won't see it again ;) */
235  }  }
236    
237  /* Sets/Unsets options for a specific socket.  /* Sets/Unsets options for a specific socket.
# Line 249  int allocsock(int sock, int options) Line 275  int allocsock(int sock, int options)
275        td->socklist[i].handler.sock.outbuflen = 0;        td->socklist[i].handler.sock.outbuflen = 0;
276        td->socklist[i].flags = options;        td->socklist[i].flags = options;
277        td->socklist[i].sock = sock;        td->socklist[i].sock = sock;
278    #ifdef TLS
279          td->socklist[i].ssl = 0;
280    #endif
281        return i;        return i;
282      }      }
283    }    }
# Line 321  void setsock(int sock, int options) Line 350  void setsock(int sock, int options)
350    fcntl(sock, F_SETFL, O_NONBLOCK);    fcntl(sock, F_SETFL, O_NONBLOCK);
351  }  }
352    
353  int getsock(int options)  int getsock(int af, int options)
354  {  {
355    int sock = socket(AF_INET, SOCK_STREAM, 0);    int sock = socket(af, SOCK_STREAM, 0);
356    
357    if (sock >= 0)    if (sock >= 0)
358      setsock(sock, options);      setsock(sock, options);
359    else    else
360      putlog(LOG_MISC, "*", "Warning: Can't create new socket!");      putlog(LOG_MISC, "*", "Warning: Can't create new socket: %s!",
361               strerror(errno));
362    return sock;    return sock;
363  }  }
364    
# Line 346  void killsock(register int sock) Line 376  void killsock(register int sock)
376    for (i = 0; i < td->MAXSOCKS; i++) {    for (i = 0; i < td->MAXSOCKS; i++) {
377      if ((td->socklist[i].sock == sock) && !(td->socklist[i].flags & SOCK_UNUSED)) {      if ((td->socklist[i].sock == sock) && !(td->socklist[i].flags & SOCK_UNUSED)) {
378        if (!(td->socklist[i].flags & SOCK_TCL)) { /* nothing to free for tclsocks */        if (!(td->socklist[i].flags & SOCK_TCL)) { /* nothing to free for tclsocks */
379    #ifdef TLS
380            if (td->socklist[i].ssl) {
381              SSL_shutdown(td->socklist[i].ssl);
382              nfree(SSL_get_app_data(td->socklist[i].ssl));
383              SSL_free(td->socklist[i].ssl);
384              td->socklist[i].ssl = NULL;
385            }
386    #endif
387          close(td->socklist[i].sock);          close(td->socklist[i].sock);
388          if (td->socklist[i].handler.sock.inbuf != NULL) {          if (td->socklist[i].handler.sock.inbuf != NULL) {
389            nfree(td->socklist[i].handler.sock.inbuf);            nfree(td->socklist[i].handler.sock.inbuf);
# Line 386  void killtclsock(register int sock) Line 424  void killtclsock(register int sock)
424    
425  /* Send connection request to proxy  /* Send connection request to proxy
426   */   */
427  static int proxy_connect(int sock, char *host, int port, int proxy)  static int proxy_connect(int sock, sockname_t *addr)
428  {  {
429    unsigned char x[10];    sockname_t name;
430    struct hostent *hp;    char host[121], s[256];
431    char s[256];    int i, port, proxy;
   int i;  
432    
433    /* socks proxy */    if (!firewall[0])
   if (proxy == PROXY_SOCKS) {  
     /* numeric IP? */  
     if (host[strlen(host) - 1] >= '0' && host[strlen(host) - 1] <= '9') {  
       IP ip = ((IP) inet_addr(host));  
       egg_memcpy(x, &ip, 4);  
     } else {  
       /* no, must be host.domain */  
       if (!sigsetjmp(alarmret, 1)) {  
         alarm(resolve_timeout);  
         hp = gethostbyname(host);  
         alarm(0);  
       } else  
         hp = NULL;  
       if (hp == NULL) {  
         killsock(sock);  
434          return -2;          return -2;
435    #ifdef IPV6
436      if (addr->family == AF_INET6) {
437        putlog(LOG_MISC, "*", "Eggdrop doesn't support IPv6 connections "
438               "through proxies yet.");
439        return -1;
440        }        }
441        egg_memcpy(x, hp->h_addr, hp->h_length);  #endif
442      if (firewall[0] == '!') {
443        proxy = PROXY_SUN;
444        strcpy(host, &firewall[1]);
445      } else {
446        proxy = PROXY_SOCKS;
447        strcpy(host, firewall);
448      }      }
449      port = addr->addr.s4.sin_port;
450      setsockname(&name, host, firewallport, 1);
451      if (connect(sock, &name.addr.sa, name.addrlen) < 0 && errno != EINPROGRESS)
452        return -1;
453      if (proxy == PROXY_SOCKS) {
454      for (i = 0; i < threaddata()->MAXSOCKS; i++)      for (i = 0; i < threaddata()->MAXSOCKS; i++)
455        if (!(socklist[i].flags & SOCK_UNUSED) && socklist[i].sock == sock)        if (!(socklist[i].flags & SOCK_UNUSED) && socklist[i].sock == sock)
456          socklist[i].flags |= SOCK_PROXYWAIT;    /* drummer */          socklist[i].flags |= SOCK_PROXYWAIT;    /* drummer */
457        egg_snprintf(s, sizeof s, "\004\001%c%c%c%c%c%c%s", (port >> 8) % 256,      egg_memcpy(host, &addr->addr.s4.sin_addr.s_addr, 4);
458                     (port % 256), x[0], x[1], x[2], x[3], botuser);      egg_snprintf(s, sizeof s, "\004\001%c%c%c%c%c%c%s", port % 256,
459                     (port >> 8) % 256, host[0], host[1], host[2], host[3], botuser);
460      tputs(sock, s, strlen(botuser) + 9);        /* drummer */      tputs(sock, s, strlen(botuser) + 9);        /* drummer */
461    } else if (proxy == PROXY_SUN) {    } else if (proxy == PROXY_SUN) {
462        inet_ntop(AF_INET, &addr->addr.s4.sin_addr, host, sizeof host);
463      egg_snprintf(s, sizeof s, "%s %d\n", host, port);      egg_snprintf(s, sizeof s, "%s %d\n", host, port);
464      tputs(sock, s, strlen(s));  /* drummer */      tputs(sock, s, strlen(s));  /* drummer */
465    }    }
466    return sock;    return sock;
467  }  }
468    
469  /* Starts a connection attempt to a socket  /* Starts a connection attempt through a socket
470   *   *
471   * If given a normal hostname, this will be resolved to the corresponding   * The server address should be filled in addr by setsockname() or by the
472   * IP address first. PLEASE try to use the non-blocking dns functions   * non-blocking dns functions and setsnport().
  * instead and then call this function with the IP address to avoid blocking.  
473   *   *
474   * returns <0 if connection refused:   * returns <0 if connection refused:
475   *   -1  neterror() type error   *   -1  strerror() type error
  *   -2  can't resolve hostname  
476   */   */
477  int open_telnet_raw(int sock, char *server, int sport)  int open_telnet_raw(int sock, sockname_t *addr)
478  {  {
479    struct sockaddr_in name;    sockname_t name;
480    struct hostent *hp;    int i, rc;
   char host[121];  
   int i, port, rc;  
   volatile int proxy;  
481    
482    /* firewall?  use socks */    getvhost(&name, addr->family);
483    if (firewall[0]) {    if (bind(sock, &name.addr.sa, name.addrlen) < 0) {
     if (firewall[0] == '!') {  
       proxy = PROXY_SUN;  
       strcpy(host, &firewall[1]);  
     } else {  
       proxy = PROXY_SOCKS;  
       strcpy(host, firewall);  
     }  
     port = firewallport;  
   } else {  
     proxy = 0;  
     strcpy(host, server);  
     port = sport;  
   }  
   egg_bzero((char *) &name, sizeof(struct sockaddr_in));  
   
   name.sin_family = AF_INET;  
   name.sin_addr.s_addr = (myip[0] ? getmyip() : INADDR_ANY);  
   if (bind(sock, (struct sockaddr *) &name, sizeof(name)) < 0) {  
     killsock(sock);  
484      return -1;      return -1;
485    }    }
   egg_bzero((char *) &name, sizeof(struct sockaddr_in));  
   
   name.sin_family = AF_INET;  
   name.sin_port = htons(port);  
   /* Numeric IP? */  
   if ((host[strlen(host) - 1] >= '0') && (host[strlen(host) - 1] <= '9'))  
     name.sin_addr.s_addr = inet_addr(host);  
   else {  
     /* No, must be host.domain */  
     debug0("WARNING: open_telnet_raw() is about to block in gethostbyname()!");  
     if (!sigsetjmp(alarmret, 1)) {  
       alarm(resolve_timeout);  
       hp = gethostbyname(host);  
       alarm(0);  
     } else  
       hp = NULL;  
     if (hp == NULL)  
       return -2;  
     egg_memcpy(&name.sin_addr, hp->h_addr, hp->h_length);  
     name.sin_family = hp->h_addrtype;  
   }  
486    for (i = 0; i < threaddata()->MAXSOCKS; i++) {    for (i = 0; i < threaddata()->MAXSOCKS; i++) {
487      if (!(socklist[i].flags & SOCK_UNUSED) && (socklist[i].sock == sock))      if (!(socklist[i].flags & SOCK_UNUSED) && (socklist[i].sock == sock))
488        socklist[i].flags = (socklist[i].flags & ~SOCK_VIRTUAL) | SOCK_CONNECT;        socklist[i].flags = (socklist[i].flags & ~SOCK_VIRTUAL) | SOCK_CONNECT;
489    }    }
490    rc = connect(sock, (struct sockaddr *) &name, sizeof(struct sockaddr_in));    if (addr->family == AF_INET && firewall[0])
491        return proxy_connect(sock, addr);
492      rc = connect(sock, &addr->addr.sa, addr->addrlen);
493    if (rc < 0) {    if (rc < 0) {
494      if (errno == EINPROGRESS) {      if (errno == EINPROGRESS)
       /* Firewall?  announce connect attempt to proxy */  
       if (firewall[0])  
         return proxy_connect(sock, server, sport, proxy);  
495        return sock; /* async success! */        return sock; /* async success! */
496      } else      else
497        return -1;        return -1;
498    }    }
   /* Synchronous? :/ */  
   if (firewall[0])  
     return proxy_connect(sock, server, sport, proxy);  
499    return sock;    return sock;
500  }  }
501    
502  /* Ordinary non-binary connection attempt */  /* Ordinary non-binary connection attempt
503  int open_telnet(char *server, int port)   * Return values:
504     *   >=0: connect successful, returned is the socket number
505     *    -1: look at errno or use strerror()
506     *    -2: lookup failed or server is not a valid IP string
507     *    -3: could not allocate socket
508     */
509    int open_telnet(int idx, char *server, int port)
510  {  {
511    int sock = getsock(0), ret = open_telnet_raw(sock, server, port);    int ret;
512    
513      ret = setsockname(&dcc[idx].sockname, server, port, 1);
514      if (ret == AF_UNSPEC)
515        return -2;
516      dcc[idx].port = port;
517      dcc[idx].sock = getsock(ret, 0);
518      if (dcc[idx].sock < 0)
519        return -3;
520      ret = open_telnet_raw(dcc[idx].sock, &dcc[idx].sockname);
521      if (ret < 0)
522        killsock(dcc[idx].sock);
523    return ret;    return ret;
524  }  }
525    
526  /* Returns a socket number for a listening socket that will accept any  /* Returns a socket number for a listening socket that will accept any
527   * connection on a certain address -- port # is returned in port   * connection on the given address. The address can be filled in by
528     * setsockname().
529   */   */
530  int open_address_listen(IP addr, int *port)  int open_address_listen(sockname_t *addr)
531   {   {
532    int sock = 0;    int sock = 0;
   socklen_t addrlen;  
   struct sockaddr_in name;  
533    
534    if (firewall[0]) {    sock = getsock(addr->family, SOCK_LISTEN);
535      /* FIXME: can't do listen port thru firewall yet */    if (sock < 0)
     putlog(LOG_MISC, "*", "Can't open a listen port (you are using a "  
            "firewall).");  
536      return -1;      return -1;
537    #if defined IPV6 && IPV6_V6ONLY
538      if (addr->family == AF_INET6) {
539        int on = 0;
540        setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &on, sizeof(on));
541    }    }
542    #endif
543    if (getmyip() > 0) {    if (bind(sock, &addr->addr.sa, addr->addrlen) < 0) {
     sock = getsock(SOCK_LISTEN);  
     if (sock < 1)  
       return -1;  
   
     egg_bzero((char *) &name, sizeof(struct sockaddr_in));  
     name.sin_family = AF_INET;  
     name.sin_port = htons(*port); /* 0 = just assign us a port */  
     name.sin_addr.s_addr = addr;  
     if (bind(sock, (struct sockaddr *) &name, sizeof(name)) < 0) {  
544        killsock(sock);        killsock(sock);
545        return -1;      return -2;
546      }      }
547      /* what port are we on? */  
548      addrlen = sizeof(name);    if (getsockname(sock, &addr->addr.sa, &addr->addrlen) < 0) {
     if (getsockname(sock, (struct sockaddr *) &name, &addrlen) < 0) {  
549        killsock(sock);        killsock(sock);
550        return -1;        return -1;
551      }      }
     *port = ntohs(name.sin_port);  
552      if (listen(sock, 1) < 0) {      if (listen(sock, 1) < 0) {
553        killsock(sock);        killsock(sock);
554        return -1;        return -1;
555      }      }
   }  
556    
557    return sock;    return sock;
558  }  }
# Line 566  int open_address_listen(IP addr, int *po Line 562  int open_address_listen(IP addr, int *po
562   */   */
563  inline int open_listen(int *port)  inline int open_listen(int *port)
564  {  {
565    return open_address_listen(myip[0] ? getmyip() : INADDR_ANY, port);    int sock;
566  }    sockname_t name;
   
 /* Returns the given network byte order IP address in the  
  * dotted format - "##.##.##.##"  
  */  
 char *iptostr(IP ip)  
 {  
   struct in_addr a;  
567    
568    a.s_addr = ip;    (void) setsockname(&name, listen_ip, *port, 1);
569    return inet_ntoa(a);    sock = open_address_listen(&name);
570      if (name.addr.sa.sa_family == AF_INET)
571        *port = ntohs(name.addr.s4.sin_port);
572    #ifdef IPV6
573      else
574        *port = ntohs(name.addr.s6.sin6_port);
575    #endif
576      return sock;
577  }  }
578    
579  /* Short routine to answer a connect received on a socket made previously  /* Short routine to answer a connect received on a listening socket.
580   * by open_listen ... returns hostname of the caller & the new socket   * Returned is the new socket.
581   * does NOT dispose of old "public" socket!   * If port is not NULL, it points to an integer to hold the port number
582     * of the caller.
583   */   */
584  int answer(int sock, char *caller, unsigned long *ip, unsigned short *port,  int answer(int sock, sockname_t *caller, unsigned short *port, int binary)
            int binary)  
585  {  {
586    int new_sock;    int new_sock;
587    socklen_t addrlen;    caller->addrlen = sizeof(caller->addr);
588    struct sockaddr_in from;    new_sock = accept(sock, &caller->addr.sa, &caller->addrlen);
   
   addrlen = sizeof(struct sockaddr);  
   new_sock = accept(sock, (struct sockaddr *) &from, &addrlen);  
589    
590    if (new_sock < 0)    if (new_sock < 0)
591      return -1;      return -1;
592    if (ip != NULL) {  
593      *ip = from.sin_addr.s_addr;    caller->family = caller->addr.sa.sa_family;
594      /* DNS is now done asynchronously. We now only provide the IP address. */    if (port) {
595      strncpyz(caller, iptostr(*ip), 121);      if (caller->family == AF_INET)
596      *ip = ntohl(*ip);        *port = ntohs(caller->addr.s4.sin_port);
597    }  #ifdef IPV6
598    if (port != NULL)      else
599      *port = ntohs(from.sin_port);        *port = ntohs(caller->addr.s6.sin6_port);
600    /* Set up all the normal socket crap */  #endif
601      }
602    setsock(new_sock, (binary ? SOCK_BINARY : 0));    setsock(new_sock, (binary ? SOCK_BINARY : 0));
603    return new_sock;    return new_sock;
604  }  }
605    
606  /* Like open_telnet, but uses server & port specifications of dcc  /* Get DCC compatible address for a client to connect (e.g. 1660944385)
607     * If addr is not NULL, it should point to the listening socket's address.
608     * Otherwise, this function will try to figure out the public address of the
609     * machine, using listen_ip and natip.
610     * The result is a string useable for DCC requests
611   */   */
612  int open_telnet_dcc(int sock, char *server, char *port)  int getdccaddr(sockname_t *addr, char *s, size_t l)
613  {  {
614    int p;    char h[121];
615    unsigned long addr;    sockname_t name, *r = &name;
   char sv[500];  
   unsigned char c[4];  
616    
617    if (port != NULL)    if (addr)
618      p = atoi(port);      r = addr;
619    else    else
620      p = 2000;      setsockname(r, listen_ip, 0, 1);
621    if (server != NULL)    if (
622      addr = my_atoul(server);  #ifdef IPV6
623          ((r->family == AF_INET6) &&
624          IN6_IS_ADDR_UNSPECIFIED(&r->addr.s6.sin6_addr)) ||
625    #endif
626          (r->family == AF_INET && !r->addr.s4.sin_addr.s_addr)) {
627          /* We can't send :: or 0.0.0.0 for dcc, so try
628             to figure out some real address */
629        r = &name;
630        gethostname(h, sizeof h);
631        setsockname(r, h, 0, 1);
632      }
633    
634      if (
635    #ifdef IPV6
636          ((r->family == AF_INET6) &&
637          IN6_IS_ADDR_UNSPECIFIED(&r->addr.s6.sin6_addr)) ||
638    #endif
639          (!natip[0] && (r->family == AF_INET) && !r->addr.s4.sin_addr.s_addr))
640        return 0;
641    
642    #ifdef IPV6
643      if (r->family == AF_INET6) {
644        if (IN6_IS_ADDR_V4MAPPED(&r->addr.s6.sin6_addr) ||
645            IN6_IS_ADDR_UNSPECIFIED(&r->addr.s6.sin6_addr))
646          snprintf(s, l, "%lu", natip[0] ? iptolong(inet_addr(natip)) :
647                   ntohl(*(IP *) &r->addr.s6.sin6_addr.s6_addr[12]));
648    else    else
649      addr = 0L;        inet_ntop(AF_INET6, &r->addr.s6.sin6_addr, s, l);
650    if (addr < (1 << 24))    } else
651      return -3;                  /* fake address */  #endif
652    c[0] = (addr >> 24) & 0xff;    snprintf(s, l, "%lu", natip[0] ? iptolong(inet_addr(natip)) :
653    c[1] = (addr >> 16) & 0xff;               ntohl(r->addr.s4.sin_addr.s_addr));
654    c[2] = (addr >> 8) & 0xff;    return 1;
   c[3] = addr & 0xff;  
   sprintf(sv, "%u.%u.%u.%u", c[0], c[1], c[2], c[3]);  
   p = open_telnet_raw(sock, sv, p);  
   return p;  
655  }  }
656    
657  /* Builds the fd_sets for select(). Eggdrop only cares about readable  /* Builds the fd_sets for select(). Eggdrop only cares about readable
# Line 710  int sockread(char *s, int *len, sock_lis Line 727  int sockread(char *s, int *len, sock_lis
727               SELECT_TYPE_ARG234 (have_w ? &fdw : NULL),               SELECT_TYPE_ARG234 (have_w ? &fdw : NULL),
728               SELECT_TYPE_ARG234 (have_e ? &fde : NULL),               SELECT_TYPE_ARG234 (have_e ? &fde : NULL),
729               SELECT_TYPE_ARG5 &t);               SELECT_TYPE_ARG5 &t);
730    if (x > 0) {    if (x == -1)
731      /* Something happened */      return -2;                  /* socket error */
732    
733      for (i = 0; i < slistmax; i++) {      for (i = 0; i < slistmax; i++) {
734        if (!tclonly && ((!(slist[i].flags & (SOCK_UNUSED | SOCK_TCL))) &&        if (!tclonly && ((!(slist[i].flags & (SOCK_UNUSED | SOCK_TCL))) &&
735            ((FD_ISSET(slist[i].sock, &fdr)) ||            ((FD_ISSET(slist[i].sock, &fdr)) ||
736    #ifdef TLS
737            (slist[i].ssl && (SSL_pending(slist[i].ssl) ||
738             !SSL_is_init_finished(slist[i].ssl))) ||
739    #endif
740            ((slist[i].sock == STDOUT) && (!backgrd) &&            ((slist[i].sock == STDOUT) && (!backgrd) &&
741            (FD_ISSET(STDIN, &fdr)))))) {            (FD_ISSET(STDIN, &fdr)))))) {
742          if (slist[i].flags & (SOCK_LISTEN | SOCK_CONNECT)) {          if (slist[i].flags & (SOCK_LISTEN | SOCK_CONNECT)) {
# Line 724  int sockread(char *s, int *len, sock_lis Line 746  int sockread(char *s, int *len, sock_lis
746            if (slist[i].flags & SOCK_PROXYWAIT) /* drummer */            if (slist[i].flags & SOCK_PROXYWAIT) /* drummer */
747              /* Hang around to get the return code from proxy */              /* Hang around to get the return code from proxy */
748              grab = 10;              grab = 10;
749    #ifdef TLS
750            else if (!(slist[i].flags & SOCK_STRONGCONN) &&
751                     (!(slist[i].ssl) || SSL_is_init_finished(slist[i].ssl))) {
752    #else
753            else if (!(slist[i].flags & SOCK_STRONGCONN)) {            else if (!(slist[i].flags & SOCK_STRONGCONN)) {
754    #endif
755              debug1("net: connect! sock %d", slist[i].sock);              debug1("net: connect! sock %d", slist[i].sock);
756              s[0] = 0;              s[0] = 0;
757              *len = 0;              *len = 0;
# Line 739  int sockread(char *s, int *len, sock_lis Line 766  int sockread(char *s, int *len, sock_lis
766          if ((slist[i].sock == STDOUT) && !backgrd)          if ((slist[i].sock == STDOUT) && !backgrd)
767            x = read(STDIN, s, grab);            x = read(STDIN, s, grab);
768          else          else
769    #ifdef TLS
770          {
771            if (slist[i].ssl) {
772              x = SSL_read(slist[i].ssl, s, grab);
773              if (x < 0) {
774                int err = SSL_get_error(slist[i].ssl, x);
775                if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
776                  errno = EAGAIN;
777                else
778                  debug1("sockread(): SSL error = %s",
779                         ERR_error_string(ERR_get_error(), 0));
780                x = -1;
781              }
782            } else
783              x = read(slist[i].sock, s, grab);
784          }
785    #else
786            x = read(slist[i].sock, s, grab);            x = read(slist[i].sock, s, grab);
787    #endif  
788          if (x <= 0) {           /* eof */          if (x <= 0) {           /* eof */
789            if (errno != EAGAIN) { /* EAGAIN happens when the operation would            if (errno != EAGAIN) { /* EAGAIN happens when the operation would
790                                    * block on a non-blocking socket, if the                                    * block on a non-blocking socket, if the
# Line 789  int sockread(char *s, int *len, sock_lis Line 834  int sockread(char *s, int *len, sock_lis
834            tclsock = i;            tclsock = i;
835        }        }
836      }      }
837    } else if (x == -1)    if (!tclonly) {
     return -2;                  /* socket error */  
   else if (!tclonly) {  
838      s[0] = 0;      s[0] = 0;
839      *len = 0;      *len = 0;
840    }    }
# Line 1046  void tputs(register int z, char *s, unsi Line 1089  void tputs(register int z, char *s, unsi
1089          socklist[i].handler.sock.outbuflen += len;          socklist[i].handler.sock.outbuflen += len;
1090          return;          return;
1091        }        }
1092    #ifdef TLS
1093          if (socklist[i].ssl) {
1094            x = SSL_write(socklist[i].ssl, s, len);
1095            if (x < 0) {
1096              int err = SSL_get_error(socklist[i].ssl, x);
1097              if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ)
1098                errno = EAGAIN;
1099              else if (!inhere) { /* Out there, somewhere */
1100                inhere = 1;
1101                debug1("tputs(): SSL error = %s",
1102                       ERR_error_string(ERR_get_error(), 0));
1103                inhere = 0;
1104              }
1105              x = -1;
1106            }
1107          } else /* not ssl, use regular write() */
1108    #endif      
1109        /* Try. */        /* Try. */
1110        x = write(z, s, len);        x = write(z, s, len);
1111        if (x == -1)        if (x == -1)
# Line 1092  void dequeue_sockets() Line 1152  void dequeue_sockets()
1152    FD_ZERO(&wfds);    FD_ZERO(&wfds);
1153    tv.tv_sec = 0;    tv.tv_sec = 0;
1154    tv.tv_usec = 0;               /* we only want to see if it's ready for writing, no need to actually wait.. */    tv.tv_usec = 0;               /* we only want to see if it's ready for writing, no need to actually wait.. */
1155    for (i = 0; i < threaddata()->MAXSOCKS; i++) {    for (i = 0; i < threaddata()->MAXSOCKS; i++)
1156      if (!(socklist[i].flags & (SOCK_UNUSED | SOCK_TCL)) &&      if (!(socklist[i].flags & (SOCK_UNUSED | SOCK_TCL)) &&
1157          socklist[i].handler.sock.outbuf != NULL) {          (socklist[i].handler.sock.outbuf != NULL)) {
1158        FD_SET(socklist[i].sock, &wfds);        FD_SET(socklist[i].sock, &wfds);
1159        z = 1;        z = 1;
1160      }      }
   }  
1161    if (!z)    if (!z)
1162      return;                     /* nothing to write */      return;                     /* nothing to write */
1163    
# Line 1113  void dequeue_sockets() Line 1172  void dequeue_sockets()
1172          (socklist[i].handler.sock.outbuf != NULL) && (FD_ISSET(socklist[i].sock, &wfds))) {          (socklist[i].handler.sock.outbuf != NULL) && (FD_ISSET(socklist[i].sock, &wfds))) {
1173        /* Trick tputs into doing the work */        /* Trick tputs into doing the work */
1174        errno = 0;        errno = 0;
1175        x = write(socklist[i].sock, socklist[i].handler.sock.outbuf, socklist[i].handler.sock.outbuflen);  #ifdef TLS
1176          if (socklist[i].ssl) {
1177            x = SSL_write(socklist[i].ssl, socklist[i].handler.sock.outbuf,
1178                          socklist[i].handler.sock.outbuflen);
1179            if (x < 0) {
1180              int err = SSL_get_error(socklist[i].ssl, x);
1181              if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ)
1182                errno = EAGAIN;
1183              else
1184                debug1("dequeue_sockets(): SSL error = %s",
1185                       ERR_error_string(ERR_get_error(), 0));
1186              x = -1;
1187            }
1188          } else
1189    #endif  
1190          x = write(socklist[i].sock, socklist[i].handler.sock.outbuf,
1191                    socklist[i].handler.sock.outbuflen);
1192        if ((x < 0) && (errno != EAGAIN)        if ((x < 0) && (errno != EAGAIN)
1193  #ifdef EBADSLT  #ifdef EBADSLT
1194            && (errno != EBADSLT)            && (errno != EBADSLT)
# Line 1135  void dequeue_sockets() Line 1210  void dequeue_sockets()
1210          char *p = socklist[i].handler.sock.outbuf;          char *p = socklist[i].handler.sock.outbuf;
1211    
1212          /* This removes any sent bytes from the beginning of the buffer */          /* This removes any sent bytes from the beginning of the buffer */
1213          socklist[i].handler.sock.outbuf = nmalloc(socklist[i].handler.sock.outbuflen - x);          socklist[i].handler.sock.outbuf =
1214          egg_memcpy(socklist[i].handler.sock.outbuf, p + x, socklist[i].handler.sock.outbuflen - x);                              nmalloc(socklist[i].handler.sock.outbuflen - x);
1215            egg_memcpy(socklist[i].handler.sock.outbuf, p + x,
1216                       socklist[i].handler.sock.outbuflen - x);
1217          socklist[i].handler.sock.outbuflen -= x;          socklist[i].handler.sock.outbuflen -= x;
1218          nfree(p);          nfree(p);
1219        } else {        } else {
# Line 1182  void tell_netdebug(int idx) Line 1259  void tell_netdebug(int idx)
1259          strcat(s, " (strong)");          strcat(s, " (strong)");
1260        if (socklist[i].flags & SOCK_NONSOCK)        if (socklist[i].flags & SOCK_NONSOCK)
1261          strcat(s, " (file)");          strcat(s, " (file)");
1262    #ifdef TLS
1263          if (socklist[i].ssl)
1264            strcat(s, " (TLS)");
1265    #endif
1266        if (socklist[i].flags & SOCK_TCL)        if (socklist[i].flags & SOCK_TCL)
1267          strcat(s, " (tcl)");          strcat(s, " (tcl)");
1268        if (!(socklist[i].flags & SOCK_TCL)) {        if (!(socklist[i].flags & SOCK_TCL)) {
# Line 1212  int sanitycheck_dcc(char *nick, char *fr Line 1293  int sanitycheck_dcc(char *nick, char *fr
1293     * DNS names that are up to 255 characters long.  This is not broken.     * DNS names that are up to 255 characters long.  This is not broken.
1294     */     */
1295    
1296    char badaddress[16];  #ifdef IPV6
1297      char badaddress[INET6_ADDRSTRLEN];
1298      sockname_t name;
1299      IP ip = 0;
1300    #else
1301      char badaddress[sizeof "255.255.255.255"];
1302    IP ip = my_atoul(ipaddy);    IP ip = my_atoul(ipaddy);
1303    #endif
1304    int prt = atoi(port);    int prt = atoi(port);
1305    
1306    /* It is disabled HERE so we only have to check in *one* spot! */    /* It is disabled HERE so we only have to check in *one* spot! */
# Line 1225  int sanitycheck_dcc(char *nick, char *fr Line 1312  int sanitycheck_dcc(char *nick, char *fr
1312             nick, from, prt);             nick, from, prt);
1313      return 0;      return 0;
1314    }    }
1315    sprintf(badaddress, "%u.%u.%u.%u", (ip >> 24) & 0xff, (ip >> 16) & 0xff,  #ifdef IPV6
1316            (ip >> 8) & 0xff, ip & 0xff);    if (strchr(ipaddy, ':')) {
1317    if (ip < (1 << 24)) {      if (inet_pton(AF_INET6, ipaddy, &name.addr.s6.sin6_addr) != 1) {
1318          putlog(LOG_MISC, "*", "ALERT: (%s!%s) specified an invalid IPv6 "
1319                 "address of %s!", nick, from, ipaddy);
1320          return 0;
1321        }
1322        if (IN6_IS_ADDR_V4MAPPED(&name.addr.s6.sin6_addr))
1323          ip = ntohl(*(IP *) &name.addr.s6.sin6_addr.s6_addr[12]);
1324      }
1325    #endif
1326      if (ip && inet_ntop(AF_INET, &ip, badaddress, sizeof badaddress) &&
1327          (ip < (1 << 24))) {
1328      putlog(LOG_MISC, "*", "ALERT: (%s!%s) specified an impossible IP of %s!",      putlog(LOG_MISC, "*", "ALERT: (%s!%s) specified an impossible IP of %s!",
1329             nick, from, badaddress);             nick, from, badaddress);
1330      return 0;      return 0;
# Line 1235  int sanitycheck_dcc(char *nick, char *fr Line 1332  int sanitycheck_dcc(char *nick, char *fr
1332    return 1;    return 1;
1333  }  }
1334    
1335  int hostsanitycheck_dcc(char *nick, char *from, IP ip, char *dnsname,  int hostsanitycheck_dcc(char *nick, char *from, sockname_t *ip, char *dnsname,
1336                          char *prt)                          char *prt)
1337  {  {
1338      char badaddress[INET6_ADDRSTRLEN];
1339    
1340    /* According to the latest RFC, the clients SHOULD be able to handle    /* According to the latest RFC, the clients SHOULD be able to handle
1341     * DNS names that are up to 255 characters long.  This is not broken.     * DNS names that are up to 255 characters long.  This is not broken.
1342     */     */
1343    char hostn[256], badaddress[16];    char hostn[256];
1344    
1345    /* It is disabled HERE so we only have to check in *one* spot! */    /* It is disabled HERE so we only have to check in *one* spot! */
1346    if (!dcc_sanitycheck)    if (!dcc_sanitycheck)
1347      return 1;      return 1;
1348    sprintf(badaddress, "%u.%u.%u.%u", (ip >> 24) & 0xff, (ip >> 16) & 0xff,    strcpy(badaddress, iptostr(&ip->addr.sa));
           (ip >> 8) & 0xff, ip & 0xff);  
1349    /* These should pad like crazy with zeros, since 120 bytes or so is    /* These should pad like crazy with zeros, since 120 bytes or so is
1350     * where the routines providing our data currently lose interest. I'm     * where the routines providing our data currently lose interest. I'm
1351     * using the n-variant in case someone changes that...     * using the n-variant in case someone changes that...
# Line 1328  int flush_inbuf(int idx) Line 1426  int flush_inbuf(int idx)
1426    }    }
1427    return -1;    return -1;
1428  }  }
1429    
1430    /* Find sock in socklist.
1431     *
1432     * Returns index in socklist or -1 if not found.
1433     */
1434    int findsock(int sock)
1435    {
1436      int i;
1437      struct threaddata *td = threaddata();
1438    
1439      for (i = 0; i < td->MAXSOCKS; i++)
1440        if (td->socklist[i].sock == sock)
1441          break;
1442      if (i == td->MAXSOCKS)
1443        return -1;
1444      return i;
1445    }

Legend:
Removed from v.1.1.1.1  
changed lines
  Added in v.1.11

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23