"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 }