my last attempt to do this fetched info from bgpd, which is great for
some things, but not so many people could use it. 

this version uses cymru.com's dns based lookups instead (nicer than
the various other traceroute implementations which do this using whois
lookups, as of course this gets cached by the dns infrastructure).

$ traceroute -A www.cymru.com                                
traceroute to www.cymru.com (68.22.187.34), 64 hops max, 40 byte packets
 1  jodrell (85.158.44.145) [AS3213]  0.417 ms  0.405 ms  0.356 ms
 2  ar0.rbsov.bogons.net (193.178.223.245) [AS3213]  264.111 ms  282.787 ms  
298.318 ms
 3  cr0-Vl456.rbsov.bogons.net (194.39.143.145) [AS3213]  13.201 ms  13.52 ms  
13.98 ms
 4  tge1-4.fr3.lon.llnw.net (195.66.224.133) [AS10310, AS5459]  13.351 ms  
13.407 ms  24.104 ms
 5  tge7-2.fr3.lga.llnw.net (69.28.171.125) [AS22822]  81.68 ms  92.952 ms  
90.74 ms
 6  tge13-1.fr3.ord.llnw.net (68.142.125.45) [AS22822]  111.914 ms 
tge8-4.fr3.ord.llnw.net (69.28.171.193) [AS22822]  107.509 ms  117.249 ms
 7  ve8.fr3.ord4.llnw.net (68.142.80.130) [AS22822]  108.281 ms  117.217 ms  
113.301 ms
 8  cymru.tge6-3.fr3.ord4.llnw.net (68.142.73.198) [AS22822]  105.921 ms  
103.310 ms  103.68 ms
 9  va06.ord08.cymru.com (38.229.35.4) [AS23028]  107.156 ms  106.876 ms  
103.517 ms
10  serv27.ord01.cymru.com (68.22.187.34) [AS23028]  103.435 ms  106.849 ms  
106.439 ms

note there are some addresses (like hop 4 above) which return multiple
entries (see http://www.team-cymru.org/Services/ip-to-asn.html for info),
currently the code just lists all of them and doesn't dedup.

$ dig +short 133.224.66.195.origin.asn.cymru.com txt
"10310 | 195.66.224.0/23 | GB | ripencc | 1997-12-01"
"5459 | 195.66.224.0/19 | GB | ripencc | 1997-12-01"

$ dig +short 241.92.52.72.origin.asn.cymru.com txt
"6939 | 72.52.92.0/24 | US | arin | 2006-08-04"
"6939 | 72.52.64.0/18 | US | arin | 2006-08-04"


Index: traceroute.c
===================================================================
RCS file: /cvs/src/usr.sbin/traceroute/traceroute.c,v
retrieving revision 1.78
diff -u -p -r1.78 traceroute.c
--- traceroute.c        17 Sep 2011 14:10:05 -0000      1.78
+++ traceroute.c        3 Nov 2011 00:32:05 -0000
@@ -219,6 +219,7 @@
 #include <netinet/udp.h>
 
 #include <arpa/inet.h>
+#include <arpa/nameser.h>
 
 #include <netmpls/mpls.h>
 
@@ -260,6 +261,7 @@ int packet_ok(u_char *, int, struct sock
 void print_exthdr(u_char *, int);
 void print(u_char *, int, struct sockaddr_in *);
 char *inetname(struct in_addr);
+void print_asn(struct in_addr);
 u_short in_cksum(u_short *, int);
 int map_tos(char *, int *);
 void usage(void);
@@ -288,6 +290,7 @@ int nflag;                  /* print addresses numerica
 int dump;
 int xflag;                     /* show ICMP extension header */
 int tflag;                     /* tos flag was set */
+int Aflag;                     /* lookup ASN */
 
 int
 main(int argc, char *argv[])
@@ -322,12 +325,15 @@ main(int argc, char *argv[])
        (void) sysctl(mib, sizeof(mib)/sizeof(mib[0]), &max_ttl, &size,
            NULL, 0);
 
-       while ((ch = getopt(argc, argv, "cDdf:g:Ilm:nP:p:q:rSs:t:V:vw:x"))
+       while ((ch = getopt(argc, argv, "AcDdf:g:Ilm:nP:p:q:rSs:t:V:vw:x"))
                        != -1)
                switch (ch) {
                case 'S':
                        sump = 1;
                        break;
+               case 'A':
+                       Aflag++;
+                       break;
                case 'f':
                        errno = 0;
                        ep = NULL;
@@ -1113,6 +1119,8 @@ print(u_char *buf, int cc, struct sockad
        else
                printf(" %s (%s)", inetname(from->sin_addr),
                    inet_ntoa(from->sin_addr));
+       if (Aflag)
+               print_asn(from->sin_addr);
 
        if (verbose)
                printf(" %d bytes to %s", cc, inet_ntoa(ip->ip_dst));
@@ -1183,6 +1191,35 @@ inetname(struct in_addr in)
        return (inet_ntoa(in));
 }
 
+void
+print_asn(struct in_addr in)
+{
+       const u_char *uaddr = (const u_char *)&in.s_addr;
+       int n, i, counter;
+       struct rrsetinfo *answers = NULL;
+       char qbuf[MAXDNAME+1];
+
+       (void) snprintf(qbuf, sizeof qbuf, "%u.%u.%u.%u.origin.asn.cymru.com",
+           (uaddr[3] & 0xff), (uaddr[2] & 0xff),
+           (uaddr[1] & 0xff), (uaddr[0] & 0xff));
+       if (n = getrrsetbyname(qbuf, C_IN, T_TXT, 0, &answers))
+               return;
+       for (counter = 0; counter < answers->rri_nrdatas; counter++) {
+               char *p, *as = answers->rri_rdatas[counter].rdi_data;
+               as++; /* skip first byte, it contains length */
+               if (p = strchr(as,'|')) {
+                       printf(counter ? ", " : " [");
+                       p[-1] = 0;
+                       printf("AS%s", as);
+               }
+       }
+       if (counter)
+               printf("]");
+
+       freerrset(answers);
+       return;
+}
+
 int
 map_tos(char *s, int *val)
 {
@@ -1237,7 +1274,7 @@ usage(void)
        extern char *__progname;
 
        fprintf(stderr,
-           "usage: %s [-cDdIlnrSvx] [-f first_ttl] [-g gateway_addr] [-m 
max_ttl]\n"
+           "usage: %s [-AcDdIlnrSvx] [-f first_ttl] [-g gateway_addr] [-m 
max_ttl]\n"
            "\t[-P proto] [-p port] [-q nqueries] [-s src_addr] [-t 
toskeyword]\n"
            "\t[-V rtable] [-w waittime] host [packetsize]\n", __progname);
        exit(1);

Reply via email to