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