Annotation of embedaddon/mtr/ui/asn.c, revision 1.1.1.1

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: 
                     19: #include "config.h"
                     20: 
                     21: #include <unistd.h>
                     22: #include <stdio.h>
                     23: #include <stdlib.h>
                     24: #include <sys/types.h>
                     25: #ifdef HAVE_ERROR_H
                     26: #include <error.h>
                     27: #else
                     28: #include "portability/error.h"
                     29: #endif
                     30: #include <errno.h>
                     31: 
                     32: #ifdef __APPLE__
                     33: #define BIND_8_COMPAT
                     34: #endif
                     35: #include <arpa/nameser.h>
                     36: #ifdef HAVE_ARPA_NAMESER_COMPAT_H
                     37: #include <arpa/nameser_compat.h>
                     38: #endif
                     39: #include <netdb.h>
                     40: #include <netinet/in.h>
                     41: #include <resolv.h>
                     42: #include <string.h>
                     43: #include <sys/socket.h>
                     44: #include <search.h>
                     45: 
                     46: #include "mtr.h"
                     47: #include "asn.h"
                     48: #include "utils.h"
                     49: 
                     50: /* #define IIDEBUG */
                     51: #ifdef IIDEBUG
                     52: #include <syslog.h>
                     53: #define DEB_syslog syslog
                     54: #else
                     55: #define DEB_syslog(...) do {} while (0)
                     56: #endif
                     57: 
                     58: #define IIHASH_HI      128
                     59: #define ITEMSMAX       15
                     60: #define ITEMSEP        '|'
                     61: #define NAMELEN        127
                     62: #define UNKN   "???"
                     63: 
                     64: static int iihash = 0;
                     65: static char fmtinfo[32];
                     66: 
                     67: /* items width: ASN, Route, Country, Registry, Allocated */
                     68: static const int iiwidth[] = { 7, 19, 4, 8, 11 };       /* item len + space */
                     69: 
                     70: typedef char *items_t[ITEMSMAX + 1];
                     71: static items_t items_a;         /* without hash: items */
                     72: static char txtrec[NAMELEN + 1];        /* without hash: txtrec */
                     73: static items_t *items = &items_a;
                     74: 
                     75: 
                     76: static char *ipinfo_lookup(
                     77:     const char *domain)
                     78: {
                     79:     unsigned char answer[PACKETSZ], *pt;
                     80:     char host[128];
                     81:     char *txt;
                     82:     int len, exp, size, txtlen, type;
                     83: 
                     84: 
                     85:     if (res_init() < 0) {
                     86:         error(0, 0, "@res_init failed");
                     87:         return NULL;
                     88:     }
                     89: 
                     90:     memset(answer, 0, PACKETSZ);
                     91:     if ((len = res_query(domain, C_IN, T_TXT, answer, PACKETSZ)) < 0) {
                     92:         if (iihash)
                     93:             DEB_syslog(LOG_INFO, "Malloc-txt: %s", UNKN);
                     94:         return xstrdup(UNKN);
                     95:     }
                     96: 
                     97:     pt = answer + sizeof(HEADER);
                     98: 
                     99:     if ((exp =
                    100:          dn_expand(answer, answer + len, pt, host, sizeof(host))) < 0) {
                    101:         printf("@dn_expand failed\n");
                    102:         return NULL;
                    103:     }
                    104: 
                    105:     pt += exp;
                    106: 
                    107:     GETSHORT(type, pt);
                    108:     if (type != T_TXT) {
                    109:         printf("@Broken DNS reply.\n");
                    110:         return NULL;
                    111:     }
                    112: 
                    113:     pt += INT16SZ;              /* class */
                    114: 
                    115:     if ((exp =
                    116:          dn_expand(answer, answer + len, pt, host, sizeof(host))) < 0) {
                    117:         printf("@second dn_expand failed\n");
                    118:         return NULL;
                    119:     }
                    120: 
                    121:     pt += exp;
                    122:     GETSHORT(type, pt);
                    123:     if (type != T_TXT) {
                    124:         printf("@Not a TXT record\n");
                    125:         return NULL;
                    126:     }
                    127: 
                    128:     pt += INT16SZ;              /* class */
                    129:     pt += INT32SZ;              /* ttl */
                    130:     GETSHORT(size, pt);
                    131:     txtlen = *pt;
                    132: 
                    133: 
                    134:     if (txtlen >= size || !txtlen) {
                    135:         printf("@Broken TXT record (txtlen = %d, size = %d)\n", txtlen,
                    136:                size);
                    137:         return NULL;
                    138:     }
                    139: 
                    140:     if (txtlen > NAMELEN)
                    141:         txtlen = NAMELEN;
                    142: 
                    143:     if (iihash) {
                    144:         txt = xmalloc(txtlen + 1);
                    145:     } else
                    146:         txt = (char *) txtrec;
                    147: 
                    148:     pt++;
                    149:     xstrncpy(txt, (char *) pt, txtlen + 1);
                    150: 
                    151:     if (iihash)
                    152:         DEB_syslog(LOG_INFO, "Malloc-txt(%p): %s", txt, txt);
                    153: 
                    154:     return txt;
                    155: }
                    156: 
                    157: /* originX.asn.cymru.com txtrec:    ASN | Route | Country | Registry | Allocated */
                    158: static char *split_txtrec(
                    159:     struct mtr_ctl *ctl,
                    160:     char *txt_rec)
                    161: {
                    162:     char *prev;
                    163:     char *next;
                    164:     int i = 0, j;
                    165: 
                    166:     if (!txt_rec)
                    167:         return NULL;
                    168:     if (iihash) {
                    169:         DEB_syslog(LOG_INFO, "Malloc-tbl: %s", txt_rec);
                    170:         if (!(items = malloc(sizeof(*items)))) {
                    171:             DEB_syslog(LOG_INFO, "Free-txt(%p)", txt_rec);
                    172:             free(txt_rec);
                    173:             return NULL;
                    174:         }
                    175:     }
                    176: 
                    177:     prev = txt_rec;
                    178: 
                    179:     while ((next = strchr(prev, ITEMSEP)) && (i < ITEMSMAX)) {
                    180:         *next = '\0';
                    181:         next++;
                    182:         (*items)[i] = trim(prev, ITEMSEP);
                    183:         prev = next;
                    184:         i++;
                    185:     }
                    186:     (*items)[i] = trim(prev, ITEMSEP);
                    187: 
                    188:     if (i < ITEMSMAX)
                    189:         i++;
                    190:     for (j = i; j <= ITEMSMAX; j++)
                    191:         (*items)[j] = NULL;
                    192: 
                    193:     if (i > ctl->ipinfo_max)
                    194:         ctl->ipinfo_max = i;
                    195:     if (ctl->ipinfo_no >= i) {
                    196:         if (ctl->ipinfo_no >= ctl->ipinfo_max)
                    197:             ctl->ipinfo_no = 0;
                    198:         return (*items)[0];
                    199:     } else
                    200:         return (*items)[ctl->ipinfo_no];
                    201: }
                    202: 
                    203: #ifdef ENABLE_IPV6
                    204: /* from dns.c:addr2ip6arpa() */
                    205: static void reverse_host6(
                    206:     struct in6_addr *addr,
                    207:     char *buff,
                    208:     int buff_length)
                    209: {
                    210:     int i;
                    211:     char *b = buff;
                    212:     for (i = (sizeof(*addr) / 2 - 1); i >= 0; i--, b += 4)      /* 64b portion */
                    213:         snprintf(b, buff_length,
                    214:                  "%x.%x.", addr->s6_addr[i] & 0xf, addr->s6_addr[i] >> 4);
                    215: 
                    216:     buff[strlen(buff) - 1] = '\0';
                    217: }
                    218: #endif
                    219: 
                    220: static char *get_ipinfo(
                    221:     struct mtr_ctl *ctl,
                    222:     ip_t * addr)
                    223: {
                    224:     char key[NAMELEN];
                    225:     char lookup_key[NAMELEN];
                    226:     char *val = NULL;
                    227:     ENTRY item;
                    228: 
                    229:     if (!addr)
                    230:         return NULL;
                    231: 
                    232:     if (ctl->af == AF_INET6) {
                    233: #ifdef ENABLE_IPV6
                    234:         reverse_host6(addr, key, NAMELEN);
                    235:         if (snprintf(lookup_key, NAMELEN, "%s.origin6.asn.cymru.com", key)
                    236:             >= NAMELEN)
                    237:             return NULL;
                    238: #else
                    239:         return NULL;
                    240: #endif
                    241:     } else {
                    242:         unsigned char buff[4];
                    243:         memcpy(buff, addr, 4);
                    244:         if (snprintf
                    245:             (key, NAMELEN, "%d.%d.%d.%d", buff[3], buff[2], buff[1],
                    246:              buff[0]) >= NAMELEN)
                    247:             return NULL;
                    248:         if (snprintf(lookup_key, NAMELEN, "%s.origin.asn.cymru.com", key)
                    249:             >= NAMELEN)
                    250:             return NULL;
                    251:     }
                    252: 
                    253:     if (iihash) {
                    254:         ENTRY *found_item;
                    255: 
                    256:         DEB_syslog(LOG_INFO, ">> Search: %s", key);
                    257:         item.key = key;;
                    258:         if ((found_item = hsearch(item, FIND))) {
                    259:             if (!(val = (*((items_t *) found_item->data))[ctl->ipinfo_no]))
                    260:                 val = (*((items_t *) found_item->data))[0];
                    261:             DEB_syslog(LOG_INFO, "Found (hashed): %s", val);
                    262:         }
                    263:     }
                    264: 
                    265:     if (!val) {
                    266:         DEB_syslog(LOG_INFO, "Lookup: %s", key);
                    267:         if ((val = split_txtrec(ctl, ipinfo_lookup(lookup_key)))) {
                    268:             DEB_syslog(LOG_INFO, "Looked up: %s", key);
                    269:             if (iihash)
                    270:                 if ((item.key = xstrdup(key))) {
                    271:                     item.data = (void *) items;
                    272:                     hsearch(item, ENTER);
                    273:                     DEB_syslog(LOG_INFO, "Insert into hash: %s", key);
                    274:                 }
                    275:         }
                    276:     }
                    277: 
                    278:     return val;
                    279: }
                    280: 
                    281: ATTRIBUTE_CONST size_t get_iiwidth_len(
                    282:     void)
                    283: {
                    284:     return (sizeof(iiwidth) / sizeof((iiwidth)[0]));
                    285: }
                    286: 
                    287: ATTRIBUTE_CONST int get_iiwidth(
                    288:     int ipinfo_no)
                    289: {
                    290:     static const int len = (sizeof(iiwidth) / sizeof((iiwidth)[0]));
                    291: 
                    292:     if (ipinfo_no < len)
                    293:         return iiwidth[ipinfo_no];
                    294:     return iiwidth[ipinfo_no % len];
                    295: }
                    296: 
                    297: char *fmt_ipinfo(
                    298:     struct mtr_ctl *ctl,
                    299:     ip_t * addr)
                    300: {
                    301:     char *ipinfo = get_ipinfo(ctl, addr);
                    302:     char fmt[8];
                    303:     snprintf(fmt, sizeof(fmt), "%s%%-%ds", ctl->ipinfo_no ? "" : "AS",
                    304:              get_iiwidth(ctl->ipinfo_no));
                    305:     snprintf(fmtinfo, sizeof(fmtinfo), fmt, ipinfo ? ipinfo : UNKN);
                    306:     return fmtinfo;
                    307: }
                    308: 
                    309: int is_printii(
                    310:     struct mtr_ctl *ctl)
                    311: {
                    312:     return ((ctl->ipinfo_no >= 0) && (ctl->ipinfo_no != ctl->ipinfo_max));
                    313: }
                    314: 
                    315: void asn_open(
                    316:     struct mtr_ctl *ctl)
                    317: {
                    318:     if (ctl->ipinfo_no >= 0) {
                    319:         DEB_syslog(LOG_INFO, "hcreate(%d)", IIHASH_HI);
                    320:         if (!(iihash = hcreate(IIHASH_HI)))
                    321:             error(0, errno, "ipinfo hash");
                    322:     }
                    323: }
                    324: 
                    325: void asn_close(
                    326:     struct mtr_ctl *ctl)
                    327: {
                    328:     if ((ctl->ipinfo_no >= 0) && iihash) {
                    329:         DEB_syslog(LOG_INFO, "hdestroy()");
                    330:         hdestroy();
                    331:         iihash = 0;
                    332:     }
                    333: }

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