/[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 by simple, Mon Jul 26 21:11:06 2010 UTC revision 1.2 by pseudo, Thu Aug 5 18:12:05 2010 UTC
# Line 58  extern unsigned long otraffic_irc_today, Line 58  extern unsigned long otraffic_irc_today,
58                       otraffic_filesys_today, otraffic_trans_today,                       otraffic_filesys_today, otraffic_trans_today,
59                       otraffic_unknown_today;                       otraffic_unknown_today;
60    
61  char hostname[121] = "";      /* Hostname can be specified in the config file.*/  char natip[121] = "";         /* Public IPv4 to report for systems behind NAT */
62  char myip[121] = "";          /* IP can be specified in the config file.      */  char listen_ip[121] = "";     /* IP (or hostname) for listening sockets       */
63    char vhost[121] = "";          /* IPv4 vhost for outgoing connections         */
64    #ifdef IPV6
65    char vhost6[121] = "";         /* IPv6 vhost for outgoing connections         */
66    int pref_af = 0;              /* Prefer IPv6 over IPv4?                       */
67    #endif
68  char firewall[121] = "";      /* Socks server for firewall.                   */  char firewall[121] = "";      /* Socks server for firewall.                   */
69  int firewallport = 1080;      /* Default port of socks 4/5 firewalls.         */  int firewallport = 1080;      /* Default port of socks 4/5 firewalls.         */
70  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 108  int expmem_net()
108    return tot;    return tot;
109  }  }
110    
111  /* Get my ip number  /* Extract the IP address from a sockaddr struct and convert it
112     * to presentation format.
113   */   */
114  IP getmyip()  char *iptostr(struct sockaddr *sa)
115    {
116    #ifdef IPV6
117      static char s[INET6_ADDRSTRLEN] = "";
118      if (sa->sa_family == AF_INET6)
119        inet_ntop(AF_INET6, &((struct sockaddr_in6 *)sa)->sin6_addr,
120                  s, sizeof s);
121      else
122    #else
123      static char s[sizeof "255.255.255.255"] = "";
124    #endif
125        inet_ntop(AF_INET, &((struct sockaddr_in *)sa)->sin_addr.s_addr, s,
126                  sizeof s);
127      return s;
128    }
129    
130    /* Fills in a sockname struct with the given server and port. If the string
131     * pointed by src isn't an IP address and allowres is not null, the function
132     * will assume it's a hostname and will attempt to resolve it. This is
133     * convenient, but you should use the async dns functions where possible, to
134     * avoid blocking the bot while the lookup is performed.
135     */
136    int setsockname(sockname_t *addr, char *src, int port, int allowres)
137  {  {
138    struct hostent *hp;    struct hostent *hp;
139    char s[121];    int af = AF_UNSPEC;
140    IP ip;  #ifdef IPV6
141    struct in_addr *in;    int pref;
142    if (myip[0]) {  
143      if ((myip[strlen(myip) - 1] >= '0') && (myip[strlen(myip) - 1] <= '9'))    /* Clean start */
144        return (IP) inet_addr(myip);    egg_bzero(addr, sizeof(sockname_t));
145    }    af = pref = pref_af ? AF_INET6 : AF_INET;
146    /* Also could be pre-defined */    if (pref == AF_INET) {
147    if (hostname[0])      if (!egg_inet_aton(src, &addr->addr.s4.sin_addr))
148      hp = gethostbyname(hostname);        af = AF_INET6;
149    else {    } else {
150      gethostname(s, 120);      if (inet_pton(af, src, &addr->addr.s6.sin6_addr) != 1)
151      hp = gethostbyname(s);        af = AF_INET;
152    }    }
153    if (hp == NULL)    if (af != pref)
154      fatal("Hostname self-lookup failed. Please set 'my-ip' in the config "      if (((af == AF_INET6) &&
155            "file.", 0);           (inet_pton(af, src, &addr->addr.s6.sin6_addr) != 1)) ||
156    in = (struct in_addr *) (hp->h_addr_list[0]);          ((af == AF_INET)  &&
157    ip = (IP) (in->s_addr);           !egg_inet_aton(src, &addr->addr.s4.sin_addr)))
158    return ip;        af = AF_UNSPEC;
159  }  
160      if (af == AF_UNSPEC && allowres) {
161  void neterror(char *s)      /* src is a hostname. Attempt to resolve it.. */
162  {      if (!sigsetjmp(alarmret, 1)) {
163    switch (errno) {        alarm(resolve_timeout);
164    case EADDRINUSE:        hp = gethostbyname2(src, pref_af ? AF_INET6 : AF_INET);
165      strcpy(s, "Address already in use");        if (!hp)
166      break;          hp = gethostbyname2(src, pref_af ? AF_INET : AF_INET6);
167    case EADDRNOTAVAIL:        alarm(0);
168      strcpy(s, "Cannot assign requested address");      } else
169      break;        hp = NULL;
170    case EAFNOSUPPORT:      if (hp) {
171      strcpy(s, "Address family not supported");        if (hp->h_addrtype == AF_INET)
172      break;          egg_memcpy(&addr->addr.s4.sin_addr, hp->h_addr, hp->h_length);
173    case EALREADY:        else
174      strcpy(s, "Socket already in use");          egg_memcpy(&addr->addr.s6.sin6_addr, hp->h_addr, hp->h_length);
175      break;        af = hp->h_addrtype;
176    case EBADF:      }
177      strcpy(s, "Socket descriptor is bad");    }
178      break;    
179    case ECONNREFUSED:    addr->family = (af == AF_UNSPEC) ? pref : af;
180      strcpy(s, "Connection refused");    addr->addr.sa.sa_family = addr->family;
181      break;    if (addr->family == AF_INET6) {
182    case EFAULT:      addr->addrlen = sizeof(struct sockaddr_in6);
183      strcpy(s, "Bad address");      addr->addr.s6.sin6_port = htons(port);
184      break;      addr->addr.s6.sin6_family = AF_INET6;
185    case EINPROGRESS:    } else {
186      strcpy(s, "Operation in progress");      addr->addrlen = sizeof(struct sockaddr_in);
187      break;      addr->addr.s4.sin_port = htons(port);
188    case EINTR:      addr->addr.s4.sin_family = AF_INET;
189      strcpy(s, "Timeout");    }
190      break;  #else
191    case EINVAL:    egg_bzero(addr, sizeof(sockname_t));
192      strcpy(s, "Invalid argument");    if (!egg_inet_aton(src, &addr->addr.s4.sin_addr) && allowres) {
193      break;      /* src is a hostname. Attempt to resolve it.. */
194    case EISCONN:      if (!sigsetjmp(alarmret, 1)) {
195      strcpy(s, "Socket already connected");        alarm(resolve_timeout);
196      break;        hp = gethostbyname(src);
197    case ENETUNREACH:        alarm(0);
198      strcpy(s, "Network unreachable");      } else
199      break;        hp = NULL;
200    case ENOTSOCK:      if (hp) {
201      strcpy(s, "Socket operation on non-socket");        egg_memcpy(&addr->addr.s4.sin_addr, hp->h_addr, hp->h_length);
202      break;        af = hp->h_addrtype;
203    case ETIMEDOUT:      }
204      strcpy(s, "Connection timed out");    }
205      break;    
206    case ENOTCONN:    addr->family = addr->addr.s4.sin_family = AF_INET;
207      strcpy(s, "Socket is not connected");    addr->addr.sa.sa_family = addr->family;
208      break;    addr->addrlen = sizeof(struct sockaddr_in);
209    case EHOSTUNREACH:    addr->addr.s4.sin_port = htons(port);
     strcpy(s, "No route to host");  
     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;  
210  #endif  #endif
211    case 0:    return af;
     strcpy(s, "Error 0");  
     break;  
   default:  
     sprintf(s, "Unforseen error %d", errno);  
     break;  
212    }    }
213    
214    /* Get socket address to bind to for outbound connections
215     */
216    void getvhost(sockname_t *addr, int af)
217    {
218      char *h;
219      
220      if (af == AF_INET)
221        h = vhost;
222    #ifdef IPV6
223      else
224        h = vhost6;
225    #endif
226      if (setsockname(addr, h, 0, 1) != af)
227        setsockname(addr, (af == AF_INET ? "0" : "::"), 0, 0);
228      /* Remember this 'self-lookup failed' thingie?
229         I have good news - you won't see it again ;) */
230  }  }
231    
232  /* Sets/Unsets options for a specific socket.  /* Sets/Unsets options for a specific socket.
# Line 321  void setsock(int sock, int options) Line 342  void setsock(int sock, int options)
342    fcntl(sock, F_SETFL, O_NONBLOCK);    fcntl(sock, F_SETFL, O_NONBLOCK);
343  }  }
344    
345  int getsock(int options)  int getsock(int af, int options)
346  {  {
347    int sock = socket(AF_INET, SOCK_STREAM, 0);    int sock = socket(af, SOCK_STREAM, 0);
348    
349    if (sock >= 0)    if (sock >= 0)
350      setsock(sock, options);      setsock(sock, options);
351    else    else
352      putlog(LOG_MISC, "*", "Warning: Can't create new socket!");      putlog(LOG_MISC, "*", "Warning: Can't create new socket: %s!",
353               strerror(errno));
354    return sock;    return sock;
355  }  }
356    
# Line 386  void killtclsock(register int sock) Line 408  void killtclsock(register int sock)
408    
409  /* Send connection request to proxy  /* Send connection request to proxy
410   */   */
411  static int proxy_connect(int sock, char *host, int port, int proxy)  static int proxy_connect(int sock, sockname_t *addr)
412  {  {
413    unsigned char x[10];    sockname_t name;
414    struct hostent *hp;    char host[121], s[256];
415    char s[256];    int i, port, proxy;
   int i;  
416    
417    /* 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);  
418          return -2;          return -2;
419    #ifdef IPV6
420      if (addr->family == AF_INET6) {
421        putlog(LOG_MISC, "*", "Eggdrop doesn't support IPv6 connections "
422               "through proxies yet.");
423        return -1;
424        }        }
425        egg_memcpy(x, hp->h_addr, hp->h_length);  #endif
426      if (firewall[0] == '!') {
427        proxy = PROXY_SUN;
428        strcpy(host, &firewall[1]);
429      } else {
430        proxy = PROXY_SOCKS;
431        strcpy(host, firewall);
432      }      }
433      port = addr->addr.s4.sin_port;
434      setsockname(&name, host, firewallport, 1);
435      if (connect(sock, &name.addr.sa, name.addrlen) < 0 && errno != EINPROGRESS)
436        return -1;
437      if (proxy == PROXY_SOCKS) {
438      for (i = 0; i < threaddata()->MAXSOCKS; i++)      for (i = 0; i < threaddata()->MAXSOCKS; i++)
439        if (!(socklist[i].flags & SOCK_UNUSED) && socklist[i].sock == sock)        if (!(socklist[i].flags & SOCK_UNUSED) && socklist[i].sock == sock)
440          socklist[i].flags |= SOCK_PROXYWAIT;    /* drummer */          socklist[i].flags |= SOCK_PROXYWAIT;    /* drummer */
441        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);
442                     (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,
443                     (port >> 8) % 256, host[0], host[1], host[2], host[3], botuser);
444      tputs(sock, s, strlen(botuser) + 9);        /* drummer */      tputs(sock, s, strlen(botuser) + 9);        /* drummer */
445    } else if (proxy == PROXY_SUN) {    } else if (proxy == PROXY_SUN) {
446        inet_ntop(AF_INET, &addr->addr.s4.sin_addr, host, sizeof host);
447      egg_snprintf(s, sizeof s, "%s %d\n", host, port);      egg_snprintf(s, sizeof s, "%s %d\n", host, port);
448      tputs(sock, s, strlen(s));  /* drummer */      tputs(sock, s, strlen(s));  /* drummer */
449    }    }
450    return sock;    return sock;
451  }  }
452    
453  /* Starts a connection attempt to a socket  /* Starts a connection attempt through a socket
454   *   *
455   * 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
456   * 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.  
457   *   *
458   * returns <0 if connection refused:   * returns <0 if connection refused:
459   *   -1  neterror() type error   *   -1  strerror() type error
  *   -2  can't resolve hostname  
460   */   */
461  int open_telnet_raw(int sock, char *server, int sport)  int open_telnet_raw(int sock, sockname_t *addr)
462  {  {
463    struct sockaddr_in name;    sockname_t name;
464    struct hostent *hp;    int i, rc;
   char host[121];  
   int i, port, rc;  
   volatile int proxy;  
465    
466    /* firewall?  use socks */    getvhost(&name, addr->family);
467    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);  
468      return -1;      return -1;
469    }    }
   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;  
   }  
470    for (i = 0; i < threaddata()->MAXSOCKS; i++) {    for (i = 0; i < threaddata()->MAXSOCKS; i++) {
471      if (!(socklist[i].flags & SOCK_UNUSED) && (socklist[i].sock == sock))      if (!(socklist[i].flags & SOCK_UNUSED) && (socklist[i].sock == sock))
472        socklist[i].flags = (socklist[i].flags & ~SOCK_VIRTUAL) | SOCK_CONNECT;        socklist[i].flags = (socklist[i].flags & ~SOCK_VIRTUAL) | SOCK_CONNECT;
473    }    }
474    rc = connect(sock, (struct sockaddr *) &name, sizeof(struct sockaddr_in));    if (addr->family == AF_INET && firewall[0])
475        return proxy_connect(sock, addr);
476      rc = connect(sock, &addr->addr.sa, addr->addrlen);
477    if (rc < 0) {    if (rc < 0) {
478      if (errno == EINPROGRESS) {      if (errno == EINPROGRESS)
       /* Firewall?  announce connect attempt to proxy */  
       if (firewall[0])  
         return proxy_connect(sock, server, sport, proxy);  
479        return sock; /* async success! */        return sock; /* async success! */
480      } else      else
481        return -1;        return -1;
482    }    }
   /* Synchronous? :/ */  
   if (firewall[0])  
     return proxy_connect(sock, server, sport, proxy);  
483    return sock;    return sock;
484  }  }
485    
486  /* Ordinary non-binary connection attempt */  /* Ordinary non-binary connection attempt
487     * Return values:
488     *   >=0: connect successful, returned is the socket number
489     *    -1: look at errno or use strerror()
490     *    -2: lookup failed or server is not a valid IP string
491     */
492  int open_telnet(char *server, int port)  int open_telnet(char *server, int port)
493  {  {
494    int sock = getsock(0), ret = open_telnet_raw(sock, server, port);    int ret, sock;
495      sockname_t name;
496    
497      ret = setsockname(&name, server, port, 1);
498      if (ret == AF_UNSPEC)
499        return -2;
500      sock = getsock(ret, 0);
501      if (sock < 0)
502        return -1;
503      ret = open_telnet_raw(sock, &name);
504      if (ret < 0)
505        killsock(sock);
506    return ret;    return ret;
507  }  }
508    
509  /* Returns a socket number for a listening socket that will accept any  /* Returns a socket number for a listening socket that will accept any
510   * connection on a certain address -- port # is returned in port   * connection on the given address. The address can be filled in by
511     * setsockname().
512   */   */
513  int open_address_listen(IP addr, int *port)  int open_address_listen(sockname_t *addr)
514   {   {
515    int sock = 0;    int sock = 0;
   socklen_t addrlen;  
   struct sockaddr_in name;  
516    
517    if (firewall[0]) {    sock = getsock(addr->family, SOCK_LISTEN);
518      /* 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).");  
519      return -1;      return -1;
520    #if defined IPV6 && IPV6_V6ONLY
521      if (addr->family == AF_INET6) {
522        int on = 0;
523        setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &on, sizeof(on));
524    }    }
525    #endif
526    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) {  
527        killsock(sock);        killsock(sock);
528        return -1;      return -2;
529      }      }
530      /* what port are we on? */  
531      addrlen = sizeof(name);    if (getsockname(sock, &addr->addr.sa, &addr->addrlen) < 0) {
     if (getsockname(sock, (struct sockaddr *) &name, &addrlen) < 0) {  
532        killsock(sock);        killsock(sock);
533        return -1;        return -1;
534      }      }
     *port = ntohs(name.sin_port);  
535      if (listen(sock, 1) < 0) {      if (listen(sock, 1) < 0) {
536        killsock(sock);        killsock(sock);
537        return -1;        return -1;
538      }      }
   }  
539    
540    return sock;    return sock;
541  }  }
# Line 566  int open_address_listen(IP addr, int *po Line 545  int open_address_listen(IP addr, int *po
545   */   */
546  inline int open_listen(int *port)  inline int open_listen(int *port)
547  {  {
548    return open_address_listen(myip[0] ? getmyip() : INADDR_ANY, port);    int sock;
549  }    sockname_t name;
   
 /* Returns the given network byte order IP address in the  
  * dotted format - "##.##.##.##"  
  */  
 char *iptostr(IP ip)  
 {  
   struct in_addr a;  
550    
551    a.s_addr = ip;    (void) setsockname(&name, listen_ip, *port, 1);
552    return inet_ntoa(a);    sock = open_address_listen(&name);
553      if (name.addr.sa.sa_family == AF_INET)
554        *port = ntohs(name.addr.s4.sin_port);
555    #ifdef IPV6
556      else
557        *port = ntohs(name.addr.s6.sin6_port);
558    #endif
559      return sock;
560  }  }
561    
562  /* Short routine to answer a connect received on a socket made previously  /* Short routine to answer a connect received on a listening socket.
563   * by open_listen ... returns hostname of the caller & the new socket   * Returned is the new socket.
564   * does NOT dispose of old "public" socket!   * If port is not NULL, it points to an integer to hold the port number
565     * of the caller.
566   */   */
567  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)  
568  {  {
569    int new_sock;    int new_sock;
570    socklen_t addrlen;    caller->addrlen = sizeof(caller->addr);
571    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);  
572    
573    if (new_sock < 0)    if (new_sock < 0)
574      return -1;      return -1;
575    if (ip != NULL) {  
576      *ip = from.sin_addr.s_addr;    caller->family = caller->addr.sa.sa_family;
577      /* DNS is now done asynchronously. We now only provide the IP address. */    if (port) {
578      strncpyz(caller, iptostr(*ip), 121);      if (caller->family == AF_INET)
579      *ip = ntohl(*ip);        *port = ntohs(caller->addr.s4.sin_port);
580    }  #ifdef IPV6
581    if (port != NULL)      else
582      *port = ntohs(from.sin_port);        *port = ntohs(caller->addr.s6.sin6_port);
583    /* Set up all the normal socket crap */  #endif
584      }
585    setsock(new_sock, (binary ? SOCK_BINARY : 0));    setsock(new_sock, (binary ? SOCK_BINARY : 0));
586    return new_sock;    return new_sock;
587  }  }
588    
589  /* Like open_telnet, but uses server & port specifications of dcc  /* Get DCC compatible address for a client to connect (e.g. 1660944385)
590     * If addr is not NULL, it should point to the listening socket's address.
591     * Otherwise, this function will try to figure out the public address of the
592     * machine, using listen_ip and natip.
593     * The result is a string useable for DCC requests
594   */   */
595  int open_telnet_dcc(int sock, char *server, char *port)  int getdccaddr(sockname_t *addr, char *s, size_t l)
596  {  {
597    int p;    char h[121];
598    unsigned long addr;    sockname_t name, *r = &name;
   char sv[500];  
   unsigned char c[4];  
599    
600    if (port != NULL)    if (addr)
601      p = atoi(port);      r = addr;
602    else    else
603      p = 2000;      setsockname(r, listen_ip, 0, 1);
604    if (server != NULL)    if (
605      addr = my_atoul(server);  #ifdef IPV6
606          ((r->family == AF_INET6) &&
607          IN6_IS_ADDR_UNSPECIFIED(&r->addr.s6.sin6_addr)) ||
608    #endif
609          (r->family == AF_INET && !r->addr.s4.sin_addr.s_addr)) {
610          /* We can't send :: or 0.0.0.0 for dcc, so try
611             to figure out some real address */
612        r = &name;
613        gethostname(h, sizeof h);
614        setsockname(r, h, 0, 1);
615      }
616    
617      if (
618    #ifdef IPV6
619          ((r->family == AF_INET6) &&
620          IN6_IS_ADDR_UNSPECIFIED(&r->addr.s6.sin6_addr)) ||
621    #endif
622          (!natip[0] && (r->family == AF_INET) && !r->addr.s4.sin_addr.s_addr))
623        return 0;
624    
625    #ifdef IPV6
626      if (r->family == AF_INET6) {
627        if (IN6_IS_ADDR_V4MAPPED(&r->addr.s6.sin6_addr) ||
628            IN6_IS_ADDR_UNSPECIFIED(&r->addr.s6.sin6_addr))
629          snprintf(s, l, "%lu", natip[0] ? iptolong(inet_addr(natip)) :
630                   ntohl((IP) &r->addr.s6.sin6_addr.s6_addr[12]));
631    else    else
632      addr = 0L;        inet_ntop(AF_INET6, &r->addr.s6.sin6_addr, s, l);
633    if (addr < (1 << 24))    } else
634      return -3;                  /* fake address */  #endif
635    c[0] = (addr >> 24) & 0xff;    snprintf(s, l, "%lu", natip[0] ? iptolong(inet_addr(natip)) :
636    c[1] = (addr >> 16) & 0xff;               ntohl(r->addr.s4.sin_addr.s_addr));
637    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;  
638  }  }
639    
640  /* Builds the fd_sets for select(). Eggdrop only cares about readable  /* Builds the fd_sets for select(). Eggdrop only cares about readable
# Line 1212  int sanitycheck_dcc(char *nick, char *fr Line 1212  int sanitycheck_dcc(char *nick, char *fr
1212     * 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.
1213     */     */
1214    
1215    char badaddress[16];  #ifdef IPV6
1216      char badaddress[INET6_ADDRSTRLEN];
1217      sockname_t name;
1218      IP ip = 0;
1219    #else
1220      char badaddress[sizeof "255.255.255.255"];
1221    IP ip = my_atoul(ipaddy);    IP ip = my_atoul(ipaddy);
1222    #endif
1223    int prt = atoi(port);    int prt = atoi(port);
1224    
1225    /* 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 1231  int sanitycheck_dcc(char *nick, char *fr
1231             nick, from, prt);             nick, from, prt);
1232      return 0;      return 0;
1233    }    }
1234    sprintf(badaddress, "%u.%u.%u.%u", (ip >> 24) & 0xff, (ip >> 16) & 0xff,  #ifdef IPV6
1235            (ip >> 8) & 0xff, ip & 0xff);    if (strchr(ipaddy, ':')) {
1236    if (ip < (1 << 24)) {      if (inet_pton(AF_INET6, ipaddy, &name.addr.s6.sin6_addr) != 1) {
1237          putlog(LOG_MISC, "*", "ALERT: (%s!%s) specified an invalid IPv6 "
1238                 "address of %s!", nick, from, ipaddy);
1239          return 0;
1240        }
1241        if (IN6_IS_ADDR_V4MAPPED(&name.addr.s6.sin6_addr))
1242          ip = ntohl(*(IP *) &name.addr.s6.sin6_addr.s6_addr[12]);
1243      }
1244    #endif
1245      if (ip && inet_ntop(AF_INET, &ip, badaddress, sizeof badaddress) &&
1246          (ip < (1 << 24))) {
1247      putlog(LOG_MISC, "*", "ALERT: (%s!%s) specified an impossible IP of %s!",      putlog(LOG_MISC, "*", "ALERT: (%s!%s) specified an impossible IP of %s!",
1248             nick, from, badaddress);             nick, from, badaddress);
1249      return 0;      return 0;
# Line 1235  int sanitycheck_dcc(char *nick, char *fr Line 1251  int sanitycheck_dcc(char *nick, char *fr
1251    return 1;    return 1;
1252  }  }
1253    
1254  int hostsanitycheck_dcc(char *nick, char *from, IP ip, char *dnsname,  int hostsanitycheck_dcc(char *nick, char *from, sockname_t *ip, char *dnsname,
1255                          char *prt)                          char *prt)
1256  {  {
1257      char badaddress[INET6_ADDRSTRLEN];
1258    
1259    /* According to the latest RFC, the clients SHOULD be able to handle    /* According to the latest RFC, the clients SHOULD be able to handle
1260     * 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.
1261     */     */
1262    char hostn[256], badaddress[16];    char hostn[256];
1263    
1264    /* 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! */
1265    if (!dcc_sanitycheck)    if (!dcc_sanitycheck)
1266      return 1;      return 1;
1267    sprintf(badaddress, "%u.%u.%u.%u", (ip >> 24) & 0xff, (ip >> 16) & 0xff,    strcpy(badaddress, iptostr(&ip->addr.sa));
           (ip >> 8) & 0xff, ip & 0xff);  
1268    /* 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
1269     * where the routines providing our data currently lose interest. I'm     * where the routines providing our data currently lose interest. I'm
1270     * using the n-variant in case someone changes that...     * using the n-variant in case someone changes that...

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.2

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23