addrtoname.c

来自「TCPDUMP的C语言源代码,是在数据链路层的应用」· C语言 代码 · 共 1,183 行 · 第 1/2 页

C
1,183
字号
/* * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 *	The Regents of the University of California.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * *  Internet, ethernet, port, and protocol string to address *  and address to string conversion routines */#ifndef lintstatic const char rcsid[] _U_ =    "@(#) $Header: /tcpdump/master/tcpdump/addrtoname.c,v 1.119 2007-08-08 14:06:34 hannes Exp $ (LBL)";#endif#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <tcpdump-stdinc.h>#ifdef USE_ETHER_NTOHOST#ifdef HAVE_NETINET_IF_ETHER_Hstruct mbuf;		/* Squelch compiler warnings on some platforms for */struct rtentry;		/* declarations in <net/if.h> */#include <net/if.h>	/* for "struct ifnet" in "struct arpcom" on Solaris */#include <netinet/if_ether.h>#endif /* HAVE_NETINET_IF_ETHER_H */#ifdef NETINET_ETHER_H_DECLARES_ETHER_NTOHOST#include <netinet/ether.h>#endif /* NETINET_ETHER_H_DECLARES_ETHER_NTOHOST */#if !defined(HAVE_DECL_ETHER_NTOHOST) || !HAVE_DECL_ETHER_NTOHOST#ifndef HAVE_STRUCT_ETHER_ADDRstruct ether_addr {	unsigned char ether_addr_octet[6];};#endifextern int ether_ntohost(char *, const struct ether_addr *);#endif#endif /* USE_ETHER_NTOHOST */#include <pcap.h>#include <pcap-namedb.h>#include <signal.h>#include <stdio.h>#include <string.h>#include <stdlib.h>#include "interface.h"#include "addrtoname.h"#include "llc.h"#include "setsignal.h"#include "extract.h"#include "oui.h"#ifndef ETHER_ADDR_LEN#define ETHER_ADDR_LEN	6#endif/* * hash tables for whatever-to-name translations * * XXX there has to be error checks against strdup(3) failure */#define HASHNAMESIZE 4096struct hnamemem {	u_int32_t addr;	const char *name;	struct hnamemem *nxt;};struct hnamemem hnametable[HASHNAMESIZE];struct hnamemem tporttable[HASHNAMESIZE];struct hnamemem uporttable[HASHNAMESIZE];struct hnamemem eprototable[HASHNAMESIZE];struct hnamemem dnaddrtable[HASHNAMESIZE];struct hnamemem ipxsaptable[HASHNAMESIZE];#if defined(INET6) && defined(WIN32)/* * fake gethostbyaddr for Win2k/XP * gethostbyaddr() returns incorrect value when AF_INET6 is passed * to 3rd argument. * * h_name in struct hostent is only valid. */static struct hostent *win32_gethostbyaddr(const char *addr, int len, int type){	static struct hostent host;	static char hostbuf[NI_MAXHOST];	char hname[NI_MAXHOST];	struct sockaddr_in6 addr6;	host.h_name = hostbuf;	switch (type) {	case AF_INET:		return gethostbyaddr(addr, len, type);		break;	case AF_INET6:		memset(&addr6, 0, sizeof(addr6));		addr6.sin6_family = AF_INET6;		memcpy(&addr6.sin6_addr, addr, len);		if (getnameinfo((struct sockaddr *)&addr6, sizeof(addr6),		    hname, sizeof(hname), NULL, 0, 0)) {			return NULL;		} else {			strcpy(host.h_name, hname);			return &host;		}		break;	default:		return NULL;	}}#define gethostbyaddr win32_gethostbyaddr#endif /* INET6 & WIN32 */#ifdef INET6struct h6namemem {	struct in6_addr addr;	char *name;	struct h6namemem *nxt;};struct h6namemem h6nametable[HASHNAMESIZE];#endif /* INET6 */struct enamemem {	u_short e_addr0;	u_short e_addr1;	u_short e_addr2;	const char *e_name;	u_char *e_nsap;			/* used only for nsaptable[] */#define e_bs e_nsap			/* for bytestringtable */	struct enamemem *e_nxt;};struct enamemem enametable[HASHNAMESIZE];struct enamemem nsaptable[HASHNAMESIZE];struct enamemem bytestringtable[HASHNAMESIZE];struct protoidmem {	u_int32_t p_oui;	u_short p_proto;	const char *p_name;	struct protoidmem *p_nxt;};struct protoidmem protoidtable[HASHNAMESIZE];/* * A faster replacement for inet_ntoa(). */const char *intoa(u_int32_t addr){	register char *cp;	register u_int byte;	register int n;	static char buf[sizeof(".xxx.xxx.xxx.xxx")];	NTOHL(addr);	cp = buf + sizeof(buf);	*--cp = '\0';	n = 4;	do {		byte = addr & 0xff;		*--cp = byte % 10 + '0';		byte /= 10;		if (byte > 0) {			*--cp = byte % 10 + '0';			byte /= 10;			if (byte > 0)				*--cp = byte + '0';		}		*--cp = '.';		addr >>= 8;	} while (--n > 0);	return cp + 1;}static u_int32_t f_netmask;static u_int32_t f_localnet;/* * Return a name for the IP address pointed to by ap.  This address * is assumed to be in network byte order. * * NOTE: ap is *NOT* necessarily part of the packet data (not even if * this is being called with the "ipaddr_string()" macro), so you * *CANNOT* use the TCHECK{2}/TTEST{2} macros on it.  Furthermore, * even in cases where it *is* part of the packet data, the caller * would still have to check for a null return value, even if it's * just printing the return value with "%s" - not all versions of * printf print "(null)" with "%s" and a null pointer, some of them * don't check for a null pointer and crash in that case. * * The callers of this routine should, before handing this routine * a pointer to packet data, be sure that the data is present in * the packet buffer.  They should probably do those checks anyway, * as other data at that layer might not be IP addresses, and it * also needs to check whether they're present in the packet buffer. */const char *getname(const u_char *ap){	register struct hostent *hp;	u_int32_t addr;	static struct hnamemem *p;		/* static for longjmp() */	memcpy(&addr, ap, sizeof(addr));	p = &hnametable[addr & (HASHNAMESIZE-1)];	for (; p->nxt; p = p->nxt) {		if (p->addr == addr)			return (p->name);	}	p->addr = addr;	p->nxt = newhnamemem();	/*	 * Print names unless:	 *	(1) -n was given.	 *      (2) Address is foreign and -f was given. (If -f was not	 *	    given, f_netmask and f_localnet are 0 and the test	 *	    evaluates to true)	 */	if (!nflag &&	    (addr & f_netmask) == f_localnet) {		hp = gethostbyaddr((char *)&addr, 4, AF_INET);		if (hp) {			char *dotp;			p->name = strdup(hp->h_name);			if (Nflag) {				/* Remove domain qualifications */				dotp = strchr(p->name, '.');				if (dotp)					*dotp = '\0';			}			return (p->name);		}	}	p->name = strdup(intoa(addr));	return (p->name);}#ifdef INET6/* * Return a name for the IP6 address pointed to by ap.  This address * is assumed to be in network byte order. */const char *getname6(const u_char *ap){	register struct hostent *hp;	struct in6_addr addr;	static struct h6namemem *p;		/* static for longjmp() */	register const char *cp;	char ntop_buf[INET6_ADDRSTRLEN];	memcpy(&addr, ap, sizeof(addr));	p = &h6nametable[*(u_int16_t *)&addr.s6_addr[14] & (HASHNAMESIZE-1)];	for (; p->nxt; p = p->nxt) {		if (memcmp(&p->addr, &addr, sizeof(addr)) == 0)			return (p->name);	}	p->addr = addr;	p->nxt = newh6namemem();	/*	 * Do not print names if -n was given.	 */	if (!nflag) {		hp = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET6);		if (hp) {			char *dotp;			p->name = strdup(hp->h_name);			if (Nflag) {				/* Remove domain qualifications */				dotp = strchr(p->name, '.');				if (dotp)					*dotp = '\0';			}			return (p->name);		}	}	cp = inet_ntop(AF_INET6, &addr, ntop_buf, sizeof(ntop_buf));	p->name = strdup(cp);	return (p->name);}#endif /* INET6 */static char hex[] = "0123456789abcdef";/* Find the hash node that corresponds the ether address 'ep' */static inline struct enamemem *lookup_emem(const u_char *ep){	register u_int i, j, k;	struct enamemem *tp;	k = (ep[0] << 8) | ep[1];	j = (ep[2] << 8) | ep[3];	i = (ep[4] << 8) | ep[5];	tp = &enametable[(i ^ j) & (HASHNAMESIZE-1)];	while (tp->e_nxt)		if (tp->e_addr0 == i &&		    tp->e_addr1 == j &&		    tp->e_addr2 == k)			return tp;		else			tp = tp->e_nxt;	tp->e_addr0 = i;	tp->e_addr1 = j;	tp->e_addr2 = k;	tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp));	if (tp->e_nxt == NULL)		error("lookup_emem: calloc");	return tp;}/* * Find the hash node that corresponds to the bytestring 'bs' * with length 'nlen' */static inline struct enamemem *lookup_bytestring(register const u_char *bs, const unsigned int nlen){	struct enamemem *tp;	register u_int i, j, k;	if (nlen >= 6) {		k = (bs[0] << 8) | bs[1];		j = (bs[2] << 8) | bs[3];		i = (bs[4] << 8) | bs[5];	} else if (nlen >= 4) {		k = (bs[0] << 8) | bs[1];		j = (bs[2] << 8) | bs[3];		i = 0;	} else		i = j = k = 0;	tp = &bytestringtable[(i ^ j) & (HASHNAMESIZE-1)];	while (tp->e_nxt)		if (tp->e_addr0 == i &&		    tp->e_addr1 == j &&		    tp->e_addr2 == k &&		    memcmp((const char *)bs, (const char *)(tp->e_bs), nlen) == 0)			return tp;		else			tp = tp->e_nxt;	tp->e_addr0 = i;	tp->e_addr1 = j;	tp->e_addr2 = k;	tp->e_bs = (u_char *) calloc(1, nlen + 1);	memcpy(tp->e_bs, bs, nlen);	tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp));	if (tp->e_nxt == NULL)		error("lookup_bytestring: calloc");	return tp;}/* Find the hash node that corresponds the NSAP 'nsap' */static inline struct enamemem *lookup_nsap(register const u_char *nsap){	register u_int i, j, k;	unsigned int nlen = *nsap;	struct enamemem *tp;	const u_char *ensap = nsap + nlen - 6;	if (nlen > 6) {		k = (ensap[0] << 8) | ensap[1];		j = (ensap[2] << 8) | ensap[3];		i = (ensap[4] << 8) | ensap[5];	}	else		i = j = k = 0;	tp = &nsaptable[(i ^ j) & (HASHNAMESIZE-1)];	while (tp->e_nxt)		if (tp->e_addr0 == i &&		    tp->e_addr1 == j &&		    tp->e_addr2 == k &&		    tp->e_nsap[0] == nlen &&		    memcmp((const char *)&(nsap[1]),			(char *)&(tp->e_nsap[1]), nlen) == 0)			return tp;		else			tp = tp->e_nxt;	tp->e_addr0 = i;	tp->e_addr1 = j;	tp->e_addr2 = k;	tp->e_nsap = (u_char *)malloc(nlen + 1);	if (tp->e_nsap == NULL)		error("lookup_nsap: malloc");	memcpy((char *)tp->e_nsap, (const char *)nsap, nlen + 1);	tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp));	if (tp->e_nxt == NULL)		error("lookup_nsap: calloc");	return tp;}/* Find the hash node that corresponds the protoid 'pi'. */static inline struct protoidmem *lookup_protoid(const u_char *pi){	register u_int i, j;	struct protoidmem *tp;	/* 5 octets won't be aligned */	i = (((pi[0] << 8) + pi[1]) << 8) + pi[2];	j =   (pi[3] << 8) + pi[4];	/* XXX should be endian-insensitive, but do big-endian testing  XXX */	tp = &protoidtable[(i ^ j) & (HASHNAMESIZE-1)];	while (tp->p_nxt)		if (tp->p_oui == i && tp->p_proto == j)			return tp;		else			tp = tp->p_nxt;	tp->p_oui = i;	tp->p_proto = j;	tp->p_nxt = (struct protoidmem *)calloc(1, sizeof(*tp));	if (tp->p_nxt == NULL)		error("lookup_protoid: calloc");	return tp;}const char *etheraddr_string(register const u_char *ep){	register int i;	register char *cp;	register struct enamemem *tp;	int oui;	char buf[BUFSIZE];	tp = lookup_emem(ep);	if (tp->e_name)		return (tp->e_name);#ifdef USE_ETHER_NTOHOST	if (!nflag) {		char buf2[BUFSIZE];		/*		 * We don't cast it to "const struct ether_addr *"		 * because some systems fail to declare the second		 * argument as a "const" pointer, even though they		 * don't modify what it points to.		 */		if (ether_ntohost(buf2, (struct ether_addr *)ep) == 0) {			tp->e_name = strdup(buf2);			return (tp->e_name);		}	}#endif	cp = buf;	oui = EXTRACT_24BITS(ep);	*cp++ = hex[*ep >> 4 ];	*cp++ = hex[*ep++ & 0xf];	for (i = 5; --i >= 0;) {		*cp++ = ':';		*cp++ = hex[*ep >> 4 ];		*cp++ = hex[*ep++ & 0xf];	}	if (!nflag) {		snprintf(cp, BUFSIZE - (2 + 5*3), " (oui %s)",		    tok2str(oui_values, "Unknown", oui));	} else		*cp = '\0';	tp->e_name = strdup(buf);	return (tp->e_name);}const char *linkaddr_string(const u_char *ep, const unsigned int type, const unsigned int len){	register u_int i;	register char *cp;	register struct enamemem *tp;	if (type == LINKADDR_ETHER && len == ETHER_ADDR_LEN) {            return etheraddr_string(ep);        }        if (type == LINKADDR_FRELAY) {            return q922_string(ep);        }	tp = lookup_bytestring(ep, len);	if (tp->e_name)		return (tp->e_name);	tp->e_name = cp = (char *)malloc(len*3);	if (tp->e_name == NULL)		error("linkaddr_string: malloc");	*cp++ = hex[*ep >> 4];	*cp++ = hex[*ep++ & 0xf];	for (i = len-1; i > 0 ; --i) {		*cp++ = ':';		*cp++ = hex[*ep >> 4];		*cp++ = hex[*ep++ & 0xf];	}	*cp = '\0';	return (tp->e_name);}const char *etherproto_string(u_short port){	register char *cp;	register struct hnamemem *tp;	register u_int32_t i = port;	char buf[sizeof("0000")];	for (tp = &eprototable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)		if (tp->addr == i)			return (tp->name);	tp->addr = i;	tp->nxt = newhnamemem();	cp = buf;	NTOHS(port);	*cp++ = hex[port >> 12 & 0xf];	*cp++ = hex[port >> 8 & 0xf];	*cp++ = hex[port >> 4 & 0xf];	*cp++ = hex[port & 0xf];	*cp++ = '\0';	tp->name = strdup(buf);	return (tp->name);}const char *protoid_string(register const u_char *pi){	register u_int i, j;	register char *cp;	register struct protoidmem *tp;	char buf[sizeof("00:00:00:00:00")];	tp = lookup_protoid(pi);	if (tp->p_name)		return tp->p_name;	cp = buf;	if ((j = *pi >> 4) != 0)		*cp++ = hex[j];	*cp++ = hex[*pi++ & 0xf];	for (i = 4; (int)--i >= 0;) {		*cp++ = ':';		if ((j = *pi >> 4) != 0)			*cp++ = hex[j];		*cp++ = hex[*pi++ & 0xf];	}	*cp = '\0';	tp->p_name = strdup(buf);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?