Index: head/contrib/tcpdump/addrtoname.c =================================================================== --- head/contrib/tcpdump/addrtoname.c (revision 324286) +++ head/contrib/tcpdump/addrtoname.c (revision 324287) @@ -1,1294 +1,1294 @@ /* * 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 */ #ifdef HAVE_CONFIG_H #include "config.h" #endif -#ifdef WITH_CASPER +#ifdef HAVE_CASPER #include #include -#endif /* WITH_CASPER */ +#endif /* HAVE_CASPER */ #include #ifdef USE_ETHER_NTOHOST #ifdef HAVE_NETINET_IF_ETHER_H struct mbuf; /* Squelch compiler warnings on some platforms for */ struct rtentry; /* declarations in */ #include /* for "struct ifnet" in "struct arpcom" on Solaris */ #include #endif /* HAVE_NETINET_IF_ETHER_H */ #ifdef NETINET_ETHER_H_DECLARES_ETHER_NTOHOST #include #endif /* NETINET_ETHER_H_DECLARES_ETHER_NTOHOST */ #if !defined(HAVE_DECL_ETHER_NTOHOST) || !HAVE_DECL_ETHER_NTOHOST #ifndef HAVE_STRUCT_ETHER_ADDR struct ether_addr { unsigned char ether_addr_octet[6]; }; #endif extern int ether_ntohost(char *, const struct ether_addr *); #endif #endif /* USE_ETHER_NTOHOST */ #include #include #include #include #include #include #include "netdissect.h" #include "addrtoname.h" #include "addrtostr.h" #include "ethertype.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 * * ndo_error() called on strdup(3) failure */ #define HASHNAMESIZE 4096 struct hnamemem { uint32_t addr; const char *name; struct hnamemem *nxt; }; static struct hnamemem hnametable[HASHNAMESIZE]; static struct hnamemem tporttable[HASHNAMESIZE]; static struct hnamemem uporttable[HASHNAMESIZE]; static struct hnamemem eprototable[HASHNAMESIZE]; static struct hnamemem dnaddrtable[HASHNAMESIZE]; static struct hnamemem ipxsaptable[HASHNAMESIZE]; #ifdef _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 /* _WIN32 */ struct h6namemem { struct in6_addr addr; char *name; struct h6namemem *nxt; }; static struct h6namemem h6nametable[HASHNAMESIZE]; 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; }; static struct enamemem enametable[HASHNAMESIZE]; static struct enamemem nsaptable[HASHNAMESIZE]; static struct enamemem bytestringtable[HASHNAMESIZE]; struct protoidmem { uint32_t p_oui; u_short p_proto; const char *p_name; struct protoidmem *p_nxt; }; static struct protoidmem protoidtable[HASHNAMESIZE]; /* * A faster replacement for inet_ntoa(). */ const char * intoa(uint32_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 uint32_t f_netmask; static uint32_t f_localnet; -#ifdef WITH_CASPER +#ifdef HAVE_CASPER extern cap_channel_t *capdns; #endif /* * 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 ND_TCHECK{2}/ND_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(netdissect_options *ndo, const u_char *ap) { register struct hostent *hp; uint32_t addr; struct hnamemem *p; 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(ndo); /* * 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 (!ndo->ndo_nflag && (addr & f_netmask) == f_localnet) { -#ifdef WITH_CASPER +#ifdef HAVE_CASPER if (capdns != NULL) { hp = cap_gethostbyaddr(capdns, (char *)&addr, 4, AF_INET); } else #endif hp = gethostbyaddr((char *)&addr, 4, AF_INET); if (hp) { char *dotp; p->name = strdup(hp->h_name); if (p->name == NULL) (*ndo->ndo_error)(ndo, "getname: strdup(hp->h_name)"); if (ndo->ndo_Nflag) { /* Remove domain qualifications */ dotp = strchr(p->name, '.'); if (dotp) *dotp = '\0'; } return (p->name); } } p->name = strdup(intoa(addr)); if (p->name == NULL) (*ndo->ndo_error)(ndo, "getname: strdup(intoa(addr))"); return (p->name); } /* * Return a name for the IP6 address pointed to by ap. This address * is assumed to be in network byte order. */ const char * getname6(netdissect_options *ndo, const u_char *ap) { register struct hostent *hp; union { struct in6_addr addr; struct for_hash_addr { char fill[14]; uint16_t d; } addra; } addr; struct h6namemem *p; register const char *cp; char ntop_buf[INET6_ADDRSTRLEN]; memcpy(&addr, ap, sizeof(addr)); p = &h6nametable[addr.addra.d & (HASHNAMESIZE-1)]; for (; p->nxt; p = p->nxt) { if (memcmp(&p->addr, &addr, sizeof(addr)) == 0) return (p->name); } p->addr = addr.addr; p->nxt = newh6namemem(ndo); /* * Do not print names if -n was given. */ if (!ndo->ndo_nflag) { -#ifdef WITH_CASPER +#ifdef HAVE_CASPER if (capdns != NULL) { hp = cap_gethostbyaddr(capdns, (char *)&addr, sizeof(addr), AF_INET6); } else #endif hp = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET6); if (hp) { char *dotp; p->name = strdup(hp->h_name); if (p->name == NULL) (*ndo->ndo_error)(ndo, "getname6: strdup(hp->h_name)"); if (ndo->ndo_Nflag) { /* Remove domain qualifications */ dotp = strchr(p->name, '.'); if (dotp) *dotp = '\0'; } return (p->name); } } cp = addrtostr6(ap, ntop_buf, sizeof(ntop_buf)); p->name = strdup(cp); if (p->name == NULL) (*ndo->ndo_error)(ndo, "getname6: strdup(cp)"); return (p->name); } static const char hex[] = "0123456789abcdef"; /* Find the hash node that corresponds the ether address 'ep' */ static inline struct enamemem * lookup_emem(netdissect_options *ndo, 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) (*ndo->ndo_error)(ndo, "lookup_emem: calloc"); return tp; } /* * Find the hash node that corresponds to the bytestring 'bs' * with length 'nlen' */ static inline struct enamemem * lookup_bytestring(netdissect_options *ndo, 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); if (tp->e_bs == NULL) (*ndo->ndo_error)(ndo, "lookup_bytestring: calloc"); memcpy(tp->e_bs, bs, nlen); tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp)); if (tp->e_nxt == NULL) (*ndo->ndo_error)(ndo, "lookup_bytestring: calloc"); return tp; } /* Find the hash node that corresponds the NSAP 'nsap' */ static inline struct enamemem * lookup_nsap(netdissect_options *ndo, register const u_char *nsap, register u_int nsap_length) { register u_int i, j, k; struct enamemem *tp; const u_char *ensap; if (nsap_length > 6) { ensap = nsap + nsap_length - 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] == nsap_length && memcmp((const char *)&(nsap[1]), (char *)&(tp->e_nsap[1]), nsap_length) == 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(nsap_length + 1); if (tp->e_nsap == NULL) (*ndo->ndo_error)(ndo, "lookup_nsap: malloc"); tp->e_nsap[0] = (u_char)nsap_length; /* guaranteed < ISONSAP_MAX_LENGTH */ memcpy((char *)&tp->e_nsap[1], (const char *)nsap, nsap_length); tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp)); if (tp->e_nxt == NULL) (*ndo->ndo_error)(ndo, "lookup_nsap: calloc"); return tp; } /* Find the hash node that corresponds the protoid 'pi'. */ static inline struct protoidmem * lookup_protoid(netdissect_options *ndo, 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) (*ndo->ndo_error)(ndo, "lookup_protoid: calloc"); return tp; } const char * etheraddr_string(netdissect_options *ndo, register const u_char *ep) { register int i; register char *cp; register struct enamemem *tp; int oui; char buf[BUFSIZE]; tp = lookup_emem(ndo, ep); if (tp->e_name) return (tp->e_name); #ifdef USE_ETHER_NTOHOST if (!ndo->ndo_nflag) { char buf2[BUFSIZE]; if (ether_ntohost(buf2, (const struct ether_addr *)ep) == 0) { tp->e_name = strdup(buf2); if (tp->e_name == NULL) (*ndo->ndo_error)(ndo, "etheraddr_string: 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 (!ndo->ndo_nflag) { snprintf(cp, BUFSIZE - (2 + 5*3), " (oui %s)", tok2str(oui_values, "Unknown", oui)); } else *cp = '\0'; tp->e_name = strdup(buf); if (tp->e_name == NULL) (*ndo->ndo_error)(ndo, "etheraddr_string: strdup(buf)"); return (tp->e_name); } const char * le64addr_string(netdissect_options *ndo, const u_char *ep) { const unsigned int len = 8; register u_int i; register char *cp; register struct enamemem *tp; char buf[BUFSIZE]; tp = lookup_bytestring(ndo, ep, len); if (tp->e_name) return (tp->e_name); cp = buf; for (i = len; i > 0 ; --i) { *cp++ = hex[*(ep + i - 1) >> 4]; *cp++ = hex[*(ep + i - 1) & 0xf]; *cp++ = ':'; } cp --; *cp = '\0'; tp->e_name = strdup(buf); if (tp->e_name == NULL) (*ndo->ndo_error)(ndo, "le64addr_string: strdup(buf)"); return (tp->e_name); } const char * linkaddr_string(netdissect_options *ndo, const u_char *ep, const unsigned int type, const unsigned int len) { register u_int i; register char *cp; register struct enamemem *tp; if (len == 0) return (""); if (type == LINKADDR_ETHER && len == ETHER_ADDR_LEN) return (etheraddr_string(ndo, ep)); if (type == LINKADDR_FRELAY) return (q922_string(ndo, ep, len)); tp = lookup_bytestring(ndo, ep, len); if (tp->e_name) return (tp->e_name); tp->e_name = cp = (char *)malloc(len*3); if (tp->e_name == NULL) (*ndo->ndo_error)(ndo, "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(netdissect_options *ndo, u_short port) { register char *cp; register struct hnamemem *tp; register uint32_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(ndo); 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); if (tp->name == NULL) (*ndo->ndo_error)(ndo, "etherproto_string: strdup(buf)"); return (tp->name); } const char * protoid_string(netdissect_options *ndo, 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(ndo, 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); if (tp->p_name == NULL) (*ndo->ndo_error)(ndo, "protoid_string: strdup(buf)"); return (tp->p_name); } #define ISONSAP_MAX_LENGTH 20 const char * isonsap_string(netdissect_options *ndo, const u_char *nsap, register u_int nsap_length) { register u_int nsap_idx; register char *cp; register struct enamemem *tp; if (nsap_length < 1 || nsap_length > ISONSAP_MAX_LENGTH) return ("isonsap_string: illegal length"); tp = lookup_nsap(ndo, nsap, nsap_length); if (tp->e_name) return tp->e_name; tp->e_name = cp = (char *)malloc(sizeof("xx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xx")); if (cp == NULL) (*ndo->ndo_error)(ndo, "isonsap_string: malloc"); for (nsap_idx = 0; nsap_idx < nsap_length; nsap_idx++) { *cp++ = hex[*nsap >> 4]; *cp++ = hex[*nsap++ & 0xf]; if (((nsap_idx & 1) == 0) && (nsap_idx + 1 < nsap_length)) { *cp++ = '.'; } } *cp = '\0'; return (tp->e_name); } const char * tcpport_string(netdissect_options *ndo, u_short port) { register struct hnamemem *tp; register uint32_t i = port; char buf[sizeof("00000")]; for (tp = &tporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) if (tp->addr == i) return (tp->name); tp->addr = i; tp->nxt = newhnamemem(ndo); (void)snprintf(buf, sizeof(buf), "%u", i); tp->name = strdup(buf); if (tp->name == NULL) (*ndo->ndo_error)(ndo, "tcpport_string: strdup(buf)"); return (tp->name); } const char * udpport_string(netdissect_options *ndo, register u_short port) { register struct hnamemem *tp; register uint32_t i = port; char buf[sizeof("00000")]; for (tp = &uporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) if (tp->addr == i) return (tp->name); tp->addr = i; tp->nxt = newhnamemem(ndo); (void)snprintf(buf, sizeof(buf), "%u", i); tp->name = strdup(buf); if (tp->name == NULL) (*ndo->ndo_error)(ndo, "udpport_string: strdup(buf)"); return (tp->name); } const char * ipxsap_string(netdissect_options *ndo, u_short port) { register char *cp; register struct hnamemem *tp; register uint32_t i = port; char buf[sizeof("0000")]; for (tp = &ipxsaptable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) if (tp->addr == i) return (tp->name); tp->addr = i; tp->nxt = newhnamemem(ndo); 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); if (tp->name == NULL) (*ndo->ndo_error)(ndo, "ipxsap_string: strdup(buf)"); return (tp->name); } static void init_servarray(netdissect_options *ndo) { struct servent *sv; register struct hnamemem *table; register int i; char buf[sizeof("0000000000")]; while ((sv = getservent()) != NULL) { int port = ntohs(sv->s_port); i = port & (HASHNAMESIZE-1); if (strcmp(sv->s_proto, "tcp") == 0) table = &tporttable[i]; else if (strcmp(sv->s_proto, "udp") == 0) table = &uporttable[i]; else continue; while (table->name) table = table->nxt; if (ndo->ndo_nflag) { (void)snprintf(buf, sizeof(buf), "%d", port); table->name = strdup(buf); } else table->name = strdup(sv->s_name); if (table->name == NULL) (*ndo->ndo_error)(ndo, "init_servarray: strdup"); table->addr = port; table->nxt = newhnamemem(ndo); } endservent(); } static const struct eproto { const char *s; u_short p; } eproto_db[] = { { "pup", ETHERTYPE_PUP }, { "xns", ETHERTYPE_NS }, { "ip", ETHERTYPE_IP }, { "ip6", ETHERTYPE_IPV6 }, { "arp", ETHERTYPE_ARP }, { "rarp", ETHERTYPE_REVARP }, { "sprite", ETHERTYPE_SPRITE }, { "mopdl", ETHERTYPE_MOPDL }, { "moprc", ETHERTYPE_MOPRC }, { "decnet", ETHERTYPE_DN }, { "lat", ETHERTYPE_LAT }, { "sca", ETHERTYPE_SCA }, { "lanbridge", ETHERTYPE_LANBRIDGE }, { "vexp", ETHERTYPE_VEXP }, { "vprod", ETHERTYPE_VPROD }, { "atalk", ETHERTYPE_ATALK }, { "atalkarp", ETHERTYPE_AARP }, { "loopback", ETHERTYPE_LOOPBACK }, { "decdts", ETHERTYPE_DECDTS }, { "decdns", ETHERTYPE_DECDNS }, { (char *)0, 0 } }; static void init_eprotoarray(netdissect_options *ndo) { register int i; register struct hnamemem *table; for (i = 0; eproto_db[i].s; i++) { int j = htons(eproto_db[i].p) & (HASHNAMESIZE-1); table = &eprototable[j]; while (table->name) table = table->nxt; table->name = eproto_db[i].s; table->addr = htons(eproto_db[i].p); table->nxt = newhnamemem(ndo); } } static const struct protoidlist { const u_char protoid[5]; const char *name; } protoidlist[] = { {{ 0x00, 0x00, 0x0c, 0x01, 0x07 }, "CiscoMLS" }, {{ 0x00, 0x00, 0x0c, 0x20, 0x00 }, "CiscoCDP" }, {{ 0x00, 0x00, 0x0c, 0x20, 0x01 }, "CiscoCGMP" }, {{ 0x00, 0x00, 0x0c, 0x20, 0x03 }, "CiscoVTP" }, {{ 0x00, 0xe0, 0x2b, 0x00, 0xbb }, "ExtremeEDP" }, {{ 0x00, 0x00, 0x00, 0x00, 0x00 }, NULL } }; /* * SNAP proto IDs with org code 0:0:0 are actually encapsulated Ethernet * types. */ static void init_protoidarray(netdissect_options *ndo) { register int i; register struct protoidmem *tp; const struct protoidlist *pl; u_char protoid[5]; protoid[0] = 0; protoid[1] = 0; protoid[2] = 0; for (i = 0; eproto_db[i].s; i++) { u_short etype = htons(eproto_db[i].p); memcpy((char *)&protoid[3], (char *)&etype, 2); tp = lookup_protoid(ndo, protoid); tp->p_name = strdup(eproto_db[i].s); if (tp->p_name == NULL) (*ndo->ndo_error)(ndo, "init_protoidarray: strdup(eproto_db[i].s)"); } /* Hardwire some SNAP proto ID names */ for (pl = protoidlist; pl->name != NULL; ++pl) { tp = lookup_protoid(ndo, pl->protoid); /* Don't override existing name */ if (tp->p_name != NULL) continue; tp->p_name = pl->name; } } static const struct etherlist { const u_char addr[6]; const char *name; } etherlist[] = { {{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, "Broadcast" }, {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, NULL } }; /* * Initialize the ethers hash table. We take two different approaches * depending on whether or not the system provides the ethers name * service. If it does, we just wire in a few names at startup, * and etheraddr_string() fills in the table on demand. If it doesn't, * then we suck in the entire /etc/ethers file at startup. The idea * is that parsing the local file will be fast, but spinning through * all the ethers entries via NIS & next_etherent might be very slow. * * XXX pcap_next_etherent doesn't belong in the pcap interface, but * since the pcap module already does name-to-address translation, * it's already does most of the work for the ethernet address-to-name * translation, so we just pcap_next_etherent as a convenience. */ static void init_etherarray(netdissect_options *ndo) { register const struct etherlist *el; register struct enamemem *tp; #ifdef USE_ETHER_NTOHOST char name[256]; #else register struct pcap_etherent *ep; register FILE *fp; /* Suck in entire ethers file */ fp = fopen(PCAP_ETHERS_FILE, "r"); if (fp != NULL) { while ((ep = pcap_next_etherent(fp)) != NULL) { tp = lookup_emem(ndo, ep->addr); tp->e_name = strdup(ep->name); if (tp->e_name == NULL) (*ndo->ndo_error)(ndo, "init_etherarray: strdup(ep->addr)"); } (void)fclose(fp); } #endif /* Hardwire some ethernet names */ for (el = etherlist; el->name != NULL; ++el) { tp = lookup_emem(ndo, el->addr); /* Don't override existing name */ if (tp->e_name != NULL) continue; #ifdef USE_ETHER_NTOHOST /* * Use YP/NIS version of name if available. */ if (ether_ntohost(name, (const struct ether_addr *)el->addr) == 0) { tp->e_name = strdup(name); if (tp->e_name == NULL) (*ndo->ndo_error)(ndo, "init_etherarray: strdup(name)"); continue; } #endif tp->e_name = el->name; } } static const struct tok ipxsap_db[] = { { 0x0000, "Unknown" }, { 0x0001, "User" }, { 0x0002, "User Group" }, { 0x0003, "PrintQueue" }, { 0x0004, "FileServer" }, { 0x0005, "JobServer" }, { 0x0006, "Gateway" }, { 0x0007, "PrintServer" }, { 0x0008, "ArchiveQueue" }, { 0x0009, "ArchiveServer" }, { 0x000a, "JobQueue" }, { 0x000b, "Administration" }, { 0x000F, "Novell TI-RPC" }, { 0x0017, "Diagnostics" }, { 0x0020, "NetBIOS" }, { 0x0021, "NAS SNA Gateway" }, { 0x0023, "NACS AsyncGateway" }, { 0x0024, "RemoteBridge/RoutingService" }, { 0x0026, "BridgeServer" }, { 0x0027, "TCP/IP Gateway" }, { 0x0028, "Point-to-point X.25 BridgeServer" }, { 0x0029, "3270 Gateway" }, { 0x002a, "CHI Corp" }, { 0x002c, "PC Chalkboard" }, { 0x002d, "TimeSynchServer" }, { 0x002e, "ARCserve5.0/PalindromeBackup" }, { 0x0045, "DI3270 Gateway" }, { 0x0047, "AdvertisingPrintServer" }, { 0x004a, "NetBlazerModems" }, { 0x004b, "BtrieveVAP" }, { 0x004c, "NetwareSQL" }, { 0x004d, "XtreeNetwork" }, { 0x0050, "BtrieveVAP4.11" }, { 0x0052, "QuickLink" }, { 0x0053, "PrintQueueUser" }, { 0x0058, "Multipoint X.25 Router" }, { 0x0060, "STLB/NLM" }, { 0x0064, "ARCserve" }, { 0x0066, "ARCserve3.0" }, { 0x0072, "WAN CopyUtility" }, { 0x007a, "TES-NetwareVMS" }, { 0x0092, "WATCOM Debugger/EmeraldTapeBackupServer" }, { 0x0095, "DDA OBGYN" }, { 0x0098, "NetwareAccessServer" }, { 0x009a, "Netware for VMS II/NamedPipeServer" }, { 0x009b, "NetwareAccessServer" }, { 0x009e, "PortableNetwareServer/SunLinkNVT" }, { 0x00a1, "PowerchuteAPC UPS" }, { 0x00aa, "LAWserve" }, { 0x00ac, "CompaqIDA StatusMonitor" }, { 0x0100, "PIPE STAIL" }, { 0x0102, "LAN ProtectBindery" }, { 0x0103, "OracleDataBaseServer" }, { 0x0107, "Netware386/RSPX RemoteConsole" }, { 0x010f, "NovellSNA Gateway" }, { 0x0111, "TestServer" }, { 0x0112, "HP PrintServer" }, { 0x0114, "CSA MUX" }, { 0x0115, "CSA LCA" }, { 0x0116, "CSA CM" }, { 0x0117, "CSA SMA" }, { 0x0118, "CSA DBA" }, { 0x0119, "CSA NMA" }, { 0x011a, "CSA SSA" }, { 0x011b, "CSA STATUS" }, { 0x011e, "CSA APPC" }, { 0x0126, "SNA TEST SSA Profile" }, { 0x012a, "CSA TRACE" }, { 0x012b, "NetwareSAA" }, { 0x012e, "IKARUS VirusScan" }, { 0x0130, "CommunicationsExecutive" }, { 0x0133, "NNS DomainServer/NetwareNamingServicesDomain" }, { 0x0135, "NetwareNamingServicesProfile" }, { 0x0137, "Netware386 PrintQueue/NNS PrintQueue" }, { 0x0141, "LAN SpoolServer" }, { 0x0152, "IRMALAN Gateway" }, { 0x0154, "NamedPipeServer" }, { 0x0166, "NetWareManagement" }, { 0x0168, "Intel PICKIT CommServer/Intel CAS TalkServer" }, { 0x0173, "Compaq" }, { 0x0174, "Compaq SNMP Agent" }, { 0x0175, "Compaq" }, { 0x0180, "XTreeServer/XTreeTools" }, { 0x018A, "NASI ServicesBroadcastServer" }, { 0x01b0, "GARP Gateway" }, { 0x01b1, "Binfview" }, { 0x01bf, "IntelLanDeskManager" }, { 0x01ca, "AXTEC" }, { 0x01cb, "ShivaNetModem/E" }, { 0x01cc, "ShivaLanRover/E" }, { 0x01cd, "ShivaLanRover/T" }, { 0x01ce, "ShivaUniversal" }, { 0x01d8, "CastelleFAXPressServer" }, { 0x01da, "CastelleLANPressPrintServer" }, { 0x01dc, "CastelleFAX/Xerox7033 FaxServer/ExcelLanFax" }, { 0x01f0, "LEGATO" }, { 0x01f5, "LEGATO" }, { 0x0233, "NMS Agent/NetwareManagementAgent" }, { 0x0237, "NMS IPX Discovery/LANternReadWriteChannel" }, { 0x0238, "NMS IP Discovery/LANternTrapAlarmChannel" }, { 0x023a, "LANtern" }, { 0x023c, "MAVERICK" }, { 0x023f, "NovellSMDR" }, { 0x024e, "NetwareConnect" }, { 0x024f, "NASI ServerBroadcast Cisco" }, { 0x026a, "NMS ServiceConsole" }, { 0x026b, "TimeSynchronizationServer Netware 4.x" }, { 0x0278, "DirectoryServer Netware 4.x" }, { 0x027b, "NetwareManagementAgent" }, { 0x0280, "Novell File and Printer Sharing Service for PC" }, { 0x0304, "NovellSAA Gateway" }, { 0x0308, "COM/VERMED" }, { 0x030a, "GalacticommWorldgroupServer" }, { 0x030c, "IntelNetport2/HP JetDirect/HP Quicksilver" }, { 0x0320, "AttachmateGateway" }, { 0x0327, "MicrosoftDiagnostiocs" }, { 0x0328, "WATCOM SQL Server" }, { 0x0335, "MultiTechSystems MultisynchCommServer" }, { 0x0343, "Xylogics RemoteAccessServer/LANModem" }, { 0x0355, "ArcadaBackupExec" }, { 0x0358, "MSLCD1" }, { 0x0361, "NETINELO" }, { 0x037e, "Powerchute UPS Monitoring" }, { 0x037f, "ViruSafeNotify" }, { 0x0386, "HP Bridge" }, { 0x0387, "HP Hub" }, { 0x0394, "NetWare SAA Gateway" }, { 0x039b, "LotusNotes" }, { 0x03b7, "CertusAntiVirus" }, { 0x03c4, "ARCserve4.0" }, { 0x03c7, "LANspool3.5" }, { 0x03d7, "LexmarkPrinterServer" }, { 0x03d8, "LexmarkXLE PrinterServer" }, { 0x03dd, "BanyanENS NetwareClient" }, { 0x03de, "GuptaSequelBaseServer/NetWareSQL" }, { 0x03e1, "UnivelUnixware" }, { 0x03e4, "UnivelUnixware" }, { 0x03fc, "IntelNetport" }, { 0x03fd, "PrintServerQueue" }, { 0x040A, "ipnServer" }, { 0x040D, "LVERRMAN" }, { 0x040E, "LVLIC" }, { 0x0414, "NET Silicon (DPI)/Kyocera" }, { 0x0429, "SiteLockVirus" }, { 0x0432, "UFHELPR???" }, { 0x0433, "Synoptics281xAdvancedSNMPAgent" }, { 0x0444, "MicrosoftNT SNA Server" }, { 0x0448, "Oracle" }, { 0x044c, "ARCserve5.01" }, { 0x0457, "CanonGP55" }, { 0x045a, "QMS Printers" }, { 0x045b, "DellSCSI Array" }, { 0x0491, "NetBlazerModems" }, { 0x04ac, "OnTimeScheduler" }, { 0x04b0, "CD-Net" }, { 0x0513, "EmulexNQA" }, { 0x0520, "SiteLockChecks" }, { 0x0529, "SiteLockChecks" }, { 0x052d, "CitrixOS2 AppServer" }, { 0x0535, "Tektronix" }, { 0x0536, "Milan" }, { 0x055d, "Attachmate SNA gateway" }, { 0x056b, "IBM8235 ModemServer" }, { 0x056c, "ShivaLanRover/E PLUS" }, { 0x056d, "ShivaLanRover/T PLUS" }, { 0x0580, "McAfeeNetShield" }, { 0x05B8, "NLM to workstation communication (Revelation Software)" }, { 0x05BA, "CompatibleSystemsRouters" }, { 0x05BE, "CheyenneHierarchicalStorageManager" }, { 0x0606, "JCWatermarkImaging" }, { 0x060c, "AXISNetworkPrinter" }, { 0x0610, "AdaptecSCSIManagement" }, { 0x0621, "IBM AntiVirus" }, { 0x0640, "Windows95 RemoteRegistryService" }, { 0x064e, "MicrosoftIIS" }, { 0x067b, "Microsoft Win95/98 File and Print Sharing for NetWare" }, { 0x067c, "Microsoft Win95/98 File and Print Sharing for NetWare" }, { 0x076C, "Xerox" }, { 0x079b, "ShivaLanRover/E 115" }, { 0x079c, "ShivaLanRover/T 115" }, { 0x07B4, "CubixWorldDesk" }, { 0x07c2, "Quarterdeck IWare Connect V2.x NLM" }, { 0x07c1, "Quarterdeck IWare Connect V3.x NLM" }, { 0x0810, "ELAN License Server Demo" }, { 0x0824, "ShivaLanRoverAccessSwitch/E" }, { 0x086a, "ISSC Collector" }, { 0x087f, "ISSC DAS AgentAIX" }, { 0x0880, "Intel Netport PRO" }, { 0x0881, "Intel Netport PRO" }, { 0x0b29, "SiteLock" }, { 0x0c29, "SiteLockApplications" }, { 0x0c2c, "LicensingServer" }, { 0x2101, "PerformanceTechnologyInstantInternet" }, { 0x2380, "LAI SiteLock" }, { 0x238c, "MeetingMaker" }, { 0x4808, "SiteLockServer/SiteLockMetering" }, { 0x5555, "SiteLockUser" }, { 0x6312, "Tapeware" }, { 0x6f00, "RabbitGateway" }, { 0x7703, "MODEM" }, { 0x8002, "NetPortPrinters" }, { 0x8008, "WordPerfectNetworkVersion" }, { 0x85BE, "Cisco EIGRP" }, { 0x8888, "WordPerfectNetworkVersion/QuickNetworkManagement" }, { 0x9000, "McAfeeNetShield" }, { 0x9604, "CSA-NT_MON" }, { 0xb6a8, "OceanIsleReachoutRemoteControl" }, { 0xf11f, "SiteLockMetering" }, { 0xf1ff, "SiteLock" }, { 0xf503, "Microsoft SQL Server" }, { 0xF905, "IBM TimeAndPlace" }, { 0xfbfb, "TopCallIII FaxServer" }, { 0xffff, "AnyService/Wildcard" }, { 0, (char *)0 } }; static void init_ipxsaparray(netdissect_options *ndo) { register int i; register struct hnamemem *table; for (i = 0; ipxsap_db[i].s != NULL; i++) { int j = htons(ipxsap_db[i].v) & (HASHNAMESIZE-1); table = &ipxsaptable[j]; while (table->name) table = table->nxt; table->name = ipxsap_db[i].s; table->addr = htons(ipxsap_db[i].v); table->nxt = newhnamemem(ndo); } } /* * Initialize the address to name translation machinery. We map all * non-local IP addresses to numeric addresses if ndo->ndo_fflag is true * (i.e., to prevent blocking on the nameserver). localnet is the IP address * of the local network. mask is its subnet mask. */ void init_addrtoname(netdissect_options *ndo, uint32_t localnet, uint32_t mask) { if (ndo->ndo_fflag) { f_localnet = localnet; f_netmask = mask; } if (ndo->ndo_nflag) /* * Simplest way to suppress names. */ return; init_etherarray(ndo); init_servarray(ndo); init_eprotoarray(ndo); init_protoidarray(ndo); init_ipxsaparray(ndo); } const char * dnaddr_string(netdissect_options *ndo, u_short dnaddr) { register struct hnamemem *tp; for (tp = &dnaddrtable[dnaddr & (HASHNAMESIZE-1)]; tp->nxt != NULL; tp = tp->nxt) if (tp->addr == dnaddr) return (tp->name); tp->addr = dnaddr; tp->nxt = newhnamemem(ndo); if (ndo->ndo_nflag) tp->name = dnnum_string(ndo, dnaddr); else tp->name = dnname_string(ndo, dnaddr); return(tp->name); } /* Return a zero'ed hnamemem struct and cuts down on calloc() overhead */ struct hnamemem * newhnamemem(netdissect_options *ndo) { register struct hnamemem *p; static struct hnamemem *ptr = NULL; static u_int num = 0; if (num <= 0) { num = 64; ptr = (struct hnamemem *)calloc(num, sizeof (*ptr)); if (ptr == NULL) (*ndo->ndo_error)(ndo, "newhnamemem: calloc"); } --num; p = ptr++; return (p); } /* Return a zero'ed h6namemem struct and cuts down on calloc() overhead */ struct h6namemem * newh6namemem(netdissect_options *ndo) { register struct h6namemem *p; static struct h6namemem *ptr = NULL; static u_int num = 0; if (num <= 0) { num = 64; ptr = (struct h6namemem *)calloc(num, sizeof (*ptr)); if (ptr == NULL) (*ndo->ndo_error)(ndo, "newh6namemem: calloc"); } --num; p = ptr++; return (p); } /* Represent TCI part of the 802.1Q 4-octet tag as text. */ const char * ieee8021q_tci_string(const uint16_t tci) { static char buf[128]; snprintf(buf, sizeof(buf), "vlan %u, p %u%s", tci & 0xfff, tci >> 13, (tci & 0x1000) ? ", DEI" : ""); return buf; } Index: head/contrib/tcpdump/tcpdump.c =================================================================== --- head/contrib/tcpdump/tcpdump.c (revision 324286) +++ head/contrib/tcpdump/tcpdump.c (revision 324287) @@ -1,2715 +1,2715 @@ /* * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000 * 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. * * Support for splitting captures into multiple files with a maximum * file size: * * Copyright (c) 2001 * Seth Webster */ #ifndef lint static const char copyright[] _U_ = "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* * tcpdump - dump traffic on a network * * First written in 1987 by Van Jacobson, Lawrence Berkeley Laboratory. * Mercilessly hacked and occasionally improved since then via the * combined efforts of Van, Steve McCanne and Craig Leres of LBL. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* * Mac OS X may ship pcap.h from libpcap 0.6 with a libpcap based on * 0.8. That means it has pcap_findalldevs() but the header doesn't * define pcap_if_t, meaning that we can't actually *use* pcap_findalldevs(). */ #ifdef HAVE_PCAP_FINDALLDEVS #ifndef HAVE_PCAP_IF_T #undef HAVE_PCAP_FINDALLDEVS #endif #endif #include #include #ifdef HAVE_FCNTL_H #include #endif #ifdef HAVE_LIBCRYPTO #include #endif #ifdef HAVE_GETOPT_LONG #include #else #include "getopt_long.h" #endif /* Capsicum-specific code requires macros from , which will fail * to compile if has already been included; including the headers * in the opposite order works fine. */ #ifdef HAVE_CAPSICUM #include #include #include #include #include #include -#ifdef WITH_CASPER +#ifdef HAVE_CASPER #include #include -#endif /* WITH_CASPER */ +#endif /* HAVE_CASPER */ #endif /* HAVE_CAPSICUM */ #include #include #include #include #include #include #include #ifndef _WIN32 #include #include #include #include #endif /* _WIN32 */ /* capabilities convenience library */ /* If a code depends on HAVE_LIBCAP_NG, it depends also on HAVE_CAP_NG_H. * If HAVE_CAP_NG_H is not defined, undefine HAVE_LIBCAP_NG. * Thus, the later tests are done only on HAVE_LIBCAP_NG. */ #ifdef HAVE_LIBCAP_NG #ifdef HAVE_CAP_NG_H #include #else #undef HAVE_LIBCAP_NG #endif /* HAVE_CAP_NG_H */ #endif /* HAVE_LIBCAP_NG */ #include "netdissect.h" #include "interface.h" #include "addrtoname.h" #include "machdep.h" #include "setsignal.h" #include "gmt2local.h" #include "pcap-missing.h" #include "ascii_strcasecmp.h" #include "print.h" #ifndef PATH_MAX #define PATH_MAX 1024 #endif #ifdef SIGINFO #define SIGNAL_REQ_INFO SIGINFO #elif SIGUSR1 #define SIGNAL_REQ_INFO SIGUSR1 #endif static int Bflag; /* buffer size */ static int Cflag; /* rotate dump files after this many bytes */ static int Cflag_count; /* Keep track of which file number we're writing */ static int Dflag; /* list available devices and exit */ /* * This is exported because, in some versions of libpcap, if libpcap * is built with optimizer debugging code (which is *NOT* the default * configuration!), the library *imports*(!) a variable named dflag, * under the expectation that tcpdump is exporting it, to govern * how much debugging information to print when optimizing * the generated BPF code. * * This is a horrible hack; newer versions of libpcap don't import * dflag but, instead, *if* built with optimizer debugging code, * *export* a routine to set that flag. */ int dflag; /* print filter code */ static int Gflag; /* rotate dump files after this many seconds */ static int Gflag_count; /* number of files created with Gflag rotation */ static time_t Gflag_time; /* The last time_t the dump file was rotated. */ static int Lflag; /* list available data link types and exit */ static int Iflag; /* rfmon (monitor) mode */ #ifdef HAVE_PCAP_SET_TSTAMP_TYPE static int Jflag; /* list available time stamp types */ #endif static int jflag = -1; /* packet time stamp source */ static int pflag; /* don't go promiscuous */ #ifdef HAVE_PCAP_SETDIRECTION static int Qflag = -1; /* restrict captured packet by send/receive direction */ #endif static int Uflag; /* "unbuffered" output of dump files */ static int Wflag; /* recycle output files after this number of files */ static int WflagChars; static char *zflag = NULL; /* compress each savefile using a specified command (like gzip or bzip2) */ static int immediate_mode; static int infodelay; static int infoprint; char *program_name; -#ifdef WITH_CASPER +#ifdef HAVE_CASPER cap_channel_t *capdns; #endif /* Forwards */ static void error(const char *, ...) __attribute__((noreturn)) #ifdef __ATTRIBUTE___FORMAT_OK __attribute__((format (printf, 1, 2))) #endif /* __ATTRIBUTE___FORMAT_OK */ ; static void warning(const char *, ...) #ifdef __ATTRIBUTE___FORMAT_OK __attribute__((format (printf, 1, 2))) #endif /* __ATTRIBUTE___FORMAT_OK */ ; static void exit_tcpdump(int) __attribute__((noreturn)); static RETSIGTYPE cleanup(int); static RETSIGTYPE child_cleanup(int); static void print_version(void); static void print_usage(void); static void show_tstamp_types_and_exit(pcap_t *, const char *device) __attribute__((noreturn)); static void show_dlts_and_exit(pcap_t *, const char *device) __attribute__((noreturn)); #ifdef HAVE_PCAP_FINDALLDEVS static void show_devices_and_exit (void) __attribute__((noreturn)); #endif static void print_packet(u_char *, const struct pcap_pkthdr *, const u_char *); static void dump_packet_and_trunc(u_char *, const struct pcap_pkthdr *, const u_char *); static void dump_packet(u_char *, const struct pcap_pkthdr *, const u_char *); static void droproot(const char *, const char *); #ifdef SIGNAL_REQ_INFO RETSIGTYPE requestinfo(int); #endif #if defined(USE_WIN32_MM_TIMER) #include static UINT timer_id; static void CALLBACK verbose_stats_dump(UINT, UINT, DWORD_PTR, DWORD_PTR, DWORD_PTR); #elif defined(HAVE_ALARM) static void verbose_stats_dump(int sig); #endif static void info(int); static u_int packets_captured; #ifdef HAVE_PCAP_FINDALLDEVS static const struct tok status_flags[] = { #ifdef PCAP_IF_UP { PCAP_IF_UP, "Up" }, #endif #ifdef PCAP_IF_RUNNING { PCAP_IF_RUNNING, "Running" }, #endif { PCAP_IF_LOOPBACK, "Loopback" }, { 0, NULL } }; #endif static pcap_t *pd; static int supports_monitor_mode; extern int optind; extern int opterr; extern char *optarg; struct dump_info { char *WFileName; char *CurrentFileName; pcap_t *pd; pcap_dumper_t *p; #ifdef HAVE_CAPSICUM int dirfd; #endif }; #if defined(HAVE_PCAP_SET_PARSER_DEBUG) /* * We have pcap_set_parser_debug() in libpcap; declare it (it's not declared * by any libpcap header, because it's a special hack, only available if * libpcap was configured to include it, and only intended for use by * libpcap developers trying to debug the parser for filter expressions). */ #ifdef _WIN32 __declspec(dllimport) #else /* _WIN32 */ extern #endif /* _WIN32 */ void pcap_set_parser_debug(int); #elif defined(HAVE_PCAP_DEBUG) || defined(HAVE_YYDEBUG) /* * We don't have pcap_set_parser_debug() in libpcap, but we do have * pcap_debug or yydebug. Make a local version of pcap_set_parser_debug() * to set the flag, and define HAVE_PCAP_SET_PARSER_DEBUG. */ static void pcap_set_parser_debug(int value) { #ifdef HAVE_PCAP_DEBUG extern int pcap_debug; pcap_debug = value; #else /* HAVE_PCAP_DEBUG */ extern int yydebug; yydebug = value; #endif /* HAVE_PCAP_DEBUG */ } #define HAVE_PCAP_SET_PARSER_DEBUG #endif #if defined(HAVE_PCAP_SET_OPTIMIZER_DEBUG) /* * We have pcap_set_optimizer_debug() in libpcap; declare it (it's not declared * by any libpcap header, because it's a special hack, only available if * libpcap was configured to include it, and only intended for use by * libpcap developers trying to debug the optimizer for filter expressions). */ #ifdef _WIN32 __declspec(dllimport) #else /* _WIN32 */ extern #endif /* _WIN32 */ void pcap_set_optimizer_debug(int); #endif /* VARARGS */ static void error(const char *fmt, ...) { va_list ap; (void)fprintf(stderr, "%s: ", program_name); va_start(ap, fmt); (void)vfprintf(stderr, fmt, ap); va_end(ap); if (*fmt) { fmt += strlen(fmt); if (fmt[-1] != '\n') (void)fputc('\n', stderr); } exit_tcpdump(1); /* NOTREACHED */ } /* VARARGS */ static void warning(const char *fmt, ...) { va_list ap; (void)fprintf(stderr, "%s: WARNING: ", program_name); va_start(ap, fmt); (void)vfprintf(stderr, fmt, ap); va_end(ap); if (*fmt) { fmt += strlen(fmt); if (fmt[-1] != '\n') (void)fputc('\n', stderr); } } static void exit_tcpdump(int status) { nd_cleanup(); exit(status); } #ifdef HAVE_PCAP_SET_TSTAMP_TYPE static void show_tstamp_types_and_exit(pcap_t *pc, const char *device) { int n_tstamp_types; int *tstamp_types = 0; const char *tstamp_type_name; int i; n_tstamp_types = pcap_list_tstamp_types(pc, &tstamp_types); if (n_tstamp_types < 0) error("%s", pcap_geterr(pc)); if (n_tstamp_types == 0) { fprintf(stderr, "Time stamp type cannot be set for %s\n", device); exit_tcpdump(0); } fprintf(stderr, "Time stamp types for %s (use option -j to set):\n", device); for (i = 0; i < n_tstamp_types; i++) { tstamp_type_name = pcap_tstamp_type_val_to_name(tstamp_types[i]); if (tstamp_type_name != NULL) { (void) fprintf(stderr, " %s (%s)\n", tstamp_type_name, pcap_tstamp_type_val_to_description(tstamp_types[i])); } else { (void) fprintf(stderr, " %d\n", tstamp_types[i]); } } pcap_free_tstamp_types(tstamp_types); exit_tcpdump(0); } #endif static void show_dlts_and_exit(pcap_t *pc, const char *device) { int n_dlts, i; int *dlts = 0; const char *dlt_name; n_dlts = pcap_list_datalinks(pc, &dlts); if (n_dlts < 0) error("%s", pcap_geterr(pc)); else if (n_dlts == 0 || !dlts) error("No data link types."); /* * If the interface is known to support monitor mode, indicate * whether these are the data link types available when not in * monitor mode, if -I wasn't specified, or when in monitor mode, * when -I was specified (the link-layer types available in * monitor mode might be different from the ones available when * not in monitor mode). */ if (supports_monitor_mode) (void) fprintf(stderr, "Data link types for %s %s (use option -y to set):\n", device, Iflag ? "when in monitor mode" : "when not in monitor mode"); else (void) fprintf(stderr, "Data link types for %s (use option -y to set):\n", device); for (i = 0; i < n_dlts; i++) { dlt_name = pcap_datalink_val_to_name(dlts[i]); if (dlt_name != NULL) { (void) fprintf(stderr, " %s (%s)", dlt_name, pcap_datalink_val_to_description(dlts[i])); /* * OK, does tcpdump handle that type? */ if (!has_printer(dlts[i])) (void) fprintf(stderr, " (printing not supported)"); fprintf(stderr, "\n"); } else { (void) fprintf(stderr, " DLT %d (printing not supported)\n", dlts[i]); } } #ifdef HAVE_PCAP_FREE_DATALINKS pcap_free_datalinks(dlts); #endif exit_tcpdump(0); } #ifdef HAVE_PCAP_FINDALLDEVS static void show_devices_and_exit (void) { pcap_if_t *dev, *devlist; char ebuf[PCAP_ERRBUF_SIZE]; int i; if (pcap_findalldevs(&devlist, ebuf) < 0) error("%s", ebuf); for (i = 0, dev = devlist; dev != NULL; i++, dev = dev->next) { printf("%d.%s", i+1, dev->name); if (dev->description != NULL) printf(" (%s)", dev->description); if (dev->flags != 0) printf(" [%s]", bittok2str(status_flags, "none", dev->flags)); printf("\n"); } pcap_freealldevs(devlist); exit_tcpdump(0); } #endif /* HAVE_PCAP_FINDALLDEVS */ /* * Short options. * * Note that there we use all letters for short options except for g, k, * o, and P, and those are used by other versions of tcpdump, and we should * only use them for the same purposes that the other versions of tcpdump * use them: * * OS X tcpdump uses -g to force non--v output for IP to be on one * line, making it more "g"repable; * * OS X tcpdump uses -k to specify that packet comments in pcap-ng files * should be printed; * * OpenBSD tcpdump uses -o to indicate that OS fingerprinting should be done * for hosts sending TCP SYN packets; * * OS X tcpdump uses -P to indicate that -w should write pcap-ng rather * than pcap files. * * OS X tcpdump also uses -Q to specify expressions that match packet * metadata, including but not limited to the packet direction. * The expression syntax is different from a simple "in|out|inout", * and those expressions aren't accepted by OS X tcpdump, but the * equivalents would be "in" = "dir=in", "out" = "dir=out", and * "inout" = "dir=in or dir=out", and the parser could conceivably * special-case "in", "out", and "inout" as expressions for backwards * compatibility, so all is not (yet) lost. */ /* * Set up flags that might or might not be supported depending on the * version of libpcap we're using. */ #if defined(HAVE_PCAP_CREATE) || defined(_WIN32) #define B_FLAG "B:" #define B_FLAG_USAGE " [ -B size ]" #else /* defined(HAVE_PCAP_CREATE) || defined(_WIN32) */ #define B_FLAG #define B_FLAG_USAGE #endif /* defined(HAVE_PCAP_CREATE) || defined(_WIN32) */ #ifdef HAVE_PCAP_CREATE #define I_FLAG "I" #else /* HAVE_PCAP_CREATE */ #define I_FLAG #endif /* HAVE_PCAP_CREATE */ #ifdef HAVE_PCAP_SET_TSTAMP_TYPE #define j_FLAG "j:" #define j_FLAG_USAGE " [ -j tstamptype ]" #define J_FLAG "J" #else /* PCAP_ERROR_TSTAMP_TYPE_NOTSUP */ #define j_FLAG #define j_FLAG_USAGE #define J_FLAG #endif /* PCAP_ERROR_TSTAMP_TYPE_NOTSUP */ #ifdef HAVE_PCAP_FINDALLDEVS #define D_FLAG "D" #else #define D_FLAG #endif #ifdef HAVE_PCAP_DUMP_FLUSH #define U_FLAG "U" #else #define U_FLAG #endif #ifdef HAVE_PCAP_SETDIRECTION #define Q_FLAG "Q:" #else #define Q_FLAG #endif #define SHORTOPTS "aAb" B_FLAG "c:C:d" D_FLAG "eE:fF:G:hHi:" I_FLAG j_FLAG J_FLAG "KlLm:M:nNOpq" Q_FLAG "r:s:StT:u" U_FLAG "vV:w:W:xXy:Yz:Z:#" /* * Long options. * * We do not currently have long options corresponding to all short * options; we should probably pick appropriate option names for them. * * However, the short options where the number of times the option is * specified matters, such as -v and -d and -t, should probably not * just map to a long option, as saying * * tcpdump --verbose --verbose * * doesn't make sense; it should be --verbosity={N} or something such * as that. * * For long options with no corresponding short options, we define values * outside the range of ASCII graphic characters, make that the last * component of the entry for the long option, and have a case for that * option in the switch statement. */ #define OPTION_VERSION 128 #define OPTION_TSTAMP_PRECISION 129 #define OPTION_IMMEDIATE_MODE 130 static const struct option longopts[] = { #if defined(HAVE_PCAP_CREATE) || defined(_WIN32) { "buffer-size", required_argument, NULL, 'B' }, #endif { "list-interfaces", no_argument, NULL, 'D' }, { "help", no_argument, NULL, 'h' }, { "interface", required_argument, NULL, 'i' }, #ifdef HAVE_PCAP_CREATE { "monitor-mode", no_argument, NULL, 'I' }, #endif #ifdef HAVE_PCAP_SET_TSTAMP_TYPE { "time-stamp-type", required_argument, NULL, 'j' }, { "list-time-stamp-types", no_argument, NULL, 'J' }, #endif #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION { "time-stamp-precision", required_argument, NULL, OPTION_TSTAMP_PRECISION}, #endif { "dont-verify-checksums", no_argument, NULL, 'K' }, { "list-data-link-types", no_argument, NULL, 'L' }, { "no-optimize", no_argument, NULL, 'O' }, { "no-promiscuous-mode", no_argument, NULL, 'p' }, #ifdef HAVE_PCAP_SETDIRECTION { "direction", required_argument, NULL, 'Q' }, #endif { "snapshot-length", required_argument, NULL, 's' }, { "absolute-tcp-sequence-numbers", no_argument, NULL, 'S' }, #ifdef HAVE_PCAP_DUMP_FLUSH { "packet-buffered", no_argument, NULL, 'U' }, #endif { "linktype", required_argument, NULL, 'y' }, #ifdef HAVE_PCAP_SET_IMMEDIATE_MODE { "immediate-mode", no_argument, NULL, OPTION_IMMEDIATE_MODE }, #endif #ifdef HAVE_PCAP_SET_PARSER_DEBUG { "debug-filter-parser", no_argument, NULL, 'Y' }, #endif { "relinquish-privileges", required_argument, NULL, 'Z' }, { "number", no_argument, NULL, '#' }, { "version", no_argument, NULL, OPTION_VERSION }, { NULL, 0, NULL, 0 } }; #ifndef _WIN32 /* Drop root privileges and chroot if necessary */ static void droproot(const char *username, const char *chroot_dir) { struct passwd *pw = NULL; if (chroot_dir && !username) { fprintf(stderr, "%s: Chroot without dropping root is insecure\n", program_name); exit_tcpdump(1); } pw = getpwnam(username); if (pw) { if (chroot_dir) { if (chroot(chroot_dir) != 0 || chdir ("/") != 0) { fprintf(stderr, "%s: Couldn't chroot/chdir to '%.64s': %s\n", program_name, chroot_dir, pcap_strerror(errno)); exit_tcpdump(1); } } #ifdef HAVE_LIBCAP_NG { int ret = capng_change_id(pw->pw_uid, pw->pw_gid, CAPNG_NO_FLAG); if (ret < 0) { fprintf(stderr, "error : ret %d\n", ret); } else { fprintf(stderr, "dropped privs to %s\n", username); } } #else if (initgroups(pw->pw_name, pw->pw_gid) != 0 || setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) { fprintf(stderr, "%s: Couldn't change to '%.32s' uid=%lu gid=%lu: %s\n", program_name, username, (unsigned long)pw->pw_uid, (unsigned long)pw->pw_gid, pcap_strerror(errno)); exit_tcpdump(1); } else { fprintf(stderr, "dropped privs to %s\n", username); } #endif /* HAVE_LIBCAP_NG */ } else { fprintf(stderr, "%s: Couldn't find user '%.32s'\n", program_name, username); exit_tcpdump(1); } #ifdef HAVE_LIBCAP_NG /* We don't need CAP_SETUID, CAP_SETGID and CAP_SYS_CHROOT any more. */ capng_updatev( CAPNG_DROP, CAPNG_EFFECTIVE | CAPNG_PERMITTED, CAP_SETUID, CAP_SETGID, CAP_SYS_CHROOT, -1); capng_apply(CAPNG_SELECT_BOTH); #endif /* HAVE_LIBCAP_NG */ } #endif /* _WIN32 */ static int getWflagChars(int x) { int c = 0; x -= 1; while (x > 0) { c += 1; x /= 10; } return c; } static void MakeFilename(char *buffer, char *orig_name, int cnt, int max_chars) { char *filename = malloc(PATH_MAX + 1); if (filename == NULL) error("Makefilename: malloc"); /* Process with strftime if Gflag is set. */ if (Gflag != 0) { struct tm *local_tm; /* Convert Gflag_time to a usable format */ if ((local_tm = localtime(&Gflag_time)) == NULL) { error("MakeTimedFilename: localtime"); } /* There's no good way to detect an error in strftime since a return * value of 0 isn't necessarily failure. */ strftime(filename, PATH_MAX, orig_name, local_tm); } else { strncpy(filename, orig_name, PATH_MAX); } if (cnt == 0 && max_chars == 0) strncpy(buffer, filename, PATH_MAX + 1); else if (snprintf(buffer, PATH_MAX + 1, "%s%0*d", filename, max_chars, cnt) > PATH_MAX) /* Report an error if the filename is too large */ error("too many output files or filename is too long (> %d)", PATH_MAX); free(filename); } static char * get_next_file(FILE *VFile, char *ptr) { char *ret; ret = fgets(ptr, PATH_MAX, VFile); if (!ret) return NULL; if (ptr[strlen(ptr) - 1] == '\n') ptr[strlen(ptr) - 1] = '\0'; return ret; } -#ifdef WITH_CASPER +#ifdef HAVE_CASPER static cap_channel_t * capdns_setup(void) { cap_channel_t *capcas, *capdnsloc; const char *types[1]; int families[2]; capcas = cap_init(); if (capcas == NULL) error("unable to create casper process"); capdnsloc = cap_service_open(capcas, "system.dns"); /* Casper capability no longer needed. */ cap_close(capcas); if (capdnsloc == NULL) error("unable to open system.dns service"); /* Limit system.dns to reverse DNS lookups. */ types[0] = "ADDR"; if (cap_dns_type_limit(capdnsloc, types, 1) < 0) error("unable to limit access to system.dns service"); families[0] = AF_INET; families[1] = AF_INET6; if (cap_dns_family_limit(capdnsloc, families, 2) < 0) error("unable to limit access to system.dns service"); return (capdnsloc); } -#endif /* WITH_CASPER */ +#endif /* HAVE_CASPER */ #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION static int tstamp_precision_from_string(const char *precision) { if (strncmp(precision, "nano", strlen("nano")) == 0) return PCAP_TSTAMP_PRECISION_NANO; if (strncmp(precision, "micro", strlen("micro")) == 0) return PCAP_TSTAMP_PRECISION_MICRO; return -EINVAL; } static const char * tstamp_precision_to_string(int precision) { switch (precision) { case PCAP_TSTAMP_PRECISION_MICRO: return "micro"; case PCAP_TSTAMP_PRECISION_NANO: return "nano"; default: return "unknown"; } } #endif #ifdef HAVE_CAPSICUM /* * Ensure that, on a dump file's descriptor, we have all the rights * necessary to make the standard I/O library work with an fdopen()ed * FILE * from that descriptor. * * A long time ago, in a galaxy far far away, AT&T decided that, instead * of providing separate APIs for getting and setting the FD_ flags on a * descriptor, getting and setting the O_ flags on a descriptor, and * locking files, they'd throw them all into a kitchen-sink fcntl() call * along the lines of ioctl(), the fact that ioctl() operations are * largely specific to particular character devices but fcntl() operations * are either generic to all descriptors or generic to all descriptors for * regular files nonwithstanding. * * The Capsicum people decided that fine-grained control of descriptor * operations was required, so that you need to grant permission for * reading, writing, seeking, and fcntl-ing. The latter, courtesy of * AT&T's decision, means that "fcntl-ing" isn't a thing, but a motley * collection of things, so there are *individual* fcntls for which * permission needs to be granted. * * The FreeBSD standard I/O people implemented some optimizations that * requires that the standard I/O routines be able to determine whether * the descriptor for the FILE * is open append-only or not; as that * descriptor could have come from an open() rather than an fopen(), * that requires that it be able to do an F_GETFL fcntl() to read * the O_ flags. * * Tcpdump uses ftell() to determine how much data has been written * to a file in order to, when used with -C, determine when it's time * to rotate capture files. ftell() therefore needs to do an lseek() * to find out the file offset and must, thanks to the aforementioned * optimization, also know whether the descriptor is open append-only * or not. * * The net result of all the above is that we need to grant CAP_SEEK, * CAP_WRITE, and CAP_FCNTL with the CAP_FCNTL_GETFL subcapability. * * Perhaps this is the universe's way of saying that either * * 1) there needs to be an fopenat() call and a pcap_dump_openat() call * using it, so that Capsicum-capable tcpdump wouldn't need to do * an fdopen() * * or * * 2) there needs to be a cap_fdopen() call in the FreeBSD standard * I/O library that knows what rights are needed by the standard * I/O library, based on the open mode, and assigns them, perhaps * with an additional argument indicating, for example, whether * seeking should be allowed, so that tcpdump doesn't need to know * what the standard I/O library happens to require this week. */ static void set_dumper_capsicum_rights(pcap_dumper_t *p) { int fd = fileno(pcap_dump_file(p)); cap_rights_t rights; cap_rights_init(&rights, CAP_SEEK, CAP_WRITE, CAP_FCNTL); if (cap_rights_limit(fd, &rights) < 0 && errno != ENOSYS) { error("unable to limit dump descriptor"); } if (cap_fcntls_limit(fd, CAP_FCNTL_GETFL) < 0 && errno != ENOSYS) { error("unable to limit dump descriptor fcntls"); } } #endif /* * Copy arg vector into a new buffer, concatenating arguments with spaces. */ static char * copy_argv(register char **argv) { register char **p; register u_int len = 0; char *buf; char *src, *dst; p = argv; if (*p == NULL) return 0; while (*p) len += strlen(*p++) + 1; buf = (char *)malloc(len); if (buf == NULL) error("copy_argv: malloc"); p = argv; dst = buf; while ((src = *p++) != NULL) { while ((*dst++ = *src++) != '\0') ; dst[-1] = ' '; } dst[-1] = '\0'; return buf; } /* * On Windows, we need to open the file in binary mode, so that * we get all the bytes specified by the size we get from "fstat()". * On UNIX, that's not necessary. O_BINARY is defined on Windows; * we define it as 0 if it's not defined, so it does nothing. */ #ifndef O_BINARY #define O_BINARY 0 #endif static char * read_infile(char *fname) { register int i, fd, cc; register char *cp; struct stat buf; fd = open(fname, O_RDONLY|O_BINARY); if (fd < 0) error("can't open %s: %s", fname, pcap_strerror(errno)); if (fstat(fd, &buf) < 0) error("can't stat %s: %s", fname, pcap_strerror(errno)); cp = malloc((u_int)buf.st_size + 1); if (cp == NULL) error("malloc(%d) for %s: %s", (u_int)buf.st_size + 1, fname, pcap_strerror(errno)); cc = read(fd, cp, (u_int)buf.st_size); if (cc < 0) error("read %s: %s", fname, pcap_strerror(errno)); if (cc != buf.st_size) error("short read %s (%d != %d)", fname, cc, (int)buf.st_size); close(fd); /* replace "# comment" with spaces */ for (i = 0; i < cc; i++) { if (cp[i] == '#') while (i < cc && cp[i] != '\n') cp[i++] = ' '; } cp[cc] = '\0'; return (cp); } #ifdef HAVE_PCAP_FINDALLDEVS static long parse_interface_number(const char *device) { long devnum; char *end; devnum = strtol(device, &end, 10); if (device != end && *end == '\0') { /* * It's all-numeric, but is it a valid number? */ if (devnum <= 0) { /* * No, it's not an ordinal. */ error("Invalid adapter index"); } return (devnum); } else { /* * It's not all-numeric; return -1, so our caller * knows that. */ return (-1); } } static char * find_interface_by_number(long devnum) { pcap_if_t *dev, *devlist; long i; char ebuf[PCAP_ERRBUF_SIZE]; char *device; if (pcap_findalldevs(&devlist, ebuf) < 0) error("%s", ebuf); /* * Look for the devnum-th entry in the list of devices (1-based). */ for (i = 0, dev = devlist; i < devnum-1 && dev != NULL; i++, dev = dev->next) ; if (dev == NULL) error("Invalid adapter index"); device = strdup(dev->name); pcap_freealldevs(devlist); return (device); } #endif static pcap_t * open_interface(const char *device, netdissect_options *ndo, char *ebuf) { pcap_t *pc; #ifdef HAVE_PCAP_CREATE int status; char *cp; #endif #ifdef HAVE_PCAP_CREATE pc = pcap_create(device, ebuf); if (pc == NULL) { /* * If this failed with "No such device", that means * the interface doesn't exist; return NULL, so that * the caller can see whether the device name is * actually an interface index. */ if (strstr(ebuf, "No such device") != NULL) return (NULL); error("%s", ebuf); } #ifdef HAVE_PCAP_SET_TSTAMP_TYPE if (Jflag) show_tstamp_types_and_exit(pc, device); #endif #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION status = pcap_set_tstamp_precision(pc, ndo->ndo_tstamp_precision); if (status != 0) error("%s: Can't set %ssecond time stamp precision: %s", device, tstamp_precision_to_string(ndo->ndo_tstamp_precision), pcap_statustostr(status)); #endif #ifdef HAVE_PCAP_SET_IMMEDIATE_MODE if (immediate_mode) { status = pcap_set_immediate_mode(pc, 1); if (status != 0) error("%s: Can't set immediate mode: %s", device, pcap_statustostr(status)); } #endif /* * Is this an interface that supports monitor mode? */ if (pcap_can_set_rfmon(pc) == 1) supports_monitor_mode = 1; else supports_monitor_mode = 0; status = pcap_set_snaplen(pc, ndo->ndo_snaplen); if (status != 0) error("%s: Can't set snapshot length: %s", device, pcap_statustostr(status)); status = pcap_set_promisc(pc, !pflag); if (status != 0) error("%s: Can't set promiscuous mode: %s", device, pcap_statustostr(status)); if (Iflag) { status = pcap_set_rfmon(pc, 1); if (status != 0) error("%s: Can't set monitor mode: %s", device, pcap_statustostr(status)); } status = pcap_set_timeout(pc, 1000); if (status != 0) error("%s: pcap_set_timeout failed: %s", device, pcap_statustostr(status)); if (Bflag != 0) { status = pcap_set_buffer_size(pc, Bflag); if (status != 0) error("%s: Can't set buffer size: %s", device, pcap_statustostr(status)); } #ifdef HAVE_PCAP_SET_TSTAMP_TYPE if (jflag != -1) { status = pcap_set_tstamp_type(pc, jflag); if (status < 0) error("%s: Can't set time stamp type: %s", device, pcap_statustostr(status)); } #endif status = pcap_activate(pc); if (status < 0) { /* * pcap_activate() failed. */ cp = pcap_geterr(pc); if (status == PCAP_ERROR) error("%s", cp); else if (status == PCAP_ERROR_NO_SUCH_DEVICE) { /* * Return an error for our caller to handle. */ snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s\n(%s)", device, pcap_statustostr(status), cp); pcap_close(pc); return (NULL); } else if (status == PCAP_ERROR_PERM_DENIED && *cp != '\0') error("%s: %s\n(%s)", device, pcap_statustostr(status), cp); #ifdef __FreeBSD__ else if (status == PCAP_ERROR_RFMON_NOTSUP && strncmp(device, "wlan", 4) == 0) { char parent[8], newdev[8]; char sysctl[32]; size_t s = sizeof(parent); snprintf(sysctl, sizeof(sysctl), "net.wlan.%d.%%parent", atoi(device + 4)); sysctlbyname(sysctl, parent, &s, NULL, 0); strlcpy(newdev, device, sizeof(newdev)); /* Suggest a new wlan device. */ newdev[strlen(newdev)-1]++; error("%s is not a monitor mode VAP\n" "To create a new monitor mode VAP use:\n" " ifconfig %s create wlandev %s wlanmode monitor\n" "and use %s as the tcpdump interface", device, newdev, parent, newdev); } #endif else error("%s: %s", device, pcap_statustostr(status)); } else if (status > 0) { /* * pcap_activate() succeeded, but it's warning us * of a problem it had. */ cp = pcap_geterr(pc); if (status == PCAP_WARNING) warning("%s", cp); else if (status == PCAP_WARNING_PROMISC_NOTSUP && *cp != '\0') warning("%s: %s\n(%s)", device, pcap_statustostr(status), cp); else warning("%s: %s", device, pcap_statustostr(status)); } #ifdef HAVE_PCAP_SETDIRECTION if (Qflag != -1) { status = pcap_setdirection(pc, Qflag); if (status != 0) error("%s: pcap_setdirection() failed: %s", device, pcap_geterr(pc)); } #endif /* HAVE_PCAP_SETDIRECTION */ #else /* HAVE_PCAP_CREATE */ *ebuf = '\0'; pc = pcap_open_live(device, ndo->ndo_snaplen, !pflag, 1000, ebuf); if (pc == NULL) { /* * If this failed with "No such device", that means * the interface doesn't exist; return NULL, so that * the caller can see whether the device name is * actually an interface index. */ if (strstr(ebuf, "No such device") != NULL) return (NULL); error("%s", ebuf); } if (*ebuf) warning("%s", ebuf); #endif /* HAVE_PCAP_CREATE */ return (pc); } int main(int argc, char **argv) { register int cnt, op, i; bpf_u_int32 localnet =0 , netmask = 0; int timezone_offset = 0; register char *cp, *infile, *cmdbuf, *device, *RFileName, *VFileName, *WFileName; pcap_handler callback; int dlt; const char *dlt_name; struct bpf_program fcode; #ifndef _WIN32 RETSIGTYPE (*oldhandler)(int); #endif struct dump_info dumpinfo; u_char *pcap_userdata; char ebuf[PCAP_ERRBUF_SIZE]; char VFileLine[PATH_MAX + 1]; char *username = NULL; char *chroot_dir = NULL; char *ret = NULL; char *end; #ifdef HAVE_PCAP_FINDALLDEVS pcap_if_t *devlist; long devnum; #endif int status; FILE *VFile; #ifdef HAVE_CAPSICUM cap_rights_t rights; int cansandbox; #endif /* HAVE_CAPSICUM */ int Oflag = 1; /* run filter code optimizer */ int yflag_dlt = -1; const char *yflag_dlt_name = NULL; netdissect_options Ndo; netdissect_options *ndo = &Ndo; /* * Initialize the netdissect code. */ if (nd_init(ebuf, sizeof ebuf) == -1) error("%s", ebuf); memset(ndo, 0, sizeof(*ndo)); ndo_set_function_pointers(ndo); ndo->ndo_snaplen = DEFAULT_SNAPLEN; cnt = -1; device = NULL; infile = NULL; RFileName = NULL; VFileName = NULL; VFile = NULL; WFileName = NULL; dlt = -1; if ((cp = strrchr(argv[0], '/')) != NULL) ndo->program_name = program_name = cp + 1; else ndo->program_name = program_name = argv[0]; #ifdef _WIN32 if (pcap_wsockinit() != 0) error("Attempting to initialize Winsock failed"); #endif /* _WIN32 */ /* * On platforms where the CPU doesn't support unaligned loads, * force unaligned accesses to abort with SIGBUS, rather than * being fixed up (slowly) by the OS kernel; on those platforms, * misaligned accesses are bugs, and we want tcpdump to crash so * that the bugs are reported. */ if (abort_on_misalignment(ebuf, sizeof(ebuf)) < 0) error("%s", ebuf); while ( (op = getopt_long(argc, argv, SHORTOPTS, longopts, NULL)) != -1) switch (op) { case 'a': /* compatibility for old -a */ break; case 'A': ++ndo->ndo_Aflag; break; case 'b': ++ndo->ndo_bflag; break; #if defined(HAVE_PCAP_CREATE) || defined(_WIN32) case 'B': Bflag = atoi(optarg)*1024; if (Bflag <= 0) error("invalid packet buffer size %s", optarg); break; #endif /* defined(HAVE_PCAP_CREATE) || defined(_WIN32) */ case 'c': cnt = atoi(optarg); if (cnt <= 0) error("invalid packet count %s", optarg); break; case 'C': Cflag = atoi(optarg) * 1000000; if (Cflag <= 0) error("invalid file size %s", optarg); break; case 'd': ++dflag; break; case 'D': Dflag++; break; case 'L': Lflag++; break; case 'e': ++ndo->ndo_eflag; break; case 'E': #ifndef HAVE_LIBCRYPTO warning("crypto code not compiled in"); #endif ndo->ndo_espsecret = optarg; break; case 'f': ++ndo->ndo_fflag; break; case 'F': infile = optarg; break; case 'G': Gflag = atoi(optarg); if (Gflag < 0) error("invalid number of seconds %s", optarg); /* We will create one file initially. */ Gflag_count = 0; /* Grab the current time for rotation use. */ if ((Gflag_time = time(NULL)) == (time_t)-1) { error("main: can't get current time: %s", pcap_strerror(errno)); } break; case 'h': print_usage(); exit_tcpdump(0); break; case 'H': ++ndo->ndo_Hflag; break; case 'i': device = optarg; break; #ifdef HAVE_PCAP_CREATE case 'I': ++Iflag; break; #endif /* HAVE_PCAP_CREATE */ #ifdef HAVE_PCAP_SET_TSTAMP_TYPE case 'j': jflag = pcap_tstamp_type_name_to_val(optarg); if (jflag < 0) error("invalid time stamp type %s", optarg); break; case 'J': Jflag++; break; #endif case 'l': #ifdef _WIN32 /* * _IOLBF is the same as _IOFBF in Microsoft's C * libraries; the only alternative they offer * is _IONBF. * * XXX - this should really be checking for MSVC++, * not _WIN32, if, for example, MinGW has its own * C library that is more UNIX-compatible. */ setvbuf(stdout, NULL, _IONBF, 0); #else /* _WIN32 */ #ifdef HAVE_SETLINEBUF setlinebuf(stdout); #else setvbuf(stdout, NULL, _IOLBF, 0); #endif #endif /* _WIN32 */ break; case 'K': ++ndo->ndo_Kflag; break; case 'm': if (nd_have_smi_support()) { if (nd_load_smi_module(optarg, ebuf, sizeof ebuf) == -1) error("%s", ebuf); } else { (void)fprintf(stderr, "%s: ignoring option `-m %s' ", program_name, optarg); (void)fprintf(stderr, "(no libsmi support)\n"); } break; case 'M': /* TCP-MD5 shared secret */ #ifndef HAVE_LIBCRYPTO warning("crypto code not compiled in"); #endif ndo->ndo_sigsecret = optarg; break; case 'n': ++ndo->ndo_nflag; break; case 'N': ++ndo->ndo_Nflag; break; case 'O': Oflag = 0; break; case 'p': ++pflag; break; case 'q': ++ndo->ndo_qflag; ++ndo->ndo_suppress_default_print; break; #ifdef HAVE_PCAP_SETDIRECTION case 'Q': if (ascii_strcasecmp(optarg, "in") == 0) Qflag = PCAP_D_IN; else if (ascii_strcasecmp(optarg, "out") == 0) Qflag = PCAP_D_OUT; else if (ascii_strcasecmp(optarg, "inout") == 0) Qflag = PCAP_D_INOUT; else error("unknown capture direction `%s'", optarg); break; #endif /* HAVE_PCAP_SETDIRECTION */ case 'r': RFileName = optarg; break; case 's': ndo->ndo_snaplen = strtol(optarg, &end, 0); if (optarg == end || *end != '\0' || ndo->ndo_snaplen < 0 || ndo->ndo_snaplen > MAXIMUM_SNAPLEN) error("invalid snaplen %s", optarg); else if (ndo->ndo_snaplen == 0) ndo->ndo_snaplen = MAXIMUM_SNAPLEN; break; case 'S': ++ndo->ndo_Sflag; break; case 't': ++ndo->ndo_tflag; break; case 'T': if (ascii_strcasecmp(optarg, "vat") == 0) ndo->ndo_packettype = PT_VAT; else if (ascii_strcasecmp(optarg, "wb") == 0) ndo->ndo_packettype = PT_WB; else if (ascii_strcasecmp(optarg, "rpc") == 0) ndo->ndo_packettype = PT_RPC; else if (ascii_strcasecmp(optarg, "rtp") == 0) ndo->ndo_packettype = PT_RTP; else if (ascii_strcasecmp(optarg, "rtcp") == 0) ndo->ndo_packettype = PT_RTCP; else if (ascii_strcasecmp(optarg, "snmp") == 0) ndo->ndo_packettype = PT_SNMP; else if (ascii_strcasecmp(optarg, "cnfp") == 0) ndo->ndo_packettype = PT_CNFP; else if (ascii_strcasecmp(optarg, "tftp") == 0) ndo->ndo_packettype = PT_TFTP; else if (ascii_strcasecmp(optarg, "aodv") == 0) ndo->ndo_packettype = PT_AODV; else if (ascii_strcasecmp(optarg, "carp") == 0) ndo->ndo_packettype = PT_CARP; else if (ascii_strcasecmp(optarg, "radius") == 0) ndo->ndo_packettype = PT_RADIUS; else if (ascii_strcasecmp(optarg, "zmtp1") == 0) ndo->ndo_packettype = PT_ZMTP1; else if (ascii_strcasecmp(optarg, "vxlan") == 0) ndo->ndo_packettype = PT_VXLAN; else if (ascii_strcasecmp(optarg, "pgm") == 0) ndo->ndo_packettype = PT_PGM; else if (ascii_strcasecmp(optarg, "pgm_zmtp1") == 0) ndo->ndo_packettype = PT_PGM_ZMTP1; else if (ascii_strcasecmp(optarg, "lmp") == 0) ndo->ndo_packettype = PT_LMP; else if (ascii_strcasecmp(optarg, "resp") == 0) ndo->ndo_packettype = PT_RESP; else error("unknown packet type `%s'", optarg); break; case 'u': ++ndo->ndo_uflag; break; #ifdef HAVE_PCAP_DUMP_FLUSH case 'U': ++Uflag; break; #endif case 'v': ++ndo->ndo_vflag; break; case 'V': VFileName = optarg; break; case 'w': WFileName = optarg; break; case 'W': Wflag = atoi(optarg); if (Wflag <= 0) error("invalid number of output files %s", optarg); WflagChars = getWflagChars(Wflag); break; case 'x': ++ndo->ndo_xflag; ++ndo->ndo_suppress_default_print; break; case 'X': ++ndo->ndo_Xflag; ++ndo->ndo_suppress_default_print; break; case 'y': yflag_dlt_name = optarg; yflag_dlt = pcap_datalink_name_to_val(yflag_dlt_name); if (yflag_dlt < 0) error("invalid data link type %s", yflag_dlt_name); break; #ifdef HAVE_PCAP_SET_PARSER_DEBUG case 'Y': { /* Undocumented flag */ pcap_set_parser_debug(1); } break; #endif case 'z': zflag = optarg; break; case 'Z': username = optarg; break; case '#': ndo->ndo_packet_number = 1; break; case OPTION_VERSION: print_version(); exit_tcpdump(0); break; #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION case OPTION_TSTAMP_PRECISION: ndo->ndo_tstamp_precision = tstamp_precision_from_string(optarg); if (ndo->ndo_tstamp_precision < 0) error("unsupported time stamp precision"); break; #endif #ifdef HAVE_PCAP_SET_IMMEDIATE_MODE case OPTION_IMMEDIATE_MODE: immediate_mode = 1; break; #endif default: print_usage(); exit_tcpdump(1); /* NOTREACHED */ } #ifdef HAVE_PCAP_FINDALLDEVS if (Dflag) show_devices_and_exit(); #endif switch (ndo->ndo_tflag) { case 0: /* Default */ case 4: /* Default + Date*/ timezone_offset = gmt2local(0); break; case 1: /* No time stamp */ case 2: /* Unix timeval style */ case 3: /* Microseconds since previous packet */ case 5: /* Microseconds since first packet */ break; default: /* Not supported */ error("only -t, -tt, -ttt, -tttt and -ttttt are supported"); break; } if (ndo->ndo_fflag != 0 && (VFileName != NULL || RFileName != NULL)) error("-f can not be used with -V or -r"); if (VFileName != NULL && RFileName != NULL) error("-V and -r are mutually exclusive."); #ifdef HAVE_PCAP_SET_IMMEDIATE_MODE /* * If we're printing dissected packets to the standard output * rather than saving raw packets to a file, and the standard * output is a terminal, use immediate mode, as the user's * probably expecting to see packets pop up immediately. */ if (WFileName == NULL && isatty(1)) immediate_mode = 1; #endif #ifdef WITH_CHROOT /* if run as root, prepare for chrooting */ if (getuid() == 0 || geteuid() == 0) { /* future extensibility for cmd-line arguments */ if (!chroot_dir) chroot_dir = WITH_CHROOT; } #endif #ifdef WITH_USER /* if run as root, prepare for dropping root privileges */ if (getuid() == 0 || geteuid() == 0) { /* Run with '-Z root' to restore old behaviour */ if (!username) username = WITH_USER; } #endif if (RFileName != NULL || VFileName != NULL) { /* * If RFileName is non-null, it's the pathname of a * savefile to read. If VFileName is non-null, it's * the pathname of a file containing a list of pathnames * (one per line) of savefiles to read. * * In either case, we're reading a savefile, not doing * a live capture. */ #ifndef _WIN32 /* * We don't need network access, so relinquish any set-UID * or set-GID privileges we have (if any). * * We do *not* want set-UID privileges when opening a * trace file, as that might let the user read other * people's trace files (especially if we're set-UID * root). */ if (setgid(getgid()) != 0 || setuid(getuid()) != 0 ) fprintf(stderr, "Warning: setgid/setuid failed !\n"); #endif /* _WIN32 */ if (VFileName != NULL) { if (VFileName[0] == '-' && VFileName[1] == '\0') VFile = stdin; else VFile = fopen(VFileName, "r"); if (VFile == NULL) error("Unable to open file: %s\n", pcap_strerror(errno)); ret = get_next_file(VFile, VFileLine); if (!ret) error("Nothing in %s\n", VFileName); RFileName = VFileLine; } #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION pd = pcap_open_offline_with_tstamp_precision(RFileName, ndo->ndo_tstamp_precision, ebuf); #else pd = pcap_open_offline(RFileName, ebuf); #endif if (pd == NULL) error("%s", ebuf); #ifdef HAVE_CAPSICUM cap_rights_init(&rights, CAP_READ); if (cap_rights_limit(fileno(pcap_file(pd)), &rights) < 0 && errno != ENOSYS) { error("unable to limit pcap descriptor"); } #endif dlt = pcap_datalink(pd); dlt_name = pcap_datalink_val_to_name(dlt); if (dlt_name == NULL) { fprintf(stderr, "reading from file %s, link-type %u\n", RFileName, dlt); } else { fprintf(stderr, "reading from file %s, link-type %s (%s)\n", RFileName, dlt_name, pcap_datalink_val_to_description(dlt)); } } else { /* * We're doing a live capture. */ if (device == NULL) { /* * No interface was specified. Pick one. */ #ifdef HAVE_PCAP_FINDALLDEVS /* * Find the list of interfaces, and pick * the first interface. */ if (pcap_findalldevs(&devlist, ebuf) >= 0 && devlist != NULL) { device = strdup(devlist->name); pcap_freealldevs(devlist); } #else /* HAVE_PCAP_FINDALLDEVS */ /* * Use whatever interface pcap_lookupdev() * chooses. */ device = pcap_lookupdev(ebuf); #endif if (device == NULL) error("%s", ebuf); } /* * Try to open the interface with the specified name. */ pd = open_interface(device, ndo, ebuf); if (pd == NULL) { /* * That failed. If we can get a list of * interfaces, and the interface name * is purely numeric, try to use it as * a 1-based index in the list of * interfaces. */ #ifdef HAVE_PCAP_FINDALLDEVS devnum = parse_interface_number(device); if (devnum == -1) { /* * It's not a number; just report * the open error and fail. */ error("%s", ebuf); } /* * OK, it's a number; try to find the * interface with that index, and try * to open it. * * find_interface_by_number() exits if it * couldn't be found. */ device = find_interface_by_number(devnum); pd = open_interface(device, ndo, ebuf); if (pd == NULL) error("%s", ebuf); #else /* HAVE_PCAP_FINDALLDEVS */ /* * We can't get a list of interfaces; just * fail. */ error("%s", ebuf); #endif /* HAVE_PCAP_FINDALLDEVS */ } /* * Let user own process after socket has been opened. */ #ifndef _WIN32 if (setgid(getgid()) != 0 || setuid(getuid()) != 0) fprintf(stderr, "Warning: setgid/setuid failed !\n"); #endif /* _WIN32 */ #if !defined(HAVE_PCAP_CREATE) && defined(_WIN32) if(Bflag != 0) if(pcap_setbuff(pd, Bflag)==-1){ error("%s", pcap_geterr(pd)); } #endif /* !defined(HAVE_PCAP_CREATE) && defined(_WIN32) */ if (Lflag) show_dlts_and_exit(pd, device); if (yflag_dlt >= 0) { #ifdef HAVE_PCAP_SET_DATALINK if (pcap_set_datalink(pd, yflag_dlt) < 0) error("%s", pcap_geterr(pd)); #else /* * We don't actually support changing the * data link type, so we only let them * set it to what it already is. */ if (yflag_dlt != pcap_datalink(pd)) { error("%s is not one of the DLTs supported by this device\n", yflag_dlt_name); } #endif (void)fprintf(stderr, "%s: data link type %s\n", program_name, yflag_dlt_name); (void)fflush(stderr); } i = pcap_snapshot(pd); if (ndo->ndo_snaplen < i) { warning("snaplen raised from %d to %d", ndo->ndo_snaplen, i); ndo->ndo_snaplen = i; } if(ndo->ndo_fflag != 0) { if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) { warning("foreign (-f) flag used but: %s", ebuf); } } } if (infile) cmdbuf = read_infile(infile); else cmdbuf = copy_argv(&argv[optind]); #ifdef HAVE_PCAP_SET_OPTIMIZER_DEBUG pcap_set_optimizer_debug(dflag); #endif if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0) error("%s", pcap_geterr(pd)); if (dflag) { bpf_dump(&fcode, dflag); pcap_close(pd); free(cmdbuf); pcap_freecode(&fcode); exit_tcpdump(0); } -#ifdef WITH_CASPER +#ifdef HAVE_CASPER if (!ndo->ndo_nflag) capdns = capdns_setup(); -#endif /* WITH_CASPER */ +#endif /* HAVE_CASPER */ init_print(ndo, localnet, netmask, timezone_offset); #ifndef _WIN32 (void)setsignal(SIGPIPE, cleanup); (void)setsignal(SIGTERM, cleanup); (void)setsignal(SIGINT, cleanup); #endif /* _WIN32 */ #if defined(HAVE_FORK) || defined(HAVE_VFORK) (void)setsignal(SIGCHLD, child_cleanup); #endif /* Cooperate with nohup(1) */ #ifndef _WIN32 if ((oldhandler = setsignal(SIGHUP, cleanup)) != SIG_DFL) (void)setsignal(SIGHUP, oldhandler); #endif /* _WIN32 */ #ifndef _WIN32 /* * If a user name was specified with "-Z", attempt to switch to * that user's UID. This would probably be used with sudo, * to allow tcpdump to be run in a special restricted * account (if you just want to allow users to open capture * devices, and can't just give users that permission, * you'd make tcpdump set-UID or set-GID). * * Tcpdump doesn't necessarily write only to one savefile; * the general only way to allow a -Z instance to write to * savefiles as the user under whose UID it's run, rather * than as the user specified with -Z, would thus be to switch * to the original user ID before opening a capture file and * then switch back to the -Z user ID after opening the savefile. * Switching to the -Z user ID only after opening the first * savefile doesn't handle the general case. */ if (getuid() == 0 || geteuid() == 0) { #ifdef HAVE_LIBCAP_NG /* Initialize capng */ capng_clear(CAPNG_SELECT_BOTH); if (username) { capng_updatev( CAPNG_ADD, CAPNG_PERMITTED | CAPNG_EFFECTIVE, CAP_SETUID, CAP_SETGID, -1); } if (chroot_dir) { capng_update( CAPNG_ADD, CAPNG_PERMITTED | CAPNG_EFFECTIVE, CAP_SYS_CHROOT ); } if (WFileName) { capng_update( CAPNG_ADD, CAPNG_PERMITTED | CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE ); } capng_apply(CAPNG_SELECT_BOTH); #endif /* HAVE_LIBCAP_NG */ if (username || chroot_dir) droproot(username, chroot_dir); } #endif /* _WIN32 */ if (pcap_setfilter(pd, &fcode) < 0) error("%s", pcap_geterr(pd)); #ifdef HAVE_CAPSICUM if (RFileName == NULL && VFileName == NULL) { static const unsigned long cmds[] = { BIOCGSTATS, BIOCROTZBUF }; /* * The various libpcap devices use a combination of * read (bpf), ioctl (bpf, netmap), poll (netmap). * Grant the relevant access rights, sorted by name. */ cap_rights_init(&rights, CAP_EVENT, CAP_IOCTL, CAP_READ); if (cap_rights_limit(pcap_fileno(pd), &rights) < 0 && errno != ENOSYS) { error("unable to limit pcap descriptor"); } if (cap_ioctls_limit(pcap_fileno(pd), cmds, sizeof(cmds) / sizeof(cmds[0])) < 0 && errno != ENOSYS) { error("unable to limit ioctls on pcap descriptor"); } } #endif if (WFileName) { pcap_dumper_t *p; /* Do not exceed the default PATH_MAX for files. */ dumpinfo.CurrentFileName = (char *)malloc(PATH_MAX + 1); if (dumpinfo.CurrentFileName == NULL) error("malloc of dumpinfo.CurrentFileName"); /* We do not need numbering for dumpfiles if Cflag isn't set. */ if (Cflag != 0) MakeFilename(dumpinfo.CurrentFileName, WFileName, 0, WflagChars); else MakeFilename(dumpinfo.CurrentFileName, WFileName, 0, 0); p = pcap_dump_open(pd, dumpinfo.CurrentFileName); #ifdef HAVE_LIBCAP_NG /* Give up CAP_DAC_OVERRIDE capability. * Only allow it to be restored if the -C or -G flag have been * set since we may need to create more files later on. */ capng_update( CAPNG_DROP, (Cflag || Gflag ? 0 : CAPNG_PERMITTED) | CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE ); capng_apply(CAPNG_SELECT_BOTH); #endif /* HAVE_LIBCAP_NG */ if (p == NULL) error("%s", pcap_geterr(pd)); #ifdef HAVE_CAPSICUM set_dumper_capsicum_rights(p); #endif if (Cflag != 0 || Gflag != 0) { #ifdef HAVE_CAPSICUM dumpinfo.WFileName = strdup(basename(WFileName)); if (dumpinfo.WFileName == NULL) { error("Unable to allocate memory for file %s", WFileName); } dumpinfo.dirfd = open(dirname(WFileName), O_DIRECTORY | O_RDONLY); if (dumpinfo.dirfd < 0) { error("unable to open directory %s", dirname(WFileName)); } cap_rights_init(&rights, CAP_CREATE, CAP_FCNTL, CAP_FTRUNCATE, CAP_LOOKUP, CAP_SEEK, CAP_WRITE); if (cap_rights_limit(dumpinfo.dirfd, &rights) < 0 && errno != ENOSYS) { error("unable to limit directory rights"); } if (cap_fcntls_limit(dumpinfo.dirfd, CAP_FCNTL_GETFL) < 0 && errno != ENOSYS) { error("unable to limit dump descriptor fcntls"); } #else /* !HAVE_CAPSICUM */ dumpinfo.WFileName = WFileName; #endif callback = dump_packet_and_trunc; dumpinfo.pd = pd; dumpinfo.p = p; pcap_userdata = (u_char *)&dumpinfo; } else { callback = dump_packet; pcap_userdata = (u_char *)p; } #ifdef HAVE_PCAP_DUMP_FLUSH if (Uflag) pcap_dump_flush(p); #endif } else { dlt = pcap_datalink(pd); ndo->ndo_if_printer = get_if_printer(ndo, dlt); callback = print_packet; pcap_userdata = (u_char *)ndo; } #ifdef SIGNAL_REQ_INFO /* * We can't get statistics when reading from a file rather * than capturing from a device. */ if (RFileName == NULL) (void)setsignal(SIGNAL_REQ_INFO, requestinfo); #endif if (ndo->ndo_vflag > 0 && WFileName) { /* * When capturing to a file, "-v" means tcpdump should, * every 10 seconds, "v"erbosely report the number of * packets captured. */ #ifdef USE_WIN32_MM_TIMER /* call verbose_stats_dump() each 1000 +/-100msec */ timer_id = timeSetEvent(1000, 100, verbose_stats_dump, 0, TIME_PERIODIC); setvbuf(stderr, NULL, _IONBF, 0); #elif defined(HAVE_ALARM) (void)setsignal(SIGALRM, verbose_stats_dump); alarm(1); #endif } if (RFileName == NULL) { /* * Live capture (if -V was specified, we set RFileName * to a file from the -V file). Print a message to * the standard error on UN*X. */ if (!ndo->ndo_vflag && !WFileName) { (void)fprintf(stderr, "%s: verbose output suppressed, use -v or -vv for full protocol decode\n", program_name); } else (void)fprintf(stderr, "%s: ", program_name); dlt = pcap_datalink(pd); dlt_name = pcap_datalink_val_to_name(dlt); if (dlt_name == NULL) { (void)fprintf(stderr, "listening on %s, link-type %u, capture size %u bytes\n", device, dlt, ndo->ndo_snaplen); } else { (void)fprintf(stderr, "listening on %s, link-type %s (%s), capture size %u bytes\n", device, dlt_name, pcap_datalink_val_to_description(dlt), ndo->ndo_snaplen); } (void)fflush(stderr); } #ifdef HAVE_CAPSICUM cansandbox = (VFileName == NULL && zflag == NULL); -#ifdef WITH_CASPER +#ifdef HAVE_CASPER cansandbox = (cansandbox && (ndo->ndo_nflag || capdns != NULL)); #else cansandbox = (cansandbox && ndo->ndo_nflag); -#endif /* WITH_CASPER */ +#endif /* HAVE_CASPER */ if (cansandbox && cap_enter() < 0 && errno != ENOSYS) error("unable to enter the capability mode"); #endif /* HAVE_CAPSICUM */ do { status = pcap_loop(pd, cnt, callback, pcap_userdata); if (WFileName == NULL) { /* * We're printing packets. Flush the printed output, * so it doesn't get intermingled with error output. */ if (status == -2) { /* * We got interrupted, so perhaps we didn't * manage to finish a line we were printing. * Print an extra newline, just in case. */ putchar('\n'); } (void)fflush(stdout); } if (status == -2) { /* * We got interrupted. If we are reading multiple * files (via -V) set these so that we stop. */ VFileName = NULL; ret = NULL; } if (status == -1) { /* * Error. Report it. */ (void)fprintf(stderr, "%s: pcap_loop: %s\n", program_name, pcap_geterr(pd)); } if (RFileName == NULL) { /* * We're doing a live capture. Report the capture * statistics. */ info(1); } pcap_close(pd); if (VFileName != NULL) { ret = get_next_file(VFile, VFileLine); if (ret) { int new_dlt; RFileName = VFileLine; pd = pcap_open_offline(RFileName, ebuf); if (pd == NULL) error("%s", ebuf); #ifdef HAVE_CAPSICUM cap_rights_init(&rights, CAP_READ); if (cap_rights_limit(fileno(pcap_file(pd)), &rights) < 0 && errno != ENOSYS) { error("unable to limit pcap descriptor"); } #endif new_dlt = pcap_datalink(pd); if (new_dlt != dlt) { /* * The new file has a different * link-layer header type from the * previous one. */ if (WFileName != NULL) { /* * We're writing raw packets * that match the filter to * a pcap file. pcap files * don't support multiple * different link-layer * header types, so we fail * here. */ error("%s: new dlt does not match original", RFileName); } /* * We're printing the decoded packets; * switch to the new DLT. * * To do that, we need to change * the printer, change the DLT name, * and recompile the filter with * the new DLT. */ dlt = new_dlt; ndo->ndo_if_printer = get_if_printer(ndo, dlt); if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0) error("%s", pcap_geterr(pd)); } /* * Set the filter on the new file. */ if (pcap_setfilter(pd, &fcode) < 0) error("%s", pcap_geterr(pd)); /* * Report the new file. */ dlt_name = pcap_datalink_val_to_name(dlt); if (dlt_name == NULL) { fprintf(stderr, "reading from file %s, link-type %u\n", RFileName, dlt); } else { fprintf(stderr, "reading from file %s, link-type %s (%s)\n", RFileName, dlt_name, pcap_datalink_val_to_description(dlt)); } } } } while (ret != NULL); free(cmdbuf); pcap_freecode(&fcode); exit_tcpdump(status == -1 ? 1 : 0); } /* make a clean exit on interrupts */ static RETSIGTYPE cleanup(int signo _U_) { #ifdef USE_WIN32_MM_TIMER if (timer_id) timeKillEvent(timer_id); timer_id = 0; #elif defined(HAVE_ALARM) alarm(0); #endif #ifdef HAVE_PCAP_BREAKLOOP /* * We have "pcap_breakloop()"; use it, so that we do as little * as possible in the signal handler (it's probably not safe * to do anything with standard I/O streams in a signal handler - * the ANSI C standard doesn't say it is). */ pcap_breakloop(pd); #else /* * We don't have "pcap_breakloop()"; this isn't safe, but * it's the best we can do. Print the summary if we're * not reading from a savefile - i.e., if we're doing a * live capture - and exit. */ if (pd != NULL && pcap_file(pd) == NULL) { /* * We got interrupted, so perhaps we didn't * manage to finish a line we were printing. * Print an extra newline, just in case. */ putchar('\n'); (void)fflush(stdout); info(1); } exit_tcpdump(0); #endif } /* On windows, we do not use a fork, so we do not care less about waiting a child processes to die */ #if defined(HAVE_FORK) || defined(HAVE_VFORK) static RETSIGTYPE child_cleanup(int signo _U_) { wait(NULL); } #endif /* HAVE_FORK && HAVE_VFORK */ static void info(register int verbose) { struct pcap_stat stats; /* * Older versions of libpcap didn't set ps_ifdrop on some * platforms; initialize it to 0 to handle that. */ stats.ps_ifdrop = 0; if (pcap_stats(pd, &stats) < 0) { (void)fprintf(stderr, "pcap_stats: %s\n", pcap_geterr(pd)); infoprint = 0; return; } if (!verbose) fprintf(stderr, "%s: ", program_name); (void)fprintf(stderr, "%u packet%s captured", packets_captured, PLURAL_SUFFIX(packets_captured)); if (!verbose) fputs(", ", stderr); else putc('\n', stderr); (void)fprintf(stderr, "%u packet%s received by filter", stats.ps_recv, PLURAL_SUFFIX(stats.ps_recv)); if (!verbose) fputs(", ", stderr); else putc('\n', stderr); (void)fprintf(stderr, "%u packet%s dropped by kernel", stats.ps_drop, PLURAL_SUFFIX(stats.ps_drop)); if (stats.ps_ifdrop != 0) { if (!verbose) fputs(", ", stderr); else putc('\n', stderr); (void)fprintf(stderr, "%u packet%s dropped by interface\n", stats.ps_ifdrop, PLURAL_SUFFIX(stats.ps_ifdrop)); } else putc('\n', stderr); infoprint = 0; } #if defined(HAVE_FORK) || defined(HAVE_VFORK) #ifdef HAVE_FORK #define fork_subprocess() fork() #else #define fork_subprocess() vfork() #endif static void compress_savefile(const char *filename) { pid_t child; child = fork_subprocess(); if (child == -1) { fprintf(stderr, "compress_savefile: fork failed: %s\n", pcap_strerror(errno)); return; } if (child != 0) { /* Parent process. */ return; } /* * Child process. * Set to lowest priority so that this doesn't disturb the capture. */ #ifdef NZERO setpriority(PRIO_PROCESS, 0, NZERO - 1); #else setpriority(PRIO_PROCESS, 0, 19); #endif if (execlp(zflag, zflag, filename, (char *)NULL) == -1) fprintf(stderr, "compress_savefile: execlp(%s, %s) failed: %s\n", zflag, filename, pcap_strerror(errno)); #ifdef HAVE_FORK exit(1); #else _exit(1); #endif } #else /* HAVE_FORK && HAVE_VFORK */ static void compress_savefile(const char *filename) { fprintf(stderr, "compress_savefile failed. Functionality not implemented under your system\n"); } #endif /* HAVE_FORK && HAVE_VFORK */ static void dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) { struct dump_info *dump_info; ++packets_captured; ++infodelay; dump_info = (struct dump_info *)user; /* * XXX - this won't force the file to rotate on the specified time * boundary, but it will rotate on the first packet received after the * specified Gflag number of seconds. Note: if a Gflag time boundary * and a Cflag size boundary coincide, the time rotation will occur * first thereby cancelling the Cflag boundary (since the file should * be 0). */ if (Gflag != 0) { /* Check if it is time to rotate */ time_t t; /* Get the current time */ if ((t = time(NULL)) == (time_t)-1) { error("dump_and_trunc_packet: can't get current_time: %s", pcap_strerror(errno)); } /* If the time is greater than the specified window, rotate */ if (t - Gflag_time >= Gflag) { #ifdef HAVE_CAPSICUM FILE *fp; int fd; #endif /* Update the Gflag_time */ Gflag_time = t; /* Update Gflag_count */ Gflag_count++; /* * Close the current file and open a new one. */ pcap_dump_close(dump_info->p); /* * Compress the file we just closed, if the user asked for it */ if (zflag != NULL) compress_savefile(dump_info->CurrentFileName); /* * Check to see if we've exceeded the Wflag (when * not using Cflag). */ if (Cflag == 0 && Wflag > 0 && Gflag_count >= Wflag) { (void)fprintf(stderr, "Maximum file limit reached: %d\n", Wflag); info(1); exit_tcpdump(0); /* NOTREACHED */ } if (dump_info->CurrentFileName != NULL) free(dump_info->CurrentFileName); /* Allocate space for max filename + \0. */ dump_info->CurrentFileName = (char *)malloc(PATH_MAX + 1); if (dump_info->CurrentFileName == NULL) error("dump_packet_and_trunc: malloc"); /* * Gflag was set otherwise we wouldn't be here. Reset the count * so multiple files would end with 1,2,3 in the filename. * The counting is handled with the -C flow after this. */ Cflag_count = 0; /* * This is always the first file in the Cflag * rotation: e.g. 0 * We also don't need numbering if Cflag is not set. */ if (Cflag != 0) MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, 0, WflagChars); else MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, 0, 0); #ifdef HAVE_LIBCAP_NG capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); capng_apply(CAPNG_SELECT_BOTH); #endif /* HAVE_LIBCAP_NG */ #ifdef HAVE_CAPSICUM fd = openat(dump_info->dirfd, dump_info->CurrentFileName, O_CREAT | O_WRONLY | O_TRUNC, 0644); if (fd < 0) { error("unable to open file %s", dump_info->CurrentFileName); } fp = fdopen(fd, "w"); if (fp == NULL) { error("unable to fdopen file %s", dump_info->CurrentFileName); } dump_info->p = pcap_dump_fopen(dump_info->pd, fp); #else /* !HAVE_CAPSICUM */ dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName); #endif #ifdef HAVE_LIBCAP_NG capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); capng_apply(CAPNG_SELECT_BOTH); #endif /* HAVE_LIBCAP_NG */ if (dump_info->p == NULL) error("%s", pcap_geterr(pd)); #ifdef HAVE_CAPSICUM set_dumper_capsicum_rights(dump_info->p); #endif } } /* * XXX - this won't prevent capture files from getting * larger than Cflag - the last packet written to the * file could put it over Cflag. */ if (Cflag != 0) { long size = pcap_dump_ftell(dump_info->p); if (size == -1) error("ftell fails on output file"); if (size > Cflag) { #ifdef HAVE_CAPSICUM FILE *fp; int fd; #endif /* * Close the current file and open a new one. */ pcap_dump_close(dump_info->p); /* * Compress the file we just closed, if the user * asked for it. */ if (zflag != NULL) compress_savefile(dump_info->CurrentFileName); Cflag_count++; if (Wflag > 0) { if (Cflag_count >= Wflag) Cflag_count = 0; } if (dump_info->CurrentFileName != NULL) free(dump_info->CurrentFileName); dump_info->CurrentFileName = (char *)malloc(PATH_MAX + 1); if (dump_info->CurrentFileName == NULL) error("dump_packet_and_trunc: malloc"); MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, Cflag_count, WflagChars); #ifdef HAVE_LIBCAP_NG capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); capng_apply(CAPNG_SELECT_BOTH); #endif /* HAVE_LIBCAP_NG */ #ifdef HAVE_CAPSICUM fd = openat(dump_info->dirfd, dump_info->CurrentFileName, O_CREAT | O_WRONLY | O_TRUNC, 0644); if (fd < 0) { error("unable to open file %s", dump_info->CurrentFileName); } fp = fdopen(fd, "w"); if (fp == NULL) { error("unable to fdopen file %s", dump_info->CurrentFileName); } dump_info->p = pcap_dump_fopen(dump_info->pd, fp); #else /* !HAVE_CAPSICUM */ dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName); #endif #ifdef HAVE_LIBCAP_NG capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); capng_apply(CAPNG_SELECT_BOTH); #endif /* HAVE_LIBCAP_NG */ if (dump_info->p == NULL) error("%s", pcap_geterr(pd)); #ifdef HAVE_CAPSICUM set_dumper_capsicum_rights(dump_info->p); #endif } } pcap_dump((u_char *)dump_info->p, h, sp); #ifdef HAVE_PCAP_DUMP_FLUSH if (Uflag) pcap_dump_flush(dump_info->p); #endif --infodelay; if (infoprint) info(0); } static void dump_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) { ++packets_captured; ++infodelay; pcap_dump(user, h, sp); #ifdef HAVE_PCAP_DUMP_FLUSH if (Uflag) pcap_dump_flush((pcap_dumper_t *)user); #endif --infodelay; if (infoprint) info(0); } static void print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) { ++packets_captured; ++infodelay; pretty_print_packet((netdissect_options *)user, h, sp, packets_captured); --infodelay; if (infoprint) info(0); } #ifdef _WIN32 /* * XXX - there should really be libpcap calls to get the version * number as a string (the string would be generated from #defines * at run time, so that it's not generated from string constants * in the library, as, on many UNIX systems, those constants would * be statically linked into the application executable image, and * would thus reflect the version of libpcap on the system on * which the application was *linked*, not the system on which it's * *running*. * * That routine should be documented, unlike the "version[]" * string, so that UNIX vendors providing their own libpcaps * don't omit it (as a couple of vendors have...). * * Packet.dll should perhaps also export a routine to return the * version number of the Packet.dll code, to supply the * "Wpcap_version" information on Windows. */ char WDversion[]="current-git.tcpdump.org"; #if !defined(HAVE_GENERATED_VERSION) char version[]="current-git.tcpdump.org"; #endif char pcap_version[]="current-git.tcpdump.org"; char Wpcap_version[]="3.1"; #endif #ifdef SIGNAL_REQ_INFO RETSIGTYPE requestinfo(int signo _U_) { if (infodelay) ++infoprint; else info(0); } #endif /* * Called once each second in verbose mode while dumping to file */ #ifdef USE_WIN32_MM_TIMER void CALLBACK verbose_stats_dump (UINT timer_id _U_, UINT msg _U_, DWORD_PTR arg _U_, DWORD_PTR dw1 _U_, DWORD_PTR dw2 _U_) { if (infodelay == 0) fprintf(stderr, "Got %u\r", packets_captured); } #elif defined(HAVE_ALARM) static void verbose_stats_dump(int sig _U_) { if (infodelay == 0) fprintf(stderr, "Got %u\r", packets_captured); alarm(1); } #endif USES_APPLE_DEPRECATED_API static void print_version(void) { extern char version[]; #ifndef HAVE_PCAP_LIB_VERSION #if defined(_WIN32) || defined(HAVE_PCAP_VERSION) extern char pcap_version[]; #else /* defined(_WIN32) || defined(HAVE_PCAP_VERSION) */ static char pcap_version[] = "unknown"; #endif /* defined(_WIN32) || defined(HAVE_PCAP_VERSION) */ #endif /* HAVE_PCAP_LIB_VERSION */ const char *smi_version_string; #ifdef HAVE_PCAP_LIB_VERSION #ifdef _WIN32 (void)fprintf(stderr, "%s version %s, based on tcpdump version %s\n", program_name, WDversion, version); #else /* _WIN32 */ (void)fprintf(stderr, "%s version %s\n", program_name, version); #endif /* _WIN32 */ (void)fprintf(stderr, "%s\n",pcap_lib_version()); #else /* HAVE_PCAP_LIB_VERSION */ #ifdef _WIN32 (void)fprintf(stderr, "%s version %s, based on tcpdump version %s\n", program_name, WDversion, version); (void)fprintf(stderr, "WinPcap version %s, based on libpcap version %s\n",Wpcap_version, pcap_version); #else /* _WIN32 */ (void)fprintf(stderr, "%s version %s\n", program_name, version); (void)fprintf(stderr, "libpcap version %s\n", pcap_version); #endif /* _WIN32 */ #endif /* HAVE_PCAP_LIB_VERSION */ #if defined(HAVE_LIBCRYPTO) && defined(SSLEAY_VERSION) (void)fprintf (stderr, "%s\n", SSLeay_version(SSLEAY_VERSION)); #endif smi_version_string = nd_smi_version_string(); if (smi_version_string != NULL) (void)fprintf (stderr, "SMI-library: %s\n", smi_version_string); } USES_APPLE_RST static void print_usage(void) { print_version(); (void)fprintf(stderr, "Usage: %s [-aAbd" D_FLAG "efhH" I_FLAG J_FLAG "KlLnNOpqStu" U_FLAG "vxX#]" B_FLAG_USAGE " [ -c count ]\n", program_name); (void)fprintf(stderr, "\t\t[ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ]\n"); (void)fprintf(stderr, "\t\t[ -i interface ]" j_FLAG_USAGE " [ -M secret ] [ --number ]\n"); #ifdef HAVE_PCAP_SETDIRECTION (void)fprintf(stderr, "\t\t[ -Q in|out|inout ]\n"); #endif (void)fprintf(stderr, "\t\t[ -r file ] [ -s snaplen ] "); #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION (void)fprintf(stderr, "[ --time-stamp-precision precision ]\n"); (void)fprintf(stderr, "\t\t"); #endif #ifdef HAVE_PCAP_SET_IMMEDIATE_MODE (void)fprintf(stderr, "[ --immediate-mode ] "); #endif (void)fprintf(stderr, "[ -T type ] [ --version ] [ -V file ]\n"); (void)fprintf(stderr, "\t\t[ -w file ] [ -W filecount ] [ -y datalinktype ] [ -z postrotate-command ]\n"); (void)fprintf(stderr, "\t\t[ -Z user ] [ expression ]\n"); } /* * Local Variables: * c-style: whitesmith * c-basic-offset: 8 * End: */ Index: head/usr.sbin/tcpdump/tcpdump/Makefile =================================================================== --- head/usr.sbin/tcpdump/tcpdump/Makefile (revision 324286) +++ head/usr.sbin/tcpdump/tcpdump/Makefile (revision 324287) @@ -1,218 +1,218 @@ # $FreeBSD$ .include TCPDUMP_DISTDIR?= ${SRCTOP}/contrib/tcpdump .PATH: ${TCPDUMP_DISTDIR} PROG= tcpdump SRCS= addrtoname.c \ addrtostr.c \ af.c \ ascii_strcasecmp.c \ checksum.c \ cpack.c \ gmpls.c \ gmt2local.c \ in_cksum.c \ ipproto.c \ l2vpn.c \ machdep.c \ netdissect.c \ nlpid.c \ oui.c \ parsenfsfh.c \ print.c \ print-802_11.c \ print-802_15_4.c \ print-ah.c \ print-ahcp.c \ print-aodv.c \ print-aoe.c \ print-ap1394.c \ print-arcnet.c \ print-arp.c \ print-ascii.c \ print-atalk.c \ print-atm.c \ print-babel.c \ print-beep.c \ print-bfd.c \ print-bgp.c \ print-bootp.c \ print-bt.c \ print-calm-fast.c \ print-carp.c \ print-cdp.c \ print-cfm.c \ print-chdlc.c \ print-cip.c \ print-cnfp.c \ print-dccp.c \ print-decnet.c \ print-dhcp6.c \ print-domain.c \ print-dtp.c \ print-dvmrp.c \ print-eap.c \ print-egp.c \ print-eigrp.c \ print-enc.c \ print-esp.c \ print-ether.c \ print-fddi.c \ print-forces.c \ print-fr.c \ print-frag6.c \ print-ftp.c \ print-geneve.c \ print-geonet.c \ print-gre.c \ print-hncp.c \ print-hsrp.c \ print-http.c \ print-icmp.c \ print-icmp6.c \ print-igmp.c \ print-igrp.c \ print-ip.c \ print-ip6.c \ print-ip6opts.c \ print-ipcomp.c \ print-ipfc.c \ print-ipnet.c \ print-ipx.c \ print-isakmp.c \ print-isoclns.c \ print-juniper.c \ print-krb.c \ print-l2tp.c \ print-lane.c \ print-ldp.c \ print-lisp.c \ print-llc.c \ print-lldp.c \ print-lmp.c \ print-loopback.c \ print-lspping.c \ print-lwapp.c \ print-lwres.c \ print-m3ua.c \ print-medsa.c \ print-mobile.c \ print-mobility.c \ print-mpcp.c \ print-mpls.c \ print-mptcp.c \ print-msdp.c \ print-msnlb.c \ print-nfs.c \ print-nsh.c \ print-ntp.c \ print-null.c \ print-olsr.c \ print-openflow.c \ print-openflow-1.0.c \ print-ospf.c \ print-ospf6.c \ print-otv.c \ print-pgm.c \ print-pim.c \ print-pktap.c \ print-ppi.c \ print-ppp.c \ print-pppoe.c \ print-pptp.c \ print-radius.c \ print-raw.c \ print-resp.c \ print-rip.c \ print-ripng.c \ print-rpki-rtr.c \ print-rrcp.c \ print-rsvp.c \ print-rt6.c \ print-rtsp.c \ print-rx.c \ print-sctp.c \ print-sflow.c \ print-sip.c \ print-sl.c \ print-sll.c \ print-slow.c \ print-smb.c \ print-smtp.c \ print-snmp.c \ print-stp.c \ print-sunatm.c \ print-sunrpc.c \ print-symantec.c \ print-syslog.c \ print-tcp.c \ print-telnet.c \ print-tftp.c \ print-timed.c \ print-tipc.c \ print-token.c \ print-udld.c \ print-udp.c \ print-vjc.c \ print-vqp.c \ print-vrrp.c \ print-vtp.c \ print-vxlan.c \ print-vxlan-gpe.c \ print-wb.c \ print-zephyr.c \ print-zeromq.c \ setsignal.c \ signature.c \ smbutil.c \ strtoaddr.c \ tcpdump.c \ util-print.c \ version.c CLEANFILES+= version.c ${MAN} CFLAGS+= -I${.CURDIR} -I${TCPDUMP_DISTDIR} CFLAGS+= -DHAVE_CONFIG_H CFLAGS+= -D_U_="__attribute__((unused))" .if ${MK_INET6_SUPPORT} != "no" CFLAGS+= -DINET6 -DHAVE_OS_IPV6_SUPPORT .endif .if ${MACHINE_CPUARCH} != "i386" CFLAGS+= -DLBL_ALIGN .endif LIBADD= l pcap .if ${MK_CASPER} != "no" LIBADD+= casper LIBADD+= cap_dns -CFLAGS+=-DWITH_CASPER +CFLAGS+=-DHAVE_CASPER .endif .if ${MK_OPENSSL} != "no" LIBADD+= crypto CFLAGS+= -I${SYSROOT:U${DESTDIR}}/usr/include/openssl CFLAGS+= -DHAVE_LIBCRYPTO -DHAVE_OPENSSL_EVP_H .endif .if ${MK_PF} != "no" SRCS+= print-pflog.c \ print-pfsync.c CFLAGS+= -DHAVE_NET_PFVAR_H -DHAVE_NET_IF_PFLOG_H .endif version.c: ${TCPDUMP_DISTDIR}/VERSION rm -f version.c ; \ sed 's/.*/char version[] = "&";/' ${TCPDUMP_DISTDIR}/VERSION \ > version.c .include .for mp in ${MAN} ${mp}: ${mp}.in sed -e 's/@MAN_MISC_INFO@/7/g' -e 's/@MAN_FILE_FORMATS@/5/g' \ ${.ALLSRC} > ${.TARGET} .endfor Index: head/usr.sbin/tcpdump/tcpdump/config.h =================================================================== --- head/usr.sbin/tcpdump/tcpdump/config.h (revision 324286) +++ head/usr.sbin/tcpdump/tcpdump/config.h (revision 324287) @@ -1,407 +1,407 @@ /* $FreeBSD$ */ /* This is an edited copy of the config.h generated by configure. */ /* config.h. Generated from config.h.in by configure. */ /* config.h.in. Generated from configure.in by autoheader. */ /* define if you want to build the possibly-buggy SMB printer */ #define ENABLE_SMB 1 /* Define to 1 if you have the `alarm' function. */ #define HAVE_ALARM 1 /* Define to 1 if you have the `bpf_dump' function. */ #define HAVE_BPF_DUMP 1 /* capsicum support available */ #define HAVE_CAPSICUM 1 /* Casper library support available */ /* See Makefile */ -/* #undef WITH_CASPER */ +/* #undef HAVE_CASPER */ /* Define to 1 if you have the `cap_enter' function. */ #define HAVE_CAP_ENTER 1 /* Define to 1 if you have the `cap_ioctls_limit' function. */ #define HAVE_CAP_IOCTLS_LIMIT 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_CAP_NG_H */ /* Define to 1 if you have the `cap_rights_limit' function. */ #define HAVE_CAP_RIGHTS_LIMIT 1 /* Define to 1 if you have the declaration of `ether_ntohost', and to 0 if you don't. */ #define HAVE_DECL_ETHER_NTOHOST 1 /* define if you have the dnet_htoa function */ /* #undef HAVE_DNET_HTOA */ /* Define to 1 if you have the `ether_ntohost' function. */ #define HAVE_ETHER_NTOHOST 1 /* Define to 1 if you have the `EVP_CIPHER_CTX_new' function. */ #define HAVE_EVP_CIPHER_CTX_NEW 1 /* Define to 1 if you have the header file. */ #define HAVE_FCNTL_H 1 /* Define to 1 if you have the `fork' function. */ #define HAVE_FORK 1 /* Define to 1 if you have the `getopt_long' function. */ #define HAVE_GETOPT_LONG 1 /* define if you have getrpcbynumber() */ #define HAVE_GETRPCBYNUMBER 1 /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 /* Define to 1 if you have the `cap-ng' library (-lcap-ng). */ /* #undef HAVE_LIBCAP_NG */ /* Define to 1 if you have the `crypto' library (-lcrypto). */ /* See Makefile */ /* #undef HAVE_LIBCRYPTO */ /* Define to 1 if you have the `rpc' library (-lrpc). */ /* #undef HAVE_LIBRPC */ /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_NETDNET_DNETDB_H */ /* define if you have a dnet_htoa declaration in */ /* #undef HAVE_NETDNET_DNETDB_H_DNET_HTOA */ /* Define to 1 if you have the header file. */ /* #undef HAVE_NETINET_ETHER_H */ /* Define to 1 if you have the header file. */ #define HAVE_NETINET_IF_ETHER_H 1 /* Define to 1 if you have the header file. */ /* See Makefile */ /* #undef HAVE_NET_IF_PFLOG_H */ /* Define to 1 if you have the header file. */ /* See Makefile */ /* #undef HAVE_NET_PFVAR_H */ /* Define to 1 if you have the `openat' function. */ #define HAVE_OPENAT 1 /* Define to 1 if you have the header file. */ /* See Makefile */ /* #undef HAVE_OPENSSL_EVP_H 1 */ /* define if the OS provides AF_INET6 and struct in6_addr */ /* See Makefile */ /* #undef HAVE_OS_IPV6_SUPPORT */ /* if there's an os_proto.h for this platform, to use additional prototypes */ /* #undef HAVE_OS_PROTO_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_PCAP_BLUETOOTH_H */ /* Define to 1 if you have the `pcap_breakloop' function. */ #define HAVE_PCAP_BREAKLOOP 1 /* Define to 1 if you have the `pcap_create' function. */ #define HAVE_PCAP_CREATE 1 /* define if libpcap has pcap_datalink_name_to_val() */ #define HAVE_PCAP_DATALINK_NAME_TO_VAL 1 /* define if libpcap has pcap_datalink_val_to_description() */ #define HAVE_PCAP_DATALINK_VAL_TO_DESCRIPTION 1 /* define if libpcap has pcap_debug */ /* #undef HAVE_PCAP_DEBUG */ /* Define to 1 if you have the `pcap_dump_flush' function. */ #define HAVE_PCAP_DUMP_FLUSH 1 /* define if libpcap has pcap_dump_ftell() */ #define HAVE_PCAP_DUMP_FTELL 1 /* Define to 1 if you have the `pcap_findalldevs' function. */ #define HAVE_PCAP_FINDALLDEVS 1 /* Define to 1 if you have the `pcap_free_datalinks' function. */ #define HAVE_PCAP_FREE_DATALINKS 1 /* Define to 1 if the system has the type `pcap_if_t'. */ #define HAVE_PCAP_IF_T 1 /* Define to 1 if you have the `pcap_lib_version' function. */ #define HAVE_PCAP_LIB_VERSION 1 /* define if libpcap has pcap_list_datalinks() */ #define HAVE_PCAP_LIST_DATALINKS 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_PCAP_NFLOG_H */ /* Define to 1 if you have the `pcap_setdirection' function. */ #define HAVE_PCAP_SETDIRECTION 1 /* Define to 1 if you have the `pcap_set_datalink' function. */ #define HAVE_PCAP_SET_DATALINK 1 /* Define to 1 if you have the `pcap_set_immediate_mode' function. */ #define HAVE_PCAP_SET_IMMEDIATE_MODE 1 /* Define to 1 if you have the `pcap_set_optimizer_debug' function. */ /* #undef HAVE_PCAP_SET_OPTIMIZER_DEBUG */ /* Define to 1 if you have the `pcap_set_parser_debug' function. */ /* #undef HAVE_PCAP_SET_PARSER_DEBUG */ /* Define to 1 if you have the `pcap_set_tstamp_precision' function. */ #define HAVE_PCAP_SET_TSTAMP_PRECISION 1 /* Define to 1 if you have the `pcap_set_tstamp_type' function. */ #define HAVE_PCAP_SET_TSTAMP_TYPE 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_PCAP_USB_H */ /* define if libpcap has pcap_version */ /* #undef HAVE_PCAP_VERSION */ /* Define to 1 if you have the `pfopen' function. */ /* #undef HAVE_PFOPEN */ /* Define to 1 if you have the header file. */ #define HAVE_RPC_RPCENT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_RPC_RPC_H 1 /* Define to 1 if you have the `setlinebuf' function. */ #define HAVE_SETLINEBUF 1 /* Define to 1 if you have the `sigaction' function. */ #define HAVE_SIGACTION 1 /* Define to 1 if you have the `sigset' function. */ /* #undef HAVE_SIGSET */ /* Define to 1 if you have the `snprintf' function. */ #define HAVE_SNPRINTF 1 /* if struct sockaddr has the sa_len member */ #define HAVE_SOCKADDR_SA_LEN 1 /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the `strdup' function. */ #define HAVE_STRDUP 1 /* Define to 1 if you have the `strftime' function. */ #define HAVE_STRFTIME 1 /* Define to 1 if you have the header file. */ #define HAVE_STRINGS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the `strlcat' function. */ #define HAVE_STRLCAT 1 /* Define to 1 if you have the `strlcpy' function. */ #define HAVE_STRLCPY 1 /* Define to 1 if you have the `strsep' function. */ #define HAVE_STRSEP 1 /* Define to 1 if the system has the type `struct ether_addr'. */ /* #undef HAVE_STRUCT_ETHER_ADDR */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* Define to 1 if the system has the type `uintptr_t'. */ #define HAVE_UINTPTR_T 1 /* Define to 1 if you have the header file. */ #define HAVE_UNISTD_H 1 /* Define to 1 if you have the `vfork' function. */ #define HAVE_VFORK 1 /* Define to 1 if you have the `vfprintf' function. */ #define HAVE_VFPRINTF 1 /* Define to 1 if you have the `vsnprintf' function. */ #define HAVE_VSNPRINTF 1 /* define if libpcap has yydebug */ /* #undef HAVE_YYDEBUG */ /* define if your compiler has __attribute__ */ #define HAVE___ATTRIBUTE__ 1 /* if unaligned access fails */ /* #undef LBL_ALIGN */ /* Define to 1 if netinet/ether.h declares `ether_ntohost' */ /* #undef NETINET_ETHER_H_DECLARES_ETHER_NTOHOST */ /* Define to 1 if netinet/if_ether.h declares `ether_ntohost' */ #define NETINET_IF_ETHER_H_DECLARES_ETHER_NTOHOST /**/ /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "" /* Define to the full name of this package. */ #define PACKAGE_NAME "" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "" /* Define to the home page for this package. */ #define PACKAGE_URL "" /* Define to the version of this package. */ #define PACKAGE_VERSION "" /* define if the platform doesn't define PRId64 */ /* #undef PRId64 */ /* define if the platform doesn't define PRIo64 */ /* #undef PRIo64 */ /* define if the platform doesn't define PRIx64 */ /* #undef PRIu64 */ /* define if the platform doesn't define PRIu64 */ /* #undef PRIx64 */ /* Define as the return type of signal handlers (`int' or `void'). */ #define RETSIGTYPE void /* return value of signal handlers */ #define RETSIGVAL /**/ /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Define to 1 if you can safely include both and . */ #define TIME_WITH_SYS_TIME 1 /* define if you have ether_ntohost() and it works */ #define USE_ETHER_NTOHOST 1 /* Define if you enable support for libsmi */ /* #undef USE_LIBSMI */ /* define if should chroot when dropping privileges */ /* #undef WITH_CHROOT */ /* define if should drop privileges by default */ /* #undef WITH_USER */ /* get BSD semantics on Irix */ /* #undef _BSD_SIGNALS */ /* define on AIX to get certain functions */ /* #undef _SUN */ /* Define for Solaris 2.5.1 so the uint32_t typedef from , , or is not used. If the typedef were allowed, the #define below would cause a syntax error. */ /* #undef _UINT32_T */ /* Define for Solaris 2.5.1 so the uint64_t typedef from , , or is not used. If the typedef were allowed, the #define below would cause a syntax error. */ /* #undef _UINT64_T */ /* Define for Solaris 2.5.1 so the uint8_t typedef from , , or is not used. If the typedef were allowed, the #define below would cause a syntax error. */ /* #undef _UINT8_T */ /* define if your compiler allows __attribute__((format)) without a warning */ #define __ATTRIBUTE___FORMAT_OK 1 /* define if your compiler allows __attribute__((format)) to be applied to function pointers */ #define __ATTRIBUTE___FORMAT_OK_FOR_FUNCTION_POINTERS 1 /* define if your compiler allows __attribute__((noreturn)) to be applied to function pointers */ #define __ATTRIBUTE___NORETURN_OK_FOR_FUNCTION_POINTERS 1 /* to handle Ultrix compilers that don't support const in prototypes */ /* #undef const */ /* Define as token for inline if inlining supported */ #define inline inline /* Define to the type of a signed integer type of width exactly 16 bits if such a type exists and the standard includes do not define it. */ /* #undef int16_t */ /* Define to the type of a signed integer type of width exactly 32 bits if such a type exists and the standard includes do not define it. */ /* #undef int32_t */ /* Define to the type of a signed integer type of width exactly 64 bits if such a type exists and the standard includes do not define it. */ /* #undef int64_t */ /* Define to the type of a signed integer type of width exactly 8 bits if such a type exists and the standard includes do not define it. */ /* #undef int8_t */ /* Define to `uint16_t' if u_int16_t not defined. */ /* #undef u_int16_t */ /* Define to `uint32_t' if u_int32_t not defined. */ /* #undef u_int32_t */ /* Define to `uint64_t' if u_int64_t not defined. */ /* #undef u_int64_t */ /* Define to `uint8_t' if u_int8_t not defined. */ /* #undef u_int8_t */ /* Define to the type of an unsigned integer type of width exactly 16 bits if such a type exists and the standard includes do not define it. */ /* #undef uint16_t */ /* Define to the type of an unsigned integer type of width exactly 32 bits if such a type exists and the standard includes do not define it. */ /* #undef uint32_t */ /* Define to the type of an unsigned integer type of width exactly 64 bits if such a type exists and the standard includes do not define it. */ /* #undef uint64_t */ /* Define to the type of an unsigned integer type of width exactly 8 bits if such a type exists and the standard includes do not define it. */ /* #undef uint8_t */ /* Define to the type of an unsigned integer type wide enough to hold a pointer, if such a type exists, and if the system does not define it. */ /* #undef uintptr_t */