#include #include #include #include #include #include #include #include #include "as.h" #ifdef sun #include #else #include #endif #ifndef boolean #define boolean int #endif #ifndef TRUE #define TRUE (1==1) #endif #ifndef FALSE #define FALSE (!(TRUE)) #endif #define MAXREPLYLEN 8192 /* marks the end of a reply (in case of whois.ripe.net another welcome messages may follow ... shoudl do substr search sigh) */ #define REPLY_DELIMITER "\n\n\n" #define DEL_LENGTH strlen(REPLY_DELIMITER) #define DATA_DELIMITER "origin:" #define ROUTE_DELIMITER "route:" #define ROUTE_DELIMITER_IP6 "route6:" #define PREFIX_DELIMITER "/" #define MAX_RECONNECT 50 int reconnect_count = 0; void RRopen(char *server, char* service) { /* * Setup connection to the specified routing registry. * We assume a RIPE Whois like server, featuring a * 'keep alive' option so we don't have to go through the * expensive TCP connect and setup phases for each request. * Can be overridden by enviroment variable. [RW 20020813] */ char *cp; struct hostent *hp; struct servent *sp; char *getenv(); /* Wipe structure, we may be called more than once.. */ bzero(&RRsockaddr,sizeof(RRsockaddr)); if ((cp = getenv("IRR_SERVER")) == 0) { cp = server; } hp = gethostbyname(cp); if (hp == NULL) { fprintf(stderr, "RRconnect: host %s unknown\n", cp); exit(1); } /* * Create an IP-family socket on which to make the connection */ RRsock = socket(hp->h_addrtype, SOCK_STREAM, 0); if (RRsock < 0) { perror("RRconnect: socket"); exit(1); } /* * Get the TCP port number of the IRR server. * Again if this needs to be updated, the environment variable * IRR_SERVICE should be set. */ if ((cp = getenv("IRR_SERVICE")) == 0) { cp = service; } sp = getservbyname(cp,"tcp"); if (sp == NULL) { fprintf(stderr, "RRconnect: getservbyname: %s: unknown service\n", cp); exit(1); } /* * Create a "sockaddr_in" structure which describes the remote * IP address we want to connect to (from gethostbyname()) and * the remote TCP port number (from getservbyname()). */ RRsockaddr.sin_family = hp->h_addrtype; bcopy(hp->h_addr, (caddr_t) &RRsockaddr.sin_addr, hp->h_length); RRsockaddr.sin_port = sp->s_port; } void RRconnect() { int n, count; char buf[256]; static char reply[MAXREPLYLEN]; /* * Connect to the address */ retry_connect: if (connect(RRsock, (struct sockaddr *)&RRsockaddr, sizeof (RRsockaddr)) < 0) { perror("RRconnect: connect"); reconnect_count++; if (reconnect_count > MAX_RECONNECT) { /* serious trouble */ fprintf(stderr, "maximum number of reconnects reached, bailing out... \n"); exit(1); } goto retry_connect; } /* * Read the welcome message (terminated by empty line) */ count=0; do { if ((n = read(RRsock, buf, sizeof(buf))) > 0) { strncpy((char *)&reply[count],(char *)buf,n); count += n; } } while ((strncmp (&reply[count - 2], "\n\n", 2) != 0) && (n > 0)); #ifdef DEBUG reply[count] = '\0'; fprintf(stderr, "RRconnect: %s\n", reply); #endif /* * Send keep alive request to the server... */ write(RRsock, "-k\r\n", 4); count=0; #ifdef DEBUG reply[count] = '\0'; fprintf(stderr, "RRconnect: %s\n", reply); #endif } /* ------------------------------------------------------------------------------- Subroutine Header Purpose : assign origin AS to IP number input : IP (character strign), flag to indicate IPv6 or IPv4 returns : origin AS or NULL if not found Comments : This routine is a modified version of the get_origin function from traceroute-nanog-6.1.1 package ------------------------------------------------------------------------------- */ char *get_origin(char *net, int ip6flag) { char *i, *j; char tmp[100],tmp2[100],tmp3[100]; /* store string delimiters */ char tmp4[100]; /* here's where we store the AS */ static char origin[100]; /* the returned route origin */ char *rp; /* pointer to route: line */ char *pp; /* pointer to /prefix part of route */ int prefix; /* prefix off this line (decimal) */ int best_prefix; /* best prefix thus far */ int n, count; char buf[MAXREPLYLEN]; boolean done; static char reply[MAXREPLYLEN]; char *getenv(); done = FALSE; retry_write: sprintf(buf,"-T route -a %s\n", net); n = write(RRsock, buf, strlen(buf)); if (n < 0) { perror("get_origin: write"); fprintf(stderr, "attempting reconnect ... \n"); usleep(0.5); /* Completely reinitialize */ close(RRsock); RRopen(RR_SERVER, RR_SERVICE); RRconnect(); reconnect_count++; if (reconnect_count > MAX_RECONNECT) { /* serious trouble */ exit(1); } goto retry_write; } else if (n != strlen(buf)) { fprintf(stderr, "get_origin: write: wrote %d of %d bytes\n", n, strlen(buf)); fprintf(stderr, "attempting reconnect ... \n"); usleep(0.5); /* Completely reinitialize */ close(RRsock) ; RRopen(RR_SERVER, RR_SERVICE); RRconnect(); reconnect_count++; if (reconnect_count > MAX_RECONNECT) { /* serious trouble */ fprintf(stderr, "maximum number of reconnects reached, bailing out... \n"); exit(1); } goto retry_write; } #ifdef DEBUG fprintf(stderr, "%s\n\n",buf); #endif /* * Now get the entire answer in one long buffer... */ count = 0; #ifdef DEBUG fprintf(stderr,"doing read loop:\n"); #endif do { if ((n = read(RRsock, buf, sizeof(buf))) > 0) { strncpy((char *)&reply[count],(char *)buf,n); count += n; #ifdef DEBUG { int jjj; buf[n+3]='\0'; fprintf(stderr,"read %d bytes\n>>%s<<\n",n,buf); fprintf(stderr,"last %d bytes\n===\n", DEL_LENGTH); for (jjj=count-DEL_LENGTH; jjj<=count; jjj++) { fprintf(stderr, "%c", reply[jjj]); } fprintf(stderr,"===\n"); } #endif } } while ((strncmp (&reply[count - DEL_LENGTH], REPLY_DELIMITER, DEL_LENGTH) != 0) && (n > 0)); /* in RIPE whois server keep alive mode, reply ends with greeting have to search for DELIMITER in the whole reply } while ((strstr (reply, REPLY_DELIMITER) != NULL) && (n > 0)); */ #ifdef DEBUG fprintf(stderr,"done.\n"); #endif if (count > MAXREPLYLEN) { fprintf(stderr, "errorr: buffer length exceeded: available %d , read %d\n", count, MAXREPLYLEN); exit(1); } if (n < 0) { perror("get_origin: read"); return(0); } reply[count] = '\0'; /* Terminate reply */ #ifdef DEBUG fprintf(stderr, "reply: %s\n",reply); #endif /* * So now we have a large string, somewhere in which we can * find origin:*AS%%%%%%. We parse this into AS%%%%%. */ strcpy(tmp,DATA_DELIMITER); /* TMP2 will have the route delimiter... */ if (ip6flag) { strcpy(tmp2,ROUTE_DELIMITER_IP6); } else { strcpy(tmp2,ROUTE_DELIMITER); } strcpy(tmp3,PREFIX_DELIMITER); /* * Find the longest matching (=best) route in the returned objects */ best_prefix = 0; /* 0 bits is not very specific */ done = FALSE; /* not done finding route: entries */ rp = (char *)reply; /* initialize main pointer to buffer */ origin[0]='\0'; /* initialize returned string */ reply[MAXREPLYLEN-1]='\0'; rp = (char *)strstr(rp,tmp2); /* Find route: in the string */ while (rp != 0) { /* If there is such a thing... */ /* find it again later */ pp = (char *)strstr(rp,tmp3); /* Find / in the route entry */ if (pp == 0) { /* No prefix... */ prefix = 0; /* So we bias it out of here */ } else { prefix = atoi(pp+1); /* convert to decimal*/ } if (prefix >= best_prefix) { /* it's equal to or better */ i = (char *)strstr(pp,tmp); /* find origin: delimiter */ if (i != 0) { /* it's nice if there is one */ i += strlen(DATA_DELIMITER); /* skip delimiter... */ i++; /* and the colon... */ while (*i == ' ') i++; /* skip spaces */ /* i now points to start of origin AS string */ /* move 2 more forward to get the number itself [RW] */ i += 2; j = i; /* terminate... */ while (*j >= '0') j++; if (prefix > best_prefix) { strcpy(origin,"/"); /* put a slash in */ best_prefix = prefix; /* update best */ } else { strcat(origin,"/"); /* put a mutiple as separator*/ } strncpy(tmp4,i,(j-i)); /* copy new origin */ tmp4[j-i] = '\0'; /* null terminate it */ if (!(strstr(origin,tmp4))) { /* if it's not a dup */ /* search for changed fields, find latest, compare with previous date, if newer replace, if equal stick it in */ strncat(origin,i,(j-i)); /* stick it in */ } else { if (prefix == best_prefix) /* Otherwise remove slash */ origin[strlen(origin)-1] = '\0'; } /* end if not a dup */ } /* end if origin found */ } /* endif prefix > best_prefix */ rp = (char *)strstr(rp+1,tmp2); /* Find route: in the string */ } /* end while */ /* * Go home... */ if (best_prefix != 0) { /* did we get anything? */ return((char *)&origin[1]); /* strip off leading slash */ } else { return(0); } }