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>