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>