Annotation of embedaddon/mtr/asn.c, revision 1.1.1.2

1.1       misho       1: /*
                      2:     mtr  --  a network diagnostic tool
                      3:     Copyright (C) 1997,1998  Matt Kimball
                      4: 
                      5:     This program is free software; you can redistribute it and/or modify
                      6:     it under the terms of the GNU General Public License version 2 as
                      7:     published by the Free Software Foundation.
                      8: 
                      9:     This program is distributed in the hope that it will be useful,
                     10:     but WITHOUT ANY WARRANTY; without even the implied warranty of
                     11:     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     12:     GNU General Public License for more details.
                     13: 
                     14:     You should have received a copy of the GNU General Public License
                     15:     along with this program; if not, write to the Free Software
                     16:     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
                     17: */
                     18: 
1.1.1.2 ! misho      19: #include "config.h"
        !            20: 
1.1       misho      21: #include <unistd.h>
                     22: #include <stdio.h>
                     23: #include <stdlib.h>
                     24: #include <sys/types.h>
                     25: 
1.1.1.2 ! misho      26: #ifdef __APPLE__
1.1       misho      27: #define BIND_8_COMPAT
                     28: #endif
                     29: #include <arpa/nameser.h>
                     30: #ifdef HAVE_ARPA_NAMESER_COMPAT_H
                     31: #include <arpa/nameser_compat.h>
                     32: #endif
                     33: #include <netdb.h>
                     34: #include <netinet/in.h>
                     35: #include <resolv.h>
                     36: #include <string.h>
                     37: #include <sys/socket.h>
                     38: #include <search.h>
                     39: 
                     40: #include "mtr.h"
                     41: #include "asn.h"
                     42: 
                     43: /*
                     44: #ifndef IIDEBUG
                     45: #define IIDEBUG
                     46: #include <syslog.h>
                     47: #endif
                     48: */
                     49: 
                     50: #define IIHASH_HI      128
                     51: #define ITEMSMAX       15
                     52: #define ITEMSEP        '|'
                     53: #define NAMELEN        127
                     54: #define UNKN   "???"
                     55: 
                     56: int  ipinfo_no = -1;
                     57: int  ipinfo_max = -1;
                     58: int  iihash = 0;
                     59: char fmtinfo[32];
                     60: extern int af;                  /* address family of remote target */
                     61: 
                     62: // items width: ASN, Route, Country, Registry, Allocated 
                     63: int iiwidth[] = { 6, 19, 4, 8, 11};    // item len + space
                     64: int iiwidth_len = sizeof(iiwidth)/sizeof((iiwidth)[0]);
                     65: 
                     66: typedef char* items_t[ITEMSMAX + 1];
                     67: items_t items_a;               // without hash: items
                     68: char txtrec[NAMELEN + 1];      // without hash: txtrec
                     69: items_t* items = &items_a;
                     70: 
                     71: 
                     72: char *ipinfo_lookup(const char *domain) {
                     73:     unsigned char answer[PACKETSZ],  *pt;
                     74:     char host[128];
                     75:     char *txt;
                     76:     int len, exp, size, txtlen, type;
                     77: 
                     78: 
                     79:     if(res_init() < 0) {
                     80:         fprintf(stderr,"@res_init failed\n");
                     81:         return NULL;
                     82:     }
                     83: 
                     84:     memset(answer, 0, PACKETSZ);
                     85:     if((len = res_query(domain, C_IN, T_TXT, answer, PACKETSZ)) < 0) {
                     86: #ifdef IIDEBUG
                     87:         if (iihash)
                     88:             syslog(LOG_INFO, "Malloc-txt: %s", UNKN);
                     89: #endif
                     90:         return (iihash)?strdup(UNKN):UNKN;
                     91:     }
                     92: 
                     93:     pt = answer + sizeof(HEADER);
                     94: 
                     95:     if((exp = dn_expand(answer, answer + len, pt, host, sizeof(host))) < 0) {
                     96:         printf("@dn_expand failed\n"); return NULL;
                     97:     }
                     98: 
                     99:     pt += exp;
                    100: 
                    101:     GETSHORT(type, pt);
                    102:     if(type != T_TXT) {
                    103:         printf("@Broken DNS reply.\n"); return NULL;
                    104:     }
                    105: 
                    106:     pt += INT16SZ; /* class */
                    107: 
                    108:     if((exp = dn_expand(answer, answer + len, pt, host, sizeof(host))) < 0) {
                    109:         printf("@second dn_expand failed\n"); return NULL;
                    110:     }
                    111: 
                    112:     pt += exp;
                    113:     GETSHORT(type, pt);
                    114:     if(type != T_TXT) {
                    115:         printf("@Not a TXT record\n"); return NULL;
                    116:     }
                    117: 
                    118:     pt += INT16SZ; /* class */
                    119:     pt += INT32SZ; /* ttl */
                    120:     GETSHORT(size, pt);
                    121:     txtlen = *pt;
                    122: 
                    123: 
                    124:     if(txtlen >= size || !txtlen) {
                    125:         printf("@Broken TXT record (txtlen = %d, size = %d)\n", txtlen, size); return NULL;
                    126:     }
                    127: 
                    128:     if (txtlen > NAMELEN)
                    129:         txtlen = NAMELEN;
                    130: 
                    131:     if (iihash) {
                    132:         if (!(txt = malloc(txtlen + 1)))
                    133:             return NULL;
                    134:     } else
                    135:         txt = (char*)txtrec;
                    136: 
                    137:     pt++;
                    138:     strncpy(txt, (char*) pt, txtlen);
                    139:     txt[txtlen] = 0;
                    140: 
                    141: #ifdef IIDEBUG
                    142:     if (iihash)
                    143:         syslog(LOG_INFO, "Malloc-txt(%p): %s", txt, txt);
                    144: #endif
                    145: 
                    146:     return txt;
                    147: }
                    148: 
                    149: char* trimsep(char *s) {
                    150:     int l;
                    151:     char *p = s;
                    152:     while (*p == ' ' || *p == ITEMSEP)
                    153:         *p++ = '\0';
                    154:     for (l = strlen(p)-1; p[l] == ' ' || p[l] == ITEMSEP; l--)
                    155:         p[l] = '\0';
                    156:     return p;
                    157: }
                    158: 
                    159: // originX.asn.cymru.com txtrec:    ASN | Route | Country | Registry | Allocated
                    160: char* split_txtrec(char *txtrec) {
                    161:     if (!txtrec)
                    162:        return NULL;
                    163:     if (iihash) {
                    164: #ifdef IIDEBUG
                    165:         syslog(LOG_INFO, "Malloc-tbl: %s", txtrec);
                    166: #endif
                    167:         if (!(items = malloc(sizeof(*items)))) {
                    168: #ifdef IIDEBUG
                    169:             syslog(LOG_INFO, "Free-txt(%p)", txtrec);
                    170: #endif
                    171:             free(txtrec);
                    172:             return NULL;
                    173:         }
                    174:     }
                    175: 
                    176:     char* prev = (*items)[0] = trimsep(txtrec);
                    177:     char* next;
                    178:     int i = 0, j;
                    179: 
                    180:     while ((next = strchr(prev, ITEMSEP)) && (i < ITEMSMAX)) {
                    181:         *next++ = '\0';
                    182:         (*items)[i++] = trimsep(prev);
                    183:         (*items)[i] = prev = trimsep(next);
                    184:     }
                    185:     if (i < ITEMSMAX)
                    186:         i++;
                    187:     for (j = i;  j <= ITEMSMAX; j++)
                    188:         (*items)[j] = NULL;
                    189: 
                    190:     if (i > ipinfo_max)
                    191:         ipinfo_max = i;
                    192:     if (ipinfo_no >= i) {
                    193:         if (ipinfo_no >= ipinfo_max)
                    194:             ipinfo_no = 0;
                    195:        return (*items)[0];
                    196:     } else
                    197:        return (*items)[ipinfo_no];
                    198: }
                    199: 
                    200: #ifdef ENABLE_IPV6
                    201: // from dns.c:addr2ip6arpa()
                    202: void reverse_host6(struct in6_addr *addr, char *buff) {
                    203:     int i;
                    204:     char *b = buff;
                    205:     for (i=(sizeof(*addr)/2-1); i>=0; i--, b+=4) // 64b portion
                    206:         sprintf(b, "%x.%x.", addr->s6_addr[i] & 0xf, addr->s6_addr[i] >> 4);
                    207:     buff[strlen(buff) - 1] = '\0';
                    208: }
                    209: #endif
                    210: 
                    211: char *get_ipinfo(ip_t *addr) {
                    212:     if (!addr)
                    213:         return NULL;
                    214: 
                    215:     char key[NAMELEN];
                    216:     char lookup_key[NAMELEN];
                    217: 
                    218:     if (af == AF_INET6) {
                    219: #ifdef ENABLE_IPV6
                    220:         reverse_host6(addr, key);
                    221:         if (snprintf(lookup_key, NAMELEN, "%s.origin6.asn.cymru.com", key) >= NAMELEN)
                    222:             return NULL;
                    223: #else
                    224:        return NULL;
                    225: #endif
                    226:     } else {
                    227:         unsigned char buff[4];
                    228:         memcpy(buff, addr, 4);
                    229:         if (snprintf(key, NAMELEN, "%d.%d.%d.%d", buff[3], buff[2], buff[1], buff[0]) >= NAMELEN)
                    230:             return NULL;
                    231:         if (snprintf(lookup_key, NAMELEN, "%s.origin.asn.cymru.com", key) >= NAMELEN)
                    232:             return NULL;
                    233:     }
                    234: 
                    235:     char *val = NULL;
                    236:     ENTRY item;
                    237: 
                    238:     if (iihash) {
                    239: #ifdef IIDEBUG
                    240:         syslog(LOG_INFO, ">> Search: %s", key);
                    241: #endif
                    242:         item.key = key;;
                    243:         ENTRY *found_item;
                    244:         if ((found_item = hsearch(item, FIND))) {
                    245:             if (!(val = (*((items_t*)found_item->data))[ipinfo_no]))
                    246:                 val = (*((items_t*)found_item->data))[0];
                    247: #ifdef IIDEBUG
                    248:         syslog(LOG_INFO, "Found (hashed): %s", val);
                    249: #endif
                    250:         }
                    251:     }
                    252: 
                    253:     if (!val) {
                    254: #ifdef IIDEBUG
                    255:         syslog(LOG_INFO, "Lookup: %s", key);
                    256: #endif
                    257:         if ((val = split_txtrec(ipinfo_lookup(lookup_key)))) {
                    258: #ifdef IIDEBUG
                    259:             syslog(LOG_INFO, "Looked up: %s", key);
                    260: #endif
                    261:             if (iihash)
                    262:                 if ((item.key = strdup(key))) {
                    263:                     item.data = items;
                    264:                     hsearch(item, ENTER);
                    265: #ifdef IIDEBUG
                    266:                     syslog(LOG_INFO, "Insert into hash: %s", key);
                    267: #endif
                    268:                 }
                    269:         }
                    270:     }
                    271: 
                    272:     return val;
                    273: }
                    274: 
                    275: int get_iiwidth(void) {
                    276:     return (ipinfo_no < iiwidth_len) ? iiwidth[ipinfo_no] : iiwidth[ipinfo_no % iiwidth_len];
                    277: }
                    278: 
                    279: char *fmt_ipinfo(ip_t *addr) {
                    280:     char *ipinfo = get_ipinfo(addr);
                    281:     char fmt[8];
                    282:     snprintf(fmt, sizeof(fmt), "%s%%-%ds", ipinfo_no?"":"AS", get_iiwidth());
                    283:     snprintf(fmtinfo, sizeof(fmtinfo), fmt, ipinfo?ipinfo:UNKN);
                    284:     return fmtinfo;
                    285: }
                    286: 
                    287: int is_printii(void) {
                    288:     return ((ipinfo_no >= 0) && (ipinfo_no != ipinfo_max));
                    289: }
                    290: 
                    291: void asn_open(void) {
                    292:     if (ipinfo_no >= 0) {
                    293: #ifdef IIDEBUG
                    294:         syslog(LOG_INFO, "hcreate(%d)", IIHASH_HI);
                    295: #endif
                    296:         if (!(iihash = hcreate(IIHASH_HI)))
                    297:             perror("ipinfo hash");
                    298:     }
                    299: }
                    300: 
                    301: void asn_close(void) {
                    302:     if (iihash) {
                    303: #ifdef IIDEBUG
                    304:         syslog(LOG_INFO, "hdestroy()");
                    305: #endif
                    306:         hdestroy();
                    307:         iihash = 0;
                    308:     }
                    309: }
                    310: 

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