Annotation of embedaddon/mtr/ui/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 "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>