]> The Tcpdump Group git mirrors - tcpdump/commitdiff
Merge pull request #452 from brooksdavis/backend-separation
authorMichael Richardson <[email protected]>
Wed, 15 Apr 2015 21:17:03 +0000 (17:17 -0400)
committerMichael Richardson <[email protected]>
Wed, 15 Apr 2015 21:17:03 +0000 (17:17 -0400)
Backend separation

Makefile.in
netdissect.h
print.c [new file with mode: 0644]
print.h [new file with mode: 0644]
tcpdump.c
util-print.c [new file with mode: 0644]
util.c

index d8a0ca235a8b6450da33d7f7202b24c0e760c26e..ddb24981e99cafbb2af3cfaed943eeb4891454da 100644 (file)
@@ -70,7 +70,7 @@ DEPENDENCY_CFLAG = @DEPENDENCY_CFLAG@
        @rm -f $@
        $(CC) $(FULL_CFLAGS) -c $(srcdir)/$*.c
 
-CSRC = setsignal.c tcpdump.c
+CSRC = setsignal.c tcpdump.c util.c
 
 LIBNETDISSECT_SRC=\
        addrtoname.c \
@@ -86,6 +86,7 @@ LIBNETDISSECT_SRC=\
        nlpid.c \
        oui.c \
        parsenfsfh.c \
+       print.c \
        print-802_11.c \
        print-802_15_4.c \
        print-ah.c \
@@ -215,7 +216,7 @@ LIBNETDISSECT_SRC=\
        print-zephyr.c \
        print-zeromq.c \
        signature.c \
-       util.c
+       util-print.c
 
 LOCALSRC = @LOCALSRC@
 GENSRC = version.c
index 7b8b5f4a1ecf382c24bee111052651a644a5fdca..d7361a4fffcd2b93aaa15fdff6fa113d91a081d9 100644 (file)
@@ -628,4 +628,6 @@ extern int esp_print_decrypt_buffer_by_ikev2(netdissect_options *ndo,
 extern void geonet_print(netdissect_options *ndo,const u_char *eth_hdr,const u_char *geo_pck, u_int len);
 extern void calm_fast_print(netdissect_options *ndo,const u_char *eth_hdr,const u_char *calm_pck, u_int len);
 
+extern netdissect_options *gndo;
+
 #endif  /* netdissect_h */
diff --git a/print.c b/print.c
new file mode 100644 (file)
index 0000000..648a899
--- /dev/null
+++ b/print.c
@@ -0,0 +1,482 @@
+/*
+ * 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 <[email protected]>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <tcpdump-stdinc.h>
+
+#include "netdissect.h"
+#include "interface.h"
+#include "addrtoname.h"
+#include "print.h"
+
+struct printer {
+       if_printer f;
+       int type;
+};
+
+static const struct printer printers[] = {
+       { ether_if_print,       DLT_EN10MB },
+#ifdef DLT_IPNET
+       { ipnet_if_print,       DLT_IPNET },
+#endif
+#ifdef DLT_IEEE802_15_4
+       { ieee802_15_4_if_print, DLT_IEEE802_15_4 },
+#endif
+#ifdef DLT_IEEE802_15_4_NOFCS
+       { ieee802_15_4_if_print, DLT_IEEE802_15_4_NOFCS },
+#endif
+#ifdef DLT_PPI
+       { ppi_if_print,         DLT_PPI },
+#endif
+#ifdef DLT_NETANALYZER
+       { netanalyzer_if_print, DLT_NETANALYZER },
+#endif
+#ifdef DLT_NETANALYZER_TRANSPARENT
+       { netanalyzer_transparent_if_print, DLT_NETANALYZER_TRANSPARENT },
+#endif
+#if defined(DLT_NFLOG) && defined(HAVE_PCAP_NFLOG_H)
+       { nflog_if_print,       DLT_NFLOG},
+#endif
+#ifdef DLT_CIP
+       { cip_if_print,         DLT_CIP },
+#endif
+#ifdef DLT_ATM_CLIP
+       { cip_if_print,         DLT_ATM_CLIP },
+#endif
+#ifdef DLT_IP_OVER_FC
+       { ipfc_if_print,        DLT_IP_OVER_FC },
+#endif
+       { null_if_print,        DLT_NULL },
+#ifdef DLT_LOOP
+       { null_if_print,        DLT_LOOP },
+#endif
+#ifdef DLT_APPLE_IP_OVER_IEEE1394
+       { ap1394_if_print,      DLT_APPLE_IP_OVER_IEEE1394 },
+#endif
+#if defined(DLT_BLUETOOTH_HCI_H4_WITH_PHDR) && defined(HAVE_PCAP_BLUETOOTH_H)
+       { bt_if_print,          DLT_BLUETOOTH_HCI_H4_WITH_PHDR},
+#endif
+#ifdef DLT_LANE8023
+       { lane_if_print,        DLT_LANE8023 },
+#endif
+       { arcnet_if_print,      DLT_ARCNET },
+#ifdef DLT_ARCNET_LINUX
+       { arcnet_linux_if_print, DLT_ARCNET_LINUX },
+#endif
+       { raw_if_print,         DLT_RAW },
+#ifdef DLT_IPV4
+       { raw_if_print,         DLT_IPV4 },
+#endif
+#ifdef DLT_IPV6
+       { raw_if_print,         DLT_IPV6 },
+#endif
+#ifdef HAVE_PCAP_USB_H
+#ifdef DLT_USB_LINUX
+       { usb_linux_48_byte_print, DLT_USB_LINUX},
+#endif /* DLT_USB_LINUX */
+#ifdef DLT_USB_LINUX_MMAPPED
+       { usb_linux_64_byte_print, DLT_USB_LINUX_MMAPPED},
+#endif /* DLT_USB_LINUX_MMAPPED */
+#endif /* HAVE_PCAP_USB_H */
+#ifdef DLT_SYMANTEC_FIREWALL
+       { symantec_if_print,    DLT_SYMANTEC_FIREWALL },
+#endif
+#ifdef DLT_C_HDLC
+       { chdlc_if_print,       DLT_C_HDLC },
+#endif
+#ifdef DLT_HDLC
+       { chdlc_if_print,       DLT_HDLC },
+#endif
+#ifdef DLT_PPP_ETHER
+       { pppoe_if_print,       DLT_PPP_ETHER },
+#endif
+#if defined(DLT_PFLOG) && defined(HAVE_NET_PFVAR_H)
+       { pflog_if_print,       DLT_PFLOG },
+#endif
+       { token_if_print,       DLT_IEEE802 },
+       { fddi_if_print,        DLT_FDDI },
+#ifdef DLT_LINUX_SLL
+       { sll_if_print,         DLT_LINUX_SLL },
+#endif
+#ifdef DLT_FR
+       { fr_if_print,          DLT_FR },
+#endif
+#ifdef DLT_FRELAY
+       { fr_if_print,          DLT_FRELAY },
+#endif
+#ifdef DLT_MFR
+       { mfr_if_print,         DLT_MFR },
+#endif
+       { atm_if_print,         DLT_ATM_RFC1483 },
+#ifdef DLT_SUNATM
+       { sunatm_if_print,      DLT_SUNATM },
+#endif
+#ifdef DLT_ENC
+       { enc_if_print,         DLT_ENC },
+#endif
+       { sl_if_print,          DLT_SLIP },
+#ifdef DLT_SLIP_BSDOS
+       { sl_bsdos_if_print,    DLT_SLIP_BSDOS },
+#endif
+#ifdef DLT_LTALK
+       { ltalk_if_print,       DLT_LTALK },
+#endif
+#ifdef DLT_JUNIPER_ATM1
+       { juniper_atm1_print,   DLT_JUNIPER_ATM1 },
+#endif
+#ifdef DLT_JUNIPER_ATM2
+       { juniper_atm2_print,   DLT_JUNIPER_ATM2 },
+#endif
+#ifdef DLT_JUNIPER_MFR
+       { juniper_mfr_print,    DLT_JUNIPER_MFR },
+#endif
+#ifdef DLT_JUNIPER_MLFR
+       { juniper_mlfr_print,   DLT_JUNIPER_MLFR },
+#endif
+#ifdef DLT_JUNIPER_MLPPP
+       { juniper_mlppp_print,  DLT_JUNIPER_MLPPP },
+#endif
+#ifdef DLT_JUNIPER_PPPOE
+       { juniper_pppoe_print,  DLT_JUNIPER_PPPOE },
+#endif
+#ifdef DLT_JUNIPER_PPPOE_ATM
+       { juniper_pppoe_atm_print, DLT_JUNIPER_PPPOE_ATM },
+#endif
+#ifdef DLT_JUNIPER_GGSN
+       { juniper_ggsn_print,   DLT_JUNIPER_GGSN },
+#endif
+#ifdef DLT_JUNIPER_ES
+       { juniper_es_print,     DLT_JUNIPER_ES },
+#endif
+#ifdef DLT_JUNIPER_MONITOR
+       { juniper_monitor_print, DLT_JUNIPER_MONITOR },
+#endif
+#ifdef DLT_JUNIPER_SERVICES
+       { juniper_services_print, DLT_JUNIPER_SERVICES },
+#endif
+#ifdef DLT_JUNIPER_ETHER
+       { juniper_ether_print,  DLT_JUNIPER_ETHER },
+#endif
+#ifdef DLT_JUNIPER_PPP
+       { juniper_ppp_print,    DLT_JUNIPER_PPP },
+#endif
+#ifdef DLT_JUNIPER_FRELAY
+       { juniper_frelay_print, DLT_JUNIPER_FRELAY },
+#endif
+#ifdef DLT_JUNIPER_CHDLC
+       { juniper_chdlc_print,  DLT_JUNIPER_CHDLC },
+#endif
+#ifdef DLT_PKTAP
+       { pktap_if_print,       DLT_PKTAP },
+#endif
+#ifdef DLT_IEEE802_11_RADIO
+       { ieee802_11_radio_if_print,    DLT_IEEE802_11_RADIO },
+#endif
+#ifdef DLT_IEEE802_11
+       { ieee802_11_if_print,  DLT_IEEE802_11},
+#endif
+#ifdef DLT_IEEE802_11_RADIO_AVS
+       { ieee802_11_radio_avs_if_print,        DLT_IEEE802_11_RADIO_AVS },
+#endif
+#ifdef DLT_PRISM_HEADER
+       { prism_if_print,       DLT_PRISM_HEADER },
+#endif
+       { ppp_if_print,         DLT_PPP },
+#ifdef DLT_PPP_WITHDIRECTION
+       { ppp_if_print,         DLT_PPP_WITHDIRECTION },
+#endif
+#ifdef DLT_PPP_BSDOS
+       { ppp_bsdos_if_print,   DLT_PPP_BSDOS },
+#endif
+#ifdef DLT_PPP_SERIAL
+       { ppp_hdlc_if_print,    DLT_PPP_SERIAL },
+#endif
+       { NULL,                 0 },
+};
+
+
+static void    ndo_default_print(netdissect_options *ndo, const u_char *bp,
+                   u_int length);
+
+static void    ndo_error(netdissect_options *ndo _U_, const char *fmt, ...)
+                   __attribute__((noreturn))
+#ifdef __ATTRIBUTE___FORMAT_OK
+                   __attribute__((format (printf, 2, 3)))
+#endif /* __ATTRIBUTE___FORMAT_OK */
+                   ;
+static void    ndo_warning(netdissect_options *ndo _U_, const char *fmt, ...)
+#ifdef __ATTRIBUTE___FORMAT_OK
+                   __attribute__((format (printf, 2, 3)))
+#endif /* __ATTRIBUTE___FORMAT_OK */
+                   ;
+
+static int     tcpdump_printf(netdissect_options *ndo _U_, const char *fmt, ...)
+#ifdef __ATTRIBUTE___FORMAT_OK
+                    __attribute ((format (printf, 2, 3)))
+#endif /* __ATTRIBUTE___FORMAT_OK */
+                    ;
+
+void
+init_print(u_int32_t localnet, u_int32_t mask, uint32_t timezone_offset)
+{
+
+       thiszone = timezone_offset;
+       init_addrtoname(gndo, localnet, mask);
+       init_checksum();
+}
+
+if_printer
+lookup_printer(int type)
+{
+       const struct printer *p;
+
+       for (p = printers; p->f; ++p)
+               if (type == p->type)
+                       return p->f;
+
+#if defined(DLT_USER2) && defined(DLT_PKTAP)
+       /*
+        * Apple incorrectly chose to use DLT_USER2 for their PKTAP
+        * header.
+        *
+        * We map DLT_PKTAP, whether it's DLT_USER2 as it is on Darwin-
+        * based OSes or the same value as LINKTYPE_PKTAP as it is on
+        * other OSes, to LINKTYPE_PKTAP, so files written with
+        * this version of libpcap for a DLT_PKTAP capture have a link-
+        * layer header type of LINKTYPE_PKTAP.
+        *
+        * However, files written on OS X Mavericks for a DLT_PKTAP
+        * capture have a link-layer header type of LINKTYPE_USER2.
+        * If we don't have a printer for DLT_USER2, and type is
+        * DLT_USER2, we look up the printer for DLT_PKTAP and use
+        * that.
+        */
+       if (type == DLT_USER2) {
+               for (p = printers; p->f; ++p)
+                       if (DLT_PKTAP == p->type)
+                               return p->f;
+       }
+#endif
+
+       return NULL;
+       /* NOTREACHED */
+}
+
+int
+has_printer(int type)
+{
+
+       return (lookup_printer(type) != NULL);
+}
+
+struct print_info
+get_print_info(int type)
+{
+       struct print_info printinfo;
+
+       printinfo.ndo = gndo;
+       printinfo.printer = lookup_printer(type);
+       if (printinfo.printer == NULL) {
+               gndo->ndo_dltname = pcap_datalink_val_to_name(type);
+               if (gndo->ndo_dltname != NULL)
+                       error("packet printing is not supported for link type %s: use -w",
+                             gndo->ndo_dltname);
+               else
+                       error("packet printing is not supported for link type %d: use -w", type);
+       }
+       return (printinfo);
+}
+
+void
+pretty_print_packet(struct print_info *print_info, const struct pcap_pkthdr *h,
+    const u_char *sp, u_int packets_captured)
+{
+       u_int hdrlen;
+        netdissect_options *ndo;
+
+        ndo = print_info->ndo;
+
+       if(ndo->ndo_packet_number)
+               ND_PRINT((ndo, "%5u  ", packets_captured));
+
+       ts_print(ndo, &h->ts);
+
+       /*
+        * Some printers want to check that they're not walking off the
+        * end of the packet.
+        * Rather than pass it all the way down, we set this member
+        * of the netdissect_options structure.
+        */
+       ndo->ndo_snapend = sp + h->caplen;
+
+        hdrlen = (*print_info->printer)(print_info->ndo, h, sp);
+
+       /*
+        * Restore the original snapend, as a printer might have
+        * changed it.
+        */
+       ndo->ndo_snapend = sp + h->caplen;
+       if (ndo->ndo_Xflag) {
+               /*
+                * Print the raw packet data in hex and ASCII.
+                */
+               if (ndo->ndo_Xflag > 1) {
+                       /*
+                        * Include the link-layer header.
+                        */
+                       hex_and_ascii_print(ndo, "\n\t", sp, h->caplen);
+               } else {
+                       /*
+                        * Don't include the link-layer header - and if
+                        * we have nothing past the link-layer header,
+                        * print nothing.
+                        */
+                       if (h->caplen > hdrlen)
+                               hex_and_ascii_print(ndo, "\n\t", sp + hdrlen,
+                                   h->caplen - hdrlen);
+               }
+       } else if (ndo->ndo_xflag) {
+               /*
+                * Print the raw packet data in hex.
+                */
+               if (ndo->ndo_xflag > 1) {
+                       /*
+                        * Include the link-layer header.
+                        */
+                        hex_print(ndo, "\n\t", sp, h->caplen);
+               } else {
+                       /*
+                        * Don't include the link-layer header - and if
+                        * we have nothing past the link-layer header,
+                        * print nothing.
+                        */
+                       if (h->caplen > hdrlen)
+                               hex_print(ndo, "\n\t", sp + hdrlen,
+                                          h->caplen - hdrlen);
+               }
+       } else if (ndo->ndo_Aflag) {
+               /*
+                * Print the raw packet data in ASCII.
+                */
+               if (ndo->ndo_Aflag > 1) {
+                       /*
+                        * Include the link-layer header.
+                        */
+                       ascii_print(ndo, sp, h->caplen);
+               } else {
+                       /*
+                        * Don't include the link-layer header - and if
+                        * we have nothing past the link-layer header,
+                        * print nothing.
+                        */
+                       if (h->caplen > hdrlen)
+                               ascii_print(ndo, sp + hdrlen, h->caplen - hdrlen);
+               }
+       }
+
+       putchar('\n');
+}
+
+/*
+ * By default, print the specified data out in hex and ASCII.
+ */
+static void
+ndo_default_print(netdissect_options *ndo, const u_char *bp, u_int length)
+{
+       hex_and_ascii_print(ndo, "\n\t", bp, length); /* pass on lf and indentation string */
+}
+
+/* VARARGS */
+static void
+ndo_error(netdissect_options *ndo _U_, 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(1);
+       /* NOTREACHED */
+}
+
+/* VARARGS */
+static void
+ndo_warning(netdissect_options *ndo _U_, 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 int
+tcpdump_printf(netdissect_options *ndo _U_, const char *fmt, ...)
+{
+       va_list args;
+       int ret;
+
+       va_start(args, fmt);
+       ret = vfprintf(stdout, fmt, args);
+       va_end(args);
+
+       return (ret);
+}
+
+void
+ndo_set_function_pointers(netdissect_options *ndo)
+{
+
+       ndo->ndo_default_print=ndo_default_print;
+       ndo->ndo_printf=tcpdump_printf;
+       ndo->ndo_error=ndo_error;
+       ndo->ndo_warning=ndo_warning;
+}
+/*
+ * Local Variables:
+ * c-style: whitesmith
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/print.h b/print.h
new file mode 100644 (file)
index 0000000..048359d
--- /dev/null
+++ b/print.h
@@ -0,0 +1,49 @@
+/*
+ * 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 <[email protected]>
+ */
+
+#ifndef print_h
+#define print_h
+
+struct print_info {
+       netdissect_options *ndo;
+       if_printer printer;
+};
+
+void   init_print(u_int32_t localnet, u_int32_t mask,
+           uint32_t timezone_offset);
+
+int    has_printer(int type);
+
+struct print_info      get_print_info(int type);
+
+void   pretty_print_packet(struct print_info *print_info,
+           const struct pcap_pkthdr *h, const u_char *sp,
+           u_int packets_captured);
+
+void   ndo_set_function_pointers(netdissect_options *ndo);
+
+#endif /* print_h */
index 8edb0367681d5c1a6ca5fd873bc1e7f1d012b93b..45db78d8d0807c70b02e5bfbfc95921dc099ef40 100644 (file)
--- a/tcpdump.c
+++ b/tcpdump.c
@@ -122,6 +122,8 @@ extern int SIZE_BUF;
 #include "gmt2local.h"
 #include "pcap-missing.h"
 
+#include "print.h"
+
 #ifndef PATH_MAX
 #define PATH_MAX 1024
 #endif
@@ -151,8 +153,6 @@ static int infoprint;
 
 char *program_name;
 
-int32_t thiszone;              /* seconds offset from gmt to local time */
-
 /* Forwards */
 static RETSIGTYPE cleanup(int);
 static RETSIGTYPE child_cleanup(int);
@@ -161,21 +161,9 @@ static void print_usage(void);
 static void show_dlts_and_exit(const char *device, pcap_t *pd) __attribute__((noreturn));
 
 static void print_packet(u_char *, const struct pcap_pkthdr *, const u_char *);
-static void ndo_default_print(netdissect_options *, const u_char *, u_int);
 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 *);
-static void ndo_error(netdissect_options *ndo, const char *fmt, ...)
-     __attribute__((noreturn))
-#ifdef __ATTRIBUTE___FORMAT_OK
-     __attribute__((format (printf, 2, 3)))
-#endif /* __ATTRIBUTE___FORMAT_OK */
-    ;
-static void ndo_warning(netdissect_options *ndo, const char *fmt, ...)
-#ifdef __ATTRIBUTE___FORMAT_OK
-     __attribute__((format (printf, 2, 3)))
-#endif /* __ATTRIBUTE___FORMAT_OK */
-    ;
 
 #ifdef SIGNAL_REQ_INFO
 RETSIGTYPE requestinfo(int);
@@ -192,192 +180,6 @@ RETSIGTYPE requestinfo(int);
 static void info(int);
 static u_int packets_captured;
 
-struct printer {
-       if_printer f;
-       int type;
-};
-
-
-static const struct printer printers[] = {
-       { ether_if_print,       DLT_EN10MB },
-#ifdef DLT_IPNET
-       { ipnet_if_print,       DLT_IPNET },
-#endif
-#ifdef DLT_IEEE802_15_4
-       { ieee802_15_4_if_print, DLT_IEEE802_15_4 },
-#endif
-#ifdef DLT_IEEE802_15_4_NOFCS
-       { ieee802_15_4_if_print, DLT_IEEE802_15_4_NOFCS },
-#endif
-#ifdef DLT_PPI
-       { ppi_if_print,         DLT_PPI },
-#endif
-#ifdef DLT_NETANALYZER
-       { netanalyzer_if_print, DLT_NETANALYZER },
-#endif
-#ifdef DLT_NETANALYZER_TRANSPARENT
-       { netanalyzer_transparent_if_print, DLT_NETANALYZER_TRANSPARENT },
-#endif
-#if defined(DLT_NFLOG) && defined(HAVE_PCAP_NFLOG_H)
-       { nflog_if_print,       DLT_NFLOG},
-#endif
-#ifdef DLT_CIP
-       { cip_if_print,         DLT_CIP },
-#endif
-#ifdef DLT_ATM_CLIP
-       { cip_if_print,         DLT_ATM_CLIP },
-#endif
-#ifdef DLT_IP_OVER_FC
-       { ipfc_if_print,        DLT_IP_OVER_FC },
-#endif
-       { null_if_print,        DLT_NULL },
-#ifdef DLT_LOOP
-       { null_if_print,        DLT_LOOP },
-#endif
-#ifdef DLT_APPLE_IP_OVER_IEEE1394
-       { ap1394_if_print,      DLT_APPLE_IP_OVER_IEEE1394 },
-#endif
-#if defined(DLT_BLUETOOTH_HCI_H4_WITH_PHDR) && defined(HAVE_PCAP_BLUETOOTH_H)
-       { bt_if_print,          DLT_BLUETOOTH_HCI_H4_WITH_PHDR},
-#endif
-#ifdef DLT_LANE8023
-       { lane_if_print,        DLT_LANE8023 },
-#endif
-       { arcnet_if_print,      DLT_ARCNET },
-#ifdef DLT_ARCNET_LINUX
-       { arcnet_linux_if_print, DLT_ARCNET_LINUX },
-#endif
-       { raw_if_print,         DLT_RAW },
-#ifdef DLT_IPV4
-       { raw_if_print,         DLT_IPV4 },
-#endif
-#ifdef DLT_IPV6
-       { raw_if_print,         DLT_IPV6 },
-#endif
-#ifdef HAVE_PCAP_USB_H
-#ifdef DLT_USB_LINUX
-       { usb_linux_48_byte_print, DLT_USB_LINUX},
-#endif /* DLT_USB_LINUX */
-#ifdef DLT_USB_LINUX_MMAPPED
-       { usb_linux_64_byte_print, DLT_USB_LINUX_MMAPPED},
-#endif /* DLT_USB_LINUX_MMAPPED */
-#endif /* HAVE_PCAP_USB_H */
-#ifdef DLT_SYMANTEC_FIREWALL
-       { symantec_if_print,    DLT_SYMANTEC_FIREWALL },
-#endif
-#ifdef DLT_C_HDLC
-       { chdlc_if_print,       DLT_C_HDLC },
-#endif
-#ifdef DLT_HDLC
-       { chdlc_if_print,       DLT_HDLC },
-#endif
-#ifdef DLT_PPP_ETHER
-       { pppoe_if_print,       DLT_PPP_ETHER },
-#endif
-#if defined(DLT_PFLOG) && defined(HAVE_NET_PFVAR_H)
-       { pflog_if_print,       DLT_PFLOG },
-#endif
-       { token_if_print,       DLT_IEEE802 },
-       { fddi_if_print,        DLT_FDDI },
-#ifdef DLT_LINUX_SLL
-       { sll_if_print,         DLT_LINUX_SLL },
-#endif
-#ifdef DLT_FR
-       { fr_if_print,          DLT_FR },
-#endif
-#ifdef DLT_FRELAY
-       { fr_if_print,          DLT_FRELAY },
-#endif
-#ifdef DLT_MFR
-       { mfr_if_print,         DLT_MFR },
-#endif
-       { atm_if_print,         DLT_ATM_RFC1483 },
-#ifdef DLT_SUNATM
-       { sunatm_if_print,      DLT_SUNATM },
-#endif
-#ifdef DLT_ENC
-       { enc_if_print,         DLT_ENC },
-#endif
-       { sl_if_print,          DLT_SLIP },
-#ifdef DLT_SLIP_BSDOS
-       { sl_bsdos_if_print,    DLT_SLIP_BSDOS },
-#endif
-#ifdef DLT_LTALK
-       { ltalk_if_print,       DLT_LTALK },
-#endif
-#ifdef DLT_JUNIPER_ATM1
-       { juniper_atm1_print,   DLT_JUNIPER_ATM1 },
-#endif
-#ifdef DLT_JUNIPER_ATM2
-       { juniper_atm2_print,   DLT_JUNIPER_ATM2 },
-#endif
-#ifdef DLT_JUNIPER_MFR
-       { juniper_mfr_print,    DLT_JUNIPER_MFR },
-#endif
-#ifdef DLT_JUNIPER_MLFR
-       { juniper_mlfr_print,   DLT_JUNIPER_MLFR },
-#endif
-#ifdef DLT_JUNIPER_MLPPP
-       { juniper_mlppp_print,  DLT_JUNIPER_MLPPP },
-#endif
-#ifdef DLT_JUNIPER_PPPOE
-       { juniper_pppoe_print,  DLT_JUNIPER_PPPOE },
-#endif
-#ifdef DLT_JUNIPER_PPPOE_ATM
-       { juniper_pppoe_atm_print, DLT_JUNIPER_PPPOE_ATM },
-#endif
-#ifdef DLT_JUNIPER_GGSN
-       { juniper_ggsn_print,   DLT_JUNIPER_GGSN },
-#endif
-#ifdef DLT_JUNIPER_ES
-       { juniper_es_print,     DLT_JUNIPER_ES },
-#endif
-#ifdef DLT_JUNIPER_MONITOR
-       { juniper_monitor_print, DLT_JUNIPER_MONITOR },
-#endif
-#ifdef DLT_JUNIPER_SERVICES
-       { juniper_services_print, DLT_JUNIPER_SERVICES },
-#endif
-#ifdef DLT_JUNIPER_ETHER
-       { juniper_ether_print,  DLT_JUNIPER_ETHER },
-#endif
-#ifdef DLT_JUNIPER_PPP
-       { juniper_ppp_print,    DLT_JUNIPER_PPP },
-#endif
-#ifdef DLT_JUNIPER_FRELAY
-       { juniper_frelay_print, DLT_JUNIPER_FRELAY },
-#endif
-#ifdef DLT_JUNIPER_CHDLC
-       { juniper_chdlc_print,  DLT_JUNIPER_CHDLC },
-#endif
-#ifdef DLT_PKTAP
-       { pktap_if_print,       DLT_PKTAP },
-#endif
-#ifdef DLT_IEEE802_11_RADIO
-       { ieee802_11_radio_if_print,    DLT_IEEE802_11_RADIO },
-#endif
-#ifdef DLT_IEEE802_11
-       { ieee802_11_if_print,  DLT_IEEE802_11},
-#endif
-#ifdef DLT_IEEE802_11_RADIO_AVS
-       { ieee802_11_radio_avs_if_print,        DLT_IEEE802_11_RADIO_AVS },
-#endif
-#ifdef DLT_PRISM_HEADER
-       { prism_if_print,       DLT_PRISM_HEADER },
-#endif
-       { ppp_if_print,         DLT_PPP },
-#ifdef DLT_PPP_WITHDIRECTION
-       { ppp_if_print,         DLT_PPP_WITHDIRECTION },
-#endif
-#ifdef DLT_PPP_BSDOS
-       { ppp_bsdos_if_print,   DLT_PPP_BSDOS },
-#endif
-#ifdef DLT_PPP_SERIAL
-       { ppp_hdlc_if_print,    DLT_PPP_SERIAL },
-#endif
-       { NULL,                 0 },
-};
-
 static const struct tok status_flags[] = {
 #ifdef PCAP_IF_UP
        { PCAP_IF_UP,       "Up"       },
@@ -389,43 +191,6 @@ static const struct tok status_flags[] = {
        { 0, NULL }
 };
 
-if_printer
-lookup_printer(int type)
-{
-       const struct printer *p;
-
-       for (p = printers; p->f; ++p)
-               if (type == p->type)
-                       return p->f;
-
-#if defined(DLT_USER2) && defined(DLT_PKTAP)
-       /*
-        * Apple incorrectly chose to use DLT_USER2 for their PKTAP
-        * header.
-        *
-        * We map DLT_PKTAP, whether it's DLT_USER2 as it is on Darwin-
-        * based OSes or the same value as LINKTYPE_PKTAP as it is on
-        * other OSes, to LINKTYPE_PKTAP, so files written with
-        * this version of libpcap for a DLT_PKTAP capture have a link-
-        * layer header type of LINKTYPE_PKTAP.
-        *
-        * However, files written on OS X Mavericks for a DLT_PKTAP
-        * capture have a link-layer header type of LINKTYPE_USER2.
-        * If we don't have a printer for DLT_USER2, and type is
-        * DLT_USER2, we look up the printer for DLT_PKTAP and use
-        * that.
-        */
-       if (type == DLT_USER2) {
-               for (p = printers; p->f; ++p)
-                       if (DLT_PKTAP == p->type)
-                               return p->f;
-       }
-#endif
-
-       return NULL;
-       /* NOTREACHED */
-}
-
 static pcap_t *pd;
 
 static int supports_monitor_mode;
@@ -434,11 +199,6 @@ extern int optind;
 extern int opterr;
 extern char *optarg;
 
-struct print_info {
-        netdissect_options *ndo;
-        if_printer printer;
-};
-
 struct dump_info {
        char    *WFileName;
        char    *CurrentFileName;
@@ -521,7 +281,7 @@ show_dlts_and_exit(const char *device, pcap_t *pd)
                        /*
                         * OK, does tcpdump handle that type?
                         */
-                       if (lookup_printer(dlts[i]) == NULL)
+                       if (!has_printer(dlts[i]))
                                (void) fprintf(stderr, " (printing not supported)");
                        fprintf(stderr, "\n");
                } else {
@@ -815,38 +575,6 @@ MakeFilename(char *buffer, char *orig_name, int cnt, int max_chars)
         free(filename);
 }
 
-static int tcpdump_printf(netdissect_options *ndo _U_,
-                         const char *fmt, ...)
-{
-
-  va_list args;
-  int ret;
-
-  va_start(args, fmt);
-  ret=vfprintf(stdout, fmt, args);
-  va_end(args);
-
-  return ret;
-}
-
-static struct print_info
-get_print_info(int type)
-{
-       struct print_info printinfo;
-
-       printinfo.ndo = gndo;
-       printinfo.printer = lookup_printer(type);
-       if (printinfo.printer == NULL) {
-               gndo->ndo_dltname = pcap_datalink_val_to_name(type);
-               if (gndo->ndo_dltname != NULL)
-                       error("packet printing is not supported for link type %s: use -w",
-                             gndo->ndo_dltname);
-               else
-                       error("packet printing is not supported for link type %d: use -w", type);
-       }
-       return (printinfo);
-}
-
 static char *
 get_next_file(FILE *VFile, char *ptr)
 {
@@ -967,6 +695,7 @@ 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 type;
@@ -1005,10 +734,7 @@ main(int argc, char **argv)
         gndo->ndo_Oflag=1;
        gndo->ndo_Rflag=1;
        gndo->ndo_dlt=-1;
-       gndo->ndo_default_print=ndo_default_print;
-       gndo->ndo_printf=tcpdump_printf;
-       gndo->ndo_error=ndo_error;
-       gndo->ndo_warning=ndo_warning;
+       ndo_set_function_pointers(gndo);
        gndo->ndo_snaplen = DEFAULT_SNAPLEN;
        gndo->ndo_immediate = 0;
 
@@ -1439,7 +1165,7 @@ main(int argc, char **argv)
 
        case 0: /* Default */
        case 4: /* Default + Date*/
-               thiszone = gmt2local(0);
+               timezone_offset = gmt2local(0);
                break;
 
        case 1: /* No time stamp */
@@ -1750,8 +1476,7 @@ main(int argc, char **argv)
                free(cmdbuf);
                exit(0);
        }
-       init_addrtoname(gndo, localnet, netmask);
-        init_checksum();
+       init_print(localnet, netmask, timezone_offset);
 
 #ifndef WIN32
        (void)setsignal(SIGPIPE, cleanup);
@@ -2407,94 +2132,14 @@ print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
 {
        struct print_info *print_info;
        u_int hdrlen;
-        netdissect_options *ndo;
 
        ++packets_captured;
 
        ++infodelay;
 
        print_info = (struct print_info *)user;
-        ndo = print_info->ndo;
-
-       if(ndo->ndo_packet_number)
-               ND_PRINT((ndo, "%5u  ", packets_captured));
-
-       ts_print(ndo, &h->ts);
-
-       /*
-        * Some printers want to check that they're not walking off the
-        * end of the packet.
-        * Rather than pass it all the way down, we set this member
-        * of the netdissect_options structure.
-        */
-       ndo->ndo_snapend = sp + h->caplen;
-
-        hdrlen = (*print_info->printer)(print_info->ndo, h, sp);
-
-       /*
-        * Restore the original snapend, as a printer might have
-        * changed it.
-        */
-       ndo->ndo_snapend = sp + h->caplen;
-       if (ndo->ndo_Xflag) {
-               /*
-                * Print the raw packet data in hex and ASCII.
-                */
-               if (ndo->ndo_Xflag > 1) {
-                       /*
-                        * Include the link-layer header.
-                        */
-                       hex_and_ascii_print(ndo, "\n\t", sp, h->caplen);
-               } else {
-                       /*
-                        * Don't include the link-layer header - and if
-                        * we have nothing past the link-layer header,
-                        * print nothing.
-                        */
-                       if (h->caplen > hdrlen)
-                               hex_and_ascii_print(ndo, "\n\t", sp + hdrlen,
-                                   h->caplen - hdrlen);
-               }
-       } else if (ndo->ndo_xflag) {
-               /*
-                * Print the raw packet data in hex.
-                */
-               if (ndo->ndo_xflag > 1) {
-                       /*
-                        * Include the link-layer header.
-                        */
-                        hex_print(ndo, "\n\t", sp, h->caplen);
-               } else {
-                       /*
-                        * Don't include the link-layer header - and if
-                        * we have nothing past the link-layer header,
-                        * print nothing.
-                        */
-                       if (h->caplen > hdrlen)
-                               hex_print(ndo, "\n\t", sp + hdrlen,
-                                          h->caplen - hdrlen);
-               }
-       } else if (ndo->ndo_Aflag) {
-               /*
-                * Print the raw packet data in ASCII.
-                */
-               if (ndo->ndo_Aflag > 1) {
-                       /*
-                        * Include the link-layer header.
-                        */
-                       ascii_print(ndo, sp, h->caplen);
-               } else {
-                       /*
-                        * Don't include the link-layer header - and if
-                        * we have nothing past the link-layer header,
-                        * print nothing.
-                        */
-                       if (h->caplen > hdrlen)
-                               ascii_print(ndo, sp + hdrlen, h->caplen - hdrlen);
-               }
-       }
 
-       putchar('\n');
+       pretty_print_packet(print_info, h, sp, packets_captured);
 
        --infodelay;
        if (infoprint)
@@ -2528,15 +2173,6 @@ print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
        char Wpcap_version[]="3.1";
 #endif
 
-/*
- * By default, print the specified data out in hex and ASCII.
- */
-static void
-ndo_default_print(netdissect_options *ndo, const u_char *bp, u_int length)
-{
-       hex_and_ascii_print(ndo, "\n\t", bp, length); /* pass on lf and indentation string */
-}
-
 #ifdef SIGNAL_REQ_INFO
 RETSIGTYPE requestinfo(int signo _U_)
 {
@@ -2640,44 +2276,6 @@ print_usage(void)
        (void)fprintf(stderr,
 "\t\t[ -Z user ] [ expression ]\n");
 }
-
-
-
-/* VARARGS */
-static void
-ndo_error(netdissect_options *ndo _U_, 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(1);
-       /* NOTREACHED */
-}
-
-/* VARARGS */
-static void
-ndo_warning(netdissect_options *ndo _U_, 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);
-       }
-}
 /*
  * Local Variables:
  * c-style: whitesmith
diff --git a/util-print.c b/util-print.c
new file mode 100644 (file)
index 0000000..4909c64
--- /dev/null
@@ -0,0 +1,777 @@
+/*
+ * Copyright (c) 1990, 1991, 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.
+ */
+
+/*
+ * txtproto_print() derived from original code by Hannes Gredler
+ *
+ * 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, and (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.
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <tcpdump-stdinc.h>
+
+#include <sys/stat.h>
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "interface.h"
+
+int32_t thiszone;              /* seconds offset from gmt to local time */
+
+/*
+ * Print out a null-terminated filename (or other ascii string).
+ * If ep is NULL, assume no truncation check is needed.
+ * Return true if truncated.
+ */
+int
+fn_print(netdissect_options *ndo,
+         register const u_char *s, register const u_char *ep)
+{
+       register int ret;
+       register u_char c;
+
+       ret = 1;                        /* assume truncated */
+       while (ep == NULL || s < ep) {
+               c = *s++;
+               if (c == '\0') {
+                       ret = 0;
+                       break;
+               }
+               if (!ND_ISASCII(c)) {
+                       c = ND_TOASCII(c);
+                       ND_PRINT((ndo, "M-"));
+               }
+               if (!ND_ISPRINT(c)) {
+                       c ^= 0x40;      /* DEL to ?, others to alpha */
+                       ND_PRINT((ndo, "^"));
+               }
+               ND_PRINT((ndo, "%c", c));
+       }
+       return(ret);
+}
+
+/*
+ * Print out a counted filename (or other ascii string).
+ * If ep is NULL, assume no truncation check is needed.
+ * Return true if truncated.
+ */
+int
+fn_printn(netdissect_options *ndo,
+          register const u_char *s, register u_int n, register const u_char *ep)
+{
+       register u_char c;
+
+       while (n > 0 && (ep == NULL || s < ep)) {
+               n--;
+               c = *s++;
+               if (!ND_ISASCII(c)) {
+                       c = ND_TOASCII(c);
+                       ND_PRINT((ndo, "M-"));
+               }
+               if (!ND_ISPRINT(c)) {
+                       c ^= 0x40;      /* DEL to ?, others to alpha */
+                       ND_PRINT((ndo, "^"));
+               }
+               ND_PRINT((ndo, "%c", c));
+       }
+       return (n == 0) ? 0 : 1;
+}
+
+/*
+ * Print out a null-padded filename (or other ascii string).
+ * If ep is NULL, assume no truncation check is needed.
+ * Return true if truncated.
+ */
+int
+fn_printzp(netdissect_options *ndo,
+           register const u_char *s, register u_int n,
+           register const u_char *ep)
+{
+       register int ret;
+       register u_char c;
+
+       ret = 1;                        /* assume truncated */
+       while (n > 0 && (ep == NULL || s < ep)) {
+               n--;
+               c = *s++;
+               if (c == '\0') {
+                       ret = 0;
+                       break;
+               }
+               if (!ND_ISASCII(c)) {
+                       c = ND_TOASCII(c);
+                       ND_PRINT((ndo, "M-"));
+               }
+               if (!ND_ISPRINT(c)) {
+                       c ^= 0x40;      /* DEL to ?, others to alpha */
+                       ND_PRINT((ndo, "^"));
+               }
+               ND_PRINT((ndo, "%c", c));
+       }
+       return (n == 0) ? 0 : ret;
+}
+
+/*
+ * Format the timestamp
+ */
+static char *
+ts_format(netdissect_options *ndo
+#ifndef HAVE_PCAP_SET_TSTAMP_PRECISION
+_U_
+#endif
+, int sec, int usec)
+{
+       static char buf[sizeof("00:00:00.000000000")];
+       const char *format;
+
+#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
+       switch (ndo->ndo_tstamp_precision) {
+
+       case PCAP_TSTAMP_PRECISION_MICRO:
+               format = "%02d:%02d:%02d.%06u";
+               break;
+
+       case PCAP_TSTAMP_PRECISION_NANO:
+               format = "%02d:%02d:%02d.%09u";
+               break;
+
+       default:
+               format = "%02d:%02d:%02d.{unknown precision}";
+               break;
+       }
+#else
+       format = "%02d:%02d:%02d.%06u";
+#endif
+
+       snprintf(buf, sizeof(buf), format,
+                 sec / 3600, (sec % 3600) / 60, sec % 60, usec);
+
+        return buf;
+}
+
+/*
+ * Print the timestamp
+ */
+void
+ts_print(netdissect_options *ndo,
+         register const struct timeval *tvp)
+{
+       register int s;
+       struct tm *tm;
+       time_t Time;
+       static unsigned b_sec;
+       static unsigned b_usec;
+       int d_usec;
+       int d_sec;
+
+       switch (ndo->ndo_tflag) {
+
+       case 0: /* Default */
+               s = (tvp->tv_sec + thiszone) % 86400;
+               ND_PRINT((ndo, "%s ", ts_format(ndo, s, tvp->tv_usec)));
+               break;
+
+       case 1: /* No time stamp */
+               break;
+
+       case 2: /* Unix timeval style */
+               ND_PRINT((ndo, "%u.%06u ",
+                            (unsigned)tvp->tv_sec,
+                            (unsigned)tvp->tv_usec));
+               break;
+
+       case 3: /* Microseconds since previous packet */
+        case 5: /* Microseconds since first packet */
+               if (b_sec == 0) {
+                        /* init timestamp for first packet */
+                        b_usec = tvp->tv_usec;
+                        b_sec = tvp->tv_sec;
+                }
+
+                d_usec = tvp->tv_usec - b_usec;
+                d_sec = tvp->tv_sec - b_sec;
+
+                while (d_usec < 0) {
+                    d_usec += 1000000;
+                    d_sec--;
+                }
+
+                ND_PRINT((ndo, "%s ", ts_format(ndo, d_sec, d_usec)));
+
+                if (ndo->ndo_tflag == 3) { /* set timestamp for last packet */
+                    b_sec = tvp->tv_sec;
+                    b_usec = tvp->tv_usec;
+                }
+               break;
+
+       case 4: /* Default + Date*/
+               s = (tvp->tv_sec + thiszone) % 86400;
+               Time = (tvp->tv_sec + thiszone) - s;
+               tm = gmtime (&Time);
+               if (!tm)
+                       ND_PRINT((ndo, "Date fail  "));
+               else
+                       ND_PRINT((ndo, "%04d-%02d-%02d %s ",
+                               tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
+                               ts_format(ndo, s, tvp->tv_usec)));
+               break;
+       }
+}
+
+/*
+ * Print a relative number of seconds (e.g. hold time, prune timer)
+ * in the form 5m1s.  This does no truncation, so 32230861 seconds
+ * is represented as 1y1w1d1h1m1s.
+ */
+void
+relts_print(netdissect_options *ndo,
+            int secs)
+{
+       static const char *lengths[] = {"y", "w", "d", "h", "m", "s"};
+       static const int seconds[] = {31536000, 604800, 86400, 3600, 60, 1};
+       const char **l = lengths;
+       const int *s = seconds;
+
+       if (secs == 0) {
+               ND_PRINT((ndo, "0s"));
+               return;
+       }
+       if (secs < 0) {
+               ND_PRINT((ndo, "-"));
+               secs = -secs;
+       }
+       while (secs > 0) {
+               if (secs >= *s) {
+                       ND_PRINT((ndo, "%d%s", secs / *s, *l));
+                       secs -= (secs / *s) * *s;
+               }
+               s++;
+               l++;
+       }
+}
+
+/*
+ *  this is a generic routine for printing unknown data;
+ *  we pass on the linefeed plus indentation string to
+ *  get a proper output - returns 0 on error
+ */
+
+int
+print_unknown_data(netdissect_options *ndo, const u_char *cp,const char *ident,int len)
+{
+       if (len < 0) {
+          ND_PRINT((ndo,"%sDissector error: print_unknown_data called with negative length",
+                   ident));
+               return(0);
+       }
+       if (ndo->ndo_snapend - cp < len)
+               len = ndo->ndo_snapend - cp;
+       if (len < 0) {
+          ND_PRINT((ndo,"%sDissector error: print_unknown_data called with pointer past end of packet",
+                   ident));
+               return(0);
+       }
+        hex_print(ndo, ident,cp,len);
+       return(1); /* everything is ok */
+}
+
+/*
+ * Convert a token value to a string; use "fmt" if not found.
+ */
+const char *
+tok2strbuf(register const struct tok *lp, register const char *fmt,
+          register u_int v, char *buf, size_t bufsize)
+{
+       if (lp != NULL) {
+               while (lp->s != NULL) {
+                       if (lp->v == v)
+                               return (lp->s);
+                       ++lp;
+               }
+       }
+       if (fmt == NULL)
+               fmt = "#%d";
+
+       (void)snprintf(buf, bufsize, fmt, v);
+       return (const char *)buf;
+}
+
+/*
+ * Convert a token value to a string; use "fmt" if not found.
+ */
+const char *
+tok2str(register const struct tok *lp, register const char *fmt,
+       register int v)
+{
+       static char buf[4][128];
+       static int idx = 0;
+       char *ret;
+
+       ret = buf[idx];
+       idx = (idx+1) & 3;
+       return tok2strbuf(lp, fmt, v, ret, sizeof(buf[0]));
+}
+
+/*
+ * Convert a bit token value to a string; use "fmt" if not found.
+ * this is useful for parsing bitfields, the output strings are seperated
+ * if the s field is positive.
+ */
+static char *
+bittok2str_internal(register const struct tok *lp, register const char *fmt,
+          register int v, register int sep)
+{
+        static char buf[256]; /* our stringbuffer */
+        int buflen=0;
+        register int rotbit; /* this is the bit we rotate through all bitpositions */
+        register int tokval;
+        const char * sepstr = "";
+
+       while (lp != NULL && lp->s != NULL) {
+            tokval=lp->v;   /* load our first value */
+            rotbit=1;
+            while (rotbit != 0) {
+                /*
+                 * lets AND the rotating bit with our token value
+                 * and see if we have got a match
+                 */
+               if (tokval == (v&rotbit)) {
+                    /* ok we have found something */
+                    buflen+=snprintf(buf+buflen, sizeof(buf)-buflen, "%s%s",
+                                     sepstr, lp->s);
+                    sepstr = sep ? ", " : "";
+                    break;
+                }
+                rotbit=rotbit<<1; /* no match - lets shift and try again */
+            }
+            lp++;
+       }
+
+        if (buflen == 0)
+            /* bummer - lets print the "unknown" message as advised in the fmt string if we got one */
+            (void)snprintf(buf, sizeof(buf), fmt == NULL ? "#%d" : fmt, v);
+        return (buf);
+}
+
+/*
+ * Convert a bit token value to a string; use "fmt" if not found.
+ * this is useful for parsing bitfields, the output strings are not seperated.
+ */
+char *
+bittok2str_nosep(register const struct tok *lp, register const char *fmt,
+          register int v)
+{
+    return (bittok2str_internal(lp, fmt, v, 0));
+}
+
+/*
+ * Convert a bit token value to a string; use "fmt" if not found.
+ * this is useful for parsing bitfields, the output strings are comma seperated.
+ */
+char *
+bittok2str(register const struct tok *lp, register const char *fmt,
+          register int v)
+{
+    return (bittok2str_internal(lp, fmt, v, 1));
+}
+
+/*
+ * Convert a value to a string using an array; the macro
+ * tok2strary() in <interface.h> is the public interface to
+ * this function and ensures that the second argument is
+ * correct for bounds-checking.
+ */
+const char *
+tok2strary_internal(register const char **lp, int n, register const char *fmt,
+       register int v)
+{
+       static char buf[128];
+
+       if (v >= 0 && v < n && lp[v] != NULL)
+               return lp[v];
+       if (fmt == NULL)
+               fmt = "#%d";
+       (void)snprintf(buf, sizeof(buf), fmt, v);
+       return (buf);
+}
+
+/*
+ * Convert a 32-bit netmask to prefixlen if possible
+ * the function returns the prefix-len; if plen == -1
+ * then conversion was not possible;
+ */
+
+int
+mask2plen(uint32_t mask)
+{
+       uint32_t bitmasks[33] = {
+               0x00000000,
+               0x80000000, 0xc0000000, 0xe0000000, 0xf0000000,
+               0xf8000000, 0xfc000000, 0xfe000000, 0xff000000,
+               0xff800000, 0xffc00000, 0xffe00000, 0xfff00000,
+               0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000,
+               0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000,
+               0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00,
+               0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0,
+               0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff
+       };
+       int prefix_len = 32;
+
+       /* let's see if we can transform the mask into a prefixlen */
+       while (prefix_len >= 0) {
+               if (bitmasks[prefix_len] == mask)
+                       break;
+               prefix_len--;
+       }
+       return (prefix_len);
+}
+
+#ifdef INET6
+int
+mask62plen(const u_char *mask)
+{
+       u_char bitmasks[9] = {
+               0x00,
+               0x80, 0xc0, 0xe0, 0xf0,
+               0xf8, 0xfc, 0xfe, 0xff
+       };
+       int byte;
+       int cidr_len = 0;
+
+       for (byte = 0; byte < 16; byte++) {
+               u_int bits;
+
+               for (bits = 0; bits < (sizeof (bitmasks) / sizeof (bitmasks[0])); bits++) {
+                       if (mask[byte] == bitmasks[bits]) {
+                               cidr_len += bits;
+                               break;
+                       }
+               }
+
+               if (mask[byte] != 0xff)
+                       break;
+       }
+       return (cidr_len);
+}
+#endif /* INET6 */
+
+/*
+ * Routine to print out information for text-based protocols such as FTP,
+ * HTTP, SMTP, RTSP, SIP, ....
+ */
+#define MAX_TOKEN      128
+
+/*
+ * Fetch a token from a packet, starting at the specified index,
+ * and return the length of the token.
+ *
+ * Returns 0 on error; yes, this is indistinguishable from an empty
+ * token, but an "empty token" isn't a valid token - it just means
+ * either a space character at the beginning of the line (this
+ * includes a blank line) or no more tokens remaining on the line.
+ */
+static int
+fetch_token(netdissect_options *ndo, const u_char *pptr, u_int idx, u_int len,
+    u_char *tbuf, size_t tbuflen)
+{
+       size_t toklen = 0;
+
+       for (; idx < len; idx++) {
+               if (!ND_TTEST(*(pptr + idx))) {
+                       /* ran past end of captured data */
+                       return (0);
+               }
+               if (!isascii(*(pptr + idx))) {
+                       /* not an ASCII character */
+                       return (0);
+               }
+               if (isspace(*(pptr + idx))) {
+                       /* end of token */
+                       break;
+               }
+               if (!isprint(*(pptr + idx))) {
+                       /* not part of a command token or response code */
+                       return (0);
+               }
+               if (toklen + 2 > tbuflen) {
+                       /* no room for this character and terminating '\0' */
+                       return (0);
+               }
+               tbuf[toklen] = *(pptr + idx);
+               toklen++;
+       }
+       if (toklen == 0) {
+               /* no token */
+               return (0);
+       }
+       tbuf[toklen] = '\0';
+
+       /*
+        * Skip past any white space after the token, until we see
+        * an end-of-line (CR or LF).
+        */
+       for (; idx < len; idx++) {
+               if (!ND_TTEST(*(pptr + idx))) {
+                       /* ran past end of captured data */
+                       break;
+               }
+               if (*(pptr + idx) == '\r' || *(pptr + idx) == '\n') {
+                       /* end of line */
+                       break;
+               }
+               if (!isascii(*(pptr + idx)) || !isprint(*(pptr + idx))) {
+                       /* not a printable ASCII character */
+                       break;
+               }
+               if (!isspace(*(pptr + idx))) {
+                       /* beginning of next token */
+                       break;
+               }
+       }
+       return (idx);
+}
+
+/*
+ * Scan a buffer looking for a line ending - LF or CR-LF.
+ * Return the index of the character after the line ending or 0 if
+ * we encounter a non-ASCII or non-printable character or don't find
+ * the line ending.
+ */
+static u_int
+print_txt_line(netdissect_options *ndo, const char *protoname,
+    const char *prefix, const u_char *pptr, u_int idx, u_int len)
+{
+       u_int startidx;
+       u_int linelen;
+
+       startidx = idx;
+       while (idx < len) {
+               ND_TCHECK(*(pptr+idx));
+               if (*(pptr+idx) == '\n') {
+                       /*
+                        * LF without CR; end of line.
+                        * Skip the LF and print the line, with the
+                        * exception of the LF.
+                        */
+                       linelen = idx - startidx;
+                       idx++;
+                       goto print;
+               } else if (*(pptr+idx) == '\r') {
+                       /* CR - any LF? */
+                       if ((idx+1) >= len) {
+                               /* not in this packet */
+                               return (0);
+                       }
+                       ND_TCHECK(*(pptr+idx+1));
+                       if (*(pptr+idx+1) == '\n') {
+                               /*
+                                * CR-LF; end of line.
+                                * Skip the CR-LF and print the line, with
+                                * the exception of the CR-LF.
+                                */
+                               linelen = idx - startidx;
+                               idx += 2;
+                               goto print;
+                       }
+
+                       /*
+                        * CR followed by something else; treat this
+                        * as if it were binary data, and don't print
+                        * it.
+                        */
+                       return (0);
+               } else if (!isascii(*(pptr+idx)) ||
+                   (!isprint(*(pptr+idx)) && *(pptr+idx) != '\t')) {
+                       /*
+                        * Not a printable ASCII character and not a tab;
+                        * treat this as if it were binary data, and
+                        * don't print it.
+                        */
+                       return (0);
+               }
+               idx++;
+       }
+
+       /*
+        * All printable ASCII, but no line ending after that point
+        * in the buffer; treat this as if it were truncated.
+        */
+trunc:
+       linelen = idx - startidx;
+       ND_PRINT((ndo, "%s%.*s[!%s]", prefix, (int)linelen, pptr + startidx,
+           protoname));
+       return (0);
+
+print:
+       ND_PRINT((ndo, "%s%.*s", prefix, (int)linelen, pptr + startidx));
+       return (idx);
+}
+
+void
+txtproto_print(netdissect_options *ndo, const u_char *pptr, u_int len,
+    const char *protoname, const char **cmds, u_int flags)
+{
+       u_int idx, eol;
+       u_char token[MAX_TOKEN+1];
+       const char *cmd;
+       int is_reqresp = 0;
+       const char *pnp;
+
+       if (cmds != NULL) {
+               /*
+                * This protocol has more than just request and
+                * response lines; see whether this looks like a
+                * request or response.
+                */
+               idx = fetch_token(ndo, pptr, 0, len, token, sizeof(token));
+               if (idx != 0) {
+                       /* Is this a valid request name? */
+                       while ((cmd = *cmds++) != NULL) {
+                               if (strcasecmp((const char *)token, cmd) == 0) {
+                                       /* Yes. */
+                                       is_reqresp = 1;
+                                       break;
+                               }
+                       }
+
+                       /*
+                        * No - is this a valid response code (3 digits)?
+                        *
+                        * Is this token the response code, or is the next
+                        * token the response code?
+                        */
+                       if (flags & RESP_CODE_SECOND_TOKEN) {
+                               /*
+                                * Next token - get it.
+                                */
+                               idx = fetch_token(ndo, pptr, idx, len, token,
+                                   sizeof(token));
+                       }
+                       if (idx != 0) {
+                               if (isdigit(token[0]) && isdigit(token[1]) &&
+                                   isdigit(token[2]) && token[3] == '\0') {
+                                       /* Yes. */
+                                       is_reqresp = 1;
+                               }
+                       }
+               }
+       } else {
+               /*
+                * This protocol has only request and response lines
+                * (e.g., FTP, where all the data goes over a
+                * different connection); assume the payload is
+                * a request or response.
+                */
+               is_reqresp = 1;
+       }
+
+       /* Capitalize the protocol name */
+       for (pnp = protoname; *pnp != '\0'; pnp++)
+               ND_PRINT((ndo, "%c", toupper(*pnp)));
+
+       if (is_reqresp) {
+               /*
+                * In non-verbose mode, just print the protocol, followed
+                * by the first line as the request or response info.
+                *
+                * In verbose mode, print lines as text until we run out
+                * of characters or see something that's not a
+                * printable-ASCII line.
+                */
+               if (ndo->ndo_vflag) {
+                       /*
+                        * We're going to print all the text lines in the
+                        * request or response; just print the length
+                        * on the first line of the output.
+                        */
+                       ND_PRINT((ndo, ", length: %u", len));
+                       for (idx = 0;
+                           idx < len && (eol = print_txt_line(ndo, protoname, "\n\t", pptr, idx, len)) != 0;
+                           idx = eol)
+                               ;
+               } else {
+                       /*
+                        * Just print the first text line.
+                        */
+                       print_txt_line(ndo, protoname, ": ", pptr, 0, len);
+               }
+       }
+}
+
+void
+safeputs(netdissect_options *ndo,
+         const u_char *s, const u_int maxlen)
+{
+       u_int idx = 0;
+
+       while (*s && idx < maxlen) {
+               safeputchar(ndo, *s);
+               idx++;
+               s++;
+       }
+}
+
+void
+safeputchar(netdissect_options *ndo,
+            const u_char c)
+{
+       ND_PRINT((ndo, (c < 0x80 && ND_ISPRINT(c)) ? "%c" : "\\0x%02x", c));
+}
+
+#ifdef LBL_ALIGN
+/*
+ * Some compilers try to optimize memcpy(), using the alignment constraint
+ * on the argument pointer type.  by using this function, we try to avoid the
+ * optimization.
+ */
+void
+unaligned_memcpy(void *p, const void *q, size_t l)
+{
+       memcpy(p, q, l);
+}
+
+/* As with memcpy(), so with memcmp(). */
+int
+unaligned_memcmp(const void *p, const void *q, size_t l)
+{
+       return (memcmp(p, q, l));
+}
+#endif
+
diff --git a/util.c b/util.c
index 03da7725330dc2824e34e15aa34c35a59e02a2ca..4a20a4b50c412b4684b6cb921db9f8e327711fb6 100644 (file)
--- a/util.c
+++ b/util.c
 
 #include "interface.h"
 
-/*
- * Print out a null-terminated filename (or other ascii string).
- * If ep is NULL, assume no truncation check is needed.
- * Return true if truncated.
- */
-int
-fn_print(netdissect_options *ndo,
-         register const u_char *s, register const u_char *ep)
-{
-       register int ret;
-       register u_char c;
-
-       ret = 1;                        /* assume truncated */
-       while (ep == NULL || s < ep) {
-               c = *s++;
-               if (c == '\0') {
-                       ret = 0;
-                       break;
-               }
-               if (!ND_ISASCII(c)) {
-                       c = ND_TOASCII(c);
-                       ND_PRINT((ndo, "M-"));
-               }
-               if (!ND_ISPRINT(c)) {
-                       c ^= 0x40;      /* DEL to ?, others to alpha */
-                       ND_PRINT((ndo, "^"));
-               }
-               ND_PRINT((ndo, "%c", c));
-       }
-       return(ret);
-}
-
-/*
- * Print out a counted filename (or other ascii string).
- * If ep is NULL, assume no truncation check is needed.
- * Return true if truncated.
- */
-int
-fn_printn(netdissect_options *ndo,
-          register const u_char *s, register u_int n, register const u_char *ep)
-{
-       register u_char c;
-
-       while (n > 0 && (ep == NULL || s < ep)) {
-               n--;
-               c = *s++;
-               if (!ND_ISASCII(c)) {
-                       c = ND_TOASCII(c);
-                       ND_PRINT((ndo, "M-"));
-               }
-               if (!ND_ISPRINT(c)) {
-                       c ^= 0x40;      /* DEL to ?, others to alpha */
-                       ND_PRINT((ndo, "^"));
-               }
-               ND_PRINT((ndo, "%c", c));
-       }
-       return (n == 0) ? 0 : 1;
-}
-
-/*
- * Print out a null-padded filename (or other ascii string).
- * If ep is NULL, assume no truncation check is needed.
- * Return true if truncated.
- */
-int
-fn_printzp(netdissect_options *ndo,
-           register const u_char *s, register u_int n,
-           register const u_char *ep)
-{
-       register int ret;
-       register u_char c;
-
-       ret = 1;                        /* assume truncated */
-       while (n > 0 && (ep == NULL || s < ep)) {
-               n--;
-               c = *s++;
-               if (c == '\0') {
-                       ret = 0;
-                       break;
-               }
-               if (!ND_ISASCII(c)) {
-                       c = ND_TOASCII(c);
-                       ND_PRINT((ndo, "M-"));
-               }
-               if (!ND_ISPRINT(c)) {
-                       c ^= 0x40;      /* DEL to ?, others to alpha */
-                       ND_PRINT((ndo, "^"));
-               }
-               ND_PRINT((ndo, "%c", c));
-       }
-       return (n == 0) ? 0 : ret;
-}
-
-/*
- * Format the timestamp
- */
-static char *
-ts_format(netdissect_options *ndo
-#ifndef HAVE_PCAP_SET_TSTAMP_PRECISION
-_U_
-#endif
-, int sec, int usec)
-{
-       static char buf[sizeof("00:00:00.000000000")];
-       const char *format;
-
-#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
-       switch (ndo->ndo_tstamp_precision) {
-
-       case PCAP_TSTAMP_PRECISION_MICRO:
-               format = "%02d:%02d:%02d.%06u";
-               break;
-
-       case PCAP_TSTAMP_PRECISION_NANO:
-               format = "%02d:%02d:%02d.%09u";
-               break;
-
-       default:
-               format = "%02d:%02d:%02d.{unknown precision}";
-               break;
-       }
-#else
-       format = "%02d:%02d:%02d.%06u";
-#endif
-
-       snprintf(buf, sizeof(buf), format,
-                 sec / 3600, (sec % 3600) / 60, sec % 60, usec);
-
-        return buf;
-}
-
-/*
- * Print the timestamp
- */
-void
-ts_print(netdissect_options *ndo,
-         register const struct timeval *tvp)
-{
-       register int s;
-       struct tm *tm;
-       time_t Time;
-       static unsigned b_sec;
-       static unsigned b_usec;
-       int d_usec;
-       int d_sec;
-
-       switch (ndo->ndo_tflag) {
-
-       case 0: /* Default */
-               s = (tvp->tv_sec + thiszone) % 86400;
-               ND_PRINT((ndo, "%s ", ts_format(ndo, s, tvp->tv_usec)));
-               break;
-
-       case 1: /* No time stamp */
-               break;
-
-       case 2: /* Unix timeval style */
-               ND_PRINT((ndo, "%u.%06u ",
-                            (unsigned)tvp->tv_sec,
-                            (unsigned)tvp->tv_usec));
-               break;
-
-       case 3: /* Microseconds since previous packet */
-        case 5: /* Microseconds since first packet */
-               if (b_sec == 0) {
-                        /* init timestamp for first packet */
-                        b_usec = tvp->tv_usec;
-                        b_sec = tvp->tv_sec;
-                }
-
-                d_usec = tvp->tv_usec - b_usec;
-                d_sec = tvp->tv_sec - b_sec;
-
-                while (d_usec < 0) {
-                    d_usec += 1000000;
-                    d_sec--;
-                }
-
-                ND_PRINT((ndo, "%s ", ts_format(ndo, d_sec, d_usec)));
-
-                if (ndo->ndo_tflag == 3) { /* set timestamp for last packet */
-                    b_sec = tvp->tv_sec;
-                    b_usec = tvp->tv_usec;
-                }
-               break;
-
-       case 4: /* Default + Date*/
-               s = (tvp->tv_sec + thiszone) % 86400;
-               Time = (tvp->tv_sec + thiszone) - s;
-               tm = gmtime (&Time);
-               if (!tm)
-                       ND_PRINT((ndo, "Date fail  "));
-               else
-                       ND_PRINT((ndo, "%04d-%02d-%02d %s ",
-                               tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
-                               ts_format(ndo, s, tvp->tv_usec)));
-               break;
-       }
-}
-
-/*
- * Print a relative number of seconds (e.g. hold time, prune timer)
- * in the form 5m1s.  This does no truncation, so 32230861 seconds
- * is represented as 1y1w1d1h1m1s.
- */
-void
-relts_print(netdissect_options *ndo,
-            int secs)
-{
-       static const char *lengths[] = {"y", "w", "d", "h", "m", "s"};
-       static const int seconds[] = {31536000, 604800, 86400, 3600, 60, 1};
-       const char **l = lengths;
-       const int *s = seconds;
-
-       if (secs == 0) {
-               ND_PRINT((ndo, "0s"));
-               return;
-       }
-       if (secs < 0) {
-               ND_PRINT((ndo, "-"));
-               secs = -secs;
-       }
-       while (secs > 0) {
-               if (secs >= *s) {
-                       ND_PRINT((ndo, "%d%s", secs / *s, *l));
-                       secs -= (secs / *s) * *s;
-               }
-               s++;
-               l++;
-       }
-}
-
-/*
- *  this is a generic routine for printing unknown data;
- *  we pass on the linefeed plus indentation string to
- *  get a proper output - returns 0 on error
- */
-
-int
-print_unknown_data(netdissect_options *ndo, const u_char *cp,const char *ident,int len)
-{
-       if (len < 0) {
-          ND_PRINT((ndo,"%sDissector error: print_unknown_data called with negative length",
-                   ident));
-               return(0);
-       }
-       if (ndo->ndo_snapend - cp < len)
-               len = ndo->ndo_snapend - cp;
-       if (len < 0) {
-          ND_PRINT((ndo,"%sDissector error: print_unknown_data called with pointer past end of packet",
-                   ident));
-               return(0);
-       }
-        hex_print(ndo, ident,cp,len);
-       return(1); /* everything is ok */
-}
-
-/*
- * Convert a token value to a string; use "fmt" if not found.
- */
-const char *
-tok2strbuf(register const struct tok *lp, register const char *fmt,
-          register u_int v, char *buf, size_t bufsize)
-{
-       if (lp != NULL) {
-               while (lp->s != NULL) {
-                       if (lp->v == v)
-                               return (lp->s);
-                       ++lp;
-               }
-       }
-       if (fmt == NULL)
-               fmt = "#%d";
-
-       (void)snprintf(buf, bufsize, fmt, v);
-       return (const char *)buf;
-}
-
-/*
- * Convert a token value to a string; use "fmt" if not found.
- */
-const char *
-tok2str(register const struct tok *lp, register const char *fmt,
-       register int v)
-{
-       static char buf[4][128];
-       static int idx = 0;
-       char *ret;
-
-       ret = buf[idx];
-       idx = (idx+1) & 3;
-       return tok2strbuf(lp, fmt, v, ret, sizeof(buf[0]));
-}
-
-/*
- * Convert a bit token value to a string; use "fmt" if not found.
- * this is useful for parsing bitfields, the output strings are seperated
- * if the s field is positive.
- */
-static char *
-bittok2str_internal(register const struct tok *lp, register const char *fmt,
-          register int v, register int sep)
-{
-        static char buf[256]; /* our stringbuffer */
-        int buflen=0;
-        register int rotbit; /* this is the bit we rotate through all bitpositions */
-        register int tokval;
-        const char * sepstr = "";
-
-       while (lp != NULL && lp->s != NULL) {
-            tokval=lp->v;   /* load our first value */
-            rotbit=1;
-            while (rotbit != 0) {
-                /*
-                 * lets AND the rotating bit with our token value
-                 * and see if we have got a match
-                 */
-               if (tokval == (v&rotbit)) {
-                    /* ok we have found something */
-                    buflen+=snprintf(buf+buflen, sizeof(buf)-buflen, "%s%s",
-                                     sepstr, lp->s);
-                    sepstr = sep ? ", " : "";
-                    break;
-                }
-                rotbit=rotbit<<1; /* no match - lets shift and try again */
-            }
-            lp++;
-       }
-
-        if (buflen == 0)
-            /* bummer - lets print the "unknown" message as advised in the fmt string if we got one */
-            (void)snprintf(buf, sizeof(buf), fmt == NULL ? "#%d" : fmt, v);
-        return (buf);
-}
-
-/*
- * Convert a bit token value to a string; use "fmt" if not found.
- * this is useful for parsing bitfields, the output strings are not seperated.
- */
-char *
-bittok2str_nosep(register const struct tok *lp, register const char *fmt,
-          register int v)
-{
-    return (bittok2str_internal(lp, fmt, v, 0));
-}
-
-/*
- * Convert a bit token value to a string; use "fmt" if not found.
- * this is useful for parsing bitfields, the output strings are comma seperated.
- */
-char *
-bittok2str(register const struct tok *lp, register const char *fmt,
-          register int v)
-{
-    return (bittok2str_internal(lp, fmt, v, 1));
-}
-
-/*
- * Convert a value to a string using an array; the macro
- * tok2strary() in <interface.h> is the public interface to
- * this function and ensures that the second argument is
- * correct for bounds-checking.
- */
-const char *
-tok2strary_internal(register const char **lp, int n, register const char *fmt,
-       register int v)
-{
-       static char buf[128];
-
-       if (v >= 0 && v < n && lp[v] != NULL)
-               return lp[v];
-       if (fmt == NULL)
-               fmt = "#%d";
-       (void)snprintf(buf, sizeof(buf), fmt, v);
-       return (buf);
-}
-
-/*
- * Convert a 32-bit netmask to prefixlen if possible
- * the function returns the prefix-len; if plen == -1
- * then conversion was not possible;
- */
-
-int
-mask2plen(uint32_t mask)
-{
-       uint32_t bitmasks[33] = {
-               0x00000000,
-               0x80000000, 0xc0000000, 0xe0000000, 0xf0000000,
-               0xf8000000, 0xfc000000, 0xfe000000, 0xff000000,
-               0xff800000, 0xffc00000, 0xffe00000, 0xfff00000,
-               0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000,
-               0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000,
-               0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00,
-               0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0,
-               0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff
-       };
-       int prefix_len = 32;
-
-       /* let's see if we can transform the mask into a prefixlen */
-       while (prefix_len >= 0) {
-               if (bitmasks[prefix_len] == mask)
-                       break;
-               prefix_len--;
-       }
-       return (prefix_len);
-}
-
-#ifdef INET6
-int
-mask62plen(const u_char *mask)
-{
-       u_char bitmasks[9] = {
-               0x00,
-               0x80, 0xc0, 0xe0, 0xf0,
-               0xf8, 0xfc, 0xfe, 0xff
-       };
-       int byte;
-       int cidr_len = 0;
-
-       for (byte = 0; byte < 16; byte++) {
-               u_int bits;
-
-               for (bits = 0; bits < (sizeof (bitmasks) / sizeof (bitmasks[0])); bits++) {
-                       if (mask[byte] == bitmasks[bits]) {
-                               cidr_len += bits;
-                               break;
-                       }
-               }
-
-               if (mask[byte] != 0xff)
-                       break;
-       }
-       return (cidr_len);
-}
-#endif /* INET6 */
-
-/*
- * Routine to print out information for text-based protocols such as FTP,
- * HTTP, SMTP, RTSP, SIP, ....
- */
-#define MAX_TOKEN      128
-
-/*
- * Fetch a token from a packet, starting at the specified index,
- * and return the length of the token.
- *
- * Returns 0 on error; yes, this is indistinguishable from an empty
- * token, but an "empty token" isn't a valid token - it just means
- * either a space character at the beginning of the line (this
- * includes a blank line) or no more tokens remaining on the line.
- */
-static int
-fetch_token(netdissect_options *ndo, const u_char *pptr, u_int idx, u_int len,
-    u_char *tbuf, size_t tbuflen)
-{
-       size_t toklen = 0;
-
-       for (; idx < len; idx++) {
-               if (!ND_TTEST(*(pptr + idx))) {
-                       /* ran past end of captured data */
-                       return (0);
-               }
-               if (!isascii(*(pptr + idx))) {
-                       /* not an ASCII character */
-                       return (0);
-               }
-               if (isspace(*(pptr + idx))) {
-                       /* end of token */
-                       break;
-               }
-               if (!isprint(*(pptr + idx))) {
-                       /* not part of a command token or response code */
-                       return (0);
-               }
-               if (toklen + 2 > tbuflen) {
-                       /* no room for this character and terminating '\0' */
-                       return (0);
-               }
-               tbuf[toklen] = *(pptr + idx);
-               toklen++;
-       }
-       if (toklen == 0) {
-               /* no token */
-               return (0);
-       }
-       tbuf[toklen] = '\0';
-
-       /*
-        * Skip past any white space after the token, until we see
-        * an end-of-line (CR or LF).
-        */
-       for (; idx < len; idx++) {
-               if (!ND_TTEST(*(pptr + idx))) {
-                       /* ran past end of captured data */
-                       break;
-               }
-               if (*(pptr + idx) == '\r' || *(pptr + idx) == '\n') {
-                       /* end of line */
-                       break;
-               }
-               if (!isascii(*(pptr + idx)) || !isprint(*(pptr + idx))) {
-                       /* not a printable ASCII character */
-                       break;
-               }
-               if (!isspace(*(pptr + idx))) {
-                       /* beginning of next token */
-                       break;
-               }
-       }
-       return (idx);
-}
-
-/*
- * Scan a buffer looking for a line ending - LF or CR-LF.
- * Return the index of the character after the line ending or 0 if
- * we encounter a non-ASCII or non-printable character or don't find
- * the line ending.
- */
-static u_int
-print_txt_line(netdissect_options *ndo, const char *protoname,
-    const char *prefix, const u_char *pptr, u_int idx, u_int len)
-{
-       u_int startidx;
-       u_int linelen;
-
-       startidx = idx;
-       while (idx < len) {
-               ND_TCHECK(*(pptr+idx));
-               if (*(pptr+idx) == '\n') {
-                       /*
-                        * LF without CR; end of line.
-                        * Skip the LF and print the line, with the
-                        * exception of the LF.
-                        */
-                       linelen = idx - startidx;
-                       idx++;
-                       goto print;
-               } else if (*(pptr+idx) == '\r') {
-                       /* CR - any LF? */
-                       if ((idx+1) >= len) {
-                               /* not in this packet */
-                               return (0);
-                       }
-                       ND_TCHECK(*(pptr+idx+1));
-                       if (*(pptr+idx+1) == '\n') {
-                               /*
-                                * CR-LF; end of line.
-                                * Skip the CR-LF and print the line, with
-                                * the exception of the CR-LF.
-                                */
-                               linelen = idx - startidx;
-                               idx += 2;
-                               goto print;
-                       }
-
-                       /*
-                        * CR followed by something else; treat this
-                        * as if it were binary data, and don't print
-                        * it.
-                        */
-                       return (0);
-               } else if (!isascii(*(pptr+idx)) ||
-                   (!isprint(*(pptr+idx)) && *(pptr+idx) != '\t')) {
-                       /*
-                        * Not a printable ASCII character and not a tab;
-                        * treat this as if it were binary data, and
-                        * don't print it.
-                        */
-                       return (0);
-               }
-               idx++;
-       }
-
-       /*
-        * All printable ASCII, but no line ending after that point
-        * in the buffer; treat this as if it were truncated.
-        */
-trunc:
-       linelen = idx - startidx;
-       ND_PRINT((ndo, "%s%.*s[!%s]", prefix, (int)linelen, pptr + startidx,
-           protoname));
-       return (0);
-
-print:
-       ND_PRINT((ndo, "%s%.*s", prefix, (int)linelen, pptr + startidx));
-       return (idx);
-}
-
-void
-txtproto_print(netdissect_options *ndo, const u_char *pptr, u_int len,
-    const char *protoname, const char **cmds, u_int flags)
-{
-       u_int idx, eol;
-       u_char token[MAX_TOKEN+1];
-       const char *cmd;
-       int is_reqresp = 0;
-       const char *pnp;
-
-       if (cmds != NULL) {
-               /*
-                * This protocol has more than just request and
-                * response lines; see whether this looks like a
-                * request or response.
-                */
-               idx = fetch_token(ndo, pptr, 0, len, token, sizeof(token));
-               if (idx != 0) {
-                       /* Is this a valid request name? */
-                       while ((cmd = *cmds++) != NULL) {
-                               if (strcasecmp((const char *)token, cmd) == 0) {
-                                       /* Yes. */
-                                       is_reqresp = 1;
-                                       break;
-                               }
-                       }
-
-                       /*
-                        * No - is this a valid response code (3 digits)?
-                        *
-                        * Is this token the response code, or is the next
-                        * token the response code?
-                        */
-                       if (flags & RESP_CODE_SECOND_TOKEN) {
-                               /*
-                                * Next token - get it.
-                                */
-                               idx = fetch_token(ndo, pptr, idx, len, token,
-                                   sizeof(token));
-                       }
-                       if (idx != 0) {
-                               if (isdigit(token[0]) && isdigit(token[1]) &&
-                                   isdigit(token[2]) && token[3] == '\0') {
-                                       /* Yes. */
-                                       is_reqresp = 1;
-                               }
-                       }
-               }
-       } else {
-               /*
-                * This protocol has only request and response lines
-                * (e.g., FTP, where all the data goes over a
-                * different connection); assume the payload is
-                * a request or response.
-                */
-               is_reqresp = 1;
-       }
-
-       /* Capitalize the protocol name */
-       for (pnp = protoname; *pnp != '\0'; pnp++)
-               ND_PRINT((ndo, "%c", toupper(*pnp)));
-
-       if (is_reqresp) {
-               /*
-                * In non-verbose mode, just print the protocol, followed
-                * by the first line as the request or response info.
-                *
-                * In verbose mode, print lines as text until we run out
-                * of characters or see something that's not a
-                * printable-ASCII line.
-                */
-               if (ndo->ndo_vflag) {
-                       /*
-                        * We're going to print all the text lines in the
-                        * request or response; just print the length
-                        * on the first line of the output.
-                        */
-                       ND_PRINT((ndo, ", length: %u", len));
-                       for (idx = 0;
-                           idx < len && (eol = print_txt_line(ndo, protoname, "\n\t", pptr, idx, len)) != 0;
-                           idx = eol)
-                               ;
-               } else {
-                       /*
-                        * Just print the first text line.
-                        */
-                       print_txt_line(ndo, protoname, ": ", pptr, 0, len);
-               }
-       }
-}
-
 /* VARARGS */
 void
 error(const char *fmt, ...)
@@ -847,43 +167,3 @@ read_infile(char *fname)
        cp[cc] = '\0';
        return (cp);
 }
-
-void
-safeputs(netdissect_options *ndo,
-         const u_char *s, const u_int maxlen)
-{
-       u_int idx = 0;
-
-       while (*s && idx < maxlen) {
-               safeputchar(ndo, *s);
-               idx++;
-               s++;
-       }
-}
-
-void
-safeputchar(netdissect_options *ndo,
-            const u_char c)
-{
-       ND_PRINT((ndo, (c < 0x80 && ND_ISPRINT(c)) ? "%c" : "\\0x%02x", c));
-}
-
-#ifdef LBL_ALIGN
-/*
- * Some compilers try to optimize memcpy(), using the alignment constraint
- * on the argument pointer type.  by using this function, we try to avoid the
- * optimization.
- */
-void
-unaligned_memcpy(void *p, const void *q, size_t l)
-{
-       memcpy(p, q, l);
-}
-
-/* As with memcpy(), so with memcmp(). */
-int
-unaligned_memcmp(const void *p, const void *q, size_t l)
-{
-       return (memcmp(p, q, l));
-}
-#endif