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

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