Diff for /embedaddon/iftop/resolver.c between versions 1.1.1.1 and 1.1.1.2

version 1.1.1.1, 2012/02/21 16:57:34 version 1.1.1.2, 2016/10/18 14:04:50
Line 25 Line 25
   
 #define RESOLVE_QUEUE_LENGTH 20  #define RESOLVE_QUEUE_LENGTH 20
   
struct in_addr resolve_queue[RESOLVE_QUEUE_LENGTH];struct addr_storage {
     int af;                     /* AF_INET or AF_INET6 */
     int len;                    /* sizeof(struct in_addr or in6_addr) */
     union {
         struct in_addr  addr4;
         struct in6_addr addr6;
     } addr;
 #define as_addr4 addr.addr4
 #define as_addr6 addr.addr6
 };
   
   struct addr_storage resolve_queue[RESOLVE_QUEUE_LENGTH];
   
 pthread_cond_t resolver_queue_cond;  pthread_cond_t resolver_queue_cond;
 pthread_mutex_t resolver_queue_mutex;  pthread_mutex_t resolver_queue_mutex;
   
Line 55  extern options_t options; Line 66  extern options_t options;
  * as NetBSD break the RFC and implement it in a non-thread-safe fashion, so   * as NetBSD break the RFC and implement it in a non-thread-safe fashion, so
  * for the moment, the configure script won't try to use it.   * for the moment, the configure script won't try to use it.
  */   */
char *do_resolve(struct in_addr *addr) {char *do_resolve(struct addr_storage *addr) {
    struct sockaddr_in sin = {0};    struct sockaddr_in sin;
     struct sockaddr_in6 sin6;
     char buf[NI_MAXHOST]; /* 1025 */      char buf[NI_MAXHOST]; /* 1025 */
    int res;    int ret;
    sin.sin_family = AF_INET; 
    sin.sin_addr = *addr; 
    sin.sin_port = 0; 
   
    if (getnameinfo((struct sockaddr*)&sin, sizeof sin, buf, sizeof buf, NULL, 0, NI_NAMEREQD) == 0)    switch (addr->af) {
         case AF_INET:
             sin.sin_family = addr->af;
             sin.sin_port = 0;
             memcpy(&sin.sin_addr, &addr->as_addr4, addr->len);
 
             ret = getnameinfo((struct sockaddr*)&sin, sizeof sin,
                               buf, sizeof buf, NULL, 0, NI_NAMEREQD);
             break;
         case AF_INET6:
             sin6.sin6_family = addr->af;
             sin6.sin6_port = 0;
             memcpy(&sin6.sin6_addr, &addr->as_addr6, addr->len);
 
             ret = getnameinfo((struct sockaddr*)&sin6, sizeof sin6,
                               buf, sizeof buf, NULL, 0, NI_NAMEREQD);
             break;
         default:
             return NULL;
     }
 
     if (ret == 0)
         return xstrdup(buf);          return xstrdup(buf);
     else      else
         return NULL;          return NULL;
Line 76  char *do_resolve(struct in_addr *addr) { Line 106  char *do_resolve(struct in_addr *addr) {
  * Some implementations of libc choose to implement gethostbyaddr_r as   * Some implementations of libc choose to implement gethostbyaddr_r as
  * a non thread-safe wrapper to gethostbyaddr.  An interesting choice...   * a non thread-safe wrapper to gethostbyaddr.  An interesting choice...
  */   */
char* do_resolve(struct in_addr * addr) {char* do_resolve(struct addr_storage *addr) {
    struct hostent hostbuf, *hp;    struct hostent hostbuf, *hp = NULL;
     size_t hstbuflen = 1024;      size_t hstbuflen = 1024;
     char *tmphstbuf;      char *tmphstbuf;
    int res;    int res = 0;
     int herr;      int herr;
     char * ret = NULL;      char * ret = NULL;
   
    /* Allocate buffer, remember to free it to avoid memory leakage.  */                /* Allocate buffer, remember to free it to avoid memory leakage. */
     tmphstbuf = xmalloc (hstbuflen);      tmphstbuf = xmalloc (hstbuflen);
   
       /* nss-myhostname's gethostbyaddr_r() causes an assertion failure if an
        * "invalid" (as in outside of IPv4 or IPv6) address family is passed */
       if (addr->af == AF_INET || addr->af == AF_INET6) {
   
     /* Some machines have gethostbyaddr_r returning an integer error code; on      /* Some machines have gethostbyaddr_r returning an integer error code; on
      * others, it returns a struct hostent*. */       * others, it returns a struct hostent*. */
 #ifdef GETHOSTBYADDR_R_RETURNS_INT  #ifdef GETHOSTBYADDR_R_RETURNS_INT
    while ((res = gethostbyaddr_r((char*)addr, sizeof(struct in_addr), AF_INET,    while ((res = gethostbyaddr_r((char*)&addr->addr, addr->len, addr->af,
                                   &hostbuf, tmphstbuf, hstbuflen,                                    &hostbuf, tmphstbuf, hstbuflen,
                                   &hp, &herr)) == ERANGE)                                    &hp, &herr)) == ERANGE)
 #else  #else
     /* ... also assume one fewer argument.... */      /* ... also assume one fewer argument.... */
    while ((hp = gethostbyaddr_r((char*)addr, sizeof(struct in_addr), AF_INET,    while ((hp = gethostbyaddr_r((char*)&addr->addr, addr->len, addr->af,
                           &hostbuf, tmphstbuf, hstbuflen, &herr)) == NULL                                 &hostbuf, tmphstbuf, hstbuflen, &herr)) == NULL
             && errno == ERANGE)              && errno == ERANGE)
 #endif  #endif
             {              {
Line 105  char* do_resolve(struct in_addr * addr) { Line 139  char* do_resolve(struct in_addr * addr) {
         hstbuflen *= 2;          hstbuflen *= 2;
         tmphstbuf = realloc (tmphstbuf, hstbuflen);          tmphstbuf = realloc (tmphstbuf, hstbuflen);
       }        }
       }
   
     /*  Check for errors.  */      /*  Check for errors.  */
     if (res || hp == NULL) {      if (res || hp == NULL) {
Line 125  char* do_resolve(struct in_addr * addr) { Line 160  char* do_resolve(struct in_addr * addr) {
  * Implementation using gethostbyname. Since this is nonreentrant, we have to   * Implementation using gethostbyname. Since this is nonreentrant, we have to
  * wrap it in a mutex, losing all benefit of multithreaded resolution.   * wrap it in a mutex, losing all benefit of multithreaded resolution.
  */   */
char *do_resolve(struct in_addr *addr) {char *do_resolve(struct addr_storage *addr) {
     static pthread_mutex_t ghba_mtx = PTHREAD_MUTEX_INITIALIZER;      static pthread_mutex_t ghba_mtx = PTHREAD_MUTEX_INITIALIZER;
     char *s = NULL;      char *s = NULL;
     struct hostent *he;      struct hostent *he;
     pthread_mutex_lock(&ghba_mtx);      pthread_mutex_lock(&ghba_mtx);
    he = gethostbyaddr((char*)addr, sizeof *addr, AF_INET);    he = gethostbyaddr((char*)&addr->addr, addr->len, addr->af);
     if (he)      if (he)
         s = xstrdup(he->h_name);          s = xstrdup(he->h_name);
     pthread_mutex_unlock(&ghba_mtx);      pthread_mutex_unlock(&ghba_mtx);
Line 147  char *do_resolve(struct in_addr *addr) { Line 182  char *do_resolve(struct in_addr *addr) {
  * libresolv implementation    * libresolv implementation 
  * resolver functions may not be thread safe   * resolver functions may not be thread safe
  */   */
char* do_resolve(struct in_addr * addr) {char* do_resolve(struct addr_storage *addr) {
   char msg[PACKETSZ];    char msg[PACKETSZ];
   char s[35];    char s[35];
   int l;    int l;
   unsigned char* a;    unsigned char* a;
   char * ret = NULL;    char * ret = NULL;
   
  a = (unsigned char*)addr;  if (addr->af != AF_INET)
     return NULL;
   
     a = (unsigned char*)&addr->addr;
   
   snprintf(s, 35, "%d.%d.%d.%d.in-addr.arpa.",a[3], a[2], a[1], a[0]);    snprintf(s, 35, "%d.%d.%d.%d.in-addr.arpa.",a[3], a[2], a[1], a[0]);
   
   l = res_search(s, C_IN, T_PTR, msg, PACKETSZ);    l = res_search(s, C_IN, T_PTR, msg, PACKETSZ);
Line 212  static void do_resolve_ares_callback(void *arg, int st Line 250  static void do_resolve_ares_callback(void *arg, int st
     }      }
 }  }
   
char *do_resolve(struct in_addr * addr) {char *do_resolve(struct addr_storage * addr) {
     struct ares_callback_comm C;      struct ares_callback_comm C;
     char s[35];      char s[35];
     unsigned char *a;      unsigned char *a;
Line 221  char *do_resolve(struct in_addr * addr) { Line 259  char *do_resolve(struct in_addr * addr) {
     static pthread_key_t ares_key;      static pthread_key_t ares_key;
     static int gotkey;      static int gotkey;
   
       if (addr->af != AF_INET)
           return NULL;
   
     /* Make sure we have an ARES channel for this thread. */      /* Make sure we have an ARES channel for this thread. */
     pthread_mutex_lock(&ares_init_mtx);      pthread_mutex_lock(&ares_init_mtx);
     if (!gotkey) {      if (!gotkey) {
Line 237  char *do_resolve(struct in_addr * addr) { Line 278  char *do_resolve(struct in_addr * addr) {
         if (ares_init(chan) != ARES_SUCCESS) return NULL;          if (ares_init(chan) != ARES_SUCCESS) return NULL;
     }      }
           
    a = (unsigned char*)addr;    a = (unsigned char*)&addr->as_addr4;
     sprintf(s, "%d.%d.%d.%d.in-addr.arpa.", a[3], a[2], a[1], a[0]);      sprintf(s, "%d.%d.%d.%d.in-addr.arpa.", a[3], a[2], a[1], a[0]);
           
     C.result = 0;      C.result = 0;
    C.addr = addr;    C.addr = &addr->as_addr4;
     ares_query(*chan, s, C_IN, T_PTR, do_resolve_ares_callback, &C);      ares_query(*chan, s, C_IN, T_PTR, do_resolve_ares_callback, &C);
     while (C.result == 0) {      while (C.result == 0) {
         int n;          int n;
Line 278  char *do_resolve(struct in_addr * addr) { Line 319  char *do_resolve(struct in_addr * addr) {
   
 int forking_resolver_worker(int fd) {  int forking_resolver_worker(int fd) {
     while (1) {      while (1) {
        struct in_addr a;        struct addr_storage a;
         struct hostent *he;          struct hostent *he;
         char buf[NAMESIZE] = {0};          char buf[NAMESIZE] = {0};
         if (read(fd, &a, sizeof a) != sizeof a)          if (read(fd, &a, sizeof a) != sizeof a)
             return -1;              return -1;
   
        he = gethostbyaddr((char*)&a, sizeof a, AF_INET);        he = gethostbyaddr((char*)&a.addr, a.len, a.af);
         if (he)          if (he)
             strncpy(buf, he->h_name, NAMESIZE - 1);              strncpy(buf, he->h_name, NAMESIZE - 1);
   
Line 293  int forking_resolver_worker(int fd) { Line 334  int forking_resolver_worker(int fd) {
     }      }
 }  }
   
char *do_resolve(struct in_addr *addr) {char *do_resolve(struct in6_addr *addr) {
     struct {      struct {
         int fd;          int fd;
         pid_t child;          pid_t child;
Line 358  char *do_resolve(struct in_addr *addr) { Line 399  char *do_resolve(struct in_addr *addr) {
   
 #   warning No name resolution method specified; name resolution will not work  #   warning No name resolution method specified; name resolution will not work
   
char *do_resolve(struct in_addr *addr) {char *do_resolve(struct addr_storage *addr) {
     return NULL;      return NULL;
 }  }
   
Line 376  void resolver_worker(void* ptr) { Line 417  void resolver_worker(void* ptr) {
         /* Keep resolving until the queue is empty */          /* Keep resolving until the queue is empty */
         while(head != tail) {          while(head != tail) {
             char * hostname;              char * hostname;
            struct in_addr addr = resolve_queue[tail];            struct addr_storage addr = resolve_queue[tail];
   
             /* mutex always locked at this point */              /* mutex always locked at this point */
   
Line 427  void resolver_initialise() { Line 468  void resolver_initialise() {
   
 }  }
   
void resolve(struct in_addr* addr, char* result, int buflen) {void resolve(int af, void* addr, char* result, int buflen) {
     char* hostname;      char* hostname;
     union {      union {
         char **ch_pp;          char **ch_pp;
         void **void_pp;          void **void_pp;
     } u_hostname = { &hostname };      } u_hostname = { &hostname };
     int added = 0;      int added = 0;
       struct addr_storage *raddr;
   
     if(options.dnsresolution == 1) {      if(options.dnsresolution == 1) {
   
           raddr = malloc(sizeof *raddr);
           memset(raddr, 0, sizeof *raddr);
           raddr->af = af;
           raddr->len = (af == AF_INET ? sizeof(struct in_addr)
                         : sizeof(struct in6_addr));
           memcpy(&raddr->addr, addr, raddr->len);
   
         pthread_mutex_lock(&resolver_queue_mutex);          pthread_mutex_lock(&resolver_queue_mutex);
   
        if(hash_find(ns_hash, addr, u_hostname.void_pp) == HASH_STATUS_OK) {        if(hash_find(ns_hash, raddr, u_hostname.void_pp) == HASH_STATUS_OK) {
            /* Found => already resolved, or on the queue */            /* Found => already resolved, or on the queue, no need to keep
              * it around */
             free(raddr);
         }          }
         else {          else {
            hostname = strdup(inet_ntoa(*addr));            hostname = xmalloc(INET6_ADDRSTRLEN);
            hash_insert(ns_hash, addr, hostname);            inet_ntop(af, &raddr->addr, hostname, INET6_ADDRSTRLEN);
   
               hash_insert(ns_hash, raddr, hostname);
   
             if(((head + 1) % RESOLVE_QUEUE_LENGTH) == tail) {              if(((head + 1) % RESOLVE_QUEUE_LENGTH) == tail) {
                 /* queue full */                  /* queue full */
             }              }
               else if ((af == AF_INET6)
                        && (IN6_IS_ADDR_LINKLOCAL(&raddr->as_addr6)
                            || IN6_IS_ADDR_SITELOCAL(&raddr->as_addr6))) {
                   /* Link-local and site-local stay numerical. */
               }
             else {              else {
                resolve_queue[head] = *addr;                resolve_queue[head] = *raddr;
                 head = (head + 1) % RESOLVE_QUEUE_LENGTH;                  head = (head + 1) % RESOLVE_QUEUE_LENGTH;
                 added = 1;                  added = 1;
             }              }

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.2


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>