File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mtr / ui / asn.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 00:07:30 2021 UTC (3 years, 3 months ago) by misho
Branches: mtr, MAIN
CVS tags: v0_94, HEAD
mtr 0.94

    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 along
   15:     with this program; if not, write to the Free Software Foundation, Inc.,
   16:     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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:         return (*items)[0];
  197:     } else
  198:         return (*items)[ctl->ipinfo_no];
  199: }
  200: 
  201: #ifdef ENABLE_IPV6
  202: /* from dns.c:addr2ip6arpa() */
  203: static void reverse_host6(
  204:     struct in6_addr *addr,
  205:     char *buff,
  206:     int buff_length)
  207: {
  208:     int i;
  209:     char *b = buff;
  210:     for (i = (sizeof(*addr) / 2 - 1); i >= 0; i--, b += 4)      /* 64b portion */
  211:         snprintf(b, buff_length,
  212:                  "%x.%x.", addr->s6_addr[i] & 0xf, addr->s6_addr[i] >> 4);
  213: 
  214:     buff[strlen(buff) - 1] = '\0';
  215: }
  216: #endif
  217: 
  218: static char *get_ipinfo(
  219:     struct mtr_ctl *ctl,
  220:     ip_t * addr)
  221: {
  222:     char key[NAMELEN];
  223:     char lookup_key[NAMELEN];
  224:     char *val = NULL;
  225:     ENTRY item;
  226: 
  227:     if (!addr)
  228:         return NULL;
  229: 
  230:     if (ctl->af == AF_INET6) {
  231: #ifdef ENABLE_IPV6
  232:         reverse_host6(addr, key, NAMELEN);
  233:         if (snprintf(lookup_key, NAMELEN, "%s.origin6.asn.cymru.com", key)
  234:             >= NAMELEN)
  235:             return NULL;
  236: #else
  237:         return NULL;
  238: #endif
  239:     } else {
  240:         unsigned char buff[4];
  241:         memcpy(buff, addr, 4);
  242:         if (snprintf
  243:             (key, NAMELEN, "%d.%d.%d.%d", buff[3], buff[2], buff[1],
  244:              buff[0]) >= NAMELEN)
  245:             return NULL;
  246:         if (snprintf(lookup_key, NAMELEN, "%s.origin.asn.cymru.com", key)
  247:             >= NAMELEN)
  248:             return NULL;
  249:     }
  250: 
  251:     if (iihash) {
  252:         ENTRY *found_item;
  253: 
  254:         DEB_syslog(LOG_INFO, ">> Search: %s", key);
  255:         item.key = key;;
  256:         if ((found_item = hsearch(item, FIND))) {
  257:             if (!(val = (*((items_t *) found_item->data))[ctl->ipinfo_no]))
  258:                 val = (*((items_t *) found_item->data))[0];
  259:             DEB_syslog(LOG_INFO, "Found (hashed): %s", val);
  260:         }
  261:     }
  262: 
  263:     if (!val) {
  264:         DEB_syslog(LOG_INFO, "Lookup: %s", key);
  265:         if ((val = split_txtrec(ctl, ipinfo_lookup(lookup_key)))) {
  266:             DEB_syslog(LOG_INFO, "Looked up: %s", key);
  267:             if (iihash)
  268:                 if ((item.key = xstrdup(key))) {
  269:                     item.data = (void *) items;
  270:                     hsearch(item, ENTER);
  271:                     DEB_syslog(LOG_INFO, "Insert into hash: %s", key);
  272:                 }
  273:         }
  274:     }
  275: 
  276:     return val;
  277: }
  278: 
  279: ATTRIBUTE_CONST size_t get_iiwidth_len(
  280:     void)
  281: {
  282:     return (sizeof(iiwidth) / sizeof((iiwidth)[0]));
  283: }
  284: 
  285: ATTRIBUTE_CONST int get_iiwidth(
  286:     int ipinfo_no)
  287: {
  288:     static const int len = (sizeof(iiwidth) / sizeof((iiwidth)[0]));
  289: 
  290:     if (ipinfo_no < len)
  291:         return iiwidth[ipinfo_no];
  292:     return iiwidth[ipinfo_no % len];
  293: }
  294: 
  295: char *fmt_ipinfo(
  296:     struct mtr_ctl *ctl,
  297:     ip_t * addr)
  298: {
  299:     char *ipinfo = get_ipinfo(ctl, addr);
  300:     char fmt[8];
  301:     snprintf(fmt, sizeof(fmt), "%s%%-%ds", ctl->ipinfo_no ? "" : "AS",
  302:              get_iiwidth(ctl->ipinfo_no));
  303:     snprintf(fmtinfo, sizeof(fmtinfo), fmt, ipinfo ? ipinfo : UNKN);
  304:     return fmtinfo;
  305: }
  306: 
  307: int is_printii(
  308:     struct mtr_ctl *ctl)
  309: {
  310:     return (ctl->ipinfo_no >= 0);
  311: }
  312: 
  313: void asn_open(
  314:     struct mtr_ctl *ctl)
  315: {
  316:     DEB_syslog(LOG_INFO, "hcreate(%d)", IIHASH_HI);
  317:     if (!(iihash = hcreate(IIHASH_HI)))
  318:         error(0, errno, "ipinfo hash");
  319: }
  320: 
  321: void asn_close(
  322:     struct mtr_ctl *ctl)
  323: {
  324:     if (iihash) {
  325:         DEB_syslog(LOG_INFO, "hdestroy()");
  326:         hdestroy();
  327:         iihash = 0;
  328:     }
  329: }

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