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 + -
显示快捷键?