"SfR Fresh" - the SfR Freeware/Shareware Archive 
Member "trafshow-3.1/addrtoname.c" of archive trafshow-3.1.tgz:
As a special service "SfR Fresh" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting with prefixed line numbers.
Alternatively you can here view or download the uninterpreted source code file.
That can be also achieved for any archive member file by clicking within an archive contents listing on the first character of the file(path) respectively on the according byte size field.
1 /*
2 * Copyright (c) 1993-1997 JSC Rinet, Novosibirsk, Russia
3 *
4 * Redistribution and use in source forms, with and without modification,
5 * are permitted provided that this entire comment appears intact.
6 * Redistribution in binary form may occur without any restrictions.
7 *
8 * THIS SOFTWARE IS PROVIDED ``AS IS'' WITHOUT ANY WARRANTIES OF ANY KIND.
9 */
10
11 /* addrtoname.c -- address to name translation routines */
12
13 /* Portions of this software may fall under the following copyrights: */
14 /*
15 * Copyright (c) 1988, 1990 The Regents of the University of California.
16 * All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that: (1) source code distributions
20 * retain the above copyright notice and this paragraph in its entirety, (2)
21 * distributions including binary code include the above copyright notice and
22 * this paragraph in its entirety in the documentation or other materials
23 * provided with the distribution, and (3) all advertising materials mentioning
24 * features or use of this software display the following acknowledgement:
25 * ``This product includes software developed by the University of California,
26 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
27 * the University nor the names of its contributors may be used to endorse
28 * or promote products derived from this software without specific prior
29 * written permission.
30 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
31 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
32 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
33 *
34 * Internet, ethernet, port, and protocol string to address
35 * and address to string conversion routines
36 */
37
38 #ifdef HAVE_CONFIG_H
39 #include <config.h>
40 #endif
41
42 #include <sys/types.h>
43 #include <sys/socket.h>
44 #include <sys/time.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <signal.h>
49 #include <unistd.h>
50 #include <netdb.h>
51 #ifdef TIME_WITH_SYS_TIME
52 #include <time.h>
53 #endif
54
55 #include "trafshow.h"
56
57 typedef void (*sigfunc) ();
58
59 /* Hash tables for whatever-to-name translations */
60
61 #define HASHNAMESIZE 4096
62
63 /* IP level */
64 struct hnamemem {
65 u_int32_t addr;
66 char *name;
67 struct hnamemem *nxt;
68 };
69 struct hnamemem hnametable[HASHNAMESIZE];
70 struct hnamemem tporttable[HASHNAMESIZE];
71 struct hnamemem uporttable[HASHNAMESIZE];
72
73 /* Ethernet level */
74 struct enamemem {
75 u_short addr0;
76 u_short addr1;
77 u_short addr2;
78 char *name;
79 struct enamemem *nxt;
80 };
81 struct enamemem enametable[HASHNAMESIZE];
82 struct hnamemem eprototable[HASHNAMESIZE];
83
84
85 static u_int32_t f_netmask;
86 static u_int32_t f_localnet;
87 static u_int32_t netmask;
88
89 /*
90 * A faster replacement for inet_ntoa().
91 */
92 char *
93 intoa(addr)
94 u_int32_t addr;
95 {
96 register char *cp;
97 register u_int byte;
98 register int n;
99 static char buf[sizeof(".xxx.xxx.xxx.xxx")];
100
101 addr = ntohl(addr);
102 cp = &buf[sizeof buf];
103 *--cp = '\0';
104
105 n = 4;
106 do {
107 byte = addr & 0xff;
108 *--cp = byte % 10 + '0';
109 byte /= 10;
110 if (byte > 0) {
111 *--cp = byte % 10 + '0';
112 byte /= 10;
113 if (byte > 0)
114 *--cp = byte + '0';
115 }
116 *--cp = '.';
117 addr >>= 8;
118 } while (--n > 0);
119
120 return cp + 1;
121 }
122
123 /* Return a zero'ed hnamemem struct and cuts down on calloc() overhead */
124 struct hnamemem *
125 newhnamemem()
126 {
127 register struct hnamemem *p;
128 static struct hnamemem *ptr = NULL;
129 static u_int num = 0;
130
131 if (num <= 0) {
132 num = 64;
133 ptr = (struct hnamemem *)calloc(num, sizeof (*ptr));
134 if (ptr == NULL) error(1, "newhnamemem: calloc");
135 }
136 --num;
137 p = ptr++;
138 return (p);
139 }
140
141 /* A replacement for strdup() that cuts down on malloc() overhead */
142 char *
143 savestr(str)
144 register const char *str;
145 {
146 register u_int size;
147 register char *p;
148 static char *strptr = NULL;
149 static u_int strsize = 0;
150
151 size = strlen(str) + 1;
152 if (size > strsize) {
153 strsize = 1024;
154 if (strsize < size)
155 strsize = size;
156 strptr = (char *)malloc(strsize);
157 if (strptr == NULL) error(1, "savestr: malloc");
158 }
159 (void)strcpy(strptr, str);
160 p = strptr;
161 strptr += size;
162 strsize -= size;
163 return (p);
164 }
165
166 /*
167 * "getname" is written in this atrocious way to make sure we don't
168 * wait forever while trying to get hostnames from yp.
169 */
170
171 #ifdef HAVE_SIGINTERRUPT /* BSD signal semantics */
172 #include <setjmp.h>
173
174 jmp_buf getname_env;
175
176 static void
177 nohostname()
178 {
179 longjmp(getname_env, 1);
180 }
181 #else /* SYSV */
182
183 static void
184 nohostname()
185 {
186 /* empty */
187 }
188 #endif
189
190 /*
191 * Return a name for the IP address pointed to by ap. This address
192 * is assumed to be in network byte order.
193 */
194 char *
195 getname(ap)
196 u_char *ap;
197 {
198 register char *cp;
199 u_int32_t addr;
200 /* static for longjmp */
201 static struct hostent *hp;
202 static struct hnamemem *p;
203 static int oldtimer;
204 static sigfunc oldalarm;
205
206 #ifndef LBL_ALIGN
207 addr = *(const u_int32_t *)ap;
208 #else
209 /*
210 * Extract 32 bits in network order, dealing with alignment.
211 */
212 switch ((long)ap & 3) {
213 case 0:
214 addr = *(u_int32_t *)ap;
215 break;
216 case 2:
217 #ifdef WORDS_BIGENDIAN
218 addr = ((u_int32_t)*(u_short *)ap << 16) |
219 (u_int32_t)*(u_short *)(ap + 2);
220 #else
221 addr = ((u_int32_t)*(u_short *)(ap + 2) << 16) |
222 (u_int32_t)*(u_short *)ap;
223 #endif
224 break;
225 default:
226 #ifdef WORDS_BIGENDIAN
227 addr = ((u_int32_t)ap[0] << 24) |
228 ((u_int32_t)ap[1] << 16) |
229 ((u_int32_t)ap[2] << 8) |
230 (u_int32_t)ap[3];
231 #else
232 addr = ((u_int32_t)ap[3] << 24) |
233 ((u_int32_t)ap[2] << 16) |
234 ((u_int32_t)ap[1] << 8) |
235 (u_int32_t)ap[0];
236 #endif
237 break;
238 }
239 #endif
240 for (p = &hnametable[addr & (HASHNAMESIZE-1)]; p->nxt; p = p->nxt)
241 if (p->addr == addr)
242 return (p->name);
243
244 p->addr = addr;
245 p->nxt = newhnamemem();
246 hp = NULL;
247
248 /*
249 * Only print names when:
250 * (1) -n was not given.
251 * (2) Address is foreign and -f was given. If -f was not
252 * present, f_netmask and f_local are 0 and the second
253 * test will succeed.
254 * (3) The host portion is not 0 (i.e., a network address).
255 * (4) The host portion is not broadcast.
256 */
257 if (!nflag && (addr & f_netmask) == f_localnet &&
258 (addr &~ netmask) != 0 && (addr | netmask) != 0xffffffff) {
259 oldtimer = alarm(dns_timeout);
260 oldalarm = signal(SIGALRM, nohostname);
261 #ifdef HAVE_SIGINTERRUPT
262 if (!setjmp(getname_env))
263 #endif
264 hp = gethostbyaddr((char *)&addr, 4, AF_INET);
265 (void)signal(SIGALRM, oldalarm);
266 if (oldtimer < 1) oldtimer = 1;
267 (void)alarm(oldtimer);
268 }
269 if (hp) {
270 if (Nflag && (cp = strchr(hp->h_name, '.')) != NULL)
271 *cp = '\0';
272 cp = hp->h_name;
273 } else cp = intoa(addr);
274
275 p->name = savestr(cp);
276 return p->name;
277 }
278
279 char *
280 tcpport_string(port)
281 u_short port;
282 {
283 register struct hnamemem *tp;
284 register u_int32_t i = port;
285 char buf[sizeof("00000")];
286
287 for (tp = &tporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
288 if (tp->addr == i)
289 return (tp->name);
290
291 tp->addr = i;
292 tp->nxt = newhnamemem();
293
294 (void)sprintf(buf, "%u", i);
295 tp->name = savestr(buf);
296 return (tp->name);
297 }
298
299 char *
300 udpport_string(port)
301 u_short port;
302 {
303 register struct hnamemem *tp;
304 register u_int32_t i = port;
305 char buf[sizeof("00000")];
306
307 for (tp = &uporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
308 if (tp->addr == i)
309 return (tp->name);
310
311 tp->addr = i;
312 tp->nxt = newhnamemem();
313
314 (void)sprintf(buf, "%u", i);
315 tp->name = savestr(buf);
316 return (tp->name);
317 }
318
319 static void
320 init_servarray()
321 {
322 struct servent *sv;
323 register struct hnamemem *table;
324 register int i;
325 char buf[sizeof("0000000000")];
326
327 while ((sv = getservent()) != NULL) {
328 int port = ntohs(sv->s_port);
329 i = port & (HASHNAMESIZE-1);
330 if (strcmp(sv->s_proto, "tcp") == 0)
331 table = &tporttable[i];
332 else if (strcmp(sv->s_proto, "udp") == 0)
333 table = &uporttable[i];
334 else continue;
335
336 while (table->name) table = table->nxt;
337
338 if (nflag) {
339 (void)sprintf(buf, "%d", port);
340 table->name = savestr(buf);
341 } else table->name = savestr(sv->s_name);
342 table->addr = port;
343 table->nxt = newhnamemem();
344 }
345 endservent();
346 }
347
348 static char hex[] = "0123456789abcdef";
349
350 char *
351 entoa(ep)
352 register u_char *ep;
353 {
354 register u_int i, j;
355 register char *cp;
356 static char buf[sizeof("00:00:00:00:00:00")];
357
358 cp = buf;
359 if ((j = *ep >> 4) != 0)
360 *cp++ = hex[j];
361 *cp++ = hex[*ep++ & 0xf];
362 for (i = 5; (int)--i >= 0;) {
363 *cp++ = ':';
364 if ((j = *ep >> 4) != 0)
365 *cp++ = hex[j];
366 *cp++ = hex[*ep++ & 0xf];
367 }
368 *cp = '\0';
369
370 return buf;
371 }
372
373 char *
374 etheraddr_string(ep)
375 register u_char *ep;
376 {
377 register u_int i, j, k;
378 register struct enamemem *tp;
379 u_char *ap;
380
381 k = (ep[0] << 8) | ep[1];
382 j = (ep[2] << 8) | ep[3];
383 i = (ep[4] << 8) | ep[5];
384
385 for (tp = &enametable[(i ^ j) & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
386 if (tp->addr0 == i && tp->addr1 == j && tp->addr2 == k)
387 return (tp->name);
388
389 tp->addr0 = i;
390 tp->addr1 = j;
391 tp->addr2 = k;
392 tp->nxt = (struct enamemem *)calloc(1, sizeof(*tp));
393 if (tp->nxt == NULL) error(1, "etheraddr_string: calloc");
394
395 if ((ap = getarptab(ep)) != NULL)
396 ap = getname(ap);
397 else ap = entoa(ep);
398
399 tp->name = savestr(ap);
400 return (tp->name);
401 }
402
403 char *
404 etherproto_string(proto)
405 u_short proto;
406 {
407 register char *cp;
408 register struct hnamemem *tp;
409 register u_int32_t i = proto;
410 char buf[sizeof("0000")];
411
412 for (tp = &eprototable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
413 if (tp->addr == i)
414 return (tp->name);
415
416 tp->addr = i;
417 tp->nxt = newhnamemem();
418
419 cp = buf;
420 proto = ntohs(proto);
421 *cp++ = hex[proto >> 12 & 0xf];
422 *cp++ = hex[proto >> 8 & 0xf];
423 *cp++ = hex[proto >> 4 & 0xf];
424 *cp++ = hex[proto & 0xf];
425 *cp++ = '\0';
426 tp->name = savestr(buf);
427 return (tp->name);
428 }
429
430 /* XXX from pcap library */
431 extern struct eproto {
432 char *s;
433 u_short p;
434 } eproto_db[];
435
436 static void
437 init_eprotoarray()
438 {
439 register int i;
440 register struct hnamemem *tp;
441
442 for (i = 0; eproto_db[i].s; i++) {
443 for (tp = &eprototable[ntohs(eproto_db[i].p) & (HASHNAMESIZE-1)];
444 tp->name; tp = tp->nxt) ;
445 tp->name = eproto_db[i].s;
446 tp->addr = ntohs(eproto_db[i].p);
447 tp->nxt = newhnamemem();
448 }
449 }
450
451 /*
452 * Initialize the address to name translation machinery. We map all
453 * non-local IP addresses to numeric addresses if fflag is true (i.e.,
454 * to prevent blocking on the nameserver). localnet is the IP address
455 * of the local network. mask is its subnet mask.
456 */
457 void
458 init_addrtoname(localnet, mask)
459 u_int32_t localnet;
460 u_int32_t mask;
461 {
462 netmask = mask;
463 if (fflag) {
464 f_localnet = localnet;
465 f_netmask = mask;
466 }
467 if (nflag)
468 /*
469 * Simplest way to suppress names.
470 */
471 return;
472
473 init_servarray();
474 init_eprotoarray();
475 }