From: R.E. Wolff Date: Wed, 24 Apr 2013 09:35:52 +0000 (+0200) Subject: Added Yakovetsky Vladimir (vsyakovetsky)'s asn/ipinfo patch from launchpad bugs... X-Git-Tag: v0.85~19 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=03f3da5c3fd79a264255bcf13f73621fc366a676;p=thirdparty%2Fmtr.git Added Yakovetsky Vladimir (vsyakovetsky)'s asn/ipinfo patch from launchpad bugs. (701514) --- diff --git a/Makefile.am b/Makefile.am index c73a069..ed06db8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -6,7 +6,6 @@ install-exec-hook: chmod u+s $(DESTDIR)$(sbindir)/mtr mtr_SOURCES = mtr.c \ - asn.c asn.h \ net.c net.h \ dns.c dns.h \ raw.c raw.h \ @@ -17,6 +16,11 @@ mtr_SOURCES = mtr.c \ select.c select.h \ mtr-curses.h \ mtr-gtk.h + +if IPINFO +mtr_SOURCES += asn.c asn.h +endif + nodist_mtr_SOURCES = version.h EXTRA_mtr_SOURCES = curses.c \ gtk.c diff --git a/asn.c b/asn.c index c4ad0f1..f384f19 100644 --- a/asn.c +++ b/asn.c @@ -16,9 +16,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "asn.h" - #include +#include #include #include @@ -34,15 +33,42 @@ #include #include #include +#include +#include "config.h" +#include "mtr.h" +#include "asn.h" -int PrintAS = 0; -#ifndef NO_GLIB -GHashTable * ashash = NULL; +/* +#ifndef IIDEBUG +#define IIDEBUG +#include #endif +*/ + +#define IIHASH_HI 128 +#define ITEMSMAX 15 +#define ITEMSEP '|' +#define NAMELEN 127 +#define UNKN "???" + +int ipinfo_no = -1; +int ipinfo_max = -1; +int iihash = 0; +char fmtinfo[32]; +extern int af; /* address family of remote target */ + +// items width: ASN, Route, Country, Registry, Allocated +int iiwidth[] = { 6, 19, 4, 8, 11}; // item len + space +int iiwidth_len = sizeof(iiwidth)/sizeof((iiwidth)[0]); -char *asn_lookup(const char *domain) -{ +typedef char* items_t[ITEMSMAX + 1]; +items_t items_a; // without hash: items +char txtrec[NAMELEN + 1]; // without hash: txtrec +items_t* items = &items_a; + + +char *ipinfo_lookup(const char *domain) { unsigned char answer[PACKETSZ], *pt; char host[128]; char *txt; @@ -56,7 +82,11 @@ char *asn_lookup(const char *domain) memset(answer, 0, PACKETSZ); if((len = res_query(domain, C_IN, T_TXT, answer, PACKETSZ)) < 0) { - return "-1"; +#ifdef IIDEBUG + if (iihash) + syslog(LOG_INFO, "Malloc-txt: %s", UNKN); +#endif + return (iihash)?strdup(UNKN):UNKN; } pt = answer + sizeof(HEADER); @@ -85,6 +115,7 @@ char *asn_lookup(const char *domain) } pt += INT16SZ; /* class */ + pt += INT32SZ; /* ttl */ GETSHORT(size, pt); txtlen = *pt; @@ -93,16 +124,186 @@ char *asn_lookup(const char *domain) printf("@Broken TXT record (txtlen = %d, size = %d)\n", txtlen, size); return NULL; } - if(!(txt = malloc(txtlen + 1))) - return NULL; + if (txtlen > NAMELEN) + txtlen = NAMELEN; + + if (iihash) { + if (!(txt = malloc(txtlen + 1))) + return NULL; + } else + txt = (char*)txtrec; pt++; strncpy(txt, (char*) pt, txtlen); txt[txtlen] = 0; +#ifdef IIDEBUG + if (iihash) + syslog(LOG_INFO, "Malloc-txt(%p): %s", txt, txt); +#endif + return txt; } +char* trimsep(char *s) { + int l; + char *p = s; + while (*p == ' ' || *p == ITEMSEP) + *p++ = '\0'; + for (l = strlen(p)-1; p[l] == ' ' || p[l] == ITEMSEP; l--) + p[l] = '\0'; + return p; +} + +// originX.asn.cymru.com txtrec: ASN | Route | Country | Registry | Allocated +char* split_txtrec(char *txtrec) { + if (!txtrec) + return NULL; + if (iihash) { +#ifdef IIDEBUG + syslog(LOG_INFO, "Malloc-tbl: %s", txtrec); +#endif + if (!(items = malloc(sizeof(*items)))) { +#ifdef IIDEBUG + syslog(LOG_INFO, "Free-txt(%p)", txtrec); +#endif + free(txtrec); + return NULL; + } + } + + char* prev = (*items)[0] = trimsep(txtrec); + char* next; + int i = 0, j; + + while ((next = strchr(prev, ITEMSEP)) && (i < ITEMSMAX)) { + *next++ = '\0'; + (*items)[i++] = trimsep(prev); + (*items)[i] = prev = trimsep(next); + } + if (i < ITEMSMAX) + i++; + for (j = i; j <= ITEMSMAX; j++) + (*items)[j] = NULL; + + if (i > ipinfo_max) + ipinfo_max = i; + if (ipinfo_no >= i) { + if (ipinfo_no >= ipinfo_max) + ipinfo_no = 0; + return (*items)[0]; + } else + return (*items)[ipinfo_no]; +} + +#ifdef ENABLE_IPV6 +// from dns.c:addr2ip6arpa() +void reverse_host6(struct in6_addr *addr, char *buff) { + int i; + char *b = buff; + for (i=(sizeof(*addr)/2-1); i>=0; i--, b+=4) // 64b portion + sprintf(b, "%x.%x.", addr->s6_addr[i] & 0xf, addr->s6_addr[i] >> 4); + buff[strlen(buff) - 1] = '\0'; +} +#endif + +char *get_ipinfo(ip_t *addr) { + if (!addr) + return NULL; + + char key[NAMELEN]; + char lookup_key[NAMELEN]; + + if (af == AF_INET6) { +#ifdef ENABLE_IPV6 + reverse_host6(addr, key); + if (snprintf(lookup_key, NAMELEN, "%s.origin6.asn.cymru.com", key) >= NAMELEN) + return NULL; +#else + return NULL; +#endif + } else { + unsigned char buff[4]; + memcpy(buff, addr, 4); + if (snprintf(key, NAMELEN, "%d.%d.%d.%d", buff[3], buff[2], buff[1], buff[0]) >= NAMELEN) + return NULL; + if (snprintf(lookup_key, NAMELEN, "%s.origin.asn.cymru.com", key) >= NAMELEN) + return NULL; + } + + char *val = NULL; + ENTRY item; + + if (iihash) { +#ifdef IIDEBUG + syslog(LOG_INFO, ">> Search: %s", key); +#endif + item.key = key;; + ENTRY *found_item; + if ((found_item = hsearch(item, FIND))) { + if (!(val = (*((items_t*)found_item->data))[ipinfo_no])) + val = (*((items_t*)found_item->data))[0]; +#ifdef IIDEBUG + syslog(LOG_INFO, "Found (hashed): %s", val); +#endif + } + } + + if (!val) { +#ifdef IIDEBUG + syslog(LOG_INFO, "Lookup: %s", key); +#endif + if ((val = split_txtrec(ipinfo_lookup(lookup_key)))) { +#ifdef IIDEBUG + syslog(LOG_INFO, "Looked up: %s", key); +#endif + if (iihash) + if ((item.key = strdup(key))) { + item.data = items; + hsearch(item, ENTER); +#ifdef IIDEBUG + syslog(LOG_INFO, "Insert into hash: %s", key); +#endif + } + } + } + + return val; +} + +int get_iiwidth(void) { + return (ipinfo_no < iiwidth_len) ? iiwidth[ipinfo_no] : iiwidth[ipinfo_no % iiwidth_len]; +} + +char *fmt_ipinfo(ip_t *addr) { + char *ipinfo = get_ipinfo(addr); + char fmt[8]; + snprintf(fmt, sizeof(fmt), "%s%%-%ds", ipinfo_no?"":"AS", get_iiwidth()); + snprintf(fmtinfo, sizeof(fmtinfo), fmt, ipinfo?ipinfo:UNKN); + return fmtinfo; +} + +int is_printii(void) { + return ((ipinfo_no >= 0) && (ipinfo_no != ipinfo_max)); +} +void asn_open(void) { + if (ipinfo_no >= 0) { +#ifdef IIDEBUG + syslog(LOG_INFO, "hcreate(%d)", IIHASH_HI); +#endif + if (!(iihash = hcreate(IIHASH_HI))) + perror("ipinfo hash"); + } +} +void asn_close(void) { + if (iihash) { +#ifdef IIDEBUG + syslog(LOG_INFO, "hdestroy()"); +#endif + hdestroy(); + iihash = 0; + } +} diff --git a/asn.h b/asn.h index a493c36..d5a6bd3 100644 --- a/asn.h +++ b/asn.h @@ -16,16 +16,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include -#ifndef NO_GLIB -#include -#endif - -/* Prototypes for asn.c */ - -extern int PrintAS; -#ifndef NO_GLIB -extern GHashTable * ashash; -#endif -char *asn_lookup(const char *domain); +extern int ipinfo_no; +extern int ipinfo_max; +extern int iiwidth_len; +extern int iihash; +void asn_open(); +void asn_close(); +char *fmt_ipinfo(ip_t *addr); +int get_iiwidth(void); +int is_printii(void); diff --git a/configure.ac b/configure.ac index 5e2475f..ebcb993 100644 --- a/configure.ac +++ b/configure.ac @@ -45,6 +45,18 @@ AC_ARG_WITH(glib, [ --without-glib Do not try to use glib at all], WANTS_GLIB=$withval, WANTS_GLIB=yes) +AC_ARG_WITH([ipinfo], +[ --without-ipinfo Do not try to use ipinfo lookup at all], +[case "${withval}" in + yes) ipinfo=true ;; + no) ipinfo=false ;; + *) AC_MSG_ERROR([bad value ${withval} for --with-ipinfo]) ;; +esac],[ipinfo=true]) +AM_CONDITIONAL([IPINFO], [test x$ipinfo = xtrue]) +if test "x$ipinfo" = "xfalse"; then + AC_DEFINE([NO_IPINFO], [1], [Define to disable ipinfo lookup]) +fi + AC_ARG_ENABLE(ipv6, [ --disable-ipv6 Do not enable IPv6], WANTS_IPV6=$enableval, WANTS_IPV6=yes) diff --git a/curses.c b/curses.c index 864e754..2e3bda1 100644 --- a/curses.c +++ b/curses.c @@ -63,11 +63,10 @@ #include "display.h" #include "net.h" #include "dns.h" +#ifndef NO_IPINFO #include "asn.h" -#include "version.h" -#ifndef NO_GLIB -#include #endif +#include "version.h" #endif #include @@ -122,6 +121,12 @@ int mtr_curses_keyaction(void) return ActionMPLS; if (tolower(c) == 'n') return ActionDNS; +#ifndef NO_IPINFO + if (tolower(c) == 'y') + return ActionII; + if (tolower(c) == 'z') + return ActionAS; +#endif if (c == '+') return ActionScrollDown; if (c == '-') @@ -268,6 +273,7 @@ int mtr_curses_keyaction(void) } /* reserve to display help message */ if (tolower(c) == '?'|| tolower(c) == 'h') { + int pressanykey_row = 20; mvprintw(2, 0, "Command:\n" ); printw(" ?|h help\n" ); printw(" p pause (SPACE to resume)\n" ); @@ -284,8 +290,14 @@ int mtr_curses_keyaction(void) printw(" s set the packet size to n or random(n<0)\n" ); printw(" b set ping bit pattern to c(0..255) or random(c<0)\n" ); printw(" Q set ping packet's TOS to t\n" ); - printw(" u switch between ICMP ECHO and UDP datagrams\n\n" ); - mvprintw(16, 0, " press any key to go back..." ); + printw(" u switch between ICMP ECHO and UDP datagrams\n" ); +#ifndef NO_IPINFO + printw(" y switching IP info\n"); + printw(" z toggle ASN info on/off\n"); + pressanykey_row += 2; +#endif + printw("\n"); + mvprintw(pressanykey_row, 0, " press any key to go back..." ); getch(); /* get any key */ return ActionNone; @@ -316,60 +328,13 @@ void mtr_curses_hosts(int startstat) mpls = net_mpls(at); if( addrcmp( (void *) addr, (void *) &unspec_addr, af ) != 0 ) { -#ifndef NO_GLIB -#ifdef ENABLE_IPV6 - struct in6_addr addr6 = *addr; -#else - unsigned char *addr4 = (unsigned char *)addr; -#endif - - if (PrintAS) { - u_char ipv4[4]; -#ifdef ENABLE_IPV6 - ipv4[0] = addr6.s6_addr[0]; - ipv4[1] = addr6.s6_addr[1]; - ipv4[2] = addr6.s6_addr[2]; - ipv4[3] = addr6.s6_addr[3]; -#else - ipv4[0] = addr4[0]; - ipv4[1] = addr4[1]; - ipv4[2] = addr4[2]; - ipv4[3] = addr4[3]; -#endif - -#define NAMELEN 127 - char ipv4_buf[NAMELEN]; - char* chip = (char*) &ipv4_buf; - char* chas = NULL; - char** key_ptr = &chip; - char** value_ptr = &chas; - - - if (snprintf(ipv4_buf, NAMELEN, "%d.%d.%d.%d.asn.routeviews.org", ipv4[3], - ipv4[2], ipv4[1], ipv4[0]) >= NAMELEN) { - return; - } - - - - gboolean result = - g_hash_table_lookup_extended - (ashash, ipv4_buf, (gpointer*)key_ptr, (gpointer*)value_ptr); - if (!result) { - char* as = asn_lookup(ipv4_buf); - chip = (char*) strdup(ipv4_buf); - chas = (char*) as; - g_hash_table_insert(ashash, chip, chas); - } - //g_hash_table_destroy(hash); - - - printw("[AS%s] ", chas); - } -#endif /* NO_GLIB */ name = dns_lookup(addr); if (! net_up(at)) attron(A_BOLD); +#ifndef NO_IPINFO + if (is_printii()) + printw(fmt_ipinfo(addr)); +#endif if(name != NULL) { if (show_ips) printw("%s (%s)", name, strlongip(addr)); else printw("%s", name); @@ -422,11 +387,16 @@ void mtr_curses_hosts(int startstat) name = dns_lookup(addrs); if (! net_up(at)) attron(A_BOLD); + printw("\n "); +#ifndef NO_IPINFO + if (is_printii()) + printw(fmt_ipinfo(addrs)); +#endif if (name != NULL) { - if (show_ips) printw("\n %s (%s)", name, strlongip(addrs)); - else printw("\n %s", name); + if (show_ips) printw("%s (%s)", name, strlongip(addrs)); + else printw("%s", name); } else { - printw("\n %s", strlongip( addrs ) ); + printw("%s", strlongip( addrs ) ); } for (k=0; k < mplss->labels && enablempls; k++) { printw("\n [MPLS: Lbl %lu Exp %u S %u TTL %u]", mplss->label[k], mplss->exp[k], mplss->s[k], mplss->ttl[k]); @@ -542,12 +512,15 @@ void mtr_curses_graph(int startstat, int cols) if (! net_up(at)) attron(A_BOLD); - name = dns_lookup(addr); - if (name) { - printw("%s", name); - } else { - printw("%s", strlongip( addr ) ); - } + if (addrcmp((void *) addr, (void *) &unspec_addr, af)) { +#ifndef NO_IPINFO + if (is_printii()) + printw(fmt_ipinfo(addr)); +#endif + name = dns_lookup(addr); + printw("%s", name?name:strlongip(addr)); + } else + printw("???"); attroff(A_BOLD); getyx(stdscr, y, __unused_int); @@ -629,8 +602,13 @@ void mtr_curses_redraw(void) } else { char msg[80]; - int max_cols = maxx<=SAVED_PINGS+30 ? maxx-30 : SAVED_PINGS; - startstat = 28; + int padding = 30; +#ifndef NO_IPINFO + if (is_printii()) + padding += get_iiwidth(); +#endif + int max_cols = maxx<=SAVED_PINGS+padding ? maxx-padding : SAVED_PINGS; + startstat = padding - 2; sprintf(msg, " Last %3d pings", max_cols); mvprintw(rowstat - 1, startstat, msg); @@ -657,9 +635,6 @@ void mtr_curses_redraw(void) void mtr_curses_open(void) { -#ifndef NO_GLIB - ashash = g_hash_table_new(g_str_hash, g_str_equal); -#endif initscr(); raw(); noecho(); diff --git a/display.c b/display.c index daea824..ee3934d 100644 --- a/display.c +++ b/display.c @@ -29,6 +29,9 @@ #include "select.h" #include "raw.h" #include "dns.h" +#ifndef NO_IPINFO +#include +#endif extern int DisplayMode; @@ -94,6 +97,10 @@ void display_open(void) break; case DisplayCurses: mtr_curses_open(); +#ifndef NO_IPINFO + if (ipinfo_no >= 0) + asn_open(); +#endif break; case DisplaySplit: split_open(); @@ -121,6 +128,10 @@ void display_close(void) csv_close(); break; case DisplayCurses: +#ifndef NO_IPINFO + if (ipinfo_no >= 0) + asn_close(); +#endif mtr_curses_close(); break; case DisplaySplit: diff --git a/display.h b/display.h index d1e8b7d..486e25d 100644 --- a/display.h +++ b/display.h @@ -22,6 +22,9 @@ (notably the one on Irix 5.2) do not like that. */ enum { ActionNone, ActionQuit, ActionReset, ActionDisplay, ActionClear, ActionPause, ActionResume, ActionMPLS, ActionDNS, +#ifndef NO_IPINFO + ActionII, ActionAS, +#endif ActionScrollDown, ActionScrollUp }; enum { DisplayReport, DisplayCurses, DisplayGTK, DisplaySplit, DisplayRaw, DisplayXML, DisplayCSV, DisplayTXT}; diff --git a/mtr.c b/mtr.c index 48accb3..0ad6bbb 100644 --- a/mtr.c +++ b/mtr.c @@ -34,7 +34,9 @@ #include "dns.h" #include "report.h" #include "net.h" +#ifndef NO_IPINFO #include "asn.h" +#endif #include "version.h" @@ -154,7 +156,10 @@ void parse_arg (int argc, char **argv) { "udp", 0, 0, 'u' }, /* UDP (default is ICMP) */ { "inet", 0, 0, '4' }, /* IPv4 only */ { "inet6", 0, 0, '6' }, /* IPv6 only */ - { "aslookup", 0, 0, 'z' }, /* Do AS lookup */ +#ifndef NO_IPINFO + { "ipinfo", 1, 0, 'y' }, /* IP info lookup */ + { "aslookup", 0, 0, 'z' }, /* Do AS lookup (--ipinfo 0) */ +#endif { 0, 0, 0, 0 } }; @@ -162,7 +167,7 @@ void parse_arg (int argc, char **argv) while(1) { /* added f:m:o: byMin */ opt = getopt_long(argc, argv, - "vhrwxtglpo:B:i:c:s:Q:ena:f:m:ubz46", long_options, NULL); + "vhrwxtglpo:B:i:c:s:Q:ena:f:m:uby:z46", long_options, NULL); if(opt == -1) break; @@ -289,9 +294,16 @@ void parse_arg (int argc, char **argv) fprintf( stderr, "IPv6 not enabled.\n" ); break; #endif +#ifndef NO_IPINFO + case 'y': + ipinfo_no = atoi (optarg); + if (ipinfo_no < 0) + ipinfo_no = 0; + break; case 'z': - PrintAS = 1; + ipinfo_no = 0; break; +#endif } } @@ -396,7 +408,11 @@ int main(int argc, char **argv) printf("usage: %s [-hvrwctglspniu46] [--help] [--version] [--report]\n" "\t\t[--report-wide] [--report-cycles=COUNT] [--curses] [--gtk]\n" "\t\t[--raw] [--split] [--mpls] [--no-dns] [--show-ips]\n" - "\t\t[--address interface] [--aslookup]\n" /* BL */ + "\t\t[--address interface]\n" /* BL */ +#ifndef NO_IPINFO + "\t\t[--ipinfo=item_no|-y item_no]\n" + "\t\t[--aslookup|-z]\n" +#endif "\t\t[--psize=bytes/-s bytes]\n" /* ok */ "\t\t[--report-wide|-w] [-u]\n" /* rew */ "\t\t[--interval=SECONDS] HOSTNAME [PACKETSIZE]\n", argv[0]); diff --git a/report.c b/report.c index 8b8cd9d..23f5117 100644 --- a/report.c +++ b/report.c @@ -30,6 +30,9 @@ #include "report.h" #include "net.h" #include "dns.h" +#ifndef NO_IPINFO +#include "asn.h" +#endif #define MAXLOADBAL 5 @@ -73,9 +76,17 @@ static size_t snprint_addr(char *dst, size_t dst_len, ip_t *addr) } +#ifndef NO_IPINFO +void print_mpls(struct mplslen *mpls) { + int k; + for (k=0; k < mpls->labels; k++) + printf(" [MPLS: Lbl %lu Exp %u S %u TTL %u]\n", mpls->label[k], mpls->exp[k], mpls->s[k], mpls->ttl[k]); +} +#endif + void report_close(void) { - int i, j, k, at, max, z, w; + int i, j, at, max, z, w; struct mplslen *mpls, *mplss; ip_t *addr; ip_t *addr2 = NULL; @@ -100,7 +111,21 @@ void report_close(void) } } +#ifndef NO_IPINFO + int len_tmp = len_hosts; + if (ipinfo_no >= 0) { + ipinfo_no %= iiwidth_len; + if (reportwide) { + len_hosts++; // space + len_tmp += get_iiwidth(); + if (!ipinfo_no) + len_tmp += 2; // align header: AS + } + } + snprintf( fmt, sizeof(fmt), "HOST: %%-%ds", len_tmp); +#else snprintf( fmt, sizeof(fmt), "HOST: %%-%ds", len_hosts); +#endif snprintf(buf, sizeof(buf), fmt, LocalHostname); len = reportwide ? strlen(buf) : len_hosts; for( i=0; ilabels && z == 1 && enablempls) + print_mpls(mpls); + snprint_addr(name, sizeof(name), addr2); + printf(" %s%s\n", fmt_ipinfo(addr2), name); + if (enablempls) + print_mpls(mplss); + } else { +#else + int k; if (mpls->labels && z == 1 && enablempls) { for (k=0; k < mpls->labels; k++) { printf(" | |+-- [MPLS: Lbl %lu Exp %u S %u TTL %u]\n", mpls->label[k], mpls->exp[k], mpls->s[k], mpls->ttl[k]); @@ -174,15 +219,30 @@ void report_close(void) printf(" | +-- [MPLS: Lbl %lu Exp %u S %u TTL %u]\n", mplss->label[k], mplss->exp[k], mplss->s[k], mplss->ttl[k]); } } +#endif +#ifndef NO_IPINFO + } +#endif } } /* No multipath */ +#ifndef NO_IPINFO + if (is_printii()) { + if (mpls->labels && z == 1 && enablempls) + print_mpls(mpls); + } else { +#else if(mpls->labels && z == 1 && enablempls) { + int k; for (k=0; k < mpls->labels; k++) { printf(" | +-- [MPLS: Lbl %lu Exp %u S %u TTL %u]\n", mpls->label[k], mpls->exp[k], mpls->s[k], mpls->ttl[k]); } } +#endif +#ifndef NO_IPINFO + } +#endif } } diff --git a/select.c b/select.c index 4134080..0e04075 100644 --- a/select.c +++ b/select.c @@ -32,6 +32,9 @@ #include "display.h" #include "dns.h" #include "net.h" +#ifndef NO_IPINFO +#include "asn.h" +#endif extern int Interactive; extern int MaxPing; @@ -201,6 +204,19 @@ void select_loop(void) { display_clear(); } break; +#ifndef NO_IPINFO + case ActionII: + if (ipinfo_no >= 0) { + ipinfo_no++; + if (ipinfo_no > ipinfo_max) + ipinfo_no = 0; + } + break; + case ActionAS: + if (ipinfo_no >= 0) + ipinfo_no = ipinfo_no?0:ipinfo_max; + break; +#endif case ActionScrollDown: display_offset += 5;