Logo Search packages:      
Sourcecode: lft version File versions  Download package

whois.c

/*  Handle communication with whois servers. 
 *  Includes:
 *          - simplified access to regular expressions
 *          - tokenizer
 *          - lookup functions for AS and NETNAME, working with
 *            ARIN, RIPE, APNIC as well as RA. Will do recursive
 *            lookups as well.
 *          - Convenient framework for further whois digging.
 *
 *    To compile:
 *                cc -o w whois.c -DSTANDALONE
 *
 *          (c) 2002 Ugen Antsilevitch (ugen@xonix.com)
 *
 * This file is part of LFT.
 *
 * The LFT software provided in this Distribution is
 * Copyright 2002 MainNerve, Inc.
 *
 * The full text of our legal notices is contained in the file called
 * COPYING, included with this Distribution.
 *
 *
 */

#ifdef WIN32
#include <windows.h>
#include <stdio.h>
#include <string.h>
#define read(a, b, c)   recv(a, b, c, 0)
#define write(a, b, c)  send(a, b, c, 0)
#define close(s) closesocket(s)
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <netdb.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#ifdef sun
#include <strings.h>
#endif
#endif

#define ASSERT(x) if (!(x)) { fprintf(stderr, "Assertion ("#x") failed\n"); exit(1); }

#ifdef WIN32
char *
index(char *s, char c)
{
      char *t;
      if (!s)
            return NULL;

      for (t = s; *t; t++)
            if (*t == c) {
                  return t;
            }

      /* Return terminating \0 if 
         specifically requested */
      if (c == '\0')
            return t;

      return NULL;
}
#endif

char *
lft_strndup(char *s, int len)
{
char *rs;

      if (!s || len < 0)
            return NULL;

      if ((int)strlen(s) <= len)
            return(strdup(s));

      if (!(rs = malloc(len + 1)))
            return NULL;

      if (len > 0)
            strncpy(rs, s, len);
      rs[len] = 0;

      return rs;
}

#ifdef WIN32
int
inet_aton(const char *cp, struct in_addr *pin)
{
      if (!pin)
            return -1;

      pin->s_addr = inet_addr(cp);
      return (pin->s_addr != -1) ? 1 : 0;
}
#endif

char *
strskip(char *buf, char *sep)
{
char *c;

      c = buf;
      while (*c != '\0') {
            if (index(sep, *c)) 
                  c++;
            else
                  break;
      }

      return c;
}

typedef struct token_s {
      char  *ptr;
} token_t;

token_t *
tokens(char *buf, char *sep)
{
char *c, *c1;
int size, cur;
token_t *rt;

      if (!buf || !sep)
            return NULL;

      size = 1;
      for (c = buf; *c ; c++) 
            if (index(sep, *c)) {
                  size++;
                  while (*c && index(sep, *c)) 
                              c++;
            }

      size++; /* for the NULL */

      if (!(rt = (token_t *)malloc(size * sizeof(token_t))))
            return NULL;

      memset(rt, 0, size * sizeof(token_t));

      rt[0].ptr = buf;
      cur = 0;

      for (c = buf; *c ; c++) {
            if (index(sep, *c)) {
                  c1 = c;
                  while (*c && index(sep, *c)) 
                              c++;
                  if (*c) 
                        rt[++cur].ptr = c;

                  *c1 = '\0';
            } 
      }

      rt[++cur].ptr = NULL;

      return rt;
}

typedef struct ip_blk_s {
      unsigned int      start;
      unsigned int      end;
} ip_blk_t;

ip_blk_t *
w_blk2range(char *s_start, char *s_end)
{
struct in_addr in;
unsigned int s, e;
ip_blk_t *r;

      if (!s_start || !s_end)
            return NULL;

      if (!inet_aton(s_start, &in))
            return NULL;

      s = ntohl(in.s_addr);

      if (!inet_aton(s_end, &in))
            return NULL;

      e = ntohl(in.s_addr);

      if (!(r = malloc(sizeof(ip_blk_t))))
            return NULL;

      r->start = s;
      r->end = e;
      return r;
}

ip_blk_t *
w_mask2range(char *addr, char *mask)
{
struct in_addr in;
unsigned int s, m;
ip_blk_t *r;

      if (!addr || !mask)
            return NULL;

      m = atoi(mask);
      if ((m < 0) || (m > 32))
            return NULL;

      if (!inet_aton(addr, &in))
            return NULL;

      s = ntohl(in.s_addr);

      if (!(r = malloc(sizeof(ip_blk_t))))
            return NULL;

      r->start = s &~ (((unsigned)0xffffffff) >> m);
      r->end = s | (((unsigned)0xffffffff) >> m);
      return r;
}
      
char *match_prefix(const char *prefix, const char *target)
{
  /* Target will be something like "origin:        AS22773" and prefix will be "origin:" and
   * we return a pointer to "AS22773" */
  while (*prefix) {
    if (tolower(*prefix) != tolower(*target))
      return NULL;
    prefix++;
    target++;
  }
  while (isspace(*target))
    target++;
  return strdup(target);
}

ip_blk_t *match_iprange(char *target)
{
  /* matches something like "1.2.3.4-5.6.7.8" */
  char *pos, *dash, *beforedash;
  ip_blk_t *out;

  while (isspace(*target))
    target++;
  pos = target;
  while (*pos && !isspace(*pos))
      pos++;

  beforedash = strdup(target);
  beforedash[pos-target] = 0;

  dash = strchr(target, '-');
  if (!dash)
    return NULL;
  dash++;
  while (isspace(*dash))
    dash++;

  return w_blk2range(beforedash, dash);
}

ip_blk_t *match_ipprefix(char *target)
{
  /* matches something like 1.2.3.0/24 */
  char *slash, *pos;
  char *beforeslash;
  ip_blk_t *out;

  while (isspace(*target))
    target++;
  pos = target;
  while (*pos && !isspace(*pos) && *pos != '/')
    pos++;
  beforeslash = strdup(target);
  beforeslash[pos - target] = 0;

  slash = strchr(target, '/');
  if (!slash) return NULL;

  slash++;

  return w_mask2range(beforeslash, slash);
}

char *match_inparens(char *target)
{
  /* matches something like "    (HELLO)" and returns "HELLO" */
  char *end, *res;

  target = strchr(target, '(');
  if (!target)
    return NULL;
  
  target++;
  end = strchr(target, ')');
  if (!end)
    return NULL;

  res = strdup(target);
  res[end - target] = 0;
  return res;
}

char *match_afterparens(char *target)
{
  /* matches something like "   (HELLO) xxx" and returns a pointer to "xxx" */
  target = strchr(target, '(');
  if (!target) return NULL;
  target = strchr(target, ')');
  if (!target) return NULL;
  target++;
  while(*target && isspace(*target)) target++;
  if (*target) return strdup(target);
  else return NULL;
}

void
w_init()
{
int e;

#ifdef WIN32
WORD wVersionRequested;
WSADATA wsaData;
      wVersionRequested = MAKEWORD( 2, 2 );
      WSAStartup( wVersionRequested, &wsaData );
#endif
}


#define PORT_WHOIS      43
char *
w_ask(char *serv, char *q)
{
int s;
struct sockaddr_in sin;
struct hostent *hp;
char *br;
int q_s, br_s, cur, n;
char buf[128];


      if (!serv || !q)
            return NULL;

      if (!(hp = gethostbyname(serv)))
            return NULL;

      sin.sin_family = AF_INET;
      sin.sin_port = htons(PORT_WHOIS);
      memcpy((void *)&sin.sin_addr, hp->h_addr, hp->h_length);

      if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0)
            return NULL;

      if (connect(s, (struct sockaddr *)&sin, sizeof (sin)) < 0) 
            return NULL;

      br_s = 512;
      if (!(br = malloc(br_s)))
            return NULL;

      q_s = strlen(q);
      if (write(s, q, q_s) != q_s || write(s, "\r\n", 2) != 2)
            return NULL;

      cur = 0;
      while ((n = read(s, buf, sizeof(buf))) > 0) {
            if ((cur + n) >= br_s) {
                  br_s = br_s * 2;
                  if (!(br = realloc(br, br_s)))
                        return NULL;
            }
            strncpy((char *)&br[cur], buf, n);
            cur += n;   
      }
      br[cur] = 0;

      close(s);

      return br;
}

char *
w_lookup_as(char *addr)
{
      token_t *ls;
      ip_blk_t *a = NULL, *b = NULL;
      char *sa, *sb;
      char *reply, *ans = NULL;
      int i;
      int use_this = 1;

      if (!addr)
            return NULL;

      reply = w_ask("whois.ra.net", addr);
      if (!reply)
            return NULL;
      ls = tokens(reply, "\n");

      for (i = 0; ls[i].ptr; i++) {
            char *value;
            if ((value = match_prefix("local-as:", ls[i].ptr))) {
                  if (ans)
                        free(ans);
                  ans = value;
                  break;
            }
            if ((value = match_prefix("route:", ls[i].ptr))) {
                  a = match_ipprefix(value);

                  if (b) {
                        if (((b->end - b->start) > (a->end - a->start))) {
                              use_this = 1;
                              free(b);
                              b = a;
                              a = NULL;
                        } else {
                              use_this = 0;
                              free(a);
                              a = NULL;
                        }
                  } else {
                        use_this = 1;
                        b = a;
                        a = NULL;
                  }
            }
            if (use_this && (value = match_prefix("origin:", ls[i].ptr))) {
                  if (ans)
                        free(ans);
                  ans = value;
            }
      }

      free(ls); free(reply); if (b) free(b);
      return ans;
}

char *
w_lookup_netname_other(char *addr, char *serv)
{
      token_t *ls;
      ip_blk_t *a = NULL, *b = NULL;
      char *reply, *ans = NULL;
      int i;
      int use_this = 1;

      if (!addr || !serv)
            return NULL;

      reply = w_ask(serv, addr);
      if (!reply)
            return NULL;
      ls = tokens(reply, "\n");

      for (i = 0; ls[i].ptr; i++) {
            char *value;
            if ((value = match_prefix("inetnum:", ls[i].ptr))) {
                  a = match_ipprefix(value);

                  if (b) {
                        if (((b->end - b->start) > (a->end - a->start))) {
                              use_this = 1;
                              free(b);
                              b = a;
                              a = NULL;
                        } else {
                              use_this = 0;
                              free(a);
                              a = NULL;
                        }
                  } else {
                        use_this = 1;
                        b = a;
                        a = NULL;
                  }
            }
            if (use_this && (value = match_prefix("netname:", ls[i].ptr))) {
                  if (ans)
                        free(ans);
                  ans = value;
            }
      }

      free(ls); free(reply); if (b) free(b);
      return ans;
}

char *
w_lookup_netname(char *addr)
{
      token_t *ls;
      ip_blk_t *a = NULL, *b = NULL;
      char *na = NULL, *nb = NULL;
      char *reply, *ans = NULL;
      int i;
      int have_new, have_old;

      if (!addr)
            return NULL;

      reply = w_ask("whois.arin.net", addr);
      if (!reply)
            return NULL;

      ls = tokens(reply, "\n");

      ans = NULL;
      for (i = 0; ls[i].ptr; i++) {
            char *value;
            if ((value = match_prefix("netname:", ls[i].ptr))) {
                  ans = value;
                  break;
            }
      }

      if (!ans) {

      for (i = 0; ls[i].ptr; i++) {
            char *value;
            if ((value = match_inparens(ls[i].ptr))) {
                  char *after = match_afterparens(ls[i].ptr);
                  if (after) {
                        na = value;
                        a = match_iprange(after);
                  } else {
                        na = value;
                        if (ls[i+1].ptr && (a = match_iprange(ls[i+1].ptr))) {
                          /* successful match */
                        } else { /* Bad format */
                              free(na); na = NULL;
                              continue;
                        }
                  }
            }

            have_new = (na && a);
            have_old = (nb && b);

            if (have_new) {
                  if (have_old) {
                        if (((b->end - b->start) > (a->end - a->start))) {
                              /* keep new, discard old */
                              free(nb); free(b);
                              nb = na; na = NULL;
                              b = a; a = NULL;
                        } else { /* keep old, discard new */
                              free(na); free(a);
                              na = NULL;
                              a = NULL;
                        }
                  } else { /* nothing old, save new */
                        nb = na; na = NULL;
                        b = a; a = NULL;
                  }
            }
      } /* loop */

      if (na) free(na);
      if (a) free(a);
      if (b) free(b);
      free(ls); free(reply);
      if (!nb)
            return NULL;

      /* Add "!" to the beginning of the question */
      na = malloc(strlen(nb) + 2);
      strcpy(&na[1], nb);
      na[0] = '!';
      free(nb);

      reply = w_ask("whois.arin.net", na);
      free(na);
      if (!reply)
            return NULL;

      ls = tokens(reply, "\n");

}
      for (i = 0; ls[i].ptr; i++) {
            char *value;
            if ((value = match_prefix("netname:", ls[i].ptr))) {
                  ans = value;
                  break;
            }
      }

      free(ls); free(reply); 

      {
        char *other = NULL;
        if (ans && strstr(ans, "RIPE")) {
          other = w_lookup_netname_other(addr, "whois.ripe.net");
        }
        
        if (ans && !strncmp(ans, "APNIC", 5)) {
          other = w_lookup_netname_other(addr, "whois.apnic.net");
        }

        if (other) {
          char *together = malloc(strlen(ans) + strlen(other) + 2);
          strcpy(together, ans);
          strcat(together, "/");
          strcat(together, other);
          free(ans);
          ans = together;
        }
      }
      

      return ans;
}
      


#ifdef STANDALONE
int main(int ac, char **av)
{
      struct hostent *he;
      char *addr;
      struct in_addr in;

      w_init();
      if (ac == 2) {
            if (inet_aton(av[1], &in)) {
                  addr = av[1];
            } else {
                  if (!(he = gethostbyname(av[1]))) {
                        printf("Cannot resolve %s\n", av[1]);
                        exit(0);
                  }

                  memcpy(&in, he->h_addr, he->h_length);
                  addr = inet_ntoa(in);
            }
            printf("Address: %s\n", addr);
            printf("Netname: %s\n", w_lookup_netname(addr));
            printf("AS: %s\n", w_lookup_as(addr));
      }
}
#endif


Generated by  Doxygen 1.6.0   Back to index