Page MenuHomeFreeBSD

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
This document is not UTF8. It was detected as ISO-8859-1 (Latin 1) and converted to UTF8 for display.
diff --git a/contrib/tcpdump/CHANGES b/contrib/tcpdump/CHANGES
index 33ced66dd826..b63d1eb658d3 100644
--- a/contrib/tcpdump/CHANGES
+++ b/contrib/tcpdump/CHANGES
@@ -1,1736 +1,1861 @@
+Friday, August 30, 2024 / The Tcpdump Group
+ Summary for 4.99.5 tcpdump release
+ Refine protocol decoding for:
+ Arista: Use the test .pcap file from pull request #955 (HwInfo).
+ BGP: Fix an undefined behavior when it tries to parse a too-short packet.
+ CARP: Print the protocol name before any GET_().
+ CDP: only hex-dump unknown TLVs in verbose mode.
+ DHCP: parse the SZTP redirect tag.
+ DHCPv6: client-id/server-id DUID type 2 correction; parse the user class,
+ boot file URL, and SZTP redirect options; add DUID-UUID printing
+ (RFC6355).
+ DNS: Detect and correctly handle too-short URI RRs.
+ EAP: Assign ndo_protocol in the eap_print() function.
+ ESP: Don't use EVP_add_cipher_alias() (fixes building on OpenBSD 7.5).
+ Frame Relay (Multilink): Fix the Timestamp Information Element printing.
+ ICMPv6: Fix printing the Home Agent Address Discovery Reply Message.
+ IEEE 802.11: no need for an element ID in the structures for IEs, make
+ the length in the IE structures a u_int, include the "TA" field while
+ printing Block Ack Control frame.
+ IP: Enable TSO (TCP Segmentation Offload) support; fix printing invalid
+ cases as invalid, not truncated; use ND_ICHECKMSG_ZU() to test the
+ header length.
+ IPv6: Fix printing invalid cases as invalid, not truncated; use
+ ND_ICHECKMSG_U() to print an invalid version.
+ IPv6: Fix invalid 32-bit versus 64-bit printouts of fragment headers.
+ ISAKMP: Fix printing Delete payload SPI when size is zero.
+ Kerberos: Print the protocol name, remove a redundant bounds check.
+ lwres: Fix an undefined behavior in pointer arithmetic.
+ OpenFlow 1.0: Fix indentation of PORT_MOD, improve handling of
+ some lengths, and fix handling of snapend.
+ TCP: Test ports < 1024 in port order to select the printer.
+ UDP: Move source port equal BCM_LI_PORT to bottom of long if else chain.
+ UDP: Test ports < 1024 in port order to select the printer.
+ LDP: Add missing fields of the Common Session Parameters TLV and fix the
+ offset for the A&D bits.
+ NFLOG: Use correct AF code points on all OSes.
+ NFS: Avoid printing non-ASCII characters.
+ OSPF: Pad TLVs in LS_OPAQUE_TYPE_RI to multiples of 4 bytes.
+ OSPF: Update LS-Ack printing not to run off the end of the packet.
+ OSPF6: Fix an undefined behavior.
+ pflog: use nd_ types in struct pfloghdr.
+ PPP: Check if there is some data to hexdump.
+ PPP: Remove an extra colon before LCP Callback Operation.
+ Use the buffer stack for de-escaping PPP; fixes CVE-2024-2397;
+ Note: This problem does not affect any tcpdump release.
+ PTP: Fix spelling of type SIGNALING, Parse major and minor version
+ correctly, Print majorSdoId field instead of just the first bit.
+ RIP: Make a couple trivial protocol updates.
+ RPKI-Router: Refine length and bounds checks.
+ RX: Use the "%Y-%m-%d" date format.
+ smbutil.c: Use the "%Y-%m-%d" date format.
+ SNMP: Fix two undefined behaviors.
+ Text protocols: Fix printing truncation if it is not the case.
+ ZEP: Use the "%Y-%m-%d" date format.
+ ZMTP: Replace custom code with bittok2str().
+ User interface:
+ Print the supported time stamp types (-J) to stdout instead of stderr.
+ Print the list of data link types (-L) to stdout instead of stderr.
+ Use symmetrical quotation characters in error messages.
+ Update --version option to print 32/64-bit build and time_t size.
+ Improve error messages for invalid interface indexes specified
+ with -i.
+ Support "3des" as an alias for "des_ede3_cbc" even if the crypto
+ library doesn't support adding aliases.
+ Source code:
+ tcpdump: Fix a memory leak.
+ child_cleanup: reap as many child processes as possible.
+ Ignore failures when setting the default "any" device DLL to LINUX_SLL2.
+ Fix for backends which doesn't support capsicum.
+ Update ND_BYTES_BETWEEN() macro for better accuracy.
+ Update ND_BYTES_AVAILABLE_AFTER() macro for better accuracy.
+ Introduce new ND_ICHECK*() macros to deduplicate more code.
+ Skip privilege dropping when using -Z root on --with-user builds.
+ Add a nd_printjn() function.
+ Make nd_trunc_longjmp() not static inline.
+ Include <time.h> from netdissect.h.
+ Remove init_crc10_table() and the entourage.
+ Initialize tzcode early.
+ Capsicum support: Fix a 'not defined' macro error.
+ Update the "Error converting time" tests for packet times.
+ Fix warnings when building for 32-bit and defining _TIME_BITS=64.
+ Free interface list just before exiting where it wasn't being
+ freed.
+ Building and testing:
+ Add a configure option to help debugging (--enable-instrument-functions).
+ At build time require a proof of suitable snprintf(3) implementation in
+ libc (and document Solaris 9 as unsupported because of that).
+ Makefile.in: Add two "touch .devel" commands in the releasecheck target.
+ Autoconf: Get --with-user and --with-chroot right.
+ Autoconf: Fix --static-pcap-only test on Solaris 10.
+ Autoconf: Add some warning flags for clang 13 or newer.
+ Autoconf: Update config.{guess,sub}, timestamps 2024-01-01.
+ Autoconf: Add autogen.sh, remove configure and config.h.in and put
+ these generated files in the release tarball.
+ Autoconf: Update the install-sh script to the 2020-11-14.01 version.
+ configure: Apply autoupdate 2.69.
+ CMake: improve the comment before project(tcpdump C).
+ Do not require vsnprintf().
+ tests: Use the -tttt option, by default, for the tests.
+ Autoconf, CMake: Get the size of a void * and a time_t.
+ Fix propagation of cc_werr_cflags() output.
+ Makefile.in: Fix the depend target.
+ mkdep: Exit with a non-zero status if a command fails.
+ Autoconf: use V_INCLS to update the list of include search paths.
+ Autoconf: don't put anything before -I and -L flags for local libpcap.
+ Autoconf, CMake: work around an Xcode 15+ issue.
+ Autoconf, CMake: use pkg-config and Homebrew when looking for
+ libcrypto.
+ Fix Sun C invocation from CMake.
+ mkdep: Use TMPDIR if it is set and not null.
+ Add initial support for building with TinyCC.
+ Makefile.in: Use the variable MAKE instead of the make command.
+ Makefile.in: Add instrumentation configuration in releasecheck target.
+ Make various improvements to the TESTrun script.
+ Untangle detection of pcap_findalldevs().
+ Autoconf: don't use egrep, use $EGREP.
+ Autoconf: check for gethostbyaddr(), not gethostbyname().
+ Autoconf, CMake: search for gethostbyaddr() in libnetwork.
+ Make illumos build warning-free.
+ Documentation:
+ Fixed errors in doc/README.Win32.md and renamed it to README.windows.md.
+ Make various improvements to the man page.
+ Add initial README file for Haiku.
+ Make various improvements to CONTRIBUTING.md.
+
Friday, April 7, 2023 / The Tcpdump Group
Summary for 4.99.4 tcpdump release
Source code:
Fix spaces before tabs in indentation.
Updated printers:
LSP ping: Fix "Unused value" warnings from Coverity.
CVE-2023-1801: Fix an out-of-bounds write in the SMB printer.
DNS: sync resource types with IANA.
ICMPv6: Update the output to show a RPL DAO field name.
Geneve: Fix the Geneve UDP port test.
Building and testing:
Require at least autoconf 2.69.
Don't check for strftime(), as it's in C90 and beyond.
Update config.{guess,sub}, timestamps 2023-01-01,2023-01-21.
Documentation:
man: Document TCP flag names better.
Thursday, January 12, 2023 / The Tcpdump Group
Summary for 4.99.3 tcpdump release
Updated printers:
PTP: Use the proper values for the control field and print un-allocated
values for the message field as "Reserved" instead of "none".
Source code:
smbutil.c: Replace obsolete function call (asctime)
Building and testing:
cmake: Update the minimum required version to 2.8.12 (except Windows).
CI: Introduce and use TCPDUMP_CMAKE_TAINTED.
Makefile.in: Add the releasecheck target.
Makefile.in: Add "make -s install" in the releasecheck target.
Cirrus CI: Run the "make releasecheck" command in the Linux task.
Makefile.in: Add the whitespacecheck target.
Cirrus CI: Run the "make whitespacecheck" command in the Linux task.
Address all shellcheck warnings in update-test.sh.
Makefile.in: Get rid of a remain of gnuc.h.
Documentation:
Reformat the installation notes (INSTALL.txt) in Markdown.
Convert CONTRIBUTING to Markdown.
CONTRIBUTING.md: Document the use of "protocol: " in a commit summary.
Add a README file for NetBSD.
Fix CMake build to set man page section numbers in tcpdump.1
Saturday, December 31, 2022 / The Tcpdump Group
Summary for 4.99.2 tcpdump release
Updated printers:
BGP: Update cease notification decoding to RFC 9003.
BGP: decode BGP link-bandwidth extended community properly.
BGP: Fix parsing the AIGP attribute
BGP: make sure the path attributes don't go past the end of the packet.
BGP: Shutdown message can be up to 255 bytes length according to rfc9003
DSA: correctly determine VID.
EAP: fix some length checks and output issues.
802.11: Fix the misleading comment regarding "From DS", "To DS" Frame
Control Flags.
802.11: Fetch the CF and TIM IEs a field at a time.
802.15.4, BGP, LISP: fix some length checks, compiler warnings,
and undefined behavior warnings.
PFLOG: handle LINKTYPE_PFLOG/DLT_PFLOG files from all OSes on all
OSes.
RRCP: support more Realtek protocols than just RRCP.
MPLS: show the EXP field as TC, as per RFC 5462.
ICMP: redo MPLS Extension code as general ICMP Extension code.
VQP: Do not print unknown error codes twice.
Juniper: Add some bounds checks.
Juniper: Don't treat known DLT_ types as "Unknown".
lwres: Fix a length check, update a variable type.
EAP: Fix some undefined behaviors at runtime.
Ethernet: Rework the length checks, add a length check.
IPX: Add two length checks.
Zephyr: Avoid printing non-ASCII characters.
VRRP: Print the protocol name before any GET_().
DCCP: Get rid of trailing commas in lists.
Juniper: Report invalid packets as invalid, not truncated.
IPv6: Remove an obsolete code in an always-false #if wrapper.
ISAKMP: Use GET_U_1() to replace a direct dereference.
RADIUS: Use GET_U_1() to replace a direct dereference.
TCP: Fix an invalid check.
RESP: Fix an invalid check.
RESP: Remove an unnecessary test.
Arista: Refine the output format and print HwInfo.
sFlow: add support for IPv6 agent, add a length check.
VRRP: add support for IPv6.
OSPF: Update to match the Router Properties registry.
OSPF: Remove two unnecessary dereferences.
OSPF: Add support bit Nt RFC3101.
OSPFv3: Remove two unnecessary dereferences.
ICMPv6: Fix output for Router Renumbering messages.
ICMPv6: Fix the Node Information flags.
ICMPv6: Remove an unused macro and extra blank lines.
ICMPv6: Add a length check in the rpl_dio_print() function.
ICMPv6: Use GET_IP6ADDR_STRING() in the rpl_dio_print() function.
IPv6: Add some checks for the Hop-by-Hop Options header
IPv6: Add a check for the Jumbo Payload Hop-by-Hop option.
NFS: Fix the format for printing an unsigned int
PTP: fix printing of the correction fields
PTP: Use ND_LCHECK_U for checking invalid length.
WHOIS: Add its own printer source file and printer function
MPTCP: print length before subtype inside MPTCP options
ESP: Add a workaround to a "use-of-uninitialized-value".
PPP: Add tests to avoid incorrectly re-entering ppp_hdlc().
PPP: Don't process further if protocol is unknown (-e option).
PPP: Change the pointer to packet data.
ZEP: Add three length checks.
Add some const qualifiers.
Building and testing:
Update config.guess and config.sub.
Use AS_HELP_STRING macro instead of AC_HELP_STRING.
Handle some Autoconf/make errors better.
Fix an error when cross-compiling.
Use "git archive" for the "make releasetar" process.
Remove the release candidate rcX targets.
Mend "make check" on Solaris 9 with Autoconf.
Address assorted compiler warnings.
Fix auto-enabling of Capsicum on FreeBSD with Autoconf.
Treat "msys" as Windows for test exit statuses.
Clean up some help messages in configure.
Use unified diff by default.
Remove awk code from mkdep.
Fix configure test errors with Clang 15
CMake: Prevent stripping of the RPATH on installation.
AppVeyor CI: update Npcap site, update to 1.12 SDK.
Cirrus CI: Use the same configuration as for the main branch.
CI: Add back running tcpdump -J/-L and capture, now with Cirrus VMs.
Remove four test files (They are now in the libpcap tests directory).
On Solaris, for 64-bit builds, use the 64-bit pcap-config.
Tell CMake not to check for a C++ compiler.
CMake: Add a way to request -Werror and equivalents.
configure: Special-case macOS /usr/bin/pcap-config as we do in CMake.
configure: Use pcap-config --static-pcap-only if available.
configure: Use ac_c_werror_flag to force unknown compiler flags to fail.
configure: Use AC_COMPILE_IFELSE() and AC_LANG_SOURCE() for testing
flags.
Run the test that fails on OpenBSD only if we're not on OpenBSD.
Source code:
Fix some snapend-changing routines to protect against pointer
underflow.
Use __func__ from C99 in some function calls.
Memory allocator: Update nd_add_alloc_list() to a static function.
addrtoname.c: Fix two invalid tests.
Use more S_SUCCESS and S_ERR_HOST_PROGRAM in main().
Add some comments about "don't use GET_IP6ADDR_STRING()".
Assign ndo->ndo_packetp in pretty_print_packet().
Add ND_LCHECKMSG_U, ND_LCHECK_U, ND_LCHECKMSG_ZU and ND_LCHECK_ZU macros.
Update tok2strbuf() to a static function.
netdissect.h: Keep the link-layer dissectors names sorted.
setsignal(): Set SA_RESTART on non-lethal signals (REQ_INFO, FLUSH_PCAP)
to avoid corrupting binary pcap output.
Use __builtin_unreachable().
Fail if nd_push_buffer() or nd_push_snaplen() fails.
Improve code style and fix many typos.
Documentation:
Some man page cleanups.
Update the print interface for the packet count to stdout.
Note that we require compilers to support at least some of C99.
Update AIX and Solaris-related specifics.
INSTALL.txt: Add doc/README.*, delete the deleted win32 directory.
Update README.md and README.Win32.md.
Update some comments with new RFC numbers.
Wednesday, June 9, 2021 by gharris
Summary for 4.99.1 tcpdump release
Source code:
Squelch some compiler warnings
ICMP: Update the snapend for some nested IP packets.
MACsec: Update the snapend thus the ICV field is not payload
for the caller.
EIGRP: Fix packet header fields
SMB: Disable printer by default in CMake builds
OLSR: Print the protocol name even if the packet is invalid
MSDP: Print ": " before the protocol name
ESP: Remove padding, padding length and next header from the buffer
DHCPv6: Update the snapend for nested DHCPv6 packets
OpenFlow 1.0: Get snapend right for nested frames.
TCP: Update the snapend before decoding a MPTCP option
Ethernet, IEEE 802.15.4, IP, L2TP, TCP, ZEP: Add bounds checks
ForCES: Refine SPARSEDATA-TLV length check.
ASCII/hex: Use nd_trunc_longjmp() in truncation cases
GeoNet: Add a ND_TCHECK_LEN() call
Replace ND_TCHECK_/memcpy() pairs with GET_CPY_BYTES().
BGP: Fix overwrites of global 'astostr' temporary buffer
ARP: fix overwrites of static buffer in q922_string().
Frame Relay: have q922_string() handle errors better.
Building and testing:
Rebuild configure script when building release
Fix "make clean" for out-of-tree autotools builds
CMake: add stuff from CMAKE_PREFIX_PATH to PKG_CONFIG_PATH.
Documentation:
- man: Update a reference as www.cifs.org is gone. [skip ci]
+ man: Update a reference as www.cifs.org is gone.
man: Update DNS sections
Solaris:
Fix a compile error with Sun C
Wednesday, December 30, 2020, by mcr@sandelman.ca, denis and fxl.
Summary for 4.99.0 tcpdump release
CVE-2018-16301: For the -F option handle large input files safely.
Improve the contents, wording and formatting of the man page.
Print unsupported link-layer protocol packets in hex.
Add support for new network protocols and DLTs: Arista, Autosar SOME/IP,
Broadcom LI and Ethernet switches tag, IEEE 802.15.9, IP-over-InfiniBand
(IPoIB), Linux SLL2, Linux vsockmon, MACsec, Marvell Distributed Switch
Architecture, OpenFlow 1.3, Precision Time Protocol (PTP), SSH, WHOIS,
ZigBee Encapsulation Protocol (ZEP).
Make protocol-specific updates for: AH, DHCP, DNS, ESP, FRF.16, HNCP,
ICMP6, IEEE 802.15.4, IPv6, IS-IS, Linux SLL, LLDP, LSP ping, MPTCP, NFS,
NSH, NTP, OSPF, OSPF6, PGM, PIM, PPTP, RADIUS, RSVP, Rx, SMB, UDLD,
VXLAN-GPE.
User interface:
Make SLL2 the default for Linux "any" pseudo-device.
Add --micro and --nano shorthands.
Add --count to print a counter only instead of decoding.
Add --print, to cause packet printing even with -w.
Add support for remote capture if libpcap supports it.
Display the "wireless" flag and connection status.
Flush the output packet buffer on a SIGUSR2.
Add the snapshot length to the "reading from file ..." message.
Fix local time printing (DST offset in timestamps).
Allow -C arguments > 2^31-1 GB if they can fit into a long.
Handle very large -f files by rejecting them.
Report periodic stats only when safe to do so.
Print the number of packets captured only as often as necessary.
With no -s, or with -s 0, don't specify the snapshot length with newer
versions of libpcap.
Improve version and usage message printing.
Building and testing:
Install into bindir, not sbindir.
autoconf: replace --with-system-libpcap with --disable-local-libpcap.
Require the compiler to support C99.
Better detect and use various C compilers and their features.
Add CMake as the second build system.
Make out-of-tree builds more reliable.
Use pkg-config to detect libpcap if available.
Improve Windows support.
Add more tests and improve the scripts that run them.
Test both with "normal" and "x87" floating-point.
Eliminate dependency on libdnet.
FreeBSD:
Print a proper error message about monitor mode VAP.
Use libcasper if available.
Fix failure to capture on RDMA device.
Include the correct capsicum header.
Source code:
Start the transition to longjmp() for packet truncation handling.
Introduce new helper functions, including GET_*(), nd_print_protocol(),
nd_print_invalid(), nd_print_trunc(), nd_trunc_longjmp() and others.
Put integer signedness right in many cases.
Introduce nd_uint*, nd_mac_addr, nd_ipv4 and nd_ipv6 types to fix
alignment issues, especially on SPARC.
Fix many C compiler, Coverity, UBSan and cppcheck warnings.
Fix issues detected with AddressSanitizer.
Remove many workarounds for older compilers and OSes.
Add a sanity check on packet header length.
Add and remove plenty of bounds checks.
Clean up pcap_findalldevs() call to find the first interface.
Use a short timeout, rather than immediate mode, for text output.
Handle DLT_ENC files *not* written on the same OS and byte-order host.
Add, and use, macros to do locale-independent case mapping.
Use a table instead of getprotobynumber().
Get rid of ND_UNALIGNED and ND_TCHECK().
Make roundup2() generally available.
Resync SMI list against Wireshark.
Fix many typos.
Friday, September 20, 2019, by mcr@sandelman.ca
A huge thank you to Denis, Francois-Xavier and Guy who did much of the heavy lifting.
Summary for 4.9.3 tcpdump release
Fix buffer overflow/overread vulnerabilities:
CVE-2017-16808 (AoE)
CVE-2018-14468 (FrameRelay)
CVE-2018-14469 (IKEv1)
CVE-2018-14470 (BABEL)
CVE-2018-14466 (AFS/RX)
CVE-2018-14461 (LDP)
CVE-2018-14462 (ICMP)
CVE-2018-14465 (RSVP)
CVE-2018-14881 (BGP)
CVE-2018-14464 (LMP)
CVE-2018-14463 (VRRP)
CVE-2018-14467 (BGP)
CVE-2018-10103 (SMB - partially fixed, but SMB printing disabled)
CVE-2018-10105 (SMB - too unreliably reproduced, SMB printing disabled)
CVE-2018-14880 (OSPF6)
CVE-2018-16451 (SMB)
CVE-2018-14882 (RPL)
CVE-2018-16227 (802.11)
CVE-2018-16229 (DCCP)
CVE-2018-16230 (BGP)
CVE-2018-16452 (SMB)
CVE-2018-16300 (BGP)
CVE-2018-16228 (HNCP)
CVE-2019-15166 (LMP)
CVE-2019-15167 (VRRP)
Fix for cmdline argument/local issues:
CVE-2018-14879 (tcpdump -V)
Sunday September 3, 2017 denis@ovsienko.info
Summary for 4.9.2 tcpdump release
Do not use getprotobynumber() for protocol name resolution. Do not do
any protocol name resolution if -n is specified.
Improve errors detection in the test scripts.
Fix a segfault with OpenSSL 1.1 and improve OpenSSL usage.
Clean up IS-IS printing.
Fix buffer overflow vulnerabilities:
CVE-2017-11543 (SLIP)
CVE-2017-13011 (bittok2str_internal)
Fix infinite loop vulnerabilities:
CVE-2017-12989 (RESP)
CVE-2017-12990 (ISAKMP)
CVE-2017-12995 (DNS)
CVE-2017-12997 (LLDP)
Fix buffer over-read vulnerabilities:
CVE-2017-11541 (safeputs)
CVE-2017-11542 (PIMv1)
CVE-2017-12893 (SMB/CIFS)
CVE-2017-12894 (lookup_bytestring)
CVE-2017-12895 (ICMP)
CVE-2017-12896 (ISAKMP)
CVE-2017-12897 (ISO CLNS)
CVE-2017-12898 (NFS)
CVE-2017-12899 (DECnet)
CVE-2017-12900 (tok2strbuf)
CVE-2017-12901 (EIGRP)
CVE-2017-12902 (Zephyr)
CVE-2017-12985 (IPv6)
CVE-2017-12986 (IPv6 routing headers)
CVE-2017-12987 (IEEE 802.11)
CVE-2017-12988 (telnet)
CVE-2017-12991 (BGP)
CVE-2017-12992 (RIPng)
CVE-2017-12993 (Juniper)
CVE-2017-12994 (BGP)
CVE-2017-12996 (PIMv2)
CVE-2017-12998 (ISO IS-IS)
CVE-2017-12999 (ISO IS-IS)
CVE-2017-13000 (IEEE 802.15.4)
CVE-2017-13001 (NFS)
CVE-2017-13002 (AODV)
CVE-2017-13003 (LMP)
CVE-2017-13004 (Juniper)
CVE-2017-13005 (NFS)
CVE-2017-13006 (L2TP)
CVE-2017-13007 (Apple PKTAP)
CVE-2017-13008 (IEEE 802.11)
CVE-2017-13009 (IPv6 mobility)
CVE-2017-13010 (BEEP)
CVE-2017-13012 (ICMP)
CVE-2017-13013 (ARP)
CVE-2017-13014 (White Board)
CVE-2017-13015 (EAP)
CVE-2017-11543 (SLIP)
CVE-2017-13016 (ISO ES-IS)
CVE-2017-13017 (DHCPv6)
CVE-2017-13018 (PGM)
CVE-2017-13019 (PGM)
CVE-2017-13020 (VTP)
CVE-2017-13021 (ICMPv6)
CVE-2017-13022 (IP)
CVE-2017-13023 (IPv6 mobility)
CVE-2017-13024 (IPv6 mobility)
CVE-2017-13025 (IPv6 mobility)
CVE-2017-13026 (ISO IS-IS)
CVE-2017-13027 (LLDP)
CVE-2017-13028 (BOOTP)
CVE-2017-13029 (PPP)
CVE-2017-13030 (PIM)
CVE-2017-13031 (IPv6 fragmentation header)
CVE-2017-13032 (RADIUS)
CVE-2017-13033 (VTP)
CVE-2017-13034 (PGM)
CVE-2017-13035 (ISO IS-IS)
CVE-2017-13036 (OSPFv3)
CVE-2017-13037 (IP)
CVE-2017-13038 (PPP)
CVE-2017-13039 (ISAKMP)
CVE-2017-13040 (MPTCP)
CVE-2017-13041 (ICMPv6)
CVE-2017-13042 (HNCP)
CVE-2017-13043 (BGP)
CVE-2017-13044 (HNCP)
CVE-2017-13045 (VQP)
CVE-2017-13046 (BGP)
CVE-2017-13047 (ISO ES-IS)
CVE-2017-13048 (RSVP)
CVE-2017-13049 (Rx)
CVE-2017-13050 (RPKI-Router)
CVE-2017-13051 (RSVP)
CVE-2017-13052 (CFM)
CVE-2017-13053 (BGP)
CVE-2017-13054 (LLDP)
CVE-2017-13055 (ISO IS-IS)
CVE-2017-13687 (Cisco HDLC)
CVE-2017-13688 (OLSR)
CVE-2017-13689 (IKEv1)
CVE-2017-13690 (IKEv2)
CVE-2017-13725 (IPv6 routing headers)
Sunday July 23, 2017 denis@ovsienko.info
Summary for 4.9.1 tcpdump release
CVE-2017-11108/Fix bounds checking for STP.
Make assorted documentation updates and fix a few typos in tcpdump output.
Fixup -C for file size >2GB (GH #488).
Show AddressSanitizer presence in version output.
Fix a bug in test scripts (exposed in GH #613).
On FreeBSD adjust Capsicum capabilities for netmap.
On Linux fix a use-after-free when the requested interface does not exist.
Wednesday January 18, 2017 devel.fx.lebail@orange.fr
Summary for 4.9.0 tcpdump release
General updates:
Fix some heap overflows found with American Fuzzy Lop by Hanno Boeck and others
(More information in the log with CVE-2016-* and CVE-2017-*)
Change the way protocols print link-layer addresses (Fix heap overflows
in CALM-FAST and GeoNetworking printers)
Pass correct caplen value to ether_print() and some other functions
Fix lookup_nsap() to match what isonsap_string() expects
Clean up relative time stamp printing (Fix an array overflow)
Fix some alignment issues with GCC on Solaris 10 SPARC
Add some ND_TTEST_/ND_TCHECK_ macros to simplify writing bounds checks
Add a fn_printztn() which returns the number of bytes processed
Add nd_init() and nd_cleanup() functions. Improve libsmi support
Add CONTRIBUTING file
Add a summary comment in all printers
Compile with more warning options in devel mode if supported (-Wcast-qual, ...)
Fix some leaks found by Valgrind/Memcheck
Fix a bunch of de-constifications
Squelch some Coverity warnings and some compiler warnings
Update Coverity and Travis-CI setup
Update Visual Studio files
Frontend:
Fix capsicum support to work with zerocopy buffers in bpf
Try opening interfaces by name first, then by name-as-index
Work around pcap_create() failures fetching time stamp type lists
Fix a segmentation fault with 'tcpdump -J'
Improve addrtostr6() bounds checking
Add exit_tcpdump() function
Don't drop CAP_SYS_CHROOT before chrooting
Fixes issue where statistics not reported when -G and -W options used
Updated printers:
802.11: Beginnings of 11ac radiotap support
802.11: Check the Protected bit for management frames
802.11: Do bounds checking on last_presentp before dereferencing it (Fix a heap overflow)
802.11: Fix the radiotap printer to handle the special bits correctly
802.11: If we have the MCS field, it's 11n
802.11: Only print unknown frame type or subtype messages once
802.11: Radiotap dBm values get printed as dB; Update a test output accordingly
802.11: Source and destination addresses were backwards
AH: Add a bounds check
AH: Report to our caller that dissection failed if a bounds check fails
AP1394: Print src > dst, not dst > src
ARP: Don't assume the target hardware address is <= 6 octets long (Fix a heap overflow)
ATALK: Add bounds and length checks (Fix heap overflows)
ATM: Add some bounds checks (Fix a heap overflow)
ATM: Fix an incorrect bounds check
BFD: Update specification from draft to RFC 5880
BFD: Update to print optional authentication field
BGP: Add support for the AIGP attribute (RFC7311)
BGP: Print LARGE_COMMUNITY Path Attribute
BGP: Update BGP numbers from IANA; Print minor values for FSM notification
BOOTP: Add a bounds check
Babel: Add decoder for source-specific extension
CDP: Filter out non-printable characters
CFM: Fixes to match the IEEE standard, additional bounds and length checks
CSLIP: Add more bounds checks (Fix a heap overflow)
ClassicalIPoATM: Add a bounds check on LLC+SNAP header (Fix a heap overflow)
DHCP: Fix MUDURL and TZ options
DHCPv6: Process MUDURL and TZ options
DHCPv6: Update Status Codes with RFCs/IANA names
DNS: Represent the "DNSSEC OK" bit as "DO" instead of "OK". Add a test case
DTP: Improve packet integrity checks
EGP: Fix bounds checks
ESP: Don't use OpenSSL_add_all_algorithms() in OpenSSL 1.1.0 or later
Ethernet: Add some bounds checking before calling isoclns_print (Fix a heap overflow)
Ethernet: Print the Length/Type field as length when needed
FDDI: Fix -e output for FDDI
FR: Add some packet-length checks and improve Q.933 printing (Fix heap overflows)
GRE: Add some bounds checks (Fix heap overflows)
Geneve: Fix error message with invalid option length; Update list option classes
HNCP: Fix incorrect time interval format. Fix handling of IPv4 prefixes
ICMP6: Fetch a 32-bit big-endian quantity with EXTRACT_32BITS()
IGMP: Add a length check
IP: Add a bounds check (Fix a heap overflow)
IP: Check before fetching the protocol version (Fix a heap overflow)
IP: Don't try to dissect if IP version != 4 (Fix a heap overflow)
IP: Stop processing IPPROTO_ values once we hit IPPROTO_IPCOMP
IPComp: Check whether we have the CPI before we fetch it (Fix a heap overflow)
IPoFC: Fix -e output (IP-over-Fibre Channel)
IPv6: Don't overwrite the destination IPv6 address for routing headers
IPv6: Fix header printing
IPv6: Stop processing IPPROTO_ values once we hit IPPROTO_IPCOMP
ISAKMP: Clean up parsing of IKEv2 Security Associations
ISOCLNS/IS-IS: Add support for Purge Originator Identifier (RFC6232) and test cases
ISOCLNS/IS-IS: Don't overwrite packet data when checking the signature
ISOCLNS/IS-IS: Filter out non-printable characters
ISOCLNS/IS-IS: Fix segmentation faults
ISOCLNS/IS-IS: Have signature_verify() do the copying and clearing
ISOCLNS: Add some bounds checks
Juniper: Make sure a Juniper header TLV isn't bigger than what's left in the packet (Fix a heap overflow)
LLC/SNAP: With -e, print the LLC header before the SNAP header; without it, cut the SNAP header
LLC: Add a bounds check (Fix a heap overflow)
LLC: Clean up printing of LLC packets
LLC: Fix the printing of RFC 948-style IP packets
LLC: Skip the LLC and SNAP headers with -x for 802.11 and some other protocols
LLDP: Implement IANA OUI and LLDP MUD option
MPLS LSP ping: Update printing for RFC 4379, bug fixes, more bounds checks
MPLS: "length" is now the *remaining* packet length
MPLS: Add bounds and length checks (Fix a heap overflow)
NFS: Don't assume the ONC RPC header is nicely aligned
NFS: Don't overflow the Opaque_Handle buffer (Fix a segmentation fault)
NFS: Don't run past the end of an NFSv3 file handle
OLSR: Add a test to cover a HNA sgw case
OLSR: Fix 'Advertised networks' count
OLSR: Fix printing of smart-gateway HNAs in IPv4
OSPF: Add a bounds check for the Hello packet options
OSPF: Do more bounds checking
OSPF: Fix a segmentation fault
OSPF: Fix printing 'ospf_topology_values' default
OTV: Add missing bounds checks
PGM: Print the formatted IP address, not the raw binary address, as a string
PIM: Add some bounds checking (Fix a heap overflow)
PIMv2: Fix checksumming of Register messages
PPP: Add some bounds checks (Fix a heap overflow)
PPP: Report invalid PAP AACK/ANAK packets
Q.933: Add a missing bounds check
RADIUS: Add Value 13 "VLAN" to Tunnel-Type attribute
RADIUS: Filter out non-printable characters
RADIUS: Translate UDP/1700 as RADIUS
RESP: Do better checking of RESP packets
RPKI-RTR: Add a return value check for "fn_printn" call
RPKI-RTR: Remove printing when truncated condition already detected
RPL: Fix 'Consistency Check' control code
RPL: Fix suboption print
RSVP: An INTEGRITY object in a submessage covers only the submessage
RSVP: Fix an infinite loop; Add bounds and length checks
RSVP: Fix some if statements missing brackets
RSVP: Have signature_verify() do the copying and clearing
RTCP: Add some bounds checks
RTP: Add some bounds checks, fix two segmentation faults
SCTP: Do more bounds checking
SFLOW: Fix bounds checking
SLOW: Fix bugs, add checks
SMB: Before fetching the flags2 field, make sure we have it
SMB: Do bounds checks on NBNS resource types and resource data lengths
SNMP: Clean up the "have libsmi but no modules loaded" case
SNMP: Clean up the object abbreviation list and fix the code to match them
SNMP: Do bounds checks when printing character and octet strings
SNMP: Improve ASN.1 bounds checks
SNMP: More bounds and length checks
STP: Add a bunch of bounds checks, and fix some printing (Fix heap overflows)
STP: Filter out non-printable characters
TCP: Add bounds and length checks for packets with TCP option 20
TCP: Correct TCP option Kind value for TCP Auth and add SCPS-TP
TCP: Fix two bounds checks (Fix heap overflows)
TCP: Make sure we have the data offset field before fetching it (Fix a heap overflow)
TCP: Put TCP-AO option decoding right
TFTP: Don't use strchr() to scan packet data (Fix a heap overflow)
Telnet: Add some bounds checks
TokenRing: Fix -e output
UDLD: Fix an infinite loop
UDP: Add a bounds check (Fix a heap overflow)
UDP: Check against the packet length first
VAT: Add some bounds checks
VTP: Add a test on Mgmt Domain Name length
VTP: Add bounds checks and filter out non-printable characters
VXLAN: Add a bound check and a test case
ZeroMQ: Fix an infinite loop
Tuesday October 25, 2016 mcr@sandelman.ca
Summary for 4.8.1 tcpdump release
Fix "-x" for Apple PKTAP and PPI packets
Improve separation frontend/backend (tcpdump/libnetdissect)
Fix display of timestamps with -tt, -ttt and -ttttt options
Add support for the Marvell Extended Distributed Switch Architecture header
Use PRIx64 to print a 64-bit number in hex.
Printer for HNCP (RFCs 7787 and 7788).
dagid is always an IPv6 address, not an opaque 128-bit string, and other fixes to RPL printer.
RSVP: Add bounds and length checks
OSPF: Do more bounds checking
Handle OpenSSL 1.1.x.
Initial support for the REdis Serialization Protocol known as RESP.
Add printing function for Generic Protocol Extension for VXLAN
draft-ietf-nvo3-vxlan-gpe-01
Network Service Header: draft-ietf-sfc-nsh-01
Don't recompile the filter if the new file has the same DLT.
Pass an adjusted struct pcap_pkthdr to the sub-printer.
Add three test cases for already fixed CVEs
CVE-2014-8767: OLSR
CVE-2014-8768: Geonet
CVE-2014-8769: AODV
Don't do the DDP-over-UDP heuristic first: GitHub issue #499.
Use the new debugging routines in libpcap.
Harmonize TCP source or destination ports tests with UDP ones
Introduce data types to use for integral values in packet structures.
RSVP: Fix an infinite loop
Support of Type 3 and Type 4 LISP packets.
Don't require IPv6 library support in order to support IPv6 addresses.
Many many changes to support libnetdissect usage.
Add a test that makes unaligned accesses: GitHub issue #478.
add a DNSSEC test case: GH #445 and GH #467.
BGP: add decoding of ADD-PATH capability
fixes to LLC header printing, and RFC948-style IP packets
Friday April 10, 2015 guy@alum.mit.edu
Summary for 4.7.4 tcpdump release
RPKI to Router Protocol: Fix Segmentation Faults and other problems
RPKI to Router Protocol: print strings with fn_printn()
wb: fix some bounds checks
Wednesday March 11, 2015 mcr@sandelman.ca
Summary for 4.7.3 tcpdump release
Capsicum fixes for FreeBSD 10
Tuesday March 10, 2015 mcr@sandelman.ca
Summary for 4.7.2 tcpdump release
DCCP: update Packet Types with RFC4340/IANA names
fixes for CVE-2015-0261: IPv6 mobility header check issue
fixes for CVE-2015-2153, 2154, 2155: kday packets
Friday Nov. 12, 2014 guy@alum.mit.edu
Summary for 4.7.0 tcpdump release
changes to hex printing of CDP packets
Fix PPI printing
Radius: update Packet Type Codes and Attribute Types with RFC/IANA names
Add a routine to print "text protocols", and add FTP/HTTP/SMTP/RTSP support.
improvements to telnet printer, even if not -v
omit length for bcp, print-tcp uses it
formatting fixes for a bunch of protocols
new bounds checks for a number of protocols
split netflow 1,6, and 6 dissector up.
added geneve dissector
CVE-2014-9140 PPP dissector fixed.
Tuesday Sep. 2, 2014 mcr@sandelman.ca
Summary for 4.6.2 tcpdump release
fix out-of-source-tree builds: find libpcap that is out of source
better configure check for libsmi
Saturday Jul. 19, 2014 mcr@sandelman.ca
Summary for 4.6.1 tcpdump release
added FreeBSD capsicum
add a short option '#', same as long option '--number'
Wednesday Jul. 2, 2014 mcr@sandelman.ca
Summary for 4.6.0 tcpdump release
all of tcpdump is now using the new "NDO" code base (Thanks Denis!)
nflog, mobile, forces, pptp, AODV, AHCP, IPv6, OSPFv4, RPL, DHCPv6 enhancements/fixes
M3UA decode added.
many new test cases: 82 in 4.5.1 to 133 in 4.6.0
many improvements to travis continuous integration system: OSX, and Coverity options
cleaned up some unnecessary header files
Added bittok2str().
a number of unaligned access faults fixed
-A flag does not consider CR to be printable anymore
fx.lebail took over coverity baby sitting
default snapshot size increased to 256K for accommodate USB captures
WARNING: this release contains a lot of very worthwhile code churn.
Wednesday Jan. 15, 2014 guy@alum.mit.edu
Summary for 4.5.2 tcpdump release
Man page fix
Fix crashes on SPARC
Monday Nov. 11, 2013 mcr@sandelman.ca
Summary for 4.5.1 tcpdump release
CREDITS file fixes
Thursday Nov. 7, 2013 mcr@sandelman.ca and guy@alum.mit.edu.
Summary for 4.5.0 tcpdump release
some NFSv4 fixes for printing
fix printing of unknown TCP options, and tcp fast-open
fixes for syslog parser
some gcc-version-specific flag tuning
adopt MacOS deprecation workarounds for openssl
improvements to babel printing
add OpenFlow 1.0 (no SSL) and test cases
GeoNet printer.
added STBC Rx support
improvements to DHCPv6 decoder
clarify which autoconf is needed
Point users to the the-tcpdump-group repository on GitHub rather
than the mcr repository
Add MSDP printer.
Fixed IPv6 check on Solaris and other OSes requiring extra
networking libraries.
Add support for VXLAN (draft-mahalingam-dutt-dcops-vxlan-03),
and add "vxlan" as an option for -T.
Add support for OTV (draft-hasmit-otv-04).
fixes for DLT_IEEE802_11_RADIO datalink types
added MPTCP decoder
Saturday April 6, 2013 guy@alum.mit.edu.
Summary for 4.4.0 tcpdump release
RPKI-RTR (RFC6810) is now official (TCP Port 323)
Fix detection of OpenSSL libcrypto.
Add DNSSL (RFC6106) support.
Add "radius" as an option for -T.
Update Action codes for handle_action function according to
802.11s amendment.
Decode DHCPv6 AFTR-Name option (RFC6334).
Updates for Babel.
Fix printing of infinite lifetime in ICMPv6.
Added support for SPB, SPBM Service Identifier, and Unicast
Address sub-TLV in ISIS.
Decode RIPv2 authentication up to RFC4822.
Fix RIP Request/full table decoding issues.
On Linux systems with cap-ng.h, drop root privileges
using Linux Capabilities.
Add support for reading multiple files.
Add MS NLB heartbeat printer.
Separate multiple nexthops in BGP.
Wednesday November 28, 2012 guy@alum.mit.edu.
Summary for 4.3.1 tcpdump release
Print "LLDP, length N" for LLDP packets even when not in verbose
mode, so something is printed even if only the timestamp is
present
Document "-T carp"
Print NTP poll interval correctly (it's an exponent, so print
both its raw value and 2^value)
Document that "-e" is used to get MAC addresses
More clearly document that you need to escape or quote
backslashes in filter expressions on the command line
Fix some "the the" in the man page
Use the right maximum path length
Don't treat 192_1_2, when passed to -i, as an interface number
Friday April 3, 2012. mcr@sandelman.ca.
Summary for 4.3.0 tcpdump release
fixes for forces: SPARSE data (per RFC 5810)
some more test cases added
updates to documentation on -l, -U and -w flags.
Fix printing of BGP optional headers.
Tried to include DLT_PFSYNC support, failed due to headers required.
added TIPC support.
Fix LLDP Network Policy bit definitions.
fixes for IGMPv3's Max Response Time: it is in units of 0.1 second.
SIGUSR1 can be used rather than SIGINFO for stats
permit -n flag to affect print-ip for protocol numbers
ND_OPT_ADVINTERVAL is in milliseconds, not seconds
Teach PPPoE parser about RFC 4638
Friday December 9, 2011. guy@alum.mit.edu.
Summary for 4.2.1 tcpdump release
Only build the Babel printer if IPv6 is enabled.
Support Babel on port 6696 as well as 6697.
Include ppi.h in release tarball.
Include all the test files in the release tarball, and don't
"include" test files that no longer exist.
Don't assume we have <rpc/rpc.h> - check for it.
Support "-T carp" as a way of dissecting IP protocol 112 as CARP
rather than VRRP.
Support Hilscher NetAnalyzer link-layer header format.
Constify some pointers and fix compiler warnings.
Get rid of never-true test.
Fix an unintended fall-through in a case statement in the ARP
printer.
Fix several cases where sizeof(sizeof(XXX)) was used when just
sizeof(XXX) was intended.
Make stricter sanity checks in the ES-IS printer.
Get rid of some GCCisms that caused builds to fai with compilers
that don't support them.
Fix typo in man page.
Added length checks to Babel printer.
Sunday July 24, 2011. mcr@sandelman.ca.
Summary for 4.2.+
merged 802.15.4 decoder from Dmitry Eremin-Solenikov <dbaryshkov
at gmail dot com>
updates to forces for new port numbers
Use "-H", not "-h", for the 802.11s option. (-h always help)
Better ICMPv6 checksum handling.
add support for the RPKI/Router Protocol, per -ietf-sidr-rpki-rtr-12
get rid of uuencoded pcap test files, git can do binary.
sFlow changes for 64-bit counters.
fixes for PPI packet header handling and printing.
Add DCB Exchange protocol (DCBX) version 1.01.
Babel dissector, from Juliusz Chroboczek and Grégoire Henry.
improvements to radiotap for rate values > 127.
Many improvements to ForCES decode, including fix SCTP TML port
updated RPL type code to RPL-17 draft
Improve printout of DHCPv6 options.
added support and test case for QinQ (802.1q VLAN) packets
Handle DLT_IEEE802_15_4_NOFCS like DLT_IEEE802_15_4.
Build fixes for Sparc and other machines with alignment restrictions.
Merged changes from Debian package.
PGM: Add ACK decoding and add PGMCC DATA and FEEDBACK options.
Build fixes for OSX (Snow Leopard and others)
Add support for IEEE 802.15.4 packets
Tue. July 20, 2010. guy@alum.mit.edu.
Summary for 4.1.2 tcpdump release
If -U is specified, flush the file after creating it, so it's
not zero-length
Fix TCP flags output description, and some typos, in the man
page
Add a -h flag, and only attempt to recognize 802.11s mesh
headers if it's set
When printing the link-layer type list, send *all* output to
stderr
Include the CFLAGS setting when configure was run in the
compiler flags
Thu. April 1, 2010. guy@alum.mit.edu.
Summary for 4.1.1 tcpdump release
Fix build on systems with PF, such as FreeBSD and OpenBSD.
Don't blow up if a zero-length link-layer address is passed to
linkaddr_string().
Thu. March 11, 2010. ken@netfunctional.ca/guy@alum.mit.edu.
Summary for 4.1.0 tcpdump release
Fix printing of MAC addresses for VLAN frames with a length
field
Add some additional bounds checks and use the EXTRACT_ macros
more
Add a -b flag to print the AS number in BGP packets in ASDOT
notation rather than ASPLAIN notation
Add ICMPv6 RFC 5006 support
Decode the access flags in NFS access requests
Handle the new DLT_ for memory-mapped USB captures on Linux
Make the default snapshot (-s) the maximum
Print name of device (when -L is used)
Support for OpenSolaris (and SXCE build 125 and later)
Print new TCP flags
Add support for RPL DIO
Add support for TCP User Timeout (UTO)
Add support for non-standard Ethertypes used by 3com PPPoE gear
Add support for 802.11n and 802.11s
Add support for Transparent Ethernet Bridge ethertype in GRE
Add 4 byte AS support for BGP printer
Add support for the MDT SAFI 66 BG printer
Add basic IPv6 support to print-olsr
Add USB printer
Add printer for ForCES
Handle frames with an FCS
Handle 802.11n Control Wrapper, Block Acq Req and Block Ack frames
Fix TCP sequence number printing
Report 802.2 packets as 802.2 instead of 802.3
Don't include -L/usr/lib in LDFLAGS
On x86_64 Linux, look in lib64 directory too
Lots of code clean ups
Autoconf clean ups
Update testcases to make output changes
Fix compiling with/out smi (--with{,out}-smi)
Fix compiling without IPv6 support (--disable-ipv6)
Mon. October 27, 2008. ken@netfunctional.ca. Summary for 4.0.0 tcpdump release
Add support for Bluetooth Sniffing
Add support for Realtek Remote Control Protocol (openrrcp.org.ru)
Add support for 802.11 AVS
Add support for SMB over TCP
Add support for 4 byte BGP AS printing
Add support for compiling on case-insensitive file systems
Add support for ikev2 printing
Update support for decoding AFS
Update DHCPv6 printer
Use newer libpcap API's (allows -B option on all platforms)
Add -I to turn on monitor mode
Bugfixes in lldp, lspping, dccp, ESP, NFS printers
Cleanup unused files and various cruft
Mon. September 10, 2007. ken@xelerance.com. Summary for 3.9.8 tcpdump release
Rework ARP printer
Rework OSPFv3 printer
Add support for Frame-Relay ARP
Decode DHCP Option 121 (RFC 3442 Classless Static Route)
Decode DHCP Option 249 (MS Classless Static Route) the same as Option 121
TLV: Add support for Juniper .pcap extensions
Print EGP header in new-world-order style
Converted print-isakmp.c to NETDISSECT
Moved AF specific stuff into af.h
Test subsystem now table driven, and saves outputs and diffs to one place
Require <net/pfvar.h> for pf definitions - allows reading of pflog formatted
libpcap files on an OS other than where the file was generated
Wed. July 23, 2007. mcr@xelerance.com. Summary for 3.9.7 libpcap release
NFS: Print unsigned values as such.
RX: parse safely.
BGP: fixes for IPv6-less builds.
801.1ag: use standard codepoint.
use /dev/bpf on systems with such a device.
802.11: print QoS data, avoid dissect of no-data frame, ignore padding.
smb: make sure that we haven't gone past the end of the captured data.
smb: squelch an uninitialized complaint from coverity.
NFS: from NetBSD; don't interpret the reply as a possible NFS reply
if it got MSG_DENIED.
BGP: don't print TLV values that didn't fit, from www.digit-labs.org.
revised INSTALL.txt about libpcap dependency.
Wed. April 25, 2007. ken@xelerance.com. Summary for 3.9.6 tcpdump release
Update man page to reflect changes to libpcap
Changes to both TCP and IP Printer Output
Fix a potential buffer overflow in the 802.11 printer
Print basic info about a few more Cisco LAN protocols.
mDNS cleanup
ICMP MPLS rework of the extension code
bugfix: use the correct codepoint for the OSPF simple text auth token
entry, and use safeputs to print the password.
Add support in pflog for additional values
Add support for OIF RSVP Extensions UNI 1.0 Rev. 2 and additional RSVP objects
Add support for the Message-id NACK c-type.
Add support for 802.3ah loopback ctrl msg
Add support for Multiple-STP as per 802.1s
Add support for rapid-SPT as per 802.1w
Add support for CFM Link-trace msg, Link-trace-Reply msg,
Sender-ID tlv, private tlv, port, interface status
Add support for unidirectional link detection as per
https://tools.ietf.org/id/draft-foschiano-udld-02.txt
Add support for the olsr protocol as per RFC 3626 plus the LQ
extensions from olsr.org
Add support for variable-length checksum in DCCP, as per section 9 of
RFC 4340.
Add support for per-VLAN spanning tree and per-VLAN rapid spanning tree
Add support for Multiple-STP as per 802.1s
- Add support for the cisco propriatry 'dynamic trunking protocol'
+ Add support for the cisco proprietary 'dynamic trunking protocol'
Add support for the cisco proprietary VTP protocol
Update dhcp6 options table as per IETF standardization activities
Tue. September 19, 2006. ken@xelerance.com. Summary for 3.9.5 tcpdump release
Fix compiling on AIX (, at end of ENUM)
Updated list of DNS RR typecodes
Use local Ethernet defs on WIN32
Add support for Frame-Relay ARP
Fixes for compiling under MSVC++
Add support for parsing Juniper .pcap files
Add support for FRF.16 Multilink Frame-Relay (DLT_MFR)
Rework the OSPFv3 printer
Fix printing for 4.4BSD/NetBSD NFS Filehandles
Add support for Cisco style NLPID encapsulation
Add cisco prop. eigrp related, extended communities
Add support for BGP signaled VPLS
Cleanup the bootp printer
Add support for PPP over Frame-Relay
Add some bounds checking to the IP options code, and clean up
the options output a bit.
Add additional modp groups to ISAKMP printer
Add support for Address-Withdraw and Label-Withdraw Msgs
Add support for the BFD Discriminator TLV
Fixes for 64bit compiling
Add support for PIMv2 checksum verification
Add support for further dissection of the IPCP Compression Option
Add support for Cisco's proposed VQP protocol
Add basic support for keyed authentication TCP option
Lots of minor cosmetic changes to output printers
Mon. September 19, 2005. ken@xelerance.com. Summary for 3.9.4 tcpdump release
Decoder support for more Juniper link-layer types
Fix a potential buffer overflow (although it can't occur in
practice).
Fix the handling of unknown management frame types in the 802.11
printer.
Add FRF.16 support, fix various Frame Relay bugs.
Add support for RSVP integrity objects, update fast-reroute
object printer to latest spec.
Clean up documentation of vlan filter expression, document mpls
filter expression.
Document new pppoed and pppoes filter expressions.
Update diffserver-TE codepoints as per RFC 4124.
Spelling fixes in ICMPv6.
Don't require any fields other than flags to be present in IS-IS
restart signaling TLVs, and only print the system ID in
those TLVs as system IDs, not as node IDs.
Support for DCCP.
Tue. July 5, 2005. ken@xelerance.com. Summary for 3.9.3 tcpdump release
Option to chroot() when dropping privs
Fixes for compiling on nearly every platform,
including improved 64bit support
Many new testcases
Support for sending packets
Many compilation fixes on most platforms
Fixes for recent version of GCC to eliminate warnings
Improved Unicode support
Decoders & DLT Changes, Updates and New:
AES ESP support
Juniper ATM, FRF.15, FRF.16, PPPoE,
ML-FR, ML-PIC, ML-PPP, PL-PPP, LS-PIC
GGSN,ES,MONITOR,SERVICES
L2VPN
Axent Raptor/Symantec Firewall
TCP-MD5 (RFC 2385)
ESP-in-UDP (RFC 3948)
ATM OAM
LMP, LMP Service Discovery
IP over FC
IP over IEEE 1394
BACnet MS/TP
SS7
LDP over TCP
LACP, MARKER as per 802.3ad
PGM (RFC 3208)
LSP-PING
G.7041/Y.1303 Generic Framing Procedure
EIGRP-IP, EIGRP-IPX
ICMP6
Radio - via radiotap
DHCPv6
HDLC over PPP
Tue. March 30, 2004. mcr@sandelman.ottawa.on.ca. Summary for 3.8.3 release
No changes from 3.8.2. Version bumped only to maintain consistency
with libpcap 0.8.3.
Mon. March 29, 2004. mcr@sandelman.ottawa.on.ca. Summary for 3.8.2 release
Fixes for print-isakmp.c CVE: CAN-2004-0183, CAN-2004-0184
https://web.archive.org/web/20160328035955/https://www.rapid7.com/resources/advisories/R7-0017.jsp
IP-over-IEEE1394 printing.
some MINGW32 changes.
updates for autoconf 2.5
fixes for print-aodv.c - check for too short packets
formatting changes to print-ascii for hex output.
check for too short packets: print-bgp.c, print-bootp.c, print-cdp.c,
print-chdlc.c, print-domain.c, print-icmp.c, print-icmp6.c,
print-ip.c, print-lwres.c, print-ospf.c, print-pim.c,
print-ppp.c,print-pppoe.c, print-rsvp.c, print-wb.c
print-ether.c - better handling of unknown types.
print-isoclns.c - additional decoding of types.
print-llc.c - strings for LLC names added.
print-pfloc.c - various enhancements
print-radius.c - better decoding to strings.
Wed. November 12, 2003. mcr@sandelman.ottawa.on.ca. Summary for 3.8 release
changed syntax of -E argument so that multiple SAs can be decrypted
fixes for Digital Unix headers and Documentation
__attribute__ fixes
CDP changes from Terry Kennedy <terry@tmk.com>.
IPv6 mobility updates from Kazushi Sugyo <sugyo@pb.jp.nec.com>
Fixes for ASN.1 decoder for 2.100.3 forms.
Added a count of packets received and processed to clarify numbers.
Incorporated WinDUMP patches for Win32 builds.
PPPoE payload length headers.
Fixes for HP C compiler builds.
Use new pcap_breakloop() and pcap_findalldevs() if we can.
BGP output split into multiple lines.
Fixes to 802.11 decoding.
Fixes to PIM decoder.
SuperH is a CPU that can't handle unaligned access. Many fixes for
unaligned access work.
Fixes to Frame-Relay decoder for Q.933/922 frames.
Clarified when Solaris can do captures as non-root.
Added tests/ subdir for examples/regression tests.
New -U flag. -flush stdout after every packet
New -A flag -print ascii only
support for decoding IS-IS inside Cisco HDLC Frames
more verbosity for tftp decoder
mDNS decoder
new BFD decoder
cross compilation patches
RFC 3561 AODV support.
UDP/TCP pseudo-checksum properly for source-route options.
sanitized all files to modified BSD license
Add support for RFC 2625 IP-over-Fibre Channel.
fixes for DECnet support.
Support RFC 2684 bridging of Ethernet, 802.5 Token Ring, and FDDI.
RFC 2684 encapsulation of BPDUs.
Tuesday, February 25, 2003. fenner@research.att.com. 3.7.2 release
Fixed infinite loop when parsing invalid isakmp packets.
(reported by iDefense; already fixed in CVS)
Fixed infinite loop when parsing invalid BGP packets.
Fixed buffer overflow with certain invalid NFS packets.
Pretty-print unprintable network names in 802.11 printer.
Handle truncated nbp (appletalk) packets.
Updated DHCPv6 printer to match draft-ietf-dhc-dhcpv6-22.txt
Print IP protocol name even if we don't have a printer for it.
Print IP protocol name or number for fragments.
Print the whole MPLS label stack, not just the top label.
Print request header and file handle for NFS v3 FSINFO and PATHCONF
requests.
Fix NFS packet truncation checks.
Handle "old" DR-Priority and Bidir-Capable PIM HELLO options.
Handle unknown RADIUS attributes properly.
Fix an ASN.1 parsing error that would cause e.g. the OID
2.100.3 to be misrepresented as 4.20.3 .
Monday, January 21, 2002. mcr@sandelman.ottawa.on.ca. Summary for 3.7 release
keyword "ipx" added.
Better OSI/802.2 support on Linux.
IEEE 802.11 support, from clenahan@fortresstech.com, achirica@ttd.net.
LLC SAP support for FDDI/token ring/RFC-1483 style ATM
BXXP protocol was replaced by the BEEP protocol;
improvements to SNAP demux.
Changes to "any" interface documentation.
Documentation on pcap_stats() counters.
Fix a memory leak found by Miklos Szeredi - pcap_ether_aton().
Added MPLS encapsulation decoding per RFC3032.
DNS dissector handles TKEY, TSIG and IXFR.
adaptive SLIP interface patch from Igor Khristophorov <igor@atdot.org>
SMB printing has much improved bounds checks
OUI 0x0000f8 decoded as encapsulated ethernet for Cisco-custom bridging
Zephyr support, from Nickolai Zeldovich <kolya@MIT.EDU>.
Solaris - devices with digits in them. Stefan Hudson <hudson@mbay.net>
IPX socket 0x85be is for Cisco EIGRP over IPX.
Improvements to fragmented ESP handling.
SCTP support from Armando L. Caro Jr. <acaro@mail.eecis.udel.edu>
Linux ARPHDR_ATM support fixed.
Added a "netbeui" keyword, which selects NetBEUI packets.
IPv6 ND improvements, MobileIP dissector, 2292bis-02 for RA option.
Handle ARPHDR_HDLC from Marcus Felipe Pereira <marcus@task.com.br>.
Handle IPX socket 0x553 -> NetBIOS-over-IPX socket, "nwlink-dgm"
Better Linux libc5 compat.
BIND9 lwres dissector added.
MIPS and SPARC get strict alignment macros (affects print-bgp.c)
Apple LocalTalk LINKTYPE_ reserved.
New time stamp formats documented.
DHCP6 updated to draft-22.txt spec.
ICMP types/codes now accept symbolic names.
Add SIGINFO handler from LBL
encrypted CIPE tunnels in IRIX, from Franz Schaefer <schaefer@mond.at>.
now we are -Wstrict-prototype clean.
NetBSD DLT_PPP_ETHER; adapted from Martin Husemann <martin@netbsd.org>.
PPPoE dissector cleaned up.
Support for LocalTalk hardware, from Uns Lider <unslider@miranda.org>.
In dissector, now the caller prints the IP addresses rather than proto.
cjclark@alum.mit.edu: print the IP proto for non-initial fragments.
LLC frames with a DSAP and LSAP of 0xe0 are IPX frames.
Linux cooked frames with a type value of LINUX_SLL_P_802_3 are IPX.
captures on the "any" device won't be done in promiscuous mode
Token Ring support on DLPI - Onno van der Linden <onno@simplex.nl>
ARCNet support, from NetBSD.
HSRP dissector, from Julian Cowley <julian@lava.net>.
Handle (GRE-encapsulated) PPTP
added -C option to rotate save file every optarg * 1,000,000 bytes.
support for "vrrp" name - NetBSD, by Klaus Klein <kleink@netbsd.org>.
PPTP support, from Motonori Shindo <mshindo@mshindo.net>.
IS-IS over PPP support, from Hannes Gredler <hannes@juniper.net>.
CNFP support for IPv6,format. Harry Raaymakers <harryr@connect.com.au>.
ESP printing updated to RFC2406.
HP-UX can now handle large number of PPAs.
MSDP printer added.
L2TP dissector improvements from Motonori Shindo.
Tuesday January 9, 2001. mcr@sandelman.ottawa.on.ca. Summary for 3.6 release
Cleaned up documentation.
Promisc mode fixes for Linux
IPsec changes/cleanups.
Alignment fixes for picky architectures
Removed dependency on native headers for packet dissectors.
Removed Linux specific headers that were shipped
libpcap changes provide for exchanging capture files between
systems. Save files now have well known PACKET_ values instead of
depending upon system dependent mappings of DLT_* types.
Support for computing/checking IP and UDP/TCP checksums.
Updated autoconf stock files.
IPv6 improvements: dhcp (draft-15), mobile-ip6, ppp, ospf6,
Added dissector support for: ISOCLNS, Token Ring, IGMPv3, bxxp,
timed, vrrp, radius, chdlc, cnfp, cdp, IEEE802.1d, raw-AppleTalk
Added filtering support for: VLANs, ESIS, ISIS
Improvements to: print-telnet, IPTalk, bootp/dhcp, ECN, PPP,
L2TP, PPPoE
HP-UX 11.0 -- find the right dlpi device.
Solaris 8 - IPv6 works
Linux - Added support for an "any" device to capture on all interfaces
Security fixes: buffer overrun audit done. Strcpy replaced with
strlcpy, sprintf replaced with snprintf.
Look for lex problems, and warn about them.
v3.5 Fri Jan 28 18:00:00 PST 2000
Bill Fenner <fenner@research.att.com>
- switch to config.h for autoconf
- unify RCSID strings
- Updated PIMv1, PIMv2, DVMRP, IGMP parsers, add Cisco Auto-RP parser
- Really fix the RIP printer
- Fix MAC address -> name translation.
- some -Wall -Wformat fixes
- update makemib to parse much of SMIv2
- Print TCP sequence # with -vv even if you normally wouldn't
- Print as much of IP/TCP/UDP headers as possible even if truncated.
itojun@iijlab.net
- -X will make a ascii dump. from netbsd.
- telnet command sequence decoder (ff xx xx). from netbsd.
- print-bgp.c: improve options printing. ugly code exists for
unaligned option parsing (need some fix).
- const poisoning in SMB decoder.
- -Wall -Werror clean checks.
- bring in KAME IPv6/IPsec decoding code.
Assar Westerlund <assar@sics.se>
- SNMPv2 and SNMPv3 printer
- If compiled with libsmi, tcpdump can load MIBs on the fly to decode
SNMP packets.
- Incorporate NFS parsing code from NetBSD. Adds support for nfsv3.
- portability fixes
- permit building in different directories.
Ken Hornstein <kenh@cmf.nrl.navy.mil>
- bring in code at
/afs/transarc.com/public/afs-contrib/tools/tcpdump for parsing
AFS3 packets
Andrew Tridgell <tridge@linuxcare.com>
- SMB printing code
Love <lha@stacken.kth.se>
- print-rx.c: add code for printing MakeDir and StoreStatus. Also
change date format to the right one.
Michael C. Richardson <mcr@sandelman.ottawa.on.ca>
- Created tcpdump.org repository
v3.4 Sat Jul 25 12:40:55 PDT 1998
- Hardwire Linux slip support since it's too hard to detect.
- Redo configuration of "network" libraries (-lsocket and -lnsl) to
deal with IRIX. Thanks to John Hawkinson (jhawk@mit.edu)
- Added -a which tries to translate network and broadcast addresses to
names. Suggested by Rob van Nieuwkerk (robn@verdi.et.tudelft.nl)
- Added a configure option to disable gcc.
- Added a "raw" packet printer.
- Not having an interface address is no longer fatal. Requested by John
Hawkinson.
- Rework signal setup to accommodate Linux.
- OSPF truncation check fix. Also display the type of OSPF packets
using MD5 authentication. Thanks to Brian Wellington
(bwelling@tis.com)
- Fix truncation check bugs in the Kerberos printer. Reported by Ezra
Peisach (epeisach@mit.edu)
- Don't catch SIGHUP when invoked with nohup(1). Thanks to Dave Plonka
(plonka@mfa.com)
- Specify full install target as a way of detecting if install
directory does not exist. Thanks to Dave Plonka.
- Bit-swap FDDI addresses for BSD/OS too. Thanks to Paul Vixie
(paul@vix.com)
- Fix off-by-one bug when testing size of ethernet packets. Thanks to
Marty Leisner (leisner@sdsp.mc.xerox.com)
- Add a local autoconf macro to check for routines in libraries; the
autoconf version is broken (it only puts the library name in the
cache variable name). Thanks to John Hawkinson.
- Add a local autoconf macro to check for types; the autoconf version
is broken (it uses grep instead of actually compiling a code fragment).
- Modified to support the new BSD/OS 2.1 PPP and SLIP link layer header
formats.
- Extend OSF ip header workaround to versions 1 and 2.
- Fix some signed problems in the nfs printer. As reported by David
Sacerdote (davids@silence.secnet.com)
- Detect group wheel and use it as the default since BSD/OS' install
can't hack numeric groups. Reported by David Sacerdote.
- AIX needs special loader options. Thanks to Jonathan I. Kamens
(jik@cam.ov.com)
- Fixed the nfs printer to print port numbers in decimal. Thanks to
Kent Vander Velden (graphix@iastate.edu)
- Find installed libpcap in /usr/local/lib when not using gcc.
- Disallow network masks with non-network bits set.
- Attempt to detect "egcs" versions of gcc.
- Add missing closing double quotes when displaying bootp strings.
Reported by Viet-Trung Luu (vluu@picard.math.uwaterloo.ca)
v3.3 Sat Nov 30 20:56:27 PST 1996
- Added Linux support.
- GRE encapsulated packet printer thanks to John Hawkinson
(jhawk@mit.edu)
- Rewrite gmt2local() to avoid problematic os dependencies.
- Suppress nfs truncation message on errors.
- Add missing m4 quoting in AC_LBL_UNALIGNED_ACCESS autoconf macro.
Reported by Joachim Ott (ott@ardala.han.de)
- Enable "ip_hl vs. ip_vhl" workaround for OSF4 too.
- Print arp hardware type in host order. Thanks to Onno van der Linden
(onno@simplex.nl)
- Avoid solaris compiler warnings. Thanks to Bruce Barnett
(barnett@grymoire.crd.ge.com)
- Fix rip printer to not print one more route than is actually in the
packet. Thanks to Jean-Luc Richier (Jean-Luc.Richier@imag.fr) and
Bill Fenner (fenner@parc.xerox.com)
- Use autoconf endian detection since BYTE_ORDER isn't defined on all systems.
- Fix dvmrp printer truncation checks and add a dvmrp probe printer.
Thanks to Danny J. Mitzel (mitzel@ipsilon.com)
- Rewrite ospf printer to improve truncation checks.
- Don't parse tcp options past the EOL. As noted by David Sacerdote
(davids@secnet.com). Also, check tcp options to make sure they ar
actually in the tcp header (in addition to the normal truncation
checks). Fix the SACK code to print the N blocks (instead of the
first block N times).
- Don't say really small UDP packets are truncated just because they
aren't big enough to be a RPC. As noted by David Sacerdote.
v3.2.1 Sun Jul 14 03:02:26 PDT 1996
- Added rfc1716 icmp codes as suggested by Martin Fredriksson
(martin@msp.se)
- Print mtu for icmp unreach need frag packets. Thanks to John
Hawkinson (jhawk@mit.edu)
- Decode icmp router discovery messages. Thanks to Jeffrey Honig
(jch@bsdi.com)
- Added a printer entry for DLT_IEEE802 as suggested by Tak Kushida
(kushida@trl.ibm.co.jp)
- Check igmp checksum if possible. Thanks to John Hawkinson.
- Made changes for SINIX. Thanks to Andrej Borsenkow
(borsenkow.msk@sni.de)
- Use autoconf's idea of the top level directory in install targets.
Thanks to John Hawkinson.
- Avoid infinite loop in tcp options printing code. Thanks to Jeffrey
Mogul (mogul@pa.dec.com)
- Avoid using -lsocket in IRIX 5.2 and earlier since it breaks snoop.
Thanks to John Hawkinson.
- Added some more packet truncation checks.
- On systems that have it, use sigset() instead of signal() since
signal() has different semantics on these systems.
- Fixed some more alignment problems on the alpha.
- Add code to massage unprintable characters in the domain and ipx
printers. Thanks to John Hawkinson.
- Added explicit netmask support. Thanks to Steve Nuchia
(steve@research.oknet.com)
- Add "sca" keyword (for DEC cluster services) as suggested by Terry
Kennedy (terry@spcvxa.spc.edu)
- Add "atalk" keyword as suggested by John Hawkinson.
- Added an igrp printer. Thanks to Francis Dupont
(francis.dupont@inria.fr)
- Print IPX net numbers in hex a la Novell Netware. Thanks to Terry
Kennedy (terry@spcvxa.spc.edu)
- Fixed snmp extended tag field parsing bug. Thanks to Pascal Hennequin
(pascal.hennequin@hugo.int-evry.fr)
- Added some ETHERTYPEs missing on some systems.
- Added truncated packet macros and various checks.
- Fixed endian problems with the DECnet printer.
- Use $CC when checking gcc version. Thanks to Carl Lindberg
(carl_lindberg@blacksmith.com)
- Fixes for AIX (although this system is not yet supported). Thanks to
John Hawkinson.
- Fix bugs in the autoconf misaligned accesses code fragment.
- Include sys/param.h to get BYTE_ORDER in a few places. Thanks to
Pavlin Ivanov Radoslavov (pavlin@cs.titech.ac.jp)
v3.2 Sun Jun 23 02:28:10 PDT 1996
- Print new icmp unreachable codes as suggested by Martin Fredriksson
(martin@msp.se). Also print code value when unknown for icmp redirect
and time exceeded.
- Fix an alignment endian bug in getname(). Thanks to John Hawkinson.
- Define "new" domain record types if not found in arpa/nameserv.h.
Resulted from a suggestion from John Hawkinson (jhawk@mit.edu). Also
fixed an endian bug when printing mx record and added some new record
types.
- Added RIP V2 support. Thanks to Jeffrey Honig (jch@bsdi.com)
- Added T/TCP options printing. As suggested by Richard Stevens
(rstevens@noao.edu)
- Use autoconf to detect architectures that can't handle misaligned
accesses.
v3.1 Thu Jun 13 20:59:32 PDT 1996
- Changed u_int32/int32 to u_int32_t/int32_t to be consistent with bsd
and bind (as suggested by Charles Hannum).
- Port to GNU autoconf.
- Add support for printing DVMRP and PIM traffic thanks to
Havard Eidnes (Havard.Eidnes@runit.sintef.no).
- Fix AppleTalk, IPX and DECnet byte order problems due to wrong endian
define being referenced. Reported by Terry Kennedy.
- Minor fixes to the man page thanks to Mark Andrews.
- Endian fixes to RTP and vat packet dumpers, thanks to Bruce Mah
(bmah@cs.berkeley.edu).
- Added support for new dns types, thanks to Rainer Orth.
- Fixed tftp_print() to print the block number for ACKs.
- Document -dd and -ddd. Resulted from a bug report from Charlie Slater
(cslater@imatek.com).
- Check return status from malloc/calloc/etc.
- Check return status from pcap_loop() so we can print an error and
exit with a bad status if there were problems.
- Bail if ip option length is <= 0. Resulted from a bug report from
Darren Reed (darrenr@vitruvius.arbld.unimelb.edu.au).
- Print out a little more information for sun rpc packets.
- Add support for Kerberos 4 thanks to John Hawkinson (jhawk@mit.edu).
- Fixed the Fix EXTRACT_SHORT() and EXTRACT_LONG() macros (which were
wrong on little endian machines).
- Fixed alignment bug in ipx_decode(). Thanks to Matt Crawford
(crawdad@fnal.gov).
- Fix ntp_print() to not print garbage when the stratum is
"unspecified." Thanks to Deus Ex Machina (root@belle.bork.com).
- Rewrote tcp options printer code to check for truncation. Added
selective acknowledgment case.
- Fixed an endian bug in the ospf printer. Thanks to Jeffrey C Honig
(jch@bsdi.com)
- Fix rip printer to handle 4.4 BSD sockaddr struct which only uses one
octet for the sa_family member. Thanks to Yoshitaka Tokugawa
(toku@dit.co.jp)
- Don't checksum ip header if we don't have all of it. Thanks to John
Hawkinson (jhawk@mit.edu).
- Print out hostnames if possible in egp printer. Thanks to Jeffrey
Honig (jhc@bsdi.com)
v3.1a1 Wed May 3 19:21:11 PDT 1995
- Include time.h when SVR4 is defined to avoid problems under Solaris
2.3.
- Fix etheraddr_string() in the ETHER_SERVICE to return the saved
strings, not the local buffer. Thanks to Stefan Petri
(petri@ibr.cs.tu-bs.de).
- Detect when pcap raises the snaplen (e.g. with snit). Print a warning
that the selected value was not used. Thanks to Pascal Hennequin
(Pascal.Hennequin@hugo.int-evry.fr).
- Add a truncated packet test to print-nfs.c. Thanks to Pascal Hennequin.
- BYTEORDER -> BYTE_ORDER Thanks to Terry Kennedy (terry@spcvxa.spc.edu).
v3.0.3 Sun Oct 1 18:35:00 GMT 1995
- Although there never was a 3.0.3 release, the linux boys cleverly
"released" one in late 1995.
v3.0.2 Thu Apr 20 21:28:16 PDT 1995
- Change configuration to not use gcc v2 flags with gcc v1.
- Redo gmt2local() so that it works under BSDI (which seems to return
an empty timezone struct from gettimeofday()). Based on report from
Terry Kennedy (terry@spcvxa.spc.edu).
- Change configure to recognize IP[0-9]* as "mips" SGI hardware. Based
on report from Mark Andrews (mandrews@alias.com).
- Don't pass cc flags to gcc. Resulted from a bug report from Rainer
Orth (ro@techfak.uni-bielefeld.de).
- Fixed printout of connection id for uncompressed tcp slip packets.
Resulted from a bug report from Richard Stevens (rstevens@noao.edu).
- Hack around deficiency in Ultrix's make.
- Add ETHERTYPE_TRAIL define which is missing from irix5.
v3.0.1 Wed Aug 31 22:42:26 PDT 1994
- Fix problems with gcc2 vs. malloc() and read() prototypes under SunOS 4.
v3.0 Mon Jun 20 19:23:27 PDT 1994
- Added support for printing tcp option timestamps thanks to
Mark Andrews (mandrews@alias.com).
- Reorganize protocol dumpers to take const pointers to packets so they
never change the contents (i.e., they used to do endian conversions
in place). Previously, whenever more than one pass was taken over
the packet, the packet contents would be dumped incorrectly (i.e.,
the output form -x would be wrong on little endian machines because
the protocol dumpers would modify the data). Thanks to Charles Hannum
(mycroft@gnu.ai.mit.edu) for reporting this problem.
- Added support for decnet protocol dumping thanks to Jeff Mogul
(mogul@pa.dec.com).
- Fix bug that caused length of packet to be incorrectly printed
(off by ether header size) for unknown ethernet types thanks
to Greg Miller (gmiller@kayak.mitre.org).
- Added support for IPX protocol dumping thanks to Brad Parker
(brad@fcr.com).
- Added check to verify IP header checksum under -v thanks to
Brad Parker (brad@fcr.com).
- Move packet capture code to new libpcap library (which is
packaged separately).
- Prototype everything and assume an ansi compiler.
- print-arp.c: Print hardware ethernet addresses if they're not
what we expect.
- print-bootp.c: Decode the cmu vendor field. Add RFC1497 tags.
Many helpful suggestions from Gordon Ross (gwr@jericho.mc.com).
- print-fddi.c: Improvements. Thanks to Jeffrey Mogul
(mogul@pa.dec.com).
- print-icmp.c: Byte swap netmask before printing. Thanks to
Richard Stevens (rstevens@noao.edu). Print icmp type when unknown.
- print-ip.c: Print the inner ip datagram of ip-in-ip encapsulated packets.
By default, only the inner packet is dumped, appended with the token
"(encap)". Under -v, both the inner and output packets are dumped
(on the same line). Note that the filter applies to the original packet,
not the encapsulated packet. So if you run tcpdump on a net with an
IP Multicast tunnel, you cannot filter out the datagrams using the
conventional syntax. (You can filter away all the ip-in-ip traffic
with "not ip proto 4".)
- print-nfs.c: Keep pending rpc's in circular table. Add generic
nfs header and remove os dependences. Thanks to Jeffrey Mogul.
- print-ospf.c: Improvements. Thanks to Jeffrey Mogul.
- tcpdump.c: Add -T flag allows interpretation of "vat", "wb", "rpc"
(sunrpc) and rtp packets. Added "inbound" and "outbound" keywords
Add && and || operators
v2.2.1 Tue Jun 6 17:57:22 PDT 1992
- Fix bug with -c flag.
v2.2 Fri May 22 17:19:41 PDT 1992
- savefile.c: Remove hack that shouldn't have been exported. Add
truncate checks.
- Added the 'icmp' keyword. For example, 'icmp[0] != 8 and icmp[0] != 0'
matches non-echo/reply ICMP packets.
- Many improvements to filter code optimizer.
- Added 'multicast' keyword and extended the 'broadcast' keyword can now be
so that protocol qualifications are allowed. For example, "ip broadcast"
and "ether multicast" are valid filters.
- Added support for monitoring the loopback interface (i.e. 'tcpdump -i lo').
Jeffrey Honig (jch@MITCHELL.CIT.CORNELL.EDU) contributed the kernel
patches to netinet/if_loop.c.
- Added support for the Ungermann-Bass Ethernet on IBM/PC-RTs running AOS.
Contact Jeffrey Honig (jch@MITCHELL.CIT.CORNELL.EDU) for the diffs.
- Added EGP and OSPF printers, thanks to Jeffrey Honig.
v2.1 Tue Jan 28 11:00:14 PST 1992
- Internal release (never publicly exported).
v2.0.1 Sun Jan 26 21:10:10 PDT
- Various byte ordering fixes.
- Add truncation checks.
- inet.c: Support BSD style SIOCGIFCONF.
- nametoaddr.c: Handle multi addresses for single host.
- optimize.c: Rewritten.
- pcap-bpf.c: don't choke when we get ptraced. only set promiscuous
for broadcast nets.
- print-atal.c: Fix an alignment bug (thanks to
stanonik@nprdc.navy.mil) Add missing printf() argument.
- print-bootp.c: First attempt at decoding the vendor buffer.
- print-domain.c: Fix truncation checks.
- print-icmp.c: Calculate length of packets from the ip header.
- print-ip.c: Print frag id in decimal (so it's easier to match up
with non-frags). Add support for ospf, egp and igmp.
- print-nfs.c: Lots of changes.
- print-ntp.c: Make some verbose output depend on -v.
- print-snmp.c: New version from John LoVerso.
- print-tcp.c: Print rfc1072 tcp options.
- tcpdump.c: Print "0x" prefix for %x formats. Always print 6 digits
(microseconds) worth of precision. Fix uid bugs.
- A packet dumper has been added (thanks to Jeff Mogul of DECWRL).
With this option, you can create an architecture independent binary
trace file in real time, without the overhead of the packet printer.
At a later time, the packets can be filtered (again) and printed.
- BSD is supported. You must have BPF in your kernel.
Since the filtering is now done in the kernel, fewer packets are
dropped. In fact, with BPF and the packet dumper option, a measly
Sun 3/50 can keep up with a busy network.
- Compressed SLIP packets can now be dumped, provided you use our
SLIP software and BPF. These packets are dumped as any other IP
packet; the compressed headers are dumped with the '-e' option.
- Machines with little-endian byte ordering are supported (thanks to
Jeff Mogul).
- Ultrix 4.0 is supported (also thanks to Jeff Mogul).
- IBM RT and Stanford Enetfilter support has been added by
- Rayan Zachariassen <rayan@canet.ca>. Tcpdump has been tested under
+ Rayan Zachariassen <rayan@canet.ca>. tcpdump has been tested under
both the vanilla Enetfilter interface, and the extended interface
(#ifdef'd by IBMRTPC) present in the MERIT version of the Enetfilter.
- TFTP packets are now printed (requests only).
- BOOTP packets are now printed.
- SNMP packets are now printed. (thanks to John LoVerso of Xylogics).
- Sparc architectures, including the Sparcstation-1, are now
supported thanks to Steve McCanne and Craig Leres.
- SunOS 4 is now supported thanks to Micky Liu of Columbia
University (micky@cunixc.cc.columbia.edu).
- IP options are now printed.
- RIP packets are now printed.
- There's a -v flag that prints out more information than the
default (e.g., it will enable printing of IP ttl, tos and id)
and -q flag that prints out less (e.g., it will disable
interpretation of AppleTalk-in-UDP).
- The grammar has undergone substantial changes (if you have an
earlier version of tcpdump, you should re-read the manual
entry).
The most useful change is the addition of an expression
syntax that lets you filter on arbitrary fields or values in the
packet. E.g., "ip[0] > 0x45" would print only packets with IP
options, "tcp[13] & 3 != 0" would print only TCP SYN and FIN
packets.
The most painful change is that concatenation no longer means
"and" -- e.g., you have to say "host foo and port bar" instead
of "host foo port bar". The up side to this down is that
repeated qualifiers can be omitted, making most filter
expressions shorter. E.g., you can now say "ip host foo and
(bar or baz)" to look at ip traffic between hosts foo and bar or
between hosts foo and baz. [The old way of saying this was "ip
host foo and (ip host bar or ip host baz)".]
v2.0 Sun Jan 13 12:20:40 PST 1991
- Initial public release.
diff --git a/contrib/tcpdump/CMakeLists.txt b/contrib/tcpdump/CMakeLists.txt
index 9495b5d4c234..f9071295eff1 100644
--- a/contrib/tcpdump/CMakeLists.txt
+++ b/contrib/tcpdump/CMakeLists.txt
@@ -1,1371 +1,1566 @@
if(WIN32)
#
# We need 3.12 or later, so that we can set policy CMP0074; see
# below.
+ #
cmake_minimum_required(VERSION 3.12)
else(WIN32)
#
- # For now, require only 2.8.6, just in case somebody is
- # configuring with CMake on a "long-term support" version
- # of some OS and that version supplies an older version of
- # CMake.
+ # For now:
+ #
+ # if this is a version of CMake less than 3.5, require only
+ # 2.8.12, just in case somebody is configuring with CMake
+ # on a "long-term support" version # of some OS and that
+ # version supplies an older version of CMake;
#
- # If this is ever updated to CMake 3.1 or later, remove the
- # stuff in cmake/Modules/FindPCAP.cmake that appends subdirectories
- # of directories from CMAKE_PREFIX_PATH to the PKG_CONFIG_PATH
- # environment variable when running pkg-config, to make sure
- # it finds any .pc file from there.
+ # otherwise, require 3.5, so we don't get messages warning
+ # that support for versions of CMake lower than 3.5 is
+ # deprecated.
#
- cmake_minimum_required(VERSION 2.8.12)
+ if(CMAKE_VERSION VERSION_LESS "3.5")
+ cmake_minimum_required(VERSION 2.8.12)
+ else()
+ cmake_minimum_required(VERSION 3.5)
+ endif()
endif(WIN32)
#
# We want find_path() and find_library() to honor {packagename}_ROOT,
# as that appears to be the standard way to say "hey, look here for
# this package" from the command line.
#
if(POLICY CMP0074)
cmake_policy(SET CMP0074 NEW)
endif()
#
# OK, this is a pain.
#
# When building on NetBSD, with a libpcap installed from pkgsrc,
# a -Wl,-rpath,/usr/pkg/lib option is added to the options when
# linking tcpdump. This puts /usr/pkg/lib into the run-time path.
#
# However, by default, CMake adds a rule to the install CMake script
# a CMake command (using an undocumented subcommand of file()) that
# strips /usr/pkg/lib *out* of the run-time path; the message in the
# output for the "install" target is
#
# -- Set runtime path of "{target-directory}/tcpdump" to ""
#
# I am not certain what the rationale is for doing this, but a
# *consequence* of this is that, when you run the installed tcpdump,
# it fails to find libpcap.so:
#
# $ {target-directory}/tcpdump -h
# {target-directory}/tcpdump: Shared object "libpcap.so.0" not found
#
# It also appears to be the case that, on Ubuntu 22.04, FreeBSD 12,
# DragonFly BSD 5.8, OpenBSD 6.6, and Solaris 11.4,
#
# On Ubuntu and Solaris, even if you have a libpcap in /usr/local, you
# have to provide not only -I/usr/local/include and -L/usr/local/lib,
# you also must provide -Wl,-rpath,/usr/local/lib in order to have
# the run-time linker look in /usr/local/lib for libpcap. If it's not
# specified, then, if the shared library major version number of the
# libpcap in /usr/lib is the same as the shared major version number
# of the libpcap in /usr/local/lib, the run-time linker will find the
# libpcap in /usr/lib; if the versions are different, the run-time
# linker will fail to find the libpcap in /usr/lib, so the program will
# fail to run.
#
# We suppress this by setting CMAKE_INSTALL_RPATH_USE_LINK_PATH to TRUE;
# as the documentation for that variable says:
#
# Add paths to linker search and installed rpath.
#
# CMAKE_INSTALL_RPATH_USE_LINK_PATH is a boolean that if set to True
# will append to the runtime search path (rpath) of installed
# binaries any directories outside the project that are in the linker
# search path or contain linked library files. The directories are
# appended after the value of the INSTALL_RPATH target property.
#
# If, for whatever reason, directories in which we search for external
# libraries, other than the standard system library directories, are
# added to the executable's rpath in the build process, we most
-# defintely want them in the installed image's rpath if they are
+# definitely want them in the installed image's rpath if they are
# necessary in order to find the libraries at run time.
#
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules)
#
-# OK, this is a royal pain.
+# We explicitly indicate what languages are used in tcpdump to avoid
+# checking for a C++ compiler.
+#
+# One reason to avoid that check is that there's no need to waste
+# configuration time performing it.
+#
+# Another reason is that:
#
# CMake will try to determine the sizes of some data types, including
# void *, early in the process of configuration; apparently, it's done
# as part of processing the project() command.
#
# At least as of CMake 2.8.6, it does so by checking the size of
# "void *" in C, setting CMAKE_C_SIZEOF_DATA_PTR based on that,
# setting CMAKE_SIZEOF_VOID_P to that, and then checking the size
# of "void *" in C++, setting CMAKE_CXX_SIZEOF_DATA_PTR based on
# that, and then setting CMAKE_SIZEOF_VOID_P to *that*.
#
# The compile tests include whatever C flags may have been provided
# to CMake in the CFLAGS and CXXFLAGS environment variables.
#
# If you set an architecture flag such as -m32 or -m64 in CFLAGS
# but *not* in CXXFLAGS, the size for C++ will win, and hilarity
# will ensue.
#
# Or if, at least on Solaris, you have a newer version of GCC
# installed, but *not* a newer version of G++, and you have Oracle
# Studio installed, it will find GCC, which will default to building
# 64-bit, and Oracle Studio's C++ compiler, which will default to
# building 32-bit, the size for C++ will win, and, again, hilarity
# will ensue.
#
-# So we *explicitly* state that only C is used; there is currently no
-# C++ code in tcpdump.
-#
project(tcpdump C)
+#
+# Export the size of void * as SIZEOF_VOID_P so that it can be
+# tested with #if.
+#
+set(SIZEOF_VOID_P "${CMAKE_SIZEOF_VOID_P}")
+
+#
+# Show the bit width for which we're compiling.
+# This can help debug problems if you're dealing with a compiler that
+# defaults to generating 32-bit code even when running on a 64-bit
+# platform, and where that platform may provide only 64-bit versions of
+# libraries that we might use (looking at *you*, Oracle Studio!).
+#
+if(CMAKE_SIZEOF_VOID_P EQUAL 4)
+ message(STATUS "Building 32-bit")
+elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)
+ message(STATUS "Building 64-bit")
+endif()
+
+#
+# Solaris pkg-config is annoying. For at least one package (D-Bus, I'm
+# looking at *you*!), there are separate include files for 32-bit and
+# 64-bit builds (I guess using "unsigned long long" as a 64-bit integer
+# type on a 64-bit build is like crossing the beams or something), and
+# there are two separate .pc files, so if we're doing a 32-bit build we
+# should make sure we look in /usr/lib/pkgconfig for .pc files and if
+# we're doing a 64-bit build we should make sure we look in
+# /usr/lib/amd64/pkgconfig for .pc files.
+#
+if(CMAKE_SYSTEM_NAME STREQUAL "SunOS" AND CMAKE_SYSTEM_VERSION MATCHES "5[.][0-9.]*")
+ #
+ # Note: string(REPLACE) does not appear to support using ENV{...}
+ # as an argument, so we set a variable and then use set() to set
+ # the environment variable.
+ #
+ if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+ #
+ # 64-bit build. If /usr/lib/pkgconfig appears in the path,
+ # prepend /usr/lib/amd64/pkgconfig to it; otherwise,
+ # put /usr/lib/amd64 at the end.
+ #
+ if((NOT DEFINED ENV{PKG_CONFIG_PATH}) OR "$ENV{PKG_CONFIG_PATH}" EQUAL "")
+ #
+ # Not set, or empty. Set it to /usr/lib/amd64/pkgconfig.
+ #
+ set(fixed_path "/usr/lib/amd64/pkgconfig")
+ elseif("$ENV{PKG_CONFIG_PATH}" MATCHES "/usr/lib/pkgconfig")
+ #
+ # It contains /usr/lib/pkgconfig. Prepend
+ # /usr/lib/amd64/pkgconfig to /usr/lib/pkgconfig.
+ #
+ string(REPLACE "/usr/lib/pkgconfig"
+ "/usr/lib/amd64/pkgconfig:/usr/lib/pkgconfig"
+ fixed_path "$ENV{PKG_CONFIG_PATH}")
+ else()
+ #
+ # Not empty, but doesn't contain /usr/lib/pkgconfig.
+ # Append /usr/lib/amd64/pkgconfig to it.
+ #
+ set(fixed_path "$ENV{PKG_CONFIG_PATH}:/usr/lib/amd64/pkgconfig")
+ endif()
+ set(ENV{PKG_CONFIG_PATH} "${fixed_path}")
+ elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
+ #
+ # 32-bit build. If /usr/amd64/lib/pkgconfig appears in the path,
+ # prepend /usr/lib/pkgconfig to it.
+ #
+ if("$ENV{PKG_CONFIG_PATH}" MATCHES "/usr/lib/amd64/pkgconfig")
+ #
+ # It contains /usr/lib/amd64/pkgconfig. Prepend
+ # /usr/lib/pkgconfig to /usr/lib/amd64/pkgconfig.
+ #
+ string(REPLACE "/usr/lib/amd64/pkgconfig"
+ "/usr/lib/pkgconfig:/usr/lib/amd64/pkgconfig"
+ fixed_path "$ENV{PKG_CONFIG_PATH}")
+ set(ENV{PKG_CONFIG_PATH} "${fixed_path}")
+ endif()
+ endif()
+endif()
+
#
# For checking if a compiler flag works and adding it if it does.
#
include(CheckCCompilerFlag)
macro(check_and_add_compiler_option _option)
message(STATUS "Checking C compiler flag ${_option}")
string(REPLACE "=" "-" _temp_option_variable ${_option})
string(REGEX REPLACE "^-" "" _option_variable ${_temp_option_variable})
check_c_compiler_flag("${_option}" ${_option_variable})
if(${${_option_variable}})
set(C_ADDITIONAL_FLAGS "${C_ADDITIONAL_FLAGS} ${_option}")
endif()
endmacro()
#
# If we're building with Visual Studio, we require Visual Studio 2015,
# in order to get sufficient C99 compatibility. Check for that.
#
# If not, try the appropriate flag for the compiler to enable C99
# features.
#
set(C_ADDITIONAL_FLAGS "")
if(MSVC)
if(MSVC_VERSION LESS 1900)
message(FATAL_ERROR "Visual Studio 2015 or later is required")
endif()
#
# Treat source files as being in UTF-8 with MSVC if it's not using
# the Clang front end.
# We assume that UTF-8 source is OK with other compilers and with
# MSVC if it's using the Clang front end.
#
if(NOT ${CMAKE_C_COMPILER} MATCHES "clang*")
set(C_ADDITIONAL_FLAGS "${C_ADDITIONAL_FLAGS} /utf-8")
endif(NOT ${CMAKE_C_COMPILER} MATCHES "clang*")
else(MSVC)
#
# Try to enable as many C99 features as we can.
# At minimum, we want C++/C99-style // comments.
#
# Newer versions of compilers might default to supporting C99, but
# older versions may require a special flag.
#
# Prior to CMake 3.1, setting CMAKE_C_STANDARD will not have any effect,
# so, unless and until we require CMake 3.1 or later, we have to do it
# ourselves on pre-3.1 CMake, so we just do it ourselves on all versions
# of CMake.
#
# Note: with CMake 3.1 through 3.5, the only compilers for which CMake
# handles CMAKE_C_STANDARD are GCC and Clang. 3.6 adds support only
# for Intel C; 3.9 adds support for PGI C, Sun C, and IBM XL C, and
# 3.10 adds support for Cray C and IAR C, but no version of CMake has
# support for HP C. Therefore, even if we use CMAKE_C_STANDARD with
# compilers for which CMake supports it, we may still have to do it
# ourselves on other compilers.
#
# See the CMake documentation for the CMAKE_<LANG>_COMPILER_ID variables
# for a list of compiler IDs.
#
# XXX - this just tests whether the option works and adds it if it does.
# We don't test whether it's necessary in order to get the C99 features
# that we use; if we ever have a user who tries to compile with a compiler
# that can't be made to support those features, we can add a test to make
# sure we actually *have* C99 support.
#
if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR
CMAKE_C_COMPILER_ID MATCHES "Clang")
check_and_add_compiler_option("-std=gnu99")
elseif(CMAKE_C_COMPILER_ID MATCHES "XL")
#
# We want support for extensions picked up for GNU C compatibility,
# so we use -qlanglvl=extc99.
#
check_and_add_compiler_option("-qlanglvl=extc99")
elseif(CMAKE_C_COMPILER_ID MATCHES "HP")
check_and_add_compiler_option("-AC99")
elseif(CMAKE_C_COMPILER_ID MATCHES "Sun")
check_and_add_compiler_option("-xc99")
elseif(CMAKE_C_COMPILER_ID MATCHES "Intel")
check_and_add_compiler_option("-c99")
endif()
endif(MSVC)
set(LIBRARY_NAME netdissect)
###################################################################
# Parameters
###################################################################
option(WITH_SMI "Build with libsmi, if available" ON)
option(WITH_CRYPTO "Build with OpenSSL/libressl libcrypto, if available" ON)
option(WITH_CAPSICUM "Build with Capsicum security functions, if available" ON)
option(WITH_CAP_NG "Use libcap-ng, if available" ON)
option(ENABLE_SMB "Build with the SMB dissector" OFF)
#
# String parameters. Neither of them are set, initially; only if the
# user explicitly configures them are they set.
#
# WITH_CHROOT is STRING, not PATH, as the directory need not exist
# when CMake is run.
#
set(WITH_CHROOT CACHE STRING
"Directory to which to chroot when dropping privileges")
set(WITH_USER CACHE STRING
"User to whom to set the UID when dropping privileges")
#
# By default, build universal with the appropriate set of architectures
# for the OS on which we're doing the build.
#
if(APPLE AND "${CMAKE_OSX_ARCHITECTURES}" STREQUAL "")
#
# Get the major version of Darwin.
#
string(REGEX MATCH "^([0-9]+)" SYSTEM_VERSION_MAJOR "${CMAKE_SYSTEM_VERSION}")
if(SYSTEM_VERSION_MAJOR EQUAL 9)
#
# Leopard. Build for x86 and 32-bit PowerPC, with
# x86 first. (That's what Apple does.)
#
set(CMAKE_OSX_ARCHITECTURES "i386;ppc")
elseif(SYSTEM_VERSION_MAJOR EQUAL 10)
#
# Snow Leopard. Build for x86-64 and x86, with
# x86-64 first. (That's what Apple does.)
#
set(CMAKE_OSX_ARCHITECTURES "x86_64;i386")
endif()
endif()
###################################################################
# Versioning
###################################################################
# Get, parse, format and set tcpdump's version string from
# [tcpdump_root]/VERSION for later use.
# Get MAJOR, MINOR, PATCH & SUFFIX
file(STRINGS ${tcpdump_SOURCE_DIR}/VERSION
PACKAGE_VERSION
LIMIT_COUNT 1 # Read only the first line
)
######################################
# Project settings
######################################
-add_definitions(-DHAVE_CONFIG_H)
-
include_directories(
${CMAKE_CURRENT_BINARY_DIR}
${tcpdump_SOURCE_DIR}
)
if(MSVC)
add_definitions(-D__STDC__)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
endif(MSVC)
if(MSVC)
if (USE_STATIC_RT)
MESSAGE(STATUS "Use STATIC runtime")
set(NAME_RT MT)
set (CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} /MT")
set (CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /MT")
set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
set (CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} /MT")
set (CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} /MT")
set (CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MT")
set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MTd")
else (USE_STATIC_RT)
MESSAGE(STATUS "Use DYNAMIC runtime")
set(NAME_RT MD)
set (CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} /MD")
set (CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /MD")
set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD")
set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MDd")
set (CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} /MD")
set (CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} /MD")
set (CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MD")
set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MDd")
endif (USE_STATIC_RT)
endif(MSVC)
###################################################################
# Detect available platform features
###################################################################
include(CMakePushCheckState)
include(CheckIncludeFile)
include(CheckIncludeFiles)
include(CheckFunctionExists)
include(CheckLibraryExists)
include(CheckSymbolExists)
include(CheckStructHasMember)
include(CheckVariableExists)
include(CheckTypeSize)
+#
+# Get the size of a time_t, to know whether it's 32-bit or 64-bit.
+#
+cmake_push_check_state()
+set(CMAKE_EXTRA_INCLUDE_FILES time.h)
+check_type_size("time_t" SIZEOF_TIME_T)
+cmake_pop_check_state()
+
#
# Header files.
#
-check_include_file(fcntl.h HAVE_FCNTL_H)
check_include_file(rpc/rpc.h HAVE_RPC_RPC_H)
check_include_file(net/if.h HAVE_NET_IF_H)
if(HAVE_RPC_RPC_H)
check_include_files("rpc/rpc.h;rpc/rpcent.h" HAVE_RPC_RPCENT_H)
endif(HAVE_RPC_RPC_H)
#
# Functions.
#
check_function_exists(strlcat HAVE_STRLCAT)
check_function_exists(strlcpy HAVE_STRLCPY)
check_function_exists(strdup HAVE_STRDUP)
check_function_exists(strsep HAVE_STRSEP)
#
# Find library needed for gethostbyaddr.
# NOTE: if you hand check_library_exists as its last argument a variable
# that's been set, it skips the test, so we need different variables.
#
set(TCPDUMP_LINK_LIBRARIES "")
if(WIN32)
#
# We need winsock2.h and ws2tcpip.h.
#
cmake_push_check_state()
set(CMAKE_REQUIRED_LIBRARIES ws2_32)
check_symbol_exists(gethostbyaddr "winsock2.h;ws2tcpip.h" LIBWS2_32_HAS_GETHOSTBYADDR)
cmake_pop_check_state()
if(LIBWS2_32_HAS_GETHOSTBYADDR)
set(TCPDUMP_LINK_LIBRARIES ws2_32 ${TCPDUMP_LINK_LIBRARIES})
else(LIBWS2_32_HAS_GETHOSTBYADDR)
message(FATAL_ERROR "gethostbyaddr is required, but wasn't found")
endif(LIBWS2_32_HAS_GETHOSTBYADDR)
else(WIN32)
check_function_exists(gethostbyaddr STDLIBS_HAVE_GETHOSTBYADDR)
if(NOT STDLIBS_HAVE_GETHOSTBYADDR)
check_library_exists(socket gethostbyaddr "" LIBSOCKET_HAS_GETHOSTBYADDR)
if(LIBSOCKET_HAS_GETHOSTBYADDR)
set(TCPDUMP_LINK_LIBRARIES ${TCPDUMP_LINK_LIBRARIES} socket)
else(LIBSOCKET_HAS_GETHOSTBYADDR)
check_library_exists(nsl gethostbyaddr "" LIBNSL_HAS_GETHOSTBYADDR)
if(LIBNSL_HAS_GETHOSTBYADDR)
set(TCPDUMP_LINK_LIBRARIES ${TCPDUMP_LINK_LIBRARIES} nsl)
else(LIBNSL_HAS_GETHOSTBYADDR)
- message(FATAL_ERROR "gethostbyaddr is required, but wasn't found")
+ check_library_exists(network gethostbyaddr "" LIBNETWORK_HAS_GETHOSTBYADDR)
+ if(LIBNETWORK_HAS_GETHOSTBYADDR)
+ set(TCPDUMP_LINK_LIBRARIES ${TCPDUMP_LINK_LIBRARIES} network)
+ else(LIBNETWORK_HAS_GETHOSTBYADDR)
+ message(FATAL_ERROR "gethostbyaddr is required, but wasn't found")
+ endif(LIBNETWORK_HAS_GETHOSTBYADDR)
endif(LIBNSL_HAS_GETHOSTBYADDR)
endif(LIBSOCKET_HAS_GETHOSTBYADDR)
endif(NOT STDLIBS_HAVE_GETHOSTBYADDR)
endif(WIN32)
#
# This may require additional libraries.
#
cmake_push_check_state()
set(CMAKE_REQUIRED_LIBRARIES ${TCPDUMP_LINK_LIBRARIES})
check_function_exists(getservent STDLIBS_HAVE_GETSERVENT)
if(STDLIBS_HAVE_GETSERVENT)
set(HAVE_GETSERVENT TRUE)
else(STDLIBS_HAVE_GETSERVENT)
#
# Some platforms may need -lsocket for getservent.
#
set(CMAKE_REQUIRED_LIBRARIES socket ${TCPDUMP_LINK_LIBRARIES})
check_function_exists(getservent LIBSOCKET_HAS_GETSERVENT)
if(LIBSOCKET_HAS_GETSERVENT)
set(HAVE_GETSERVENT TRUE)
set(TCPDUMP_LINK_LIBRARIES socket ${TCPDUMP_LINK_LIBRARIES})
endif(LIBSOCKET_HAS_GETSERVENT)
endif(STDLIBS_HAVE_GETSERVENT)
cmake_pop_check_state()
#
-# Make sure we have vsnprintf() and snprintf(); we require them.
-# We use check_symbol_exists(), as they aren't necessarily external
-# functions - in Visual Studio, for example, they're inline functions
-# calling a common external function.
+# Make sure we have snprintf(); we require it.
+# We use check_symbol_exists(), as it isn't necessarily an external
+# function - in Visual Studio, for example, it is an inline function
+# calling an external function.
#
-check_symbol_exists(vsnprintf "stdio.h" HAVE_VSNPRINTF)
-if(NOT HAVE_VSNPRINTF)
- message(FATAL_ERROR "vsnprintf() is required but wasn't found")
-endif(NOT HAVE_VSNPRINTF)
check_symbol_exists(snprintf "stdio.h" HAVE_SNPRINTF)
if(NOT HAVE_SNPRINTF)
message(FATAL_ERROR "snprintf() is required but wasn't found")
endif()
+#
+# Require a proof of suitable snprintf(3), same as in Autoconf.
+#
+include(CheckCSourceRuns)
+check_c_source_runs("
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <sys/types.h>
+
+int main()
+{
+ char buf[100];
+ uint64_t t = (uint64_t)1 << 32;
+
+ snprintf(buf, sizeof(buf), \"%zu\", sizeof(buf));
+ if (strncmp(buf, \"100\", sizeof(buf)))
+ return 1;
+
+ snprintf(buf, sizeof(buf), \"%zd\", -sizeof(buf));
+ if (strncmp(buf, \"-100\", sizeof(buf)))
+ return 2;
+
+ snprintf(buf, sizeof(buf), \"%\" PRId64, -t);
+ if (strncmp(buf, \"-4294967296\", sizeof(buf)))
+ return 3;
+
+ snprintf(buf, sizeof(buf), \"0o%\" PRIo64, t);
+ if (strncmp(buf, \"0o40000000000\", sizeof(buf)))
+ return 4;
+
+ snprintf(buf, sizeof(buf), \"0x%\" PRIx64, t);
+ if (strncmp(buf, \"0x100000000\", sizeof(buf)))
+ return 5;
+
+ snprintf(buf, sizeof(buf), \"%\" PRIu64, t);
+ if (strncmp(buf, \"4294967296\", sizeof(buf)))
+ return 6;
+
+ return 0;
+}
+
+"
+ SUITABLE_SNPRINTF
+)
+if(NOT SUITABLE_SNPRINTF)
+ message(FATAL_ERROR
+"The snprintf(3) implementation in this libc is not suitable,
+tcpdump would not work correctly even if it managed to compile."
+ )
+endif()
+
check_function_exists(getopt_long HAVE_GETOPT_LONG)
check_function_exists(setlinebuf HAVE_SETLINEBUF)
#
# For Windows, don't need to waste time checking for fork() or vfork().
#
if(NOT WIN32)
check_function_exists(fork HAVE_FORK)
check_function_exists(vfork HAVE_VFORK)
endif(NOT WIN32)
#
# Some platforms may need -lnsl for getrpcbynumber.
#
cmake_push_check_state()
set(CMAKE_REQUIRED_LIBRARIES ${TCPDUMP_LINK_LIBRARIES})
check_function_exists(getrpcbynumber STDLIBS_HAVE_GETRPCBYNUMBER)
if(STDLIBS_HAVE_GETRPCBYNUMBER)
set(HAVE_GETRPCBYNUMBER TRUE)
else(STDLIBS_HAVE_GETRPCBYNUMBER)
set(CMAKE_REQUIRED_LIBRARIES ${TCPDUMP_LINK_LIBRARIES} nsl)
check_function_exists(getrpcbynumber LIBNSL_HAS_GETRPCBYNUMBER)
if(LIBNSL_HAS_GETRPCBYNUMBER)
set(HAVE_GETRPCBYNUMBER TRUE)
set(TCPDUMP_LINK_LIBRARIES ${TCPDUMP_LINK_LIBRARIES} nsl)
endif(LIBNSL_HAS_GETRPCBYNUMBER)
endif(STDLIBS_HAVE_GETRPCBYNUMBER)
cmake_pop_check_state()
#
# This requires the libraries we require, as ether_ntohost might be
# in one of those libraries. That means we have to do this after
# we check for those libraries.
#
# You are in a twisty little maze of UN*Xes, all different.
# Some might not have ether_ntohost().
# Some might have it and declare it in <net/ethernet.h>.
# Some might have it and declare it in <netinet/ether.h>
# Some might have it and declare it in <sys/ethernet.h>.
# Some might have it and declare it in <arpa/inet.h>.
# Some might have it and declare it in <netinet/if_ether.h>.
# Some might have it and not declare it in any header file.
#
# Before you is a C compiler.
#
cmake_push_check_state()
set(CMAKE_REQUIRED_LIBRARIES ${TCPDUMP_LINK_LIBRARIES})
check_function_exists(ether_ntohost HAVE_ETHER_NTOHOST)
if(HAVE_ETHER_NTOHOST)
#
# OK, we have ether_ntohost(). We don't check whether it's buggy,
# as we assume any system that has CMake is likely to be new enough
# that, if it has ether_ntohost(), whatever bug is checked for in
# autotools is fixed; we just decide to use it.
#
set(USE_ETHER_NTOHOST TRUE)
#
# Is it declared in <net/ethernet.h>?
#
# This test fails if we don't have <net/ethernet.h> or if we do
# but it doesn't declare ether_ntohost().
#
check_symbol_exists(ether_ntohost net/ethernet.h NET_ETHERNET_H_DECLARES_ETHER_NTOHOST)
if(NET_ETHERNET_H_DECLARES_ETHER_NTOHOST)
#
# Yes - we have it declared.
#
set(HAVE_DECL_ETHER_NTOHOST TRUE)
endif()
#
# Did that succeed?
#
if(NOT HAVE_DECL_ETHER_NTOHOST)
#
# No - how about <netinet/ether.h>, as on Linux?
#
# This test fails if we don't have <netinet/ether.h>
# or if we do but it doesn't declare ether_ntohost().
#
check_symbol_exists(ether_ntohost netinet/ether.h NETINET_ETHER_H_DECLARES_ETHER_NTOHOST)
if(NETINET_ETHER_H_DECLARES_ETHER_NTOHOST)
#
# Yes - we have it declared.
#
set(HAVE_DECL_ETHER_NTOHOST TRUE)
endif()
endif()
#
# Did that succeed?
#
if(NOT HAVE_DECL_ETHER_NTOHOST)
#
# No - how about <sys/ethernet.h>, as on Solaris 10 and later?
#
# This test fails if we don't have <sys/ethernet.h>
# or if we do but it doesn't declare ether_ntohost().
#
check_symbol_exists(ether_ntohost sys/ethernet.h SYS_ETHERNET_H_DECLARES_ETHER_NTOHOST)
if(SYS_ETHERNET_H_DECLARES_ETHER_NTOHOST)
#
# Yes - we have it declared.
#
set(HAVE_DECL_ETHER_NTOHOST TRUE)
endif()
endif()
#
# Did that succeed?
#
if(NOT HAVE_DECL_ETHER_NTOHOST)
#
# No, how about <arpa/inet.h>, as on AIX?
#
# This test fails if we don't have <arpa/inet.h>
# or if we do but it doesn't declare ether_ntohost().
#
check_symbol_exists(ether_ntohost arpa/inet.h ARPA_INET_H_DECLARES_ETHER_NTOHOST)
if(ARPA_INET_H_DECLARES_ETHER_NTOHOST)
#
# Yes - we have it declared.
#
set(HAVE_DECL_ETHER_NTOHOST TRUE)
endif()
endif()
#
# Did that succeed?
#
if(NOT HAVE_DECL_ETHER_NTOHOST)
#
# No, how about <netinet/if_ether.h>?
# On some platforms, it requires <net/if.h> and
# <netinet/in.h>, and we always include it with
# both of them, so test it with both of them.
#
# This test fails if we don't have <netinet/if_ether.h>
# and the headers we include before it, or if we do but
# <netinet/if_ether.h> doesn't declare ether_ntohost().
#
check_symbol_exists(ether_ntohost "sys/types.h;sys/socket.h;net/if.h;netinet/in.h;netinet/if_ether.h" NETINET_IF_ETHER_H_DECLARES_ETHER_NTOHOST)
if(NETINET_IF_ETHER_H_DECLARES_ETHER_NTOHOST)
#
# Yes - we have it declared.
#
set(HAVE_DECL_ETHER_NTOHOST TRUE)
endif()
endif()
#
# After all that, is ether_ntohost() declared?
#
if(NOT HAVE_DECL_ETHER_NTOHOST)
#
# No, we'll have to declare it ourselves.
# Do we have "struct ether_addr" if we include<netinet/if_ether.h>?
#
check_struct_has_member("struct ether_addr" octet "sys/types.h;sys/socket.h;net/if.h;netinet/in.h;netinet/if_ether.h" HAVE_STRUCT_ETHER_ADDR)
endif()
endif()
cmake_pop_check_state()
#
# Data types.
#
# XXX - there's no check_struct() macro that's like check_struct_has_member()
# except that it only checks for the existence of the structure type,
# so we use check_struct_has_member() and look for ss_family.
#
#
# Check for IPv6 support.
# We just check for AF_INET6 and struct in6_addr.
#
cmake_push_check_state()
if(WIN32)
set(CMAKE_EXTRA_INCLUDE_FILES sys/types.h ws2tcpip.h)
check_symbol_exists(AF_INET6 "sys/types.h;ws2tcpip.h" HAVE_AF_INET6)
else(WIN32)
set(CMAKE_EXTRA_INCLUDE_FILES sys/types.h sys/socket.h netinet/in.h)
check_symbol_exists(AF_INET6 "sys/types.h;sys/socket.h;netinet/in.h" HAVE_AF_INET6)
endif(WIN32)
check_type_size("struct in6_addr" HAVE_STRUCT_IN6_ADDR)
cmake_pop_check_state()
if(HAVE_AF_INET6 AND HAVE_STRUCT_IN6_ADDR)
set(HAVE_OS_IPV6_SUPPORT TRUE)
endif(HAVE_AF_INET6 AND HAVE_STRUCT_IN6_ADDR)
######################################
# External dependencies
######################################
#
# libpcap/WinPcap/Npcap.
# First, find it.
#
find_package(PCAP REQUIRED)
include_directories(${PCAP_INCLUDE_DIRS})
cmake_push_check_state()
#
# Now check headers.
#
set(CMAKE_REQUIRED_INCLUDES ${PCAP_INCLUDE_DIRS})
#
# Check whether we have pcap/pcap-inttypes.h.
# If we do, we use that to get the C99 types defined.
#
check_include_file(pcap/pcap-inttypes.h HAVE_PCAP_PCAP_INTTYPES_H)
+#
+# At compile time HAVE_PCAP_FINDALLDEVS depends on HAVE_PCAP_IF_T.
+#
+cmake_push_check_state()
+set(CMAKE_EXTRA_INCLUDE_FILES pcap.h)
+check_type_size(pcap_if_t PCAP_IF_T)
+cmake_pop_check_state()
+
#
# Check for various functions in libpcap/WinPcap/Npcap.
#
cmake_push_check_state()
set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARIES})
#
# Check for "pcap_list_datalinks()" and use a substitute version if
# it's not present. If it is present, check for "pcap_free_datalinks()";
# if it's not present, we don't replace it for now. (We could do so
# on UN*X, but not on Windows, where hilarity ensues if a program
# built with one version of the MSVC support library tries to free
# something allocated by a library built with another version of
# the MSVC support library.)
#
check_function_exists(pcap_list_datalinks HAVE_PCAP_LIST_DATALINKS)
if(HAVE_PCAP_LIST_DATALINKS)
check_function_exists(pcap_free_datalinks HAVE_PCAP_FREE_DATALINKS)
endif(HAVE_PCAP_LIST_DATALINKS)
#
# Check for "pcap_datalink_name_to_val()", and use a substitute
# version if it's not present. If it is present, check for
# "pcap_datalink_val_to_description()", and if we don't have it,
# use a substitute version.
#
check_function_exists(pcap_datalink_name_to_val HAVE_PCAP_DATALINK_NAME_TO_VAL)
if(HAVE_PCAP_DATALINK_NAME_TO_VAL)
check_function_exists(pcap_datalink_val_to_description HAVE_PCAP_DATALINK_VAL_TO_DESCRIPTION)
endif(HAVE_PCAP_DATALINK_NAME_TO_VAL)
#
# Check for "pcap_set_datalink()"; you can't substitute for it if
# it's absent (it has hooks into libpcap), so just define the
# HAVE_ value if it's there.
#
check_function_exists(pcap_set_datalink HAVE_PCAP_SET_DATALINK)
#
# Check for "pcap_breakloop()"; you can't substitute for it if
# it's absent (it has hooks into the live capture routines),
# so just define the HAVE_ value if it's there.
#
check_function_exists(pcap_breakloop HAVE_PCAP_BREAKLOOP)
#
# Check for "pcap_dump_ftell()"; we use a substitute version
# if it's not present.
#
check_function_exists(pcap_dump_ftell HAVE_PCAP_DUMP_FTELL)
#
# Do we have the new open API? Check for pcap_create() and for
# pcap_statustostr(), and assume that, if we have both of them,
# we also have pcap_activate() and the other new routines
# introduced in libpcap 1.0.0. (We check for pcap_statustostr()
# as well, because WinPcap 4.1.3 screwed up and exported pcap_create()
# but not other routines such as pcap_statustostr(), even though it
# defined them and even though you really want pcap_statustostr() to
# get strings corresponding to some of the status returns from the
# new routines.)
#
check_function_exists(pcap_statustostr HAVE_PCAP_STATUSTOSTR)
#
# If we don't have pcap_statustostr(), don't check for pcap_create(),
# so we pretend we don't have it.
#
if(HAVE_PCAP_STATUSTOSTR)
check_function_exists(pcap_create HAVE_PCAP_CREATE)
endif(HAVE_PCAP_STATUSTOSTR)
if(HAVE_PCAP_CREATE)
#
# OK, do we have pcap_set_tstamp_type? If so, assume we have
# pcap_list_tstamp_types and pcap_free_tstamp_types as well.
#
check_function_exists(pcap_set_tstamp_type HAVE_PCAP_SET_TSTAMP_TYPE)
#
# And do we have pcap_set_tstamp_precision? If so, we assume
# we also have pcap_open_offline_with_tstamp_precision.
#
check_function_exists(pcap_set_tstamp_precision HAVE_PCAP_SET_TSTAMP_PRECISION)
endif(HAVE_PCAP_CREATE)
#
# Check for a miscellaneous collection of functions which we use
# if we have them.
#
check_function_exists(pcap_findalldevs HAVE_PCAP_FINDALLDEVS)
-if(HAVE_PCAP_FINDALLDEVS)
- #
- # Check for libpcap having pcap_findalldevs() but the pcap.h header
- # not having pcap_if_t; some versions of Mac OS X shipped with pcap.h
- # from 0.6 and libpcap 0.8, so that libpcap had pcap_findalldevs but
- # pcap.h didn't have pcap_if_t.
- #
- cmake_push_check_state()
- set(CMAKE_REQUIRED_INCLUDES ${PCAP_INCLUDE_DIRS})
- set(CMAKE_EXTRA_INCLUDE_FILES pcap.h)
- check_type_size(pcap_if_t PCAP_IF_T)
- cmake_pop_check_state()
-endif(HAVE_PCAP_FINDALLDEVS)
check_function_exists(pcap_dump_flush HAVE_PCAP_DUMP_FLUSH)
check_function_exists(pcap_lib_version HAVE_PCAP_LIB_VERSION)
if(NOT HAVE_PCAP_LIB_VERSION)
# Check for the pcap_version string variable and set HAVE_PCAP_VERSION
endif(NOT HAVE_PCAP_LIB_VERSION)
check_function_exists(pcap_setdirection HAVE_PCAP_SETDIRECTION)
check_function_exists(pcap_set_immediate_mode HAVE_PCAP_SET_IMMEDIATE_MODE)
check_function_exists(pcap_dump_ftell64 HAVE_PCAP_DUMP_FTELL64)
-check_function_exists(pcap_open HAVE_PCAP_OPEN)
-check_function_exists(pcap_findalldevs_ex HAVE_PCAP_FINDALLDEVS_EX)
+#
+# macOS Sonoma's libpcap includes stub versions of the remote-
+# capture APIs. They are exported as "weakly linked symbols".
+#
+# Xcode 15 offers only a macOS Sonoma SDK, which has a .tbd
+# file for libpcap that claims it includes those APIs. (Newer
+# versions of macOS don't provide the system shared libraries,
+# they only provide the dyld shared cache containing those
+# libraries, so the OS provides SDKs that include a .tbd file
+# to use when linking.)
+#
+# This means that check_function_exists() will think that
+# the remote-capture APIs are present, including pcap_open()
+# and pcap_findalldevs_ex().
+#
+# However, they are *not* present in macOS Ventura and earlier,
+# which means that building on Ventura with Xcode 15 produces
+# executables that fail to start because one of those APIs
+# isn't found in the system libpcap.
+#
+# Protecting calls to those APIs with __builtin_available()
+# does not prevent this, because the libpcap header files
+# in the Sonoma SDK mark them as being first available
+# in macOS 10.13, just like all the other routines introduced
+# in libpcap 1.9, even though they're only available if libpcap
+# is built with remote capture enabled or stub routines are
+# provided. (A fix to enable this has been checked into the
+# libpcap repository, and may end up in a later version of
+# the SDK.)
+#
+# Given all that, and given that the versions of the
+# remote-capture APIs in Sonoma are stubs that always fail,
+# there doesn't seem to be any point in checking for pcap_open()
+# and pcap_findalldevs_ex() if we're linking against the Apple libpcap.
+#
+# However, if we're *not* linking against the Apple libpcap,
+# we should check for it, so that we can use it if it's present.
+#
+# So we check for pcap_open() and pcap_findalldevs_ex() if 1) this isn't
+# macOS or 2) the the libpcap we found is not a system library, meaning
+# that its path begins neither with /usr/lib (meaning it's a system
+# dylib) nor /Application/Xcode.app (meaning it's a file in
+# the Xcode SDK).
+#
+if(NOT APPLE OR NOT
+ (PCAP_LIBRARIES MATCHES "/usr/lib/.*" OR
+ PCAP_LIBRARIES MATCHES "/Application/Xcode.app/.*"))
+ check_function_exists(pcap_open HAVE_PCAP_OPEN)
+ check_function_exists(pcap_findalldevs_ex HAVE_PCAP_FINDALLDEVS_EX)
+endif()
#
# On Windows, check for pcap_wsockinit(); if we don't have it, check for
# wsockinit().
#
if(WIN32)
check_function_exists(pcap_wsockinit HAVE_PCAP_WSOCKINIT)
if(NOT HAVE_PCAP_WSOCKINIT)
check_function_exists(wsockinit HAVE_WSOCKINIT)
endif(NOT HAVE_PCAP_WSOCKINIT)
endif(WIN32)
#
# Check for special debugging functions
#
check_function_exists(pcap_set_parser_debug HAVE_PCAP_SET_PARSER_DEBUG)
if(NOT HAVE_PCAP_SET_PARSER_DEBUG)
# Check whether libpcap defines pcap_debug or yydebug
check_variable_exists(pcap_debug HAVE_PCAP_DEBUG)
if(NOT HAVE_PCAP_DEBUG)
check_variable_exists(yydebug HAVE_YYDEBUG)
endif(NOT HAVE_PCAP_DEBUG)
endif(NOT HAVE_PCAP_SET_PARSER_DEBUG)
check_function_exists(pcap_set_optimizer_debug HAVE_PCAP_SET_OPTIMIZER_DEBUG)
check_function_exists(bpf_dump HAVE_BPF_DUMP)
cmake_pop_check_state()
#
# We have libpcap.
#
include_directories(SYSTEM ${PCAP_INCLUDE_DIRS})
set(TCPDUMP_LINK_LIBRARIES ${PCAP_LIBRARIES} ${TCPDUMP_LINK_LIBRARIES})
#
# Optional libraries.
#
#
# libsmi.
#
if(WITH_SMI)
find_package(SMI)
if(SMI_FOUND)
include_directories(SYSTEM ${SMI_INCLUDE_DIRS})
set(TCPDUMP_LINK_LIBRARIES ${TCPDUMP_LINK_LIBRARIES} ${SMI_LIBRARIES})
set(USE_LIBSMI ON)
endif(SMI_FOUND)
endif(WITH_SMI)
#
# OpenSSL/libressl libcrypto.
#
if(WITH_CRYPTO)
find_package(CRYPTO)
if(CRYPTO_FOUND)
- #
- # Check for some headers and functions.
- #
- check_include_file(openssl/evp.h HAVE_OPENSSL_EVP_H)
-
#
# 1) do we have EVP_CIPHER_CTX_new?
# If so, we use it to allocate an EVP_CIPHER_CTX, as
# EVP_CIPHER_CTX may be opaque; otherwise, we allocate
# it ourselves.
#
cmake_push_check_state()
set(CMAKE_REQUIRED_LIBRARIES "${CRYPTO_LIBRARIES}")
check_function_exists(EVP_CIPHER_CTX_new HAVE_EVP_CIPHER_CTX_NEW)
#
# 2) do we have EVP_DecryptInit_ex()?
# If so, we use it, because we need to be able to make two
# "initialize the cipher" calls, one with the cipher and key,
# and one with the IV, and, as of OpenSSL 1.1, You Can't Do That
# with EVP_DecryptInit(), because a call to EVP_DecryptInit() will
# unconditionally clear the context, and if you don't supply a
# cipher, it'll clear the cipher, rendering the context unusable
# and causing a crash.
#
check_function_exists(EVP_DecryptInit_ex HAVE_EVP_DECRYPTINIT_EX)
cmake_pop_check_state()
#
# We have libcrypto.
#
include_directories(SYSTEM ${CRYPTO_INCLUDE_DIRS})
set(TCPDUMP_LINK_LIBRARIES ${TCPDUMP_LINK_LIBRARIES} ${CRYPTO_LIBRARIES})
set(HAVE_LIBCRYPTO ON)
endif(CRYPTO_FOUND)
endif(WITH_CRYPTO)
#
# Capsicum sandboxing.
# Some of this is in the system library, some of it is in other libraries.
#
if(WITH_CAPSICUM)
check_include_files("sys/capsicum.h" HAVE_SYS_CAPSICUM_H)
if(HAVE_SYS_CAPSICUM_H)
check_function_exists(cap_enter HAVE_CAP_ENTER)
check_function_exists(cap_rights_limit HAVE_CAP_RIGHTS_LIMIT)
check_function_exists(cap_ioctls_limit HAVE_CAP_IOCTLS_LIMIT)
check_function_exists(openat HAVE_OPENAT)
if(HAVE_CAP_ENTER AND HAVE_CAP_RIGHTS_LIMIT AND
HAVE_CAP_IOCTLS_LIMIT AND HAVE_OPENAT)
#
# OK, we have the functions we need to support Capsicum.
#
set(HAVE_CAPSICUM TRUE)
#
# OK, can we use Casper?
#
check_library_exists(casper cap_init "" HAVE_CAP_INIT)
if(HAVE_CAP_INIT)
cmake_push_check_state()
set(CMAKE_REQUIRED_LIBRARIES casper)
check_library_exists(cap_dns cap_gethostbyaddr "" HAVE_CAP_GETHOSTBYADDR)
cmake_pop_check_state()
if(HAVE_CAP_GETHOSTBYADDR)
set(HAVE_CASPER TRUE)
set(TCPDUMP_LINK_LIBRARIES ${TCPDUMP_LINK_LIBRARIES} casper cap_dns)
endif(HAVE_CAP_GETHOSTBYADDR)
endif(HAVE_CAP_INIT)
endif(HAVE_CAP_ENTER AND HAVE_CAP_RIGHTS_LIMIT AND
HAVE_CAP_IOCTLS_LIMIT AND HAVE_OPENAT)
endif(HAVE_SYS_CAPSICUM_H)
endif(WITH_CAPSICUM)
#
# libcap-ng.
#
if(WITH_CAP_NG)
check_include_file(cap-ng.h HAVE_CAP_NG_H)
check_library_exists(cap-ng capng_change_id "" HAVE_LIBCAP_NG)
if(HAVE_LIBCAP_NG)
set(TCPDUMP_LINK_LIBRARIES ${TCPDUMP_LINK_LIBRARIES} cap-ng)
endif(HAVE_LIBCAP_NG)
endif(WITH_CAP_NG)
###################################################################
# Warning options
###################################################################
#
# Check and add warning options if we have a .devel file.
#
if(EXISTS ${CMAKE_SOURCE_DIR}/.devel OR EXISTS ${CMAKE_BINARY_DIR}/.devel)
#
# Warning options.
#
if(MSVC AND NOT ${CMAKE_C_COMPILER} MATCHES "clang*")
#
# MSVC, with Microsoft's front end and code generator.
# "MSVC" is also set for Microsoft's compiler with a Clang
# front end and their code generator ("Clang/C2"), so we
# check for clang.exe and treat that differently.
#
check_and_add_compiler_option(-Wall)
#
# Disable some pointless warnings that /Wall turns on.
#
# Unfortunately, MSVC does not appear to have an equivalent
# to "__attribute__((unused))" to mark a particular function
# parameter as being known to be unused, so that the compiler
# won't warn about it (for example, the function might have
# that parameter because a pointer to it is being used, and
# the signature of that function includes that parameter).
# C++ lets you give a parameter a type but no name, but C
# doesn't have that.
#
check_and_add_compiler_option(-wd4100)
#
# In theory, we care whether somebody uses f() rather than
# f(void) to declare a function with no arguments, but, in
# practice, there are places in the Windows header files
# that appear to do that, so we squelch that warning.
#
check_and_add_compiler_option(-wd4255)
#
# Windows FD_SET() generates this, so we suppress it.
#
check_and_add_compiler_option(-wd4548)
#
# Perhaps testing something #defined to be 0 with #ifdef is an
# error, and it should be tested with #if, but perhaps it's
# not, and Microsoft does that in its headers, so we squelch
# that warning.
#
check_and_add_compiler_option(-wd4574)
#
# The Windows headers also test not-defined values in #if, so
# we don't want warnings about that, either.
#
check_and_add_compiler_option(-wd4668)
#
# We do *not* care whether some function is, or isn't, going to be
# expanded inline.
#
check_and_add_compiler_option(-wd4710)
check_and_add_compiler_option(-wd4711)
#
# We do *not* care whether we're adding padding bytes after
# structure members.
#
check_and_add_compiler_option(-wd4820)
#
# We do *not* care about every single place the compiler would
# have inserted Spectre mitigation if only we had told it to
# do so with /Qspectre. I guess the theory is that it's seeing
# bounds checks that would prevent out-of-bounds loads and that
# those out-of-bounds loads could be done speculatively and that
# the Spectre attack could detect the value of the out-of-bounds
# data *if* it's within our address space, but unless I'm
# missing something I don't see that as being any form of
# security hole.
#
# XXX - add /Qspectre if that is really worth doing.
#
check_and_add_compiler_option(-wd5045)
#
# We do *not* care whether a structure had padding added at
# the end because of __declspec(align) - *we* don't use
# __declspec(align), because the only structures whose layout
- # we precisely specify are those that get overlayed on packet
+ # we precisely specify are those that get overlaid on packet
# data, and in those every element is an array of octets so
- # that we have full control over the size and aligmnet, and,
+ # that we have full control over the size and alignment, and,
# apparently, jmp_buf has such a declaration on x86, meaning
# that everything that includes netdissect.h, i.e. almost every
# file in tcpdump, gets a warning.
#
check_and_add_compiler_option(-wd4324)
else()
#
# Other compilers, including MSVC with a Clang front end and
# Microsoft's code generator. We currently treat them as if
# they might support GCC-style -W options.
#
check_and_add_compiler_option(-W)
check_and_add_compiler_option(-Wall)
check_and_add_compiler_option(-Wassign-enum)
check_and_add_compiler_option(-Wcast-qual)
check_and_add_compiler_option(-Wmissing-prototypes)
check_and_add_compiler_option(-Wmissing-variable-declarations)
check_and_add_compiler_option(-Wold-style-definition)
- check_and_add_compiler_option(-Wpedantic)
+ if(NOT CMAKE_C_COMPILER_ID MATCHES "Sun")
+ # In Sun C versions that implement GCC compatibility "-Wpedantic"
+ # means the same as "-pedantic". The latter is mutually exclusive
+ # with several other options. One of those is "-xc99", which has
+ # already been set for Sun C above.
+ check_and_add_compiler_option(-Wpedantic)
+ endif()
check_and_add_compiler_option(-Wpointer-arith)
check_and_add_compiler_option(-Wpointer-sign)
check_and_add_compiler_option(-Wshadow)
check_and_add_compiler_option(-Wsign-compare)
check_and_add_compiler_option(-Wstrict-prototypes)
+ check_and_add_compiler_option(-Wundef)
check_and_add_compiler_option(-Wunreachable-code-return)
check_and_add_compiler_option(-Wused-but-marked-unused)
check_and_add_compiler_option(-Wwrite-strings)
endif()
endif()
#
# Extra compiler options for the build matrix scripts to request -Werror or
# its equivalent if required. The CMake variable name cannot be CFLAGS
# because that is already used for a different purpose in CMake. Example
# usage: cmake -DEXTRA_CFLAGS='-Wall -Wextra -Werror' ...
#
if(NOT "${EXTRA_CFLAGS}" STREQUAL "")
- foreach(_extra_cflag ${EXTRA_CFLAGS})
- check_and_add_compiler_option("${_extra_cflag}")
- endforeach(_extra_cflag)
+ # The meaning of EXTRA_CFLAGS is "use the exact specified options, or the
+ # build risks failing to fail", not "try every specified option, omit those
+ # that do not work and use the rest". Thus use add_compile_options(), not
+ # foreach()/check_and_add_compiler_option(). Another reason to do that is
+ # that the effect lasts in testprogs/ and testprogs/fuzz/.
+ string(REPLACE " " ";" _extra_cflags_list ${EXTRA_CFLAGS})
+ add_compile_options(${_extra_cflags_list})
message(STATUS "Added extra compile options (${EXTRA_CFLAGS})")
endif()
######################################
# Input files
######################################
if(ENABLE_SMB)
#
# We allow the SMB dissector to be omitted.
#
set(LOCALSRC ${LOCALSRC}
print-smb.c
smbutil.c)
endif(ENABLE_SMB)
set(NETDISSECT_SOURCE_LIST_C
addrtoname.c
addrtostr.c
af.c
ascii_strcasecmp.c
checksum.c
cpack.c
gmpls.c
in_cksum.c
ipproto.c
l2vpn.c
machdep.c
netdissect.c
netdissect-alloc.c
nlpid.c
oui.c
ntp.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-arista.c
print-arp.c
print-ascii.c
print-atalk.c
print-atm.c
print-babel.c
print-bcm-li.c
print-beep.c
print-bfd.c
print-bgp.c
print-bootp.c
print-brcmtag.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-dsa.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-demux.c
print-ip.c
print-ip6.c
print-ip6opts.c
print-ipcomp.c
print-ipfc.c
print-ipnet.c
print-ipoib.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-macsec.c
print-mobile.c
print-mobility.c
print-mpcp.c
print-mpls.c
print-mptcp.c
print-msdp.c
print-msnlb.c
print-nflog.c
print-nfs.c
print-nsh.c
print-ntp.c
print-null.c
print-olsr.c
print-openflow-1.0.c
print-openflow-1.3.c
print-openflow.c
print-ospf.c
print-ospf6.c
print-otv.c
print-pflog.c
print-pgm.c
print-pim.c
print-pktap.c
print-ppi.c
print-ppp.c
print-pppoe.c
print-pptp.c
print-ptp.c
print-radius.c
print-raw.c
print-realtek.c
print-resp.c
print-rip.c
print-ripng.c
print-rpki-rtr.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-smtp.c
print-snmp.c
print-someip.c
print-ssh.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-unsupported.c
print-usb.c
print-vjc.c
print-vqp.c
print-vrrp.c
print-vsock.c
print-vtp.c
print-vxlan-gpe.c
print-vxlan.c
print-wb.c
print-whois.c
print-zep.c
print-zephyr.c
print-zeromq.c
${LOCALSRC}
signature.c
strtoaddr.c
util-print.c
)
#
# Replace missing functions
#
foreach(FUNC strlcat strlcpy strdup strsep getservent getopt_long)
string(TOUPPER ${FUNC} FUNC_UPPERCASE)
set(HAVE_FUNC_UPPERCASE HAVE_${FUNC_UPPERCASE})
if(NOT ${HAVE_FUNC_UPPERCASE})
set(NETDISSECT_SOURCE_LIST_C ${NETDISSECT_SOURCE_LIST_C} missing/${FUNC}.c)
endif()
endforeach()
add_library(netdissect STATIC
${NETDISSECT_SOURCE_LIST_C}
)
if(NOT C_ADDITIONAL_FLAGS STREQUAL "")
set_target_properties(netdissect PROPERTIES COMPILE_FLAGS ${C_ADDITIONAL_FLAGS})
endif()
set(TCPDUMP_SOURCE_LIST_C fptype.c tcpdump.c)
if(NOT HAVE_BPF_DUMP)
set(TCPDUMP_SOURCE_LIST_C ${TCPDUMP_SOURCE_LIST_C} bpf_dump.c)
endif(NOT HAVE_BPF_DUMP)
if(NOT HAVE_PCAP_DUMP_FTELL)
set(TCPDUMP_SOURCE_LIST_C ${TCPDUMP_SOURCE_LIST_C} missing/pcap_dump_ftell.c)
endif(NOT HAVE_PCAP_DUMP_FTELL)
if(NOT HAVE_PCAP_LIST_DATALINKS)
set(TCPDUMP_SOURCE_LIST_C ${TCPDUMP_SOURCE_LIST_C} missing/datalinks.c)
endif(NOT HAVE_PCAP_LIST_DATALINKS)
if((NOT HAVE_PCAP_DATALINK_NAME_TO_VAL) OR (NOT HAVE_PCAP_DATALINK_VAL_TO_DESCRIPTION))
set(TCPDUMP_SOURCE_LIST_C ${TCPDUMP_SOURCE_LIST_C} missing/dlnames.c)
endif((NOT HAVE_PCAP_DATALINK_NAME_TO_VAL) OR (NOT HAVE_PCAP_DATALINK_VAL_TO_DESCRIPTION))
set(PROJECT_SOURCE_LIST_C ${NETDISSECT_SOURCE_LIST_C} ${TCPDUMP_SOURCE_LIST_C})
file(GLOB PROJECT_SOURCE_LIST_H
*.h
)
#
# Assume, by default, no support for shared libraries and V7/BSD
# convention for man pages (devices in section 4, file formats in
# section 5, miscellaneous info in section 7, administrative commands
# and daemons in section 8). Individual cases can override this.
# Individual cases can override this.
#
set(MAN_FILE_FORMATS 5)
set(MAN_MISC_INFO 7)
if(CMAKE_SYSTEM_NAME STREQUAL "AIX")
# Workaround to enable certain features
set(_SUN TRUE)
elseif(CMAKE_SYSTEM_NAME STREQUAL "HP-UX")
#
# Use System V conventions for man pages.
#
set(MAN_FILE_FORMATS 4)
set(MAN_MISC_INFO 5)
elseif(CMAKE_SYSTEM_NAME STREQUAL "IRIX" OR CMAKE_SYSTEM_NAME STREQUAL "IRIX64")
#
# Use IRIX conventions for man pages; they're the same as the
# System V conventions, except that they use section 8 for
# administrative commands and daemons.
#
set(MAN_FILE_FORMATS 4)
set(MAN_MISC_INFO 5)
elseif(CMAKE_SYSTEM_NAME STREQUAL "OSF1")
#
# DEC OSF/1, a/k/a Digital UNIX, a/k/a Tru64 UNIX.
# Use Tru64 UNIX conventions for man pages; they're the same as the
# System V conventions except that they use section 8 for
# administrative commands and daemons.
#
set(MAN_FILE_FORMATS 4)
set(MAN_MISC_INFO 5)
elseif(CMAKE_SYSTEM_NAME STREQUAL "SunOS" AND CMAKE_SYSTEM_VERSION MATCHES "5[.][0-9.]*")
#
# SunOS 5.x.
#
if(CMAKE_SYSTEM_VERSION STREQUAL "5.12")
else()
#
# Use System V conventions for man pages.
#
set(MAN_FILE_FORMATS 4)
set(MAN_MISC_INFO 5)
endif()
endif()
source_group("Source Files" FILES ${PROJECT_SOURCE_LIST_C})
source_group("Header Files" FILES ${PROJECT_SOURCE_LIST_H})
######################################
# Register targets
######################################
add_executable(tcpdump ${TCPDUMP_SOURCE_LIST_C})
if(NOT C_ADDITIONAL_FLAGS STREQUAL "")
set_target_properties(tcpdump PROPERTIES COMPILE_FLAGS ${C_ADDITIONAL_FLAGS})
endif()
target_link_libraries(tcpdump netdissect ${TCPDUMP_LINK_LIBRARIES})
######################################
# Write out the config.h file
######################################
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmakeconfig.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
######################################
# Install tcpdump and man pages
######################################
#
# "Define GNU standard installation directories", which actually
# are also defined, to some degree, by autotools, and at least
# some of which are general UN*X conventions.
#
include(GNUInstallDirs)
set(MAN1_EXPAND tcpdump.1.in)
if(WIN32)
# XXX TODO where to install on Windows?
else(WIN32)
install(TARGETS tcpdump DESTINATION bin)
endif(WIN32)
# On UN*X, and on Windows when not using MSVC, process man pages and
# arrange that they be installed.
if(NOT MSVC)
#
# Man pages.
#
# For each section of the manual for which we have man pages
# that require macro expansion, do the expansion.
#
set(MAN1 "")
foreach(TEMPLATE_MANPAGE ${MAN1_EXPAND})
string(REPLACE ".in" "" MANPAGE ${TEMPLATE_MANPAGE})
configure_file(${CMAKE_SOURCE_DIR}/${TEMPLATE_MANPAGE} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE} @ONLY)
set(MAN1 ${MAN1} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE})
endforeach(TEMPLATE_MANPAGE)
install(FILES ${MAN1} DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
endif(NOT MSVC)
# uninstall target
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
IMMEDIATE @ONLY)
add_custom_target(uninstall
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
#
# Tcpdump tests
# We try to find the Perl interpreter and, if we do, we have the check
# rule run tests/TESTrun with it, because just trying to run the TESTrun
# script as a command won't work on Windows.
#
find_program(PERL perl)
if(PERL)
message(STATUS "Found perl at ${PERL}")
add_custom_target(check
COMMAND ${PERL} ${CMAKE_SOURCE_DIR}/tests/TESTrun)
else()
message(STATUS "Didn't find perl")
endif()
diff --git a/contrib/tcpdump/CONTRIBUTING.md b/contrib/tcpdump/CONTRIBUTING.md
index 26f226ebd973..215e4c6831c4 100644
--- a/contrib/tcpdump/CONTRIBUTING.md
+++ b/contrib/tcpdump/CONTRIBUTING.md
@@ -1,191 +1,394 @@
# Some Information for Contributors
Thank you for considering to make a contribution to tcpdump! Please use the
guidelines below to achieve the best results and experience for everyone.
## How to report bugs and other problems
**To report a security issue (segfault, buffer overflow, infinite loop, arbitrary
code execution etc) please send an e-mail to security@tcpdump.org, do not use
the bug tracker!**
To report a non-security problem (failure to compile, incorrect output in the
protocol printout, missing support for a particular protocol etc) please check
first that it reproduces with the latest stable release of tcpdump and the latest
stable release of libpcap. If it does, please check that the problem reproduces
with the current git master branch of tcpdump and the current git master branch of
libpcap. If it does (and it is not a security-related problem, otherwise see
above), please navigate to the
[bug tracker](https://github.com/the-tcpdump-group/tcpdump/issues)
and check if the problem has already been reported. If it has not, please open
a new issue and provide the following details:
* tcpdump and libpcap version (`tcpdump --version`)
* operating system name and version and any other details that may be relevant
(`uname -a`, compiler name and version, CPU type etc.)
* custom `configure`/`cmake` flags, if any
* statement of the problem
* steps to reproduce
Please note that if you know exactly how to solve the problem and the solution
would not be too intrusive, it would be best to contribute some development time
and to open a pull request instead as discussed below.
Still not sure how to do? Feel free to
[subscribe to the mailing list](https://www.tcpdump.org/#mailing-lists)
and ask!
## How to add new code and to update existing code
-0) Check that there isn't a pull request already opened for the changes you
+1) Check that there isn't a pull request already opened for the changes you
intend to make.
-1) [Fork](https://help.github.com/articles/fork-a-repo/) the Tcpdump
+2) [Fork](https://help.github.com/articles/fork-a-repo/) the Tcpdump
[repository](https://github.com/the-tcpdump-group/tcpdump).
-2) The easiest way to test your changes on multiple operating systems and
+3) The easiest way to test your changes on multiple operating systems and
architectures is to let the upstream CI test your pull request (more on
this below).
-3) Setup your git working copy
+4) Setup your git working copy
```
git clone https://github.com/<username>/tcpdump.git
cd tcpdump
git remote add upstream https://github.com/the-tcpdump-group/tcpdump
git fetch upstream
```
-4) Do a `touch .devel` in your working directory.
+5) Do a `touch .devel` in your working directory.
Currently, the effect is
* add (via `configure`, in `Makefile`) some warnings options (`-Wall`,
`-Wmissing-prototypes`, `-Wstrict-prototypes`, ...) to the compiler if it
supports these options,
* have the `Makefile` support `make depend` and the `configure` script run it.
-5) Configure and build
+6) Configure and build
```
./configure && make -s && make check
```
-6) Add/update tests
+7) Add/update tests
The `tests` directory contains regression tests of the dissection of captured
packets. Those captured packets were saved running tcpdump with option
`-w sample.pcap`. Additional options, such as `-n`, are used to create relevant
and reproducible output; `-#` is used to indicate which particular packets
have output that differs. The tests are run with the `TZ` environment
variable set to `GMT0`, so that UTC, rather than the local time where the
tests are being run, is used when "local time" values are printed. The
actual test compares the current text output with the expected result
(`sample.out`) saved from a previous version.
Any new/updated fields in a dissector must be present in a `sample.pcap` file
and the corresponding output file.
Configuration is set in `tests/TESTLIST`.
Each line in this file has the following format:
```
test-name sample.pcap sample.out tcpdump-options
```
The `sample.out` file can be produced as follows:
```
(cd tests && TZ=GMT0 ../tcpdump -# -n -r sample.pcap tcpdump-options > sample.out)
```
Or, for convenience, use `./update-test.sh test-name`
It is often useful to have test outputs with different verbosity levels
(none, `-v`, `-vv`, `-vvv`, etc.) depending on the code.
-7) Test using `make check` (current build options) and `./build_matrix.sh`
+8) Test using `make check` (current build options) and `./build_matrix.sh`
(a multitude of build options, build systems and compilers). If you can,
test on more than one operating system. Don't send a pull request until
all tests pass.
-8) Try to rebase your commits to keep the history simple.
+9) Try to rebase your commits to keep the history simple.
```
git fetch upstream
git rebase upstream/master
```
(If the rebase fails and you cannot resolve, issue `git rebase --abort`
and ask for help in the pull request comment.)
-9) Once 100% happy, put your work into your forked repository using `git push`.
+10) Once 100% happy, put your work into your forked repository using `git push`.
-10) [Initiate and send](https://help.github.com/articles/using-pull-requests/)
+11) [Initiate and send](https://help.github.com/articles/using-pull-requests/)
a pull request.
This will trigger the upstream repository CI tests.
## Code style and generic remarks
-* A thorough reading of some other printers code is useful.
+1) A thorough reading of some other printers code is useful.
-* Put the normative reference if any as comments (RFC, etc.).
+2) To help learn how tcpdump works or to help debugging:
+ You can configure and build tcpdump with the instrumentation of functions:
+ ```
+ $ ./configure --enable-instrument-functions
+ $ make -s clean all
+ ```
+
+ This generates instrumentation calls for entry and exit to functions.
+ Just after function entry and just before function exit, these
+ profiling functions are called and print the function names with
+ indentation and call level.
+
+ If entering in a function, it prints also the calling function name with
+ file name and line number. There may be a small shift in the line number.
+
+ In some cases, with Clang 11, the file number is unknown (printed '??')
+ or the line number is unknown (printed '?'). In this case, use GCC.
+
+ If the environment variable INSTRUMENT is
+ - unset or set to an empty string, print nothing, like with no
+ instrumentation
+ - set to "all" or "a", print all the functions names
+ - set to "global" or "g", print only the global functions names
+
+ This allows to run:
+ ```
+ $ INSTRUMENT=a ./tcpdump ...
+ $ INSTRUMENT=g ./tcpdump ...
+ $ INSTRUMENT= ./tcpdump ...
+ ```
+ or
+ ```
+ $ export INSTRUMENT=global
+ $ ./tcpdump ...
+ ```
+
+ The library libbfd is used, therefore the binutils-dev package is required.
-* Put the format of packets/headers/options as comments if there is no
+3) Put the normative reference if any as comments (RFC, etc.).
+
+4) Put the format of packets/headers/options as comments if there is no
published normative reference.
-* The printer may receive incomplete packet in the buffer, truncated at any
+5) The printer may receive incomplete packet in the buffer, truncated at any
random position, for example by capturing with `-s size` option.
+ This means that an attempt to fetch packet data based on the expected
+ format of the packet may run the risk of overrunning the buffer.
+
+ Furthermore, if the packet is complete, but is not correctly formed,
+ that can also cause a printer to overrun the buffer, as it will be
+ fetching packet data based on the expected format of the packet.
+
+ Therefore, integral, IPv4 address, and octet sequence values should
+ be fetched using the `GET_*()` macros, which are defined in
+ `extract.h`.
+
If your code reads and decodes every byte of the protocol packet, then to
ensure proper and complete bounds checks it would be sufficient to read all
- packet data using the `GET_*()` macros, typically:
- ```
- GET_U_1(p)
- GET_S_1(p)
- GET_BE_U_n(p), n in { 2, 3, 4, 5, 6, 7, 8 }
- GET_BE_S_n(p), n in { 2, 3, 4, 5, 6, 7, 8 }
- ```
+ packet data using the `GET_*()` macros.
+
If your code uses the macros above only on some packet data, then the gaps
would have to be bounds-checked using the `ND_TCHECK_*()` macros:
```
ND_TCHECK_n(p), n in { 1, 2, 3, 4, 5, 6, 7, 8, 16 }
ND_TCHECK_SIZE(p)
ND_TCHECK_LEN(p, l)
```
- For the `ND_TCHECK_*` macros (if not already done):
+
+ where *p* points to the data not being decoded. For `ND_CHECK_n()`,
+ *n* is the length of the gap, in bytes. For `ND_CHECK_SIZE()`, the
+ length of the gap, in bytes, is the size of an item of the data type
+ to which *p* points. For `ND_CHECK_LEN()`, *l* is the length of the
+ gap, in bytes.
+
+ For the `GET_*()` and `ND_TCHECK_*` macros (if not already done):
* Assign: `ndo->ndo_protocol = "protocol";`
* Define: `ND_LONGJMP_FROM_TCHECK` before including `netdissect.h`
* Make sure that the intersection of `GET_*()` and `ND_TCHECK_*()` is minimal,
but at the same time their union covers all packet data in all cases.
You can test the code via:
```
sudo ./tcpdump -s snaplen [-v][v][...] -i lo # in a terminal
sudo tcpreplay -i lo sample.pcap # in another terminal
```
You should try several values for snaplen to do various truncation.
-* Do invalid packet checks in code: Think that your code can receive in input
+* The `GET_*()` macros that fetch integral values are:
+ ```
+ GET_U_1(p)
+ GET_S_1(p)
+ GET_BE_U_n(p), n in { 2, 3, 4, 5, 6, 7, 8 }
+ GET_BE_S_n(p), n in { 2, 3, 4, 5, 6, 7, 8 }
+ GET_LE_U_n(p), n in { 2, 3, 4, 5, 6, 7, 8 }
+ GET_LE_S_n(p), n in { 2, 3, 4, 5, 6, 7, 8 }
+ ```
+
+ where *p* points to the integral value in the packet buffer. The
+ macro returns the integral value at that location.
+
+ `U` indicates that an unsigned value is fetched; `S` indicates that a
+ signed value is fetched. For multi-byte values, `BE` indicates that
+ a big-endian value ("network byte order") is fetched, and `LE`
+ indicates that a little-endian value is fetched. *n* is the length,
+ in bytes, of the multi-byte integral value to be fetched.
+
+ In addition to the bounds checking the `GET_*()` macros perform,
+ using those macros has other advantages:
+
+ * tcpdump runs on both big-endian and little-endian systems, so
+ fetches of multi-byte integral values must be done in a fashion
+ that works regardless of the byte order of the machine running
+ tcpdump. The `GET_BE_*()` macros will fetch a big-endian value and
+ return a host-byte-order value on both big-endian and little-endian
+ machines, and the `GET_LE_*()` macros will fetch a little-endian
+ value and return a host-byte-order value on both big-endian and
+ little-endian machines.
+
+ * tcpdump runs on machines that do not support unaligned access to
+ multi-byte values, and packet values are not guaranteed to be
+ aligned on the proper boundary. The `GET_BE_*()` and `GET_LE_*()`
+ macros will fetch values even if they are not aligned on the proper
+ boundary.
+
+* The `GET_*()` macros that fetch IPv4 address values are:
+ ```
+ GET_IPV4_TO_HOST_ORDER(p)
+ GET_IPV4_TO_NETWORK_ORDER(p)
+ ```
+
+ where *p* points to the address in the packet buffer.
+ `GET_IPV4_TO_HOST_ORDER()` returns the address in the byte order of
+ the host that is running tcpdump; `GET_IPV4_TO_NETWORK_ORDER()`
+ returns it in network byte order.
+
+ Like the integral `GET_*()` macros, these macros work correctly on
+ both big-endian and little-endian machines and will fetch values even
+ if they are not aligned on the proper boundary.
+
+* The `GET_*()` macro that fetches an arbitrary sequences of bytes is:
+ ```
+ GET_CPY_BYTES(dst, p, len)
+ ```
+
+ where *dst* is the destination to which the sequence of bytes should
+ be copied, *p* points to the first byte of the sequence of bytes, and
+ *len* is the number of bytes to be copied. The bytes are copied in
+ the order in which they appear in the packet.
+
+* To fetch a network address and convert it to a printable string, use
+ the following `GET_*()` macros, defined in `addrtoname.h`, to
+ perform bounds checks to make sure the entire address is within the
+ buffer and to translate the address to a string to print:
+ ```
+ GET_IPADDR_STRING(p)
+ GET_IP6ADDR_STRING(p)
+ GET_MAC48_STRING(p)
+ GET_EUI64_STRING(p)
+ GET_EUI64LE_STRING(p)
+ GET_LINKADDR_STRING(p, type, len)
+ GET_ISONSAP_STRING(nsap, nsap_length)
+ ```
+
+ `GET_IPADDR_STRING()` fetches an IPv4 address pointed to by *p* and
+ returns a string that is either a host name, if the `-n` flag wasn't
+ specified and a host name could be found for the address, or the
+ standard XXX.XXX.XXX.XXX-style representation of the address.
+
+ `GET_IP6ADDR_STRING()` fetches an IPv6 address pointed to by *p* and
+ returns a string that is either a host name, if the `-n` flag wasn't
+ specified and a host name could be found for the address, or the
+ standard XXXX::XXXX-style representation of the address.
+
+ `GET_MAC48_STRING()` fetches a 48-bit MAC address (Ethernet, 802.11,
+ etc.) pointed to by *p* and returns a string that is either a host
+ name, if the `-n` flag wasn't specified and a host name could be
+ found in the ethers file for the address, or the standard
+ XX:XX:XX:XX:XX:XX-style representation of the address.
+
+ `GET_EUI64_STRING()` fetches a 64-bit EUI pointed to by *p* and
+ returns a string that is the standard XX:XX:XX:XX:XX:XX:XX:XX-style
+ representation of the address.
+
+ `GET_EUI64LE_STRING()` fetches a 64-bit EUI, in reverse byte order,
+ pointed to by *p* and returns a string that is the standard
+ XX:XX:XX:XX:XX:XX:XX:XX-style representation of the address.
+
+ `GET_LINKADDR_STRING()` fetches an octet string, of length *length*
+ and type *type*, pointed to by *p* and returns a string whose format
+ depends on the value of *type*:
+
+ * `LINKADDR_MAC48` - if the length is 6, the string has the same
+ value as `GET_MAC48_STRING()` would return for that address,
+ otherwise, the string is a sequence of XX:XX:... values for the bytes
+ of the address;
+
+ * `LINKADDR_FRELAY` - the string is "DLCI XXX", where XXX is the
+ DLCI, if the address is a valid Q.922 header, and an error indication
+ otherwise;
+
+ * `LINKADDR_EUI64`, `LINKADDR_ATM`, `LINKADDR_OTHER` -
+ the string is a sequence of XX:XX:... values for the bytes
+ of the address.
+
+6) When defining a structure corresponding to a packet or part of a
+ packet, so that a pointer to packet data can be cast to a pointer to
+ that structure and that structure pointer used to refer to fields in
+ the packet, use the `nd_*` types for the structure members.
+
+ Those types all are aligned only on a 1-byte boundary, so a
+ compiler will not assume that the structure is aligned on a boundary
+ stricter than one byte; there is no guarantee that fields in packets
+ are aligned on any particular boundary.
+
+ This means that all padding in the structure must be explicitly
+ declared as fields in the structure.
+
+ The `nd_*` types for integral values are:
+
+ * `nd_uintN_t`, for unsigned integral values, where *N* is the number
+ of bytes in the value.
+ * `nd_intN_t`, for signed integral values, where *N* is the number
+ of bytes in the value.
+
+ The `nd_*` types for IP addresses are:
+
+ * `nd_ipv4`, for IPv4 addresses;
+ * `nd_ipv6`, for IPv6 addresses.
+
+ The `nd_*` types for link-layer addresses are:
+
+ * `nd_mac48`, for MAC-48 (Ethernet, 802.11, etc.) addresses;
+ * `nd_eui64`, for EUI-64 values.
+
+ The `nd_*` type for a byte in a sequence of bytes is `nd_byte`; an
+ *N*-byte sequence should be declared as `nd_byte[N]`.
+
+7) Do invalid packet checks in code: Think that your code can receive in input
not only a valid packet but any arbitrary random sequence of octets (packet
* built malformed originally by the sender or by a fuzz tester,
* became corrupted in transit or for some other reason).
Print with: `nd_print_invalid(ndo); /* to print " (invalid)" */`
-* Use `struct tok` for indexed strings and print them with
+8) Use `struct tok` for indexed strings and print them with
`tok2str()` or `bittok2str()` (for flags).
+ All `struct tok` must end with `{ 0, NULL }`.
-* Avoid empty lines in output of printers.
+9) Avoid empty lines in output of printers.
-* A commit message must have:
+10) A commit message must have:
```
First line: Capitalized short summary in the imperative (50 chars or less)
If the commit concerns a protocol, the summary line must start with
"protocol: ".
Body: Detailed explanatory text, if necessary. Fold it to approximately
72 characters. There must be an empty line separating the summary from
the body.
```
-* Avoid non-ASCII characters in code and commit messages.
+11) Avoid non-ASCII characters in code and commit messages.
-* Use the style of the modified sources.
+12) Use the style of the modified sources.
-* Don't mix declarations and code.
+13) Don't mix declarations and code.
-* Don't use `//` for comments.
- Not all C compilers accept C++/C99 comments by default.
+14) tcpdump requires a compiler that supports C99 or later, so C99
+ features may be used in code, but C11 or later features should not be
+ used.
-* Avoid trailing tabs/spaces
+15) Avoid trailing tabs/spaces
diff --git a/contrib/tcpdump/CREDITS b/contrib/tcpdump/CREDITS
index b6862ccba5a8..fca45605f8ad 100644
--- a/contrib/tcpdump/CREDITS
+++ b/contrib/tcpdump/CREDITS
@@ -1,359 +1,373 @@
This file lists people who have contributed to tcpdump.
The current maintainers (in alphabetical order):
Denis Ovsienko <denis at ovsienko dot info>
Francois-Xavier Le Bail <devel dot fx dot lebail at orange dot fr>
Guy Harris <gharris at sonic dot net>
Michael Richardson <mcr at sandelman dot ottawa dot on dot ca>
Additional people who have contributed patches (in alphabetical order):
Aaron Campbell <aaron at arbor dot net>
- A Costa <agcosta at gis dot net>
ABHIMANYU <agupta07 at sourceforge dot net>
+ A Costa <agcosta at gis dot net>
Adam Sampson <ats at offog dot org>
Ahmed Abdelsalam <ahabdels at gmail dot com>
Ajith Adapa <adapa dot ajith at gmail dot com>
Albert Chin <china at thewrittenword dot com>
Alexandra Kossovsky <alexandra1975 at sourceforge dot net>
- Alexandr Nedvedicky <alexandr dot nedvedicky at oracle dot com>
Alexandre Ferrieux <alexandre dot ferrieux at orange dot com>
+ Alexandr Nedvedicky <alexandr dot nedvedicky at oracle dot com>
Alexis La Goutte <alexis dot lagoutte at gmail dot com>
Alfredo Andres <aandres at s21sec dot com>
Ali Abdulkadir <autostart dot ini at gmail dot com>
Ananth Suryanarayana <anantha at juniper dot net>
Andrea Bittau <a dot bittau at cs dot ucl dot ac dot uk>
Andrea Ieri <andrea dot ieri at canonical dot com>
Andreas Jaggi <andreas dot jaggi at waterwave dot ch>
Andrew Brown <atatat at atatdot dot net>
Andrew Church <andrew at users dot sourceforge dot net>
Andrew Darqui <andrew dot darqui at gmail dot com>
Andrew Hintz <adhintz at users dot sourceforge dot net>
Andrew Lunn <andrew at lunn dot ch>
Andrew Nording <andrew at nording dot ru>
Andrew Tridgell <tridge at linuxcare dot com>
Andy Heffernan <ahh at juniper dot net>
Angus Cameron <anguscc at yahoo dot com>
Anton Bernal <anton at juniper dot net>
Antonin Décimo <antonin dot decimo at gmail dot com>
Aravind Prasad S <raja dot avi at gmail dot com>
Arkadiusz Miskiewicz <misiek at pld dot org dot pl>
Armando L. Caro Jr. <acaro at mail dot eecis dot udel dot edu>
Arnaldo Carvalho de Melo <acme at ghostprotocols dot net>
Atsushi Onoe <onoe at netbsd dot org>
Baptiste Jonglez <baptiste dot jonglez at ens-lyon dot org>
Baruch Siach <baruch at tkos dot co dot il>
Ben Byer <bushing at sourceforge dot net>
Ben Smithurst <ben at scientia dot demon dot co dot uk>
Bert Vermeulen <bert at biot dot com>
Bill Fenner <fenner at gmail dot com>
Bill Parker <wp02855 at gmail dot com>
Bjoern A. Zeeb <bzeeb at Zabbadoz dot NeT>
Bram <tcpdump at mail dot wizbit dot be>
Brent L. Bates <blbates at vigyan dot com>
Brian Carpenter <brian dot carpenter at gmail dot com>
Brian Ginsbach <ginsbach at cray dot com>
Brooks Davis <brooks at one-eyed-alien dot net>
Bruce M. Simpson <bms at spc dot org>
Bryce Wood <woodbr at oregonstate dot edu>
bugyo <bugyo at users dot noreply dot github dot com>
Carles Kishimoto Bisbe <ckishimo at ac dot upc dot es>
Casey Deccio <casey at deccio dot net>
+ Casper Andersson <casper dot casan at gmail dot com>
Charles (Chas) Williams <chwillia at ciena dot com>
Charles M. Hannum <mycroft at netbsd dot org>
Charlie Lenahan <clenahan at fortresstech dot com>
Chris Cogdon <chris at cogdon dot org>
Chris G. Demetriou <cgd at netbsd dot org>
Chris Jepeway <jepeway at blasted-heath dot com>
Chris Larson <clarson at kergoth dot com>
Christian Sievers <c_s at users dot sourceforge dot net>
Christophe Rhodes <csr21 at cantab dot net>
Cliff Frey <cliff at meraki dot com>
Craig Leres <leres at xse dot com>
Craig Rodrigues <rodrigc at mediaone dot net>
Crist J. Clark <cjclark at alum dot mit dot edu>
+ Dag-Erling Smørgrav <des at FreeBSD dot org>
Dagobert Michelsen <dam at opencsw dot org>
Daniel Hagerty <hag at ai dot mit dot edu>
Daniel Lee <Longinus00 at gmail dot com>
Daniel Miller <dmiller at nmap dot org>
Dario Lombardo <lomato at gmail dot com>
Darren Reed <darrenr at reed dot wattle dot id dot au>
David Binderman <d dot binderman at virgin dot net>
David Cronin <davidcronin94 at gmail dot com>
Davide Caratti <dcaratti at redhat dot com>
David Horn <dhorn2000 at gmail dot com>
+ David Karoly <david dot karoly at outlook dot com>
+ David Mirabito <davidjm at arista dot com>
David Smith <dsmith at redhat dot com>
David Young <dyoung at ojctech dot com>
Dion Bosschieter <dbosschieter at transip dot nl>
Dmitrij Tejblum <tejblum at yandex-team dot ru>
Dmitry Eremin-Solenikov <dbaryshkov at gmail dot com>
- Don Ebright <Don dot Ebright at compuware dot com>
+ Dominique Martinet <dominique dot martinet at atmark-techno dot com>
Donatas Abraitis <donatas dot abraitis at gmail dot com>
+ Don Ebright <Don dot Ebright at compuware dot com>
d simonov <simonov-d at yandex-team dot ru>
Duane Wessels <dwessels at verisign dot com>
Eamon Doyle <eamonjd at arista dot com>
Eddie Kohler <xexd at sourceforge dot net>
- Ege Cetin <egecetin at hotmail dot com dot tr>
+ Ed Maste <emaste at FreeBSD dot org>
+ Ege Çetin <egecetin at hotmail dot com dot tr>
Eliot Lear <lear at upstairs dot ofcourseimright dot com>
Elmar Kirchner <elmar at juniper dot net>
Eric S. Raymond <esr at thyrsus dot com>
Etienne Marais <etienne at marais dot green>
Fang Wang <fangwang at sourceforge dot net>
Ferry Huberts <ferry dot huberts at pelagic dot nl>
Florent Drouin <Florent dot Drouin at alcatel-lucent dot fr>
Florian Fainelli <f dot fainelli at gmail dot com>
Florian Forster <octo at verplant dot org>
fra <foo at bar dot baz>
Francesco Fondelli <francesco dot fondelli at gmail dot com>
Francisco Matias Cuenca-Acuna <mcuenca at george dot rutgers dot edu>
Francis Dupont <Francis dot Dupont at enst-bretagne dot fr>
Frank Volf <volf at oasis dot IAEhv dot nl>
Fulvio Risso <risso at polito dot it>
George Bakos <gbakos at ists dot dartmouth dot edu>
- Gerald Combs <gerald at ethereal dot com>
- Gerard Garcia <ggarcia at deic dot uab dot cat>
George Neville-Neil <gnn at freebsd dot org>
Gerald Combs <gerald at wireshark dot org>
+ Gerard Garcia <ggarcia at deic dot uab dot cat>
Gerrit Renker <gerrit at erg dot abdn dot ac dot uk>
Gert Doering <gert at greenie dot muc dot de>
Gianluca Varenni <gianluca dot varenni at gmail dot com>
Gilbert Ramirez Jr. <gram at xiexie dot org>
Gisle Vanem <gvanem at yahoo dot no>
Gleb Smirnoff <glebius at FreeBSD dot org>
Gokul Sivakumar <gokulkumar792 at gmail dot com>
Greg Minshall <minshall at acm dot org>
Grégoire Henry <henry at pps dot jussieu dot fr>
Gregory Detal <gregory dot detal at uclouvain dot be>
Greg Stark <gsstark at mit dot edu>
Greg Steinbrecher <steinbrecher at alum dot mit dot edu>
Guy Lewin <guy at lewin dot co dot il>
Hank Leininger <tcpdump-workers at progressive-comp dot com>
Hannes Gredler <hannes at gredler dot at>
Hannes Viertel <hviertel at juniper dot net>
Hanno Böck <hanno at hboeck dot de>
+ Hans Petter Selasky <hps at selasky dot org>
Harry Raaymakers <harryr at connect dot com dot au>
Heinz-Ado Arnolds <Ado dot Arnolds at dhm-systems dot de>
Hendrik Scholz <hendrik at scholz dot net>
Herwin Weststrate <herwin at quarantainenet dot nl>
Ian McDonald <imcdnzl at gmail dot com>
Ilpo Järvinen <ilpo dot jarvinen at helsinki dot fi>
ishaangandhi <ishaangandhi at gmail dot com>
Jacek Tobiasz <Jacek dot Tobiasz at atm dot com dot pl>
Jacob Davis <jacobgb24 at yahoo dot com>
Jakob Schlyter <jakob at openbsd dot org>
Jakub Zawadzki <darkjames at darkjames dot pl>
Jamal Hadi Salim <hadi at cyberus dot ca>
James Ko <jck at exegin dot com>
Jamie Bainbridge <jamie dot bainbridge at gmail dot com>
+ Janne Heß <janne at hess dot ooo>
Jan Oravec <wsx at wsx6 dot net>
Jason L. Wright <jason at thought dot net>
Jason R. Thorpe <thorpej at netbsd dot org>
Jean-Raphaël Gaglione <jr dot gaglione at yahoo dot fr>
Jeff Chan <jchan at arista dot com>
Jefferson Ogata <jogata at nodc dot noaa dot gov>
Jeffrey Hutzelman <jhutz at cmu dot edu>
Jeremy Browne <jer at ifni dot ca>
+ Jerome Duval <jerome dot duval at gmail dot com>
Jesper Peterson <jesper at endace dot com>
Jesse Gross <jesse at nicira dot com>
+ Jesse Rosenstock <jmr at google dot com>
Jim Hutchins <jim at ca dot sandia dot gov>
João Medeiros <ignotus21 at sourceforge dot net>
Job Snijders <job at instituut dot net>
Joerg Mayer <jmayer at loplof dot de>
+ Jonas Chianu <jchianu at onx-jchianu-02 dot ciena dot com>
Jonathan Heusser <jonny at drugphish dot ch>
Jorge Boncompte [DTI2] <jorge at dti2 dot net>
Jørgen Thomsen <jth at jth dot net>
+ Josh Soref <2119212+jsoref at users dot noreply dot github dot com>
Julian Cowley <julian at lava dot net>
Juliusz Chroboczek <jch at pps dot jussieu dot fr>
Kaarthik Sivakumar <kaarthik at torrentnet dot com>
Kaladhar Musunuru <kaladharm at sourceforge dot net>
Kamil Frankowicz <kontakt at frankowicz dot me>
Karl Norby <karl-norby at sourceforge dot net>
Kazushi Sugyo <sugyo at pb dot jp dot nec dot com>
Kelly Carmichael <kcarmich at ipapp dot com>
Ken Bantoft <ken at xelerance dot com>
Ken Hornstein <kenh at cmf dot nrl dot navy dot mil>
Kenichi Maehashi <webmaster at kenichimaehashi dot com>
Kevin Steves <stevesk at pobox dot com>
Klaus Klein <kleink at reziprozitaet dot de>
Kovarththanan Rajaratnam <kovarththanan dot rajaratnam at gmail dot com>
Kris Kennaway <kris at freebsd dot org>
Krzysztof Halasa <khc at pm dot waw dot pl>
Larry Lile <lile at stdio dot com>
Lennert Buytenhek <buytenh at gnu dot org>
Loganaden Velvindron <logan at cyberstorm dot mu>
Loris Degioanni <loris at netgroup-serv dot polito dot it>
Love Hörnquist-Åstrand <lha at stacken dot kth dot se>
Lucas C. Villa Real <lucasvr at us dot ibm dot com>
Luigi Rizzo <luigi at freebsd dot org>
Luis MartinGarcia <luis dot mgarc at gmail dot com>
Luiz Otavio O Souza <loos at freebsd dot org>
Maciej W. Rozycki <macro at ds2 dot pg dot gda dot pl>
Manoharan Sundaramoorthy <manoharan at arista dot com>
Manu Pathak <mapathak at cisco dot com>
Marc Abramowitz <marc at marc-abramowitz dot com>
Marc A. Lehmann <pcg at goof dot com>
Marc Binderberger <mbind at sourceforge dot net>
Mark Andrews <marka at isc dot org>
Mark Ellzey Thomas <mark at ackers dot net>
Marko Kiiskila <carnil at cs dot tut dot fi>
Markus Schöpflin <schoepflin at sourceforge dot net>
Marshall Rose <mrose at dbc dot mtview dot ca dot us>
Martin Buck <mb-tmp-tvguho dot pbz at gromit dot dyndns dot org>
Martin Husemann <martin at netbsd dot org>
Martin Sehnoutka <msehnout at redhat dot com>
+ Martin Willi <martin at strongswan dot org>
Matt Eaton <agnosticdev at gmail dot com>
Matthew Luckie <matthewluckie at sourceforge dot net>
+ Matthew Martin <phy1729 at gmail dot com>
Matthieu Boutier <boutier at pps dot univ-paris-diderot dot fr>
Max Laier <max at love2party dot net>
Michael A. Meffie III <meffie at sourceforge dot net>
Michael Haardt <michael at moria dot de>
Michael Kirkhart <michael dot kirkhart at att dot net>
Michael Madore <mmadore at turbolinux dot com>
Michael Riepe <too-tired at sourceforge dot net>
Michael Shalayeff <mickey at openbsd dot org>
Michael Shields <shields at msrl dot com>
Michael T. Stolarchuk <mts at off dot to>
Michal Ruprich <michalruprich at gmail dot com>
Michal Sekletar <msekleta at redhat dot com>
Michele "mydecay" Marchetto <smarchetto1 at tin dot it>
Mike Frysinger <vapier at gmail dot com>
Mingrui <972931182 at qq dot com>
Minto Jeyananth <minto at juniper dot net>
Miroslav Lichvar <mlichvar at redhat dot com>
Mister X <3520734+Mister-X- at users dot noreply dot github dot com>
Mitsunori Komatsu <komamitsu at gmail dot com>
Monroe Williams <monroe at pobox dot com>
Monthadar Al Jaberi <monthadar at gmail dot com>
Moses Devadason <mosesdevadason at gmail dot com>
Motonori Shindo <mshindo at mshindo dot net>
Nan Xiao <nan at chinadtrace dot org>
Nathaniel Couper-Noles <Nathaniel at isi1 dot tccisi dot com>
Nathan J. Williams <nathanw at MIT dot EDU>
Neelabh <neelabhsahay at gmail dot com>
Neil T. Spring <bluehal at users dot sourceforge dot net>
Nicholas Reilly <nreilly at blackberry dot com>
Nickolai Zeldovich <kolya at MIT dot EDU>
- Nikolay Edigaryev <edigaryev at gmail dot com>
Nicolas Ferrero <toorop at babylo dot net>
- niks3089 <niks3089 at gmail dot com>
Niels Provos <provos at openbsd dot org>
Nikhil AP <nikhilap at arista dot com>
+ Nikolay Edigaryev <edigaryev at gmail dot com>
+ niks3089 <niks3089 at gmail dot com>
Noritoshi Demizu <demizu at users dot sourceforge dot net>
Olaf Kirch <okir at caldera dot de>
Ola Martin Lykkja <ola dot lykkja at q-free dot com>
Oleksij Rempel <linux at rempel-privat dot de>
Onno van der Linden <onno at simplex dot nl>
Paolo Abeni <paolo dot abeni at email dot it>
Partha Ghosh <psg at cumulusnetworks dot com>
Pascal Hennequin <pascal dot hennequin at int-evry dot fr>
Pasvorn Boonmark <boonmark at juniper dot net>
Patrik Lundquist <patrik dot lundquist at gmail dot com>
Paul Ferrell <pflarr at sourceforge dot net>
Paul Mundt <lethal at linux-sh dot org>
Paul S. Traina <pst at freebsd dot org>
Pavlin Radoslavov <pavlin at icir dot org>
Pawel Worach <pawel dot worach at gmail dot com>
Pedro Monreal <pmgdeb at gmail dot com>
Pekka Savola <pekkas at netcore dot fi>
peppe <g1pi at libero dot it>
Petar Alilovic <petar dot alilovic at gmail dot com>
Peter Fales <peter at fales-lorenz dot net>
Peter Jeremy <peter dot jeremy at alcatel dot com dot au>
Peter Krystad <peter dot krystad at linux dot intel dot com>
Peter Volkov <pva at gentoo dot org>
Petr Vorel <pvorel at suse dot cz>
<pfhunt at users dot sourceforge dot net>
Phil Wood <cpw at lanl dot gov>
Pier Carlo Chiodi <pierky at pierky dot com>
Quentin Armitage <quentin at armitage dot org dot uk>
Rafal Maszkowski <rzm at icm dot edu dot pl>
Randy Sofia <rsofia at users dot sourceforge dot net>
Raphael Raimbault <raphael dot raimbault at netasq dot com>
Renato Botelho <garga at FreeBSD dot org>
Ricardo Nabinger Sanchez <rnsanchez at taghos dot com dot br>
Richard Scheffenegger <srichard at netapp dot com>
Rick Cheng <rcheng at juniper dot net>
Rick Jones <rick dot jones2 at hp dot com>
Rick Watson <watsonrick at users dot sourceforge dot net>
Ritesh Ranjan <r dot ranjan789 at gmail dot com>
Rob Braun <bbraun at synack dot net>
Robert Edmonds <stu-42 at sourceforge dot net>
Rocco Lucia <rlucia at iscanet dot com>
Roderick Schertler <roderick at argon dot org>
Romain Francoise <rfrancoise at debian dot org>
Romero Malaquias <romero dot malaquias at gmail dot com>
+ Rose <83477269+AtariDreams at users dot noreply dot github dot com>
Ruben Kerkhof <ruben at rubenkerkhof dot com>
Rui Paulo <rpaulo at FreeBSD dot org>
Sabrina Dubroca <sd at queasysnail dot net>
Sagun Shakya <sagun dot shakya at sun dot com>
- Sam James <sam at gentoo dot org>
Sami Farin <safari at iki dot fi>
+ Sam James <sam at gentoo dot org>
Sascha Wildner <swildner at sourceforge dot net>
Sawssen Hadded <saw dot hadded at gmail dot com>
Scott Mcmillan <scott dot a dot mcmillan at intel dot com>
Scott Rose <syberpunk at users dot sourceforge dot net>
Sebastian Krahmer <krahmer at cs dot uni-potsdam dot de>
Sebastien Raveau <sebastien dot raveau at epita dot fr>
Sebastien Vincent <svincent at idems dot fr>
Sepherosa Ziehau <sepherosa at gmail dot com>
Seth Webster <swebster at sst dot ll dot mit dot edu>
Shinsuke Suzuki <suz at kame dot net>
Simon Nicolussi <sinic at sinic dot name>
Simon Ruderich <simon at ruderich dot org>
Slava Shwartsman <slavash at mellanox dot com>
Stefan Hajnoczi <stefanha at redhat dot com>
Steinar Haug <sthaug at nethelp dot no>
Stephane Bortzmeyer <stephane+github at bortzmeyer dot org>
Steve Kay <stevekay at gmail dot com>
- Steve-o <fnjordy at sourceforge dot net>
Steven H. Wang <wang dot steven dot h at gmail dot com>
+ Steve-o <fnjordy at sourceforge dot net>
Swaathi Vetrivel <swaathiv at juniper dot net>
Swaminathan Chandrasekaran <chander at juniper dot net>
Takashi Yamamoto <yamt at mwd dot biglobe dot ne dot jp>
Tatuya Jinmei <jinmei at kame dot net>
Tero Kivinen <kivinen at iki dot fi>
Terry Kennedy <terry at tmk dot com>
test2 <test2 at safs64 dot (none)>
Thomas Jacob <jacob at internet24 dot de>
Tillmann Karras <tilkax at gmail dot com>
Timo Koskiahde
Tobias Waldekranz <tobias at waldekranz dot com>
Tom Jones <thj at freebsd dot org>
Tommy Beadle <tbeadle at arbor dot net>
Tony Li <tli at procket dot com>
Tony Samuels <vegizombie at gmail dot com>
Tony Xu <hhktony at gmail dot com>
Toshihiro Kanda <candy at fct dot kgc dot co dot jp>
Udayakumar <udaya011 at gmail dot com>
Ulrich Windl <Ulrich dot Windl at RZ dot Uni-Regensburg dot DE>
Uns Lider <unslider at miranda dot org>
Victor Oppleman <oppleman at users dot sourceforge dot net>
Viral Mehta <viral dot mehta at dell dot com>
Vitaly Lavrov <vel21ripn at gmail dot com>
Vivien Didelot <vivien dot didelot at gmail dot com>
Vyacheslav Trushkin <dogonthesun at gmail dot com>
Wang Jian <larkwang at gmail dot com>
Weesan Lee <weesan at juniper dot net>
Wesley Griffin <wgriffin at users dot sourceforge dot net>
Wesley Shields <wxs at FreeBSD dot org>
Wilbert de Graaf <wilbertdg at hetnet dot nl>
Will Drewry <will at alum dot bu dot edu>
William J. Hulley <bill dot hulley at gmail dot com>
Wim Torfs <wtorfs at gmail dot com>
Wolfgang Karall <office at karall-edv dot at>
Xin Li <delphij at FreeBSD dot org>
yekm <yekm at h0me>
Yen Yen Lim
Yoshifumi Nishida
zilog80a <zilog80a at sourceforge dot net>
zolf <flos at xs4all dot nl>
The original LBL crew:
Steve McCanne
Craig Leres
Van Jacobson
Past maintainers (in alphabetical order):
Bill Fenner <fenner at gmail dot com>
Fulvio Risso <risso at polito dot it>
Hannes Gredler <hannes at gredler dot at>
Jun-ichiro itojun Hagino <itojun at iijlab dot net> Also see: http://www.wide.ad.jp/itojun-award/
diff --git a/contrib/tcpdump/INSTALL.md b/contrib/tcpdump/INSTALL.md
index b3fbf42eaca8..08fc31b682d0 100644
--- a/contrib/tcpdump/INSTALL.md
+++ b/contrib/tcpdump/INSTALL.md
@@ -1,126 +1,143 @@
# tcpdump installation notes
If you have not built libpcap, and your system does not have libpcap
installed, install libpcap first. Your system might provide a version
of libpcap that can be installed; if so, to compile tcpdump you might
need to install a "developer" version of libpcap as well as the
-"run-time" version. You can also install tcpdump.org's version of
+"run-time" version. You can also install The Tcpdump Group version of
libpcap; see [this file](README.md) for the location.
You will need a C99 compiler to build tcpdump. The build system
will abort if your compiler is not C99 compliant. If this happens, use
the generally available GNU C compiler (GCC) or Clang.
After libpcap has been built (either install it with `make install` or
make sure both the libpcap and tcpdump source trees are in the same
-directory), run `./configure` (a shell script). `configure` will
+directory), do the following steps:
+
+* If you build from a git clone rather than from a release archive,
+run `./autogen.sh` (a shell script). The autogen.sh script will
+build the `configure` and `config.h.in` files.
+
+On some system, you may need to set the `AUTORECONF` variable, like:
+`AUTORECONF=autoreconf-2.69 ./autogen.sh`
+to select the `autoreconf` version you want to use.
+
+* Run `./configure` (a shell script). The configure script will
determine your system attributes and generate an appropriate `Makefile`
-from `Makefile.in`. Now build tcpdump by running `make`.
+from `Makefile.in`. The configure script has a number of options to
+control the configuration of tcpdump; `./configure --help` will show
+them.
+
+* Next, build tcpdump by running `make`.
+
+On OpenBSD, you may need to set, before the `make`, the `AUTOCONF_VERSION`
+variable like:
+`AUTOCONF_VERSION=2.69 make`
-If everything builds ok, `su` and type `make install`. This will install
+If everything builds fine, `su` and type `make install`. This will install
tcpdump and the manual entry. Any user will be able to use tcpdump to
read saved captures. Whether a user will be able to capture traffic
depends on the OS and the configuration of the system; see the
[tcpdump man page](https://www.tcpdump.org/manpages/tcpdump.1.html)
-for details. DO NOT give untrusted users the ability to
+for details. Do **NOT** give untrusted users the ability to
capture traffic. If a user can capture traffic, he or she could use
utilities such as tcpdump to capture any traffic on your net, including
passwords.
Note that most systems ship tcpdump, but usually an older version.
Building tcpdump from source as explained above will usually install the
binary as `/usr/local/bin/tcpdump`. If your system has other tcpdump
-binaries, you might need to deinstall these or to set the PATH environment
+binaries, you might need to deinstall these or to set the `PATH` environment
variable if you need the `tcpdump` command to run the new binary
(`tcpdump --version` can be used to tell different versions apart).
-If your system is not one which we have tested tcpdump on, you may have
+If your system is not one that we have tested tcpdump on, you may have
to modify the `configure` script and `Makefile.in`. Please
[send us patches](https://www.tcpdump.org/index.html#patches)
for any modifications you need to make.
Please see [this file](README.md) for notes about tested platforms.
## Description of files
```
CHANGES - description of differences between releases
CONTRIBUTING.md - guidelines for contributing
CREDITS - people that have helped tcpdump along
INSTALL.md - this file
LICENSE - the license under which tcpdump is distributed
Makefile.in - compilation rules (input to the configure script)
README.md - description of distribution
VERSION - version of this release
aclocal.m4 - autoconf macros
addrtoname.c - address to hostname routines
addrtoname.h - address to hostname definitions
addrtostr.c - address to printable string routines
addrtostr.h - address to printable string definitions
ah.h - IPSEC Authentication Header definitions
appletalk.h - AppleTalk definitions
ascii_strcasecmp.c - locale-independent case-independent string comparison
routines
atime.awk - TCP ack awk script
atm.h - ATM traffic type definitions
+autogen.sh - build configure and config.h.in (run this first)
bpf_dump.c - BPF program printing routines, in case libpcap doesn't
have them
chdlc.h - Cisco HDLC definitions
cpack.c - functions to extract packed data
cpack.h - declarations of functions to extract packed data
config.guess - autoconf support
-config.h.in - autoconf input
config.sub - autoconf support
-configure - configure script (run this first)
configure.ac - configure script source
doc/README.* - some building documentation
ethertype.h - Ethernet type value definitions
extract.h - alignment definitions
gmpls.c - GMPLS definitions
gmpls.h - GMPLS declarations
install-sh - BSD style install script
interface.h - globals, prototypes and definitions
ip.h - IP definitions
ip6.h - IPv6 definitions
ipproto.c - IP protocol type value-to-name table
ipproto.h - IP protocol type value definitions
l2vpn.c - L2VPN encapsulation value-to-name table
l2vpn.h - L2VPN encapsulation definitions
lbl/os-*.h - OS-dependent defines and prototypes
llc.h - LLC definitions
machdep.c - machine dependent routines
machdep.h - machine dependent definitions
makemib - mib to header script
mib.h - mib definitions
missing/* - replacements for missing library functions
ntp.c - functions to handle ntp structs
ntp.h - declarations of functions to handle ntp structs
mkdep - construct Makefile dependency list
mpls.h - MPLS definitions
nameser.h - DNS definitions
netdissect.h - definitions and declarations for tcpdump-as-library
(under development)
nfs.h - Network File System V2 definitions
nfsfh.h - Network File System file handle definitions
nlpid.c - OSI NLPID value-to-name table
nlpid.h - OSI NLPID definitions
ospf.h - Open Shortest Path First definitions
packetdat.awk - TCP chunk summary awk script
parsenfsfh.c - Network File System file parser routines
pcap-missing.h - declarations of functions possibly missing from libpcap
ppp.h - Point to Point Protocol definitions
print.c - Top-level routines for protocol printing
print-*.c - The netdissect printers
rpc_auth.h - definitions for ONC RPC authentication
rpc_msg.h - definitions for ONC RPC messages
send-ack.awk - unidirectional tcp send/ack awk script
slcompress.h - SLIP/PPP Van Jacobson compression (RFC1144) definitions
smb.h - SMB/CIFS definitions
smbutil.c - SMB/CIFS utility routines
stime.awk - TCP send awk script
tcp.h - TCP definitions
tcpdump.1 - manual entry
tcpdump.c - main program
timeval-operations.h - timeval operations macros
udp.h - UDP definitions
util-print.c - utility routines for protocol printers
```
diff --git a/contrib/tcpdump/Makefile.in b/contrib/tcpdump/Makefile.in
index 1bdeb514fc33..e991cce2da0f 100644
--- a/contrib/tcpdump/Makefile.in
+++ b/contrib/tcpdump/Makefile.in
@@ -1,539 +1,581 @@
# Copyright (c) 1988, 1989, 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.
#
# Various configurable paths (remember to edit Makefile.in, not Makefile)
#
# Top level hierarchy
prefix = @prefix@
exec_prefix = @exec_prefix@
datarootdir = @datarootdir@
# Pathname of directory to install the binary
bindir = @bindir@
# Pathname of directory to install the man page
mandir = @mandir@
# VPATH
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
#
# You shouldn't need to edit anything below here.
#
CC = @CC@
AR = @AR@
MKDEP = @MKDEP@
PROG = tcpdump
CCOPT = @V_CCOPT@
INCLS = -I. @V_INCLS@
DEFS = @DEFS@ @CPPFLAGS@ @V_DEFS@
# Standard CFLAGS
CFLAGS = @CFLAGS@
FULL_CFLAGS = $(CCOPT) $(DEFS) $(INCLS) $(CFLAGS)
# Standard LDFLAGS
LDFLAGS = @LDFLAGS@
# Standard LIBS
LIBS = @LIBS@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
RANLIB = @RANLIB@
DEPENDENCY_CFLAG = @DEPENDENCY_CFLAG@
# Explicitly define compilation rule since SunOS 4's make doesn't like gcc.
# Also, gcc does not remove the .o before forking 'as', which can be a
# problem if you don't own the file but can write to the directory.
.c.o:
@rm -f $@
$(CC) $(FULL_CFLAGS) -c $(srcdir)/$*.c
CSRC = fptype.c tcpdump.c
LIBNETDISSECT_SRC=\
addrtoname.c \
addrtostr.c \
af.c \
ascii_strcasecmp.c \
checksum.c \
cpack.c \
gmpls.c \
in_cksum.c \
ipproto.c \
l2vpn.c \
machdep.c \
netdissect.c \
netdissect-alloc.c \
nlpid.c \
ntp.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-arista.c \
print-arp.c \
print-ascii.c \
print-atalk.c \
print-atm.c \
print-babel.c \
print-bcm-li.c \
print-beep.c \
print-bfd.c \
print-bgp.c \
print-bootp.c \
print-brcmtag.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-dsa.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-demux.c \
print-ip.c \
print-ip6.c \
print-ip6opts.c \
print-ipcomp.c \
print-ipfc.c \
print-ipnet.c \
print-ipoib.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-macsec.c \
print-mobile.c \
print-mobility.c \
print-mpcp.c \
print-mpls.c \
print-mptcp.c \
print-msdp.c \
print-msnlb.c \
print-nflog.c \
print-nfs.c \
print-nsh.c \
print-ntp.c \
print-null.c \
print-olsr.c \
print-openflow-1.0.c \
print-openflow-1.3.c \
print-openflow.c \
print-ospf.c \
print-ospf6.c \
print-otv.c \
print-pflog.c \
print-pgm.c \
print-pim.c \
print-pktap.c \
print-ppi.c \
print-ppp.c \
print-pppoe.c \
print-pptp.c \
print-ptp.c \
print-radius.c \
print-raw.c \
print-realtek.c \
print-resp.c \
print-rip.c \
print-ripng.c \
print-rpki-rtr.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-smtp.c \
print-snmp.c \
print-someip.c \
print-ssh.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-unsupported.c \
print-usb.c \
print-vjc.c \
print-vqp.c \
print-vrrp.c \
print-vsock.c \
print-vtp.c \
print-vxlan-gpe.c \
print-vxlan.c \
print-wb.c \
print-whois.c \
print-zep.c \
print-zephyr.c \
print-zeromq.c \
signature.c \
strtoaddr.c \
util-print.c
LOCALSRC = @LOCALSRC@
LIBOBJS = @LIBOBJS@
LIBNETDISSECT_OBJ=$(LIBNETDISSECT_SRC:.c=.o) ${LOCALSRC:.c=.o} ${LIBOBJS}
LIBNETDISSECT=libnetdissect.a
SRC = $(CSRC) $(LOCALSRC)
# We would like to say "OBJ = $(SRC:.c=.o)" but Ultrix's make cannot
# hack the extra indirection
OBJ = $(CSRC:.c=.o)
HDR = \
addrtoname.h \
addrtostr.h \
af.h \
ah.h \
appletalk.h \
ascii_strcasecmp.h \
atm.h \
chdlc.h \
compiler-tests.h \
cpack.h \
diag-control.h \
ethertype.h \
extract.h \
fptype.h \
ftmacros.h \
funcattrs.h \
getservent.h \
gmpls.h \
interface.h \
ip.h \
ip6.h \
ipproto.h \
l2vpn.h \
llc.h \
machdep.h \
mib.h \
mpls.h \
nameser.h \
netdissect.h \
netdissect-alloc.h \
netdissect-ctype.h \
netdissect-stdinc.h \
nfs.h \
nfsfh.h \
nlpid.h \
ntp.h \
openflow.h \
ospf.h \
oui.h \
pcap-missing.h \
pflog.h \
ppp.h \
print.h \
rpc_auth.h \
rpc_msg.h \
signature.h \
slcompress.h \
smb.h \
status-exit-codes.h \
strtoaddr.h \
tcp.h \
timeval-operations.h \
udp.h \
varattrs.h
TAGHDR = \
/usr/include/netinet/if_ether.h \
/usr/include/netinet/in.h
TAGFILES = $(SRC) $(HDR) $(TAGHDR) $(LIBNETDISSECT_SRC) \
print-smb.c smbutil.c
-CLEANFILES = $(PROG) $(OBJ) $(LIBNETDISSECT_OBJ) print-smb.o smbutil.o
+CLEANFILES = $(PROG) $(OBJ) $(LIBNETDISSECT_OBJ) \
+ print-smb.o smbutil.o instrument-functions.o
EXTRA_DIST = \
CHANGES \
CMakeLists.txt \
CONTRIBUTING.md \
CREDITS \
INSTALL.md \
LICENSE \
Makefile-devel-adds \
Makefile.in \
README.md \
VERSION \
aclocal.m4 \
+ autogen.sh \
atime.awk \
bpf_dump.c \
cmake/Modules/FindCRYPTO.cmake \
cmake/Modules/FindPCAP.cmake \
cmake/Modules/FindSMI.cmake \
cmake_uninstall.cmake.in \
cmakeconfig.h.in \
config.guess \
- config.h.in \
config.sub \
- configure \
configure.ac \
doc/README.aix.md \
+ doc/README.haiku.md \
doc/README.NetBSD.md \
doc/README.solaris.md \
- doc/README.Win32.md \
+ doc/README.windows.md \
install-sh \
+ instrument-functions.c \
lbl/os-osf4.h \
lbl/os-solaris2.h \
lbl/os-sunos4.h \
lbl/os-ultrix4.h \
makemib \
missing/datalinks.c \
missing/dlnames.c \
missing/getopt_long.c \
missing/getopt_long.h \
missing/getservent.c \
missing/pcap_dump_ftell.c \
missing/snprintf.c \
missing/strdup.c \
missing/strlcat.c \
missing/strlcpy.c \
missing/strsep.c \
mkdep \
packetdat.awk \
print-smb.c \
send-ack.awk \
smbutil.c \
stime.awk \
tcpdump.1.in
-TEST_DIST= `git ls-files tests | grep -v 'tests/\..*'`
+TEST_DIST= `git -C "$$DIR" ls-files tests | grep -v 'tests/\..*'`
RELEASE_FILES = $(CSRC) $(HDR) $(LIBNETDISSECT_SRC) $(EXTRA_DIST) $(TEST_DIST)
all: $(PROG)
$(PROG): $(OBJ) @V_PCAPDEP@ $(LIBNETDISSECT)
@rm -f $@
$(CC) $(FULL_CFLAGS) $(LDFLAGS) -o $@ $(OBJ) $(LIBNETDISSECT) $(LIBS)
$(LIBNETDISSECT): $(LIBNETDISSECT_OBJ)
@rm -f $@
$(AR) cr $@ $(LIBNETDISSECT_OBJ)
$(RANLIB) $@
datalinks.o: $(srcdir)/missing/datalinks.c
$(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/datalinks.c
dlnames.o: $(srcdir)/missing/dlnames.c
$(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/dlnames.c
getservent.o: $(srcdir)/missing/getservent.c
$(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/getservent.c
getopt_long.o: $(srcdir)/missing/getopt_long.c
$(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/getopt_long.c
snprintf.o: $(srcdir)/missing/snprintf.c
$(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/snprintf.c
strdup.o: $(srcdir)/missing/strdup.c
$(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/strdup.c
strlcat.o: $(srcdir)/missing/strlcat.c
$(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/strlcat.c
strlcpy.o: $(srcdir)/missing/strlcpy.c
$(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/strlcpy.c
strsep.o: $(srcdir)/missing/strsep.c
$(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/strsep.c
pcap_dump_ftell.o: $(srcdir)/missing/pcap_dump_ftell.c
$(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/pcap_dump_ftell.c
install: all
[ -d $(DESTDIR)$(bindir) ] || \
(mkdir -p $(DESTDIR)$(bindir); chmod 755 $(DESTDIR)$(bindir))
$(INSTALL_PROGRAM) $(PROG) $(DESTDIR)$(bindir)/$(PROG)
$(INSTALL_PROGRAM) $(PROG) $(DESTDIR)$(bindir)/$(PROG).`cat ${srcdir}/VERSION`
[ -d $(DESTDIR)$(mandir)/man1 ] || \
(mkdir -p $(DESTDIR)$(mandir)/man1; chmod 755 $(DESTDIR)$(mandir)/man1)
$(INSTALL_DATA) $(PROG).1 $(DESTDIR)$(mandir)/man1/$(PROG).1
uninstall:
rm -f $(DESTDIR)$(bindir)/$(PROG)
rm -f $(DESTDIR)$(bindir)/$(PROG).`cat ${srcdir}/VERSION`
rm -f $(DESTDIR)$(mandir)/man1/$(PROG).1
lint:
lint -hbxn $(SRC) $(LIBNETDISSECT_SRC) | \
grep -v 'struct/union .* never defined' | \
grep -v 'possible pointer alignment problem'
clean:
- rm -f $(CLEANFILES) $(PROG)-`cat ${srcdir}/VERSION`.tar.gz
+ rm -f $(CLEANFILES) $(PROG)-`cat ${srcdir}/VERSION`.tar.gz \
+ config.h.in~ configure~ configure.ac~
-distclean:
- rm -f $(CLEANFILES) Makefile config.cache config.log config.status \
+distclean: clean
+ rm -f Makefile config.cache config.log config.status \
config.h os-proto.h stamp-h stamp-h.in $(PROG).1 \
libnetdissect.a tests/.failed tests/.passed \
tests/failure-outputs.txt
rm -rf autom4te.cache tests/DIFF tests/NEW
check: tcpdump
$(srcdir)/tests/TESTrun
extags: $(TAGFILES)
ctags $(TAGFILES)
tags: $(TAGFILES)
ctags -wtd $(TAGFILES)
TAGS: $(TAGFILES)
etags $(TAGFILES)
+#
+# Use git archive piped to tar to construct a subdirectory whose name
+# is tcpdump-{release}, containing all the checked-in source files,
+# and then run autoreconf in that directory to generate the configure
+# script and other files from that source. Then remove autom4te.cache,
+# construct the release tarball from that subdirectory, and remove
+# the subdirectory.
+#
+# The --format=tar is to force git archive to write a non-compressed
+# archive, in case the platform's tar command doesn't have built-in
+# decompression.
+#
+# The ^{tree} is there to force git archive not to write out the
+# "helpful" global extended pax header with a commit ID, as not all
+# versions of tar can handle that (Solaris tar can't, for example).
+# (It turns HEAD, or a tag, both of which are apparently "tree-ish"es,
+# into a tree; apparently, unlike HEAD, or a tag, which have a commit
+# ID associated with them, the tree associated with them doesn't have
+# a commit ID, so no commit ID is available to write, and thus
+# git archive doesn't write one.)
+#
releasetar:
@TAG=$(PROG)-`cat VERSION` && \
- if git show-ref --tags --quiet --verify -- "refs/tags/$$TAG"; then \
- git archive --prefix="$$TAG"/ -o "$$TAG".tar.gz "$$TAG" \
- $(RELEASE_FILES) && \
+ if [ ! -d .git ]; then echo 'Not in a git clone, stop.'; exit 1; fi && \
+ TMPTESTFILE=`mktemp -t tmptestfile_XXXXXXXX` && \
+ rm -f "$$TMPTESTFILE" && \
+ AUTORECONF_DIR=`dirname "$$TMPTESTFILE"`/"$(PROG)"_build_autoreconf_$$$$ && \
+ DIR=`pwd` && \
+ rm -rf "$$AUTORECONF_DIR" && \
+ mkdir "$$AUTORECONF_DIR" && \
+ cd "$$AUTORECONF_DIR" && \
+ if git -C "$$DIR" show-ref --tags --quiet --verify -- "refs/tags/$$TAG"; then \
+ (git -C "$$DIR" archive --format=tar --prefix="$$TAG"/ "$$TAG^{tree}" $(RELEASE_FILES) | \
+ tar xf -) && \
echo "Archive build from tag $$TAG."; \
else \
- git archive --prefix="$$TAG"/ -o "$$TAG".tar.gz HEAD \
- $(RELEASE_FILES) && \
+ (git -C "$$DIR" archive --format=tar --prefix="$$TAG"/ "HEAD^{tree}" $(RELEASE_FILES) | \
+ tar xf -) && \
echo "No $$TAG tag. Archive build from HEAD."; \
- fi
+ fi && \
+ (cd "$$TAG" && "$${AUTORECONF:-autoreconf}" && rm -rf autom4te.cache) && \
+ tar cf "$$DIR/$$TAG".tar "$$TAG" && \
+ rm -f "$$DIR/$$TAG".tar.gz && \
+ gzip --best "$$DIR/$$TAG".tar && \
+ cd "$$DIR" && \
+ rm -rf "$$AUTORECONF_DIR"
releasecheck: releasetar
@TAG=$(PROG)-`cat VERSION` && \
INSTALL_DIR=/tmp/install_"$$TAG"_$$$$ && \
DIR=`pwd` && \
cd /tmp && \
rm -rf "$$TAG" && \
rm -rf "$$INSTALL_DIR" && \
tar xf "$$DIR"/"$$TAG".tar.gz && \
cd "$$TAG" && \
- echo "[$@] $$ ./configure --enable-smb --quiet --prefix=$$INSTALL_DIR" && \
- ./configure --enable-smb --quiet --prefix="$$INSTALL_DIR" && \
- echo '[$@] $$ make -s all check' && \
- make -s all check >/dev/null && \
- echo '[$@] $$ make -s install' && \
- make -s install && \
+ echo "[$@] $$ touch .devel" && \
+ touch .devel && \
+ echo "[$@] $$ ./configure --enable-instrument-functions --enable-smb --quiet --prefix=$$INSTALL_DIR" && \
+ ./configure --enable-instrument-functions --enable-smb --quiet --prefix="$$INSTALL_DIR" && \
+ echo '[$@] $$ $(MAKE) -s all check' && \
+ $(MAKE) -s all check >/dev/null && \
+ echo '[$@] $$ $(MAKE) -s install' && \
+ $(MAKE) -s install && \
cd .. && \
rm -rf "$$TAG" && \
rm -rf "$$INSTALL_DIR" && \
tar xf "$$DIR"/"$$TAG".tar.gz && \
cd "$$TAG" && \
+ echo "[$@] $$ touch .devel" && \
+ touch .devel && \
mkdir build && \
cd build && \
echo '[$@] $$ cmake -DENABLE_SMB=yes [...] ..' && \
cmake -DENABLE_SMB=yes \
-DCMAKE_INSTALL_PREFIX="$$INSTALL_DIR" \
-DCMAKE_MESSAGE_LOG_LEVEL=NOTICE \
-DCMAKE_RULE_MESSAGES=OFF \
-DCMAKE_INSTALL_MESSAGE=NEVER \
.. && \
- echo '[$@] $$ make -s all check' && \
- make -s all check >/dev/null && \
- echo '[$@] $$ make -s install' && \
- make -s install && \
+ echo '[$@] $$ $(MAKE) -s all check' && \
+ $(MAKE) -s all check >/dev/null && \
+ echo '[$@] $$ $(MAKE) -s install' && \
+ $(MAKE) -s install && \
cd ../.. && \
rm -rf "$$TAG" && \
rm -rf "$$INSTALL_DIR" && \
echo '[$@] Done.'
whitespacecheck:
@# trailing space(s)?
@if git grep -I -n ' $$' $$(git ls-files|grep -v '^tests/'); then \
echo 'Error: Trailing space(s).'; \
exit 1; \
fi
@# trailing tab(s)?
- @# install-sh has a tab at the end of one line
- @if git grep -I -n ' $$' $$(git ls-files|grep -vE '^(tests/|install-sh$$)'); then \
+ @if git grep -I -n ' $$' $$(git ls-files|grep -v '^tests/'); then \
echo 'Error: Trailing tabs(s).'; \
exit 1; \
fi
@# space(s) before tab(s)?
@if git grep -I -n '[ ][ ]' $$(git ls-files|grep -v '^tests/'); then \
echo 'Error: space(s) before tab(s).'; \
exit 1; \
fi
testlist:
echo $(TEST_DIST)
depend:
- $(MKDEP) -c "$(CC)" -m "$(DEPENDENCY_CFLAG)" -s "$(srcdir)" $(DEFS) $(INCLS) $(SRC) $(LIBNETDISSECT_SRC)
+ @echo $(MKDEP) -c $(CC) -m "$(DEPENDENCY_CFLAG)" -s "$(srcdir)" $(DEFS) $(INCLS) $(SRC) '<libnetdissect src list>'
+ @$(MKDEP) -c $(CC) -m "$(DEPENDENCY_CFLAG)" -s "$(srcdir)" $(DEFS) $(INCLS) $(SRC) $(LIBNETDISSECT_SRC)
shellcheck:
- shellcheck -f gcc -e SC2006 build.sh build_matrix.sh build_common.sh
+ shellcheck -f gcc -e SC2006 autogen.sh build.sh build_matrix.sh build_common.sh mkdep .ci-coverity-scan-build.sh
diff --git a/contrib/tcpdump/VERSION b/contrib/tcpdump/VERSION
index 9609202bb584..33640cd1b928 100644
--- a/contrib/tcpdump/VERSION
+++ b/contrib/tcpdump/VERSION
@@ -1 +1 @@
-4.99.4
+4.99.5
diff --git a/contrib/tcpdump/addrtoname.c b/contrib/tcpdump/addrtoname.c
index 914665c2315a..fd04e781996f 100644
--- a/contrib/tcpdump/addrtoname.c
+++ b/contrib/tcpdump/addrtoname.c
@@ -1,1330 +1,1327 @@
/*
* 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 HAVE_CASPER
#include <libcasper.h>
#include <casper/cap_dns.h>
#endif /* HAVE_CASPER */
#include "netdissect-stdinc.h"
#ifdef USE_ETHER_NTOHOST
#if defined(NET_ETHERNET_H_DECLARES_ETHER_NTOHOST)
/*
* OK, just include <net/ethernet.h>.
*/
#include <net/ethernet.h>
#elif defined(NETINET_ETHER_H_DECLARES_ETHER_NTOHOST)
/*
* OK, just include <netinet/ether.h>
*/
#include <netinet/ether.h>
#elif defined(SYS_ETHERNET_H_DECLARES_ETHER_NTOHOST)
/*
* OK, just include <sys/ethernet.h>
*/
#include <sys/ethernet.h>
#elif defined(ARPA_INET_H_DECLARES_ETHER_NTOHOST)
/*
* OK, just include <arpa/inet.h>
*/
#include <arpa/inet.h>
#elif defined(NETINET_IF_ETHER_H_DECLARES_ETHER_NTOHOST)
/*
* OK, include <netinet/if_ether.h>, after all the other stuff we
* need to include or define for its benefit.
*/
#define NEED_NETINET_IF_ETHER_H
#else
/*
* We'll have to declare it ourselves.
* If <netinet/if_ether.h> defines struct ether_addr, include
* it. Otherwise, define it ourselves.
*/
#ifdef HAVE_STRUCT_ETHER_ADDR
#define NEED_NETINET_IF_ETHER_H
#else /* HAVE_STRUCT_ETHER_ADDR */
struct ether_addr {
/* Beware FreeBSD calls this "octet". */
unsigned char ether_addr_octet[MAC_ADDR_LEN];
};
#endif /* HAVE_STRUCT_ETHER_ADDR */
#endif /* what declares ether_ntohost() */
#ifdef NEED_NETINET_IF_ETHER_H
/*
* Include diag-control.h before <net/if.h>, which too defines a macro
* named ND_UNREACHABLE.
*/
#include "diag-control.h"
#include <net/if.h> /* Needed on some platforms */
#include <netinet/in.h> /* Needed on some platforms */
#include <netinet/if_ether.h>
#endif /* NEED_NETINET_IF_ETHER_H */
#ifndef HAVE_DECL_ETHER_NTOHOST
/*
* No header declares it, so declare it ourselves.
*/
extern int ether_ntohost(char *, const struct ether_addr *);
#endif /* !defined(HAVE_DECL_ETHER_NTOHOST) */
#endif /* USE_ETHER_NTOHOST */
#include <pcap.h>
#include <pcap-namedb.h>
#ifndef HAVE_GETSERVENT
#include <getservent.h>
#endif
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "netdissect.h"
#include "addrtoname.h"
#include "addrtostr.h"
#include "ethertype.h"
#include "llc.h"
#include "extract.h"
#include "oui.h"
/*
* hash tables for whatever-to-name translations
*
* ndo_error() called on strdup(3) failure with S_ERR_ND_MEM_ALLOC status
*/
#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 {
strlcpy(host.h_name, hname, NI_MAXHOST);
return &host;
}
break;
default:
return NULL;
}
}
#define gethostbyaddr win32_gethostbyaddr
#endif /* _WIN32 */
struct h6namemem {
nd_ipv6 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[] */
struct enamemem *e_nxt;
};
static struct enamemem enametable[HASHNAMESIZE];
static struct enamemem nsaptable[HASHNAMESIZE];
struct bsnamemem {
u_short bs_addr0;
u_short bs_addr1;
u_short bs_addr2;
const char *bs_name;
u_char *bs_bytes;
unsigned int bs_nbytes;
struct bsnamemem *bs_nxt;
};
static struct bsnamemem 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)
{
char *cp;
u_int byte;
int n;
static char buf[sizeof(".xxx.xxx.xxx.xxx")];
addr = ntohl(addr);
cp = buf + sizeof(buf);
*--cp = '\0';
n = 4;
do {
byte = addr & 0xff;
*--cp = (char)(byte % 10) + '0';
byte /= 10;
if (byte > 0) {
*--cp = (char)(byte % 10) + '0';
byte /= 10;
if (byte > 0)
*--cp = (char)byte + '0';
}
*--cp = '.';
addr >>= 8;
} while (--n > 0);
return cp + 1;
}
static uint32_t f_netmask;
static uint32_t f_localnet;
#ifdef HAVE_CASPER
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, so you
* *CANNOT* use the ND_TCHECK_* or ND_TTEST_* 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 *
ipaddr_string(netdissect_options *ndo, const u_char *ap)
{
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 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, S_ERR_ND_MEM_ALLOC,
"%s: strdup(hp->h_name)", __func__);
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, S_ERR_ND_MEM_ALLOC,
"%s: strdup(intoa(addr))", __func__);
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 *
ip6addr_string(netdissect_options *ndo, const u_char *ap)
{
struct hostent *hp;
union {
nd_ipv6 addr;
struct for_hash_addr {
char fill[14];
uint16_t d;
} addra;
} addr;
struct h6namemem *p;
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);
}
memcpy(p->addr, addr.addr, sizeof(nd_ipv6));
p->nxt = newh6namemem(ndo);
/*
* Do not print names if -n was given.
*/
if (!ndo->ndo_nflag) {
#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, S_ERR_ND_MEM_ALLOC,
"%s: strdup(hp->h_name)", __func__);
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, S_ERR_ND_MEM_ALLOC,
"%s: strdup(cp)", __func__);
return (p->name);
}
static const char hex[16] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};
/*
* Convert an octet to two hex digits.
*
* Coverity appears either:
*
* not to believe the C standard when it asserts that a uint8_t is
* exactly 8 bits in size;
*
* not to believe that an unsigned type of exactly 8 bits has a value
* in the range of 0 to 255;
*
* not to believe that, for a range of unsigned values, if you shift
* one of those values right by 4 bits, the maximum result value is
* the maximum value shifted right by 4 bits, with no stray 1's shifted
* in;
*
* not to believe that 255 >> 4 is 15;
*
* so it gets upset that we're taking a "tainted" unsigned value, shifting
* it right 4 bits, and using it as an index into a 16-element array.
*
* So we do a stupid pointless masking of the result of the shift with
* 0xf, to hammer the point home to Coverity.
*/
static inline char *
octet_to_hex(char *cp, uint8_t octet)
{
*cp++ = hex[(octet >> 4) & 0xf];
*cp++ = hex[(octet >> 0) & 0xf];
return (cp);
}
/* Find the hash node that corresponds the ether address 'ep' */
static struct enamemem *
lookup_emem(netdissect_options *ndo, const u_char *ep)
{
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 = (u_short)i;
tp->e_addr1 = (u_short)j;
tp->e_addr2 = (u_short)k;
tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp));
if (tp->e_nxt == NULL)
(*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC, "%s: calloc", __func__);
return tp;
}
/*
* Find the hash node that corresponds to the bytestring 'bs'
* with length 'nlen'
*/
static struct bsnamemem *
lookup_bytestring(netdissect_options *ndo, const u_char *bs,
const unsigned int nlen)
{
struct bsnamemem *tp;
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->bs_nxt)
if (nlen == tp->bs_nbytes &&
tp->bs_addr0 == i &&
tp->bs_addr1 == j &&
tp->bs_addr2 == k &&
memcmp((const char *)bs, (const char *)(tp->bs_bytes), nlen) == 0)
return tp;
else
tp = tp->bs_nxt;
tp->bs_addr0 = (u_short)i;
tp->bs_addr1 = (u_short)j;
tp->bs_addr2 = (u_short)k;
tp->bs_bytes = (u_char *) calloc(1, nlen);
if (tp->bs_bytes == NULL)
(*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC,
"%s: calloc", __func__);
memcpy(tp->bs_bytes, bs, nlen);
tp->bs_nbytes = nlen;
tp->bs_nxt = (struct bsnamemem *)calloc(1, sizeof(*tp));
if (tp->bs_nxt == NULL)
(*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC,
"%s: calloc", __func__);
return tp;
}
/* Find the hash node that corresponds the NSAP 'nsap' */
static struct enamemem *
lookup_nsap(netdissect_options *ndo, const u_char *nsap,
u_int nsap_length)
{
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
+ } else
i = j = k = 0;
tp = &nsaptable[(i ^ j) & (HASHNAMESIZE-1)];
while (tp->e_nxt)
if (nsap_length == tp->e_nsap[0] &&
tp->e_addr0 == i &&
tp->e_addr1 == j &&
tp->e_addr2 == k &&
memcmp((const char *)nsap,
(char *)&(tp->e_nsap[1]), nsap_length) == 0)
return tp;
else
tp = tp->e_nxt;
tp->e_addr0 = (u_short)i;
tp->e_addr1 = (u_short)j;
tp->e_addr2 = (u_short)k;
tp->e_nsap = (u_char *)malloc(nsap_length + 1);
if (tp->e_nsap == NULL)
(*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC, "%s: malloc", __func__);
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, S_ERR_ND_MEM_ALLOC, "%s: calloc", __func__);
return tp;
}
/* Find the hash node that corresponds the protoid 'pi'. */
static struct protoidmem *
lookup_protoid(netdissect_options *ndo, const u_char *pi)
{
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 = (u_short)j;
tp->p_nxt = (struct protoidmem *)calloc(1, sizeof(*tp));
if (tp->p_nxt == NULL)
(*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC, "%s: calloc", __func__);
return tp;
}
const char *
etheraddr_string(netdissect_options *ndo, const uint8_t *ep)
{
int i;
char *cp;
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];
/*
* This is a non-const copy of ep for ether_ntohost(), which
* has its second argument non-const in OpenBSD. Also saves a
* type cast.
*/
struct ether_addr ea;
memcpy (&ea, ep, MAC_ADDR_LEN);
if (ether_ntohost(buf2, &ea) == 0) {
tp->e_name = strdup(buf2);
if (tp->e_name == NULL)
(*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC,
"%s: strdup(buf2)", __func__);
return (tp->e_name);
}
}
#endif
cp = buf;
oui = EXTRACT_BE_U_3(ep);
cp = octet_to_hex(cp, *ep++);
for (i = 5; --i >= 0;) {
*cp++ = ':';
cp = octet_to_hex(cp, *ep++);
}
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, S_ERR_ND_MEM_ALLOC,
"%s: strdup(buf)", __func__);
return (tp->e_name);
}
const char *
le64addr_string(netdissect_options *ndo, const uint8_t *ep)
{
const unsigned int len = 8;
u_int i;
char *cp;
struct bsnamemem *tp;
char buf[BUFSIZE];
tp = lookup_bytestring(ndo, ep, len);
if (tp->bs_name)
return (tp->bs_name);
cp = buf;
for (i = len; i > 0 ; --i) {
cp = octet_to_hex(cp, *(ep + i - 1));
*cp++ = ':';
}
cp --;
*cp = '\0';
tp->bs_name = strdup(buf);
if (tp->bs_name == NULL)
(*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC,
"%s: strdup(buf)", __func__);
return (tp->bs_name);
}
const char *
linkaddr_string(netdissect_options *ndo, const uint8_t *ep,
const unsigned int type, const unsigned int len)
{
u_int i;
char *cp;
struct bsnamemem *tp;
if (len == 0)
return ("<empty>");
if (type == LINKADDR_ETHER && len == MAC_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->bs_name)
return (tp->bs_name);
tp->bs_name = cp = (char *)malloc(len*3);
if (tp->bs_name == NULL)
(*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC,
"%s: malloc", __func__);
cp = octet_to_hex(cp, *ep++);
for (i = len-1; i > 0 ; --i) {
*cp++ = ':';
cp = octet_to_hex(cp, *ep++);
}
*cp = '\0';
return (tp->bs_name);
}
#define ISONSAP_MAX_LENGTH 20
const char *
isonsap_string(netdissect_options *ndo, const uint8_t *nsap,
u_int nsap_length)
{
u_int nsap_idx;
char *cp;
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, S_ERR_ND_MEM_ALLOC,
"%s: malloc", __func__);
for (nsap_idx = 0; nsap_idx < nsap_length; nsap_idx++) {
cp = octet_to_hex(cp, *nsap++);
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)
{
struct hnamemem *tp;
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, S_ERR_ND_MEM_ALLOC,
"%s: strdup(buf)", __func__);
return (tp->name);
}
const char *
udpport_string(netdissect_options *ndo, u_short port)
{
struct hnamemem *tp;
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, S_ERR_ND_MEM_ALLOC,
"%s: strdup(buf)", __func__);
return (tp->name);
}
const char *
ipxsap_string(netdissect_options *ndo, u_short port)
{
char *cp;
struct hnamemem *tp;
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;
port = 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, S_ERR_ND_MEM_ALLOC,
"%s: strdup(buf)", __func__);
return (tp->name);
}
static void
init_servarray(netdissect_options *ndo)
{
struct servent *sv;
struct hnamemem *table;
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, S_ERR_ND_MEM_ALLOC,
"%s: strdup", __func__);
table->addr = port;
table->nxt = newhnamemem(ndo);
}
endservent();
}
static const struct eproto {
const char *s;
u_short p;
} eproto_db[] = {
{ "aarp", ETHERTYPE_AARP },
{ "arp", ETHERTYPE_ARP },
{ "atalk", ETHERTYPE_ATALK },
{ "decnet", ETHERTYPE_DN },
{ "ip", ETHERTYPE_IP },
{ "ip6", ETHERTYPE_IPV6 },
{ "lat", ETHERTYPE_LAT },
{ "loopback", ETHERTYPE_LOOPBACK },
{ "mopdl", ETHERTYPE_MOPDL },
{ "moprc", ETHERTYPE_MOPRC },
{ "rarp", ETHERTYPE_REVARP },
{ "sca", ETHERTYPE_SCA },
{ (char *)0, 0 }
};
static void
init_eprotoarray(netdissect_options *ndo)
{
int i;
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)
{
int i;
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, S_ERR_ND_MEM_ALLOC,
"%s: strdup(eproto_db[i].s)", __func__);
}
/* 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 nd_mac_addr addr;
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)
{
const struct etherlist *el;
struct enamemem *tp;
#ifdef USE_ETHER_NTOHOST
char name[256];
#else
struct pcap_etherent *ep;
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, S_ERR_ND_MEM_ALLOC,
"%s: strdup(ep->addr)", __func__);
}
(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.
*/
/* Same workaround as in etheraddr_string(). */
struct ether_addr ea;
memcpy (&ea, el->addr, MAC_ADDR_LEN);
if (ether_ntohost(name, &ea) == 0) {
tp->e_name = strdup(name);
if (tp->e_name == NULL)
(*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC,
"%s: strdup(name)", __func__);
continue;
}
#endif
tp->e_name = el->name;
}
}
static const struct ipxsap_ent {
uint16_t v;
const char *s;
} 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" },
+ { 0x0327, "MicrosoftDiagnostics" },
{ 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)
{
int i;
struct hnamemem *table;
for (i = 0; ipxsap_db[i].s != NULL; i++) {
u_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)
{
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);
tp->name = dnnum_string(ndo, dnaddr);
return(tp->name);
}
/* Return a zero'ed hnamemem struct and cuts down on calloc() overhead */
struct hnamemem *
newhnamemem(netdissect_options *ndo)
{
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, S_ERR_ND_MEM_ALLOC,
"%s: calloc", __func__);
}
--num;
p = ptr++;
return (p);
}
/* Return a zero'ed h6namemem struct and cuts down on calloc() overhead */
struct h6namemem *
newh6namemem(netdissect_options *ndo)
{
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, S_ERR_ND_MEM_ALLOC,
"%s: calloc", __func__);
}
--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;
}
diff --git a/contrib/tcpdump/addrtostr.c b/contrib/tcpdump/addrtostr.c
index c3bdb8af342c..1fd2cf0908bf 100644
--- a/contrib/tcpdump/addrtostr.c
+++ b/contrib/tcpdump/addrtostr.c
@@ -1,213 +1,203 @@
/*
* Copyright (c) 1999 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the Kungliga Tekniska
* Högskolan and its contributors.
*
* 4. Neither the name of the Institute 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 BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "addrtostr.h"
#include <stdio.h>
#include <string.h>
/*
*
*/
#ifndef IN6ADDRSZ
#define IN6ADDRSZ 16 /* IPv6 T_AAAA */
#endif
#ifndef INT16SZ
#define INT16SZ 2 /* word size */
#endif
const char *
addrtostr (const void *src, char *dst, size_t size)
{
const u_char *srcaddr = (const u_char *)src;
const char digits[] = "0123456789";
int i;
const char *orig_dst = dst;
if (size < INET_ADDRSTRLEN) {
errno = ENOSPC;
return NULL;
}
for (i = 0; i < 4; ++i) {
int n = *srcaddr++;
int non_zerop = 0;
if (non_zerop || n / 100 > 0) {
*dst++ = digits[n / 100];
n %= 100;
non_zerop = 1;
}
if (non_zerop || n / 10 > 0) {
*dst++ = digits[n / 10];
n %= 10;
non_zerop = 1;
}
*dst++ = digits[n];
if (i != 3)
*dst++ = '.';
}
*dst++ = '\0';
return orig_dst;
}
/*
* Convert IPv6 binary address into presentation (printable) format.
*/
const char *
addrtostr6 (const void *src, char *dst, size_t size)
{
/*
* Note that int32_t and int16_t need only be "at least" large enough
* to contain a value of the specified size. On some systems, like
* Crays, there is no such thing as an integer variable with 16 bits.
* Keep this in mind if you think this function should have been coded
* to use pointer overlays. All the world's not a VAX.
*/
const u_char *srcaddr = (const u_char *)src;
char *dp;
size_t space_left, added_space;
int snprintfed;
struct {
int base;
int len;
} best, cur;
uint16_t words [IN6ADDRSZ / INT16SZ];
int i;
/* Preprocess:
* Copy the input (bytewise) array into a wordwise array.
* Find the longest run of 0x00's in src[] for :: shorthanding.
*/
for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
words[i] = (srcaddr[2*i] << 8) | srcaddr[2*i + 1];
best.len = 0;
best.base = -1;
cur.len = 0;
cur.base = -1;
- for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
- {
- if (words[i] == 0)
- {
+ for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
+ if (words[i] == 0) {
if (cur.base == -1)
cur.base = i, cur.len = 1;
else cur.len++;
- }
- else if (cur.base != -1)
- {
+ } else if (cur.base != -1) {
if (best.base == -1 || cur.len > best.len)
best = cur;
cur.base = -1;
}
}
if ((cur.base != -1) && (best.base == -1 || cur.len > best.len))
best = cur;
if (best.base != -1 && best.len < 2)
best.base = -1;
/* Format the result.
*/
dp = dst;
space_left = size;
#define APPEND_CHAR(c) \
{ \
if (space_left == 0) { \
errno = ENOSPC; \
return (NULL); \
} \
*dp++ = c; \
space_left--; \
}
- for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
- {
+ for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
/* Are we inside the best run of 0x00's?
*/
- if (best.base != -1 && i >= best.base && i < (best.base + best.len))
- {
+ if (best.base != -1 && i >= best.base && i < (best.base + best.len)) {
if (i == best.base)
APPEND_CHAR(':');
continue;
}
/* Are we following an initial run of 0x00s or any real hex?
*/
if (i != 0)
APPEND_CHAR(':');
/* Is this address an encapsulated IPv4?
*/
if (i == 6 && best.base == 0 &&
(best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
{
- if (!addrtostr(srcaddr+12, dp, space_left))
- {
+ if (!addrtostr(srcaddr+12, dp, space_left)) {
errno = ENOSPC;
return (NULL);
}
added_space = strlen(dp);
dp += added_space;
space_left -= added_space;
break;
}
snprintfed = snprintf (dp, space_left, "%x", words[i]);
if (snprintfed < 0)
return (NULL);
- if ((size_t) snprintfed >= space_left)
- {
+ if ((size_t) snprintfed >= space_left) {
errno = ENOSPC;
return (NULL);
}
dp += snprintfed;
space_left -= snprintfed;
}
/* Was it a trailing run of 0x00's?
*/
if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
APPEND_CHAR(':');
APPEND_CHAR('\0');
return (dst);
}
diff --git a/contrib/tcpdump/af.c b/contrib/tcpdump/af.c
index 1153f102b407..8c3e4da6e831 100644
--- a/contrib/tcpdump/af.c
+++ b/contrib/tcpdump/af.c
@@ -1,58 +1,56 @@
/*
* Copyright (c) 1998-2006 The TCPDUMP project
*
* 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.
*
* Original code by Hannes Gredler (hannes@gredler.at)
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "af.h"
const struct tok af_values[] = {
{ 0, "Reserved"},
{ AFNUM_INET, "IPv4"},
{ AFNUM_INET6, "IPv6"},
{ AFNUM_NSAP, "NSAP"},
{ AFNUM_HDLC, "HDLC"},
{ AFNUM_BBN1822, "BBN 1822"},
{ AFNUM_802, "802"},
{ AFNUM_E163, "E.163"},
{ AFNUM_E164, "E.164"},
{ AFNUM_F69, "F.69"},
{ AFNUM_X121, "X.121"},
{ AFNUM_IPX, "Novell IPX"},
{ AFNUM_ATALK, "Appletalk"},
{ AFNUM_DECNET, "Decnet IV"},
{ AFNUM_BANYAN, "Banyan Vines"},
{ AFNUM_E164NSAP, "E.164 with NSAP subaddress"},
{ AFNUM_L2VPN, "Layer-2 VPN"},
{ AFNUM_VPLS, "VPLS"},
{ 0, NULL},
};
const struct tok bsd_af_values[] = {
{ BSD_AFNUM_INET, "IPv4" },
{ BSD_AFNUM_NS, "NS" },
{ BSD_AFNUM_ISO, "ISO" },
{ BSD_AFNUM_APPLETALK, "Appletalk" },
{ BSD_AFNUM_IPX, "IPX" },
{ BSD_AFNUM_INET6_BSD, "IPv6" },
{ BSD_AFNUM_INET6_FREEBSD, "IPv6" },
{ BSD_AFNUM_INET6_DARWIN, "IPv6" },
{ 0, NULL}
};
diff --git a/contrib/tcpdump/autogen.sh b/contrib/tcpdump/autogen.sh
new file mode 100755
index 000000000000..c84a6b5c5dd2
--- /dev/null
+++ b/contrib/tcpdump/autogen.sh
@@ -0,0 +1,25 @@
+#!/bin/sh -e
+
+: "${AUTORECONF:=autoreconf}"
+
+AUTORECONFVERSION=`$AUTORECONF --version 2>&1 | grep "^autoreconf" | sed 's/.*) *//'`
+
+maj=`echo "$AUTORECONFVERSION" | cut -d. -f1`
+min=`echo "$AUTORECONFVERSION" | cut -d. -f2`
+# The minimum required version of autoconf is currently 2.69.
+if [ "$maj" = "" ] || [ "$min" = "" ] || \
+ [ "$maj" -lt 2 ] || { [ "$maj" -eq 2 ] && [ "$min" -lt 69 ]; }; then
+ cat >&2 <<-EOF
+ Please install the 'autoconf' package version 2.69 or later.
+ If version 2.69 or later is already installed and there is no
+ autoconf default, it may be necessary to set the AUTORECONF
+ environment variable to enable the one to use, like:
+ AUTORECONF=autoreconf-2.69 ./autogen.sh
+ or
+ AUTORECONF=autoreconf-2.71 ./autogen.sh
+ EOF
+ exit 1
+fi
+
+echo "$AUTORECONF identification: $AUTORECONFVERSION"
+"$AUTORECONF" -f
diff --git a/contrib/tcpdump/bpf_dump.c b/contrib/tcpdump/bpf_dump.c
index 1ac74a24127c..da50c3e2dd1c 100644
--- a/contrib/tcpdump/bpf_dump.c
+++ b/contrib/tcpdump/bpf_dump.c
@@ -1,62 +1,60 @@
/*
* Copyright (c) 1992, 1993, 1994, 1995, 1996
* 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.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <stdio.h>
#include "netdissect.h"
#include "interface.h"
void
bpf_dump(const struct bpf_program *p, int option)
{
struct bpf_insn *insn;
int i;
int n = p->bf_len;
insn = p->bf_insns;
if (option > 2) {
printf("%d\n", n);
for (i = 0; i < n; ++insn, ++i) {
printf("%u %u %u %u\n", insn->code,
insn->jt, insn->jf, insn->k);
}
return ;
}
if (option > 1) {
for (i = 0; i < n; ++insn, ++i)
printf("{ 0x%x, %d, %d, 0x%08x },\n",
insn->code, insn->jt, insn->jf, insn->k);
return;
}
for (i = 0; i < n; ++insn, ++i) {
#ifdef BDEBUG
extern int bids[];
printf(bids[i] > 0 ? "[%02d]" : " -- ", bids[i] - 1);
#endif
puts(bpf_image(insn, i));
}
}
diff --git a/contrib/tcpdump/checksum.c b/contrib/tcpdump/checksum.c
index e6e84a2510db..4bb97f1e33f4 100644
--- a/contrib/tcpdump/checksum.c
+++ b/contrib/tcpdump/checksum.c
@@ -1,189 +1,154 @@
/*
* Copyright (c) 1998-2006 The TCPDUMP project
*
* 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.
*
* miscellaneous checksumming routines
*
* Original code by Hannes Gredler (hannes@gredler.at)
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <assert.h>
#include "netdissect.h"
/*
* CRC-10 table generated using the following Python snippet:
import sys
crc_table = []
for i in range(256):
accum = i << 2
for j in range(8):
accum <<= 1
if accum & 0x400:
accum ^= 0x633
crc_table.append(accum)
-for i in range(len(crc_table)/8):
+for i in range(int(len(crc_table)/8)):
for j in range(8):
sys.stdout.write("0x%04x, " % crc_table[i*8+j])
sys.stdout.write("\n")
*/
static const uint16_t crc10_table[256] =
{
0x0000, 0x0233, 0x0255, 0x0066, 0x0299, 0x00aa, 0x00cc, 0x02ff,
0x0301, 0x0132, 0x0154, 0x0367, 0x0198, 0x03ab, 0x03cd, 0x01fe,
0x0031, 0x0202, 0x0264, 0x0057, 0x02a8, 0x009b, 0x00fd, 0x02ce,
0x0330, 0x0103, 0x0165, 0x0356, 0x01a9, 0x039a, 0x03fc, 0x01cf,
0x0062, 0x0251, 0x0237, 0x0004, 0x02fb, 0x00c8, 0x00ae, 0x029d,
0x0363, 0x0150, 0x0136, 0x0305, 0x01fa, 0x03c9, 0x03af, 0x019c,
0x0053, 0x0260, 0x0206, 0x0035, 0x02ca, 0x00f9, 0x009f, 0x02ac,
0x0352, 0x0161, 0x0107, 0x0334, 0x01cb, 0x03f8, 0x039e, 0x01ad,
0x00c4, 0x02f7, 0x0291, 0x00a2, 0x025d, 0x006e, 0x0008, 0x023b,
0x03c5, 0x01f6, 0x0190, 0x03a3, 0x015c, 0x036f, 0x0309, 0x013a,
0x00f5, 0x02c6, 0x02a0, 0x0093, 0x026c, 0x005f, 0x0039, 0x020a,
0x03f4, 0x01c7, 0x01a1, 0x0392, 0x016d, 0x035e, 0x0338, 0x010b,
0x00a6, 0x0295, 0x02f3, 0x00c0, 0x023f, 0x000c, 0x006a, 0x0259,
0x03a7, 0x0194, 0x01f2, 0x03c1, 0x013e, 0x030d, 0x036b, 0x0158,
0x0097, 0x02a4, 0x02c2, 0x00f1, 0x020e, 0x003d, 0x005b, 0x0268,
0x0396, 0x01a5, 0x01c3, 0x03f0, 0x010f, 0x033c, 0x035a, 0x0169,
0x0188, 0x03bb, 0x03dd, 0x01ee, 0x0311, 0x0122, 0x0144, 0x0377,
0x0289, 0x00ba, 0x00dc, 0x02ef, 0x0010, 0x0223, 0x0245, 0x0076,
0x01b9, 0x038a, 0x03ec, 0x01df, 0x0320, 0x0113, 0x0175, 0x0346,
0x02b8, 0x008b, 0x00ed, 0x02de, 0x0021, 0x0212, 0x0274, 0x0047,
0x01ea, 0x03d9, 0x03bf, 0x018c, 0x0373, 0x0140, 0x0126, 0x0315,
0x02eb, 0x00d8, 0x00be, 0x028d, 0x0072, 0x0241, 0x0227, 0x0014,
0x01db, 0x03e8, 0x038e, 0x01bd, 0x0342, 0x0171, 0x0117, 0x0324,
0x02da, 0x00e9, 0x008f, 0x02bc, 0x0043, 0x0270, 0x0216, 0x0025,
0x014c, 0x037f, 0x0319, 0x012a, 0x03d5, 0x01e6, 0x0180, 0x03b3,
0x024d, 0x007e, 0x0018, 0x022b, 0x00d4, 0x02e7, 0x0281, 0x00b2,
0x017d, 0x034e, 0x0328, 0x011b, 0x03e4, 0x01d7, 0x01b1, 0x0382,
0x027c, 0x004f, 0x0029, 0x021a, 0x00e5, 0x02d6, 0x02b0, 0x0083,
0x012e, 0x031d, 0x037b, 0x0148, 0x03b7, 0x0184, 0x01e2, 0x03d1,
0x022f, 0x001c, 0x007a, 0x0249, 0x00b6, 0x0285, 0x02e3, 0x00d0,
0x011f, 0x032c, 0x034a, 0x0179, 0x0386, 0x01b5, 0x01d3, 0x03e0,
0x021e, 0x002d, 0x004b, 0x0278, 0x0087, 0x02b4, 0x02d2, 0x00e1
};
-static void
-init_crc10_table(void)
-{
-#define CRC10_POLYNOMIAL 0x633
- int i, j;
- uint16_t accum;
- uint16_t verify_crc10_table[256];
-
- for ( i = 0; i < 256; i++ )
- {
- accum = ((unsigned short) i << 2);
- for ( j = 0; j < 8; j++ )
- {
- if ((accum <<= 1) & 0x400) accum ^= CRC10_POLYNOMIAL;
- }
- verify_crc10_table[i] = accum;
- }
- assert(memcmp(verify_crc10_table,
- crc10_table,
- sizeof(verify_crc10_table)) == 0);
-#undef CRC10_POLYNOMIAL
-}
-
uint16_t
verify_crc10_cksum(uint16_t accum, const u_char *p, int length)
{
int i;
- for ( i = 0; i < length; i++ )
- {
+ for ( i = 0; i < length; i++ ) {
accum = ((accum << 8) & 0x3ff)
^ crc10_table[( accum >> 2) & 0xff]
^ *p++;
}
return accum;
}
-/* precompute checksum tables */
-void
-init_checksum(void) {
-
- init_crc10_table();
-
-}
-
/*
* Creates the OSI Fletcher checksum. See 8473-1, Appendix C, section C.3.
* The checksum field of the passed PDU does not need to be reset to zero.
*/
uint16_t
create_osi_cksum (const uint8_t *pptr, int checksum_offset, int length)
{
int x;
int y;
uint32_t mul;
uint32_t c0;
uint32_t c1;
uint16_t checksum;
int idx;
c0 = 0;
c1 = 0;
for (idx = 0; idx < length; idx++) {
/*
* Ignore the contents of the checksum field.
*/
if (idx == checksum_offset ||
idx == checksum_offset+1) {
c1 += c0;
pptr++;
} else {
c0 = c0 + *(pptr++);
c1 += c0;
}
}
c0 = c0 % 255;
c1 = c1 % 255;
mul = (length - checksum_offset)*(c0);
x = mul - c0 - c1;
y = c1 - mul - 1;
if ( y >= 0 ) y++;
if ( x < 0 ) x--;
x %= 255;
y %= 255;
if (x == 0) x = 255;
if (y == 0) y = 255;
y &= 0x00FF;
checksum = ((x << 8) | y);
return checksum;
}
diff --git a/contrib/tcpdump/cmake/Modules/FindCRYPTO.cmake b/contrib/tcpdump/cmake/Modules/FindCRYPTO.cmake
index 453c6516e071..25846f3ca093 100644
--- a/contrib/tcpdump/cmake/Modules/FindCRYPTO.cmake
+++ b/contrib/tcpdump/cmake/Modules/FindCRYPTO.cmake
@@ -1,24 +1,187 @@
#
# Try to find libcrypto.
#
-# Try to find the header
-find_path(CRYPTO_INCLUDE_DIR openssl/crypto.h)
+#
+# Were we told where to look for libcrypto?
+#
+if(NOT CRYPTO_ROOT)
+ #
+ # No.
+ #
+ # First, try looking for it with pkg-config, if we have it.
+ #
+ find_package(PkgConfig)
+
+ #
+ # Homebrew's pkg-config does not, by default, look for
+ # pkg-config files for packages it has installed.
+ # Furthermore, at least for OpenSSL, they appear to be
+ # dumped in package-specific directories whose paths are
+ # not only package-specific but package-version-specific.
+ #
+ # So the only way to find openssl is to get the value of
+ # PKG_CONFIG_PATH from "brew --env openssl" and add that
+ # to PKG_CONFIG_PATH. (No, we can't just assume it's under
+ # /usr/local; Homebrew have conveniently chosen to put it
+ # under /opt/homebrew on ARM.)
+ #
+ # That's the nice thing about Homebrew - it makes things easier!
+ # Thanks!
+ #
+ find_program(BREW brew)
+ if(BREW)
+ #
+ # We have Homebrew.
+ # Get the pkg-config directory for openssl.
+ #
+ execute_process(COMMAND "${BREW}" "--env" "--plain" "openssl"
+ RESULT_VARIABLE BREW_RESULT
+ OUTPUT_VARIABLE BREW_OUTPUT
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+ if(BREW_RESULT EQUAL 0)
+ #
+ # brew --env --plain openssl succeeded.
+ # Split its output into a list, one entry per line.
+ #
+ string(REGEX MATCHALL "[^\n\r]+" BREW_OUTPUT_LINES "${BREW_OUTPUT}")
+
+ #
+ # Find the line that begins with "PKG_CONFIG_PATH: ", and extract
+ # the path following that.
+ #
+ foreach(LINE IN LISTS BREW_OUTPUT_LINES)
+ if(LINE MATCHES "PKG_CONFIG_PATH: \(.*\)")
+ string(REGEX REPLACE "PKG_CONFIG_PATH: \(.*\)"
+ "\\1" OPENSSL_PKGCONFIG_DIR
+ ${LINE})
+ endif()
+ endforeach()
+ endif()
+ endif()
+
+ #
+ # Save the current value of the PKG_CONFIG_PATH environment
+ # variable.
+ #
+ set(SAVE_PKG_CONFIG_PATH $ENV{PKG_CONFIG_PATH})
+
+ #
+ # If we got an additional pkg-config directory from Homebrew, add
+ # it to the PKG_CONFIG_PATH environment variable.
+ #
+ if(OPENSSL_PKGCONFIG_DIR)
+ set(ENV{PKG_CONFIG_PATH} "${OPENSSL_PKGCONFIG_DIR}:$ENV{PKG_CONFIG_PATH}")
+ endif()
+
+ #
+ # Use pkg-config to find libcrypto.
+ #
+ pkg_check_modules(CRYPTO libcrypto)
-# Try to find the library
-find_library(CRYPTO_LIBRARY crypto)
+ #
+ # Revert the change to PKG_CONFIG_PATH.
+ #
+ set(ENV{PKG_CONFIG_PATH} "${SAVE_PKG_CONFIG_PATH}")
+
+ #
+ # Did pkg-config find it?
+ #
+ if(CRYPTO_FOUND)
+ #
+ # This "helpfully" supplies CRYPTO_LIBRARIES as a bunch of
+ # library names - not paths - and CRYPTO_LIBRARY_DIRS as
+ # a bunch of directories.
+ #
+ # CMake *really* doesn't like the notion of specifying "here are
+ # the directories in which to look for libraries" except in
+ # find_library() calls; it *really* prefers using full paths to
+ # library files, rather than library names.
+ #
+ # Find the libraries and add their full paths.
+ #
+ set(CRYPTO_LIBRARY_FULLPATHS)
+ foreach(_lib IN LISTS CRYPTO_LIBRARIES)
+ #
+ # Try to find this library, so we get its full path.
+ #
+ find_library(_libfullpath ${_lib} HINTS ${CRYPTO_LIBRARY_DIRS})
+ list(APPEND CRYPTO_LIBRARY_FULLPATHS ${_libfullpath})
+ endforeach()
+ set(CRYPTO_LIBRARIES "${CRYPTO_LIBRARY_FULLPATHS}")
+ else()
+ #
+ # No. If we have Homebrew installed, see if it's in Homebrew.
+ #
+ if(BREW)
+ #
+ # The brew man page lies when it speaks of
+ # $BREW --prefix --installed <formula>
+ # outputting nothing. In Homebrew 3.3.16,
+ # it produces output regardless of whether
+ # the formula is installed or not, so we
+ # send the standard output and error to
+ # the bit bucket.
+ #
+ # libcrypto isn't a formula, openssl is a formula.
+ #
+ execute_process(COMMAND "${BREW}" "--prefix" "--installed" "openssl"
+ RESULT_VARIABLE BREW_RESULT
+ OUTPUT_QUIET
+ )
+ if(BREW_RESULT EQUAL 0)
+ #
+ # Yes. Get the include directory and library
+ # directory. (No, we can't just assume it's
+ # under /usr/local; Homebrew have conveniently
+ # chosen to put it under /opt/homebrew on ARM.)
+ #
+ execute_process(COMMAND "${BREW}" "--prefix" "openssl"
+ RESULT_VARIABLE BREW_RESULT
+ OUTPUT_VARIABLE OPENSSL_PATH
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+ set(CRYPTO_INCLUDE_DIRS "${OPENSSL_PATH}/include")
+
+ #
+ # Search for the libcrypto library under lib.
+ #
+ find_library(CRYPTO_LIBRARIES crypto
+ PATHS "${OPENSSL_PATH}/lib"
+ NO_DEFAULT_PATH)
+ endif()
+ endif()
+ endif()
+endif()
+
+#
+# Have we found it with pkg-config or Homebrew?
+#
+if(NOT CRYPTO_INCLUDE_DIRS)
+ #
+ # No.
+ # Try to find the openss/evp.h header.
+ # We search for that header to make sure that it's installed (if
+ # it's just a shared library for the benefit of existing
+ # programs, that's not useful).
+ #
+ find_path(CRYPTO_INCLUDE_DIRS openssl/evp.h)
+
+ #
+ # Try to find the library.
+ #
+ find_library(CRYPTO_LIBRARIES crypto)
+endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(CRYPTO
DEFAULT_MSG
- CRYPTO_INCLUDE_DIR
- CRYPTO_LIBRARY
+ CRYPTO_INCLUDE_DIRS
+ CRYPTO_LIBRARIES
)
mark_as_advanced(
- CRYPTO_INCLUDE_DIR
- CRYPTO_LIBRARY
+ CRYPTO_INCLUDE_DIRS
+ CRYPTO_LIBRARIES
)
-
-set(CRYPTO_INCLUDE_DIRS ${CRYPTO_INCLUDE_DIR})
-set(CRYPTO_LIBRARIES ${CRYPTO_LIBRARY})
diff --git a/contrib/tcpdump/cmakeconfig.h.in b/contrib/tcpdump/cmakeconfig.h.in
index 02a4a352e42a..0bd1e96e165a 100644
--- a/contrib/tcpdump/cmakeconfig.h.in
+++ b/contrib/tcpdump/cmakeconfig.h.in
@@ -1,290 +1,290 @@
/* cmakeconfig.h.in */
/* Define to 1 if arpa/inet.h declares `ether_ntohost' */
#cmakedefine ARPA_INET_H_DECLARES_ETHER_NTOHOST 1
/* define if you want to build the possibly-buggy SMB printer */
#cmakedefine ENABLE_SMB 1
/* Define to 1 if you have the `bpf_dump' function. */
#cmakedefine HAVE_BPF_DUMP 1
/* capsicum support available */
#cmakedefine HAVE_CAPSICUM 1
/* Define to 1 if you have the `cap_enter' function. */
#cmakedefine HAVE_CAP_ENTER 1
/* Define to 1 if you have the `cap_ioctls_limit' function. */
#cmakedefine HAVE_CAP_IOCTLS_LIMIT 1
/* Define to 1 if you have the <cap-ng.h> header file. */
#cmakedefine HAVE_CAP_NG_H 1
/* Define to 1 if you have the `cap_rights_limit' function. */
#cmakedefine HAVE_CAP_RIGHTS_LIMIT 1
/* Casper support available */
#cmakedefine HAVE_CASPER 1
/* Define to 1 if you have the declaration of `ether_ntohost' */
#cmakedefine HAVE_DECL_ETHER_NTOHOST 1
/* Define to 1 if you have the `ether_ntohost' function. */
#cmakedefine HAVE_ETHER_NTOHOST 1
/* Define to 1 if you have the `EVP_CIPHER_CTX_new' function. */
#cmakedefine HAVE_EVP_CIPHER_CTX_NEW 1
/* Define to 1 if you have the `EVP_DecryptInit_ex' function. */
#cmakedefine HAVE_EVP_DECRYPTINIT_EX 1
-/* Define to 1 if you have the <fcntl.h> header file. */
-#cmakedefine HAVE_FCNTL_H 1
-
/* Define to 1 if you have the `fork' function. */
#cmakedefine HAVE_FORK 1
/* Define to 1 if you have the `getopt_long' function. */
#cmakedefine HAVE_GETOPT_LONG 1
/* define if you have getrpcbynumber() */
#cmakedefine HAVE_GETRPCBYNUMBER 1
/* Define to 1 if you have the `getservent' function. */
#cmakedefine HAVE_GETSERVENT 1
/* Define to 1 if you have the <inttypes.h> header file. */
#cmakedefine HAVE_INTTYPES_H 1
/* Define to 1 if you have the `cap-ng' library (-lcap-ng). */
#cmakedefine HAVE_LIBCAP_NG 1
-/* Define to 1 if you have the `crypto' library (-lcrypto). */
+/* Define to 1 if you have a usable `crypto' library (-lcrypto). */
#cmakedefine HAVE_LIBCRYPTO 1
/* Define to 1 if you have the `rpc' library (-lrpc). */
#cmakedefine HAVE_LIBRPC 1
/* Define to 1 if you have the <memory.h> header file. */
#cmakedefine HAVE_MEMORY_H 1
/* Define to 1 if you have the <net/if.h> header file. */
#cmakedefine HAVE_NET_IF_H 1
/* Define to 1 if you have the `openat' function. */
#cmakedefine HAVE_OPENAT 1
-/* Define to 1 if you have the <openssl/evp.h> header file. */
-#cmakedefine HAVE_OPENSSL_EVP_H 1
-
/* define if the OS provides AF_INET6 and struct in6_addr */
#cmakedefine HAVE_OS_IPV6_SUPPORT 1
/* if there's an os_proto.h for this platform, to use additional prototypes */
#cmakedefine HAVE_OS_PROTO_H 1
/* Define to 1 if you have the `pcap_breakloop' function. */
#cmakedefine HAVE_PCAP_BREAKLOOP 1
/* Define to 1 if you have the `pcap_create' function. */
#cmakedefine HAVE_PCAP_CREATE 1
/* define if libpcap has pcap_datalink_name_to_val() */
#cmakedefine HAVE_PCAP_DATALINK_NAME_TO_VAL 1
/* define if libpcap has pcap_datalink_val_to_description() */
#cmakedefine HAVE_PCAP_DATALINK_VAL_TO_DESCRIPTION 1
/* define if libpcap has pcap_debug */
#cmakedefine HAVE_PCAP_DEBUG 1
/* Define to 1 if you have the `pcap_dump_flush' function. */
#cmakedefine HAVE_PCAP_DUMP_FLUSH 1
/* Define to 1 if you have the `pcap_dump_ftell' function. */
#cmakedefine HAVE_PCAP_DUMP_FTELL 1
/* Define to 1 if you have the `pcap_dump_ftell64' function. */
#cmakedefine HAVE_PCAP_DUMP_FTELL64 1
/* Define to 1 if you have the `pcap_findalldevs' function. */
#cmakedefine HAVE_PCAP_FINDALLDEVS 1
/* Define to 1 if you have the `pcap_findalldevs_ex' function. */
#cmakedefine HAVE_PCAP_FINDALLDEVS_EX 1
/* Define to 1 if you have the `pcap_free_datalinks' function. */
#cmakedefine HAVE_PCAP_FREE_DATALINKS 1
/* Define to 1 if the system has the type `pcap_if_t'. */
#cmakedefine HAVE_PCAP_IF_T 1
/* Define to 1 if you have the `pcap_lib_version' function. */
#cmakedefine HAVE_PCAP_LIB_VERSION 1
/* define if libpcap has pcap_list_datalinks() */
#cmakedefine HAVE_PCAP_LIST_DATALINKS 1
/* Define to 1 if you have the `pcap_open' function. */
#cmakedefine HAVE_PCAP_OPEN 1
/* Define to 1 if you have the <pcap/pcap-inttypes.h> header file. */
#cmakedefine HAVE_PCAP_PCAP_INTTYPES_H 1
/* Define to 1 if you have the `pcap_setdirection' function. */
#cmakedefine HAVE_PCAP_SETDIRECTION 1
/* Define to 1 if you have the `pcap_set_datalink' function. */
#cmakedefine HAVE_PCAP_SET_DATALINK 1
/* Define to 1 if you have the `pcap_set_immediate_mode' function. */
#cmakedefine HAVE_PCAP_SET_IMMEDIATE_MODE 1
/* Define to 1 if you have the `pcap_set_optimizer_debug' function. */
#cmakedefine HAVE_PCAP_SET_OPTIMIZER_DEBUG 1
/* Define to 1 if you have the `pcap_set_parser_debug' function. */
#cmakedefine HAVE_PCAP_SET_PARSER_DEBUG 1
/* Define to 1 if you have the `pcap_set_tstamp_precision' function. */
#cmakedefine HAVE_PCAP_SET_TSTAMP_PRECISION 1
/* Define to 1 if you have the `pcap_set_tstamp_type' function. */
#cmakedefine HAVE_PCAP_SET_TSTAMP_TYPE 1
/* define if libpcap has pcap_version */
#cmakedefine HAVE_PCAP_VERSION 1
/* Define to 1 if you have the `pcap_wsockinit' function. */
#cmakedefine HAVE_PCAP_WSOCKINIT 1
/* Define to 1 if you have the `pfopen' function. */
#cmakedefine HAVE_PFOPEN 1
/* Define to 1 if you have the <rpc/rpcent.h> header file. */
#cmakedefine HAVE_RPC_RPCENT_H 1
/* Define to 1 if you have the <rpc/rpc.h> header file. */
#cmakedefine HAVE_RPC_RPC_H 1
/* Define to 1 if you have the `setlinebuf' function. */
#cmakedefine HAVE_SETLINEBUF 1
/* Define to 1 if you have the <stdint.h> header file. */
#cmakedefine HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#cmakedefine HAVE_STDLIB_H 1
/* Define to 1 if you have the `strdup' function. */
#cmakedefine HAVE_STRDUP 1
/* Define to 1 if you have the <strings.h> header file. */
#cmakedefine HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#cmakedefine HAVE_STRING_H 1
/* Define to 1 if you have the `strlcat' function. */
#cmakedefine HAVE_STRLCAT 1
/* Define to 1 if you have the `strlcpy' function. */
#cmakedefine HAVE_STRLCPY 1
/* Define to 1 if you have the `strsep' function. */
#cmakedefine HAVE_STRSEP 1
/* Define to 1 if the system has the type `struct ether_addr'. */
#cmakedefine HAVE_STRUCT_ETHER_ADDR 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#cmakedefine HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#cmakedefine HAVE_SYS_TYPES_H 1
/* Define to 1 if the system has the type `uintptr_t'. */
#cmakedefine HAVE_UINTPTR_T 1
/* Define to 1 if you have the <unistd.h> header file. */
#cmakedefine HAVE_UNISTD_H 1
/* Define to 1 if you have the `vfork' function. */
#cmakedefine HAVE_VFORK 1
/* Define to 1 if you have the `wsockinit' function. */
#cmakedefine HAVE_WSOCKINIT 1
/* define if libpcap has yydebug */
#cmakedefine HAVE_YYDEBUG 1
/* Define to 1 if netinet/ether.h declares `ether_ntohost' */
#cmakedefine NETINET_ETHER_H_DECLARES_ETHER_NTOHOST 1
/* Define to 1 if netinet/if_ether.h declares `ether_ntohost' */
#cmakedefine NETINET_IF_ETHER_H_DECLARES_ETHER_NTOHOST 1
/* Define to 1 if net/ethernet.h declares `ether_ntohost' */
#cmakedefine NET_ETHERNET_H_DECLARES_ETHER_NTOHOST 1
/* Define to the address where bug reports for this package should be sent. */
#cmakedefine PACKAGE_BUGREPORT ""
/* Define to the full name of this package. */
#cmakedefine PACKAGE_NAME "@PACKAGE_NAME@"
/* Define to the full name and version of this package. */
#cmakedefine PACKAGE_STRING "@PACKAGE_STRING@"
/* Define to the one symbol short name of this package. */
#cmakedefine PACKAGE_TARNAME ""
/* Define to the home page for this package. */
#cmakedefine PACKAGE_URL ""
/* Define to the version of this package. */
#cmakedefine PACKAGE_VERSION "@PACKAGE_VERSION@"
+/* The size of `time_t', as computed by sizeof. */
+#cmakedefine SIZEOF_TIME_T @SIZEOF_TIME_T@
+
+/* The size of `void *', as computed by sizeof. */
+#cmakedefine SIZEOF_VOID_P @SIZEOF_VOID_P@
+
/* Define to 1 if you have the ANSI C header files. */
#cmakedefine STDC_HEADERS 1
/* Define to 1 if sys/ethernet.h declares `ether_ntohost' */
#cmakedefine SYS_ETHERNET_H_DECLARES_ETHER_NTOHOST 1
/* define if you have ether_ntohost() and it works */
#cmakedefine USE_ETHER_NTOHOST 1
/* Define if you enable support for libsmi */
#cmakedefine USE_LIBSMI 1
/* define if should chroot when dropping privileges */
#cmakedefine WITH_CHROOT "@WITH_CHROOT@"
/* define if should drop privileges by default */
#cmakedefine WITH_USER "@WITH_USER@"
/* define on AIX to get certain functions */
#cmakedefine _SUN 1
/* to handle Ultrix compilers that don't support const in prototypes */
#cmakedefine const 1
/* Define as token for inline if inlining supported */
#cmakedefine inline 1
/* Define to `uint16_t' if u_int16_t not defined. */
#cmakedefine u_int16_t 1
/* Define to `uint32_t' if u_int32_t not defined. */
#cmakedefine u_int32_t 1
/* Define to `uint64_t' if u_int64_t not defined. */
#cmakedefine u_int64_t 1
/* Define to `uint8_t' if u_int8_t not defined. */
#cmakedefine u_int8_t 1
/* 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. */
#cmakedefine uintptr_t 1
diff --git a/contrib/tcpdump/config.guess b/contrib/tcpdump/config.guess
index 69188da73d74..f6d217a49f8f 100755
--- a/contrib/tcpdump/config.guess
+++ b/contrib/tcpdump/config.guess
@@ -1,1774 +1,1812 @@
#! /bin/sh
# Attempt to guess a canonical system name.
-# Copyright 1992-2023 Free Software Foundation, Inc.
+# Copyright 1992-2024 Free Software Foundation, Inc.
# shellcheck disable=SC2006,SC2268 # see below for rationale
-timestamp='2023-01-01'
+timestamp='2024-01-01'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <https://www.gnu.org/licenses/>.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that
# program. This Exception is an additional permission under section 7
# of the GNU General Public License, version 3 ("GPLv3").
#
# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
#
# You can get the latest version of this script from:
# https://git.savannah.gnu.org/cgit/config.git/plain/config.guess
#
# Please send patches to <config-patches@gnu.org>.
# The "shellcheck disable" line above the timestamp inhibits complaints
# about features and limitations of the classic Bourne shell that were
# superseded or lifted in POSIX. However, this script identifies a wide
# variety of pre-POSIX systems that do not have POSIX shells at all, and
# even some reasonably current systems (Solaris 10 as case-in-point) still
# have a pre-POSIX /bin/sh.
me=`echo "$0" | sed -e 's,.*/,,'`
usage="\
Usage: $0 [OPTION]
-Output the configuration name of the system \`$me' is run on.
+Output the configuration name of the system '$me' is run on.
Options:
-h, --help print this help, then exit
-t, --time-stamp print date of last modification, then exit
-v, --version print version number, then exit
Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.guess ($timestamp)
Originally written by Per Bothner.
-Copyright 1992-2023 Free Software Foundation, Inc.
+Copyright 1992-2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
help="
-Try \`$me --help' for more information."
+Try '$me --help' for more information."
# Parse command line
while test $# -gt 0 ; do
case $1 in
--time-stamp | --time* | -t )
echo "$timestamp" ; exit ;;
--version | -v )
echo "$version" ; exit ;;
--help | --h* | -h )
echo "$usage"; exit ;;
-- ) # Stop option processing
shift; break ;;
- ) # Use stdin as input.
break ;;
-* )
echo "$me: invalid option $1$help" >&2
exit 1 ;;
* )
break ;;
esac
done
if test $# != 0; then
echo "$me: too many arguments$help" >&2
exit 1
fi
# Just in case it came from the environment.
GUESS=
# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
# compiler to aid in system detection is discouraged as it requires
# temporary files to be created and, as you can see below, it is a
# headache to deal with in a portable fashion.
-# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
-# use `HOST_CC' if defined, but it is deprecated.
+# Historically, 'CC_FOR_BUILD' used to be named 'HOST_CC'. We still
+# use 'HOST_CC' if defined, but it is deprecated.
# Portable tmp directory creation inspired by the Autoconf team.
tmp=
# shellcheck disable=SC2172
trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15
set_cc_for_build() {
# prevent multiple calls if $tmp is already set
test "$tmp" && return 0
: "${TMPDIR=/tmp}"
# shellcheck disable=SC2039,SC3028
{ tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
{ test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } ||
{ tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } ||
{ echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; }
dummy=$tmp/dummy
case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in
,,) echo "int x;" > "$dummy.c"
for driver in cc gcc c89 c99 ; do
if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then
CC_FOR_BUILD=$driver
break
fi
done
if test x"$CC_FOR_BUILD" = x ; then
CC_FOR_BUILD=no_compiler_found
fi
;;
,,*) CC_FOR_BUILD=$CC ;;
,*,*) CC_FOR_BUILD=$HOST_CC ;;
esac
}
# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
# (ghazi@noc.rutgers.edu 1994-08-24)
if test -f /.attbin/uname ; then
PATH=$PATH:/.attbin ; export PATH
fi
UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
case $UNAME_SYSTEM in
Linux|GNU|GNU/*)
LIBC=unknown
set_cc_for_build
cat <<-EOF > "$dummy.c"
+ #if defined(__ANDROID__)
+ LIBC=android
+ #else
#include <features.h>
#if defined(__UCLIBC__)
LIBC=uclibc
#elif defined(__dietlibc__)
LIBC=dietlibc
#elif defined(__GLIBC__)
LIBC=gnu
+ #elif defined(__LLVM_LIBC__)
+ LIBC=llvm
#else
#include <stdarg.h>
/* First heuristic to detect musl libc. */
#ifdef __DEFINED_va_list
LIBC=musl
#endif
#endif
+ #endif
EOF
cc_set_libc=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
eval "$cc_set_libc"
# Second heuristic to detect musl libc.
if [ "$LIBC" = unknown ] &&
command -v ldd >/dev/null &&
ldd --version 2>&1 | grep -q ^musl; then
LIBC=musl
fi
# If the system lacks a compiler, then just pick glibc.
# We could probably try harder.
if [ "$LIBC" = unknown ]; then
LIBC=gnu
fi
;;
esac
# Note: order is significant - the case branches are not exclusive.
case $UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION in
*:NetBSD:*:*)
# NetBSD (nbsd) targets should (where applicable) match one or
# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
# *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
# switched to ELF, *-*-netbsd* would select the old
# object file format. This provides both forward
# compatibility and a consistent mechanism for selecting the
# object file format.
#
# Note: NetBSD doesn't particularly care about the vendor
# portion of the name. We always set it to "unknown".
UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
/sbin/sysctl -n hw.machine_arch 2>/dev/null || \
/usr/sbin/sysctl -n hw.machine_arch 2>/dev/null || \
echo unknown)`
case $UNAME_MACHINE_ARCH in
aarch64eb) machine=aarch64_be-unknown ;;
armeb) machine=armeb-unknown ;;
arm*) machine=arm-unknown ;;
sh3el) machine=shl-unknown ;;
sh3eb) machine=sh-unknown ;;
sh5el) machine=sh5le-unknown ;;
earmv*)
arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'`
machine=${arch}${endian}-unknown
;;
*) machine=$UNAME_MACHINE_ARCH-unknown ;;
esac
# The Operating System including object format, if it has switched
# to ELF recently (or will in the future) and ABI.
case $UNAME_MACHINE_ARCH in
earm*)
os=netbsdelf
;;
arm*|i386|m68k|ns32k|sh3*|sparc|vax)
set_cc_for_build
if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ELF__
then
# Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
# Return netbsd for either. FIX?
os=netbsd
else
os=netbsdelf
fi
;;
*)
os=netbsd
;;
esac
# Determine ABI tags.
case $UNAME_MACHINE_ARCH in
earm*)
expr='s/^earmv[0-9]/-eabi/;s/eb$//'
abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"`
;;
esac
# The OS release
# Debian GNU/NetBSD machines have a different userland, and
# thus, need a distinct triplet. However, they do not need
# kernel version information, so it can be replaced with a
# suitable tag, in the style of linux-gnu.
case $UNAME_VERSION in
Debian*)
release='-gnu'
;;
*)
release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2`
;;
esac
# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
# contains redundant information, the shorter form:
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
GUESS=$machine-${os}${release}${abi-}
;;
*:Bitrig:*:*)
UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
GUESS=$UNAME_MACHINE_ARCH-unknown-bitrig$UNAME_RELEASE
;;
*:OpenBSD:*:*)
UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
GUESS=$UNAME_MACHINE_ARCH-unknown-openbsd$UNAME_RELEASE
;;
*:SecBSD:*:*)
UNAME_MACHINE_ARCH=`arch | sed 's/SecBSD.//'`
GUESS=$UNAME_MACHINE_ARCH-unknown-secbsd$UNAME_RELEASE
;;
*:LibertyBSD:*:*)
UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
GUESS=$UNAME_MACHINE_ARCH-unknown-libertybsd$UNAME_RELEASE
;;
*:MidnightBSD:*:*)
GUESS=$UNAME_MACHINE-unknown-midnightbsd$UNAME_RELEASE
;;
*:ekkoBSD:*:*)
GUESS=$UNAME_MACHINE-unknown-ekkobsd$UNAME_RELEASE
;;
*:SolidBSD:*:*)
GUESS=$UNAME_MACHINE-unknown-solidbsd$UNAME_RELEASE
;;
*:OS108:*:*)
GUESS=$UNAME_MACHINE-unknown-os108_$UNAME_RELEASE
;;
macppc:MirBSD:*:*)
GUESS=powerpc-unknown-mirbsd$UNAME_RELEASE
;;
*:MirBSD:*:*)
GUESS=$UNAME_MACHINE-unknown-mirbsd$UNAME_RELEASE
;;
*:Sortix:*:*)
GUESS=$UNAME_MACHINE-unknown-sortix
;;
*:Twizzler:*:*)
GUESS=$UNAME_MACHINE-unknown-twizzler
;;
*:Redox:*:*)
GUESS=$UNAME_MACHINE-unknown-redox
;;
mips:OSF1:*.*)
GUESS=mips-dec-osf1
;;
alpha:OSF1:*:*)
# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
trap '' 0
case $UNAME_RELEASE in
*4.0)
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
;;
*5.*)
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
;;
esac
# According to Compaq, /usr/sbin/psrinfo has been available on
# OSF/1 and Tru64 systems produced since 1995. I hope that
# covers most systems running today. This code pipes the CPU
# types through head -n 1, so we only detect the type of CPU 0.
ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
case $ALPHA_CPU_TYPE in
"EV4 (21064)")
UNAME_MACHINE=alpha ;;
"EV4.5 (21064)")
UNAME_MACHINE=alpha ;;
"LCA4 (21066/21068)")
UNAME_MACHINE=alpha ;;
"EV5 (21164)")
UNAME_MACHINE=alphaev5 ;;
"EV5.6 (21164A)")
UNAME_MACHINE=alphaev56 ;;
"EV5.6 (21164PC)")
UNAME_MACHINE=alphapca56 ;;
"EV5.7 (21164PC)")
UNAME_MACHINE=alphapca57 ;;
"EV6 (21264)")
UNAME_MACHINE=alphaev6 ;;
"EV6.7 (21264A)")
UNAME_MACHINE=alphaev67 ;;
"EV6.8CB (21264C)")
UNAME_MACHINE=alphaev68 ;;
"EV6.8AL (21264B)")
UNAME_MACHINE=alphaev68 ;;
"EV6.8CX (21264D)")
UNAME_MACHINE=alphaev68 ;;
"EV6.9A (21264/EV69A)")
UNAME_MACHINE=alphaev69 ;;
"EV7 (21364)")
UNAME_MACHINE=alphaev7 ;;
"EV7.9 (21364A)")
UNAME_MACHINE=alphaev79 ;;
esac
# A Pn.n version is a patched version.
# A Vn.n version is a released version.
# A Tn.n version is a released field test version.
# A Xn.n version is an unreleased experimental baselevel.
# 1.2 uses "1.2" for uname -r.
OSF_REL=`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
GUESS=$UNAME_MACHINE-dec-osf$OSF_REL
;;
Amiga*:UNIX_System_V:4.0:*)
GUESS=m68k-unknown-sysv4
;;
*:[Aa]miga[Oo][Ss]:*:*)
GUESS=$UNAME_MACHINE-unknown-amigaos
;;
*:[Mm]orph[Oo][Ss]:*:*)
GUESS=$UNAME_MACHINE-unknown-morphos
;;
*:OS/390:*:*)
GUESS=i370-ibm-openedition
;;
*:z/VM:*:*)
GUESS=s390-ibm-zvmoe
;;
*:OS400:*:*)
GUESS=powerpc-ibm-os400
;;
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
GUESS=arm-acorn-riscix$UNAME_RELEASE
;;
arm*:riscos:*:*|arm*:RISCOS:*:*)
GUESS=arm-unknown-riscos
;;
SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
GUESS=hppa1.1-hitachi-hiuxmpp
;;
Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
case `(/bin/universe) 2>/dev/null` in
att) GUESS=pyramid-pyramid-sysv3 ;;
*) GUESS=pyramid-pyramid-bsd ;;
esac
;;
NILE*:*:*:dcosx)
GUESS=pyramid-pyramid-svr4
;;
DRS?6000:unix:4.0:6*)
GUESS=sparc-icl-nx6
;;
DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
case `/usr/bin/uname -p` in
sparc) GUESS=sparc-icl-nx7 ;;
esac
;;
s390x:SunOS:*:*)
SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
GUESS=$UNAME_MACHINE-ibm-solaris2$SUN_REL
;;
sun4H:SunOS:5.*:*)
SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
GUESS=sparc-hal-solaris2$SUN_REL
;;
sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
GUESS=sparc-sun-solaris2$SUN_REL
;;
i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
GUESS=i386-pc-auroraux$UNAME_RELEASE
;;
i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
set_cc_for_build
SUN_ARCH=i386
# If there is a compiler, see if it is configured for 64-bit objects.
# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
# This test works for both compilers.
if test "$CC_FOR_BUILD" != no_compiler_found; then
if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
(CCOPTS="" $CC_FOR_BUILD -m64 -E - 2>/dev/null) | \
grep IS_64BIT_ARCH >/dev/null
then
SUN_ARCH=x86_64
fi
fi
SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
GUESS=$SUN_ARCH-pc-solaris2$SUN_REL
;;
sun4*:SunOS:6*:*)
# According to config.sub, this is the proper way to canonicalize
# SunOS6. Hard to guess exactly what SunOS6 will be like, but
# it's likely to be more like Solaris than SunOS4.
SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
GUESS=sparc-sun-solaris3$SUN_REL
;;
sun4*:SunOS:*:*)
case `/usr/bin/arch -k` in
Series*|S4*)
UNAME_RELEASE=`uname -v`
;;
esac
- # Japanese Language versions have a version number like `4.1.3-JL'.
+ # Japanese Language versions have a version number like '4.1.3-JL'.
SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/'`
GUESS=sparc-sun-sunos$SUN_REL
;;
sun3*:SunOS:*:*)
GUESS=m68k-sun-sunos$UNAME_RELEASE
;;
sun*:*:4.2BSD:*)
UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3
case `/bin/arch` in
sun3)
GUESS=m68k-sun-sunos$UNAME_RELEASE
;;
sun4)
GUESS=sparc-sun-sunos$UNAME_RELEASE
;;
esac
;;
aushp:SunOS:*:*)
GUESS=sparc-auspex-sunos$UNAME_RELEASE
;;
# The situation for MiNT is a little confusing. The machine name
# can be virtually everything (everything which is not
# "atarist" or "atariste" at least should have a processor
# > m68000). The system name ranges from "MiNT" over "FreeMiNT"
# to the lowercase version "mint" (or "freemint"). Finally
# the system name "TOS" denotes a system which is actually not
# MiNT. But MiNT is downward compatible to TOS, so this should
# be no problem.
atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
GUESS=m68k-atari-mint$UNAME_RELEASE
;;
atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
GUESS=m68k-atari-mint$UNAME_RELEASE
;;
*falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
GUESS=m68k-atari-mint$UNAME_RELEASE
;;
milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
GUESS=m68k-milan-mint$UNAME_RELEASE
;;
hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
GUESS=m68k-hades-mint$UNAME_RELEASE
;;
*:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
GUESS=m68k-unknown-mint$UNAME_RELEASE
;;
m68k:machten:*:*)
GUESS=m68k-apple-machten$UNAME_RELEASE
;;
powerpc:machten:*:*)
GUESS=powerpc-apple-machten$UNAME_RELEASE
;;
RISC*:Mach:*:*)
GUESS=mips-dec-mach_bsd4.3
;;
RISC*:ULTRIX:*:*)
GUESS=mips-dec-ultrix$UNAME_RELEASE
;;
VAX*:ULTRIX*:*:*)
GUESS=vax-dec-ultrix$UNAME_RELEASE
;;
2020:CLIX:*:* | 2430:CLIX:*:*)
GUESS=clipper-intergraph-clix$UNAME_RELEASE
;;
mips:*:*:UMIPS | mips:*:*:RISCos)
set_cc_for_build
sed 's/^ //' << EOF > "$dummy.c"
#ifdef __cplusplus
#include <stdio.h> /* for printf() prototype */
int main (int argc, char *argv[]) {
#else
int main (argc, argv) int argc; char *argv[]; {
#endif
#if defined (host_mips) && defined (MIPSEB)
#if defined (SYSTYPE_SYSV)
printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0);
#endif
#if defined (SYSTYPE_SVR4)
printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0);
#endif
#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0);
#endif
#endif
exit (-1);
}
EOF
$CC_FOR_BUILD -o "$dummy" "$dummy.c" &&
dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` &&
SYSTEM_NAME=`"$dummy" "$dummyarg"` &&
{ echo "$SYSTEM_NAME"; exit; }
GUESS=mips-mips-riscos$UNAME_RELEASE
;;
Motorola:PowerMAX_OS:*:*)
GUESS=powerpc-motorola-powermax
;;
Motorola:*:4.3:PL8-*)
GUESS=powerpc-harris-powermax
;;
Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
GUESS=powerpc-harris-powermax
;;
Night_Hawk:Power_UNIX:*:*)
GUESS=powerpc-harris-powerunix
;;
m88k:CX/UX:7*:*)
GUESS=m88k-harris-cxux7
;;
m88k:*:4*:R4*)
GUESS=m88k-motorola-sysv4
;;
m88k:*:3*:R3*)
GUESS=m88k-motorola-sysv3
;;
AViiON:dgux:*:*)
# DG/UX returns AViiON for all architectures
UNAME_PROCESSOR=`/usr/bin/uname -p`
if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110
then
if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \
test "$TARGET_BINARY_INTERFACE"x = x
then
GUESS=m88k-dg-dgux$UNAME_RELEASE
else
GUESS=m88k-dg-dguxbcs$UNAME_RELEASE
fi
else
GUESS=i586-dg-dgux$UNAME_RELEASE
fi
;;
M88*:DolphinOS:*:*) # DolphinOS (SVR3)
GUESS=m88k-dolphin-sysv3
;;
M88*:*:R3*:*)
# Delta 88k system running SVR3
GUESS=m88k-motorola-sysv3
;;
XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
GUESS=m88k-tektronix-sysv3
;;
Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
GUESS=m68k-tektronix-bsd
;;
*:IRIX*:*:*)
IRIX_REL=`echo "$UNAME_RELEASE" | sed -e 's/-/_/g'`
GUESS=mips-sgi-irix$IRIX_REL
;;
????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
GUESS=romp-ibm-aix # uname -m gives an 8 hex-code CPU id
;; # Note that: echo "'`uname -s`'" gives 'AIX '
i*86:AIX:*:*)
GUESS=i386-ibm-aix
;;
ia64:AIX:*:*)
if test -x /usr/bin/oslevel ; then
IBM_REV=`/usr/bin/oslevel`
else
IBM_REV=$UNAME_VERSION.$UNAME_RELEASE
fi
GUESS=$UNAME_MACHINE-ibm-aix$IBM_REV
;;
*:AIX:2:3)
if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
set_cc_for_build
sed 's/^ //' << EOF > "$dummy.c"
#include <sys/systemcfg.h>
main()
{
if (!__power_pc())
exit(1);
puts("powerpc-ibm-aix3.2.5");
exit(0);
}
EOF
if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"`
then
GUESS=$SYSTEM_NAME
else
GUESS=rs6000-ibm-aix3.2.5
fi
elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
GUESS=rs6000-ibm-aix3.2.4
else
GUESS=rs6000-ibm-aix3.2
fi
;;
*:AIX:*:[4567])
IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then
IBM_ARCH=rs6000
else
IBM_ARCH=powerpc
fi
if test -x /usr/bin/lslpp ; then
IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | \
awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
else
IBM_REV=$UNAME_VERSION.$UNAME_RELEASE
fi
GUESS=$IBM_ARCH-ibm-aix$IBM_REV
;;
*:AIX:*:*)
GUESS=rs6000-ibm-aix
;;
ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*)
GUESS=romp-ibm-bsd4.4
;;
ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
GUESS=romp-ibm-bsd$UNAME_RELEASE # 4.3 with uname added to
;; # report: romp-ibm BSD 4.3
*:BOSX:*:*)
GUESS=rs6000-bull-bosx
;;
DPX/2?00:B.O.S.:*:*)
GUESS=m68k-bull-sysv3
;;
9000/[34]??:4.3bsd:1.*:*)
GUESS=m68k-hp-bsd
;;
hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
GUESS=m68k-hp-bsd4.4
;;
9000/[34678]??:HP-UX:*:*)
HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'`
case $UNAME_MACHINE in
9000/31?) HP_ARCH=m68000 ;;
9000/[34]??) HP_ARCH=m68k ;;
9000/[678][0-9][0-9])
if test -x /usr/bin/getconf; then
sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
case $sc_cpu_version in
523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
532) # CPU_PA_RISC2_0
case $sc_kernel_bits in
32) HP_ARCH=hppa2.0n ;;
64) HP_ARCH=hppa2.0w ;;
'') HP_ARCH=hppa2.0 ;; # HP-UX 10.20
esac ;;
esac
fi
if test "$HP_ARCH" = ""; then
set_cc_for_build
sed 's/^ //' << EOF > "$dummy.c"
#define _HPUX_SOURCE
#include <stdlib.h>
#include <unistd.h>
int main ()
{
#if defined(_SC_KERNEL_BITS)
long bits = sysconf(_SC_KERNEL_BITS);
#endif
long cpu = sysconf (_SC_CPU_VERSION);
switch (cpu)
{
case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
case CPU_PA_RISC2_0:
#if defined(_SC_KERNEL_BITS)
switch (bits)
{
case 64: puts ("hppa2.0w"); break;
case 32: puts ("hppa2.0n"); break;
default: puts ("hppa2.0"); break;
} break;
#else /* !defined(_SC_KERNEL_BITS) */
puts ("hppa2.0"); break;
#endif
default: puts ("hppa1.0"); break;
}
exit (0);
}
EOF
(CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"`
test -z "$HP_ARCH" && HP_ARCH=hppa
fi ;;
esac
if test "$HP_ARCH" = hppa2.0w
then
set_cc_for_build
# hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
# 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
# generating 64-bit code. GNU and HP use different nomenclature:
#
# $ CC_FOR_BUILD=cc ./config.guess
# => hppa2.0w-hp-hpux11.23
# $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
# => hppa64-hp-hpux11.23
if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) |
grep -q __LP64__
then
HP_ARCH=hppa2.0w
else
HP_ARCH=hppa64
fi
fi
GUESS=$HP_ARCH-hp-hpux$HPUX_REV
;;
ia64:HP-UX:*:*)
HPUX_REV=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*.[0B]*//'`
GUESS=ia64-hp-hpux$HPUX_REV
;;
3050*:HI-UX:*:*)
set_cc_for_build
sed 's/^ //' << EOF > "$dummy.c"
#include <unistd.h>
int
main ()
{
long cpu = sysconf (_SC_CPU_VERSION);
/* The order matters, because CPU_IS_HP_MC68K erroneously returns
true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
results, however. */
if (CPU_IS_PA_RISC (cpu))
{
switch (cpu)
{
case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
default: puts ("hppa-hitachi-hiuxwe2"); break;
}
}
else if (CPU_IS_HP_MC68K (cpu))
puts ("m68k-hitachi-hiuxwe2");
else puts ("unknown-hitachi-hiuxwe2");
exit (0);
}
EOF
$CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` &&
{ echo "$SYSTEM_NAME"; exit; }
GUESS=unknown-hitachi-hiuxwe2
;;
9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*)
GUESS=hppa1.1-hp-bsd
;;
9000/8??:4.3bsd:*:*)
GUESS=hppa1.0-hp-bsd
;;
*9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
GUESS=hppa1.0-hp-mpeix
;;
hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*)
GUESS=hppa1.1-hp-osf
;;
hp8??:OSF1:*:*)
GUESS=hppa1.0-hp-osf
;;
i*86:OSF1:*:*)
if test -x /usr/sbin/sysversion ; then
GUESS=$UNAME_MACHINE-unknown-osf1mk
else
GUESS=$UNAME_MACHINE-unknown-osf1
fi
;;
parisc*:Lites*:*:*)
GUESS=hppa1.1-hp-lites
;;
C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
GUESS=c1-convex-bsd
;;
C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
if getsysinfo -f scalar_acc
then echo c32-convex-bsd
else echo c2-convex-bsd
fi
exit ;;
C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
GUESS=c34-convex-bsd
;;
C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
GUESS=c38-convex-bsd
;;
C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
GUESS=c4-convex-bsd
;;
CRAY*Y-MP:*:*:*)
CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
GUESS=ymp-cray-unicos$CRAY_REL
;;
CRAY*[A-Z]90:*:*:*)
echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \
| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
-e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
-e 's/\.[^.]*$/.X/'
exit ;;
CRAY*TS:*:*:*)
CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
GUESS=t90-cray-unicos$CRAY_REL
;;
CRAY*T3E:*:*:*)
CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
GUESS=alphaev5-cray-unicosmk$CRAY_REL
;;
CRAY*SV1:*:*:*)
CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
GUESS=sv1-cray-unicos$CRAY_REL
;;
*:UNICOS/mp:*:*)
CRAY_REL=`echo "$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'`
GUESS=craynv-cray-unicosmp$CRAY_REL
;;
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'`
GUESS=${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}
;;
5000:UNIX_System_V:4.*:*)
FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
GUESS=sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}
;;
i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
GUESS=$UNAME_MACHINE-pc-bsdi$UNAME_RELEASE
;;
sparc*:BSD/OS:*:*)
GUESS=sparc-unknown-bsdi$UNAME_RELEASE
;;
*:BSD/OS:*:*)
GUESS=$UNAME_MACHINE-unknown-bsdi$UNAME_RELEASE
;;
arm:FreeBSD:*:*)
UNAME_PROCESSOR=`uname -p`
set_cc_for_build
if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_PCS_VFP
then
FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabi
else
FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL-gnueabihf
fi
;;
*:FreeBSD:*:*)
- UNAME_PROCESSOR=`/usr/bin/uname -p`
+ UNAME_PROCESSOR=`uname -p`
case $UNAME_PROCESSOR in
amd64)
UNAME_PROCESSOR=x86_64 ;;
i386)
UNAME_PROCESSOR=i586 ;;
esac
FREEBSD_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
GUESS=$UNAME_PROCESSOR-unknown-freebsd$FREEBSD_REL
;;
i*:CYGWIN*:*)
GUESS=$UNAME_MACHINE-pc-cygwin
;;
*:MINGW64*:*)
GUESS=$UNAME_MACHINE-pc-mingw64
;;
*:MINGW*:*)
GUESS=$UNAME_MACHINE-pc-mingw32
;;
*:MSYS*:*)
GUESS=$UNAME_MACHINE-pc-msys
;;
i*:PW*:*)
GUESS=$UNAME_MACHINE-pc-pw32
;;
*:SerenityOS:*:*)
GUESS=$UNAME_MACHINE-pc-serenity
;;
*:Interix*:*)
case $UNAME_MACHINE in
x86)
GUESS=i586-pc-interix$UNAME_RELEASE
;;
authenticamd | genuineintel | EM64T)
GUESS=x86_64-unknown-interix$UNAME_RELEASE
;;
IA64)
GUESS=ia64-unknown-interix$UNAME_RELEASE
;;
esac ;;
i*:UWIN*:*)
GUESS=$UNAME_MACHINE-pc-uwin
;;
amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
GUESS=x86_64-pc-cygwin
;;
prep*:SunOS:5.*:*)
SUN_REL=`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`
GUESS=powerpcle-unknown-solaris2$SUN_REL
;;
*:GNU:*:*)
# the GNU system
GNU_ARCH=`echo "$UNAME_MACHINE" | sed -e 's,[-/].*$,,'`
GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's,/.*$,,'`
GUESS=$GNU_ARCH-unknown-$LIBC$GNU_REL
;;
*:GNU/*:*:*)
# other systems with GNU libc and userland
GNU_SYS=`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"`
GNU_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
GUESS=$UNAME_MACHINE-unknown-$GNU_SYS$GNU_REL-$LIBC
;;
x86_64:[Mm]anagarm:*:*|i?86:[Mm]anagarm:*:*)
GUESS="$UNAME_MACHINE-pc-managarm-mlibc"
;;
*:[Mm]anagarm:*:*)
GUESS="$UNAME_MACHINE-unknown-managarm-mlibc"
;;
*:Minix:*:*)
GUESS=$UNAME_MACHINE-unknown-minix
;;
aarch64:Linux:*:*)
- GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ set_cc_for_build
+ CPU=$UNAME_MACHINE
+ LIBCABI=$LIBC
+ if test "$CC_FOR_BUILD" != no_compiler_found; then
+ ABI=64
+ sed 's/^ //' << EOF > "$dummy.c"
+ #ifdef __ARM_EABI__
+ #ifdef __ARM_PCS_VFP
+ ABI=eabihf
+ #else
+ ABI=eabi
+ #endif
+ #endif
+EOF
+ cc_set_abi=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^ABI' | sed 's, ,,g'`
+ eval "$cc_set_abi"
+ case $ABI in
+ eabi | eabihf) CPU=armv8l; LIBCABI=$LIBC$ABI ;;
+ esac
+ fi
+ GUESS=$CPU-unknown-linux-$LIBCABI
;;
aarch64_be:Linux:*:*)
UNAME_MACHINE=aarch64_be
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
alpha:Linux:*:*)
case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in
EV5) UNAME_MACHINE=alphaev5 ;;
EV56) UNAME_MACHINE=alphaev56 ;;
PCA56) UNAME_MACHINE=alphapca56 ;;
PCA57) UNAME_MACHINE=alphapca56 ;;
EV6) UNAME_MACHINE=alphaev6 ;;
EV67) UNAME_MACHINE=alphaev67 ;;
EV68*) UNAME_MACHINE=alphaev68 ;;
esac
objdump --private-headers /bin/sh | grep -q ld.so.1
if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
arc:Linux:*:* | arceb:Linux:*:* | arc32:Linux:*:* | arc64:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
arm*:Linux:*:*)
set_cc_for_build
if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_EABI__
then
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
else
if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_PCS_VFP
then
GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabi
else
GUESS=$UNAME_MACHINE-unknown-linux-${LIBC}eabihf
fi
fi
;;
avr32*:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
cris:Linux:*:*)
GUESS=$UNAME_MACHINE-axis-linux-$LIBC
;;
crisv32:Linux:*:*)
GUESS=$UNAME_MACHINE-axis-linux-$LIBC
;;
e2k:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
frv:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
hexagon:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
i*86:Linux:*:*)
GUESS=$UNAME_MACHINE-pc-linux-$LIBC
;;
ia64:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
k1om:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
+ kvx:Linux:*:*)
+ GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
+ ;;
+ kvx:cos:*:*)
+ GUESS=$UNAME_MACHINE-unknown-cos
+ ;;
+ kvx:mbr:*:*)
+ GUESS=$UNAME_MACHINE-unknown-mbr
+ ;;
loongarch32:Linux:*:* | loongarch64:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
m32r*:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
m68*:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
mips:Linux:*:* | mips64:Linux:*:*)
set_cc_for_build
IS_GLIBC=0
test x"${LIBC}" = xgnu && IS_GLIBC=1
sed 's/^ //' << EOF > "$dummy.c"
#undef CPU
#undef mips
#undef mipsel
#undef mips64
#undef mips64el
#if ${IS_GLIBC} && defined(_ABI64)
LIBCABI=gnuabi64
#else
#if ${IS_GLIBC} && defined(_ABIN32)
LIBCABI=gnuabin32
#else
LIBCABI=${LIBC}
#endif
#endif
#if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
CPU=mipsisa64r6
#else
#if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
CPU=mipsisa32r6
#else
#if defined(__mips64)
CPU=mips64
#else
CPU=mips
#endif
#endif
#endif
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
MIPS_ENDIAN=el
#else
#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
MIPS_ENDIAN=
#else
MIPS_ENDIAN=
#endif
#endif
EOF
cc_set_vars=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'`
eval "$cc_set_vars"
test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; }
;;
mips64el:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
openrisc*:Linux:*:*)
GUESS=or1k-unknown-linux-$LIBC
;;
or32:Linux:*:* | or1k*:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
padre:Linux:*:*)
GUESS=sparc-unknown-linux-$LIBC
;;
parisc64:Linux:*:* | hppa64:Linux:*:*)
GUESS=hppa64-unknown-linux-$LIBC
;;
parisc:Linux:*:* | hppa:Linux:*:*)
# Look for CPU level
case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
PA7*) GUESS=hppa1.1-unknown-linux-$LIBC ;;
PA8*) GUESS=hppa2.0-unknown-linux-$LIBC ;;
*) GUESS=hppa-unknown-linux-$LIBC ;;
esac
;;
ppc64:Linux:*:*)
GUESS=powerpc64-unknown-linux-$LIBC
;;
ppc:Linux:*:*)
GUESS=powerpc-unknown-linux-$LIBC
;;
ppc64le:Linux:*:*)
GUESS=powerpc64le-unknown-linux-$LIBC
;;
ppcle:Linux:*:*)
GUESS=powerpcle-unknown-linux-$LIBC
;;
riscv32:Linux:*:* | riscv32be:Linux:*:* | riscv64:Linux:*:* | riscv64be:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
s390:Linux:*:* | s390x:Linux:*:*)
GUESS=$UNAME_MACHINE-ibm-linux-$LIBC
;;
sh64*:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
sh*:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
sparc:Linux:*:* | sparc64:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
tile*:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
vax:Linux:*:*)
GUESS=$UNAME_MACHINE-dec-linux-$LIBC
;;
x86_64:Linux:*:*)
set_cc_for_build
CPU=$UNAME_MACHINE
LIBCABI=$LIBC
if test "$CC_FOR_BUILD" != no_compiler_found; then
ABI=64
sed 's/^ //' << EOF > "$dummy.c"
#ifdef __i386__
ABI=x86
#else
#ifdef __ILP32__
ABI=x32
#endif
#endif
EOF
cc_set_abi=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^ABI' | sed 's, ,,g'`
eval "$cc_set_abi"
case $ABI in
x86) CPU=i686 ;;
x32) LIBCABI=${LIBC}x32 ;;
esac
fi
GUESS=$CPU-pc-linux-$LIBCABI
;;
xtensa*:Linux:*:*)
GUESS=$UNAME_MACHINE-unknown-linux-$LIBC
;;
i*86:DYNIX/ptx:4*:*)
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
# earlier versions are messed up and put the nodename in both
# sysname and nodename.
GUESS=i386-sequent-sysv4
;;
i*86:UNIX_SV:4.2MP:2.*)
# Unixware is an offshoot of SVR4, but it has its own version
# number series starting with 2...
# I am not positive that other SVR4 systems won't match this,
# I just have to hope. -- rms.
# Use sysv4.2uw... so that sysv4* matches it.
GUESS=$UNAME_MACHINE-pc-sysv4.2uw$UNAME_VERSION
;;
i*86:OS/2:*:*)
- # If we were able to find `uname', then EMX Unix compatibility
+ # If we were able to find 'uname', then EMX Unix compatibility
# is probably installed.
GUESS=$UNAME_MACHINE-pc-os2-emx
;;
i*86:XTS-300:*:STOP)
GUESS=$UNAME_MACHINE-unknown-stop
;;
i*86:atheos:*:*)
GUESS=$UNAME_MACHINE-unknown-atheos
;;
i*86:syllable:*:*)
GUESS=$UNAME_MACHINE-pc-syllable
;;
i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
GUESS=i386-unknown-lynxos$UNAME_RELEASE
;;
i*86:*DOS:*:*)
GUESS=$UNAME_MACHINE-pc-msdosdjgpp
;;
i*86:*:4.*:*)
UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'`
if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
GUESS=$UNAME_MACHINE-univel-sysv$UNAME_REL
else
GUESS=$UNAME_MACHINE-pc-sysv$UNAME_REL
fi
;;
i*86:*:5:[678]*)
# UnixWare 7.x, OpenUNIX and OpenServer 6.
case `/bin/uname -X | grep "^Machine"` in
*486*) UNAME_MACHINE=i486 ;;
*Pentium) UNAME_MACHINE=i586 ;;
*Pent*|*Celeron) UNAME_MACHINE=i686 ;;
esac
GUESS=$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
;;
i*86:*:3.2:*)
if test -f /usr/options/cb.name; then
UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
GUESS=$UNAME_MACHINE-pc-isc$UNAME_REL
elif /bin/uname -X 2>/dev/null >/dev/null ; then
UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
&& UNAME_MACHINE=i586
(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
&& UNAME_MACHINE=i686
(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
&& UNAME_MACHINE=i686
GUESS=$UNAME_MACHINE-pc-sco$UNAME_REL
else
GUESS=$UNAME_MACHINE-pc-sysv32
fi
;;
pc:*:*:*)
# Left here for compatibility:
# uname -m prints for DJGPP always 'pc', but it prints nothing about
# the processor, so we play safe by assuming i586.
# Note: whatever this is, it MUST be the same as what config.sub
# prints for the "djgpp" host, or else GDB configure will decide that
# this is a cross-build.
GUESS=i586-pc-msdosdjgpp
;;
Intel:Mach:3*:*)
GUESS=i386-pc-mach3
;;
paragon:*:*:*)
GUESS=i860-intel-osf1
;;
i860:*:4.*:*) # i860-SVR4
if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
GUESS=i860-stardent-sysv$UNAME_RELEASE # Stardent Vistra i860-SVR4
else # Add other i860-SVR4 vendors below as they are discovered.
GUESS=i860-unknown-sysv$UNAME_RELEASE # Unknown i860-SVR4
fi
;;
mini*:CTIX:SYS*5:*)
# "miniframe"
GUESS=m68010-convergent-sysv
;;
mc68k:UNIX:SYSTEM5:3.51m)
GUESS=m68k-convergent-sysv
;;
M680?0:D-NIX:5.3:*)
GUESS=m68k-diab-dnix
;;
M68*:*:R3V[5678]*:*)
test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
OS_REL=''
test -r /etc/.relid \
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
&& { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& { echo i486-ncr-sysv4; exit; } ;;
NCR*:*:4.2:* | MPRAS*:*:4.2:*)
OS_REL='.3'
test -r /etc/.relid \
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
&& { echo i586-ncr-sysv4.3"$OS_REL"; exit; }
/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
&& { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
GUESS=m68k-unknown-lynxos$UNAME_RELEASE
;;
mc68030:UNIX_System_V:4.*:*)
GUESS=m68k-atari-sysv4
;;
TSUNAMI:LynxOS:2.*:*)
GUESS=sparc-unknown-lynxos$UNAME_RELEASE
;;
rs6000:LynxOS:2.*:*)
GUESS=rs6000-unknown-lynxos$UNAME_RELEASE
;;
PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
GUESS=powerpc-unknown-lynxos$UNAME_RELEASE
;;
SM[BE]S:UNIX_SV:*:*)
GUESS=mips-dde-sysv$UNAME_RELEASE
;;
RM*:ReliantUNIX-*:*:*)
GUESS=mips-sni-sysv4
;;
RM*:SINIX-*:*:*)
GUESS=mips-sni-sysv4
;;
*:SINIX-*:*:*)
if uname -p 2>/dev/null >/dev/null ; then
UNAME_MACHINE=`(uname -p) 2>/dev/null`
GUESS=$UNAME_MACHINE-sni-sysv4
else
GUESS=ns32k-sni-sysv
fi
;;
- PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ PENTIUM:*:4.0*:*) # Unisys 'ClearPath HMP IX 4000' SVR4/MP effort
# says <Richard.M.Bartel@ccMail.Census.GOV>
GUESS=i586-unisys-sysv4
;;
*:UNIX_System_V:4*:FTX*)
# From Gerald Hewes <hewes@openmarket.com>.
# How about differentiating between stratus architectures? -djm
GUESS=hppa1.1-stratus-sysv4
;;
*:*:*:FTX*)
# From seanf@swdc.stratus.com.
GUESS=i860-stratus-sysv4
;;
i*86:VOS:*:*)
# From Paul.Green@stratus.com.
GUESS=$UNAME_MACHINE-stratus-vos
;;
*:VOS:*:*)
# From Paul.Green@stratus.com.
GUESS=hppa1.1-stratus-vos
;;
mc68*:A/UX:*:*)
GUESS=m68k-apple-aux$UNAME_RELEASE
;;
news*:NEWS-OS:6*:*)
GUESS=mips-sony-newsos6
;;
R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
if test -d /usr/nec; then
GUESS=mips-nec-sysv$UNAME_RELEASE
else
GUESS=mips-unknown-sysv$UNAME_RELEASE
fi
;;
BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
GUESS=powerpc-be-beos
;;
BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
GUESS=powerpc-apple-beos
;;
BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
GUESS=i586-pc-beos
;;
BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
GUESS=i586-pc-haiku
;;
ppc:Haiku:*:*) # Haiku running on Apple PowerPC
GUESS=powerpc-apple-haiku
;;
*:Haiku:*:*) # Haiku modern gcc (not bound by BeOS compat)
GUESS=$UNAME_MACHINE-unknown-haiku
;;
SX-4:SUPER-UX:*:*)
GUESS=sx4-nec-superux$UNAME_RELEASE
;;
SX-5:SUPER-UX:*:*)
GUESS=sx5-nec-superux$UNAME_RELEASE
;;
SX-6:SUPER-UX:*:*)
GUESS=sx6-nec-superux$UNAME_RELEASE
;;
SX-7:SUPER-UX:*:*)
GUESS=sx7-nec-superux$UNAME_RELEASE
;;
SX-8:SUPER-UX:*:*)
GUESS=sx8-nec-superux$UNAME_RELEASE
;;
SX-8R:SUPER-UX:*:*)
GUESS=sx8r-nec-superux$UNAME_RELEASE
;;
SX-ACE:SUPER-UX:*:*)
GUESS=sxace-nec-superux$UNAME_RELEASE
;;
Power*:Rhapsody:*:*)
GUESS=powerpc-apple-rhapsody$UNAME_RELEASE
;;
*:Rhapsody:*:*)
GUESS=$UNAME_MACHINE-apple-rhapsody$UNAME_RELEASE
;;
arm64:Darwin:*:*)
GUESS=aarch64-apple-darwin$UNAME_RELEASE
;;
*:Darwin:*:*)
UNAME_PROCESSOR=`uname -p`
case $UNAME_PROCESSOR in
unknown) UNAME_PROCESSOR=powerpc ;;
esac
if command -v xcode-select > /dev/null 2> /dev/null && \
! xcode-select --print-path > /dev/null 2> /dev/null ; then
# Avoid executing cc if there is no toolchain installed as
# cc will be a stub that puts up a graphical alert
# prompting the user to install developer tools.
CC_FOR_BUILD=no_compiler_found
else
set_cc_for_build
fi
if test "$CC_FOR_BUILD" != no_compiler_found; then
if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_64BIT_ARCH >/dev/null
then
case $UNAME_PROCESSOR in
i386) UNAME_PROCESSOR=x86_64 ;;
powerpc) UNAME_PROCESSOR=powerpc64 ;;
esac
fi
# On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc
if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_PPC >/dev/null
then
UNAME_PROCESSOR=powerpc
fi
elif test "$UNAME_PROCESSOR" = i386 ; then
# uname -m returns i386 or x86_64
UNAME_PROCESSOR=$UNAME_MACHINE
fi
GUESS=$UNAME_PROCESSOR-apple-darwin$UNAME_RELEASE
;;
*:procnto*:*:* | *:QNX:[0123456789]*:*)
UNAME_PROCESSOR=`uname -p`
if test "$UNAME_PROCESSOR" = x86; then
UNAME_PROCESSOR=i386
UNAME_MACHINE=pc
fi
GUESS=$UNAME_PROCESSOR-$UNAME_MACHINE-nto-qnx$UNAME_RELEASE
;;
*:QNX:*:4*)
GUESS=i386-pc-qnx
;;
NEO-*:NONSTOP_KERNEL:*:*)
GUESS=neo-tandem-nsk$UNAME_RELEASE
;;
NSE-*:NONSTOP_KERNEL:*:*)
GUESS=nse-tandem-nsk$UNAME_RELEASE
;;
NSR-*:NONSTOP_KERNEL:*:*)
GUESS=nsr-tandem-nsk$UNAME_RELEASE
;;
NSV-*:NONSTOP_KERNEL:*:*)
GUESS=nsv-tandem-nsk$UNAME_RELEASE
;;
NSX-*:NONSTOP_KERNEL:*:*)
GUESS=nsx-tandem-nsk$UNAME_RELEASE
;;
*:NonStop-UX:*:*)
GUESS=mips-compaq-nonstopux
;;
BS2000:POSIX*:*:*)
GUESS=bs2000-siemens-sysv
;;
DS/*:UNIX_System_V:*:*)
GUESS=$UNAME_MACHINE-$UNAME_SYSTEM-$UNAME_RELEASE
;;
*:Plan9:*:*)
# "uname -m" is not consistent, so use $cputype instead. 386
# is converted to i386 for consistency with other x86
# operating systems.
if test "${cputype-}" = 386; then
UNAME_MACHINE=i386
elif test "x${cputype-}" != x; then
UNAME_MACHINE=$cputype
fi
GUESS=$UNAME_MACHINE-unknown-plan9
;;
*:TOPS-10:*:*)
GUESS=pdp10-unknown-tops10
;;
*:TENEX:*:*)
GUESS=pdp10-unknown-tenex
;;
KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
GUESS=pdp10-dec-tops20
;;
XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
GUESS=pdp10-xkl-tops20
;;
*:TOPS-20:*:*)
GUESS=pdp10-unknown-tops20
;;
*:ITS:*:*)
GUESS=pdp10-unknown-its
;;
SEI:*:*:SEIUX)
GUESS=mips-sei-seiux$UNAME_RELEASE
;;
*:DragonFly:*:*)
DRAGONFLY_REL=`echo "$UNAME_RELEASE" | sed -e 's/[-(].*//'`
GUESS=$UNAME_MACHINE-unknown-dragonfly$DRAGONFLY_REL
;;
*:*VMS:*:*)
UNAME_MACHINE=`(uname -p) 2>/dev/null`
case $UNAME_MACHINE in
A*) GUESS=alpha-dec-vms ;;
I*) GUESS=ia64-dec-vms ;;
V*) GUESS=vax-dec-vms ;;
esac ;;
*:XENIX:*:SysV)
GUESS=i386-pc-xenix
;;
i*86:skyos:*:*)
SKYOS_REL=`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`
GUESS=$UNAME_MACHINE-pc-skyos$SKYOS_REL
;;
i*86:rdos:*:*)
GUESS=$UNAME_MACHINE-pc-rdos
;;
i*86:Fiwix:*:*)
GUESS=$UNAME_MACHINE-pc-fiwix
;;
*:AROS:*:*)
GUESS=$UNAME_MACHINE-unknown-aros
;;
x86_64:VMkernel:*:*)
GUESS=$UNAME_MACHINE-unknown-esx
;;
amd64:Isilon\ OneFS:*:*)
GUESS=x86_64-unknown-onefs
;;
*:Unleashed:*:*)
GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE
;;
+ *:Ironclad:*:*)
+ GUESS=$UNAME_MACHINE-unknown-ironclad
+ ;;
esac
# Do we have a guess based on uname results?
if test "x$GUESS" != x; then
echo "$GUESS"
exit
fi
# No uname command or uname output not recognized.
set_cc_for_build
cat > "$dummy.c" <<EOF
#ifdef _SEQUENT_
#include <sys/types.h>
#include <sys/utsname.h>
#endif
#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
#include <signal.h>
#if defined(_SIZE_T_) || defined(SIGLOST)
#include <sys/utsname.h>
#endif
#endif
#endif
main ()
{
#if defined (sony)
#if defined (MIPSEB)
/* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
I don't know.... */
printf ("mips-sony-bsd\n"); exit (0);
#else
#include <sys/param.h>
printf ("m68k-sony-newsos%s\n",
#ifdef NEWSOS4
"4"
#else
""
#endif
); exit (0);
#endif
#endif
#if defined (NeXT)
#if !defined (__ARCHITECTURE__)
#define __ARCHITECTURE__ "m68k"
#endif
int version;
version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
if (version < 4)
printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
else
printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
exit (0);
#endif
#if defined (MULTIMAX) || defined (n16)
#if defined (UMAXV)
printf ("ns32k-encore-sysv\n"); exit (0);
#else
#if defined (CMU)
printf ("ns32k-encore-mach\n"); exit (0);
#else
printf ("ns32k-encore-bsd\n"); exit (0);
#endif
#endif
#endif
#if defined (__386BSD__)
printf ("i386-pc-bsd\n"); exit (0);
#endif
#if defined (sequent)
#if defined (i386)
printf ("i386-sequent-dynix\n"); exit (0);
#endif
#if defined (ns32000)
printf ("ns32k-sequent-dynix\n"); exit (0);
#endif
#endif
#if defined (_SEQUENT_)
struct utsname un;
uname(&un);
if (strncmp(un.version, "V2", 2) == 0) {
printf ("i386-sequent-ptx2\n"); exit (0);
}
if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
printf ("i386-sequent-ptx1\n"); exit (0);
}
printf ("i386-sequent-ptx\n"); exit (0);
#endif
#if defined (vax)
#if !defined (ultrix)
#include <sys/param.h>
#if defined (BSD)
#if BSD == 43
printf ("vax-dec-bsd4.3\n"); exit (0);
#else
#if BSD == 199006
printf ("vax-dec-bsd4.3reno\n"); exit (0);
#else
printf ("vax-dec-bsd\n"); exit (0);
#endif
#endif
#else
printf ("vax-dec-bsd\n"); exit (0);
#endif
#else
#if defined(_SIZE_T_) || defined(SIGLOST)
struct utsname un;
uname (&un);
printf ("vax-dec-ultrix%s\n", un.release); exit (0);
#else
printf ("vax-dec-ultrix\n"); exit (0);
#endif
#endif
#endif
#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
#if defined(_SIZE_T_) || defined(SIGLOST)
struct utsname *un;
uname (&un);
printf ("mips-dec-ultrix%s\n", un.release); exit (0);
#else
printf ("mips-dec-ultrix\n"); exit (0);
#endif
#endif
#endif
#if defined (alliant) && defined (i860)
printf ("i860-alliant-bsd\n"); exit (0);
#endif
exit (1);
}
EOF
$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`"$dummy"` &&
{ echo "$SYSTEM_NAME"; exit; }
# Apollos put the system type in the environment.
test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; }
echo "$0: unable to guess system type" >&2
case $UNAME_MACHINE:$UNAME_SYSTEM in
mips:Linux | mips64:Linux)
# If we got here on MIPS GNU/Linux, output extra information.
cat >&2 <<EOF
NOTE: MIPS GNU/Linux systems require a C compiler to fully recognize
the system type. Please install a C compiler and try again.
EOF
;;
esac
cat >&2 <<EOF
This script (version $timestamp), has failed to recognize the
operating system you are using. If your script is old, overwrite *all*
copies of config.guess and config.sub with the latest versions from:
https://git.savannah.gnu.org/cgit/config.git/plain/config.guess
and
https://git.savannah.gnu.org/cgit/config.git/plain/config.sub
EOF
our_year=`echo $timestamp | sed 's,-.*,,'`
thisyear=`date +%Y`
# shellcheck disable=SC2003
script_age=`expr "$thisyear" - "$our_year"`
if test "$script_age" -lt 3 ; then
cat >&2 <<EOF
If $0 has already been updated, send the following data and any
information you think might be pertinent to config-patches@gnu.org to
provide the necessary information to handle your system.
config.guess timestamp = $timestamp
uname -m = `(uname -m) 2>/dev/null || echo unknown`
uname -r = `(uname -r) 2>/dev/null || echo unknown`
uname -s = `(uname -s) 2>/dev/null || echo unknown`
uname -v = `(uname -v) 2>/dev/null || echo unknown`
/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
hostinfo = `(hostinfo) 2>/dev/null`
/bin/universe = `(/bin/universe) 2>/dev/null`
/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
/bin/arch = `(/bin/arch) 2>/dev/null`
/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
UNAME_MACHINE = "$UNAME_MACHINE"
UNAME_RELEASE = "$UNAME_RELEASE"
UNAME_SYSTEM = "$UNAME_SYSTEM"
UNAME_VERSION = "$UNAME_VERSION"
EOF
fi
exit 1
# Local variables:
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-end: "'"
# End:
diff --git a/contrib/tcpdump/config.h.in b/contrib/tcpdump/config.h.in
index 59bc6120a5d9..c1bc5f7d9de8 100644
--- a/contrib/tcpdump/config.h.in
+++ b/contrib/tcpdump/config.h.in
@@ -1,290 +1,289 @@
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 if arpa/inet.h declares `ether_ntohost' */
#undef ARPA_INET_H_DECLARES_ETHER_NTOHOST
+/* define if you want to build the instrument functions code */
+#undef ENABLE_INSTRUMENT_FUNCTIONS
+
/* define if you want to build the possibly-buggy SMB printer */
#undef ENABLE_SMB
/* Define to 1 if you have the `bpf_dump' function. */
#undef HAVE_BPF_DUMP
/* capsicum support available */
#undef HAVE_CAPSICUM
/* Define to 1 if you have the `cap_enter' function. */
#undef HAVE_CAP_ENTER
/* Define to 1 if you have the `cap_ioctls_limit' function. */
#undef HAVE_CAP_IOCTLS_LIMIT
/* Define to 1 if you have the <cap-ng.h> header file. */
#undef HAVE_CAP_NG_H
/* Define to 1 if you have the `cap_rights_limit' function. */
#undef HAVE_CAP_RIGHTS_LIMIT
/* Casper support available */
#undef HAVE_CASPER
/* Define to 1 if you have the declaration of `ether_ntohost' */
#undef HAVE_DECL_ETHER_NTOHOST
/* Define to 1 if you have the `ether_ntohost' function. */
#undef HAVE_ETHER_NTOHOST
/* Define to 1 if you have the `EVP_CIPHER_CTX_new' function. */
#undef HAVE_EVP_CIPHER_CTX_NEW
/* Define to 1 if you have the `EVP_DecryptInit_ex' function. */
#undef HAVE_EVP_DECRYPTINIT_EX
-/* Define to 1 if you have the <fcntl.h> header file. */
-#undef HAVE_FCNTL_H
-
/* Define to 1 if you have the `fork' function. */
#undef HAVE_FORK
/* Define to 1 if you have the `getopt_long' function. */
#undef HAVE_GETOPT_LONG
/* define if you have getrpcbynumber() */
#undef HAVE_GETRPCBYNUMBER
/* Define to 1 if you have the `getservent' function. */
#undef HAVE_GETSERVENT
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* 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). */
+/* Define to 1 if you have a usable `crypto' library (-lcrypto). */
#undef HAVE_LIBCRYPTO
/* Define to 1 if you have the `rpc' library (-lrpc). */
#undef HAVE_LIBRPC
-/* Define to 1 if you have the <memory.h> header file. */
-#undef HAVE_MEMORY_H
-
/* Define to 1 if you have the <net/if.h> header file. */
#undef HAVE_NET_IF_H
-/* Define to 1 if printf(3) does not support the z length modifier. */
-#undef HAVE_NO_PRINTF_Z
-
/* Define to 1 if you have the `openat' function. */
#undef HAVE_OPENAT
-/* Define to 1 if you have the <openssl/evp.h> header file. */
-#undef HAVE_OPENSSL_EVP_H
-
/* define if the OS provides AF_INET6 and struct in6_addr */
#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 `pcap_breakloop' function. */
#undef HAVE_PCAP_BREAKLOOP
/* Define to 1 if you have the `pcap_create' function. */
#undef HAVE_PCAP_CREATE
/* define if libpcap has pcap_datalink_name_to_val() */
#undef HAVE_PCAP_DATALINK_NAME_TO_VAL
/* define if libpcap has pcap_datalink_val_to_description() */
#undef HAVE_PCAP_DATALINK_VAL_TO_DESCRIPTION
/* define if libpcap has pcap_debug */
#undef HAVE_PCAP_DEBUG
/* Define to 1 if you have the `pcap_dump_flush' function. */
#undef HAVE_PCAP_DUMP_FLUSH
/* Define to 1 if you have the `pcap_dump_ftell' function. */
#undef HAVE_PCAP_DUMP_FTELL
/* Define to 1 if you have the `pcap_dump_ftell64' function. */
#undef HAVE_PCAP_DUMP_FTELL64
/* Define to 1 if you have the `pcap_findalldevs' function. */
#undef HAVE_PCAP_FINDALLDEVS
/* Define to 1 if you have the `pcap_findalldevs_ex' function. */
#undef HAVE_PCAP_FINDALLDEVS_EX
/* Define to 1 if you have the `pcap_free_datalinks' function. */
#undef HAVE_PCAP_FREE_DATALINKS
/* Define to 1 if the system has the type `pcap_if_t'. */
#undef HAVE_PCAP_IF_T
/* Define to 1 if you have the `pcap_lib_version' function. */
#undef HAVE_PCAP_LIB_VERSION
/* define if libpcap has pcap_list_datalinks() */
#undef HAVE_PCAP_LIST_DATALINKS
/* Define to 1 if you have the `pcap_open' function. */
#undef HAVE_PCAP_OPEN
/* Define to 1 if you have the <pcap/pcap-inttypes.h> header file. */
#undef HAVE_PCAP_PCAP_INTTYPES_H
/* Define to 1 if you have the `pcap_setdirection' function. */
#undef HAVE_PCAP_SETDIRECTION
/* Define to 1 if you have the `pcap_set_datalink' function. */
#undef HAVE_PCAP_SET_DATALINK
/* Define to 1 if you have the `pcap_set_immediate_mode' function. */
#undef HAVE_PCAP_SET_IMMEDIATE_MODE
/* 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. */
#undef HAVE_PCAP_SET_TSTAMP_PRECISION
/* Define to 1 if you have the `pcap_set_tstamp_type' function. */
#undef HAVE_PCAP_SET_TSTAMP_TYPE
/* 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 <rpc/rpcent.h> header file. */
#undef HAVE_RPC_RPCENT_H
/* Define to 1 if you have the <rpc/rpc.h> header file. */
#undef HAVE_RPC_RPC_H
/* Define to 1 if you have the `setlinebuf' function. */
#undef HAVE_SETLINEBUF
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
+/* Define to 1 if you have the <stdio.h> header file. */
+#undef HAVE_STDIO_H
+
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the `strdup' function. */
#undef HAVE_STRDUP
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the `strlcat' function. */
#undef HAVE_STRLCAT
/* Define to 1 if you have the `strlcpy' function. */
#undef HAVE_STRLCPY
/* Define to 1 if you have the `strsep' function. */
#undef HAVE_STRSEP
/* Define to 1 if the system has the type `struct ether_addr'. */
#undef HAVE_STRUCT_ETHER_ADDR
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if the system has the type `uintptr_t'. */
#undef HAVE_UINTPTR_T
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to 1 if you have the `vfork' function. */
#undef HAVE_VFORK
/* define if libpcap has yydebug */
#undef HAVE_YYDEBUG
/* 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' */
#undef NETINET_IF_ETHER_H_DECLARES_ETHER_NTOHOST
/* Define to 1 if net/ethernet.h declares `ether_ntohost' */
#undef NET_ETHERNET_H_DECLARES_ETHER_NTOHOST
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
+/* The size of `time_t', as computed by sizeof. */
+#undef SIZEOF_TIME_T
+
/* The size of `void *', as computed by sizeof. */
#undef SIZEOF_VOID_P
-/* Define to 1 if you have the ANSI C header files. */
+/* Define to 1 if all of the C90 standard headers exist (not just the ones
+ required in a freestanding environment). This macro is provided for
+ backward compatibility; new code need not use it. */
#undef STDC_HEADERS
/* Define to 1 if sys/ethernet.h declares `ether_ntohost' */
#undef SYS_ETHERNET_H_DECLARES_ETHER_NTOHOST
/* define if you have ether_ntohost() and it works */
#undef USE_ETHER_NTOHOST
/* 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
/* define on AIX to get certain functions */
#undef _SUN
/* to handle Ultrix compilers that don't support const in prototypes */
#undef const
/* Define as token for inline if inlining supported */
#undef inline
/* 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 wide enough to hold a
pointer, if such a type exists, and if the system does not define it. */
#undef uintptr_t
diff --git a/contrib/tcpdump/config.sub b/contrib/tcpdump/config.sub
index de4259e40479..2c6a07ab3c34 100755
--- a/contrib/tcpdump/config.sub
+++ b/contrib/tcpdump/config.sub
@@ -1,1907 +1,1971 @@
#! /bin/sh
# Configuration validation subroutine script.
-# Copyright 1992-2023 Free Software Foundation, Inc.
+# Copyright 1992-2024 Free Software Foundation, Inc.
# shellcheck disable=SC2006,SC2268 # see below for rationale
-timestamp='2023-01-21'
+timestamp='2024-01-01'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <https://www.gnu.org/licenses/>.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that
# program. This Exception is an additional permission under section 7
# of the GNU General Public License, version 3 ("GPLv3").
# Please send patches to <config-patches@gnu.org>.
#
# Configuration subroutine to validate and canonicalize a configuration type.
# Supply the specified configuration type as an argument.
# If it is invalid, we print an error message on stderr and exit with code 1.
# Otherwise, we print the canonical config type on stdout and succeed.
# You can get the latest version of this script from:
# https://git.savannah.gnu.org/cgit/config.git/plain/config.sub
# This file is supposed to be the same for all GNU packages
# and recognize all the CPU types, system types and aliases
# that are meaningful with *any* GNU software.
# Each package is responsible for reporting which valid configurations
# it does not support. The user should be able to distinguish
# a failure to support a valid configuration from a meaningless
# configuration.
# The goal of this file is to map all the various variations of a given
# machine specification into a single specification in the form:
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
# or in some cases, the newer four-part form:
# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
# It is wrong to echo any other type of specification.
# The "shellcheck disable" line above the timestamp inhibits complaints
# about features and limitations of the classic Bourne shell that were
# superseded or lifted in POSIX. However, this script identifies a wide
# variety of pre-POSIX systems that do not have POSIX shells at all, and
# even some reasonably current systems (Solaris 10 as case-in-point) still
# have a pre-POSIX /bin/sh.
me=`echo "$0" | sed -e 's,.*/,,'`
usage="\
Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
Canonicalize a configuration name.
Options:
-h, --help print this help, then exit
-t, --time-stamp print date of last modification, then exit
-v, --version print version number, then exit
Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
-Copyright 1992-2023 Free Software Foundation, Inc.
+Copyright 1992-2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
help="
-Try \`$me --help' for more information."
+Try '$me --help' for more information."
# Parse command line
while test $# -gt 0 ; do
case $1 in
--time-stamp | --time* | -t )
echo "$timestamp" ; exit ;;
--version | -v )
echo "$version" ; exit ;;
--help | --h* | -h )
echo "$usage"; exit ;;
-- ) # Stop option processing
shift; break ;;
- ) # Use stdin as input.
break ;;
-* )
echo "$me: invalid option $1$help" >&2
exit 1 ;;
*local*)
# First pass through any local machine types.
echo "$1"
exit ;;
* )
break ;;
esac
done
case $# in
0) echo "$me: missing argument$help" >&2
exit 1;;
1) ;;
*) echo "$me: too many arguments$help" >&2
exit 1;;
esac
# Split fields of configuration type
# shellcheck disable=SC2162
saved_IFS=$IFS
IFS="-" read field1 field2 field3 field4 <<EOF
$1
EOF
IFS=$saved_IFS
# Separate into logical components for further validation
case $1 in
*-*-*-*-*)
- echo Invalid configuration \`"$1"\': more than four components >&2
+ echo "Invalid configuration '$1': more than four components" >&2
exit 1
;;
*-*-*-*)
basic_machine=$field1-$field2
basic_os=$field3-$field4
;;
*-*-*)
# Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two
# parts
maybe_os=$field2-$field3
case $maybe_os in
nto-qnx* | linux-* | uclinux-uclibc* \
| uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \
| netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \
- | storm-chaos* | os2-emx* | rtmk-nova* | managarm-*)
+ | storm-chaos* | os2-emx* | rtmk-nova* | managarm-* \
+ | windows-* )
basic_machine=$field1
basic_os=$maybe_os
;;
android-linux)
basic_machine=$field1-unknown
basic_os=linux-android
;;
*)
basic_machine=$field1-$field2
basic_os=$field3
;;
esac
;;
*-*)
# A lone config we happen to match not fitting any pattern
case $field1-$field2 in
decstation-3100)
basic_machine=mips-dec
basic_os=
;;
*-*)
# Second component is usually, but not always the OS
case $field2 in
# Prevent following clause from handling this valid os
sun*os*)
basic_machine=$field1
basic_os=$field2
;;
zephyr*)
basic_machine=$field1-unknown
basic_os=$field2
;;
# Manufacturers
dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \
| att* | 7300* | 3300* | delta* | motorola* | sun[234]* \
| unicom* | ibm* | next | hp | isi* | apollo | altos* \
| convergent* | ncr* | news | 32* | 3600* | 3100* \
| hitachi* | c[123]* | convex* | sun | crds | omron* | dg \
| ultra | tti* | harris | dolphin | highlevel | gould \
| cbm | ns | masscomp | apple | axis | knuth | cray \
| microblaze* | sim | cisco \
| oki | wec | wrs | winbond)
basic_machine=$field1-$field2
basic_os=
;;
*)
basic_machine=$field1
basic_os=$field2
;;
esac
;;
esac
;;
*)
# Convert single-component short-hands not valid as part of
# multi-component configurations.
case $field1 in
386bsd)
basic_machine=i386-pc
basic_os=bsd
;;
a29khif)
basic_machine=a29k-amd
basic_os=udi
;;
adobe68k)
basic_machine=m68010-adobe
basic_os=scout
;;
alliant)
basic_machine=fx80-alliant
basic_os=
;;
altos | altos3068)
basic_machine=m68k-altos
basic_os=
;;
am29k)
basic_machine=a29k-none
basic_os=bsd
;;
amdahl)
basic_machine=580-amdahl
basic_os=sysv
;;
amiga)
basic_machine=m68k-unknown
basic_os=
;;
amigaos | amigados)
basic_machine=m68k-unknown
basic_os=amigaos
;;
amigaunix | amix)
basic_machine=m68k-unknown
basic_os=sysv4
;;
apollo68)
basic_machine=m68k-apollo
basic_os=sysv
;;
apollo68bsd)
basic_machine=m68k-apollo
basic_os=bsd
;;
aros)
basic_machine=i386-pc
basic_os=aros
;;
aux)
basic_machine=m68k-apple
basic_os=aux
;;
balance)
basic_machine=ns32k-sequent
basic_os=dynix
;;
blackfin)
basic_machine=bfin-unknown
basic_os=linux
;;
cegcc)
basic_machine=arm-unknown
basic_os=cegcc
;;
convex-c1)
basic_machine=c1-convex
basic_os=bsd
;;
convex-c2)
basic_machine=c2-convex
basic_os=bsd
;;
convex-c32)
basic_machine=c32-convex
basic_os=bsd
;;
convex-c34)
basic_machine=c34-convex
basic_os=bsd
;;
convex-c38)
basic_machine=c38-convex
basic_os=bsd
;;
cray)
basic_machine=j90-cray
basic_os=unicos
;;
crds | unos)
basic_machine=m68k-crds
basic_os=
;;
da30)
basic_machine=m68k-da30
basic_os=
;;
decstation | pmax | pmin | dec3100 | decstatn)
basic_machine=mips-dec
basic_os=
;;
delta88)
basic_machine=m88k-motorola
basic_os=sysv3
;;
dicos)
basic_machine=i686-pc
basic_os=dicos
;;
djgpp)
basic_machine=i586-pc
basic_os=msdosdjgpp
;;
ebmon29k)
basic_machine=a29k-amd
basic_os=ebmon
;;
es1800 | OSE68k | ose68k | ose | OSE)
basic_machine=m68k-ericsson
basic_os=ose
;;
gmicro)
basic_machine=tron-gmicro
basic_os=sysv
;;
go32)
basic_machine=i386-pc
basic_os=go32
;;
h8300hms)
basic_machine=h8300-hitachi
basic_os=hms
;;
h8300xray)
basic_machine=h8300-hitachi
basic_os=xray
;;
h8500hms)
basic_machine=h8500-hitachi
basic_os=hms
;;
harris)
basic_machine=m88k-harris
basic_os=sysv3
;;
hp300 | hp300hpux)
basic_machine=m68k-hp
basic_os=hpux
;;
hp300bsd)
basic_machine=m68k-hp
basic_os=bsd
;;
hppaosf)
basic_machine=hppa1.1-hp
basic_os=osf
;;
hppro)
basic_machine=hppa1.1-hp
basic_os=proelf
;;
i386mach)
basic_machine=i386-mach
basic_os=mach
;;
isi68 | isi)
basic_machine=m68k-isi
basic_os=sysv
;;
m68knommu)
basic_machine=m68k-unknown
basic_os=linux
;;
magnum | m3230)
basic_machine=mips-mips
basic_os=sysv
;;
merlin)
basic_machine=ns32k-utek
basic_os=sysv
;;
mingw64)
basic_machine=x86_64-pc
basic_os=mingw64
;;
mingw32)
basic_machine=i686-pc
basic_os=mingw32
;;
mingw32ce)
basic_machine=arm-unknown
basic_os=mingw32ce
;;
monitor)
basic_machine=m68k-rom68k
basic_os=coff
;;
morphos)
basic_machine=powerpc-unknown
basic_os=morphos
;;
moxiebox)
basic_machine=moxie-unknown
basic_os=moxiebox
;;
msdos)
basic_machine=i386-pc
basic_os=msdos
;;
msys)
basic_machine=i686-pc
basic_os=msys
;;
mvs)
basic_machine=i370-ibm
basic_os=mvs
;;
nacl)
basic_machine=le32-unknown
basic_os=nacl
;;
ncr3000)
basic_machine=i486-ncr
basic_os=sysv4
;;
netbsd386)
basic_machine=i386-pc
basic_os=netbsd
;;
netwinder)
basic_machine=armv4l-rebel
basic_os=linux
;;
news | news700 | news800 | news900)
basic_machine=m68k-sony
basic_os=newsos
;;
news1000)
basic_machine=m68030-sony
basic_os=newsos
;;
necv70)
basic_machine=v70-nec
basic_os=sysv
;;
nh3000)
basic_machine=m68k-harris
basic_os=cxux
;;
nh[45]000)
basic_machine=m88k-harris
basic_os=cxux
;;
nindy960)
basic_machine=i960-intel
basic_os=nindy
;;
mon960)
basic_machine=i960-intel
basic_os=mon960
;;
nonstopux)
basic_machine=mips-compaq
basic_os=nonstopux
;;
os400)
basic_machine=powerpc-ibm
basic_os=os400
;;
OSE68000 | ose68000)
basic_machine=m68000-ericsson
basic_os=ose
;;
os68k)
basic_machine=m68k-none
basic_os=os68k
;;
paragon)
basic_machine=i860-intel
basic_os=osf
;;
parisc)
basic_machine=hppa-unknown
basic_os=linux
;;
psp)
basic_machine=mipsallegrexel-sony
basic_os=psp
;;
pw32)
basic_machine=i586-unknown
basic_os=pw32
;;
rdos | rdos64)
basic_machine=x86_64-pc
basic_os=rdos
;;
rdos32)
basic_machine=i386-pc
basic_os=rdos
;;
rom68k)
basic_machine=m68k-rom68k
basic_os=coff
;;
sa29200)
basic_machine=a29k-amd
basic_os=udi
;;
sei)
basic_machine=mips-sei
basic_os=seiux
;;
sequent)
basic_machine=i386-sequent
basic_os=
;;
sps7)
basic_machine=m68k-bull
basic_os=sysv2
;;
st2000)
basic_machine=m68k-tandem
basic_os=
;;
stratus)
basic_machine=i860-stratus
basic_os=sysv4
;;
sun2)
basic_machine=m68000-sun
basic_os=
;;
sun2os3)
basic_machine=m68000-sun
basic_os=sunos3
;;
sun2os4)
basic_machine=m68000-sun
basic_os=sunos4
;;
sun3)
basic_machine=m68k-sun
basic_os=
;;
sun3os3)
basic_machine=m68k-sun
basic_os=sunos3
;;
sun3os4)
basic_machine=m68k-sun
basic_os=sunos4
;;
sun4)
basic_machine=sparc-sun
basic_os=
;;
sun4os3)
basic_machine=sparc-sun
basic_os=sunos3
;;
sun4os4)
basic_machine=sparc-sun
basic_os=sunos4
;;
sun4sol2)
basic_machine=sparc-sun
basic_os=solaris2
;;
sun386 | sun386i | roadrunner)
basic_machine=i386-sun
basic_os=
;;
sv1)
basic_machine=sv1-cray
basic_os=unicos
;;
symmetry)
basic_machine=i386-sequent
basic_os=dynix
;;
t3e)
basic_machine=alphaev5-cray
basic_os=unicos
;;
t90)
basic_machine=t90-cray
basic_os=unicos
;;
toad1)
basic_machine=pdp10-xkl
basic_os=tops20
;;
tpf)
basic_machine=s390x-ibm
basic_os=tpf
;;
udi29k)
basic_machine=a29k-amd
basic_os=udi
;;
ultra3)
basic_machine=a29k-nyu
basic_os=sym1
;;
v810 | necv810)
basic_machine=v810-nec
basic_os=none
;;
vaxv)
basic_machine=vax-dec
basic_os=sysv
;;
vms)
basic_machine=vax-dec
basic_os=vms
;;
vsta)
basic_machine=i386-pc
basic_os=vsta
;;
vxworks960)
basic_machine=i960-wrs
basic_os=vxworks
;;
vxworks68)
basic_machine=m68k-wrs
basic_os=vxworks
;;
vxworks29k)
basic_machine=a29k-wrs
basic_os=vxworks
;;
xbox)
basic_machine=i686-pc
basic_os=mingw32
;;
ymp)
basic_machine=ymp-cray
basic_os=unicos
;;
*)
basic_machine=$1
basic_os=
;;
esac
;;
esac
# Decode 1-component or ad-hoc basic machines
case $basic_machine in
# Here we handle the default manufacturer of certain CPU types. It is in
# some cases the only manufacturer, in others, it is the most popular.
w89k)
cpu=hppa1.1
vendor=winbond
;;
op50n)
cpu=hppa1.1
vendor=oki
;;
op60c)
cpu=hppa1.1
vendor=oki
;;
ibm*)
cpu=i370
vendor=ibm
;;
orion105)
cpu=clipper
vendor=highlevel
;;
mac | mpw | mac-mpw)
cpu=m68k
vendor=apple
;;
pmac | pmac-mpw)
cpu=powerpc
vendor=apple
;;
# Recognize the various machine names and aliases which stand
# for a CPU type and a company and sometimes even an OS.
3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
cpu=m68000
vendor=att
;;
3b*)
cpu=we32k
vendor=att
;;
bluegene*)
cpu=powerpc
vendor=ibm
basic_os=cnk
;;
decsystem10* | dec10*)
cpu=pdp10
vendor=dec
basic_os=tops10
;;
decsystem20* | dec20*)
cpu=pdp10
vendor=dec
basic_os=tops20
;;
delta | 3300 | motorola-3300 | motorola-delta \
| 3300-motorola | delta-motorola)
cpu=m68k
vendor=motorola
;;
dpx2*)
cpu=m68k
vendor=bull
basic_os=sysv3
;;
encore | umax | mmax)
cpu=ns32k
vendor=encore
;;
elxsi)
cpu=elxsi
vendor=elxsi
basic_os=${basic_os:-bsd}
;;
fx2800)
cpu=i860
vendor=alliant
;;
genix)
cpu=ns32k
vendor=ns
;;
h3050r* | hiux*)
cpu=hppa1.1
vendor=hitachi
basic_os=hiuxwe2
;;
hp3k9[0-9][0-9] | hp9[0-9][0-9])
cpu=hppa1.0
vendor=hp
;;
hp9k2[0-9][0-9] | hp9k31[0-9])
cpu=m68000
vendor=hp
;;
hp9k3[2-9][0-9])
cpu=m68k
vendor=hp
;;
hp9k6[0-9][0-9] | hp6[0-9][0-9])
cpu=hppa1.0
vendor=hp
;;
hp9k7[0-79][0-9] | hp7[0-79][0-9])
cpu=hppa1.1
vendor=hp
;;
hp9k78[0-9] | hp78[0-9])
# FIXME: really hppa2.0-hp
cpu=hppa1.1
vendor=hp
;;
hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
# FIXME: really hppa2.0-hp
cpu=hppa1.1
vendor=hp
;;
hp9k8[0-9][13679] | hp8[0-9][13679])
cpu=hppa1.1
vendor=hp
;;
hp9k8[0-9][0-9] | hp8[0-9][0-9])
cpu=hppa1.0
vendor=hp
;;
i*86v32)
cpu=`echo "$1" | sed -e 's/86.*/86/'`
vendor=pc
basic_os=sysv32
;;
i*86v4*)
cpu=`echo "$1" | sed -e 's/86.*/86/'`
vendor=pc
basic_os=sysv4
;;
i*86v)
cpu=`echo "$1" | sed -e 's/86.*/86/'`
vendor=pc
basic_os=sysv
;;
i*86sol2)
cpu=`echo "$1" | sed -e 's/86.*/86/'`
vendor=pc
basic_os=solaris2
;;
j90 | j90-cray)
cpu=j90
vendor=cray
basic_os=${basic_os:-unicos}
;;
iris | iris4d)
cpu=mips
vendor=sgi
case $basic_os in
irix*)
;;
*)
basic_os=irix4
;;
esac
;;
miniframe)
cpu=m68000
vendor=convergent
;;
*mint | mint[0-9]* | *MiNT | *MiNT[0-9]*)
cpu=m68k
vendor=atari
basic_os=mint
;;
news-3600 | risc-news)
cpu=mips
vendor=sony
basic_os=newsos
;;
next | m*-next)
cpu=m68k
vendor=next
case $basic_os in
openstep*)
;;
nextstep*)
;;
ns2*)
basic_os=nextstep2
;;
*)
basic_os=nextstep3
;;
esac
;;
np1)
cpu=np1
vendor=gould
;;
op50n-* | op60c-*)
cpu=hppa1.1
vendor=oki
basic_os=proelf
;;
pa-hitachi)
cpu=hppa1.1
vendor=hitachi
basic_os=hiuxwe2
;;
pbd)
cpu=sparc
vendor=tti
;;
pbb)
cpu=m68k
vendor=tti
;;
pc532)
cpu=ns32k
vendor=pc532
;;
pn)
cpu=pn
vendor=gould
;;
power)
cpu=power
vendor=ibm
;;
ps2)
cpu=i386
vendor=ibm
;;
rm[46]00)
cpu=mips
vendor=siemens
;;
rtpc | rtpc-*)
cpu=romp
vendor=ibm
;;
sde)
cpu=mipsisa32
vendor=sde
basic_os=${basic_os:-elf}
;;
simso-wrs)
cpu=sparclite
vendor=wrs
basic_os=vxworks
;;
tower | tower-32)
cpu=m68k
vendor=ncr
;;
vpp*|vx|vx-*)
cpu=f301
vendor=fujitsu
;;
w65)
cpu=w65
vendor=wdc
;;
w89k-*)
cpu=hppa1.1
vendor=winbond
basic_os=proelf
;;
none)
cpu=none
vendor=none
;;
leon|leon[3-9])
cpu=sparc
vendor=$basic_machine
;;
leon-*|leon[3-9]-*)
cpu=sparc
vendor=`echo "$basic_machine" | sed 's/-.*//'`
;;
*-*)
# shellcheck disable=SC2162
saved_IFS=$IFS
IFS="-" read cpu vendor <<EOF
$basic_machine
EOF
IFS=$saved_IFS
;;
- # We use `pc' rather than `unknown'
+ # We use 'pc' rather than 'unknown'
# because (1) that's what they normally are, and
# (2) the word "unknown" tends to confuse beginning users.
i*86 | x86_64)
cpu=$basic_machine
vendor=pc
;;
# These rules are duplicated from below for sake of the special case above;
# i.e. things that normalized to x86 arches should also default to "pc"
pc98)
cpu=i386
vendor=pc
;;
x64 | amd64)
cpu=x86_64
vendor=pc
;;
# Recognize the basic CPU types without company name.
*)
cpu=$basic_machine
vendor=unknown
;;
esac
unset -v basic_machine
# Decode basic machines in the full and proper CPU-Company form.
case $cpu-$vendor in
# Here we handle the default manufacturer of certain CPU types in canonical form. It is in
# some cases the only manufacturer, in others, it is the most popular.
craynv-unknown)
vendor=cray
basic_os=${basic_os:-unicosmp}
;;
c90-unknown | c90-cray)
vendor=cray
basic_os=${Basic_os:-unicos}
;;
fx80-unknown)
vendor=alliant
;;
romp-unknown)
vendor=ibm
;;
mmix-unknown)
vendor=knuth
;;
microblaze-unknown | microblazeel-unknown)
vendor=xilinx
;;
rs6000-unknown)
vendor=ibm
;;
vax-unknown)
vendor=dec
;;
pdp11-unknown)
vendor=dec
;;
we32k-unknown)
vendor=att
;;
cydra-unknown)
vendor=cydrome
;;
i370-ibm*)
vendor=ibm
;;
orion-unknown)
vendor=highlevel
;;
xps-unknown | xps100-unknown)
cpu=xps100
vendor=honeywell
;;
# Here we normalize CPU types with a missing or matching vendor
armh-unknown | armh-alt)
cpu=armv7l
vendor=alt
basic_os=${basic_os:-linux-gnueabihf}
;;
dpx20-unknown | dpx20-bull)
cpu=rs6000
vendor=bull
basic_os=${basic_os:-bosx}
;;
# Here we normalize CPU types irrespective of the vendor
amd64-*)
cpu=x86_64
;;
blackfin-*)
cpu=bfin
basic_os=linux
;;
c54x-*)
cpu=tic54x
;;
c55x-*)
cpu=tic55x
;;
c6x-*)
cpu=tic6x
;;
e500v[12]-*)
cpu=powerpc
basic_os=${basic_os}"spe"
;;
mips3*-*)
cpu=mips64
;;
ms1-*)
cpu=mt
;;
m68knommu-*)
cpu=m68k
basic_os=linux
;;
m9s12z-* | m68hcs12z-* | hcs12z-* | s12z-*)
cpu=s12z
;;
openrisc-*)
cpu=or32
;;
parisc-*)
cpu=hppa
basic_os=linux
;;
pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
cpu=i586
;;
pentiumpro-* | p6-* | 6x86-* | athlon-* | athlon_*-*)
cpu=i686
;;
pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
cpu=i686
;;
pentium4-*)
cpu=i786
;;
pc98-*)
cpu=i386
;;
ppc-* | ppcbe-*)
cpu=powerpc
;;
ppcle-* | powerpclittle-*)
cpu=powerpcle
;;
ppc64-*)
cpu=powerpc64
;;
ppc64le-* | powerpc64little-*)
cpu=powerpc64le
;;
sb1-*)
cpu=mipsisa64sb1
;;
sb1el-*)
cpu=mipsisa64sb1el
;;
sh5e[lb]-*)
cpu=`echo "$cpu" | sed 's/^\(sh.\)e\(.\)$/\1\2e/'`
;;
spur-*)
cpu=spur
;;
strongarm-* | thumb-*)
cpu=arm
;;
tx39-*)
cpu=mipstx39
;;
tx39el-*)
cpu=mipstx39el
;;
x64-*)
cpu=x86_64
;;
xscale-* | xscalee[bl]-*)
cpu=`echo "$cpu" | sed 's/^xscale/arm/'`
;;
arm64-* | aarch64le-*)
cpu=aarch64
;;
# Recognize the canonical CPU Types that limit and/or modify the
# company names they are paired with.
cr16-*)
basic_os=${basic_os:-elf}
;;
crisv32-* | etraxfs*-*)
cpu=crisv32
vendor=axis
;;
cris-* | etrax*-*)
cpu=cris
vendor=axis
;;
crx-*)
basic_os=${basic_os:-elf}
;;
neo-tandem)
cpu=neo
vendor=tandem
;;
nse-tandem)
cpu=nse
vendor=tandem
;;
nsr-tandem)
cpu=nsr
vendor=tandem
;;
nsv-tandem)
cpu=nsv
vendor=tandem
;;
nsx-tandem)
cpu=nsx
vendor=tandem
;;
mipsallegrexel-sony)
cpu=mipsallegrexel
vendor=sony
;;
tile*-*)
basic_os=${basic_os:-linux-gnu}
;;
*)
# Recognize the canonical CPU types that are allowed with any
# company name.
case $cpu in
1750a | 580 \
| a29k \
- | aarch64 | aarch64_be \
+ | aarch64 | aarch64_be | aarch64c | arm64ec \
| abacus \
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \
| alphapca5[67] | alpha64pca5[67] \
| am33_2.0 \
| amdgcn \
| arc | arceb | arc32 | arc64 \
| arm | arm[lb]e | arme[lb] | armv* \
| avr | avr32 \
| asmjs \
| ba \
| be32 | be64 \
| bfin | bpf | bs2000 \
| c[123]* | c30 | [cjt]90 | c4x \
| c8051 | clipper | craynv | csky | cydra \
| d10v | d30v | dlx | dsp16xx \
| e2k | elxsi | epiphany \
| f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \
+ | javascript \
| h8300 | h8500 \
| hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
| hexagon \
| i370 | i*86 | i860 | i960 | ia16 | ia64 \
| ip2k | iq2000 \
| k1om \
+ | kvx \
| le32 | le64 \
| lm32 \
| loongarch32 | loongarch64 \
| m32c | m32r | m32rle \
| m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \
| m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \
| m88110 | m88k | maxq | mb | mcore | mep | metag \
| microblaze | microblazeel \
- | mips | mipsbe | mipseb | mipsel | mipsle \
- | mips16 \
- | mips64 | mips64eb | mips64el \
- | mips64octeon | mips64octeonel \
- | mips64orion | mips64orionel \
- | mips64r5900 | mips64r5900el \
- | mips64vr | mips64vrel \
- | mips64vr4100 | mips64vr4100el \
- | mips64vr4300 | mips64vr4300el \
- | mips64vr5000 | mips64vr5000el \
- | mips64vr5900 | mips64vr5900el \
- | mipsisa32 | mipsisa32el \
- | mipsisa32r2 | mipsisa32r2el \
- | mipsisa32r3 | mipsisa32r3el \
- | mipsisa32r5 | mipsisa32r5el \
- | mipsisa32r6 | mipsisa32r6el \
- | mipsisa64 | mipsisa64el \
- | mipsisa64r2 | mipsisa64r2el \
- | mipsisa64r3 | mipsisa64r3el \
- | mipsisa64r5 | mipsisa64r5el \
- | mipsisa64r6 | mipsisa64r6el \
- | mipsisa64sb1 | mipsisa64sb1el \
- | mipsisa64sr71k | mipsisa64sr71kel \
- | mipsr5900 | mipsr5900el \
- | mipstx39 | mipstx39el \
+ | mips* \
| mmix \
| mn10200 | mn10300 \
| moxie \
| mt \
| msp430 \
+ | nanomips* \
| nds32 | nds32le | nds32be \
| nfp \
| nios | nios2 | nios2eb | nios2el \
| none | np1 | ns16k | ns32k | nvptx \
| open8 \
| or1k* \
| or32 \
| orion \
| picochip \
| pdp10 | pdp11 | pj | pjl | pn | power \
| powerpc | powerpc64 | powerpc64le | powerpcle | powerpcspe \
| pru \
| pyramid \
| riscv | riscv32 | riscv32be | riscv64 | riscv64be \
| rl78 | romp | rs6000 | rx \
| s390 | s390x \
| score \
| sh | shl \
| sh[1234] | sh[24]a | sh[24]ae[lb] | sh[23]e | she[lb] | sh[lb]e \
| sh[1234]e[lb] | sh[12345][lb]e | sh[23]ele | sh64 | sh64le \
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet \
| sparclite \
| sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \
| spu \
| tahoe \
| thumbv7* \
| tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \
| tron \
| ubicom32 \
| v70 | v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \
| vax \
+ | vc4 \
| visium \
| w65 \
| wasm32 | wasm64 \
| we32k \
| x86 | x86_64 | xc16x | xgate | xps100 \
| xstormy16 | xtensa* \
| ymp \
| z8k | z80)
;;
*)
- echo Invalid configuration \`"$1"\': machine \`"$cpu-$vendor"\' not recognized 1>&2
+ echo "Invalid configuration '$1': machine '$cpu-$vendor' not recognized" 1>&2
exit 1
;;
esac
;;
esac
# Here we canonicalize certain aliases for manufacturers.
case $vendor in
digital*)
vendor=dec
;;
commodore*)
vendor=cbm
;;
*)
;;
esac
# Decode manufacturer-specific aliases for certain operating systems.
-if test x$basic_os != x
+if test x"$basic_os" != x
then
# First recognize some ad-hoc cases, or perhaps split kernel-os, or else just
# set os.
+obj=
case $basic_os in
gnu/linux*)
kernel=linux
os=`echo "$basic_os" | sed -e 's|gnu/linux|gnu|'`
;;
os2-emx)
kernel=os2
os=`echo "$basic_os" | sed -e 's|os2-emx|emx|'`
;;
nto-qnx*)
kernel=nto
os=`echo "$basic_os" | sed -e 's|nto-qnx|qnx|'`
;;
*-*)
# shellcheck disable=SC2162
saved_IFS=$IFS
IFS="-" read kernel os <<EOF
$basic_os
EOF
IFS=$saved_IFS
;;
# Default OS when just kernel was specified
nto*)
kernel=nto
os=`echo "$basic_os" | sed -e 's|nto|qnx|'`
;;
linux*)
kernel=linux
os=`echo "$basic_os" | sed -e 's|linux|gnu|'`
;;
managarm*)
kernel=managarm
os=`echo "$basic_os" | sed -e 's|managarm|mlibc|'`
;;
*)
kernel=
os=$basic_os
;;
esac
# Now, normalize the OS (knowing we just have one component, it's not a kernel,
# etc.)
case $os in
# First match some system type aliases that might get confused
# with valid system types.
# solaris* is a basic system type, with this one exception.
auroraux)
os=auroraux
;;
bluegene*)
os=cnk
;;
solaris1 | solaris1.*)
os=`echo "$os" | sed -e 's|solaris1|sunos4|'`
;;
solaris)
os=solaris2
;;
unixware*)
os=sysv4.2uw
;;
# es1800 is here to avoid being matched by es* (a different OS)
es1800*)
os=ose
;;
# Some version numbers need modification
chorusos*)
os=chorusos
;;
isc)
os=isc2.2
;;
sco6)
os=sco5v6
;;
sco5)
os=sco3.2v5
;;
sco4)
os=sco3.2v4
;;
sco3.2.[4-9]*)
os=`echo "$os" | sed -e 's/sco3.2./sco3.2v/'`
;;
sco*v* | scout)
# Don't match below
;;
sco*)
os=sco3.2v2
;;
psos*)
os=psos
;;
qnx*)
os=qnx
;;
hiux*)
os=hiuxwe2
;;
lynx*178)
os=lynxos178
;;
lynx*5)
os=lynxos5
;;
lynxos*)
# don't get caught up in next wildcard
;;
lynx*)
os=lynxos
;;
mac[0-9]*)
os=`echo "$os" | sed -e 's|mac|macos|'`
;;
opened*)
os=openedition
;;
os400*)
os=os400
;;
sunos5*)
os=`echo "$os" | sed -e 's|sunos5|solaris2|'`
;;
sunos6*)
os=`echo "$os" | sed -e 's|sunos6|solaris3|'`
;;
wince*)
os=wince
;;
utek*)
os=bsd
;;
dynix*)
os=bsd
;;
acis*)
os=aos
;;
atheos*)
os=atheos
;;
syllable*)
os=syllable
;;
386bsd)
os=bsd
;;
ctix* | uts*)
os=sysv
;;
nova*)
os=rtmk-nova
;;
ns2)
os=nextstep2
;;
# Preserve the version number of sinix5.
sinix5.*)
os=`echo "$os" | sed -e 's|sinix|sysv|'`
;;
sinix*)
os=sysv4
;;
tpf*)
os=tpf
;;
triton*)
os=sysv3
;;
oss*)
os=sysv3
;;
svr4*)
os=sysv4
;;
svr3)
os=sysv3
;;
sysvr4)
os=sysv4
;;
ose*)
os=ose
;;
*mint | mint[0-9]* | *MiNT | MiNT[0-9]*)
os=mint
;;
dicos*)
os=dicos
;;
pikeos*)
# Until real need of OS specific support for
# particular features comes up, bare metal
# configurations are quite functional.
case $cpu in
arm*)
os=eabi
;;
*)
- os=elf
+ os=
+ obj=elf
;;
esac
;;
+ aout* | coff* | elf* | pe*)
+ # These are machine code file formats, not OSes
+ obj=$os
+ os=
+ ;;
*)
# No normalization, but not necessarily accepted, that comes below.
;;
esac
else
# Here we handle the default operating systems that come with various machines.
# The value should be what the vendor currently ships out the door with their
# machine or put another way, the most popular os provided with the machine.
# Note that if you're going to try to match "-MANUFACTURER" here (say,
# "-sun"), then you have to tell the case statement up towards the top
# that MANUFACTURER isn't an operating system. Otherwise, code above
# will signal an error saying that MANUFACTURER isn't an operating
# system, and we'll never get to this point.
kernel=
+obj=
case $cpu-$vendor in
score-*)
- os=elf
+ os=
+ obj=elf
;;
spu-*)
- os=elf
+ os=
+ obj=elf
;;
*-acorn)
os=riscix1.2
;;
arm*-rebel)
kernel=linux
os=gnu
;;
arm*-semi)
- os=aout
+ os=
+ obj=aout
;;
c4x-* | tic4x-*)
- os=coff
+ os=
+ obj=coff
;;
c8051-*)
- os=elf
+ os=
+ obj=elf
;;
clipper-intergraph)
os=clix
;;
hexagon-*)
- os=elf
+ os=
+ obj=elf
;;
tic54x-*)
- os=coff
+ os=
+ obj=coff
;;
tic55x-*)
- os=coff
+ os=
+ obj=coff
;;
tic6x-*)
- os=coff
+ os=
+ obj=coff
;;
# This must come before the *-dec entry.
pdp10-*)
os=tops20
;;
pdp11-*)
os=none
;;
*-dec | vax-*)
os=ultrix4.2
;;
m68*-apollo)
os=domain
;;
i386-sun)
os=sunos4.0.2
;;
m68000-sun)
os=sunos3
;;
m68*-cisco)
- os=aout
+ os=
+ obj=aout
;;
mep-*)
- os=elf
+ os=
+ obj=elf
;;
mips*-cisco)
- os=elf
+ os=
+ obj=elf
;;
- mips*-*)
- os=elf
+ mips*-*|nanomips*-*)
+ os=
+ obj=elf
;;
or32-*)
- os=coff
+ os=
+ obj=coff
;;
*-tti) # must be before sparc entry or we get the wrong os.
os=sysv3
;;
sparc-* | *-sun)
os=sunos4.1.1
;;
pru-*)
- os=elf
+ os=
+ obj=elf
;;
*-be)
os=beos
;;
*-ibm)
os=aix
;;
*-knuth)
os=mmixware
;;
*-wec)
os=proelf
;;
*-winbond)
os=proelf
;;
*-oki)
os=proelf
;;
*-hp)
os=hpux
;;
*-hitachi)
os=hiux
;;
i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
os=sysv
;;
*-cbm)
os=amigaos
;;
*-dg)
os=dgux
;;
*-dolphin)
os=sysv3
;;
m68k-ccur)
os=rtu
;;
m88k-omron*)
os=luna
;;
*-next)
os=nextstep
;;
*-sequent)
os=ptx
;;
*-crds)
os=unos
;;
*-ns)
os=genix
;;
i370-*)
os=mvs
;;
*-gould)
os=sysv
;;
*-highlevel)
os=bsd
;;
*-encore)
os=bsd
;;
*-sgi)
os=irix
;;
*-siemens)
os=sysv4
;;
*-masscomp)
os=rtu
;;
f30[01]-fujitsu | f700-fujitsu)
os=uxpv
;;
*-rom68k)
- os=coff
+ os=
+ obj=coff
;;
*-*bug)
- os=coff
+ os=
+ obj=coff
;;
*-apple)
os=macos
;;
*-atari*)
os=mint
;;
*-wrs)
os=vxworks
;;
*)
os=none
;;
esac
fi
-# Now, validate our (potentially fixed-up) OS.
+# Now, validate our (potentially fixed-up) individual pieces (OS, OBJ).
+
case $os in
# Sometimes we do "kernel-libc", so those need to count as OSes.
- musl* | newlib* | relibc* | uclibc*)
+ llvm* | musl* | newlib* | relibc* | uclibc*)
;;
# Likewise for "kernel-abi"
eabi* | gnueabi*)
;;
# VxWorks passes extra cpu info in the 4th filed.
simlinux | simwindows | spe)
;;
+ # See `case $cpu-$os` validation below
+ ghcjs)
+ ;;
# Now accept the basic system types.
# The portable systems comes first.
# Each alternative MUST end in a * to match a version number.
gnu* | android* | bsd* | mach* | minix* | genix* | ultrix* | irix* \
| *vms* | esix* | aix* | cnk* | sunos | sunos[34]* \
| hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \
| sym* | plan9* | psp* | sim* | xray* | os68k* | v88r* \
| hiux* | abug | nacl* | netware* | windows* \
- | os9* | macos* | osx* | ios* \
+ | os9* | macos* | osx* | ios* | tvos* | watchos* \
| mpw* | magic* | mmixware* | mon960* | lnews* \
| amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \
| aos* | aros* | cloudabi* | sortix* | twizzler* \
| nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \
| clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \
| mirbsd* | netbsd* | dicos* | openedition* | ose* \
| bitrig* | openbsd* | secbsd* | solidbsd* | libertybsd* | os108* \
| ekkobsd* | freebsd* | riscix* | lynxos* | os400* \
- | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \
- | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \
+ | bosx* | nextstep* | cxux* | oabi* \
+ | ptx* | ecoff* | winnt* | domain* | vsta* \
| udi* | lites* | ieee* | go32* | aux* | hcos* \
| chorusrdb* | cegcc* | glidix* | serenity* \
- | cygwin* | msys* | pe* | moss* | proelf* | rtems* \
+ | cygwin* | msys* | moss* | proelf* | rtems* \
| midipix* | mingw32* | mingw64* | mint* \
| uxpv* | beos* | mpeix* | udk* | moxiebox* \
| interix* | uwin* | mks* | rhapsody* | darwin* \
| openstep* | oskit* | conix* | pw32* | nonstopux* \
| storm-chaos* | tops10* | tenex* | tops20* | its* \
| os2* | vos* | palmos* | uclinux* | nucleus* | morphos* \
| scout* | superux* | sysv* | rtmk* | tpf* | windiss* \
| powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \
| skyos* | haiku* | rdos* | toppers* | drops* | es* \
| onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
| midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
| nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \
- | fiwix* | mlibc* )
+ | fiwix* | mlibc* | cos* | mbr* | ironclad* )
;;
# This one is extra strict with allowed versions
sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
# Don't forget version if it is 3.2v4 or newer.
;;
+ # This refers to builds using the UEFI calling convention
+ # (which depends on the architecture) and PE file format.
+ # Note that this is both a different calling convention and
+ # different file format than that of GNU-EFI
+ # (x86_64-w64-mingw32).
+ uefi)
+ ;;
none)
;;
- kernel* )
+ kernel* | msvc* )
# Restricted further below
;;
+ '')
+ if test x"$obj" = x
+ then
+ echo "Invalid configuration '$1': Blank OS only allowed with explicit machine code file format" 1>&2
+ fi
+ ;;
*)
- echo Invalid configuration \`"$1"\': OS \`"$os"\' not recognized 1>&2
+ echo "Invalid configuration '$1': OS '$os' not recognized" 1>&2
+ exit 1
+ ;;
+esac
+
+case $obj in
+ aout* | coff* | elf* | pe*)
+ ;;
+ '')
+ # empty is fine
+ ;;
+ *)
+ echo "Invalid configuration '$1': Machine code format '$obj' not recognized" 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we handle the constraint that a (synthetic) cpu and os are
+# valid only in combination with each other and nowhere else.
+case $cpu-$os in
+ # The "javascript-unknown-ghcjs" triple is used by GHC; we
+ # accept it here in order to tolerate that, but reject any
+ # variations.
+ javascript-ghcjs)
+ ;;
+ javascript-* | *-ghcjs)
+ echo "Invalid configuration '$1': cpu '$cpu' is not valid with os '$os$obj'" 1>&2
exit 1
;;
esac
# As a final step for OS-related things, validate the OS-kernel combination
# (given a valid OS), if there is a kernel.
-case $kernel-$os in
- linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \
- | linux-musl* | linux-relibc* | linux-uclibc* | linux-mlibc* )
+case $kernel-$os-$obj in
+ linux-gnu*- | linux-android*- | linux-dietlibc*- | linux-llvm*- \
+ | linux-mlibc*- | linux-musl*- | linux-newlib*- \
+ | linux-relibc*- | linux-uclibc*- )
;;
- uclinux-uclibc* )
+ uclinux-uclibc*- )
;;
- managarm-mlibc* | managarm-kernel* )
+ managarm-mlibc*- | managarm-kernel*- )
;;
- -dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* | -mlibc* )
+ windows*-msvc*-)
+ ;;
+ -dietlibc*- | -llvm*- | -mlibc*- | -musl*- | -newlib*- | -relibc*- \
+ | -uclibc*- )
# These are just libc implementations, not actual OSes, and thus
# require a kernel.
- echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2
+ echo "Invalid configuration '$1': libc '$os' needs explicit kernel." 1>&2
exit 1
;;
- -kernel* )
- echo "Invalid configuration \`$1': \`$os' needs explicit kernel." 1>&2
+ -kernel*- )
+ echo "Invalid configuration '$1': '$os' needs explicit kernel." 1>&2
exit 1
;;
- *-kernel* )
- echo "Invalid configuration \`$1': \`$kernel' does not support \`$os'." 1>&2
+ *-kernel*- )
+ echo "Invalid configuration '$1': '$kernel' does not support '$os'." 1>&2
exit 1
;;
- kfreebsd*-gnu* | kopensolaris*-gnu*)
+ *-msvc*- )
+ echo "Invalid configuration '$1': '$os' needs 'windows'." 1>&2
+ exit 1
;;
- vxworks-simlinux | vxworks-simwindows | vxworks-spe)
+ kfreebsd*-gnu*- | kopensolaris*-gnu*-)
;;
- nto-qnx*)
+ vxworks-simlinux- | vxworks-simwindows- | vxworks-spe-)
;;
- os2-emx)
+ nto-qnx*-)
+ ;;
+ os2-emx-)
+ ;;
+ *-eabi*- | *-gnueabi*-)
;;
- *-eabi* | *-gnueabi*)
+ none--*)
+ # None (no kernel, i.e. freestanding / bare metal),
+ # can be paired with an machine code file format
;;
- -*)
+ -*-)
# Blank kernel with real OS is always fine.
;;
- *-*)
- echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2
+ --*)
+ # Blank kernel and OS with real machine code file format is always fine.
+ ;;
+ *-*-*)
+ echo "Invalid configuration '$1': Kernel '$kernel' not known to work with OS '$os'." 1>&2
exit 1
;;
esac
# Here we handle the case where we know the os, and the CPU type, but not the
# manufacturer. We pick the logical manufacturer.
case $vendor in
unknown)
case $cpu-$os in
*-riscix*)
vendor=acorn
;;
*-sunos*)
vendor=sun
;;
*-cnk* | *-aix*)
vendor=ibm
;;
*-beos*)
vendor=be
;;
*-hpux*)
vendor=hp
;;
*-mpeix*)
vendor=hp
;;
*-hiux*)
vendor=hitachi
;;
*-unos*)
vendor=crds
;;
*-dgux*)
vendor=dg
;;
*-luna*)
vendor=omron
;;
*-genix*)
vendor=ns
;;
*-clix*)
vendor=intergraph
;;
*-mvs* | *-opened*)
vendor=ibm
;;
*-os400*)
vendor=ibm
;;
s390-* | s390x-*)
vendor=ibm
;;
*-ptx*)
vendor=sequent
;;
*-tpf*)
vendor=ibm
;;
*-vxsim* | *-vxworks* | *-windiss*)
vendor=wrs
;;
*-aux*)
vendor=apple
;;
*-hms*)
vendor=hitachi
;;
*-mpw* | *-macos*)
vendor=apple
;;
*-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*)
vendor=atari
;;
*-vos*)
vendor=stratus
;;
esac
;;
esac
-echo "$cpu-$vendor-${kernel:+$kernel-}$os"
+echo "$cpu-$vendor${kernel:+-$kernel}${os:+-$os}${obj:+-$obj}"
exit
# Local variables:
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-end: "'"
# End:
diff --git a/contrib/tcpdump/configure b/contrib/tcpdump/configure
index 53c62d5e95a4..9400d62bc838 100755
--- a/contrib/tcpdump/configure
+++ b/contrib/tcpdump/configure
@@ -1,9681 +1,10993 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for tcpdump 4.99.4.
+# Generated by GNU Autoconf 2.71 for tcpdump 4.99.5.
#
#
-# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+# Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation,
+# Inc.
#
#
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.
## -------------------- ##
## M4sh Initialization. ##
## -------------------- ##
# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+as_nop=:
+if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
# is contrary to our usage. Disable this feature.
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
-else
+else $as_nop
case `(set -o) 2>/dev/null` in #(
*posix*) :
set -o posix ;; #(
*) :
;;
esac
fi
+
+# Reset variables that may have inherited troublesome values from
+# the environment.
+
+# IFS needs to be set, to space, tab, and newline, in precisely that order.
+# (If _AS_PATH_WALK were called with IFS unset, it would have the
+# side effect of setting IFS to empty, thus disabling word splitting.)
+# Quoting is to prevent editors from complaining about space-tab.
as_nl='
'
export as_nl
-# Printing a long string crashes Solaris 7 /usr/bin/printf.
-as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
-# Prefer a ksh shell builtin over an external printf program on Solaris,
-# but without wasting forks for bash or zsh.
-if test -z "$BASH_VERSION$ZSH_VERSION" \
- && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='print -r --'
- as_echo_n='print -rn --'
-elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='printf %s\n'
- as_echo_n='printf %s'
-else
- if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
- as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
- as_echo_n='/usr/ucb/echo -n'
- else
- as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
- as_echo_n_body='eval
- arg=$1;
- case $arg in #(
- *"$as_nl"*)
- expr "X$arg" : "X\\(.*\\)$as_nl";
- arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
- esac;
- expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
- '
- export as_echo_n_body
- as_echo_n='sh -c $as_echo_n_body as_echo'
- fi
- export as_echo_body
- as_echo='sh -c $as_echo_body as_echo'
-fi
+IFS=" "" $as_nl"
+
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# Ensure predictable behavior from utilities with locale-dependent output.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# We cannot yet rely on "unset" to work, but we need these variables
+# to be unset--not just set to an empty or harmless value--now, to
+# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct
+# also avoids known problems related to "unset" and subshell syntax
+# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
+for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
+do eval test \${$as_var+y} \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+
+# Ensure that fds 0, 1, and 2 are open.
+if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi
+if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
+if (exec 3>&2) ; then :; else exec 2>/dev/null; fi
# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
+if ${PATH_SEPARATOR+false} :; then
PATH_SEPARATOR=:
(PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
(PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
PATH_SEPARATOR=';'
}
fi
-# IFS
-# We need space, tab and new line, in precisely that order. Quoting is
-# there to prevent editors from complaining about space-tab.
-# (If _AS_PATH_WALK were called with IFS unset, it would disable word
-# splitting by setting IFS to empty value.)
-IFS=" "" $as_nl"
-
# Find who we are. Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
*[\\/]* ) as_myself=$0 ;;
*) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ test -r "$as_dir$0" && as_myself=$as_dir$0 && break
done
IFS=$as_save_IFS
;;
esac
# We did not find ourselves, most probably we were run as `sh COMMAND'
# in which case we are not to be found in the path.
if test "x$as_myself" = x; then
as_myself=$0
fi
if test ! -f "$as_myself"; then
- $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
exit 1
fi
-# Unset variables that we do not need and which cause bugs (e.g. in
-# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
-# suppresses any "Segmentation fault" message there. '((' could
-# trigger a bug in pdksh 5.2.14.
-for as_var in BASH_ENV ENV MAIL MAILPATH
-do eval test x\${$as_var+set} = xset \
- && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
-done
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-LC_ALL=C
-export LC_ALL
-LANGUAGE=C
-export LANGUAGE
-
-# CDPATH.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
# Use a proper internal environment variable to ensure we don't fall
# into an infinite loop, continuously re-executing ourselves.
if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
_as_can_reexec=no; export _as_can_reexec;
# We cannot yet assume a decent shell, so we have to provide a
# neutralization value for shells without unset; and this also
# works around shells that cannot unset nonexistent variables.
# Preserve -v and -x to the replacement shell.
BASH_ENV=/dev/null
ENV=/dev/null
(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
case $- in # ((((
*v*x* | *x*v* ) as_opts=-vx ;;
*v* ) as_opts=-v ;;
*x* ) as_opts=-x ;;
* ) as_opts= ;;
esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
-$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
-as_fn_exit 255
+printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
fi
# We don't want this to propagate to other subprocesses.
{ _as_can_reexec=; unset _as_can_reexec;}
if test "x$CONFIG_SHELL" = x; then
- as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ as_bourne_compatible="as_nop=:
+if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
# is contrary to our usage. Disable this feature.
alias -g '\${1+\"\$@\"}'='\"\$@\"'
setopt NO_GLOB_SUBST
-else
+else \$as_nop
case \`(set -o) 2>/dev/null\` in #(
*posix*) :
set -o posix ;; #(
*) :
;;
esac
fi
"
as_required="as_fn_return () { (exit \$1); }
as_fn_success () { as_fn_return 0; }
as_fn_failure () { as_fn_return 1; }
as_fn_ret_success () { return 0; }
as_fn_ret_failure () { return 1; }
exitcode=0
as_fn_success || { exitcode=1; echo as_fn_success failed.; }
as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
-if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+if ( set x; as_fn_ret_success y && test x = \"\$1\" )
+then :
-else
+else \$as_nop
exitcode=1; echo positional parameters were not saved.
fi
test x\$exitcode = x0 || exit 1
+blah=\$(echo \$(echo blah))
+test x\"\$blah\" = xblah || exit 1
test -x / || exit 1"
as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
test \$(( 1 + 1 )) = 2 || exit 1"
- if (eval "$as_required") 2>/dev/null; then :
+ if (eval "$as_required") 2>/dev/null
+then :
as_have_required=yes
-else
+else $as_nop
as_have_required=no
fi
- if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null
+then :
-else
+else $as_nop
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
as_found=false
for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
as_found=:
case $as_dir in #(
/*)
for as_base in sh bash ksh sh5; do
# Try only shells that exist, to save several forks.
- as_shell=$as_dir/$as_base
+ as_shell=$as_dir$as_base
if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
- { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null
+then :
CONFIG_SHELL=$as_shell as_have_required=yes
- if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null
+then :
break 2
fi
fi
done;;
esac
as_found=false
done
-$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
- { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
- CONFIG_SHELL=$SHELL as_have_required=yes
-fi; }
IFS=$as_save_IFS
+if $as_found
+then :
+
+else $as_nop
+ if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null
+then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi
+fi
- if test "x$CONFIG_SHELL" != x; then :
+ if test "x$CONFIG_SHELL" != x
+then :
export CONFIG_SHELL
# We cannot yet assume a decent shell, so we have to provide a
# neutralization value for shells without unset; and this also
# works around shells that cannot unset nonexistent variables.
# Preserve -v and -x to the replacement shell.
BASH_ENV=/dev/null
ENV=/dev/null
(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
case $- in # ((((
*v*x* | *x*v* ) as_opts=-vx ;;
*v* ) as_opts=-v ;;
*x* ) as_opts=-x ;;
* ) as_opts= ;;
esac
exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
# Admittedly, this is quite paranoid, since all the known shells bail
# out after a failed `exec'.
-$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2
exit 255
fi
- if test x$as_have_required = xno; then :
- $as_echo "$0: This script requires a shell more modern than all"
- $as_echo "$0: the shells that I found on your system."
- if test x${ZSH_VERSION+set} = xset ; then
- $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
- $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ if test x$as_have_required = xno
+then :
+ printf "%s\n" "$0: This script requires a shell more modern than all"
+ printf "%s\n" "$0: the shells that I found on your system."
+ if test ${ZSH_VERSION+y} ; then
+ printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later."
else
- $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+ printf "%s\n" "$0: Please tell bug-autoconf@gnu.org about your system,
$0: including any error possibly output before this
$0: message. Then install a modern shell, or manually run
$0: the script under such a shell if you do have one."
fi
exit 1
fi
fi
fi
SHELL=${CONFIG_SHELL-/bin/sh}
export SHELL
# Unset more variables known to interfere with behavior of common tools.
CLICOLOR_FORCE= GREP_OPTIONS=
unset CLICOLOR_FORCE GREP_OPTIONS
## --------------------- ##
## M4sh Shell Functions. ##
## --------------------- ##
# as_fn_unset VAR
# ---------------
# Portably unset VAR.
as_fn_unset ()
{
{ eval $1=; unset $1;}
}
as_unset=as_fn_unset
+
# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
as_fn_set_status ()
{
return $1
} # as_fn_set_status
# as_fn_exit STATUS
# -----------------
# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
as_fn_exit ()
{
set +e
as_fn_set_status $1
exit $1
} # as_fn_exit
+# as_fn_nop
+# ---------
+# Do nothing but, unlike ":", preserve the value of $?.
+as_fn_nop ()
+{
+ return $?
+}
+as_nop=as_fn_nop
# as_fn_mkdir_p
# -------------
# Create "$as_dir" as a directory, including parents if necessary.
as_fn_mkdir_p ()
{
case $as_dir in #(
-*) as_dir=./$as_dir;;
esac
test -d "$as_dir" || eval $as_mkdir_p || {
as_dirs=
while :; do
case $as_dir in #(
- *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
*) as_qdir=$as_dir;;
esac
as_dirs="'$as_qdir' $as_dirs"
as_dir=`$as_dirname -- "$as_dir" ||
$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_dir" : 'X\(//\)[^/]' \| \
X"$as_dir" : 'X\(//\)$' \| \
X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_dir" |
+printf "%s\n" X"$as_dir" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
}
/^X\(\/\/\)[^/].*/{
s//\1/
q
}
/^X\(\/\/\)$/{
s//\1/
q
}
/^X\(\/\).*/{
s//\1/
q
}
s/.*/./; q'`
test -d "$as_dir" && break
done
test -z "$as_dirs" || eval "mkdir $as_dirs"
} || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
} # as_fn_mkdir_p
# as_fn_executable_p FILE
# -----------------------
# Test if FILE is an executable regular file.
as_fn_executable_p ()
{
test -f "$1" && test -x "$1"
} # as_fn_executable_p
# as_fn_append VAR VALUE
# ----------------------
# Append the text in VALUE to the end of the definition contained in VAR. Take
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
-if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
+then :
eval 'as_fn_append ()
{
eval $1+=\$2
}'
-else
+else $as_nop
as_fn_append ()
{
eval $1=\$$1\$2
}
fi # as_fn_append
# as_fn_arith ARG...
# ------------------
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
-if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
+then :
eval 'as_fn_arith ()
{
as_val=$(( $* ))
}'
-else
+else $as_nop
as_fn_arith ()
{
as_val=`expr "$@" || test $? -eq 1`
}
fi # as_fn_arith
+# as_fn_nop
+# ---------
+# Do nothing but, unlike ":", preserve the value of $?.
+as_fn_nop ()
+{
+ return $?
+}
+as_nop=as_fn_nop
# as_fn_error STATUS ERROR [LINENO LOG_FD]
# ----------------------------------------
# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
# script with STATUS, using 1 if that was 0.
as_fn_error ()
{
as_status=$1; test $as_status -eq 0 && as_status=1
if test "$4"; then
as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
fi
- $as_echo "$as_me: error: $2" >&2
+ printf "%s\n" "$as_me: error: $2" >&2
as_fn_exit $as_status
} # as_fn_error
if expr a : '\(a\)' >/dev/null 2>&1 &&
test "X`expr 00001 : '.*\(...\)'`" = X001; then
as_expr=expr
else
as_expr=false
fi
if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
as_basename=basename
else
as_basename=false
fi
if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
as_dirname=dirname
else
as_dirname=false
fi
as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
X"$0" : 'X\(//\)$' \| \
X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X/"$0" |
+printf "%s\n" X/"$0" |
sed '/^.*\/\([^/][^/]*\)\/*$/{
s//\1/
q
}
/^X\/\(\/\/\)$/{
s//\1/
q
}
/^X\/\(\/\).*/{
s//\1/
q
}
s/.*/./; q'`
# Avoid depending upon Character Ranges.
as_cr_letters='abcdefghijklmnopqrstuvwxyz'
as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
as_cr_Letters=$as_cr_letters$as_cr_LETTERS
as_cr_digits='0123456789'
as_cr_alnum=$as_cr_Letters$as_cr_digits
as_lineno_1=$LINENO as_lineno_1a=$LINENO
as_lineno_2=$LINENO as_lineno_2a=$LINENO
eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
# Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
sed -n '
p
/[$]LINENO/=
' <$as_myself |
sed '
s/[$]LINENO.*/&-/
t lineno
b
:lineno
N
:loop
s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
t loop
s/-\n.*//
' >$as_me.lineno &&
chmod +x "$as_me.lineno" ||
- { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+ { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
# If we had to re-execute with $CONFIG_SHELL, we're ensured to have
# already done that, so ensure we don't try to do so again and fall
# in an infinite loop. This has already happened in practice.
_as_can_reexec=no; export _as_can_reexec
# Don't try to exec as it changes $[0], causing all sort of problems
# (the dirname of $[0] is not the place where we might find the
# original and so on. Autoconf is especially sensitive to this).
. "./$as_me.lineno"
# Exit status is that of the last command.
exit
}
+
+# Determine whether it's possible to make 'echo' print without a newline.
+# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
+# for compatibility with existing Makefiles.
ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
case `echo 'xy\c'` in
*c*) ECHO_T=' ';; # ECHO_T is single tab character.
xy) ECHO_C='\c';;
*) echo `echo ksh88 bug on AIX 6.1` > /dev/null
ECHO_T=' ';;
esac;;
*)
ECHO_N='-n';;
esac
+# For backward compatibility with old third-party macros, we provide
+# the shell variables $as_echo and $as_echo_n. New code should use
+# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
+as_echo='printf %s\n'
+as_echo_n='printf %s'
+
+
rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
rm -f conf$$.dir/conf$$.file
else
rm -f conf$$.dir
mkdir conf$$.dir 2>/dev/null
fi
if (echo >conf$$.file) 2>/dev/null; then
if ln -s conf$$.file conf$$ 2>/dev/null; then
as_ln_s='ln -s'
# ... but there are two gotchas:
# 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
# 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
# In both cases, we have to default to `cp -pR'.
ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
as_ln_s='cp -pR'
elif ln conf$$.file conf$$ 2>/dev/null; then
as_ln_s=ln
else
as_ln_s='cp -pR'
fi
else
as_ln_s='cp -pR'
fi
rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
rmdir conf$$.dir 2>/dev/null
if mkdir -p . 2>/dev/null; then
as_mkdir_p='mkdir -p "$as_dir"'
else
test -d ./-p && rmdir ./-p
as_mkdir_p=false
fi
as_test_x='test -x'
as_executable_p=as_fn_executable_p
# Sed expression to map a string onto a valid CPP name.
as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
# Sed expression to map a string onto a valid variable name.
as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
test -n "$DJDIR" || exec 7<&0 </dev/null
exec 6>&1
# Name of the host.
# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
# so uname gets run too.
ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
#
# Initializations.
#
ac_default_prefix=/usr/local
ac_clean_files=
ac_config_libobj_dir=.
LIBOBJS=
cross_compiling=no
subdirs=
MFLAGS=
MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='tcpdump'
PACKAGE_TARNAME='tcpdump'
-PACKAGE_VERSION='4.99.4'
-PACKAGE_STRING='tcpdump 4.99.4'
+PACKAGE_VERSION='4.99.5'
+PACKAGE_STRING='tcpdump 4.99.5'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
ac_unique_file="tcpdump.c"
# Factoring default headers for most tests.
ac_includes_default="\
-#include <stdio.h>
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-# include <sys/stat.h>
+#include <stddef.h>
+#ifdef HAVE_STDIO_H
+# include <stdio.h>
#endif
-#ifdef STDC_HEADERS
+#ifdef HAVE_STDLIB_H
# include <stdlib.h>
-# include <stddef.h>
-#else
-# ifdef HAVE_STDLIB_H
-# include <stdlib.h>
-# endif
#endif
#ifdef HAVE_STRING_H
-# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
-# include <memory.h>
-# endif
# include <string.h>
#endif
-#ifdef HAVE_STRINGS_H
-# include <strings.h>
-#endif
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#endif
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif"
+ac_header_c_list=
ac_subst_vars='LTLIBOBJS
INSTALL_DATA
INSTALL_SCRIPT
INSTALL_PROGRAM
MAN_MISC_INFO
MAN_FILE_FORMATS
LOCALSRC
V_PCAPDEP
V_INCLS
-V_GROUP
V_DEFS
V_CCOPT
+LIBCRYPTO_LIBS_STATIC
+LIBCRYPTO_LIBS
+LIBCRYPTO_CFLAGS
MKDEP
DEPENDENCY_CFLAG
AR
RANLIB
PCAP_CONFIG
-PKG_CONFIG
LIBOBJS
EGREP
GREP
CPP
+BREW
+PKG_CONFIG_LIBDIR
+PKG_CONFIG_PATH
+PKG_CONFIG
OBJEXT
EXEEXT
ac_ct_CC
CPPFLAGS
LDFLAGS
CFLAGS
CC
SHLICC2
host_os
host_vendor
host_cpu
host
build_os
build_vendor
build_cpu
build
target_alias
host_alias
build_alias
LIBS
ECHO_T
ECHO_N
ECHO_C
DEFS
mandir
localedir
libdir
psdir
pdfdir
dvidir
htmldir
infodir
docdir
oldincludedir
includedir
+runstatedir
localstatedir
sharedstatedir
sysconfdir
datadir
datarootdir
libexecdir
sbindir
bindir
program_transform_name
prefix
exec_prefix
PACKAGE_URL
PACKAGE_BUGREPORT
PACKAGE_STRING
PACKAGE_VERSION
PACKAGE_TARNAME
PACKAGE_NAME
PATH_SEPARATOR
SHELL'
ac_subst_files=''
ac_user_opts='
enable_option_checking
with_gcc
enable_universal
with_smi
+enable_instrument_functions
enable_smb
with_user
with_chroot
with_sandbox_capsicum
enable_local_libpcap
with_crypto
with_cap_ng
'
ac_precious_vars='build_alias
host_alias
target_alias
CC
CFLAGS
LDFLAGS
LIBS
CPPFLAGS
-CPP'
+PKG_CONFIG
+PKG_CONFIG_PATH
+PKG_CONFIG_LIBDIR
+CPP
+LIBCRYPTO_CFLAGS
+LIBCRYPTO_LIBS
+LIBCRYPTO_LIBS_STATIC'
# Initialize some variables set by options.
ac_init_help=
ac_init_version=false
ac_unrecognized_opts=
ac_unrecognized_sep=
# The variables have the same names as the options, with
# dashes changed to underlines.
cache_file=/dev/null
exec_prefix=NONE
no_create=
no_recursion=
prefix=NONE
program_prefix=NONE
program_suffix=NONE
program_transform_name=s,x,x,
silent=
site=
srcdir=
verbose=
x_includes=NONE
x_libraries=NONE
# Installation directory options.
# These are left unexpanded so users can "make install exec_prefix=/foo"
# and all the variables that are supposed to be based on exec_prefix
# by default will actually change.
# Use braces instead of parens because sh, perl, etc. also accept them.
# (The list follows the same order as the GNU Coding Standards.)
bindir='${exec_prefix}/bin'
sbindir='${exec_prefix}/sbin'
libexecdir='${exec_prefix}/libexec'
datarootdir='${prefix}/share'
datadir='${datarootdir}'
sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
includedir='${prefix}/include'
oldincludedir='/usr/include'
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
infodir='${datarootdir}/info'
htmldir='${docdir}'
dvidir='${docdir}'
pdfdir='${docdir}'
psdir='${docdir}'
libdir='${exec_prefix}/lib'
localedir='${datarootdir}/locale'
mandir='${datarootdir}/man'
ac_prev=
ac_dashdash=
for ac_option
do
# If the previous option needs an argument, assign it.
if test -n "$ac_prev"; then
eval $ac_prev=\$ac_option
ac_prev=
continue
fi
case $ac_option in
*=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
*=) ac_optarg= ;;
*) ac_optarg=yes ;;
esac
- # Accept the important Cygnus configure options, so we can diagnose typos.
-
case $ac_dashdash$ac_option in
--)
ac_dashdash=yes ;;
-bindir | --bindir | --bindi | --bind | --bin | --bi)
ac_prev=bindir ;;
-bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
bindir=$ac_optarg ;;
-build | --build | --buil | --bui | --bu)
ac_prev=build_alias ;;
-build=* | --build=* | --buil=* | --bui=* | --bu=*)
build_alias=$ac_optarg ;;
-cache-file | --cache-file | --cache-fil | --cache-fi \
| --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
ac_prev=cache_file ;;
-cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
| --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
cache_file=$ac_optarg ;;
--config-cache | -C)
cache_file=config.cache ;;
-datadir | --datadir | --datadi | --datad)
ac_prev=datadir ;;
-datadir=* | --datadir=* | --datadi=* | --datad=*)
datadir=$ac_optarg ;;
-datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
| --dataroo | --dataro | --datar)
ac_prev=datarootdir ;;
-datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
| --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
datarootdir=$ac_optarg ;;
-disable-* | --disable-*)
ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid feature name: $ac_useropt"
+ as_fn_error $? "invalid feature name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"enable_$ac_useropt"
"*) ;;
*) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
ac_unrecognized_sep=', ';;
esac
eval enable_$ac_useropt=no ;;
-docdir | --docdir | --docdi | --doc | --do)
ac_prev=docdir ;;
-docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
docdir=$ac_optarg ;;
-dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
ac_prev=dvidir ;;
-dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
dvidir=$ac_optarg ;;
-enable-* | --enable-*)
ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid feature name: $ac_useropt"
+ as_fn_error $? "invalid feature name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"enable_$ac_useropt"
"*) ;;
*) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
ac_unrecognized_sep=', ';;
esac
eval enable_$ac_useropt=\$ac_optarg ;;
-exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
| --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
| --exec | --exe | --ex)
ac_prev=exec_prefix ;;
-exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
| --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
| --exec=* | --exe=* | --ex=*)
exec_prefix=$ac_optarg ;;
-gas | --gas | --ga | --g)
# Obsolete; use --with-gas.
with_gas=yes ;;
-help | --help | --hel | --he | -h)
ac_init_help=long ;;
-help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
ac_init_help=recursive ;;
-help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
ac_init_help=short ;;
-host | --host | --hos | --ho)
ac_prev=host_alias ;;
-host=* | --host=* | --hos=* | --ho=*)
host_alias=$ac_optarg ;;
-htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
ac_prev=htmldir ;;
-htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
| --ht=*)
htmldir=$ac_optarg ;;
-includedir | --includedir | --includedi | --included | --include \
| --includ | --inclu | --incl | --inc)
ac_prev=includedir ;;
-includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
| --includ=* | --inclu=* | --incl=* | --inc=*)
includedir=$ac_optarg ;;
-infodir | --infodir | --infodi | --infod | --info | --inf)
ac_prev=infodir ;;
-infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
infodir=$ac_optarg ;;
-libdir | --libdir | --libdi | --libd)
ac_prev=libdir ;;
-libdir=* | --libdir=* | --libdi=* | --libd=*)
libdir=$ac_optarg ;;
-libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
| --libexe | --libex | --libe)
ac_prev=libexecdir ;;
-libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
| --libexe=* | --libex=* | --libe=*)
libexecdir=$ac_optarg ;;
-localedir | --localedir | --localedi | --localed | --locale)
ac_prev=localedir ;;
-localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
localedir=$ac_optarg ;;
-localstatedir | --localstatedir | --localstatedi | --localstated \
| --localstate | --localstat | --localsta | --localst | --locals)
ac_prev=localstatedir ;;
-localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
| --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
localstatedir=$ac_optarg ;;
-mandir | --mandir | --mandi | --mand | --man | --ma | --m)
ac_prev=mandir ;;
-mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
mandir=$ac_optarg ;;
-nfp | --nfp | --nf)
# Obsolete; use --without-fp.
with_fp=no ;;
-no-create | --no-create | --no-creat | --no-crea | --no-cre \
| --no-cr | --no-c | -n)
no_create=yes ;;
-no-recursion | --no-recursion | --no-recursio | --no-recursi \
| --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
no_recursion=yes ;;
-oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
| --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
| --oldin | --oldi | --old | --ol | --o)
ac_prev=oldincludedir ;;
-oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
| --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
| --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
oldincludedir=$ac_optarg ;;
-prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
ac_prev=prefix ;;
-prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
prefix=$ac_optarg ;;
-program-prefix | --program-prefix | --program-prefi | --program-pref \
| --program-pre | --program-pr | --program-p)
ac_prev=program_prefix ;;
-program-prefix=* | --program-prefix=* | --program-prefi=* \
| --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
program_prefix=$ac_optarg ;;
-program-suffix | --program-suffix | --program-suffi | --program-suff \
| --program-suf | --program-su | --program-s)
ac_prev=program_suffix ;;
-program-suffix=* | --program-suffix=* | --program-suffi=* \
| --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
program_suffix=$ac_optarg ;;
-program-transform-name | --program-transform-name \
| --program-transform-nam | --program-transform-na \
| --program-transform-n | --program-transform- \
| --program-transform | --program-transfor \
| --program-transfo | --program-transf \
| --program-trans | --program-tran \
| --progr-tra | --program-tr | --program-t)
ac_prev=program_transform_name ;;
-program-transform-name=* | --program-transform-name=* \
| --program-transform-nam=* | --program-transform-na=* \
| --program-transform-n=* | --program-transform-=* \
| --program-transform=* | --program-transfor=* \
| --program-transfo=* | --program-transf=* \
| --program-trans=* | --program-tran=* \
| --progr-tra=* | --program-tr=* | --program-t=*)
program_transform_name=$ac_optarg ;;
-pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
ac_prev=pdfdir ;;
-pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
pdfdir=$ac_optarg ;;
-psdir | --psdir | --psdi | --psd | --ps)
ac_prev=psdir ;;
-psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
psdir=$ac_optarg ;;
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
| -silent | --silent | --silen | --sile | --sil)
silent=yes ;;
+ -runstatedir | --runstatedir | --runstatedi | --runstated \
+ | --runstate | --runstat | --runsta | --runst | --runs \
+ | --run | --ru | --r)
+ ac_prev=runstatedir ;;
+ -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+ | --run=* | --ru=* | --r=*)
+ runstatedir=$ac_optarg ;;
+
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
ac_prev=sbindir ;;
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
| --sbi=* | --sb=*)
sbindir=$ac_optarg ;;
-sharedstatedir | --sharedstatedir | --sharedstatedi \
| --sharedstated | --sharedstate | --sharedstat | --sharedsta \
| --sharedst | --shareds | --shared | --share | --shar \
| --sha | --sh)
ac_prev=sharedstatedir ;;
-sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
| --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
| --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
| --sha=* | --sh=*)
sharedstatedir=$ac_optarg ;;
-site | --site | --sit)
ac_prev=site ;;
-site=* | --site=* | --sit=*)
site=$ac_optarg ;;
-srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
ac_prev=srcdir ;;
-srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
srcdir=$ac_optarg ;;
-sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
| --syscon | --sysco | --sysc | --sys | --sy)
ac_prev=sysconfdir ;;
-sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
| --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
sysconfdir=$ac_optarg ;;
-target | --target | --targe | --targ | --tar | --ta | --t)
ac_prev=target_alias ;;
-target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
target_alias=$ac_optarg ;;
-v | -verbose | --verbose | --verbos | --verbo | --verb)
verbose=yes ;;
-version | --version | --versio | --versi | --vers | -V)
ac_init_version=: ;;
-with-* | --with-*)
ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid package name: $ac_useropt"
+ as_fn_error $? "invalid package name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"with_$ac_useropt"
"*) ;;
*) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
ac_unrecognized_sep=', ';;
esac
eval with_$ac_useropt=\$ac_optarg ;;
-without-* | --without-*)
ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
# Reject names that are not valid shell variable names.
expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
- as_fn_error $? "invalid package name: $ac_useropt"
+ as_fn_error $? "invalid package name: \`$ac_useropt'"
ac_useropt_orig=$ac_useropt
- ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'`
case $ac_user_opts in
*"
"with_$ac_useropt"
"*) ;;
*) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
ac_unrecognized_sep=', ';;
esac
eval with_$ac_useropt=no ;;
--x)
# Obsolete; use --with-x.
with_x=yes ;;
-x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
| --x-incl | --x-inc | --x-in | --x-i)
ac_prev=x_includes ;;
-x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
| --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
x_includes=$ac_optarg ;;
-x-libraries | --x-libraries | --x-librarie | --x-librari \
| --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
ac_prev=x_libraries ;;
-x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
| --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
x_libraries=$ac_optarg ;;
-*) as_fn_error $? "unrecognized option: \`$ac_option'
Try \`$0 --help' for more information"
;;
*=*)
ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
# Reject names that are not valid shell variable names.
case $ac_envvar in #(
'' | [0-9]* | *[!_$as_cr_alnum]* )
as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
esac
eval $ac_envvar=\$ac_optarg
export $ac_envvar ;;
*)
# FIXME: should be removed in autoconf 3.0.
- $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2
expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
- $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2
: "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
;;
esac
done
if test -n "$ac_prev"; then
ac_option=--`echo $ac_prev | sed 's/_/-/g'`
as_fn_error $? "missing argument to $ac_option"
fi
if test -n "$ac_unrecognized_opts"; then
case $enable_option_checking in
no) ;;
fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
- *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ *) printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
esac
fi
# Check all directory arguments for consistency.
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
datadir sysconfdir sharedstatedir localstatedir includedir \
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
- libdir localedir mandir
+ libdir localedir mandir runstatedir
do
eval ac_val=\$$ac_var
# Remove trailing slashes.
case $ac_val in
*/ )
ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
eval $ac_var=\$ac_val;;
esac
# Be sure to have absolute directory names.
case $ac_val in
[\\/$]* | ?:[\\/]* ) continue;;
NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
esac
as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
done
# There might be people who depend on the old broken behavior: `$host'
# used to hold the argument of --host etc.
# FIXME: To remove some day.
build=$build_alias
host=$host_alias
target=$target_alias
# FIXME: To remove some day.
if test "x$host_alias" != x; then
if test "x$build_alias" = x; then
cross_compiling=maybe
elif test "x$build_alias" != "x$host_alias"; then
cross_compiling=yes
fi
fi
ac_tool_prefix=
test -n "$host_alias" && ac_tool_prefix=$host_alias-
test "$silent" = yes && exec 6>/dev/null
ac_pwd=`pwd` && test -n "$ac_pwd" &&
ac_ls_di=`ls -di .` &&
ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
as_fn_error $? "working directory cannot be determined"
test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
as_fn_error $? "pwd does not report name of working directory"
# Find the source files, if location was not specified.
if test -z "$srcdir"; then
ac_srcdir_defaulted=yes
# Try the directory containing this script, then the parent directory.
ac_confdir=`$as_dirname -- "$as_myself" ||
$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_myself" : 'X\(//\)[^/]' \| \
X"$as_myself" : 'X\(//\)$' \| \
X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_myself" |
+printf "%s\n" X"$as_myself" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
}
/^X\(\/\/\)[^/].*/{
s//\1/
q
}
/^X\(\/\/\)$/{
s//\1/
q
}
/^X\(\/\).*/{
s//\1/
q
}
s/.*/./; q'`
srcdir=$ac_confdir
if test ! -r "$srcdir/$ac_unique_file"; then
srcdir=..
fi
else
ac_srcdir_defaulted=no
fi
if test ! -r "$srcdir/$ac_unique_file"; then
test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
fi
ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
ac_abs_confdir=`(
cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
pwd)`
# When building in place, set srcdir=.
if test "$ac_abs_confdir" = "$ac_pwd"; then
srcdir=.
fi
# Remove unnecessary trailing slashes from srcdir.
# Double slashes in file names in object file debugging info
# mess up M-x gdb in Emacs.
case $srcdir in
*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
esac
for ac_var in $ac_precious_vars; do
eval ac_env_${ac_var}_set=\${${ac_var}+set}
eval ac_env_${ac_var}_value=\$${ac_var}
eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
eval ac_cv_env_${ac_var}_value=\$${ac_var}
done
#
# Report the --help message.
#
if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures tcpdump 4.99.4 to adapt to many kinds of systems.
+\`configure' configures tcpdump 4.99.5 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
To assign environment variables (e.g., CC, CFLAGS...), specify them as
VAR=VALUE. See below for descriptions of some of the useful variables.
Defaults for the options are specified in brackets.
Configuration:
-h, --help display this help and exit
--help=short display options specific to this package
--help=recursive display the short help of all the included packages
-V, --version display version information and exit
-q, --quiet, --silent do not print \`checking ...' messages
--cache-file=FILE cache test results in FILE [disabled]
-C, --config-cache alias for \`--cache-file=config.cache'
-n, --no-create do not create output files
--srcdir=DIR find the sources in DIR [configure dir or \`..']
Installation directories:
--prefix=PREFIX install architecture-independent files in PREFIX
[$ac_default_prefix]
--exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
[PREFIX]
By default, \`make install' will install all the files in
\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
an installation prefix other than \`$ac_default_prefix' using \`--prefix',
for instance \`--prefix=\$HOME'.
For better control, use the options below.
Fine tuning of the installation directories:
--bindir=DIR user executables [EPREFIX/bin]
--sbindir=DIR system admin executables [EPREFIX/sbin]
--libexecdir=DIR program executables [EPREFIX/libexec]
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
--libdir=DIR object code libraries [EPREFIX/lib]
--includedir=DIR C header files [PREFIX/include]
--oldincludedir=DIR C header files for non-gcc [/usr/include]
--datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
--datadir=DIR read-only architecture-independent data [DATAROOTDIR]
--infodir=DIR info documentation [DATAROOTDIR/info]
--localedir=DIR locale-dependent data [DATAROOTDIR/locale]
--mandir=DIR man documentation [DATAROOTDIR/man]
--docdir=DIR documentation root [DATAROOTDIR/doc/tcpdump]
--htmldir=DIR html documentation [DOCDIR]
--dvidir=DIR dvi documentation [DOCDIR]
--pdfdir=DIR pdf documentation [DOCDIR]
--psdir=DIR ps documentation [DOCDIR]
_ACEOF
cat <<\_ACEOF
System types:
--build=BUILD configure for building on BUILD [guessed]
--host=HOST cross-compile to build programs to run on HOST [BUILD]
_ACEOF
fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of tcpdump 4.99.4:";;
+ short | recursive ) echo "Configuration of tcpdump 4.99.5:";;
esac
cat <<\_ACEOF
Optional Features:
--disable-option-checking ignore unrecognized --enable/--with options
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
--disable-universal don't build universal on macOS
+ --enable-instrument-functions
+ enable instrument functions code [default=no]
--enable-smb enable possibly-buggy SMB printer [default=no]
--disable-local-libpcap don't look for a local libpcap [default=check for a
local libpcap]
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
--without-gcc don't use gcc
--with-smi link with libsmi (allows to load MIBs on the fly to
decode SNMP packets) [default=yes, if available]
--with-user=USERNAME drop privileges by default to USERNAME
--with-chroot=DIRECTORY when dropping privileges, chroot to DIRECTORY
--with-sandbox-capsicum use Capsicum security functions [default=yes, if
available]
--with-crypto[=DIR] use OpenSSL/libressl libcrypto (located in directory
DIR, if specified) [default=yes, if available]
--with-cap-ng use libcap-ng [default=yes, if available]
Some influential environment variables:
CC C compiler command
CFLAGS C compiler flags
LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
nonstandard directory <lib dir>
LIBS libraries to pass to the linker, e.g. -l<library>
CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
you have headers in a nonstandard directory <include dir>
+ PKG_CONFIG path to pkg-config utility
+ PKG_CONFIG_PATH
+ directories to add to pkg-config's search path
+ PKG_CONFIG_LIBDIR
+ path overriding pkg-config's built-in search path
CPP C preprocessor
+ LIBCRYPTO_CFLAGS
+ C compiler flags for libcrypto, overriding pkg-config
+ LIBCRYPTO_LIBS
+ linker flags for libcrypto, overriding pkg-config
+ LIBCRYPTO_LIBS_STATIC
+ static-link linker flags for libcrypto, overriding pkg-config
Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.
Report bugs to the package provider.
_ACEOF
ac_status=$?
fi
if test "$ac_init_help" = "recursive"; then
# If there are subdirs, report their specific --help.
for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
test -d "$ac_dir" ||
{ cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
continue
ac_builddir=.
case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
- ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
# A ".." for each directory in $ac_dir_suffix.
- ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
case $ac_top_builddir_sub in
"") ac_top_builddir_sub=. ac_top_build_prefix= ;;
*) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
esac ;;
esac
ac_abs_top_builddir=$ac_pwd
ac_abs_builddir=$ac_pwd$ac_dir_suffix
# for backward compatibility:
ac_top_builddir=$ac_top_build_prefix
case $srcdir in
.) # We are building in place.
ac_srcdir=.
ac_top_srcdir=$ac_top_builddir_sub
ac_abs_top_srcdir=$ac_pwd ;;
[\\/]* | ?:[\\/]* ) # Absolute name.
ac_srcdir=$srcdir$ac_dir_suffix;
ac_top_srcdir=$srcdir
ac_abs_top_srcdir=$srcdir ;;
*) # Relative name.
ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
ac_top_srcdir=$ac_top_build_prefix$srcdir
ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
esac
ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
cd "$ac_dir" || { ac_status=$?; continue; }
- # Check for guested configure.
+ # Check for configure.gnu first; this name is used for a wrapper for
+ # Metaconfig's "Configure" on case-insensitive file systems.
if test -f "$ac_srcdir/configure.gnu"; then
echo &&
$SHELL "$ac_srcdir/configure.gnu" --help=recursive
elif test -f "$ac_srcdir/configure"; then
echo &&
$SHELL "$ac_srcdir/configure" --help=recursive
else
- $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2
fi || ac_status=$?
cd "$ac_pwd" || { ac_status=$?; break; }
done
fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-tcpdump configure 4.99.4
-generated by GNU Autoconf 2.69
+tcpdump configure 4.99.5
+generated by GNU Autoconf 2.71
-Copyright (C) 2012 Free Software Foundation, Inc.
+Copyright (C) 2021 Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
_ACEOF
exit
fi
## ------------------------ ##
## Autoconf initialization. ##
## ------------------------ ##
# ac_fn_c_try_compile LINENO
# --------------------------
# Try to compile conftest.$ac_ext, and return whether this succeeded.
ac_fn_c_try_compile ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- rm -f conftest.$ac_objext
+ rm -f conftest.$ac_objext conftest.beam
if { { ac_try="$ac_compile"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_compile") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
grep -v '^ *+' conftest.err >conftest.er1
cat conftest.er1 >&5
mv -f conftest.er1 conftest.err
fi
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
- } && test -s conftest.$ac_objext; then :
+ } && test -s conftest.$ac_objext
+then :
ac_retval=0
-else
- $as_echo "$as_me: failed program was:" >&5
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=1
fi
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
as_fn_set_status $ac_retval
} # ac_fn_c_try_compile
-# ac_fn_c_try_cpp LINENO
-# ----------------------
-# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
-ac_fn_c_try_cpp ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- if { { ac_try="$ac_cpp conftest.$ac_ext"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
- ac_status=$?
- if test -s conftest.err; then
- grep -v '^ *+' conftest.err >conftest.er1
- cat conftest.er1 >&5
- mv -f conftest.er1 conftest.err
- fi
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; } > conftest.i && {
- test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
- test ! -s conftest.err
- }; then :
- ac_retval=0
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_retval=1
-fi
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
- as_fn_set_status $ac_retval
-
-} # ac_fn_c_try_cpp
-
-# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
# -------------------------------------------------------
-# Tests whether HEADER exists, giving a warning if it cannot be compiled using
-# the include files in INCLUDES and setting the cache variable VAR
-# accordingly.
-ac_fn_c_check_header_mongrel ()
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- if eval \${$3+:} false; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-fi
-eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-else
- # Is the header compilable?
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
-$as_echo_n "checking $2 usability... " >&6; }
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+printf %s "checking for $2... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
#include <$2>
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_header_compiler=yes
-else
- ac_header_compiler=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
-$as_echo "$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
-$as_echo_n "checking $2 presence... " >&6; }
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <$2>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
- ac_header_preproc=yes
-else
- ac_header_preproc=no
+if ac_fn_c_try_compile "$LINENO"
+then :
+ eval "$3=yes"
+else $as_nop
+ eval "$3=no"
fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
-$as_echo "$ac_header_preproc" >&6; }
-
-# So? What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
- yes:no: )
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
-$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
-$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
- ;;
- no:yes:* )
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
-$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5
-$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
-$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5
-$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
-$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
- ;;
-esac
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- eval "$3=\$ac_header_compiler"
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-fi
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-} # ac_fn_c_check_header_mongrel
+} # ac_fn_c_check_header_compile
# ac_fn_c_try_run LINENO
# ----------------------
-# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
-# that executables *can* be run.
+# Try to run conftest.$ac_ext, and return whether this succeeded. Assumes that
+# executables *can* be run.
ac_fn_c_try_run ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
if { { ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
{ { case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_try") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; }; then :
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }
+then :
ac_retval=0
-else
- $as_echo "$as_me: program exited with status $ac_status" >&5
- $as_echo "$as_me: failed program was:" >&5
+else $as_nop
+ printf "%s\n" "$as_me: program exited with status $ac_status" >&5
+ printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_retval=$ac_status
fi
rm -rf conftest.dSYM conftest_ipa8_conftest.oo
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
as_fn_set_status $ac_retval
} # ac_fn_c_try_run
-# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
-# -------------------------------------------------------
-# Tests whether HEADER exists and can be compiled using the include files in
-# INCLUDES, setting the cache variable VAR accordingly.
-ac_fn_c_check_header_compile ()
+# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES
+# --------------------------------------------
+# Tries to find the compile-time value of EXPR in a program that includes
+# INCLUDES, setting VAR accordingly. Returns whether the value could be
+# computed
+ac_fn_c_compute_int ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ if test "$cross_compiling" = yes; then
+ # Depending upon the size, compute the lo and hi bounds.
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
-#include <$2>
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- eval "$3=yes"
-else
- eval "$3=no"
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-
-} # ac_fn_c_check_header_compile
+int
+main (void)
+{
+static int test_array [1 - 2 * !(($2) >= 0)];
+test_array [0] = 0;
+return test_array [0];
-# ac_fn_c_try_link LINENO
-# -----------------------
-# Try to link conftest.$ac_ext, and return whether this succeeded.
-ac_fn_c_try_link ()
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_lo=0 ac_mid=0
+ while :; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main (void)
{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- rm -f conftest.$ac_objext conftest$ac_exeext
- if { { ac_try="$ac_link"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
- (eval "$ac_link") 2>conftest.err
- ac_status=$?
- if test -s conftest.err; then
- grep -v '^ *+' conftest.err >conftest.er1
- cat conftest.er1 >&5
- mv -f conftest.er1 conftest.err
- fi
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest$ac_exeext && {
- test "$cross_compiling" = yes ||
- test -x conftest$ac_exeext
- }; then :
- ac_retval=0
-else
- $as_echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
+static int test_array [1 - 2 * !(($2) <= $ac_mid)];
+test_array [0] = 0;
+return test_array [0];
- ac_retval=1
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_hi=$ac_mid; break
+else $as_nop
+ as_fn_arith $ac_mid + 1 && ac_lo=$as_val
+ if test $ac_lo -le $ac_mid; then
+ ac_lo= ac_hi=
+ break
+ fi
+ as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val
fi
- # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
- # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
- # interfere with the next link command; also delete a directory that is
- # left behind by Apple's compiler. We do this before executing the actions.
- rm -rf conftest.dSYM conftest_ipa8_conftest.oo
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
- as_fn_set_status $ac_retval
-
-} # ac_fn_c_try_link
-
-# ac_fn_c_check_func LINENO FUNC VAR
-# ----------------------------------
-# Tests whether FUNC exists, setting the cache variable VAR accordingly
-ac_fn_c_check_func ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ done
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
- For example, HP-UX 11i <limits.h> declares gettimeofday. */
-#define $2 innocuous_$2
-
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $2 (); below.
- Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- <limits.h> exists even on freestanding compilers. */
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
-
-#undef $2
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char $2 ();
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined __stub_$2 || defined __stub___$2
-choke me
-#endif
-
-int
-main ()
-{
-return $2 ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- eval "$3=yes"
-else
- eval "$3=no"
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-fi
-eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-
-} # ac_fn_c_check_func
-
-# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES
-# --------------------------------------------
-# Tries to find the compile-time value of EXPR in a program that includes
-# INCLUDES, setting VAR accordingly. Returns whether the value could be
-# computed
-ac_fn_c_compute_int ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- if test "$cross_compiling" = yes; then
- # Depending upon the size, compute the lo and hi bounds.
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-$4
-int
-main ()
-{
-static int test_array [1 - 2 * !(($2) >= 0)];
-test_array [0] = 0;
-return test_array [0];
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_lo=0 ac_mid=0
- while :; do
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-$4
-int
-main ()
-{
-static int test_array [1 - 2 * !(($2) <= $ac_mid)];
-test_array [0] = 0;
-return test_array [0];
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_hi=$ac_mid; break
-else
- as_fn_arith $ac_mid + 1 && ac_lo=$as_val
- if test $ac_lo -le $ac_mid; then
- ac_lo= ac_hi=
- break
- fi
- as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- done
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-$4
-int
-main ()
-{
-static int test_array [1 - 2 * !(($2) < 0)];
-test_array [0] = 0;
-return test_array [0];
+$4
+int
+main (void)
+{
+static int test_array [1 - 2 * !(($2) < 0)];
+test_array [0] = 0;
+return test_array [0];
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_hi=-1 ac_mid=-1
while :; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) >= $ac_mid)];
test_array [0] = 0;
return test_array [0];
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_lo=$ac_mid; break
-else
+else $as_nop
as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val
if test $ac_mid -le $ac_hi; then
ac_lo= ac_hi=
break
fi
as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
done
-else
+else $as_nop
ac_lo= ac_hi=
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
# Binary search between lo and hi bounds.
while test "x$ac_lo" != "x$ac_hi"; do
as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(($2) <= $ac_mid)];
test_array [0] = 0;
return test_array [0];
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_hi=$ac_mid
-else
+else $as_nop
as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
done
case $ac_lo in #((
?*) eval "$3=\$ac_lo"; ac_retval=0 ;;
'') ac_retval=1 ;;
esac
else
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
-static long int longval () { return $2; }
-static unsigned long int ulongval () { return $2; }
+static long int longval (void) { return $2; }
+static unsigned long int ulongval (void) { return $2; }
#include <stdio.h>
#include <stdlib.h>
int
-main ()
+main (void)
{
FILE *f = fopen ("conftest.val", "w");
if (! f)
return 1;
if (($2) < 0)
{
long int i = longval ();
if (i != ($2))
return 1;
fprintf (f, "%ld", i);
}
else
{
unsigned long int i = ulongval ();
if (i != ($2))
return 1;
fprintf (f, "%lu", i);
}
/* Do not output a trailing newline, as this causes \r\n confusion
on some platforms. */
return ferror (f) || fclose (f) != 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
+if ac_fn_c_try_run "$LINENO"
+then :
echo >>conftest.val; read $3 <conftest.val; ac_retval=0
-else
+else $as_nop
ac_retval=1
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
rm -f conftest.val
fi
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
as_fn_set_status $ac_retval
} # ac_fn_c_compute_int
-# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES
-# ---------------------------------------------
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext && {
+ test "$cross_compiling" = yes ||
+ test -x conftest$ac_exeext
+ }
+then :
+ ac_retval=0
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+ # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+ # interfere with the next link command; also delete a directory that is
+ # left behind by Apple's compiler. We do this before executing the actions.
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+printf %s "checking for $2... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $2 (); below. */
+
+#include <limits.h>
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main (void)
+{
+return $2 ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ eval "$3=yes"
+else $as_nop
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_func
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+printf "%s\n" "$ac_try_echo"; } >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } > conftest.i && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }
+then :
+ ac_retval=0
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_check_decl LINENO SYMBOL VAR INCLUDES EXTRA-OPTIONS FLAG-VAR
+# ------------------------------------------------------------------
# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
-# accordingly.
-ac_fn_c_check_decl ()
+# accordingly. Pass EXTRA-OPTIONS to the compiler, using FLAG-VAR.
+ac_fn_check_decl ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
as_decl_name=`echo $2|sed 's/ *(.*//'`
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
+printf %s "checking whether $as_decl_name is declared... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
-$as_echo_n "checking whether $as_decl_name is declared... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ eval ac_save_FLAGS=\$$6
+ as_fn_append $6 " $5"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
#ifndef $as_decl_name
#ifdef __cplusplus
(void) $as_decl_use;
#else
(void) $as_decl_name;
#endif
#endif
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
eval "$3=yes"
-else
+else $as_nop
eval "$3=no"
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ eval $6=\$ac_save_FLAGS
+
fi
eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-} # ac_fn_c_check_decl
+} # ac_fn_check_decl
# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
# -------------------------------------------
# Tests whether TYPE exists after having included INCLUDES, setting cache
# variable VAR accordingly.
ac_fn_c_check_type ()
{
as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+printf %s "checking for $2... " >&6; }
+if eval test \${$3+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
eval "$3=no"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
if (sizeof ($2))
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$4
int
-main ()
+main (void)
{
if (sizeof (($2)))
return 0;
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
-else
+else $as_nop
eval "$3=yes"
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_type
+ac_configure_args_raw=
+for ac_arg
+do
+ case $ac_arg in
+ *\'*)
+ ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append ac_configure_args_raw " '$ac_arg'"
+done
+
+case $ac_configure_args_raw in
+ *$as_nl*)
+ ac_safe_unquote= ;;
+ *)
+ ac_unsafe_z='|&;<>()$`\\"*?[ '' ' # This string ends in space, tab.
+ ac_unsafe_a="$ac_unsafe_z#~"
+ ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g"
+ ac_configure_args_raw=` printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;;
+esac
+
cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by tcpdump $as_me 4.99.4, which was
-generated by GNU Autoconf 2.69. Invocation command line was
+It was created by tcpdump $as_me 4.99.5, which was
+generated by GNU Autoconf 2.71. Invocation command line was
- $ $0 $@
+ $ $0$ac_configure_args_raw
_ACEOF
exec 5>>config.log
{
cat <<_ASUNAME
## --------- ##
## Platform. ##
## --------- ##
hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
uname -m = `(uname -m) 2>/dev/null || echo unknown`
uname -r = `(uname -r) 2>/dev/null || echo unknown`
uname -s = `(uname -s) 2>/dev/null || echo unknown`
uname -v = `(uname -v) 2>/dev/null || echo unknown`
/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
_ASUNAME
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- $as_echo "PATH: $as_dir"
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ printf "%s\n" "PATH: $as_dir"
done
IFS=$as_save_IFS
} >&5
cat >&5 <<_ACEOF
## ----------- ##
## Core tests. ##
## ----------- ##
_ACEOF
# Keep a trace of the command line.
# Strip out --no-create and --no-recursion so they do not pile up.
# Strip out --silent because we don't want to record it for future runs.
# Also quote any args containing shell meta-characters.
# Make two passes to allow for proper duplicate-argument suppression.
ac_configure_args=
ac_configure_args0=
ac_configure_args1=
ac_must_keep_next=false
for ac_pass in 1 2
do
for ac_arg
do
case $ac_arg in
-no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
| -silent | --silent | --silen | --sile | --sil)
continue ;;
*\'*)
- ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
esac
case $ac_pass in
1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
2)
as_fn_append ac_configure_args1 " '$ac_arg'"
if test $ac_must_keep_next = true; then
ac_must_keep_next=false # Got value, back to normal.
else
case $ac_arg in
*=* | --config-cache | -C | -disable-* | --disable-* \
| -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
| -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
| -with-* | --with-* | -without-* | --without-* | --x)
case "$ac_configure_args0 " in
"$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
esac
;;
-* ) ac_must_keep_next=true ;;
esac
fi
as_fn_append ac_configure_args " '$ac_arg'"
;;
esac
done
done
{ ac_configure_args0=; unset ac_configure_args0;}
{ ac_configure_args1=; unset ac_configure_args1;}
# When interrupted or exit'd, cleanup temporary files, and complete
# config.log. We remove comments because anyway the quotes in there
# would cause problems or look ugly.
# WARNING: Use '\'' to represent an apostrophe within the trap.
# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
trap 'exit_status=$?
+ # Sanitize IFS.
+ IFS=" "" $as_nl"
# Save into config.log some information that might help in debugging.
{
echo
- $as_echo "## ---------------- ##
+ printf "%s\n" "## ---------------- ##
## Cache variables. ##
## ---------------- ##"
echo
# The following way of writing the cache mishandles newlines in values,
(
for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
eval ac_val=\$$ac_var
case $ac_val in #(
*${as_nl}*)
case $ac_var in #(
- *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
-$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
esac
case $ac_var in #(
_ | IFS | as_nl) ;; #(
BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
*) { eval $ac_var=; unset $ac_var;} ;;
esac ;;
esac
done
(set) 2>&1 |
case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
*${as_nl}ac_space=\ *)
sed -n \
"s/'\''/'\''\\\\'\'''\''/g;
s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
;; #(
*)
sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
;;
esac |
sort
)
echo
- $as_echo "## ----------------- ##
+ printf "%s\n" "## ----------------- ##
## Output variables. ##
## ----------------- ##"
echo
for ac_var in $ac_subst_vars
do
eval ac_val=\$$ac_var
case $ac_val in
- *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
esac
- $as_echo "$ac_var='\''$ac_val'\''"
+ printf "%s\n" "$ac_var='\''$ac_val'\''"
done | sort
echo
if test -n "$ac_subst_files"; then
- $as_echo "## ------------------- ##
+ printf "%s\n" "## ------------------- ##
## File substitutions. ##
## ------------------- ##"
echo
for ac_var in $ac_subst_files
do
eval ac_val=\$$ac_var
case $ac_val in
- *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
esac
- $as_echo "$ac_var='\''$ac_val'\''"
+ printf "%s\n" "$ac_var='\''$ac_val'\''"
done | sort
echo
fi
if test -s confdefs.h; then
- $as_echo "## ----------- ##
+ printf "%s\n" "## ----------- ##
## confdefs.h. ##
## ----------- ##"
echo
cat confdefs.h
echo
fi
test "$ac_signal" != 0 &&
- $as_echo "$as_me: caught signal $ac_signal"
- $as_echo "$as_me: exit $exit_status"
+ printf "%s\n" "$as_me: caught signal $ac_signal"
+ printf "%s\n" "$as_me: exit $exit_status"
} >&5
rm -f core *.core core.conftest.* &&
rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
exit $exit_status
' 0
for ac_signal in 1 2 13 15; do
trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
done
ac_signal=0
# confdefs.h avoids OS command line length limits that DEFS can exceed.
rm -f -r conftest* confdefs.h
-$as_echo "/* confdefs.h */" > confdefs.h
+printf "%s\n" "/* confdefs.h */" > confdefs.h
# Predefined preprocessor variables.
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_NAME "$PACKAGE_NAME"
-_ACEOF
+printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
-_ACEOF
+printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_VERSION "$PACKAGE_VERSION"
-_ACEOF
+printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_STRING "$PACKAGE_STRING"
-_ACEOF
+printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
-_ACEOF
+printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define PACKAGE_URL "$PACKAGE_URL"
-_ACEOF
+printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h
# Let the site file select an alternate cache file if it wants to.
# Prefer an explicitly selected file to automatically selected ones.
-ac_site_file1=NONE
-ac_site_file2=NONE
if test -n "$CONFIG_SITE"; then
- # We do not want a PATH search for config.site.
- case $CONFIG_SITE in #((
- -*) ac_site_file1=./$CONFIG_SITE;;
- */*) ac_site_file1=$CONFIG_SITE;;
- *) ac_site_file1=./$CONFIG_SITE;;
- esac
+ ac_site_files="$CONFIG_SITE"
elif test "x$prefix" != xNONE; then
- ac_site_file1=$prefix/share/config.site
- ac_site_file2=$prefix/etc/config.site
+ ac_site_files="$prefix/share/config.site $prefix/etc/config.site"
else
- ac_site_file1=$ac_default_prefix/share/config.site
- ac_site_file2=$ac_default_prefix/etc/config.site
+ ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
fi
-for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+
+for ac_site_file in $ac_site_files
do
- test "x$ac_site_file" = xNONE && continue
- if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
-$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ case $ac_site_file in #(
+ */*) :
+ ;; #(
+ *) :
+ ac_site_file=./$ac_site_file ;;
+esac
+ if test -f "$ac_site_file" && test -r "$ac_site_file"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;}
sed 's/^/| /' "$ac_site_file" >&5
. "$ac_site_file" \
- || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "failed to load site script $ac_site_file
See \`config.log' for more details" "$LINENO" 5; }
fi
done
if test -r "$cache_file"; then
# Some versions of bash will fail to source /dev/null (special files
# actually), so we avoid doing that. DJGPP emulates it as a regular file.
if test /dev/null != "$cache_file" && test -f "$cache_file"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
-$as_echo "$as_me: loading cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+printf "%s\n" "$as_me: loading cache $cache_file" >&6;}
case $cache_file in
[\\/]* | ?:[\\/]* ) . "$cache_file";;
*) . "./$cache_file";;
esac
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
-$as_echo "$as_me: creating cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+printf "%s\n" "$as_me: creating cache $cache_file" >&6;}
>$cache_file
fi
-# Check that the precious variables saved in the cache have kept the same
-# value.
-ac_cache_corrupted=false
-for ac_var in $ac_precious_vars; do
- eval ac_old_set=\$ac_cv_env_${ac_var}_set
- eval ac_new_set=\$ac_env_${ac_var}_set
- eval ac_old_val=\$ac_cv_env_${ac_var}_value
- eval ac_new_val=\$ac_env_${ac_var}_value
- case $ac_old_set,$ac_new_set in
- set,)
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
-$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
- ac_cache_corrupted=: ;;
- ,set)
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
-$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
- ac_cache_corrupted=: ;;
- ,);;
- *)
+# Test code for whether the C compiler supports C89 (global declarations)
+ac_c_conftest_c89_globals='
+/* Does the compiler advertise C89 conformance?
+ Do not test the value of __STDC__, because some compilers set it to 0
+ while being otherwise adequately conformant. */
+#if !defined __STDC__
+# error "Compiler does not advertise C89 conformance"
+#endif
+
+#include <stddef.h>
+#include <stdarg.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7 src/conf.sh. */
+struct buf { int x; };
+struct buf * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not \xHH hex character constants.
+ These do not provoke an error unfortunately, instead are silently treated
+ as an "x". The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously \x00 != x always comes out true, for an
+ array size at least. It is necessary to write \x00 == 0 to get something
+ that is true only with -std. */
+int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) '\''x'\''
+int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int),
+ int, int);'
+
+# Test code for whether the C compiler supports C89 (body of main).
+ac_c_conftest_c89_main='
+ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]);
+'
+
+# Test code for whether the C compiler supports C99 (global declarations)
+ac_c_conftest_c99_globals='
+// Does the compiler advertise C99 conformance?
+#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L
+# error "Compiler does not advertise C99 conformance"
+#endif
+
+#include <stdbool.h>
+extern int puts (const char *);
+extern int printf (const char *, ...);
+extern int dprintf (int, const char *, ...);
+extern void *malloc (size_t);
+
+// Check varargs macros. These examples are taken from C99 6.10.3.5.
+// dprintf is used instead of fprintf to avoid needing to declare
+// FILE and stderr.
+#define debug(...) dprintf (2, __VA_ARGS__)
+#define showlist(...) puts (#__VA_ARGS__)
+#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
+static void
+test_varargs_macros (void)
+{
+ int x = 1234;
+ int y = 5678;
+ debug ("Flag");
+ debug ("X = %d\n", x);
+ showlist (The first, second, and third items.);
+ report (x>y, "x is %d but y is %d", x, y);
+}
+
+// Check long long types.
+#define BIG64 18446744073709551615ull
+#define BIG32 4294967295ul
+#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
+#if !BIG_OK
+ #error "your preprocessor is broken"
+#endif
+#if BIG_OK
+#else
+ #error "your preprocessor is broken"
+#endif
+static long long int bignum = -9223372036854775807LL;
+static unsigned long long int ubignum = BIG64;
+
+struct incomplete_array
+{
+ int datasize;
+ double data[];
+};
+
+struct named_init {
+ int number;
+ const wchar_t *name;
+ double average;
+};
+
+typedef const char *ccp;
+
+static inline int
+test_restrict (ccp restrict text)
+{
+ // See if C++-style comments work.
+ // Iterate through items via the restricted pointer.
+ // Also check for declarations in for loops.
+ for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i)
+ continue;
+ return 0;
+}
+
+// Check varargs and va_copy.
+static bool
+test_varargs (const char *format, ...)
+{
+ va_list args;
+ va_start (args, format);
+ va_list args_copy;
+ va_copy (args_copy, args);
+
+ const char *str = "";
+ int number = 0;
+ float fnumber = 0;
+
+ while (*format)
+ {
+ switch (*format++)
+ {
+ case '\''s'\'': // string
+ str = va_arg (args_copy, const char *);
+ break;
+ case '\''d'\'': // int
+ number = va_arg (args_copy, int);
+ break;
+ case '\''f'\'': // float
+ fnumber = va_arg (args_copy, double);
+ break;
+ default:
+ break;
+ }
+ }
+ va_end (args_copy);
+ va_end (args);
+
+ return *str && number && fnumber;
+}
+'
+
+# Test code for whether the C compiler supports C99 (body of main).
+ac_c_conftest_c99_main='
+ // Check bool.
+ _Bool success = false;
+ success |= (argc != 0);
+
+ // Check restrict.
+ if (test_restrict ("String literal") == 0)
+ success = true;
+ char *restrict newvar = "Another string";
+
+ // Check varargs.
+ success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234);
+ test_varargs_macros ();
+
+ // Check flexible array members.
+ struct incomplete_array *ia =
+ malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
+ ia->datasize = 10;
+ for (int i = 0; i < ia->datasize; ++i)
+ ia->data[i] = i * 1.234;
+
+ // Check named initializers.
+ struct named_init ni = {
+ .number = 34,
+ .name = L"Test wide string",
+ .average = 543.34343,
+ };
+
+ ni.number = 58;
+
+ int dynamic_array[ni.number];
+ dynamic_array[0] = argv[0][0];
+ dynamic_array[ni.number - 1] = 543;
+
+ // work around unused variable warnings
+ ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\''
+ || dynamic_array[ni.number - 1] != 543);
+'
+
+# Test code for whether the C compiler supports C11 (global declarations)
+ac_c_conftest_c11_globals='
+// Does the compiler advertise C11 conformance?
+#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L
+# error "Compiler does not advertise C11 conformance"
+#endif
+
+// Check _Alignas.
+char _Alignas (double) aligned_as_double;
+char _Alignas (0) no_special_alignment;
+extern char aligned_as_int;
+char _Alignas (0) _Alignas (int) aligned_as_int;
+
+// Check _Alignof.
+enum
+{
+ int_alignment = _Alignof (int),
+ int_array_alignment = _Alignof (int[100]),
+ char_alignment = _Alignof (char)
+};
+_Static_assert (0 < -_Alignof (int), "_Alignof is signed");
+
+// Check _Noreturn.
+int _Noreturn does_not_return (void) { for (;;) continue; }
+
+// Check _Static_assert.
+struct test_static_assert
+{
+ int x;
+ _Static_assert (sizeof (int) <= sizeof (long int),
+ "_Static_assert does not work in struct");
+ long int y;
+};
+
+// Check UTF-8 literals.
+#define u8 syntax error!
+char const utf8_literal[] = u8"happens to be ASCII" "another string";
+
+// Check duplicate typedefs.
+typedef long *long_ptr;
+typedef long int *long_ptr;
+typedef long_ptr long_ptr;
+
+// Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1.
+struct anonymous
+{
+ union {
+ struct { int i; int j; };
+ struct { int k; long int l; } w;
+ };
+ int m;
+} v1;
+'
+
+# Test code for whether the C compiler supports C11 (body of main).
+ac_c_conftest_c11_main='
+ _Static_assert ((offsetof (struct anonymous, i)
+ == offsetof (struct anonymous, w.k)),
+ "Anonymous union alignment botch");
+ v1.i = 2;
+ v1.w.k = 5;
+ ok |= v1.i != 5;
+'
+
+# Test code for whether the C compiler supports C11 (complete).
+ac_c_conftest_c11_program="${ac_c_conftest_c89_globals}
+${ac_c_conftest_c99_globals}
+${ac_c_conftest_c11_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_c_conftest_c89_main}
+ ${ac_c_conftest_c99_main}
+ ${ac_c_conftest_c11_main}
+ return ok;
+}
+"
+
+# Test code for whether the C compiler supports C99 (complete).
+ac_c_conftest_c99_program="${ac_c_conftest_c89_globals}
+${ac_c_conftest_c99_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_c_conftest_c89_main}
+ ${ac_c_conftest_c99_main}
+ return ok;
+}
+"
+
+# Test code for whether the C compiler supports C89 (complete).
+ac_c_conftest_c89_program="${ac_c_conftest_c89_globals}
+
+int
+main (int argc, char **argv)
+{
+ int ok = 0;
+ ${ac_c_conftest_c89_main}
+ return ok;
+}
+"
+
+as_fn_append ac_header_c_list " stdio.h stdio_h HAVE_STDIO_H"
+as_fn_append ac_header_c_list " stdlib.h stdlib_h HAVE_STDLIB_H"
+as_fn_append ac_header_c_list " string.h string_h HAVE_STRING_H"
+as_fn_append ac_header_c_list " inttypes.h inttypes_h HAVE_INTTYPES_H"
+as_fn_append ac_header_c_list " stdint.h stdint_h HAVE_STDINT_H"
+as_fn_append ac_header_c_list " strings.h strings_h HAVE_STRINGS_H"
+as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H"
+as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H"
+as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H"
+
+# Auxiliary files required by this configure script.
+ac_aux_files="install-sh config.guess config.sub"
+
+# Locations in which to look for auxiliary files.
+ac_aux_dir_candidates="${srcdir}${PATH_SEPARATOR}${srcdir}/..${PATH_SEPARATOR}${srcdir}/../.."
+
+# Search for a directory containing all of the required auxiliary files,
+# $ac_aux_files, from the $PATH-style list $ac_aux_dir_candidates.
+# If we don't find one directory that contains all the files we need,
+# we report the set of missing files from the *first* directory in
+# $ac_aux_dir_candidates and give up.
+ac_missing_aux_files=""
+ac_first_candidate=:
+printf "%s\n" "$as_me:${as_lineno-$LINENO}: looking for aux files: $ac_aux_files" >&5
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in $ac_aux_dir_candidates
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ as_found=:
+
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: trying $as_dir" >&5
+ ac_aux_dir_found=yes
+ ac_install_sh=
+ for ac_aux in $ac_aux_files
+ do
+ # As a special case, if "install-sh" is required, that requirement
+ # can be satisfied by any of "install-sh", "install.sh", or "shtool",
+ # and $ac_install_sh is set appropriately for whichever one is found.
+ if test x"$ac_aux" = x"install-sh"
+ then
+ if test -f "${as_dir}install-sh"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install-sh found" >&5
+ ac_install_sh="${as_dir}install-sh -c"
+ elif test -f "${as_dir}install.sh"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install.sh found" >&5
+ ac_install_sh="${as_dir}install.sh -c"
+ elif test -f "${as_dir}shtool"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}shtool found" >&5
+ ac_install_sh="${as_dir}shtool install -c"
+ else
+ ac_aux_dir_found=no
+ if $ac_first_candidate; then
+ ac_missing_aux_files="${ac_missing_aux_files} install-sh"
+ else
+ break
+ fi
+ fi
+ else
+ if test -f "${as_dir}${ac_aux}"; then
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}${ac_aux} found" >&5
+ else
+ ac_aux_dir_found=no
+ if $ac_first_candidate; then
+ ac_missing_aux_files="${ac_missing_aux_files} ${ac_aux}"
+ else
+ break
+ fi
+ fi
+ fi
+ done
+ if test "$ac_aux_dir_found" = yes; then
+ ac_aux_dir="$as_dir"
+ break
+ fi
+ ac_first_candidate=false
+
+ as_found=false
+done
+IFS=$as_save_IFS
+if $as_found
+then :
+
+else $as_nop
+ as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5
+fi
+
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+if test -f "${ac_aux_dir}config.guess"; then
+ ac_config_guess="$SHELL ${ac_aux_dir}config.guess"
+fi
+if test -f "${ac_aux_dir}config.sub"; then
+ ac_config_sub="$SHELL ${ac_aux_dir}config.sub"
+fi
+if test -f "$ac_aux_dir/configure"; then
+ ac_configure="$SHELL ${ac_aux_dir}configure"
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
if test "x$ac_old_val" != "x$ac_new_val"; then
# differences in whitespace do not lead to failure.
ac_old_val_w=`echo x $ac_old_val`
ac_new_val_w=`echo x $ac_new_val`
if test "$ac_old_val_w" != "$ac_new_val_w"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
-$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+printf "%s\n" "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
ac_cache_corrupted=:
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
-$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+printf "%s\n" "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
eval $ac_var=\$ac_old_val
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
-$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
-$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+printf "%s\n" "$as_me: former value: \`$ac_old_val'" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+printf "%s\n" "$as_me: current value: \`$ac_new_val'" >&2;}
fi;;
esac
# Pass precious variables to config.status.
if test "$ac_new_set" = set; then
case $ac_new_val in
- *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
*) ac_arg=$ac_var=$ac_new_val ;;
esac
case " $ac_configure_args " in
*" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
*) as_fn_append ac_configure_args " '$ac_arg'" ;;
esac
fi
done
if $ac_cache_corrupted; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
- { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
-$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
- as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`${MAKE-make} distclean' and/or \`rm $cache_file'
+ and start over" "$LINENO" 5
fi
## -------------------- ##
## Main body of script. ##
## -------------------- ##
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
-ac_aux_dir=
-for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
- if test -f "$ac_dir/install-sh"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install-sh -c"
- break
- elif test -f "$ac_dir/install.sh"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install.sh -c"
- break
- elif test -f "$ac_dir/shtool"; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/shtool install -c"
- break
- fi
-done
-if test -z "$ac_aux_dir"; then
- as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
-fi
-# These three variables are undocumented and unsupported,
-# and are intended to be withdrawn in a future Autoconf release.
-# They can cause serious problems if a builder's source tree is in a directory
-# whose full name contains unusual characters.
-ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
-ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
-ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
-# Make sure we can run config.sub.
-$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
- as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
+ # Make sure we can run config.sub.
+$SHELL "${ac_aux_dir}config.sub" sun4 >/dev/null 2>&1 ||
+ as_fn_error $? "cannot run $SHELL ${ac_aux_dir}config.sub" "$LINENO" 5
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
-$as_echo_n "checking build system type... " >&6; }
-if ${ac_cv_build+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+printf %s "checking build system type... " >&6; }
+if test ${ac_cv_build+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_build_alias=$build_alias
test "x$ac_build_alias" = x &&
- ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+ ac_build_alias=`$SHELL "${ac_aux_dir}config.guess"`
test "x$ac_build_alias" = x &&
as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
-ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
- as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+ac_cv_build=`$SHELL "${ac_aux_dir}config.sub" $ac_build_alias` ||
+ as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $ac_build_alias failed" "$LINENO" 5
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
-$as_echo "$ac_cv_build" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+printf "%s\n" "$ac_cv_build" >&6; }
case $ac_cv_build in
*-*-*) ;;
*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
esac
build=$ac_cv_build
ac_save_IFS=$IFS; IFS='-'
set x $ac_cv_build
shift
build_cpu=$1
build_vendor=$2
shift; shift
# Remember, the first character of IFS is used to create $*,
# except with old shells:
build_os=$*
IFS=$ac_save_IFS
case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
-$as_echo_n "checking host system type... " >&6; }
-if ${ac_cv_host+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+printf %s "checking host system type... " >&6; }
+if test ${ac_cv_host+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test "x$host_alias" = x; then
ac_cv_host=$ac_cv_build
else
- ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
- as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+ ac_cv_host=`$SHELL "${ac_aux_dir}config.sub" $host_alias` ||
+ as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $host_alias failed" "$LINENO" 5
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
-$as_echo "$ac_cv_host" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+printf "%s\n" "$ac_cv_host" >&6; }
case $ac_cv_host in
*-*-*) ;;
*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
esac
host=$ac_cv_host
ac_save_IFS=$IFS; IFS='-'
set x $ac_cv_host
shift
host_cpu=$1
host_vendor=$2
shift; shift
# Remember, the first character of IFS is used to create $*,
# except with old shells:
host_os=$*
IFS=$ac_save_IFS
case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
-
# Check whether --with-gcc was given.
-if test "${with_gcc+set}" = set; then :
+if test ${with_gcc+y}
+then :
withval=$with_gcc;
fi
V_INCLS=""
if test "${srcdir}" != "." ; then
V_INCLS="-I$srcdir"
fi
if test "${CFLAGS+set}" = set; then
LBL_CFLAGS="$CFLAGS"
fi
if test -z "$CC" ; then
case "$host_os" in
bsdi*)
# Extract the first word of "shlicc2", so it can be a program name with args.
set dummy shlicc2; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_SHLICC2+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_SHLICC2+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$SHLICC2"; then
ac_cv_prog_SHLICC2="$SHLICC2" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_SHLICC2="yes"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
test -z "$ac_cv_prog_SHLICC2" && ac_cv_prog_SHLICC2="no"
fi
fi
SHLICC2=$ac_cv_prog_SHLICC2
if test -n "$SHLICC2"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SHLICC2" >&5
-$as_echo "$SHLICC2" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $SHLICC2" >&5
+printf "%s\n" "$SHLICC2" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test $SHLICC2 = yes ; then
CC=shlicc2
export CC
fi
;;
esac
fi
if test -z "$CC" -a "$with_gcc" = no ; then
CC=cc
export CC
fi
#
# Try to enable as many C99 features as we can.
# At minimum, we want C++/C99-style // comments.
#
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+
+
+
+
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
set dummy ${ac_tool_prefix}gcc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="${ac_tool_prefix}gcc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
fi
if test -z "$ac_cv_prog_CC"; then
ac_ct_CC=$CC
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$ac_ct_CC"; then
ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_CC="gcc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
-$as_echo "$ac_ct_CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_CC" = x; then
CC=""
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
CC=$ac_ct_CC
fi
else
CC="$ac_cv_prog_CC"
fi
if test -z "$CC"; then
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
set dummy ${ac_tool_prefix}cc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="${ac_tool_prefix}cc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
fi
fi
if test -z "$CC"; then
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
ac_prog_rejected=no
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
ac_prog_rejected=yes
continue
fi
ac_cv_prog_CC="cc"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
if test $ac_prog_rejected = yes; then
# We found a bogon in the path, so make sure we never use it.
set dummy $ac_cv_prog_CC
shift
if test $# != 0; then
# We chose a different compiler from the bogus one.
# However, it has the same basename, so the bogon will be chosen
# first if we set CC to just the basename; use the full file name.
shift
- ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@"
fi
fi
fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
fi
if test -z "$CC"; then
if test -n "$ac_tool_prefix"; then
for ac_prog in cl.exe
do
# Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi
fi
CC=$ac_cv_prog_CC
if test -n "$CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
test -n "$CC" && break
done
fi
if test -z "$CC"; then
ac_ct_CC=$CC
for ac_prog in cl.exe
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_CC+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$ac_ct_CC"; then
ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_CC="$ac_prog"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi
fi
ac_ct_CC=$ac_cv_prog_ac_ct_CC
if test -n "$ac_ct_CC"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
-$as_echo "$ac_ct_CC" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
test -n "$ac_ct_CC" && break
done
if test "x$ac_ct_CC" = x; then
CC=""
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args.
+set dummy ${ac_tool_prefix}clang; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}clang"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+printf "%s\n" "$CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "clang", so it can be a program name with args.
+set dummy clang; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_CC+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="clang"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+printf "%s\n" "$ac_ct_CC" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
CC=$ac_ct_CC
fi
+else
+ CC="$ac_cv_prog_CC"
fi
fi
-test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "no acceptable C compiler found in \$PATH
See \`config.log' for more details" "$LINENO" 5; }
# Provide some information about the compiler.
-$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
set X $ac_compile
ac_compiler=$2
-for ac_option in --version -v -V -qversion; do
+for ac_option in --version -v -V -qversion -version; do
{ { ac_try="$ac_compiler $ac_option >&5"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_compiler $ac_option >&5") 2>conftest.err
ac_status=$?
if test -s conftest.err; then
sed '10a\
... rest of stderr output deleted ...
10q' conftest.err >conftest.er1
cat conftest.er1 >&5
fi
rm -f conftest.er1 conftest.err
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
done
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
ac_clean_files_save=$ac_clean_files
ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
# Try to create an executable without -o first, disregard a.out.
# It will help us diagnose broken compilers, and finding out an intuition
# of exeext.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
-$as_echo_n "checking whether the C compiler works... " >&6; }
-ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+printf %s "checking whether the C compiler works... " >&6; }
+ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
# The possible output files:
ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
ac_rmfiles=
for ac_file in $ac_files
do
case $ac_file in
*.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
* ) ac_rmfiles="$ac_rmfiles $ac_file";;
esac
done
rm -f $ac_rmfiles
if { { ac_try="$ac_link_default"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link_default") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then :
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
# Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
# in a Makefile. We should not override ac_cv_exeext if it was cached,
# so that the user can short-circuit this test for compilers unknown to
# Autoconf.
for ac_file in $ac_files ''
do
test -f "$ac_file" || continue
case $ac_file in
*.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
;;
[ab].out )
# We found the default executable, but exeext='' is most
# certainly right.
break;;
*.* )
- if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no;
then :; else
ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
fi
# We set ac_cv_exeext here because the later test for it is not
# safe: cross compilers may not add the suffix if given an `-o'
# argument, so we may need to know it at that point already.
# Even if this section looks crufty: it has the advantage of
# actually working.
break;;
* )
break;;
esac
done
test "$ac_cv_exeext" = no && ac_cv_exeext=
-else
+else $as_nop
ac_file=''
fi
-if test -z "$ac_file"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-$as_echo "$as_me: failed program was:" >&5
+if test -z "$ac_file"
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
-{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "C compiler cannot create executables
See \`config.log' for more details" "$LINENO" 5; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
-$as_echo_n "checking for C compiler default output file name... " >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
-$as_echo "$ac_file" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+printf %s "checking for C compiler default output file name... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+printf "%s\n" "$ac_file" >&6; }
ac_exeext=$ac_cv_exeext
rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
ac_clean_files=$ac_clean_files_save
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
-$as_echo_n "checking for suffix of executables... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+printf %s "checking for suffix of executables... " >&6; }
if { { ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then :
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
# If both `conftest.exe' and `conftest' are `present' (well, observable)
# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
# work properly (i.e., refer to `conftest.exe'), while it won't with
# `rm'.
for ac_file in conftest.exe conftest conftest.*; do
test -f "$ac_file" || continue
case $ac_file in
*.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
*.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
break;;
* ) break;;
esac
done
-else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+else $as_nop
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of executables: cannot compile and link
See \`config.log' for more details" "$LINENO" 5; }
fi
rm -f conftest conftest$ac_cv_exeext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
-$as_echo "$ac_cv_exeext" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+printf "%s\n" "$ac_cv_exeext" >&6; }
rm -f conftest.$ac_ext
EXEEXT=$ac_cv_exeext
ac_exeext=$EXEEXT
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
int
-main ()
+main (void)
{
FILE *f = fopen ("conftest.out", "w");
return ferror (f) || fclose (f) != 0;
;
return 0;
}
_ACEOF
ac_clean_files="$ac_clean_files conftest.out"
# Check that the compiler produces executables we can run. If not, either
# the compiler is broken, or we cross compile.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
-$as_echo_n "checking whether we are cross compiling... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+printf %s "checking whether we are cross compiling... " >&6; }
if test "$cross_compiling" != yes; then
{ { ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_link") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }
if { ac_try='./conftest$ac_cv_exeext'
{ { case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_try") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; }; then
cross_compiling=no
else
if test "$cross_compiling" = maybe; then
cross_compiling=yes
else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "cannot run C compiled programs.
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot run C compiled programs.
If you meant to cross compile, use \`--host'.
See \`config.log' for more details" "$LINENO" 5; }
fi
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
-$as_echo "$cross_compiling" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+printf "%s\n" "$cross_compiling" >&6; }
rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
ac_clean_files=$ac_clean_files_save
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
-$as_echo_n "checking for suffix of object files... " >&6; }
-if ${ac_cv_objext+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+printf %s "checking for suffix of object files... " >&6; }
+if test ${ac_cv_objext+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
rm -f conftest.o conftest.obj
if { { ac_try="$ac_compile"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
+printf "%s\n" "$ac_try_echo"; } >&5
(eval "$ac_compile") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then :
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+then :
for ac_file in conftest.o conftest.obj conftest.*; do
test -f "$ac_file" || continue;
case $ac_file in
*.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
*) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
break;;
esac
done
-else
- $as_echo "$as_me: failed program was:" >&5
+else $as_nop
+ printf "%s\n" "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
-{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error $? "cannot compute suffix of object files: cannot compile
See \`config.log' for more details" "$LINENO" 5; }
fi
rm -f conftest.$ac_cv_objext conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
-$as_echo "$ac_cv_objext" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+printf "%s\n" "$ac_cv_objext" >&6; }
OBJEXT=$ac_cv_objext
ac_objext=$OBJEXT
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
-$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
-if ${ac_cv_c_compiler_gnu+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5
+printf %s "checking whether the compiler supports GNU C... " >&6; }
+if test ${ac_cv_c_compiler_gnu+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
#ifndef __GNUC__
choke me
#endif
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_compiler_gnu=yes
-else
+else $as_nop
ac_compiler_gnu=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_cv_c_compiler_gnu=$ac_compiler_gnu
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
-$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; }
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
if test $ac_compiler_gnu = yes; then
GCC=yes
else
GCC=
fi
-ac_test_CFLAGS=${CFLAGS+set}
+ac_test_CFLAGS=${CFLAGS+y}
ac_save_CFLAGS=$CFLAGS
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
-$as_echo_n "checking whether $CC accepts -g... " >&6; }
-if ${ac_cv_prog_cc_g+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+printf %s "checking whether $CC accepts -g... " >&6; }
+if test ${ac_cv_prog_cc_g+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_save_c_werror_flag=$ac_c_werror_flag
ac_c_werror_flag=yes
ac_cv_prog_cc_g=no
CFLAGS="-g"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_prog_cc_g=yes
-else
+else $as_nop
CFLAGS=""
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
-else
+else $as_nop
ac_c_werror_flag=$ac_save_c_werror_flag
CFLAGS="-g"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_prog_cc_g=yes
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_c_werror_flag=$ac_save_c_werror_flag
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
-$as_echo "$ac_cv_prog_cc_g" >&6; }
-if test "$ac_test_CFLAGS" = set; then
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+printf "%s\n" "$ac_cv_prog_cc_g" >&6; }
+if test $ac_test_CFLAGS; then
CFLAGS=$ac_save_CFLAGS
elif test $ac_cv_prog_cc_g = yes; then
if test "$GCC" = yes; then
CFLAGS="-g -O2"
else
CFLAGS="-g"
fi
else
if test "$GCC" = yes; then
CFLAGS="-O2"
else
CFLAGS=
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
-$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
-if ${ac_cv_prog_cc_c89+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_cv_prog_cc_c89=no
+ac_prog_cc_stdc=no
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5
+printf %s "checking for $CC option to enable C11 features... " >&6; }
+if test ${ac_cv_prog_cc_c11+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cc_c11=no
ac_save_CC=$CC
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-#include <stdarg.h>
-#include <stdio.h>
-struct stat;
-/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
-struct buf { int x; };
-FILE * (*rcsopen) (struct buf *, struct stat *, int);
-static char *e (p, i)
- char **p;
- int i;
-{
- return p[i];
-}
-static char *f (char * (*g) (char **, int), char **p, ...)
-{
- char *s;
- va_list v;
- va_start (v,p);
- s = g (p, va_arg (v,int));
- va_end (v);
- return s;
-}
-
-/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
- function prototypes and stuff, but not '\xHH' hex character constants.
- These don't provoke an error unfortunately, instead are silently treated
- as 'x'. The following induces an error, until -std is added to get
- proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
- array size at least. It's necessary to write '\x00'==0 to get something
- that's true only with -std. */
-int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+$ac_c_conftest_c11_program
+_ACEOF
+for ac_arg in '' -std=gnu11
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_prog_cc_c11=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cc_c11" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+fi
-/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
- inside strings and character constants. */
-#define FOO(x) 'x'
-int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+if test "x$ac_cv_prog_cc_c11" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cc_c11" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5
+printf "%s\n" "$ac_cv_prog_cc_c11" >&6; }
+ CC="$CC $ac_cv_prog_cc_c11"
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11
+ ac_prog_cc_stdc=c11
+fi
+fi
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5
+printf %s "checking for $CC option to enable C99 features... " >&6; }
+if test ${ac_cv_prog_cc_c99+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cc_c99=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_c_conftest_c99_program
+_ACEOF
+for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99=
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_cv_prog_cc_c99=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam
+ test "x$ac_cv_prog_cc_c99" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+fi
-int test (int i, double x);
-struct s1 {int (*f) (int a);};
-struct s2 {int (*f) (double a);};
-int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
-int argc;
-char **argv;
-int
-main ()
-{
-return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
- ;
- return 0;
-}
+if test "x$ac_cv_prog_cc_c99" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cc_c99" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
+printf "%s\n" "$ac_cv_prog_cc_c99" >&6; }
+ CC="$CC $ac_cv_prog_cc_c99"
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99
+ ac_prog_cc_stdc=c99
+fi
+fi
+if test x$ac_prog_cc_stdc = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5
+printf %s "checking for $CC option to enable C89 features... " >&6; }
+if test ${ac_cv_prog_cc_c89+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_c_conftest_c89_program
_ACEOF
-for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
- -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
do
CC="$ac_save_CC $ac_arg"
- if ac_fn_c_try_compile "$LINENO"; then :
+ if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_prog_cc_c89=$ac_arg
fi
-rm -f core conftest.err conftest.$ac_objext
+rm -f core conftest.err conftest.$ac_objext conftest.beam
test "x$ac_cv_prog_cc_c89" != "xno" && break
done
rm -f conftest.$ac_ext
CC=$ac_save_CC
-
fi
-# AC_CACHE_VAL
-case "x$ac_cv_prog_cc_c89" in
- x)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
-$as_echo "none needed" >&6; } ;;
- xno)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
-$as_echo "unsupported" >&6; } ;;
- *)
- CC="$CC $ac_cv_prog_cc_c89"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
-$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
-esac
-if test "x$ac_cv_prog_cc_c89" != xno; then :
+if test "x$ac_cv_prog_cc_c89" = xno
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+printf "%s\n" "unsupported" >&6; }
+else $as_nop
+ if test "x$ac_cv_prog_cc_c89" = x
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+printf "%s\n" "none needed" >&6; }
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+printf "%s\n" "$ac_cv_prog_cc_c89" >&6; }
+ CC="$CC $ac_cv_prog_cc_c89"
+fi
+ ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89
+ ac_prog_cc_stdc=c89
+fi
fi
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
ac_compiler_gnu=$ac_cv_c_compiler_gnu
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C99" >&5
-$as_echo_n "checking for $CC option to accept ISO C99... " >&6; }
-if ${ac_cv_prog_cc_c99+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_cv_prog_cc_c99=no
-ac_save_CC=$CC
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <wchar.h>
-#include <stdio.h>
-// Check varargs macros. These examples are taken from C99 6.10.3.5.
-#define debug(...) fprintf (stderr, __VA_ARGS__)
-#define showlist(...) puts (#__VA_ARGS__)
-#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
-static void
-test_varargs_macros (void)
-{
- int x = 1234;
- int y = 5678;
- debug ("Flag");
- debug ("X = %d\n", x);
- showlist (The first, second, and third items.);
- report (x>y, "x is %d but y is %d", x, y);
-}
+if test "$ac_cv_prog_cc_c99" = "no"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: The C compiler does not support C99; there may be compiler errors" >&5
+printf "%s\n" "$as_me: WARNING: The C compiler does not support C99; there may be compiler errors" >&2;}
+fi
-// Check long long types.
-#define BIG64 18446744073709551615ull
-#define BIG32 4294967295ul
-#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
-#if !BIG_OK
- your preprocessor is broken;
-#endif
-#if BIG_OK
-#else
- your preprocessor is broken;
-#endif
-static long long int bignum = -9223372036854775807LL;
-static unsigned long long int ubignum = BIG64;
-struct incomplete_array
-{
- int datasize;
- double data[];
-};
+ if test "$GCC" = yes ; then
+ #
+ # -Werror forces warnings to be errors.
+ #
+ ac_lbl_cc_force_warning_errors=-Werror
+ else
+ V_INCLS="$V_INCLS -I/usr/local/include"
+ LDFLAGS="$LDFLAGS -L/usr/local/lib"
-struct named_init {
- int number;
- const wchar_t *name;
- double average;
-};
+ case "$host_os" in
-typedef const char *ccp;
+ darwin*)
+ #
+ # This is assumed either to be GCC or clang, both
+ # of which use -Werror to force warnings to be errors.
+ #
+ ac_lbl_cc_force_warning_errors=-Werror
+ ;;
-static inline int
-test_restrict (ccp restrict text)
-{
- // See if C++-style comments work.
- // Iterate through items via the restricted pointer.
- // Also check for declarations in for loops.
- for (unsigned int i = 0; *(text+i) != '\0'; ++i)
- continue;
- return 0;
-}
-
-// Check varargs and va_copy.
-static void
-test_varargs (const char *format, ...)
-{
- va_list args;
- va_start (args, format);
- va_list args_copy;
- va_copy (args_copy, args);
-
- const char *str;
- int number;
- float fnumber;
-
- while (*format)
- {
- switch (*format++)
- {
- case 's': // string
- str = va_arg (args_copy, const char *);
- break;
- case 'd': // int
- number = va_arg (args_copy, int);
- break;
- case 'f': // float
- fnumber = va_arg (args_copy, double);
- break;
- default:
- break;
- }
- }
- va_end (args_copy);
- va_end (args);
-}
-
-int
-main ()
-{
-
- // Check bool.
- _Bool success = false;
-
- // Check restrict.
- if (test_restrict ("String literal") == 0)
- success = true;
- char *restrict newvar = "Another string";
-
- // Check varargs.
- test_varargs ("s, d' f .", "string", 65, 34.234);
- test_varargs_macros ();
-
- // Check flexible array members.
- struct incomplete_array *ia =
- malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
- ia->datasize = 10;
- for (int i = 0; i < ia->datasize; ++i)
- ia->data[i] = i * 1.234;
-
- // Check named initializers.
- struct named_init ni = {
- .number = 34,
- .name = L"Test wide string",
- .average = 543.34343,
- };
-
- ni.number = 58;
-
- int dynamic_array[ni.number];
- dynamic_array[ni.number - 1] = 543;
-
- // work around unused variable warnings
- return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x'
- || dynamic_array[ni.number - 1] != 543);
-
- ;
- return 0;
-}
-_ACEOF
-for ac_arg in '' -std=gnu99 -std=c99 -c99 -AC99 -D_STDC_C99= -qlanglvl=extc99
-do
- CC="$ac_save_CC $ac_arg"
- if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_prog_cc_c99=$ac_arg
-fi
-rm -f core conftest.err conftest.$ac_objext
- test "x$ac_cv_prog_cc_c99" != "xno" && break
-done
-rm -f conftest.$ac_ext
-CC=$ac_save_CC
-
-fi
-# AC_CACHE_VAL
-case "x$ac_cv_prog_cc_c99" in
- x)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
-$as_echo "none needed" >&6; } ;;
- xno)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
-$as_echo "unsupported" >&6; } ;;
- *)
- CC="$CC $ac_cv_prog_cc_c99"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
-$as_echo "$ac_cv_prog_cc_c99" >&6; } ;;
-esac
-if test "x$ac_cv_prog_cc_c99" != xno; then :
-
-fi
-
-
-if test "$ac_cv_prog_cc_c99" = "no"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: The C compiler does not support C99; there may be compiler errors" >&5
-$as_echo "$as_me: WARNING: The C compiler does not support C99; there may be compiler errors" >&2;}
-fi
-
-
-
-
- if test "$GCC" = yes ; then
- #
- # -Werror forces warnings to be errors.
- #
- ac_lbl_cc_force_warning_errors=-Werror
- else
- V_INCLS="$V_INCLS -I/usr/local/include"
- LDFLAGS="$LDFLAGS -L/usr/local/lib"
-
- case "$host_os" in
-
- darwin*)
- #
- # This is assumed either to be GCC or clang, both
- # of which use -Werror to force warnings to be errors.
- #
- ac_lbl_cc_force_warning_errors=-Werror
- ;;
-
- hpux*)
- #
- # HP C, which is what we presume we're using, doesn't
- # exit with a non-zero exit status if we hand it an
- # invalid -W flag, can't be forced to do so even with
- # +We, and doesn't handle GCC-style -W flags, so we
- # don't want to try using GCC-style -W flags.
- #
- ac_lbl_cc_dont_try_gcc_dashW=yes
- ;;
+ hpux*)
+ #
+ # HP C, which is what we presume we're using, doesn't
+ # exit with a non-zero exit status if we hand it an
+ # invalid -W flag, can't be forced to do so even with
+ # +We, and doesn't handle GCC-style -W flags, so we
+ # don't want to try using GCC-style -W flags.
+ #
+ ac_lbl_cc_dont_try_gcc_dashW=yes
+ ;;
irix*)
#
# MIPS C, which is what we presume we're using, doesn't
# necessarily exit with a non-zero exit status if we
# hand it an invalid -W flag, can't be forced to do
# so, and doesn't handle GCC-style -W flags, so we
# don't want to try using GCC-style -W flags.
#
ac_lbl_cc_dont_try_gcc_dashW=yes
#
# It also, apparently, defaults to "char" being
# unsigned, unlike most other C implementations;
# I suppose we could say "signed char" whenever
# we want to guarantee a signed "char", but let's
# just force signed chars.
#
# -xansi is normally the default, but the
# configure script was setting it; perhaps -cckr
# was the default in the Old Days. (Then again,
# that would probably be for backwards compatibility
# in the days when ANSI C was Shiny and New, i.e.
# 1989 and the early '90's, so maybe we can just
# drop support for those compilers.)
#
# -g is equivalent to -g2, which turns off
# optimization; we choose -g3, which generates
# debugging information but doesn't turn off
# optimization (even if the optimization would
# cause inaccuracies in debugging).
#
V_CCOPT="$V_CCOPT -xansi -signed -g3"
;;
osf*)
#
# Presumed to be DEC OSF/1, Digital UNIX, or
# Tru64 UNIX.
#
# The DEC C compiler, which is what we presume we're
# using, doesn't exit with a non-zero exit status if we
# hand it an invalid -W flag, can't be forced to do
# so, and doesn't handle GCC-style -W flags, so we
# don't want to try using GCC-style -W flags.
#
ac_lbl_cc_dont_try_gcc_dashW=yes
#
# -g is equivalent to -g2, which turns off
# optimization; we choose -g3, which generates
# debugging information but doesn't turn off
# optimization (even if the optimization would
# cause inaccuracies in debugging).
#
V_CCOPT="$V_CCOPT -g3"
;;
solaris*)
#
# Assumed to be Sun C, which requires -errwarn to force
# warnings to be treated as errors.
#
ac_lbl_cc_force_warning_errors=-errwarn
;;
ultrix*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking that Ultrix $CC hacks const in prototypes" >&5
-$as_echo_n "checking that Ultrix $CC hacks const in prototypes... " >&6; }
- if ${ac_cv_lbl_cc_const_proto+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking that Ultrix $CC hacks const in prototypes" >&5
+printf %s "checking that Ultrix $CC hacks const in prototypes... " >&6; }
+ if test ${ac_cv_lbl_cc_const_proto+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/types.h>
int
-main ()
+main (void)
{
struct a { int b; };
void c(const struct a *)
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
ac_cv_lbl_cc_const_proto=yes
-else
+else $as_nop
ac_cv_lbl_cc_const_proto=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_cc_const_proto" >&5
-$as_echo "$ac_cv_lbl_cc_const_proto" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_cc_const_proto" >&5
+printf "%s\n" "$ac_cv_lbl_cc_const_proto" >&6; }
if test $ac_cv_lbl_cc_const_proto = no ; then
-$as_echo "#define const /**/" >>confdefs.h
+printf "%s\n" "#define const /**/" >>confdefs.h
fi
;;
esac
V_CCOPT="$V_CCOPT -O"
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5
-$as_echo_n "checking for inline... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for inline" >&5
+printf %s "checking for inline... " >&6; }
save_CFLAGS="$CFLAGS"
CFLAGS="$V_CCOPT"
- if ${ac_cv_lbl_inline+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ if test ${ac_cv_lbl_inline+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_cv_lbl_inline=""
ac_lbl_cc_inline=no
for ac_lbl_inline in inline __inline__ __inline
do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#define inline $ac_lbl_inline
static inline struct iltest *foo(void);
struct iltest {
int iltest1;
int iltest2;
};
- static inline struct iltest *
- foo()
- {
- static struct iltest xxx;
-
- return &xxx;
- }
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_lbl_cc_inline=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- if test "$ac_lbl_cc_inline" = yes ; then
- break;
- fi
- done
- if test "$ac_lbl_cc_inline" = yes ; then
- ac_cv_lbl_inline=$ac_lbl_inline
- fi
-fi
-
- CFLAGS="$save_CFLAGS"
- if test ! -z "$ac_cv_lbl_inline" ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_inline" >&5
-$as_echo "$ac_cv_lbl_inline" >&6; }
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
- fi
-
-cat >>confdefs.h <<_ACEOF
-#define inline $ac_cv_lbl_inline
-_ACEOF
-
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
-$as_echo_n "checking how to run the C preprocessor... " >&6; }
-# On Suns, sometimes $CPP names a directory.
-if test -n "$CPP" && test -d "$CPP"; then
- CPP=
-fi
-if test -z "$CPP"; then
- if ${ac_cv_prog_CPP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- # Double quotes because CPP needs to be expanded
- for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
- do
- ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
- # Use a header file that comes with gcc, so configuring glibc
- # with a fresh cross-compiler works.
- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- # <limits.h> exists even on freestanding compilers.
- # On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp. "Syntax error" is here to catch this case.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
- Syntax error
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
-
-else
- # Broken: fails on valid input.
-continue
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
- # OK, works on sane cases. Now check whether nonexistent headers
- # can be detected and how.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ac_nonexistent.h>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
- # Broken: success on invalid input.
-continue
-else
- # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.i conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then :
- break
-fi
-
- done
- ac_cv_prog_CPP=$CPP
-
-fi
- CPP=$ac_cv_prog_CPP
-else
- ac_cv_prog_CPP=$CPP
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
-$as_echo "$CPP" >&6; }
-ac_preproc_ok=false
-for ac_c_preproc_warn_flag in '' yes
-do
- # Use a header file that comes with gcc, so configuring glibc
- # with a fresh cross-compiler works.
- # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
- # <limits.h> exists even on freestanding compilers.
- # On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp. "Syntax error" is here to catch this case.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#ifdef __STDC__
-# include <limits.h>
-#else
-# include <assert.h>
-#endif
- Syntax error
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
-
-else
- # Broken: fails on valid input.
-continue
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
- # OK, works on sane cases. Now check whether nonexistent headers
- # can be detected and how.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ac_nonexistent.h>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
- # Broken: success on invalid input.
-continue
-else
- # Passes both tests.
-ac_preproc_ok=:
-break
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-
-done
-# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
-rm -f conftest.i conftest.err conftest.$ac_ext
-if $ac_preproc_ok; then :
-
-else
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
-See \`config.log' for more details" "$LINENO" 5; }
-fi
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
-$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
-if ${ac_cv_path_GREP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if test -z "$GREP"; then
- ac_path_GREP_found=false
- # Loop through the user's path and test for each of PROGNAME-LIST
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_prog in grep ggrep; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
- as_fn_executable_p "$ac_path_GREP" || continue
-# Check for GNU ac_path_GREP and select it if it is found.
- # Check for GNU $ac_path_GREP
-case `"$ac_path_GREP" --version 2>&1` in
-*GNU*)
- ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
-*)
- ac_count=0
- $as_echo_n 0123456789 >"conftest.in"
- while :
- do
- cat "conftest.in" "conftest.in" >"conftest.tmp"
- mv "conftest.tmp" "conftest.in"
- cp "conftest.in" "conftest.nl"
- $as_echo 'GREP' >> "conftest.nl"
- "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
- diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
- as_fn_arith $ac_count + 1 && ac_count=$as_val
- if test $ac_count -gt ${ac_path_GREP_max-0}; then
- # Best one so far, save it but keep looking for a better one
- ac_cv_path_GREP="$ac_path_GREP"
- ac_path_GREP_max=$ac_count
- fi
- # 10*(2^10) chars as input seems more than enough
- test $ac_count -gt 10 && break
- done
- rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
-
- $ac_path_GREP_found && break 3
- done
- done
- done
-IFS=$as_save_IFS
- if test -z "$ac_cv_path_GREP"; then
- as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
- fi
-else
- ac_cv_path_GREP=$GREP
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
-$as_echo "$ac_cv_path_GREP" >&6; }
- GREP="$ac_cv_path_GREP"
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
-$as_echo_n "checking for egrep... " >&6; }
-if ${ac_cv_path_EGREP+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
- then ac_cv_path_EGREP="$GREP -E"
- else
- if test -z "$EGREP"; then
- ac_path_EGREP_found=false
- # Loop through the user's path and test for each of PROGNAME-LIST
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_prog in egrep; do
- for ac_exec_ext in '' $ac_executable_extensions; do
- ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
- as_fn_executable_p "$ac_path_EGREP" || continue
-# Check for GNU ac_path_EGREP and select it if it is found.
- # Check for GNU $ac_path_EGREP
-case `"$ac_path_EGREP" --version 2>&1` in
-*GNU*)
- ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
-*)
- ac_count=0
- $as_echo_n 0123456789 >"conftest.in"
- while :
- do
- cat "conftest.in" "conftest.in" >"conftest.tmp"
- mv "conftest.tmp" "conftest.in"
- cp "conftest.in" "conftest.nl"
- $as_echo 'EGREP' >> "conftest.nl"
- "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
- diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
- as_fn_arith $ac_count + 1 && ac_count=$as_val
- if test $ac_count -gt ${ac_path_EGREP_max-0}; then
- # Best one so far, save it but keep looking for a better one
- ac_cv_path_EGREP="$ac_path_EGREP"
- ac_path_EGREP_max=$ac_count
- fi
- # 10*(2^10) chars as input seems more than enough
- test $ac_count -gt 10 && break
- done
- rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
-esac
-
- $ac_path_EGREP_found && break 3
- done
- done
- done
-IFS=$as_save_IFS
- if test -z "$ac_cv_path_EGREP"; then
- as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
- fi
-else
- ac_cv_path_EGREP=$EGREP
-fi
-
- fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
-$as_echo "$ac_cv_path_EGREP" >&6; }
- EGREP="$ac_cv_path_EGREP"
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
-$as_echo_n "checking for ANSI C header files... " >&6; }
-if ${ac_cv_header_stdc+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <float.h>
-
+ static inline struct iltest *
+ foo()
+ {
+ static struct iltest xxx;
+
+ return &xxx;
+ }
int
-main ()
+main (void)
{
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_header_stdc=yes
-else
- ac_cv_header_stdc=no
+if ac_fn_c_try_compile "$LINENO"
+then :
+ ac_lbl_cc_inline=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ if test "$ac_lbl_cc_inline" = yes ; then
+ break;
+ fi
+ done
+ if test "$ac_lbl_cc_inline" = yes ; then
+ ac_cv_lbl_inline=$ac_lbl_inline
+ fi
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-if test $ac_cv_header_stdc = yes; then
- # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <string.h>
+ CFLAGS="$save_CFLAGS"
+ if test ! -z "$ac_cv_lbl_inline" ; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_inline" >&5
+printf "%s\n" "$ac_cv_lbl_inline" >&6; }
+ else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+ fi
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "memchr" >/dev/null 2>&1; then :
+printf "%s\n" "#define inline $ac_cv_lbl_inline" >>confdefs.h
-else
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-fi
+ac_header= ac_cache=
+for ac_item in $ac_header_c_list
+do
+ if test $ac_cache; then
+ ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default"
+ if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then
+ printf "%s\n" "#define $ac_item 1" >> confdefs.h
+ fi
+ ac_header= ac_cache=
+ elif test $ac_header; then
+ ac_cache=$ac_item
+ else
+ ac_header=$ac_item
+ fi
+done
-if test $ac_cv_header_stdc = yes; then
- # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdlib.h>
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "free" >/dev/null 2>&1; then :
-else
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-fi
-if test $ac_cv_header_stdc = yes; then
- # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
- if test "$cross_compiling" = yes; then :
- :
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ctype.h>
-#include <stdlib.h>
-#if ((' ' & 0x0FF) == 0x020)
-# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
-# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
-#else
-# define ISLOWER(c) \
- (('a' <= (c) && (c) <= 'i') \
- || ('j' <= (c) && (c) <= 'r') \
- || ('s' <= (c) && (c) <= 'z'))
-# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
-#endif
-#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
-int
-main ()
-{
- int i;
- for (i = 0; i < 256; i++)
- if (XOR (islower (i), ISLOWER (i))
- || toupper (i) != TOUPPER (i))
- return 2;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-else
- ac_cv_header_stdc=no
+
+if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes
+then :
+
+printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h
+
fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
- conftest.$ac_objext conftest.beam conftest.$ac_ext
+ac_fn_c_check_header_compile "$LINENO" "rpc/rpc.h" "ac_cv_header_rpc_rpc_h" "$ac_includes_default"
+if test "x$ac_cv_header_rpc_rpc_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_RPC_RPC_H 1" >>confdefs.h
+
fi
+ac_fn_c_check_header_compile "$LINENO" "rpc/rpcent.h" "ac_cv_header_rpc_rpcent_h" "$ac_includes_default"
+if test "x$ac_cv_header_rpc_rpcent_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_RPC_RPCENT_H 1" >>confdefs.h
fi
+ac_fn_c_check_header_compile "$LINENO" "net/if.h" "ac_cv_header_net_if_h" "$ac_includes_default"
+if test "x$ac_cv_header_net_if_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_NET_IF_H 1" >>confdefs.h
+
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
-$as_echo "$ac_cv_header_stdc" >&6; }
-if test $ac_cv_header_stdc = yes; then
-$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+#
+# Get the size of a void *, to know whether this is a 32-bit or 64-bit build.
+#
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5
+printf %s "checking size of void *... " >&6; }
+if test ${ac_cv_sizeof_void_p+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"
+then :
+
+else $as_nop
+ if test "$ac_cv_type_void_p" = yes; then
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (void *)
+See \`config.log' for more details" "$LINENO" 5; }
+ else
+ ac_cv_sizeof_void_p=0
+ fi
+fi
fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5
+printf "%s\n" "$ac_cv_sizeof_void_p" >&6; }
-# On IRIX 5.3, sys/types and inttypes.h are conflicting.
-for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
- inttypes.h stdint.h unistd.h
-do :
- as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+
+
+printf "%s\n" "#define SIZEOF_VOID_P $ac_cv_sizeof_void_p" >>confdefs.h
+
+
+
+#
+# Get the size of a time_t, to know whether it's 32-bit or 64-bit.
+#
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of time_t" >&5
+printf %s "checking size of time_t... " >&6; }
+if test ${ac_cv_sizeof_time_t+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (time_t))" "ac_cv_sizeof_time_t" "#include <time.h>
"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
+then :
+else $as_nop
+ if test "$ac_cv_type_time_t" = yes; then
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (time_t)
+See \`config.log' for more details" "$LINENO" 5; }
+ else
+ ac_cv_sizeof_time_t=0
+ fi
fi
-done
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_time_t" >&5
+printf "%s\n" "$ac_cv_sizeof_time_t" >&6; }
-for ac_header in fcntl.h rpc/rpc.h rpc/rpcent.h net/if.h
-do :
- as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-fi
+printf "%s\n" "#define SIZEOF_TIME_T $ac_cv_sizeof_time_t" >>confdefs.h
-done
case "$host_os" in
darwin*)
# Check whether --enable-universal was given.
-if test "${enable_universal+set}" = set; then :
+if test ${enable_universal+y}
+then :
enableval=$enable_universal;
fi
if test "$enable_universal" != "no"; then
case "$host_os" in
darwin9.*)
#
# Leopard. Build for x86 and 32-bit PowerPC, with
# x86 first. (That's what Apple does.)
#
V_CCOPT="$V_CCOPT -arch i386 -arch ppc"
LDFLAGS="$LDFLAGS -arch i386 -arch ppc"
;;
darwin10.*)
#
# Snow Leopard. Build for x86-64 and x86, with
# x86-64 first. (That's what Apple does.)
#
V_CCOPT="$V_CCOPT -arch x86_64 -arch i386"
LDFLAGS="$LDFLAGS -arch x86_64 -arch i386"
;;
esac
fi
;;
esac
+#
+# Do we have pkg-config?
+#
+
+
+
+
+
+
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
+set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_PKG_CONFIG+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ case $PKG_CONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_PKG_CONFIG="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+PKG_CONFIG=$ac_cv_path_PKG_CONFIG
+if test -n "$PKG_CONFIG"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
+printf "%s\n" "$PKG_CONFIG" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_path_PKG_CONFIG"; then
+ ac_pt_PKG_CONFIG=$PKG_CONFIG
+ # Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_ac_pt_PKG_CONFIG+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ case $ac_pt_PKG_CONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_ac_pt_PKG_CONFIG="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG
+if test -n "$ac_pt_PKG_CONFIG"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5
+printf "%s\n" "$ac_pt_PKG_CONFIG" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+ if test "x$ac_pt_PKG_CONFIG" = x; then
+ PKG_CONFIG=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ PKG_CONFIG=$ac_pt_PKG_CONFIG
+ fi
+else
+ PKG_CONFIG="$ac_cv_path_PKG_CONFIG"
+fi
+
+fi
+if test -n "$PKG_CONFIG"; then
+ _pkg_min_version=0.17.0
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5
+printf %s "checking pkg-config is at least version $_pkg_min_version... " >&6; }
+ if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+ else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+ PKG_CONFIG=""
+ fi
+fi
+
+#
+# Do we have the brew command from Homebrew?
+#
+# Extract the first word of "brew", so it can be a program name with args.
+set dummy brew; ac_word=$2
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_BREW+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ case $BREW in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_BREW="$BREW" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_BREW="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+BREW=$ac_cv_path_BREW
+if test -n "$BREW"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $BREW" >&5
+printf "%s\n" "$BREW" >&6; }
+else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+fi
+
+
# Check whether --with-smi was given.
-if test "${with_smi+set}" = set; then :
+if test ${with_smi+y}
+then :
withval=$with_smi;
-else
+else $as_nop
with_smi=yes
fi
if test "x$with_smi" != "xno" ; then
- ac_fn_c_check_header_mongrel "$LINENO" "smi.h" "ac_cv_header_smi_h" "$ac_includes_default"
-if test "x$ac_cv_header_smi_h" = xyes; then :
+ ac_fn_c_check_header_compile "$LINENO" "smi.h" "ac_cv_header_smi_h" "$ac_includes_default"
+if test "x$ac_cv_header_smi_h" = xyes
+then :
#
# OK, we found smi.h. Do we have libsmi with smiInit?
#
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for smiInit in -lsmi" >&5
-$as_echo_n "checking for smiInit in -lsmi... " >&6; }
-if ${ac_cv_lib_smi_smiInit+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for smiInit in -lsmi" >&5
+printf %s "checking for smiInit in -lsmi... " >&6; }
+if test ${ac_cv_lib_smi_smiInit+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lsmi $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char smiInit ();
int
-main ()
+main (void)
{
return smiInit ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_smi_smiInit=yes
-else
+else $as_nop
ac_cv_lib_smi_smiInit=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_smi_smiInit" >&5
-$as_echo "$ac_cv_lib_smi_smiInit" >&6; }
-if test "x$ac_cv_lib_smi_smiInit" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_smi_smiInit" >&5
+printf "%s\n" "$ac_cv_lib_smi_smiInit" >&6; }
+if test "x$ac_cv_lib_smi_smiInit" = xyes
+then :
#
# OK, we have libsmi with smiInit. Can we use it?
#
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable libsmi" >&5
-$as_echo_n "checking whether to enable libsmi... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to enable libsmi" >&5
+printf %s "checking whether to enable libsmi... " >&6; }
savedlibs="$LIBS"
LIBS="-lsmi $LIBS"
- if test "$cross_compiling" = yes; then :
+ if test "$cross_compiling" = yes
+then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not when cross-compiling" >&5
-$as_echo "not when cross-compiling" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not when cross-compiling" >&5
+printf "%s\n" "not when cross-compiling" >&6; }
LIBS="$savedlibs"
-else
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* libsmi available check */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <smi.h>
int main()
{
int current, revision, age, n;
const int required = 2;
if (smiInit(""))
exit(1);
if (strcmp(SMI_LIBRARY_VERSION, smi_library_version))
exit(2);
n = sscanf(smi_library_version, "%d:%d:%d", &current, &revision, &age);
if (n != 3)
exit(3);
if (required < current - age || required > current)
exit(4);
exit(0);
}
+
_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
+if ac_fn_c_try_run "$LINENO"
+then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
-$as_echo "#define USE_LIBSMI 1" >>confdefs.h
+printf "%s\n" "#define USE_LIBSMI 1" >>confdefs.h
-else
+else $as_nop
case $? in
- 1) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no - smiInit failed" >&5
-$as_echo "no - smiInit failed" >&6; } ;;
- 2) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no - header/library version mismatch" >&5
-$as_echo "no - header/library version mismatch" >&6; } ;;
- 3) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no - can't determine library version" >&5
-$as_echo "no - can't determine library version" >&6; } ;;
- 4) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no - too old" >&5
-$as_echo "no - too old" >&6; } ;;
- *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; } ;;
+ 1) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no - smiInit failed" >&5
+printf "%s\n" "no - smiInit failed" >&6; } ;;
+ 2) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no - header/library version mismatch" >&5
+printf "%s\n" "no - header/library version mismatch" >&6; } ;;
+ 3) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no - can't determine library version" >&5
+printf "%s\n" "no - can't determine library version" >&6; } ;;
+ 4) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no - too old" >&5
+printf "%s\n" "no - too old" >&6; } ;;
+ *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; } ;;
esac
LIBS="$savedlibs"
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
fi
fi
+fi
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to enable the instrument functions code" >&5
+printf %s "checking whether to enable the instrument functions code... " >&6; }
+# Check whether --enable-instrument-functions was given.
+if test ${enable_instrument_functions+y}
+then :
+ enableval=$enable_instrument_functions;
+else $as_nop
+ enableval=no
+fi
+
+case "$enableval" in
+yes) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for bfd_init in -lbfd" >&5
+printf %s "checking for bfd_init in -lbfd... " >&6; }
+if test ${ac_cv_lib_bfd_bfd_init+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lbfd $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+char bfd_init ();
+int
+main (void)
+{
+return bfd_init ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_bfd_bfd_init=yes
+else $as_nop
+ ac_cv_lib_bfd_bfd_init=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bfd_bfd_init" >&5
+printf "%s\n" "$ac_cv_lib_bfd_bfd_init" >&6; }
+if test "x$ac_cv_lib_bfd_bfd_init" = xyes
+then :
+ true
+else $as_nop
+ as_fn_error $? "--enable-instrument-functions was given, but test for library libbfd failed. Please install the 'binutils-dev' package." "$LINENO" 5
+fi
+
+
+printf "%s\n" "#define ENABLE_INSTRUMENT_FUNCTIONS 1" >>confdefs.h
+
+ LOCALSRC="$LOCALSRC instrument-functions.c"
+ # Add '-finstrument-functions' instrumentation option to generate
+ # instrumentation calls for entry and exit to functions.
+ # Try to avoid Address Space Layout Randomization (ALSR).
+ CFLAGS="$CFLAGS -O0 -ggdb -finstrument-functions -fno-stack-protector -fno-pic"
+ LDFLAGS="$LDFLAGS -O0 -ggdb -fno-stack-protector -no-pie"
+ LIBS="$LIBS -lbfd"
+ ;;
+*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+ ;;
+esac
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable the possibly-buggy SMB printer" >&5
-$as_echo_n "checking whether to enable the possibly-buggy SMB printer... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to enable the possibly-buggy SMB printer" >&5
+printf %s "checking whether to enable the possibly-buggy SMB printer... " >&6; }
# Check whether --enable-smb was given.
-if test "${enable_smb+set}" = set; then :
+if test ${enable_smb+y}
+then :
enableval=$enable_smb;
-else
+else $as_nop
enableval=no
fi
case "$enableval" in
-yes) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+yes) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
-$as_echo "#define ENABLE_SMB 1" >>confdefs.h
+printf "%s\n" "#define ENABLE_SMB 1" >>confdefs.h
LOCALSRC="print-smb.c smbutil.c $LOCALSRC"
;;
-*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
;;
esac
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to drop root privileges by default" >&5
+printf %s "checking whether to drop root privileges by default... " >&6; }
# Check whether --with-user was given.
-if test "${with_user+set}" = set; then :
+if test ${with_user+y}
+then :
withval=$with_user;
+else $as_nop
+ withval=no
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to drop root privileges by default" >&5
-$as_echo_n "checking whether to drop root privileges by default... " >&6; }
-if test ! -z "$with_user" ; then
+case "$withval" in #(
+ no) :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; } ;; #(
+ ''|yes) :
+ as_fn_error $? "--with-user requires a username" "$LINENO" 5 ;; #(
+ *) :
-cat >>confdefs.h <<_ACEOF
-#define WITH_USER "$withval"
-_ACEOF
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: to \"$withval\"" >&5
-$as_echo "to \"$withval\"" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
+printf "%s\n" "#define WITH_USER \"$withval\"" >>confdefs.h
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes, to user \"$withval\"" >&5
+printf "%s\n" "yes, to user \"$withval\"" >&6; }
+
+ ;;
+esac
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to chroot" >&5
+printf %s "checking whether to chroot... " >&6; }
# Check whether --with-chroot was given.
-if test "${with_chroot+set}" = set; then :
+if test ${with_chroot+y}
+then :
withval=$with_chroot;
+else $as_nop
+ withval=no
+
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to chroot" >&5
-$as_echo_n "checking whether to chroot... " >&6; }
-if test ! -z "$with_chroot" && test "$with_chroot" != "no" ; then
+case "$withval" in #(
+ no) :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; } ;; #(
+ ''|yes) :
+ as_fn_error $? "--with-chroot requires a directory" "$LINENO" 5 ;; #(
+ *) :
+
+
+printf "%s\n" "#define WITH_CHROOT \"$withval\"" >>confdefs.h
-cat >>confdefs.h <<_ACEOF
-#define WITH_CHROOT "$withval"
-_ACEOF
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes, to directory \"$withval\"" >&5
+printf "%s\n" "yes, to directory \"$withval\"" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: to \"$withval\"" >&5
-$as_echo "to \"$withval\"" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
+ ;;
+esac
# Check whether --with-sandbox-capsicum was given.
-if test "${with_sandbox_capsicum+set}" = set; then :
+if test ${with_sandbox_capsicum+y}
+then :
withval=$with_sandbox_capsicum;
fi
#
# Check whether various functions are available. If any are, set
# ac_lbl_capsicum_function_seen to yes; if any are not, set
# ac_lbl_capsicum_function_not_seen to yes.
#
# We don't check cap_rights_init(), as it's a macro, wrapping another
# function, in at least some versions of FreeBSD, and AC_CHECK_FUNCS()
# doesn't handle that.
#
# All of the ones we check for must be available in order to enable
# capsicum sandboxing.
#
# XXX - do we need to check for all of them, or are there some that, if
# present, imply others are present?
#
if test -z "$with_sandbox_capsicum" || test "$with_sandbox_capsicum" != "no" ; then
#
# First, make sure we have the required header.
#
- ac_fn_c_check_header_mongrel "$LINENO" "sys/capsicum.h" "ac_cv_header_sys_capsicum_h" "$ac_includes_default"
-if test "x$ac_cv_header_sys_capsicum_h" = xyes; then :
+ ac_fn_c_check_header_compile "$LINENO" "sys/capsicum.h" "ac_cv_header_sys_capsicum_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_capsicum_h" = xyes
+then :
#
# We do; now make sure we have the required functions.
#
- for ac_func in cap_enter cap_rights_limit cap_ioctls_limit openat
+
+ for ac_func in cap_enter cap_rights_limit cap_ioctls_limit openat
do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ as_ac_var=`printf "%s\n" "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+if eval test \"x\$"$as_ac_var"\" = x"yes"
+then :
cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+#define `printf "%s\n" "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
ac_lbl_capsicum_function_seen=yes
-else
+else $as_nop
ac_lbl_capsicum_function_not_seen=yes
fi
-done
+done
fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cap_init in -lcasper" >&5
-$as_echo_n "checking for cap_init in -lcasper... " >&6; }
-if ${ac_cv_lib_casper_cap_init+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for cap_init in -lcasper" >&5
+printf %s "checking for cap_init in -lcasper... " >&6; }
+if test ${ac_cv_lib_casper_cap_init+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lcasper $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char cap_init ();
int
-main ()
+main (void)
{
return cap_init ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_casper_cap_init=yes
-else
+else $as_nop
ac_cv_lib_casper_cap_init=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_casper_cap_init" >&5
-$as_echo "$ac_cv_lib_casper_cap_init" >&6; }
-if test "x$ac_cv_lib_casper_cap_init" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_casper_cap_init" >&5
+printf "%s\n" "$ac_cv_lib_casper_cap_init" >&6; }
+if test "x$ac_cv_lib_casper_cap_init" = xyes
+then :
LIBS="$LIBS -lcasper"
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cap_gethostbyaddr in -lcap_dns" >&5
-$as_echo_n "checking for cap_gethostbyaddr in -lcap_dns... " >&6; }
-if ${ac_cv_lib_cap_dns_cap_gethostbyaddr+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for cap_gethostbyaddr in -lcap_dns" >&5
+printf %s "checking for cap_gethostbyaddr in -lcap_dns... " >&6; }
+if test ${ac_cv_lib_cap_dns_cap_gethostbyaddr+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lcap_dns $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char cap_gethostbyaddr ();
int
-main ()
+main (void)
{
return cap_gethostbyaddr ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_cap_dns_cap_gethostbyaddr=yes
-else
+else $as_nop
ac_cv_lib_cap_dns_cap_gethostbyaddr=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_cap_dns_cap_gethostbyaddr" >&5
-$as_echo "$ac_cv_lib_cap_dns_cap_gethostbyaddr" >&6; }
-if test "x$ac_cv_lib_cap_dns_cap_gethostbyaddr" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_cap_dns_cap_gethostbyaddr" >&5
+printf "%s\n" "$ac_cv_lib_cap_dns_cap_gethostbyaddr" >&6; }
+if test "x$ac_cv_lib_cap_dns_cap_gethostbyaddr" = xyes
+then :
LIBS="$LIBS -lcap_dns"
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to sandbox using capsicum" >&5
-$as_echo_n "checking whether to sandbox using capsicum... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to sandbox using capsicum" >&5
+printf %s "checking whether to sandbox using capsicum... " >&6; }
if test "x$ac_lbl_capsicum_function_seen" = "xyes" -a "x$ac_lbl_capsicum_function_not_seen" != "xyes"; then
-$as_echo "#define HAVE_CAPSICUM 1" >>confdefs.h
+printf "%s\n" "#define HAVE_CAPSICUM 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to sandbox using Casper library" >&5
-$as_echo_n "checking whether to sandbox using Casper library... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to sandbox using Casper library" >&5
+printf %s "checking whether to sandbox using Casper library... " >&6; }
if test "x$ac_cv_lib_casper_cap_init" = "xyes" -a "x$ac_cv_lib_cap_dns_cap_gethostbyaddr" = "xyes"; then
-$as_echo "#define HAVE_CASPER 1" >>confdefs.h
+printf "%s\n" "#define HAVE_CASPER 1" >>confdefs.h
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
#
# We must check this before checking whether to check the OS's IPv6,
# support because, on some platforms (such as SunOS 5.x), the test
# program requires the extra networking libraries.
#
- # Most operating systems have gethostbyname() in the default searched
+ # Most operating systems have gethostbyaddr() in the default searched
# libraries (i.e. libc):
# Some OSes (eg. Solaris) place it in libnsl
# Some strange OSes (SINIX) have it in libsocket:
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing gethostbyname" >&5
-$as_echo_n "checking for library containing gethostbyname... " >&6; }
-if ${ac_cv_search_gethostbyname+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing gethostbyaddr" >&5
+printf %s "checking for library containing gethostbyaddr... " >&6; }
+if test ${ac_cv_search_gethostbyaddr+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char gethostbyname ();
+char gethostbyaddr ();
int
-main ()
+main (void)
{
-return gethostbyname ();
+return gethostbyaddr ();
;
return 0;
}
_ACEOF
-for ac_lib in '' nsl socket resolv; do
+for ac_lib in '' network nsl socket resolv
+do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_gethostbyname=$ac_res
+ if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_search_gethostbyaddr=$ac_res
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext
- if ${ac_cv_search_gethostbyname+:} false; then :
+ if test ${ac_cv_search_gethostbyaddr+y}
+then :
break
fi
done
-if ${ac_cv_search_gethostbyname+:} false; then :
+if test ${ac_cv_search_gethostbyaddr+y}
+then :
-else
- ac_cv_search_gethostbyname=no
+else $as_nop
+ ac_cv_search_gethostbyaddr=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gethostbyname" >&5
-$as_echo "$ac_cv_search_gethostbyname" >&6; }
-ac_res=$ac_cv_search_gethostbyname
-if test "$ac_res" != no; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gethostbyaddr" >&5
+printf "%s\n" "$ac_cv_search_gethostbyaddr" >&6; }
+ac_res=$ac_cv_search_gethostbyaddr
+if test "$ac_res" != no
+then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
fi
# Unfortunately libsocket sometimes depends on libnsl and
# AC_SEARCH_LIBS isn't up to the task of handling dependencies like this.
- if test "$ac_cv_search_gethostbyname" = "no"
+ if test "$ac_cv_search_gethostbyaddr" = "no"
then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lsocket" >&5
-$as_echo_n "checking for gethostbyname in -lsocket... " >&6; }
-if ${ac_cv_lib_socket_gethostbyname+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gethostbyaddr in -lsocket" >&5
+printf %s "checking for gethostbyaddr in -lsocket... " >&6; }
+if test ${ac_cv_lib_socket_gethostbyaddr+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lsocket -lnsl $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char gethostbyname ();
+char gethostbyaddr ();
int
-main ()
+main (void)
{
-return gethostbyname ();
+return gethostbyaddr ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_socket_gethostbyname=yes
-else
- ac_cv_lib_socket_gethostbyname=no
+if ac_fn_c_try_link "$LINENO"
+then :
+ ac_cv_lib_socket_gethostbyaddr=yes
+else $as_nop
+ ac_cv_lib_socket_gethostbyaddr=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_gethostbyname" >&5
-$as_echo "$ac_cv_lib_socket_gethostbyname" >&6; }
-if test "x$ac_cv_lib_socket_gethostbyname" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_gethostbyaddr" >&5
+printf "%s\n" "$ac_cv_lib_socket_gethostbyaddr" >&6; }
+if test "x$ac_cv_lib_socket_gethostbyaddr" = xyes
+then :
LIBS="-lsocket -lnsl $LIBS"
fi
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing socket" >&5
-$as_echo_n "checking for library containing socket... " >&6; }
-if ${ac_cv_search_socket+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing socket" >&5
+printf %s "checking for library containing socket... " >&6; }
+if test ${ac_cv_search_socket+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char socket ();
int
-main ()
+main (void)
{
return socket ();
;
return 0;
}
_ACEOF
-for ac_lib in '' socket; do
+for ac_lib in '' socket
+do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
- if ac_fn_c_try_link "$LINENO"; then :
+ if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_search_socket=$ac_res
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext
- if ${ac_cv_search_socket+:} false; then :
+ if test ${ac_cv_search_socket+y}
+then :
break
fi
done
-if ${ac_cv_search_socket+:} false; then :
+if test ${ac_cv_search_socket+y}
+then :
-else
+else $as_nop
ac_cv_search_socket=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_socket" >&5
-$as_echo "$ac_cv_search_socket" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_socket" >&5
+printf "%s\n" "$ac_cv_search_socket" >&6; }
ac_res=$ac_cv_search_socket
-if test "$ac_res" != no; then :
+if test "$ac_res" != no
+then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socket in -lsocket" >&5
-$as_echo_n "checking for socket in -lsocket... " >&6; }
-if ${ac_cv_lib_socket_socket+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for socket in -lsocket" >&5
+printf %s "checking for socket in -lsocket... " >&6; }
+if test ${ac_cv_lib_socket_socket+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lsocket -lnsl $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char socket ();
int
-main ()
+main (void)
{
return socket ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_socket_socket=yes
-else
+else $as_nop
ac_cv_lib_socket_socket=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_socket" >&5
-$as_echo "$ac_cv_lib_socket_socket" >&6; }
-if test "x$ac_cv_lib_socket_socket" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_socket" >&5
+printf "%s\n" "$ac_cv_lib_socket_socket" >&6; }
+if test "x$ac_cv_lib_socket_socket" = xyes
+then :
LIBS="-lsocket -lnsl $LIBS"
fi
fi
# DLPI needs putmsg under HPUX so test for -lstr while we're at it
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing putmsg" >&5
-$as_echo_n "checking for library containing putmsg... " >&6; }
-if ${ac_cv_search_putmsg+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing putmsg" >&5
+printf %s "checking for library containing putmsg... " >&6; }
+if test ${ac_cv_search_putmsg+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char putmsg ();
int
-main ()
+main (void)
{
return putmsg ();
;
return 0;
}
_ACEOF
-for ac_lib in '' str; do
+for ac_lib in '' str
+do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
- if ac_fn_c_try_link "$LINENO"; then :
+ if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_search_putmsg=$ac_res
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext
- if ${ac_cv_search_putmsg+:} false; then :
+ if test ${ac_cv_search_putmsg+y}
+then :
break
fi
done
-if ${ac_cv_search_putmsg+:} false; then :
+if test ${ac_cv_search_putmsg+y}
+then :
-else
+else $as_nop
ac_cv_search_putmsg=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_putmsg" >&5
-$as_echo "$ac_cv_search_putmsg" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_putmsg" >&5
+printf "%s\n" "$ac_cv_search_putmsg" >&6; }
ac_res=$ac_cv_search_putmsg
-if test "$ac_res" != no; then :
+if test "$ac_res" != no
+then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
fi
#
# Check whether AF_INET6 and struct in6_addr are defined.
# If they aren't both defined, we don't have sufficient OS
# support for IPv6, so we don't look for IPv6 support libraries,
# and we define AF_INET6 and struct in6_addr ourselves.
#
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the operating system supports IPv6" >&5
-$as_echo_n "checking whether the operating system supports IPv6... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the operating system supports IPv6" >&5
+printf %s "checking whether the operating system supports IPv6... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <string.h>
/* AF_INET6 available check */
#include <sys/types.h>
#ifdef _WIN32
#include <ws2tcpip.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#endif
#ifdef AF_INET6
void
foo(struct in6_addr *addr)
{
memset(addr, 0, sizeof (struct in6_addr));
}
#else
#error "AF_INET6 not defined"
#endif
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
-$as_echo "#define HAVE_OS_IPV6_SUPPORT 1" >>confdefs.h
+printf "%s\n" "#define HAVE_OS_IPV6_SUPPORT 1" >>confdefs.h
ipv6=yes
-else
+else $as_nop
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
ipv6=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ipv6type=unknown
ipv6lib=none
ipv6trylibc=no
if test "$ipv6" = "yes"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking ipv6 stack type" >&5
-$as_echo_n "checking ipv6 stack type... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking ipv6 stack type" >&5
+printf %s "checking ipv6 stack type... " >&6; }
for i in inria kame linux-glibc linux-libinet6 toshiba v6d zeta; do
case $i in
inria)
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+printf %s "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if test ${ac_cv_prog_CPP+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ # Double quotes because $CC needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" cpp /lib/cpp
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <limits.h>
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"
+then :
+
+else $as_nop
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"
+then :
+ # Broken: success on invalid input.
+continue
+else $as_nop
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok
+then :
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+printf "%s\n" "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <limits.h>
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"
+then :
+
+else $as_nop
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"
+then :
+ # Broken: success on invalid input.
+continue
+else $as_nop
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok
+then :
+
+else $as_nop
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+printf %s "checking for grep that handles long lines and -e... " >&6; }
+if test ${ac_cv_path_GREP+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if test -z "$GREP"; then
+ ac_path_GREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_prog in grep ggrep
+ do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_GREP" || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ printf %s 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ printf "%s\n" 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_GREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_GREP"; then
+ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+printf "%s\n" "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+printf %s "checking for egrep... " >&6; }
+if test ${ac_cv_path_EGREP+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ if test -z "$EGREP"; then
+ ac_path_EGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ for ac_prog in egrep
+ do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_EGREP" || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ printf %s 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ printf "%s\n" 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_EGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_EGREP"; then
+ as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+ fi
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+printf "%s\n" "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <netinet/in.h>
#ifdef IPV6_INRIA_VERSION
yes
#endif
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "yes" >/dev/null 2>&1; then :
+ $EGREP "yes" >/dev/null 2>&1
+then :
ipv6type=$i
fi
-rm -f conftest*
+rm -rf conftest*
;;
kame)
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <netinet/in.h>
#ifdef __KAME__
yes
#endif
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "yes" >/dev/null 2>&1; then :
+ $EGREP "yes" >/dev/null 2>&1
+then :
ipv6type=$i;
ipv6lib=inet6;
ipv6libdir=/usr/local/v6/lib;
ipv6trylibc=yes
fi
-rm -f conftest*
+rm -rf conftest*
;;
linux-glibc)
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <features.h>
#if defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1
yes
#endif
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "yes" >/dev/null 2>&1; then :
+ $EGREP "yes" >/dev/null 2>&1
+then :
ipv6type=$i
fi
-rm -f conftest*
+rm -rf conftest*
;;
linux-libinet6)
if test -d /usr/inet6 -o -f /usr/include/netinet/ip6.h; then
ipv6type=$i
ipv6lib=inet6
ipv6libdir=/usr/inet6/lib
ipv6trylibc=yes;
CFLAGS="-I/usr/inet6/include $CFLAGS"
fi
;;
toshiba)
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/param.h>
#ifdef _TOSHIBA_INET6
yes
#endif
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "yes" >/dev/null 2>&1; then :
+ $EGREP "yes" >/dev/null 2>&1
+then :
ipv6type=$i;
ipv6lib=inet6;
ipv6libdir=/usr/local/v6/lib
fi
-rm -f conftest*
+rm -rf conftest*
;;
v6d)
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include </usr/local/v6/include/sys/v6config.h>
#ifdef __V6D__
yes
#endif
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "yes" >/dev/null 2>&1; then :
+ $EGREP "yes" >/dev/null 2>&1
+then :
ipv6type=$i;
ipv6lib=v6;
ipv6libdir=/usr/local/v6/lib;
CFLAGS="-I/usr/local/v6/include $CFLAGS"
fi
-rm -f conftest*
+rm -rf conftest*
;;
zeta)
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <sys/param.h>
#ifdef _ZETA_MINAMI_INET6
yes
#endif
_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "yes" >/dev/null 2>&1; then :
+ $EGREP "yes" >/dev/null 2>&1
+then :
ipv6type=$i;
ipv6lib=inet6;
ipv6libdir=/usr/local/v6/lib
fi
-rm -f conftest*
+rm -rf conftest*
;;
esac
if test "$ipv6type" != "unknown"; then
break
fi
done
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ipv6type" >&5
-$as_echo "$ipv6type" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ipv6type" >&5
+printf "%s\n" "$ipv6type" >&6; }
fi
if test "$ipv6" = "yes" -a "$ipv6lib" != "none"; then
if test -d $ipv6libdir -a -f $ipv6libdir/lib$ipv6lib.a; then
LIBS="-L$ipv6libdir -l$ipv6lib $LIBS"
echo "You have $ipv6lib library, using it"
else
if test "$ipv6trylibc" = "yes"; then
echo "You do not have $ipv6lib library, using libc"
else
echo 'Fatal: no $ipv6lib library found. cannot continue.'
echo "You need to fetch lib$ipv6lib.a from appropriate"
echo 'ipv6 kit and compile beforehand.'
exit 1
fi
fi
fi
ac_fn_c_check_func "$LINENO" "strlcat" "ac_cv_func_strlcat"
-if test "x$ac_cv_func_strlcat" = xyes; then :
- $as_echo "#define HAVE_STRLCAT 1" >>confdefs.h
+if test "x$ac_cv_func_strlcat" = xyes
+then :
+ printf "%s\n" "#define HAVE_STRLCAT 1" >>confdefs.h
-else
+else $as_nop
case " $LIBOBJS " in
*" strlcat.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS strlcat.$ac_objext"
;;
esac
fi
-
ac_fn_c_check_func "$LINENO" "strlcpy" "ac_cv_func_strlcpy"
-if test "x$ac_cv_func_strlcpy" = xyes; then :
- $as_echo "#define HAVE_STRLCPY 1" >>confdefs.h
+if test "x$ac_cv_func_strlcpy" = xyes
+then :
+ printf "%s\n" "#define HAVE_STRLCPY 1" >>confdefs.h
-else
+else $as_nop
case " $LIBOBJS " in
*" strlcpy.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS strlcpy.$ac_objext"
;;
esac
fi
-
ac_fn_c_check_func "$LINENO" "strdup" "ac_cv_func_strdup"
-if test "x$ac_cv_func_strdup" = xyes; then :
- $as_echo "#define HAVE_STRDUP 1" >>confdefs.h
+if test "x$ac_cv_func_strdup" = xyes
+then :
+ printf "%s\n" "#define HAVE_STRDUP 1" >>confdefs.h
-else
+else $as_nop
case " $LIBOBJS " in
*" strdup.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS strdup.$ac_objext"
;;
esac
fi
-
ac_fn_c_check_func "$LINENO" "strsep" "ac_cv_func_strsep"
-if test "x$ac_cv_func_strsep" = xyes; then :
- $as_echo "#define HAVE_STRSEP 1" >>confdefs.h
+if test "x$ac_cv_func_strsep" = xyes
+then :
+ printf "%s\n" "#define HAVE_STRSEP 1" >>confdefs.h
-else
+else $as_nop
case " $LIBOBJS " in
*" strsep.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS strsep.$ac_objext"
;;
esac
fi
-
ac_fn_c_check_func "$LINENO" "getservent" "ac_cv_func_getservent"
-if test "x$ac_cv_func_getservent" = xyes; then :
- $as_echo "#define HAVE_GETSERVENT 1" >>confdefs.h
+if test "x$ac_cv_func_getservent" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETSERVENT 1" >>confdefs.h
-else
+else $as_nop
case " $LIBOBJS " in
*" getservent.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS getservent.$ac_objext"
;;
esac
fi
-
ac_fn_c_check_func "$LINENO" "getopt_long" "ac_cv_func_getopt_long"
-if test "x$ac_cv_func_getopt_long" = xyes; then :
- $as_echo "#define HAVE_GETOPT_LONG 1" >>confdefs.h
+if test "x$ac_cv_func_getopt_long" = xyes
+then :
+ printf "%s\n" "#define HAVE_GETOPT_LONG 1" >>confdefs.h
-else
+else $as_nop
case " $LIBOBJS " in
*" getopt_long.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS getopt_long.$ac_objext"
;;
esac
fi
+ac_fn_c_check_func "$LINENO" "fork" "ac_cv_func_fork"
+if test "x$ac_cv_func_fork" = xyes
+then :
+ printf "%s\n" "#define HAVE_FORK 1" >>confdefs.h
-for ac_func in fork vfork
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
+fi
+ac_fn_c_check_func "$LINENO" "vfork" "ac_cv_func_vfork"
+if test "x$ac_cv_func_vfork" = xyes
+then :
+ printf "%s\n" "#define HAVE_VFORK 1" >>confdefs.h
fi
-done
-for ac_func in setlinebuf
-do :
- ac_fn_c_check_func "$LINENO" "setlinebuf" "ac_cv_func_setlinebuf"
-if test "x$ac_cv_func_setlinebuf" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_SETLINEBUF 1
-_ACEOF
+ac_fn_c_check_func "$LINENO" "setlinebuf" "ac_cv_func_setlinebuf"
+if test "x$ac_cv_func_setlinebuf" = xyes
+then :
+ printf "%s\n" "#define HAVE_SETLINEBUF 1" >>confdefs.h
fi
-done
#
-# Make sure we have vsnprintf() and snprintf(); we require them.
+# Make sure we have snprintf(); we require it.
#
-ac_fn_c_check_func "$LINENO" "vsnprintf" "ac_cv_func_vsnprintf"
-if test "x$ac_cv_func_vsnprintf" = xyes; then :
-
-else
- as_fn_error $? "vsnprintf() is required but wasn't found" "$LINENO" 5
-fi
-
ac_fn_c_check_func "$LINENO" "snprintf" "ac_cv_func_snprintf"
-if test "x$ac_cv_func_snprintf" = xyes; then :
+if test "x$ac_cv_func_snprintf" = xyes
+then :
-else
+else $as_nop
as_fn_error $? "snprintf() is required but wasn't found" "$LINENO" 5
fi
#
-# Define HAVE_NO_PRINTF_Z to make it possible to disable test cases that
-# depend on %zu.
+# It became apparent at some point that using a suitable C99 compiler does not
+# automatically mean snprintf(3) implementation in the libc supports all the
+# modifiers and specifiers used in the project, so let's test that before the
+# build, not after.
+#
+# Testing the sizeof_t length modifier takes making an snprintf() call and
+# comparing the actual result with the expected result. If this fails, it will
+# most likely happen at run time, not compile time.
#
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether printf(3) supports the z length modifier" >&5
-$as_echo_n "checking whether printf(3) supports the z length modifier... " >&6; }
-if test "$cross_compiling" = yes; then :
+# Testing the 64-bit conversion specifiers in addition to that requires the
+# <inttypes.h> header to be present and the macros to be defined, so if this
+# fails, it will more likely happen at compile time.
+#
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether snprintf is suitable" >&5
+printf %s "checking whether snprintf is suitable... " >&6; }
+if test "$cross_compiling" = yes
+then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not while cross-compiling" >&5
-$as_echo "not while cross-compiling" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not while cross-compiling" >&5
+printf "%s\n" "not while cross-compiling" >&6; }
-else
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <stdio.h>
#include <string.h>
+#include <inttypes.h>
+#include <sys/types.h>
int main()
{
char buf[100];
+ uint64_t t = (uint64_t)1 << 32;
+
snprintf(buf, sizeof(buf), "%zu", sizeof(buf));
- return strncmp(buf, "100", sizeof(buf)) ? 1 : 0;
-}
+ if (strncmp(buf, "100", sizeof(buf)))
+ return 1;
+ snprintf(buf, sizeof(buf), "%zd", -sizeof(buf));
+ if (strncmp(buf, "-100", sizeof(buf)))
+ return 2;
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
+ snprintf(buf, sizeof(buf), "%" PRId64, -t);
+ if (strncmp(buf, "-4294967296", sizeof(buf)))
+ return 3;
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ snprintf(buf, sizeof(buf), "0o%" PRIo64, t);
+ if (strncmp(buf, "0o40000000000", sizeof(buf)))
+ return 4;
-else
+ snprintf(buf, sizeof(buf), "0x%" PRIx64, t);
+ if (strncmp(buf, "0x100000000", sizeof(buf)))
+ return 5;
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ snprintf(buf, sizeof(buf), "%" PRIu64, t);
+ if (strncmp(buf, "4294967296", sizeof(buf)))
+ return 6;
-$as_echo "#define HAVE_NO_PRINTF_Z 1" >>confdefs.h
+ return 0;
+}
+
+
+_ACEOF
+if ac_fn_c_try_run "$LINENO"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+ as_fn_error $? "The snprintf(3) implementation in this libc is not suitable,
+tcpdump would not work correctly even if it managed to compile." "$LINENO" 5
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lrpc" >&5
-$as_echo_n "checking for main in -lrpc... " >&6; }
-if ${ac_cv_lib_rpc_main+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for main in -lrpc" >&5
+printf %s "checking for main in -lrpc... " >&6; }
+if test ${ac_cv_lib_rpc_main+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lrpc $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return main ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_rpc_main=yes
-else
+else $as_nop
ac_cv_lib_rpc_main=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rpc_main" >&5
-$as_echo "$ac_cv_lib_rpc_main" >&6; }
-if test "x$ac_cv_lib_rpc_main" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBRPC 1
-_ACEOF
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rpc_main" >&5
+printf "%s\n" "$ac_cv_lib_rpc_main" >&6; }
+if test "x$ac_cv_lib_rpc_main" = xyes
+then :
+ printf "%s\n" "#define HAVE_LIBRPC 1" >>confdefs.h
LIBS="-lrpc $LIBS"
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing getrpcbynumber" >&5
-$as_echo_n "checking for library containing getrpcbynumber... " >&6; }
-if ${ac_cv_search_getrpcbynumber+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing getrpcbynumber" >&5
+printf %s "checking for library containing getrpcbynumber... " >&6; }
+if test ${ac_cv_search_getrpcbynumber+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_func_search_save_LIBS=$LIBS
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char getrpcbynumber ();
int
-main ()
+main (void)
{
return getrpcbynumber ();
;
return 0;
}
_ACEOF
-for ac_lib in '' nsl; do
+for ac_lib in '' nsl
+do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
- if ac_fn_c_try_link "$LINENO"; then :
+ if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_search_getrpcbynumber=$ac_res
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext
- if ${ac_cv_search_getrpcbynumber+:} false; then :
+ if test ${ac_cv_search_getrpcbynumber+y}
+then :
break
fi
done
-if ${ac_cv_search_getrpcbynumber+:} false; then :
+if test ${ac_cv_search_getrpcbynumber+y}
+then :
-else
+else $as_nop
ac_cv_search_getrpcbynumber=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_getrpcbynumber" >&5
-$as_echo "$ac_cv_search_getrpcbynumber" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_getrpcbynumber" >&5
+printf "%s\n" "$ac_cv_search_getrpcbynumber" >&6; }
ac_res=$ac_cv_search_getrpcbynumber
-if test "$ac_res" != no; then :
+if test "$ac_res" != no
+then :
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-$as_echo "#define HAVE_GETRPCBYNUMBER 1" >>confdefs.h
+printf "%s\n" "#define HAVE_GETRPCBYNUMBER 1" >>confdefs.h
fi
+
+
LBL_LIBS="$LIBS"
pfopen=/usr/examples/packetfilter/pfopen.c
if test -f $pfopen ; then
- for ac_func in pfopen
-do :
- ac_fn_c_check_func "$LINENO" "pfopen" "ac_cv_func_pfopen"
-if test "x$ac_cv_func_pfopen" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_PFOPEN 1
-_ACEOF
+ ac_fn_c_check_func "$LINENO" "pfopen" "ac_cv_func_pfopen"
+if test "x$ac_cv_func_pfopen" = xyes
+then :
+ printf "%s\n" "#define HAVE_PFOPEN 1" >>confdefs.h
fi
-done
if test $ac_cv_func_pfopen = "no" ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using $pfopen" >&5
-$as_echo "Using $pfopen" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: Using $pfopen" >&5
+printf "%s\n" "Using $pfopen" >&6; }
LIBS="$LIBS $pfopen"
fi
fi
libpcap=FAIL
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to look for a local libpcap" >&5
-$as_echo_n "checking whether to look for a local libpcap... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to look for a local libpcap" >&5
+printf %s "checking whether to look for a local libpcap... " >&6; }
# Check whether --enable-local-libpcap was given.
-if test "${enable_local_libpcap+set}" = set; then :
+if test ${enable_local_libpcap+y}
+then :
enableval=$enable_local_libpcap;
-else
+else $as_nop
enableval=yes
fi
case "$enableval" in
no)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
#
# Don't look for a local libpcap.
#
using_local_libpcap=no
;;
*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
#
# Look for a local pcap library.
#
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for local pcap library" >&5
-$as_echo_n "checking for local pcap library... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for local pcap library" >&5
+printf %s "checking for local pcap library... " >&6; }
lastdir=FAIL
places=`ls $srcdir/.. | sed -e 's,/$,,' -e "s,^,$srcdir/../," | \
- egrep '/libpcap-[0-9]+\.[0-9]+(\.[0-9]*)?([ab][0-9]*|-PRE-GIT|rc.)?$'`
+ $EGREP '/libpcap-[0-9]+\.[0-9]+(\.[0-9]*)?([ab][0-9]*|-PRE-GIT|rc.)?$'`
places2=`ls .. | sed -e 's,/$,,' -e "s,^,../," | \
- egrep '/libpcap-[0-9]+\.[0-9]+(\.[0-9]*)?([ab][0-9]*|-PRE-GIT|rc.)?$'`
+ $EGREP '/libpcap-[0-9]+\.[0-9]+(\.[0-9]*)?([ab][0-9]*|-PRE-GIT|rc.)?$'`
for dir in $places $srcdir/../libpcap ../libpcap $srcdir/libpcap $places2 ; do
basedir=`echo $dir | sed -e 's/[ab][0-9]*$//' | \
sed -e 's/-PRE-GIT$//' `
if test $lastdir = $basedir ; then
continue;
fi
lastdir=$dir
if test -r $dir/libpcap.a ; then
libpcap=$dir/libpcap.a
local_pcap_dir=$dir
fi
done
if test $libpcap = FAIL ; then
#
# We didn't find a local libpcap.
#
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
-$as_echo "not found" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+printf "%s\n" "not found" >&6; }
using_local_libpcap=no;
else
#
# We found a local libpcap.
#
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libpcap" >&5
-$as_echo "$libpcap" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libpcap" >&5
+printf "%s\n" "$libpcap" >&6; }
using_local_libpcap=yes
fi
;;
esac
if test $using_local_libpcap = no ; then
#
# We didn't find a local libpcap.
# Look for an installed pkg-config.
#
- if test -n "$ac_tool_prefix"; then
- # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
-set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_PKG_CONFIG+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- case $PKG_CONFIG in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
- ;;
-esac
-fi
-PKG_CONFIG=$ac_cv_path_PKG_CONFIG
-if test -n "$PKG_CONFIG"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
-$as_echo "$PKG_CONFIG" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_path_PKG_CONFIG"; then
- ac_pt_PKG_CONFIG=$PKG_CONFIG
- # Extract the first word of "pkg-config", so it can be a program name with args.
-set dummy pkg-config; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- case $ac_pt_PKG_CONFIG in
- [\\/]* | ?:[\\/]*)
- ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path.
- ;;
- *)
- as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
- IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
- break 2
- fi
-done
- done
-IFS=$as_save_IFS
-
- ;;
-esac
-fi
-ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG
-if test -n "$ac_pt_PKG_CONFIG"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5
-$as_echo "$ac_pt_PKG_CONFIG" >&6; }
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
- if test "x$ac_pt_PKG_CONFIG" = x; then
- PKG_CONFIG=""
- else
- case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
- PKG_CONFIG=$ac_pt_PKG_CONFIG
- fi
-else
- PKG_CONFIG="$ac_cv_path_PKG_CONFIG"
-fi
-
if test -n "$PKG_CONFIG" ; then
#
# We have it. Are there .pc files for libpcap?
#
# --exists was introduced in pkg-config 0.4.0; that
# dates back to late 2000, so we won't worry about
# earlier releases that lack it.
#
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether there are .pc files for libpcap" >&5
-$as_echo_n "checking whether there are .pc files for libpcap... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether there are .pc files for libpcap" >&5
+printf %s "checking whether there are .pc files for libpcap... " >&6; }
if "$PKG_CONFIG" libpcap --exists ; then
#
# Yes, so we can use pkg-config to get configuration
# information for libpcap.
#
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
pkg_config_usable=yes
else
#
# No, so we can't use pkg-config to get configuration
# information for libpcap.
#
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
pkg_config_usable=no
fi
else
#
# We don't have it, so we obviously can't use it.
#
pkg_config_usable=no
fi
if test "$pkg_config_usable" = "yes" ; then
#
# Found both - use pkg-config to get the include flags for
# libpcap and the flags to link with libpcap.
#
# Please read section 11.6 "Shell Substitutions"
# in the autoconf manual before doing anything
# to this that involves quoting. Especially note
# the statement "There is just no portable way to use
# double-quoted strings inside double-quoted back-quoted
# expressions (pfew!)."
#
cflags=`"$PKG_CONFIG" libpcap --cflags`
V_INCLS="$cflags $V_INCLS"
libpcap=`"$PKG_CONFIG" libpcap --libs`
else
#
# No pkg-config
# Look for an installed pcap-config.
#
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}pcap-config", so it can be a program name with args.
set dummy ${ac_tool_prefix}pcap-config; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_PCAP_CONFIG+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_PCAP_CONFIG+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
case $PCAP_CONFIG in
[\\/]* | ?:[\\/]*)
ac_cv_path_PCAP_CONFIG="$PCAP_CONFIG" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_path_PCAP_CONFIG="$as_dir/$ac_word$ac_exec_ext"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_PCAP_CONFIG="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
;;
esac
fi
PCAP_CONFIG=$ac_cv_path_PCAP_CONFIG
if test -n "$PCAP_CONFIG"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PCAP_CONFIG" >&5
-$as_echo "$PCAP_CONFIG" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PCAP_CONFIG" >&5
+printf "%s\n" "$PCAP_CONFIG" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
fi
if test -z "$ac_cv_path_PCAP_CONFIG"; then
ac_pt_PCAP_CONFIG=$PCAP_CONFIG
# Extract the first word of "pcap-config", so it can be a program name with args.
set dummy pcap-config; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_ac_pt_PCAP_CONFIG+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_ac_pt_PCAP_CONFIG+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
case $ac_pt_PCAP_CONFIG in
[\\/]* | ?:[\\/]*)
ac_cv_path_ac_pt_PCAP_CONFIG="$ac_pt_PCAP_CONFIG" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_path_ac_pt_PCAP_CONFIG="$as_dir/$ac_word$ac_exec_ext"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_ac_pt_PCAP_CONFIG="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
;;
esac
fi
ac_pt_PCAP_CONFIG=$ac_cv_path_ac_pt_PCAP_CONFIG
if test -n "$ac_pt_PCAP_CONFIG"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PCAP_CONFIG" >&5
-$as_echo "$ac_pt_PCAP_CONFIG" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PCAP_CONFIG" >&5
+printf "%s\n" "$ac_pt_PCAP_CONFIG" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$ac_pt_PCAP_CONFIG" = x; then
PCAP_CONFIG=""
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
PCAP_CONFIG=$ac_pt_PCAP_CONFIG
fi
else
PCAP_CONFIG="$ac_cv_path_PCAP_CONFIG"
fi
if test -n "$PCAP_CONFIG" ; then
#
# Found - use it to get the include flags for
# libpcap and the flags to link with libpcap.
#
# If this is a vendor-supplied pcap-config, which
# we define as being "a pcap-config in /usr/bin
# or /usr/ccs/bin" (the latter is for Solaris and
# Sun/Oracle Studio), there are some issues. Work
# around them.
#
if test \( "$PCAP_CONFIG" = "/usr/bin/pcap-config" \) -o \
\( "$PCAP_CONFIG" = "/usr/ccs/bin/pcap-config" \) ; then
#
# It's vendor-supplied.
#
case "$host_os" in
darwin*)
#
# This is macOS or another Darwin-based OS.
#
# That means that /usr/bin/pcap-config it
# may provide -I/usr/local/include with --cflags
# and -L/usr/local/lib with --libs, rather than
# pointing to the OS-supplied library and
# Xcode-supplied headers. Remember that, so we
# ignore those values.
#
_broken_apple_pcap_config=yes
+
+ #
+ # Furthermore:
+ #
+ # macOS Sonoma's libpcap includes stub versions
+ # of the remote-capture APIs. They are exported
+ # as "weakly linked symbols".
+ #
+ # Xcode 15 offers only a macOS Sonoma SDK, which
+ # has a .tbd file for libpcap that claims it
+ # includes those APIs. (Newer versions of macOS
+ # don't provide the system shared libraries,
+ # they only provide the dyld shared cache
+ # containing those libraries, so the OS provides
+ # SDKs that include a .tbd file to use when
+ # linking.)
+ #
+ # This means that AC_CHECK_FUNCS() will think
+ # that the remote-capture APIs are present,
+ # including pcap_open() and
+ # pcap_findalldevs_ex().
+ #
+ # However, they are *not* present in macOS
+ # Ventura and earlier, which means that building
+ # on Ventura with Xcode 15 produces executables
+ # that fail to start because one of those APIs
+ # isn't found in the system libpcap.
+ #
+ # Protecting calls to those APIs with
+ # __builtin_available() does not appear to
+ # prevent this, for some unknown reason, and it
+ # doesn't even allow the program to compile with
+ # versions of Xcode prior to Xcode 15, as the
+ # pcap.h file doesn't specify minimum OS
+ # versions for those functions.
+ #
+ # Given all that, and given that the versions of
+ # the remote-capture APIs in Sonoma are stubs
+ # that always fail, there doesn't seem to be any
+ # point in checking for pcap_open() if we're
+ # linking against the Apple libpcap.
+ #
+ # However, if we're *not* linking against the
+ # Apple libpcap, we should check for it, so that
+ # we can use it if it's present.
+ #
+ # We know this is macOS and that we're using
+ # the system-provided pcap-config to find
+ # libpcap, so we know it'll be the system
+ # libpcap, and note that we should not search
+ # for remote-capture APIs.
+ #
+ _dont_check_for_remote_apis=yes
;;
solaris*)
#
# This is Solaris 2 or later, i.e. SunOS 5.x.
#
# At least on Solaris 11; there's /usr/bin/pcap-config,
# which reports -L/usr/lib with --libs, causing
# the 32-bit libraries to be found, and there's
# /usr/bin/{64bitarch}/pcap-config, where {64bitarch}
# is a name for the 64-bit version of the instruction
# set, which reports -L /usr/lib/{64bitarch}, causing
# the 64-bit libraries to be found.
#
# So if we're building 64-bit targets, we replace
# PCAP_CONFIG with /usr/bin/{64bitarch}; we get
# {64bitarch} as the output of "isainfo -n".
#
# Are we building 32-bit or 64-bit? Get the
# size of void *, and check that.
#
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5
-$as_echo_n "checking size of void *... " >&6; }
-if ${ac_cv_sizeof_void_p+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"; then :
-
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5
+printf %s "checking size of void *... " >&6; }
+if test ${ac_cv_sizeof_void_p+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"
+then :
+
+else $as_nop
if test "$ac_cv_type_void_p" = yes; then
- { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (void *)
See \`config.log' for more details" "$LINENO" 5; }
else
ac_cv_sizeof_void_p=0
fi
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5
-$as_echo "$ac_cv_sizeof_void_p" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5
+printf "%s\n" "$ac_cv_sizeof_void_p" >&6; }
-cat >>confdefs.h <<_ACEOF
-#define SIZEOF_VOID_P $ac_cv_sizeof_void_p
-_ACEOF
+printf "%s\n" "#define SIZEOF_VOID_P $ac_cv_sizeof_void_p" >>confdefs.h
if test ac_cv_sizeof_void_p -eq 8 ; then
isainfo_output=`isainfo -n`
if test ! -z "$isainfo_output" ; then
#
# Success - change PCAP_CONFIG.
#
PCAP_CONFIG=`echo $PCAP_CONFIG | sed "s;/bin/;/bin/$isainfo_output/;"`
fi
fi
;;
esac
fi
#
# Please read section 11.6 "Shell Substitutions"
# in the autoconf manual before doing anything
# to this that involves quoting. Especially note
# the statement "There is just no portable way to use
# double-quoted strings inside double-quoted back-quoted
# expressions (pfew!)."
#
cflags=`"$PCAP_CONFIG" --cflags`
#
# Work around macOS (and probably other Darwin) brokenness,
# by not adding /usr/local/include if it's from the broken
# Apple pcap-config.
#
if test "$_broken_apple_pcap_config" = "yes" ; then
#
# Strip -I/usr/local/include with sed.
#
cflags=`echo $cflags | sed 's;-I/usr/local/include;;'`
fi
V_INCLS="$cflags $V_INCLS"
libpcap=`"$PCAP_CONFIG" --libs`
#
# Work around macOS (and probably other Darwin) brokenness,
# by not adding /usr/local/lib if it's from the broken
# Apple pcap-config.
#
if test "$_broken_apple_pcap_config" = "yes" ; then
#
# Strip -L/usr/local/lib with sed.
#
libpcap=`echo $libpcap | sed 's;-L/usr/local/lib;;'`
fi
else
#
# Not found; look for an installed pcap.
#
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lpcap" >&5
-$as_echo_n "checking for main in -lpcap... " >&6; }
-if ${ac_cv_lib_pcap_main+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for main in -lpcap" >&5
+printf %s "checking for main in -lpcap... " >&6; }
+if test ${ac_cv_lib_pcap_main+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lpcap $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
return main ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_pcap_main=yes
-else
+else $as_nop
ac_cv_lib_pcap_main=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pcap_main" >&5
-$as_echo "$ac_cv_lib_pcap_main" >&6; }
-if test "x$ac_cv_lib_pcap_main" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pcap_main" >&5
+printf "%s\n" "$ac_cv_lib_pcap_main" >&6; }
+if test "x$ac_cv_lib_pcap_main" = xyes
+then :
libpcap="-lpcap"
fi
if test $libpcap = FAIL ; then
- as_fn_error $? "see the INSTALL doc for more info" "$LINENO" 5
+ as_fn_error $? "see the INSTALL.md file for more info" "$LINENO" 5
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for extraneous pcap header directories" >&5
-$as_echo_n "checking for extraneous pcap header directories... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for extraneous pcap header directories" >&5
+printf %s "checking for extraneous pcap header directories... " >&6; }
if test \( ! -r /usr/local/include/pcap.h \) -a \
\( ! -r /usr/include/pcap.h \); then
if test -r /usr/local/include/pcap/pcap.h; then
d="/usr/local/include/pcap"
elif test -r /usr/include/pcap/pcap.h; then
d="/usr/include/pcap"
fi
fi
if test -z "$d" ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
-$as_echo "not found" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+printf "%s\n" "not found" >&6; }
else
V_INCLS="-I$d $V_INCLS"
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: found -- -I$d added" >&5
-$as_echo "found -- -I$d added" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: found -- -I$d added" >&5
+printf "%s\n" "found -- -I$d added" >&6; }
fi
fi
fi
else
#
# We found a local libpcap. Add it to the dependencies for
# tcpdump.
#
V_PCAPDEP=$libpcap
#
# Look for its pcap-config script.
#
# Extract the first word of "pcap-config", so it can be a program name with args.
set dummy pcap-config; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_path_PCAP_CONFIG+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_path_PCAP_CONFIG+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
case $PCAP_CONFIG in
[\\/]* | ?:[\\/]*)
ac_cv_path_PCAP_CONFIG="$PCAP_CONFIG" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $local_pcap_dir
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
- ac_cv_path_PCAP_CONFIG="$as_dir/$ac_word$ac_exec_ext"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
+ ac_cv_path_PCAP_CONFIG="$as_dir$ac_word$ac_exec_ext"
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
;;
esac
fi
PCAP_CONFIG=$ac_cv_path_PCAP_CONFIG
if test -n "$PCAP_CONFIG"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PCAP_CONFIG" >&5
-$as_echo "$PCAP_CONFIG" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PCAP_CONFIG" >&5
+printf "%s\n" "$PCAP_CONFIG" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test -n "$PCAP_CONFIG"; then
#
# We don't want its --cflags or --libs output, because
# those presume it's installed. For the C compiler flags,
# we add the source directory for the local libpcap, so
# we pick up its header files.
#
# We do, however, want its additional libraries, as required
# when linking statically, because it makes calls to
# routines in those libraries, so we'll need to link with
# them, because we'll be linking statically with it.
#
# If it supports --static-pcap-only. use that, as we will be
# linking with a static libpcap but won't be linking
# statically with any of the libraries on which it depends;
# those libraries might not even have static versions
# installed.
#
# That means we need to find out the libraries on which
# libpcap directly depends, so we can link with them, but we
# don't need to link with the libraries on which those
# libraries depend as, on all UN*Xes with which I'm
# familiar, the libraries on which a shared library depends
# are stored in the library and are automatically loaded by
# the run-time linker, without the executable having to be
# linked with those libraries. (This allows a library to be
# changed to depend on more libraries without breaking that
# library's ABI.)
#
# The only way to test for that support is to see if the
# script contains the string "static-pcap-only"; we can't
# try using that flag and checking for errors, as the
# versions of the script that didn't have that flag wouldn't
# report or return an error for an unsupported command-line
# flag. Those older versions provided, with --static, only
# the libraries on which libpcap depends, not the
# dependencies of those libraries; the versions with
# --static-pcap-only provide all the dependencies with
# --static, for the benefit of programs that are completely
# statically linked, and provide only the direct
# dependencies with --static-pcap-only.
#
- if grep -s -q "static-pcap-only" "$PCAP_CONFIG"
+ if grep "static-pcap-only" "$PCAP_CONFIG" >/dev/null 2>&1
then
static_opt="--static-pcap-only"
else
static_opt="--static"
fi
V_INCLS="-I$local_pcap_dir $V_INCLS"
additional_libs=`"$PCAP_CONFIG" $static_opt --additional-libs`
libpcap="$libpcap $additional_libs"
else
#
# It doesn't have a pcap-config script.
# Make sure it has a pcap.h file.
#
places=`ls $srcdir/.. | sed -e 's,/$,,' -e "s,^,$srcdir/../," | \
- egrep '/libpcap-[0-9]*.[0-9]*(.[0-9]*)?([ab][0-9]*)?$'`
+ $EGREP '/libpcap-[0-9]*.[0-9]*(.[0-9]*)?([ab][0-9]*)?$'`
places2=`ls .. | sed -e 's,/$,,' -e "s,^,../," | \
- egrep '/libpcap-[0-9]*.[0-9]*(.[0-9]*)?([ab][0-9]*)?$'`
+ $EGREP '/libpcap-[0-9]*.[0-9]*(.[0-9]*)?([ab][0-9]*)?$'`
pcapH=FAIL
if test -r $local_pcap_dir/pcap.h; then
pcapH=$local_pcap_dir
else
for dir in $places $srcdir/../libpcap ../libpcap $srcdir/libpcap $places2 ; do
if test -r $dir/pcap.h ; then
pcapH=$dir
fi
done
fi
if test $pcapH = FAIL ; then
- as_fn_error $? "cannot find pcap.h: see INSTALL" "$LINENO" 5
+ as_fn_error $? "cannot find pcap.h: see the INSTALL.md file" "$LINENO" 5
fi
#
# Force the compiler to look for header files in the
# directory containing pcap.h.
#
V_INCLS="-I$pcapH $V_INCLS"
fi
fi
if test -z "$PKG_CONFIG" -a -z "$PCAP_CONFIG"; then
#
# We don't have pkg-config or pcap-config; find out any additional
# link flags we need. (If we have pkg-config or pcap-config, we
# assume it tells us what we need.)
#
case "$host_os" in
aix*)
#
# If libpcap is DLPI-based, we have to use /lib/pse.exp if
# present, as we use the STREAMS routines.
#
# (XXX - true only if we're linking with a static libpcap?)
#
pseexe="/lib/pse.exp"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $pseexe" >&5
-$as_echo_n "checking for $pseexe... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $pseexe" >&5
+printf %s "checking for $pseexe... " >&6; }
if test -f $pseexe ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
LIBS="$LIBS -I:$pseexe"
fi
#
# If libpcap is BPF-based, we need "-lodm" and "-lcfg", as
# we use them to load the BPF module.
#
# (XXX - true only if we're linking with a static libpcap?)
#
LIBS="$LIBS -lodm -lcfg"
;;
solaris*)
# libdlpi is needed for Solaris 11 and later.
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlpi_walk in -ldlpi" >&5
-$as_echo_n "checking for dlpi_walk in -ldlpi... " >&6; }
-if ${ac_cv_lib_dlpi_dlpi_walk+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dlpi_walk in -ldlpi" >&5
+printf %s "checking for dlpi_walk in -ldlpi... " >&6; }
+if test ${ac_cv_lib_dlpi_dlpi_walk+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-ldlpi -L/lib $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char dlpi_walk ();
int
-main ()
+main (void)
{
return dlpi_walk ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_dlpi_dlpi_walk=yes
-else
+else $as_nop
ac_cv_lib_dlpi_dlpi_walk=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dlpi_dlpi_walk" >&5
-$as_echo "$ac_cv_lib_dlpi_dlpi_walk" >&6; }
-if test "x$ac_cv_lib_dlpi_dlpi_walk" = xyes; then :
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dlpi_dlpi_walk" >&5
+printf "%s\n" "$ac_cv_lib_dlpi_dlpi_walk" >&6; }
+if test "x$ac_cv_lib_dlpi_dlpi_walk" = xyes
+then :
LIBS="$LIBS -ldlpi" LDFLAGS="-L/lib $LDFLAGS"
fi
;;
esac
fi
LIBS="$libpcap $LIBS"
ac_fn_c_check_func "$LINENO" "pcap_loop" "ac_cv_func_pcap_loop"
-if test "x$ac_cv_func_pcap_loop" = xyes; then :
+if test "x$ac_cv_func_pcap_loop" = xyes
+then :
-else
+else $as_nop
- as_fn_error $? "This is a bug, please follow the guidelines in CONTRIBUTING.md and include the
-config.log file in your report. If you have downloaded libpcap from
+ as_fn_error $? "
+1. Do you try to build a 32-bit tcpdump with a 64-bit libpcap or vice versa?
+2. This is a bug, please follow the guidelines in CONTRIBUTING.md and include
+the config.log file in your report. If you have downloaded libpcap from
tcpdump.org, and built it yourself, please also include the config.log
file from the libpcap source directory, the Makefile from the libpcap
source directory, and the output of the make process for libpcap, as
this could be a problem with the libpcap that was built, and we will
not be able to determine why this is happening, and thus will not be
able to fix it, without that information, as we have not been able to
reproduce this problem ourselves." "$LINENO" 5
fi
#
# Check for these after AC_LBL_LIBPCAP, so we link with the appropriate
# libraries (e.g., "-lsocket -lnsl" on Solaris).
#
# You are in a twisty little maze of UN*Xes, all different.
# Some might not have ether_ntohost().
# Some might have it and declare it in <net/ethernet.h>.
# Some might have it and declare it in <netinet/ether.h>
# Some might have it and declare it in <sys/ethernet.h>.
# Some might have it and declare it in <arpa/inet.h>.
# Some might have it and declare it in <netinet/if_ether.h>.
# Some might have it and not declare it in any header file.
#
# Before you is a C compiler.
#
-for ac_func in ether_ntohost
+
+ for ac_func in ether_ntohost
do :
ac_fn_c_check_func "$LINENO" "ether_ntohost" "ac_cv_func_ether_ntohost"
-if test "x$ac_cv_func_ether_ntohost" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_ETHER_NTOHOST 1
-_ACEOF
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for buggy ether_ntohost" >&5
-$as_echo_n "checking for buggy ether_ntohost... " >&6; }
-if ${ac_cv_buggy_ether_ntohost+:} false; then :
- $as_echo_n "(cached) " >&6
-else
-
- if test "$cross_compiling" = yes; then :
+if test "x$ac_cv_func_ether_ntohost" = xyes
+then :
+ printf "%s\n" "#define HAVE_ETHER_NTOHOST 1" >>confdefs.h
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for buggy ether_ntohost" >&5
+printf %s "checking for buggy ether_ntohost... " >&6; }
+if test ${ac_cv_buggy_ether_ntohost+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+
+ if test "$cross_compiling" = yes
+then :
ac_cv_buggy_ether_ntohost="not while cross-compiling"
-else
+else $as_nop
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <netdb.h>
#include <netinet/ether.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
int
main(int argc, char **argv)
{
u_char ea[6] = { 0xff, 0xff, 0xff, 0xff, 0xff };
char name[MAXHOSTNAMELEN];
ether_ntohost(name, (struct ether_addr *)ea);
exit(0);
}
+
_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
+if ac_fn_c_try_run "$LINENO"
+then :
ac_cv_buggy_ether_ntohost=no
-else
+else $as_nop
ac_cv_buggy_ether_ntohost=yes
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
conftest.$ac_objext conftest.beam conftest.$ac_ext
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_buggy_ether_ntohost" >&5
-$as_echo "$ac_cv_buggy_ether_ntohost" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_buggy_ether_ntohost" >&5
+printf "%s\n" "$ac_cv_buggy_ether_ntohost" >&6; }
if test "$ac_cv_buggy_ether_ntohost" = "no"; then
-$as_echo "#define USE_ETHER_NTOHOST 1" >>confdefs.h
+printf "%s\n" "#define USE_ETHER_NTOHOST 1" >>confdefs.h
fi
fi
-done
+done
if test "$ac_cv_func_ether_ntohost" = yes -a \
"$ac_cv_buggy_ether_ntohost" = "no"; then
#
# OK, we have ether_ntohost(). Is it declared in <net/ethernet.h>?
#
# This test fails if we don't have <net/ethernet.h> or if we do
# but it doesn't declare ether_ntohost().
#
- ac_fn_c_check_decl "$LINENO" "ether_ntohost" "ac_cv_have_decl_ether_ntohost" "
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC options needed to detect all undeclared functions" >&5
+printf %s "checking for $CC options needed to detect all undeclared functions... " >&6; }
+if test ${ac_cv_c_undeclared_builtin_options+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
+ ac_save_CFLAGS=$CFLAGS
+ ac_cv_c_undeclared_builtin_options='cannot detect'
+ for ac_arg in '' -fno-builtin; do
+ CFLAGS="$ac_save_CFLAGS $ac_arg"
+ # This test program should *not* compile successfully.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main (void)
+{
+(void) strchr;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+
+else $as_nop
+ # This test program should compile successfully.
+ # No library function is consistently available on
+ # freestanding implementations, so test against a dummy
+ # declaration. Include always-available headers on the
+ # off chance that they somehow elicit warnings.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <float.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stddef.h>
+extern void ac_decl (int, char *);
+
+int
+main (void)
+{
+(void) ac_decl (0, (char *) 0);
+ (void) ac_decl;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+ if test x"$ac_arg" = x
+then :
+ ac_cv_c_undeclared_builtin_options='none needed'
+else $as_nop
+ ac_cv_c_undeclared_builtin_options=$ac_arg
+fi
+ break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ done
+ CFLAGS=$ac_save_CFLAGS
+
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_undeclared_builtin_options" >&5
+printf "%s\n" "$ac_cv_c_undeclared_builtin_options" >&6; }
+ case $ac_cv_c_undeclared_builtin_options in #(
+ 'cannot detect') :
+ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot make $CC report undeclared builtins
+See \`config.log' for more details" "$LINENO" 5; } ;; #(
+ 'none needed') :
+ ac_c_undeclared_builtin_options='' ;; #(
+ *) :
+ ac_c_undeclared_builtin_options=$ac_cv_c_undeclared_builtin_options ;;
+esac
+
+ac_fn_check_decl "$LINENO" "ether_ntohost" "ac_cv_have_decl_ether_ntohost" "
#include <net/ethernet.h>
-"
-if test "x$ac_cv_have_decl_ether_ntohost" = xyes; then :
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_ether_ntohost" = xyes
+then :
-$as_echo "#define NET_ETHERNET_H_DECLARES_ETHER_NTOHOST /**/" >>confdefs.h
+printf "%s\n" "#define NET_ETHERNET_H_DECLARES_ETHER_NTOHOST /**/" >>confdefs.h
fi
-
#
# Did that succeed?
#
if test "$ac_cv_have_decl_ether_ntohost" != yes; then
#
# No, how about <netinet/ether.h>, as on Linux?
#
# This test fails if we don't have <netinet/ether.h>
# or if we do but it doesn't declare ether_ntohost().
#
# Unset ac_cv_have_decl_ether_ntohost so we don't
# treat the previous failure as a cached value and
# suppress the next test.
#
unset ac_cv_have_decl_ether_ntohost
- ac_fn_c_check_decl "$LINENO" "ether_ntohost" "ac_cv_have_decl_ether_ntohost" "
+ ac_fn_check_decl "$LINENO" "ether_ntohost" "ac_cv_have_decl_ether_ntohost" "
#include <netinet/ether.h>
-"
-if test "x$ac_cv_have_decl_ether_ntohost" = xyes; then :
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_ether_ntohost" = xyes
+then :
-$as_echo "#define NETINET_ETHER_H_DECLARES_ETHER_NTOHOST /**/" >>confdefs.h
+printf "%s\n" "#define NETINET_ETHER_H_DECLARES_ETHER_NTOHOST 1" >>confdefs.h
fi
-
fi
#
# Did that succeed?
#
if test "$ac_cv_have_decl_ether_ntohost" != yes; then
#
# No, how about <sys/ethernet.h>, as on Solaris 10
# and later?
#
# This test fails if we don't have <sys/ethernet.h>
# or if we do but it doesn't declare ether_ntohost().
#
# Unset ac_cv_have_decl_ether_ntohost so we don't
# treat the previous failure as a cached value and
# suppress the next test.
#
unset ac_cv_have_decl_ether_ntohost
- ac_fn_c_check_decl "$LINENO" "ether_ntohost" "ac_cv_have_decl_ether_ntohost" "
+ ac_fn_check_decl "$LINENO" "ether_ntohost" "ac_cv_have_decl_ether_ntohost" "
#include <sys/ethernet.h>
-"
-if test "x$ac_cv_have_decl_ether_ntohost" = xyes; then :
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_ether_ntohost" = xyes
+then :
-$as_echo "#define SYS_ETHERNET_H_DECLARES_ETHER_NTOHOST /**/" >>confdefs.h
+printf "%s\n" "#define SYS_ETHERNET_H_DECLARES_ETHER_NTOHOST /**/" >>confdefs.h
fi
-
fi
#
# Did that succeed?
#
if test "$ac_cv_have_decl_ether_ntohost" != yes; then
#
# No, how about <arpa/inet.h>, as in AIX?
#
# This test fails if we don't have <arpa/inet.h>
# (if we have ether_ntohost(), we should have
# networking, and if we have networking, we should
# have <arpa/inet.h>) or if we do but it doesn't
# declare ether_ntohost().
#
# Unset ac_cv_have_decl_ether_ntohost so we don't
# treat the previous failure as a cached value and
# suppress the next test.
#
unset ac_cv_have_decl_ether_ntohost
- ac_fn_c_check_decl "$LINENO" "ether_ntohost" "ac_cv_have_decl_ether_ntohost" "
+ ac_fn_check_decl "$LINENO" "ether_ntohost" "ac_cv_have_decl_ether_ntohost" "
#include <arpa/inet.h>
-"
-if test "x$ac_cv_have_decl_ether_ntohost" = xyes; then :
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_ether_ntohost" = xyes
+then :
-$as_echo "#define ARPA_INET_H_DECLARES_ETHER_NTOHOST /**/" >>confdefs.h
+printf "%s\n" "#define ARPA_INET_H_DECLARES_ETHER_NTOHOST /**/" >>confdefs.h
fi
-
fi
#
# Did that succeed?
#
if test "$ac_cv_have_decl_ether_ntohost" != yes; then
#
# No, how about <netinet/if_ether.h>?
# On some platforms, it requires <net/if.h> and
# <netinet/in.h>, and we always include it with
# both of them, so test it with both of them.
#
# This test fails if we don't have <netinet/if_ether.h>
# and the headers we include before it, or if we do but
# <netinet/if_ether.h> doesn't declare ether_hostton().
#
# Unset ac_cv_have_decl_ether_ntohost so we don't
# treat the previous failure as a cached value and
# suppress the next test.
#
unset ac_cv_have_decl_ether_ntohost
- ac_fn_c_check_decl "$LINENO" "ether_ntohost" "ac_cv_have_decl_ether_ntohost" "
+ ac_fn_check_decl "$LINENO" "ether_ntohost" "ac_cv_have_decl_ether_ntohost" "
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
-"
-if test "x$ac_cv_have_decl_ether_ntohost" = xyes; then :
+" "$ac_c_undeclared_builtin_options" "CFLAGS"
+if test "x$ac_cv_have_decl_ether_ntohost" = xyes
+then :
-$as_echo "#define NETINET_IF_ETHER_H_DECLARES_ETHER_NTOHOST /**/" >>confdefs.h
+printf "%s\n" "#define NETINET_IF_ETHER_H_DECLARES_ETHER_NTOHOST /**/" >>confdefs.h
fi
-
fi
#
# After all that, is ether_ntohost() declared?
#
if test "$ac_cv_have_decl_ether_ntohost" = yes; then
#
# Yes.
#
-$as_echo "#define HAVE_DECL_ETHER_NTOHOST 1" >>confdefs.h
+printf "%s\n" "#define HAVE_DECL_ETHER_NTOHOST 1" >>confdefs.h
else
#
# No, we'll have to declare it ourselves.
# Do we have "struct ether_addr" if we include
# <netinet/if_ether.h>?
#
ac_fn_c_check_type "$LINENO" "struct ether_addr" "ac_cv_type_struct_ether_addr" "
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
"
-if test "x$ac_cv_type_struct_ether_addr" = xyes; then :
+if test "x$ac_cv_type_struct_ether_addr" = xyes
+then :
-cat >>confdefs.h <<_ACEOF
-#define HAVE_STRUCT_ETHER_ADDR 1
-_ACEOF
+printf "%s\n" "#define HAVE_STRUCT_ETHER_ADDR 1" >>confdefs.h
fi
fi
fi
ac_fn_c_check_func "$LINENO" "pcap_list_datalinks" "ac_cv_func_pcap_list_datalinks"
-if test "x$ac_cv_func_pcap_list_datalinks" = xyes; then :
+if test "x$ac_cv_func_pcap_list_datalinks" = xyes
+then :
-$as_echo "#define HAVE_PCAP_LIST_DATALINKS 1" >>confdefs.h
+printf "%s\n" "#define HAVE_PCAP_LIST_DATALINKS 1" >>confdefs.h
- for ac_func in pcap_free_datalinks
-do :
- ac_fn_c_check_func "$LINENO" "pcap_free_datalinks" "ac_cv_func_pcap_free_datalinks"
-if test "x$ac_cv_func_pcap_free_datalinks" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_PCAP_FREE_DATALINKS 1
-_ACEOF
+ ac_fn_c_check_func "$LINENO" "pcap_free_datalinks" "ac_cv_func_pcap_free_datalinks"
+if test "x$ac_cv_func_pcap_free_datalinks" = xyes
+then :
+ printf "%s\n" "#define HAVE_PCAP_FREE_DATALINKS 1" >>confdefs.h
fi
-done
-else
+else $as_nop
case " $LIBOBJS " in
*" datalinks.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS datalinks.$ac_objext"
;;
esac
fi
ac_fn_c_check_func "$LINENO" "pcap_datalink_name_to_val" "ac_cv_func_pcap_datalink_name_to_val"
-if test "x$ac_cv_func_pcap_datalink_name_to_val" = xyes; then :
+if test "x$ac_cv_func_pcap_datalink_name_to_val" = xyes
+then :
-$as_echo "#define HAVE_PCAP_DATALINK_NAME_TO_VAL 1" >>confdefs.h
+printf "%s\n" "#define HAVE_PCAP_DATALINK_NAME_TO_VAL 1" >>confdefs.h
ac_fn_c_check_func "$LINENO" "pcap_datalink_val_to_description" "ac_cv_func_pcap_datalink_val_to_description"
-if test "x$ac_cv_func_pcap_datalink_val_to_description" = xyes; then :
+if test "x$ac_cv_func_pcap_datalink_val_to_description" = xyes
+then :
-$as_echo "#define HAVE_PCAP_DATALINK_VAL_TO_DESCRIPTION 1" >>confdefs.h
+printf "%s\n" "#define HAVE_PCAP_DATALINK_VAL_TO_DESCRIPTION 1" >>confdefs.h
-else
+else $as_nop
case " $LIBOBJS " in
*" dlnames.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS dlnames.$ac_objext"
;;
esac
fi
-else
+else $as_nop
case " $LIBOBJS " in
*" dlnames.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS dlnames.$ac_objext"
;;
esac
fi
-for ac_func in pcap_set_datalink
-do :
- ac_fn_c_check_func "$LINENO" "pcap_set_datalink" "ac_cv_func_pcap_set_datalink"
-if test "x$ac_cv_func_pcap_set_datalink" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_PCAP_SET_DATALINK 1
-_ACEOF
+ac_fn_c_check_func "$LINENO" "pcap_set_datalink" "ac_cv_func_pcap_set_datalink"
+if test "x$ac_cv_func_pcap_set_datalink" = xyes
+then :
+ printf "%s\n" "#define HAVE_PCAP_SET_DATALINK 1" >>confdefs.h
fi
-done
-for ac_func in pcap_breakloop
-do :
- ac_fn_c_check_func "$LINENO" "pcap_breakloop" "ac_cv_func_pcap_breakloop"
-if test "x$ac_cv_func_pcap_breakloop" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_PCAP_BREAKLOOP 1
-_ACEOF
+ac_fn_c_check_func "$LINENO" "pcap_breakloop" "ac_cv_func_pcap_breakloop"
+if test "x$ac_cv_func_pcap_breakloop" = xyes
+then :
+ printf "%s\n" "#define HAVE_PCAP_BREAKLOOP 1" >>confdefs.h
fi
-done
#
# Do we have the new open API? Check for pcap_create, and assume that,
# if we do, we also have pcap_activate() and the other new routines
# introduced in libpcap 1.0.0.
#
-for ac_func in pcap_create
-do :
- ac_fn_c_check_func "$LINENO" "pcap_create" "ac_cv_func_pcap_create"
-if test "x$ac_cv_func_pcap_create" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_PCAP_CREATE 1
-_ACEOF
+ac_fn_c_check_func "$LINENO" "pcap_create" "ac_cv_func_pcap_create"
+if test "x$ac_cv_func_pcap_create" = xyes
+then :
+ printf "%s\n" "#define HAVE_PCAP_CREATE 1" >>confdefs.h
fi
-done
if test $ac_cv_func_pcap_create = "yes" ; then
#
# OK, do we have pcap_set_tstamp_type? If so, assume we have
# pcap_list_tstamp_types and pcap_free_tstamp_types as well.
#
- for ac_func in pcap_set_tstamp_type
-do :
- ac_fn_c_check_func "$LINENO" "pcap_set_tstamp_type" "ac_cv_func_pcap_set_tstamp_type"
-if test "x$ac_cv_func_pcap_set_tstamp_type" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_PCAP_SET_TSTAMP_TYPE 1
-_ACEOF
+ ac_fn_c_check_func "$LINENO" "pcap_set_tstamp_type" "ac_cv_func_pcap_set_tstamp_type"
+if test "x$ac_cv_func_pcap_set_tstamp_type" = xyes
+then :
+ printf "%s\n" "#define HAVE_PCAP_SET_TSTAMP_TYPE 1" >>confdefs.h
fi
-done
#
# And do we have pcap_set_tstamp_precision? If so, we assume
# we also have pcap_open_offline_with_tstamp_precision.
#
- for ac_func in pcap_set_tstamp_precision
-do :
- ac_fn_c_check_func "$LINENO" "pcap_set_tstamp_precision" "ac_cv_func_pcap_set_tstamp_precision"
-if test "x$ac_cv_func_pcap_set_tstamp_precision" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_PCAP_SET_TSTAMP_PRECISION 1
-_ACEOF
-
-fi
-done
-
-fi
-
-#
-# Check for a miscellaneous collection of functions which we use
-# if we have them.
-#
-for ac_func in pcap_findalldevs
-do :
- ac_fn_c_check_func "$LINENO" "pcap_findalldevs" "ac_cv_func_pcap_findalldevs"
-if test "x$ac_cv_func_pcap_findalldevs" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_PCAP_FINDALLDEVS 1
-_ACEOF
+ ac_fn_c_check_func "$LINENO" "pcap_set_tstamp_precision" "ac_cv_func_pcap_set_tstamp_precision"
+if test "x$ac_cv_func_pcap_set_tstamp_precision" = xyes
+then :
+ printf "%s\n" "#define HAVE_PCAP_SET_TSTAMP_PRECISION 1" >>confdefs.h
fi
-done
-
-if test $ac_cv_func_pcap_findalldevs = "yes" ; then
- savedcppflags="$CPPFLAGS"
- CPPFLAGS="$CPPFLAGS $V_INCLS"
- ac_fn_c_check_type "$LINENO" "pcap_if_t" "ac_cv_type_pcap_if_t" "#include <pcap.h>
-"
-if test "x$ac_cv_type_pcap_if_t" = xyes; then :
-cat >>confdefs.h <<_ACEOF
-#define HAVE_PCAP_IF_T 1
-_ACEOF
+fi
+#
+# Check for a miscellaneous collection of functions which we use
+# if we have them.
+#
+ac_fn_c_check_func "$LINENO" "pcap_findalldevs" "ac_cv_func_pcap_findalldevs"
+if test "x$ac_cv_func_pcap_findalldevs" = xyes
+then :
+ printf "%s\n" "#define HAVE_PCAP_FINDALLDEVS 1" >>confdefs.h
fi
- CPPFLAGS="$savedcppflags"
+ac_fn_c_check_func "$LINENO" "pcap_dump_flush" "ac_cv_func_pcap_dump_flush"
+if test "x$ac_cv_func_pcap_dump_flush" = xyes
+then :
+ printf "%s\n" "#define HAVE_PCAP_DUMP_FLUSH 1" >>confdefs.h
+
fi
-for ac_func in pcap_dump_flush pcap_lib_version
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
+ac_fn_c_check_func "$LINENO" "pcap_lib_version" "ac_cv_func_pcap_lib_version"
+if test "x$ac_cv_func_pcap_lib_version" = xyes
+then :
+ printf "%s\n" "#define HAVE_PCAP_LIB_VERSION 1" >>confdefs.h
fi
-done
if test $ac_cv_func_pcap_lib_version = "no" ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pcap_version is defined by libpcap" >&5
-$as_echo_n "checking whether pcap_version is defined by libpcap... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether pcap_version is defined by libpcap" >&5
+printf %s "checking whether pcap_version is defined by libpcap... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
extern char pcap_version[];
return (int)pcap_version;
;
return 0;
}
+
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_lbl_cv_pcap_version_defined=yes
-else
+else $as_nop
ac_lbl_cv_pcap_version_defined=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
if test "$ac_lbl_cv_pcap_version_defined" = yes ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
-$as_echo "#define HAVE_PCAP_VERSION 1" >>confdefs.h
+printf "%s\n" "#define HAVE_PCAP_VERSION 1" >>confdefs.h
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
fi
-for ac_func in pcap_setdirection pcap_set_immediate_mode pcap_dump_ftell64
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
+ac_fn_c_check_func "$LINENO" "pcap_setdirection" "ac_cv_func_pcap_setdirection"
+if test "x$ac_cv_func_pcap_setdirection" = xyes
+then :
+ printf "%s\n" "#define HAVE_PCAP_SETDIRECTION 1" >>confdefs.h
fi
-done
+ac_fn_c_check_func "$LINENO" "pcap_set_immediate_mode" "ac_cv_func_pcap_set_immediate_mode"
+if test "x$ac_cv_func_pcap_set_immediate_mode" = xyes
+then :
+ printf "%s\n" "#define HAVE_PCAP_SET_IMMEDIATE_MODE 1" >>confdefs.h
-for ac_func in pcap_open pcap_findalldevs_ex
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
-_ACEOF
+fi
+ac_fn_c_check_func "$LINENO" "pcap_dump_ftell64" "ac_cv_func_pcap_dump_ftell64"
+if test "x$ac_cv_func_pcap_dump_ftell64" = xyes
+then :
+ printf "%s\n" "#define HAVE_PCAP_DUMP_FTELL64 1" >>confdefs.h
fi
-done
+#
+# See the comment in AC_LBL_LIBPCAP in aclocal.m4 for the reason
+# why we don't check for remote-capture APIs if we're building
+# with the system libpcap on macOS.
+#
+if test "$_dont_check_for_remote_apis" != "yes"; then
+ ac_fn_c_check_func "$LINENO" "pcap_open" "ac_cv_func_pcap_open"
+if test "x$ac_cv_func_pcap_open" = xyes
+then :
+ printf "%s\n" "#define HAVE_PCAP_OPEN 1" >>confdefs.h
+
+fi
+ac_fn_c_check_func "$LINENO" "pcap_findalldevs_ex" "ac_cv_func_pcap_findalldevs_ex"
+if test "x$ac_cv_func_pcap_findalldevs_ex" = xyes
+then :
+ printf "%s\n" "#define HAVE_PCAP_FINDALLDEVS_EX 1" >>confdefs.h
+
+fi
+
+fi
ac_fn_c_check_func "$LINENO" "pcap_dump_ftell" "ac_cv_func_pcap_dump_ftell"
-if test "x$ac_cv_func_pcap_dump_ftell" = xyes; then :
- $as_echo "#define HAVE_PCAP_DUMP_FTELL 1" >>confdefs.h
+if test "x$ac_cv_func_pcap_dump_ftell" = xyes
+then :
+ printf "%s\n" "#define HAVE_PCAP_DUMP_FTELL 1" >>confdefs.h
-else
+else $as_nop
case " $LIBOBJS " in
*" pcap_dump_ftell.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS pcap_dump_ftell.$ac_objext"
;;
esac
fi
-
#
# Check for special debugging functions
#
-for ac_func in pcap_set_parser_debug
-do :
- ac_fn_c_check_func "$LINENO" "pcap_set_parser_debug" "ac_cv_func_pcap_set_parser_debug"
-if test "x$ac_cv_func_pcap_set_parser_debug" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_PCAP_SET_PARSER_DEBUG 1
-_ACEOF
+ac_fn_c_check_func "$LINENO" "pcap_set_parser_debug" "ac_cv_func_pcap_set_parser_debug"
+if test "x$ac_cv_func_pcap_set_parser_debug" = xyes
+then :
+ printf "%s\n" "#define HAVE_PCAP_SET_PARSER_DEBUG 1" >>confdefs.h
fi
-done
if test "$ac_cv_func_pcap_set_parser_debug" = "no" ; then
#
# OK, we don't have pcap_set_parser_debug() to set the libpcap
# filter expression parser debug flag; can we directly set the
# flag?
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pcap_debug is defined by libpcap" >&5
-$as_echo_n "checking whether pcap_debug is defined by libpcap... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether pcap_debug is defined by libpcap" >&5
+printf %s "checking whether pcap_debug is defined by libpcap... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
extern int pcap_debug;
return pcap_debug;
;
return 0;
}
+
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_lbl_cv_pcap_debug_defined=yes
-else
+else $as_nop
ac_lbl_cv_pcap_debug_defined=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
if test "$ac_lbl_cv_pcap_debug_defined" = yes ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
-$as_echo "#define HAVE_PCAP_DEBUG 1" >>confdefs.h
+printf "%s\n" "#define HAVE_PCAP_DEBUG 1" >>confdefs.h
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
#
# OK, what about "yydebug"?
#
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether yydebug is defined by libpcap" >&5
-$as_echo_n "checking whether yydebug is defined by libpcap... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether yydebug is defined by libpcap" >&5
+printf %s "checking whether yydebug is defined by libpcap... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int
-main ()
+main (void)
{
extern int yydebug;
return yydebug;
;
return 0;
}
+
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_lbl_cv_yydebug_defined=yes
-else
+else $as_nop
ac_lbl_cv_yydebug_defined=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
if test "$ac_lbl_cv_yydebug_defined" = yes ; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
-$as_echo "#define HAVE_YYDEBUG 1" >>confdefs.h
+printf "%s\n" "#define HAVE_YYDEBUG 1" >>confdefs.h
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
fi
fi
-for ac_func in pcap_set_optimizer_debug
-do :
- ac_fn_c_check_func "$LINENO" "pcap_set_optimizer_debug" "ac_cv_func_pcap_set_optimizer_debug"
-if test "x$ac_cv_func_pcap_set_optimizer_debug" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_PCAP_SET_OPTIMIZER_DEBUG 1
-_ACEOF
+ac_fn_c_check_func "$LINENO" "pcap_set_optimizer_debug" "ac_cv_func_pcap_set_optimizer_debug"
+if test "x$ac_cv_func_pcap_set_optimizer_debug" = xyes
+then :
+ printf "%s\n" "#define HAVE_PCAP_SET_OPTIMIZER_DEBUG 1" >>confdefs.h
fi
-done
ac_fn_c_check_func "$LINENO" "bpf_dump" "ac_cv_func_bpf_dump"
-if test "x$ac_cv_func_bpf_dump" = xyes; then :
- $as_echo "#define HAVE_BPF_DUMP 1" >>confdefs.h
+if test "x$ac_cv_func_bpf_dump" = xyes
+then :
+ printf "%s\n" "#define HAVE_BPF_DUMP 1" >>confdefs.h
-else
+else $as_nop
case " $LIBOBJS " in
*" bpf_dump.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS bpf_dump.$ac_objext"
;;
esac
fi
-
-V_GROUP=0
-if test -f /etc/group -a ! -z "`grep '^wheel:' /etc/group`" ; then
- V_GROUP=wheel
-fi
#
# Assume V7/BSD convention for man pages (file formats in section 5,
# miscellaneous info in section 7).
#
MAN_FILE_FORMATS=5
MAN_MISC_INFO=7
case "$host_os" in
aix*)
-$as_echo "#define _SUN 1" >>confdefs.h
+printf "%s\n" "#define _SUN 1" >>confdefs.h
;;
hpux*)
#
# Use System V conventions for man pages.
#
MAN_FILE_FORMATS=4
MAN_MISC_INFO=5
;;
irix*)
V_GROUP=sys
#
# Use System V conventions for man pages.
#
MAN_FILE_FORMATS=4
MAN_MISC_INFO=5
;;
osf*)
V_GROUP=system
#
# Use System V conventions for man pages.
#
MAN_FILE_FORMATS=4
MAN_MISC_INFO=5
;;
solaris*)
- V_GROUP=sys
-
#
# Use System V conventions for man pages.
#
MAN_FILE_FORMATS=4
MAN_MISC_INFO=5
;;
esac
-if test -f /dev/bpf0 ; then
- V_GROUP=bpf
-fi
-
#
# Make sure we have a definition for C99's uintptr_t (regardless of
# whether the environment is a C99 environment or not).
#
ac_fn_c_check_type "$LINENO" "uintptr_t" "ac_cv_type_uintptr_t" "$ac_includes_default"
-if test "x$ac_cv_type_uintptr_t" = xyes; then :
+if test "x$ac_cv_type_uintptr_t" = xyes
+then :
-$as_echo "#define HAVE_UINTPTR_T 1" >>confdefs.h
+printf "%s\n" "#define HAVE_UINTPTR_T 1" >>confdefs.h
-else
+else $as_nop
for ac_type in 'unsigned int' 'unsigned long int' \
'unsigned long long int'; do
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
$ac_includes_default
int
-main ()
+main (void)
{
static int test_array [1 - 2 * !(sizeof (void *) <= sizeof ($ac_type))];
test_array [0] = 0;
return test_array [0];
;
return 0;
}
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
-cat >>confdefs.h <<_ACEOF
-#define uintptr_t $ac_type
-_ACEOF
+printf "%s\n" "#define uintptr_t $ac_type" >>confdefs.h
ac_type=
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
test -z "$ac_type" && break
done
fi
+savedcppflags="$CPPFLAGS"
+CPPFLAGS="$CPPFLAGS $V_INCLS"
+
#
# Check whether we have pcap/pcap-inttypes.h.
# If we do, we use that to get the C99 types defined.
#
-savedcppflags="$CPPFLAGS"
-CPPFLAGS="$CPPFLAGS $V_INCLS"
-for ac_header in pcap/pcap-inttypes.h
-do :
- ac_fn_c_check_header_mongrel "$LINENO" "pcap/pcap-inttypes.h" "ac_cv_header_pcap_pcap_inttypes_h" "$ac_includes_default"
-if test "x$ac_cv_header_pcap_pcap_inttypes_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_PCAP_PCAP_INTTYPES_H 1
-_ACEOF
+ac_fn_c_check_header_compile "$LINENO" "pcap/pcap-inttypes.h" "ac_cv_header_pcap_pcap_inttypes_h" "$ac_includes_default"
+if test "x$ac_cv_header_pcap_pcap_inttypes_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_PCAP_PCAP_INTTYPES_H 1" >>confdefs.h
+
+fi
+
+
+#
+# At compile time HAVE_PCAP_FINDALLDEVS depends on HAVE_PCAP_IF_T.
+#
+ac_fn_c_check_type "$LINENO" "pcap_if_t" "ac_cv_type_pcap_if_t" "#include <pcap.h>
+"
+if test "x$ac_cv_type_pcap_if_t" = xyes
+then :
+
+printf "%s\n" "#define HAVE_PCAP_IF_T 1" >>confdefs.h
+
fi
-done
CPPFLAGS="$savedcppflags"
#
# Define the old BSD specified-width types in terms of the C99 types;
# we may need them with libpcap include files.
#
ac_fn_c_check_type "$LINENO" "u_int8_t" "ac_cv_type_u_int8_t" "$ac_includes_default
#include <sys/types.h>
"
-if test "x$ac_cv_type_u_int8_t" = xyes; then :
+if test "x$ac_cv_type_u_int8_t" = xyes
+then :
-else
+else $as_nop
-$as_echo "#define u_int8_t uint8_t" >>confdefs.h
+printf "%s\n" "#define u_int8_t uint8_t" >>confdefs.h
fi
ac_fn_c_check_type "$LINENO" "u_int16_t" "ac_cv_type_u_int16_t" "$ac_includes_default
#include <sys/types.h>
"
-if test "x$ac_cv_type_u_int16_t" = xyes; then :
+if test "x$ac_cv_type_u_int16_t" = xyes
+then :
-else
+else $as_nop
-$as_echo "#define u_int16_t uint16_t" >>confdefs.h
+printf "%s\n" "#define u_int16_t uint16_t" >>confdefs.h
fi
ac_fn_c_check_type "$LINENO" "u_int32_t" "ac_cv_type_u_int32_t" "$ac_includes_default
#include <sys/types.h>
"
-if test "x$ac_cv_type_u_int32_t" = xyes; then :
+if test "x$ac_cv_type_u_int32_t" = xyes
+then :
-else
+else $as_nop
-$as_echo "#define u_int32_t uint32_t" >>confdefs.h
+printf "%s\n" "#define u_int32_t uint32_t" >>confdefs.h
fi
ac_fn_c_check_type "$LINENO" "u_int64_t" "ac_cv_type_u_int64_t" "$ac_includes_default
#include <sys/types.h>
"
-if test "x$ac_cv_type_u_int64_t" = xyes; then :
+if test "x$ac_cv_type_u_int64_t" = xyes
+then :
-else
+else $as_nop
-$as_echo "#define u_int64_t uint64_t" >>confdefs.h
+printf "%s\n" "#define u_int64_t uint64_t" >>confdefs.h
fi
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
set dummy ${ac_tool_prefix}ranlib; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_RANLIB+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_RANLIB+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$RANLIB"; then
ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi
fi
RANLIB=$ac_cv_prog_RANLIB
if test -n "$RANLIB"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
-$as_echo "$RANLIB" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+printf "%s\n" "$RANLIB" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
fi
if test -z "$ac_cv_prog_RANLIB"; then
ac_ct_RANLIB=$RANLIB
# Extract the first word of "ranlib", so it can be a program name with args.
set dummy ranlib; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_RANLIB+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$ac_ct_RANLIB"; then
ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_RANLIB="ranlib"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi
fi
ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
if test -n "$ac_ct_RANLIB"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
-$as_echo "$ac_ct_RANLIB" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+printf "%s\n" "$ac_ct_RANLIB" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_RANLIB" = x; then
RANLIB=":"
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
RANLIB=$ac_ct_RANLIB
fi
else
RANLIB="$ac_cv_prog_RANLIB"
fi
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
set dummy ${ac_tool_prefix}ar; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_AR+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_AR+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$AR"; then
ac_cv_prog_AR="$AR" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_AR="${ac_tool_prefix}ar"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi
fi
AR=$ac_cv_prog_AR
if test -n "$AR"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
-$as_echo "$AR" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+printf "%s\n" "$AR" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
fi
if test -z "$ac_cv_prog_AR"; then
ac_ct_AR=$AR
# Extract the first word of "ar", so it can be a program name with args.
set dummy ar; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_AR+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+printf %s "checking for $ac_word... " >&6; }
+if test ${ac_cv_prog_ac_ct_AR+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
if test -n "$ac_ct_AR"; then
ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then
ac_cv_prog_ac_ct_AR="ar"
- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi
fi
ac_ct_AR=$ac_cv_prog_ac_ct_AR
if test -n "$ac_ct_AR"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
-$as_echo "$ac_ct_AR" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+printf "%s\n" "$ac_ct_AR" >&6; }
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
if test "x$ac_ct_AR" = x; then
AR=""
else
case $cross_compiling:$ac_tool_warned in
yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
ac_tool_warned=yes ;;
esac
AR=$ac_ct_AR
fi
else
AR="$ac_cv_prog_AR"
fi
rm -f os-proto.h
if test "${LBL_CFLAGS+set}" = set; then
V_CCOPT="$V_CCOPT ${LBL_CFLAGS}"
fi
if test -f .devel ; then
#
# Skip all the warning option stuff on some compilers.
#
if test "$ac_lbl_cc_dont_try_gcc_dashW" != yes; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -W option" >&5
-$as_echo_n "checking whether the compiler supports the -W option... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -W option" >&5
+printf %s "checking whether the compiler supports the -W option... " >&6; }
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -W"
#
# XXX - yes, this depends on the way AC_LANG_WERROR works,
# but no mechanism is provided to turn AC_LANG_WERROR on
# *and then turn it back off*, so that we *only* do it when
# testing compiler options - 15 years after somebody asked
# for it:
#
# https://autoconf.gnu.narkive.com/gTAVmfKD/how-to-cancel-flags-set-by-ac-lang-werror
#
save_ac_c_werror_flag="$ac_c_werror_flag"
ac_c_werror_flag=yes
#
# We use AC_LANG_SOURCE() so that we can control the complete
# content of the program being compiled. We do not, for example,
# want the default "int main()" that AC_LANG_PROGRAM() generates,
# as it will generate a warning with -Wold-style-definition, meaning
# that we would treat it as not working, as the test will fail if
# *any* error output, including a warning due to the flag we're
# testing, is generated; see
#
# https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
# https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
#
# This may, as per those two messages, be fixed in autoconf 2.70,
- # but we only require 2.64 or newer for now.
+ # but we only require 2.69 or newer for now.
#
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int main(void) { return 0; }
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
CFLAGS="$save_CFLAGS"
V_CCOPT="$V_CCOPT -W"
-else
+else $as_nop
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
CFLAGS="$save_CFLAGS"
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_c_werror_flag="$save_ac_c_werror_flag"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wall option" >&5
-$as_echo_n "checking whether the compiler supports the -Wall option... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wall option" >&5
+printf %s "checking whether the compiler supports the -Wall option... " >&6; }
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Wall"
#
# XXX - yes, this depends on the way AC_LANG_WERROR works,
# but no mechanism is provided to turn AC_LANG_WERROR on
# *and then turn it back off*, so that we *only* do it when
# testing compiler options - 15 years after somebody asked
# for it:
#
# https://autoconf.gnu.narkive.com/gTAVmfKD/how-to-cancel-flags-set-by-ac-lang-werror
#
save_ac_c_werror_flag="$ac_c_werror_flag"
ac_c_werror_flag=yes
#
# We use AC_LANG_SOURCE() so that we can control the complete
# content of the program being compiled. We do not, for example,
# want the default "int main()" that AC_LANG_PROGRAM() generates,
# as it will generate a warning with -Wold-style-definition, meaning
# that we would treat it as not working, as the test will fail if
# *any* error output, including a warning due to the flag we're
# testing, is generated; see
#
# https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
# https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
#
# This may, as per those two messages, be fixed in autoconf 2.70,
- # but we only require 2.64 or newer for now.
+ # but we only require 2.69 or newer for now.
#
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int main(void) { return 0; }
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
CFLAGS="$save_CFLAGS"
V_CCOPT="$V_CCOPT -Wall"
-else
+else $as_nop
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
CFLAGS="$save_CFLAGS"
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_c_werror_flag="$save_ac_c_werror_flag"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wassign-enum option" >&5
-$as_echo_n "checking whether the compiler supports the -Wassign-enum option... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wassign-enum option" >&5
+printf %s "checking whether the compiler supports the -Wassign-enum option... " >&6; }
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Wassign-enum"
#
# XXX - yes, this depends on the way AC_LANG_WERROR works,
# but no mechanism is provided to turn AC_LANG_WERROR on
# *and then turn it back off*, so that we *only* do it when
# testing compiler options - 15 years after somebody asked
# for it:
#
# https://autoconf.gnu.narkive.com/gTAVmfKD/how-to-cancel-flags-set-by-ac-lang-werror
#
save_ac_c_werror_flag="$ac_c_werror_flag"
ac_c_werror_flag=yes
#
# We use AC_LANG_SOURCE() so that we can control the complete
# content of the program being compiled. We do not, for example,
# want the default "int main()" that AC_LANG_PROGRAM() generates,
# as it will generate a warning with -Wold-style-definition, meaning
# that we would treat it as not working, as the test will fail if
# *any* error output, including a warning due to the flag we're
# testing, is generated; see
#
# https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
# https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
#
# This may, as per those two messages, be fixed in autoconf 2.70,
- # but we only require 2.64 or newer for now.
+ # but we only require 2.69 or newer for now.
#
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int main(void) { return 0; }
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
CFLAGS="$save_CFLAGS"
V_CCOPT="$V_CCOPT -Wassign-enum"
-else
+else $as_nop
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
CFLAGS="$save_CFLAGS"
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_c_werror_flag="$save_ac_c_werror_flag"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wcast-qual option" >&5
-$as_echo_n "checking whether the compiler supports the -Wcast-qual option... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wcast-qual option" >&5
+printf %s "checking whether the compiler supports the -Wcast-qual option... " >&6; }
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Wcast-qual"
#
# XXX - yes, this depends on the way AC_LANG_WERROR works,
# but no mechanism is provided to turn AC_LANG_WERROR on
# *and then turn it back off*, so that we *only* do it when
# testing compiler options - 15 years after somebody asked
# for it:
#
# https://autoconf.gnu.narkive.com/gTAVmfKD/how-to-cancel-flags-set-by-ac-lang-werror
#
save_ac_c_werror_flag="$ac_c_werror_flag"
ac_c_werror_flag=yes
#
# We use AC_LANG_SOURCE() so that we can control the complete
# content of the program being compiled. We do not, for example,
# want the default "int main()" that AC_LANG_PROGRAM() generates,
# as it will generate a warning with -Wold-style-definition, meaning
# that we would treat it as not working, as the test will fail if
# *any* error output, including a warning due to the flag we're
# testing, is generated; see
#
# https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
# https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
#
# This may, as per those two messages, be fixed in autoconf 2.70,
- # but we only require 2.64 or newer for now.
+ # but we only require 2.69 or newer for now.
#
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int main(void) { return 0; }
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
CFLAGS="$save_CFLAGS"
V_CCOPT="$V_CCOPT -Wcast-qual"
-else
+else $as_nop
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
CFLAGS="$save_CFLAGS"
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_c_werror_flag="$save_ac_c_werror_flag"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wmissing-prototypes option" >&5
-$as_echo_n "checking whether the compiler supports the -Wmissing-prototypes option... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wmissing-prototypes option" >&5
+printf %s "checking whether the compiler supports the -Wmissing-prototypes option... " >&6; }
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Wmissing-prototypes"
#
# XXX - yes, this depends on the way AC_LANG_WERROR works,
# but no mechanism is provided to turn AC_LANG_WERROR on
# *and then turn it back off*, so that we *only* do it when
# testing compiler options - 15 years after somebody asked
# for it:
#
# https://autoconf.gnu.narkive.com/gTAVmfKD/how-to-cancel-flags-set-by-ac-lang-werror
#
save_ac_c_werror_flag="$ac_c_werror_flag"
ac_c_werror_flag=yes
#
# We use AC_LANG_SOURCE() so that we can control the complete
# content of the program being compiled. We do not, for example,
# want the default "int main()" that AC_LANG_PROGRAM() generates,
# as it will generate a warning with -Wold-style-definition, meaning
# that we would treat it as not working, as the test will fail if
# *any* error output, including a warning due to the flag we're
# testing, is generated; see
#
# https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
# https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
#
# This may, as per those two messages, be fixed in autoconf 2.70,
- # but we only require 2.64 or newer for now.
+ # but we only require 2.69 or newer for now.
#
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int main(void) { return 0; }
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
CFLAGS="$save_CFLAGS"
V_CCOPT="$V_CCOPT -Wmissing-prototypes"
-else
+else $as_nop
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
CFLAGS="$save_CFLAGS"
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_c_werror_flag="$save_ac_c_werror_flag"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wmissing-variable-declarations option" >&5
-$as_echo_n "checking whether the compiler supports the -Wmissing-variable-declarations option... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wmissing-variable-declarations option" >&5
+printf %s "checking whether the compiler supports the -Wmissing-variable-declarations option... " >&6; }
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Wmissing-variable-declarations"
#
# XXX - yes, this depends on the way AC_LANG_WERROR works,
# but no mechanism is provided to turn AC_LANG_WERROR on
# *and then turn it back off*, so that we *only* do it when
# testing compiler options - 15 years after somebody asked
# for it:
#
# https://autoconf.gnu.narkive.com/gTAVmfKD/how-to-cancel-flags-set-by-ac-lang-werror
#
save_ac_c_werror_flag="$ac_c_werror_flag"
ac_c_werror_flag=yes
#
# We use AC_LANG_SOURCE() so that we can control the complete
# content of the program being compiled. We do not, for example,
# want the default "int main()" that AC_LANG_PROGRAM() generates,
# as it will generate a warning with -Wold-style-definition, meaning
# that we would treat it as not working, as the test will fail if
# *any* error output, including a warning due to the flag we're
# testing, is generated; see
#
# https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
# https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
#
# This may, as per those two messages, be fixed in autoconf 2.70,
- # but we only require 2.64 or newer for now.
+ # but we only require 2.69 or newer for now.
+ #
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+int main(void) { return 0; }
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+ CFLAGS="$save_CFLAGS"
+ V_CCOPT="$V_CCOPT -Wmissing-variable-declarations"
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+ CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ ac_c_werror_flag="$save_ac_c_werror_flag"
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wnull-pointer-subtraction option" >&5
+printf %s "checking whether the compiler supports the -Wnull-pointer-subtraction option... " >&6; }
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Wnull-pointer-subtraction"
+ #
+ # XXX - yes, this depends on the way AC_LANG_WERROR works,
+ # but no mechanism is provided to turn AC_LANG_WERROR on
+ # *and then turn it back off*, so that we *only* do it when
+ # testing compiler options - 15 years after somebody asked
+ # for it:
+ #
+ # https://autoconf.gnu.narkive.com/gTAVmfKD/how-to-cancel-flags-set-by-ac-lang-werror
+ #
+ save_ac_c_werror_flag="$ac_c_werror_flag"
+ ac_c_werror_flag=yes
+ #
+ # We use AC_LANG_SOURCE() so that we can control the complete
+ # content of the program being compiled. We do not, for example,
+ # want the default "int main()" that AC_LANG_PROGRAM() generates,
+ # as it will generate a warning with -Wold-style-definition, meaning
+ # that we would treat it as not working, as the test will fail if
+ # *any* error output, including a warning due to the flag we're
+ # testing, is generated; see
+ #
+ # https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
+ # https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
+ #
+ # This may, as per those two messages, be fixed in autoconf 2.70,
+ # but we only require 2.69 or newer for now.
+ #
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+int main(void) { return 0; }
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+ CFLAGS="$save_CFLAGS"
+ V_CCOPT="$V_CCOPT -Wnull-pointer-subtraction"
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+ CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ ac_c_werror_flag="$save_ac_c_werror_flag"
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wold-style-definition option" >&5
+printf %s "checking whether the compiler supports the -Wold-style-definition option... " >&6; }
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Wold-style-definition"
+ #
+ # XXX - yes, this depends on the way AC_LANG_WERROR works,
+ # but no mechanism is provided to turn AC_LANG_WERROR on
+ # *and then turn it back off*, so that we *only* do it when
+ # testing compiler options - 15 years after somebody asked
+ # for it:
+ #
+ # https://autoconf.gnu.narkive.com/gTAVmfKD/how-to-cancel-flags-set-by-ac-lang-werror
+ #
+ save_ac_c_werror_flag="$ac_c_werror_flag"
+ ac_c_werror_flag=yes
+ #
+ # We use AC_LANG_SOURCE() so that we can control the complete
+ # content of the program being compiled. We do not, for example,
+ # want the default "int main()" that AC_LANG_PROGRAM() generates,
+ # as it will generate a warning with -Wold-style-definition, meaning
+ # that we would treat it as not working, as the test will fail if
+ # *any* error output, including a warning due to the flag we're
+ # testing, is generated; see
+ #
+ # https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
+ # https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
+ #
+ # This may, as per those two messages, be fixed in autoconf 2.70,
+ # but we only require 2.69 or newer for now.
+ #
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+int main(void) { return 0; }
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+ CFLAGS="$save_CFLAGS"
+ V_CCOPT="$V_CCOPT -Wold-style-definition"
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+ CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ ac_c_werror_flag="$save_ac_c_werror_flag"
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wpedantic option" >&5
+printf %s "checking whether the compiler supports the -Wpedantic option... " >&6; }
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Wpedantic"
+ #
+ # XXX - yes, this depends on the way AC_LANG_WERROR works,
+ # but no mechanism is provided to turn AC_LANG_WERROR on
+ # *and then turn it back off*, so that we *only* do it when
+ # testing compiler options - 15 years after somebody asked
+ # for it:
+ #
+ # https://autoconf.gnu.narkive.com/gTAVmfKD/how-to-cancel-flags-set-by-ac-lang-werror
+ #
+ save_ac_c_werror_flag="$ac_c_werror_flag"
+ ac_c_werror_flag=yes
+ #
+ # We use AC_LANG_SOURCE() so that we can control the complete
+ # content of the program being compiled. We do not, for example,
+ # want the default "int main()" that AC_LANG_PROGRAM() generates,
+ # as it will generate a warning with -Wold-style-definition, meaning
+ # that we would treat it as not working, as the test will fail if
+ # *any* error output, including a warning due to the flag we're
+ # testing, is generated; see
+ #
+ # https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
+ # https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
+ #
+ # This may, as per those two messages, be fixed in autoconf 2.70,
+ # but we only require 2.69 or newer for now.
+ #
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+int main(void) { return 0; }
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+ CFLAGS="$save_CFLAGS"
+ V_CCOPT="$V_CCOPT -Wpedantic"
+
+else $as_nop
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+ CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
+ ac_c_werror_flag="$save_ac_c_werror_flag"
+
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wpointer-arith option" >&5
+printf %s "checking whether the compiler supports the -Wpointer-arith option... " >&6; }
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Wpointer-arith"
+ #
+ # XXX - yes, this depends on the way AC_LANG_WERROR works,
+ # but no mechanism is provided to turn AC_LANG_WERROR on
+ # *and then turn it back off*, so that we *only* do it when
+ # testing compiler options - 15 years after somebody asked
+ # for it:
+ #
+ # https://autoconf.gnu.narkive.com/gTAVmfKD/how-to-cancel-flags-set-by-ac-lang-werror
+ #
+ save_ac_c_werror_flag="$ac_c_werror_flag"
+ ac_c_werror_flag=yes
+ #
+ # We use AC_LANG_SOURCE() so that we can control the complete
+ # content of the program being compiled. We do not, for example,
+ # want the default "int main()" that AC_LANG_PROGRAM() generates,
+ # as it will generate a warning with -Wold-style-definition, meaning
+ # that we would treat it as not working, as the test will fail if
+ # *any* error output, including a warning due to the flag we're
+ # testing, is generated; see
+ #
+ # https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
+ # https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
+ #
+ # This may, as per those two messages, be fixed in autoconf 2.70,
+ # but we only require 2.69 or newer for now.
#
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int main(void) { return 0; }
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
CFLAGS="$save_CFLAGS"
- V_CCOPT="$V_CCOPT -Wmissing-variable-declarations"
+ V_CCOPT="$V_CCOPT -Wpointer-arith"
-else
+else $as_nop
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
CFLAGS="$save_CFLAGS"
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_c_werror_flag="$save_ac_c_werror_flag"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wold-style-definition option" >&5
-$as_echo_n "checking whether the compiler supports the -Wold-style-definition option... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wpointer-sign option" >&5
+printf %s "checking whether the compiler supports the -Wpointer-sign option... " >&6; }
save_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS -Wold-style-definition"
+ CFLAGS="$CFLAGS -Wpointer-sign"
#
# XXX - yes, this depends on the way AC_LANG_WERROR works,
# but no mechanism is provided to turn AC_LANG_WERROR on
# *and then turn it back off*, so that we *only* do it when
# testing compiler options - 15 years after somebody asked
# for it:
#
# https://autoconf.gnu.narkive.com/gTAVmfKD/how-to-cancel-flags-set-by-ac-lang-werror
#
save_ac_c_werror_flag="$ac_c_werror_flag"
ac_c_werror_flag=yes
#
# We use AC_LANG_SOURCE() so that we can control the complete
# content of the program being compiled. We do not, for example,
# want the default "int main()" that AC_LANG_PROGRAM() generates,
# as it will generate a warning with -Wold-style-definition, meaning
# that we would treat it as not working, as the test will fail if
# *any* error output, including a warning due to the flag we're
# testing, is generated; see
#
# https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
# https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
#
# This may, as per those two messages, be fixed in autoconf 2.70,
- # but we only require 2.64 or newer for now.
+ # but we only require 2.69 or newer for now.
#
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int main(void) { return 0; }
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
CFLAGS="$save_CFLAGS"
- V_CCOPT="$V_CCOPT -Wold-style-definition"
+ V_CCOPT="$V_CCOPT -Wpointer-sign"
-else
+else $as_nop
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
CFLAGS="$save_CFLAGS"
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_c_werror_flag="$save_ac_c_werror_flag"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wpedantic option" >&5
-$as_echo_n "checking whether the compiler supports the -Wpedantic option... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wshadow option" >&5
+printf %s "checking whether the compiler supports the -Wshadow option... " >&6; }
save_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS -Wpedantic"
+ CFLAGS="$CFLAGS -Wshadow"
#
# XXX - yes, this depends on the way AC_LANG_WERROR works,
# but no mechanism is provided to turn AC_LANG_WERROR on
# *and then turn it back off*, so that we *only* do it when
# testing compiler options - 15 years after somebody asked
# for it:
#
# https://autoconf.gnu.narkive.com/gTAVmfKD/how-to-cancel-flags-set-by-ac-lang-werror
#
save_ac_c_werror_flag="$ac_c_werror_flag"
ac_c_werror_flag=yes
#
# We use AC_LANG_SOURCE() so that we can control the complete
# content of the program being compiled. We do not, for example,
# want the default "int main()" that AC_LANG_PROGRAM() generates,
# as it will generate a warning with -Wold-style-definition, meaning
# that we would treat it as not working, as the test will fail if
# *any* error output, including a warning due to the flag we're
# testing, is generated; see
#
# https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
# https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
#
# This may, as per those two messages, be fixed in autoconf 2.70,
- # but we only require 2.64 or newer for now.
+ # but we only require 2.69 or newer for now.
#
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int main(void) { return 0; }
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
CFLAGS="$save_CFLAGS"
- V_CCOPT="$V_CCOPT -Wpedantic"
+ V_CCOPT="$V_CCOPT -Wshadow"
-else
+else $as_nop
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
CFLAGS="$save_CFLAGS"
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_c_werror_flag="$save_ac_c_werror_flag"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wpointer-arith option" >&5
-$as_echo_n "checking whether the compiler supports the -Wpointer-arith option... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wsign-compare option" >&5
+printf %s "checking whether the compiler supports the -Wsign-compare option... " >&6; }
save_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS -Wpointer-arith"
+ CFLAGS="$CFLAGS -Wsign-compare"
#
# XXX - yes, this depends on the way AC_LANG_WERROR works,
# but no mechanism is provided to turn AC_LANG_WERROR on
# *and then turn it back off*, so that we *only* do it when
# testing compiler options - 15 years after somebody asked
# for it:
#
# https://autoconf.gnu.narkive.com/gTAVmfKD/how-to-cancel-flags-set-by-ac-lang-werror
#
save_ac_c_werror_flag="$ac_c_werror_flag"
ac_c_werror_flag=yes
#
# We use AC_LANG_SOURCE() so that we can control the complete
# content of the program being compiled. We do not, for example,
# want the default "int main()" that AC_LANG_PROGRAM() generates,
# as it will generate a warning with -Wold-style-definition, meaning
# that we would treat it as not working, as the test will fail if
# *any* error output, including a warning due to the flag we're
# testing, is generated; see
#
# https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
# https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
#
# This may, as per those two messages, be fixed in autoconf 2.70,
- # but we only require 2.64 or newer for now.
+ # but we only require 2.69 or newer for now.
#
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int main(void) { return 0; }
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
CFLAGS="$save_CFLAGS"
- V_CCOPT="$V_CCOPT -Wpointer-arith"
+ V_CCOPT="$V_CCOPT -Wsign-compare"
-else
+else $as_nop
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
CFLAGS="$save_CFLAGS"
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_c_werror_flag="$save_ac_c_werror_flag"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wpointer-sign option" >&5
-$as_echo_n "checking whether the compiler supports the -Wpointer-sign option... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wstrict-prototypes option" >&5
+printf %s "checking whether the compiler supports the -Wstrict-prototypes option... " >&6; }
save_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS -Wpointer-sign"
+ CFLAGS="$CFLAGS -Wstrict-prototypes"
#
# XXX - yes, this depends on the way AC_LANG_WERROR works,
# but no mechanism is provided to turn AC_LANG_WERROR on
# *and then turn it back off*, so that we *only* do it when
# testing compiler options - 15 years after somebody asked
# for it:
#
# https://autoconf.gnu.narkive.com/gTAVmfKD/how-to-cancel-flags-set-by-ac-lang-werror
#
save_ac_c_werror_flag="$ac_c_werror_flag"
ac_c_werror_flag=yes
#
# We use AC_LANG_SOURCE() so that we can control the complete
# content of the program being compiled. We do not, for example,
# want the default "int main()" that AC_LANG_PROGRAM() generates,
# as it will generate a warning with -Wold-style-definition, meaning
# that we would treat it as not working, as the test will fail if
# *any* error output, including a warning due to the flag we're
# testing, is generated; see
#
# https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
# https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
#
# This may, as per those two messages, be fixed in autoconf 2.70,
- # but we only require 2.64 or newer for now.
+ # but we only require 2.69 or newer for now.
#
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int main(void) { return 0; }
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
CFLAGS="$save_CFLAGS"
- V_CCOPT="$V_CCOPT -Wpointer-sign"
+ V_CCOPT="$V_CCOPT -Wstrict-prototypes"
-else
+else $as_nop
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
CFLAGS="$save_CFLAGS"
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_c_werror_flag="$save_ac_c_werror_flag"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wshadow option" >&5
-$as_echo_n "checking whether the compiler supports the -Wshadow option... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wundef option" >&5
+printf %s "checking whether the compiler supports the -Wundef option... " >&6; }
save_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS -Wshadow"
+ CFLAGS="$CFLAGS -Wundef"
#
# XXX - yes, this depends on the way AC_LANG_WERROR works,
# but no mechanism is provided to turn AC_LANG_WERROR on
# *and then turn it back off*, so that we *only* do it when
# testing compiler options - 15 years after somebody asked
# for it:
#
# https://autoconf.gnu.narkive.com/gTAVmfKD/how-to-cancel-flags-set-by-ac-lang-werror
#
save_ac_c_werror_flag="$ac_c_werror_flag"
ac_c_werror_flag=yes
#
# We use AC_LANG_SOURCE() so that we can control the complete
# content of the program being compiled. We do not, for example,
# want the default "int main()" that AC_LANG_PROGRAM() generates,
# as it will generate a warning with -Wold-style-definition, meaning
# that we would treat it as not working, as the test will fail if
# *any* error output, including a warning due to the flag we're
# testing, is generated; see
#
# https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
# https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
#
# This may, as per those two messages, be fixed in autoconf 2.70,
- # but we only require 2.64 or newer for now.
+ # but we only require 2.69 or newer for now.
#
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int main(void) { return 0; }
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
CFLAGS="$save_CFLAGS"
- V_CCOPT="$V_CCOPT -Wshadow"
+ V_CCOPT="$V_CCOPT -Wundef"
-else
+else $as_nop
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
CFLAGS="$save_CFLAGS"
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_c_werror_flag="$save_ac_c_werror_flag"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wsign-compare option" >&5
-$as_echo_n "checking whether the compiler supports the -Wsign-compare option... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wunreachable-code-return option" >&5
+printf %s "checking whether the compiler supports the -Wunreachable-code-return option... " >&6; }
save_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS -Wsign-compare"
+ CFLAGS="$CFLAGS -Wunreachable-code-return"
#
# XXX - yes, this depends on the way AC_LANG_WERROR works,
# but no mechanism is provided to turn AC_LANG_WERROR on
# *and then turn it back off*, so that we *only* do it when
# testing compiler options - 15 years after somebody asked
# for it:
#
# https://autoconf.gnu.narkive.com/gTAVmfKD/how-to-cancel-flags-set-by-ac-lang-werror
#
save_ac_c_werror_flag="$ac_c_werror_flag"
ac_c_werror_flag=yes
#
# We use AC_LANG_SOURCE() so that we can control the complete
# content of the program being compiled. We do not, for example,
# want the default "int main()" that AC_LANG_PROGRAM() generates,
# as it will generate a warning with -Wold-style-definition, meaning
# that we would treat it as not working, as the test will fail if
# *any* error output, including a warning due to the flag we're
# testing, is generated; see
#
# https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
# https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
#
# This may, as per those two messages, be fixed in autoconf 2.70,
- # but we only require 2.64 or newer for now.
+ # but we only require 2.69 or newer for now.
#
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int main(void) { return 0; }
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
CFLAGS="$save_CFLAGS"
- V_CCOPT="$V_CCOPT -Wsign-compare"
+ V_CCOPT="$V_CCOPT -Wunreachable-code-return"
-else
+else $as_nop
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
CFLAGS="$save_CFLAGS"
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_c_werror_flag="$save_ac_c_werror_flag"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wstrict-prototypes option" >&5
-$as_echo_n "checking whether the compiler supports the -Wstrict-prototypes option... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wunused-but-set-parameter option" >&5
+printf %s "checking whether the compiler supports the -Wunused-but-set-parameter option... " >&6; }
save_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS -Wstrict-prototypes"
+ CFLAGS="$CFLAGS -Wunused-but-set-parameter"
#
# XXX - yes, this depends on the way AC_LANG_WERROR works,
# but no mechanism is provided to turn AC_LANG_WERROR on
# *and then turn it back off*, so that we *only* do it when
# testing compiler options - 15 years after somebody asked
# for it:
#
# https://autoconf.gnu.narkive.com/gTAVmfKD/how-to-cancel-flags-set-by-ac-lang-werror
#
save_ac_c_werror_flag="$ac_c_werror_flag"
ac_c_werror_flag=yes
#
# We use AC_LANG_SOURCE() so that we can control the complete
# content of the program being compiled. We do not, for example,
# want the default "int main()" that AC_LANG_PROGRAM() generates,
# as it will generate a warning with -Wold-style-definition, meaning
# that we would treat it as not working, as the test will fail if
# *any* error output, including a warning due to the flag we're
# testing, is generated; see
#
# https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
# https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
#
# This may, as per those two messages, be fixed in autoconf 2.70,
- # but we only require 2.64 or newer for now.
+ # but we only require 2.69 or newer for now.
#
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int main(void) { return 0; }
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
CFLAGS="$save_CFLAGS"
- V_CCOPT="$V_CCOPT -Wstrict-prototypes"
+ V_CCOPT="$V_CCOPT -Wunused-but-set-parameter"
-else
+else $as_nop
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
CFLAGS="$save_CFLAGS"
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_c_werror_flag="$save_ac_c_werror_flag"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wunreachable-code-return option" >&5
-$as_echo_n "checking whether the compiler supports the -Wunreachable-code-return option... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wunused-but-set-variable option" >&5
+printf %s "checking whether the compiler supports the -Wunused-but-set-variable option... " >&6; }
save_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS -Wunreachable-code-return"
+ CFLAGS="$CFLAGS -Wunused-but-set-variable"
#
# XXX - yes, this depends on the way AC_LANG_WERROR works,
# but no mechanism is provided to turn AC_LANG_WERROR on
# *and then turn it back off*, so that we *only* do it when
# testing compiler options - 15 years after somebody asked
# for it:
#
# https://autoconf.gnu.narkive.com/gTAVmfKD/how-to-cancel-flags-set-by-ac-lang-werror
#
save_ac_c_werror_flag="$ac_c_werror_flag"
ac_c_werror_flag=yes
#
# We use AC_LANG_SOURCE() so that we can control the complete
# content of the program being compiled. We do not, for example,
# want the default "int main()" that AC_LANG_PROGRAM() generates,
# as it will generate a warning with -Wold-style-definition, meaning
# that we would treat it as not working, as the test will fail if
# *any* error output, including a warning due to the flag we're
# testing, is generated; see
#
# https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
# https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
#
# This may, as per those two messages, be fixed in autoconf 2.70,
- # but we only require 2.64 or newer for now.
+ # but we only require 2.69 or newer for now.
#
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int main(void) { return 0; }
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
CFLAGS="$save_CFLAGS"
- V_CCOPT="$V_CCOPT -Wunreachable-code-return"
+ V_CCOPT="$V_CCOPT -Wunused-but-set-variable"
-else
+else $as_nop
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
CFLAGS="$save_CFLAGS"
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_c_werror_flag="$save_ac_c_werror_flag"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wused-but-marked-unused option" >&5
-$as_echo_n "checking whether the compiler supports the -Wused-but-marked-unused option... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wused-but-marked-unused option" >&5
+printf %s "checking whether the compiler supports the -Wused-but-marked-unused option... " >&6; }
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Wused-but-marked-unused"
#
# XXX - yes, this depends on the way AC_LANG_WERROR works,
# but no mechanism is provided to turn AC_LANG_WERROR on
# *and then turn it back off*, so that we *only* do it when
# testing compiler options - 15 years after somebody asked
# for it:
#
# https://autoconf.gnu.narkive.com/gTAVmfKD/how-to-cancel-flags-set-by-ac-lang-werror
#
save_ac_c_werror_flag="$ac_c_werror_flag"
ac_c_werror_flag=yes
#
# We use AC_LANG_SOURCE() so that we can control the complete
# content of the program being compiled. We do not, for example,
# want the default "int main()" that AC_LANG_PROGRAM() generates,
# as it will generate a warning with -Wold-style-definition, meaning
# that we would treat it as not working, as the test will fail if
# *any* error output, including a warning due to the flag we're
# testing, is generated; see
#
# https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
# https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
#
# This may, as per those two messages, be fixed in autoconf 2.70,
- # but we only require 2.64 or newer for now.
+ # but we only require 2.69 or newer for now.
#
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int main(void) { return 0; }
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
CFLAGS="$save_CFLAGS"
V_CCOPT="$V_CCOPT -Wused-but-marked-unused"
-else
+else $as_nop
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
CFLAGS="$save_CFLAGS"
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_c_werror_flag="$save_ac_c_werror_flag"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wwrite-strings option" >&5
-$as_echo_n "checking whether the compiler supports the -Wwrite-strings option... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wwrite-strings option" >&5
+printf %s "checking whether the compiler supports the -Wwrite-strings option... " >&6; }
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Wwrite-strings"
#
# XXX - yes, this depends on the way AC_LANG_WERROR works,
# but no mechanism is provided to turn AC_LANG_WERROR on
# *and then turn it back off*, so that we *only* do it when
# testing compiler options - 15 years after somebody asked
# for it:
#
# https://autoconf.gnu.narkive.com/gTAVmfKD/how-to-cancel-flags-set-by-ac-lang-werror
#
save_ac_c_werror_flag="$ac_c_werror_flag"
ac_c_werror_flag=yes
#
# We use AC_LANG_SOURCE() so that we can control the complete
# content of the program being compiled. We do not, for example,
# want the default "int main()" that AC_LANG_PROGRAM() generates,
# as it will generate a warning with -Wold-style-definition, meaning
# that we would treat it as not working, as the test will fail if
# *any* error output, including a warning due to the flag we're
# testing, is generated; see
#
# https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
# https://www.postgresql.org/message-id/2192993.1591682589%40sss.pgh.pa.us
#
# This may, as per those two messages, be fixed in autoconf 2.70,
- # but we only require 2.64 or newer for now.
+ # but we only require 2.69 or newer for now.
#
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int main(void) { return 0; }
_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
+if ac_fn_c_try_compile "$LINENO"
+then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
CFLAGS="$save_CFLAGS"
V_CCOPT="$V_CCOPT -Wwrite-strings"
-else
+else $as_nop
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
CFLAGS="$save_CFLAGS"
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
ac_c_werror_flag="$save_ac_c_werror_flag"
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports generating dependencies" >&5
-$as_echo_n "checking whether the compiler supports generating dependencies... " >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports generating dependencies" >&5
+printf %s "checking whether the compiler supports generating dependencies... " >&6; }
if test "$GCC" = yes ; then
#
# GCC, or a compiler deemed to be GCC by AC_PROG_CC (even
# though it's not); we assume that, in this case, the flag
# would be -M.
#
ac_lbl_dependency_flag="-M"
else
#
# Not GCC or a compiler deemed to be GCC; what platform is
# this? (We're assuming that if the compiler isn't GCC
# it's the compiler from the vendor of the OS; that won't
# necessarily be true for x86 platforms, where it might be
# the Intel C compiler.)
#
case "$host_os" in
irix*|osf*|darwin*)
#
# MIPS C for IRIX, DEC C, and clang all use -M.
#
ac_lbl_dependency_flag="-M"
;;
solaris*)
#
# Sun C uses -xM.
#
ac_lbl_dependency_flag="-xM"
;;
hpux*)
#
# HP's older C compilers don't support this.
# HP's newer C compilers support this with
# either +M or +Make; the older compilers
# interpret +M as something completely
# different, so we use +Make so we don't
# think it works with the older compilers.
#
ac_lbl_dependency_flag="+Make"
;;
*)
#
# Not one of the above; assume no support for
# generating dependencies.
#
ac_lbl_dependency_flag=""
;;
esac
fi
#
# Is ac_lbl_dependency_flag defined and, if so, does the compiler
# complain about it?
#
# Note: clang doesn't seem to exit with an error status when handed
# an unknown non-warning error, even if you pass it
# -Werror=unknown-warning-option. However, it always supports
# -M, so the fact that this test always succeeds with clang
# isn't an issue.
#
if test ! -z "$ac_lbl_dependency_flag"; then
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
int main(void) { return 0; }
_ACEOF
- if { { $as_echo "$as_me:${as_lineno-$LINENO}: eval \"\$CC \$ac_lbl_dependency_flag conftest.c >/dev/null 2>&1\""; } >&5
+ if { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: eval \"\$CC \$ac_lbl_dependency_flag conftest.c >/dev/null 2>&1\""; } >&5
(eval "$CC $ac_lbl_dependency_flag conftest.c >/dev/null 2>&1") 2>&5
ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, with $ac_lbl_dependency_flag" >&5
-$as_echo "yes, with $ac_lbl_dependency_flag" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes, with $ac_lbl_dependency_flag" >&5
+printf "%s\n" "yes, with $ac_lbl_dependency_flag" >&6; }
DEPENDENCY_CFLAG="$ac_lbl_dependency_flag"
MKDEP='${top_srcdir}/mkdep'
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
#
# We can't run mkdep, so have "make depend" do
# nothing.
#
MKDEP=:
fi
rm -rf conftest*
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
#
# We can't run mkdep, so have "make depend" do
# nothing.
#
MKDEP=:
fi
#
# We used to set -n32 for IRIX 6 when not using GCC (presumed
# to mean that we're using MIPS C or MIPSpro C); it specified
# the "new" faster 32-bit ABI, introduced in IRIX 6.2. I'm
# not sure why that would be something to do *only* with a
# .devel file; why should the ABI for which we produce code
# depend on .devel?
#
os=`echo $host_os | sed -e 's/\([0-9][0-9]*\)[^0-9].*$/\1/'`
name="lbl/os-$os.h"
if test -f $name ; then
ln -s $name os-proto.h
-$as_echo "#define HAVE_OS_PROTO_H 1" >>confdefs.h
+printf "%s\n" "#define HAVE_OS_PROTO_H 1" >>confdefs.h
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: can't find $name" >&5
-$as_echo "$as_me: WARNING: can't find $name" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: can't find $name" >&5
+printf "%s\n" "$as_me: WARNING: can't find $name" >&2;}
fi
fi
# Check for OpenSSL/libressl libcrypto
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use OpenSSL/libressl libcrypto" >&5
-$as_echo_n "checking whether to use OpenSSL/libressl libcrypto... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to use OpenSSL/libressl libcrypto" >&5
+printf %s "checking whether to use OpenSSL/libressl libcrypto... " >&6; }
# Specify location for both includes and libraries.
want_libcrypto=ifavailable
# Check whether --with-crypto was given.
-if test "${with_crypto+set}" = set; then :
+if test ${with_crypto+y}
+then :
withval=$with_crypto;
if test $withval = no
then
# User doesn't want to link with libcrypto.
want_libcrypto=no
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
elif test $withval = yes
then
# User wants to link with libcrypto but hasn't specified
# a directory.
want_libcrypto=yes
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
else
# User wants to link with libcrypto and has specified
# a directory, so use the provided value.
want_libcrypto=yes
libcrypto_root=$withval
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, using the version installed in $withval" >&5
-$as_echo "yes, using the version installed in $withval" >&6; }
-
- #
- # Put the subdirectories of the libcrypto root directory
- # at the front of the header and library search path.
- #
- CFLAGS="-I$withval/include $CFLAGS"
- LIBS="-L$withval/lib $LIBS"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes, using the version installed in $withval" >&5
+printf "%s\n" "yes, using the version installed in $withval" >&6; }
fi
-else
+else $as_nop
#
# Use libcrypto if it's present, otherwise don't; no directory
# was specified.
#
want_libcrypto=ifavailable
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, if available" >&5
-$as_echo "yes, if available" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes, if available" >&5
+printf "%s\n" "yes, if available" >&6; }
fi
if test "$want_libcrypto" != "no"; then
#
- # Don't check for libcrypto unless we have its headers;
- # Apple, bless their pointy little heads, apparently ship
- # libcrypto as a library, but not the header files, in
- # El Capitan, probably because they don't want you writing
- # nasty portable code that could run on other UN*Xes, they
- # want you writing code that uses their Shiny New Crypto
- # Library and that only runs on macOS.
- #
- ac_fn_c_check_header_mongrel "$LINENO" "openssl/crypto.h" "ac_cv_header_openssl_crypto_h" "$ac_includes_default"
-if test "x$ac_cv_header_openssl_crypto_h" = xyes; then :
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for DES_cbc_encrypt in -lcrypto" >&5
-$as_echo_n "checking for DES_cbc_encrypt in -lcrypto... " >&6; }
-if ${ac_cv_lib_crypto_DES_cbc_encrypt+:} false; then :
- $as_echo_n "(cached) " >&6
+ # Were we told where to look for libcrypto?
+ #
+ if test -z "$libcrypto_root"; then
+ #
+ # No.
+ #
+ # First, try looking for it with pkg-config, if we have it.
+ #
+ # Homebrew's pkg-config does not, by default, look for
+ # pkg-config files for packages it has installed.
+ # Furthermore, at least for OpenSSL, they appear to be
+ # dumped in package-specific directories whose paths are
+ # not only package-specific but package-version-specific.
+ #
+ # So the only way to find openssl is to get the value of
+ # PKG_CONFIG_PATH from "brew --env openssl" and add that
+ # to PKG_CONFIG_PATH. (No, we can't just assume it's under
+ # /usr/local; Homebrew have conveniently chosen to put it
+ # under /opt/homebrew on ARM.)
+ #
+ # That's the nice thing about Homebrew - it makes things easier!
+ # Thanks!
+ #
+ save_PKG_CONFIG_PATH="$PKG_CONFIG_PATH"
+ if test -n "$BREW"; then
+ openssl_pkgconfig_dir=`$BREW --env --plain openssl | sed -n 's/PKG_CONFIG_PATH: //p'`
+ PKG_CONFIG_PATH="$openssl_pkgconfig_dir:$PKG_CONFIG_PATH"
+ fi
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libcrypto with pkg-config" >&5
+printf %s "checking for libcrypto with pkg-config... " >&6; }
+if test -n "$PKG_CONFIG"; then
+
+ if { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcrypto\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libcrypto") 2>&5
+ ac_status=$?
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ #
+ # The package was found, so try to get its C flags and
+ # libraries.
+ #
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: found" >&5
+printf "%s\n" "found" >&6; }
+ if test ! -n "$LIBCRYPTO_CFLAGS"; then
+ LIBCRYPTO_CFLAGS=`$PKG_CONFIG --cflags "libcrypto" 2>/dev/null`
+ if test "x$?" != "x0"; then
+ #
+ # That failed - report an error.
+ # Re-run the command, telling pkg-config to print an error
+ # message, capture the error message, and report it.
+ # This causes the configuration script to fail, as it means
+ # the script is almost certainly doing something wrong.
+ #
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lcrypto $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ _pkg_short_errors_supported=no
+fi
+ if test $_pkg_short_errors_supported = yes; then
+ _pkg_error_string=`$PKG_CONFIG --short-errors --print-errors --cflags "libcrypto" 2>&1`
+ else
+ _pkg_error_string=`$PKG_CONFIG --print-errors --cflags "libcrypto" 2>&1`
+ fi
+ as_fn_error $? "$PKG_CONFIG --cflags \"libcrypto\" failed: $_pkg_error_string" "$LINENO" 5
+ fi
+ fi
+ if test ! -n "$LIBCRYPTO_LIBS"; then
+ LIBCRYPTO_LIBS=`$PKG_CONFIG --libs "libcrypto" 2>/dev/null`
+ if test "x$?" != "x0"; then
+ #
+ # That failed - report an error.
+ # Re-run the command, telling pkg-config to print an error
+ # message, capture the error message, and report it.
+ # This causes the configuration script to fail, as it means
+ # the script is almost certainly doing something wrong.
+ #
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi
+ if test $_pkg_short_errors_supported = yes; then
+ _pkg_error_string=`$PKG_CONFIG --short-errors --print-errors --libs "libcrypto" 2>&1`
+ else
+ _pkg_error_string=`$PKG_CONFIG --print-errors --libs "libcrypto" 2>&1`
+ fi
+ as_fn_error $? "$PKG_CONFIG --libs \"libcrypto\" failed: $_pkg_error_string" "$LINENO" 5
+ fi
+ fi
+ if test ! -n "$LIBCRYPTO_LIBS_STATIC"; then
+ LIBCRYPTO_LIBS_STATIC=`$PKG_CONFIG --libs --static "libcrypto" 2>/dev/null`
+ if test "x$?" != "x0"; then
+ #
+ # That failed - report an error.
+ # Re-run the command, telling pkg-config to print an error
+ # message, capture the error message, and report it.
+ # This causes the configuration script to fail, as it means
+ # the script is almost certainly doing something wrong.
+ #
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi
+ if test $_pkg_short_errors_supported = yes; then
+ _pkg_error_string=`$PKG_CONFIG --short-errors --print-errors --libs --static "libcrypto" 2>&1`
+ else
+ _pkg_error_string=`$PKG_CONFIG --print-errors --libs --static "libcrypto" 2>&1`
+ fi
+ as_fn_error $? "$PKG_CONFIG --libs --static \"libcrypto\" failed: $_pkg_error_string" "$LINENO" 5
+ fi
+ fi
+
+ #
+ # We found OpenSSL/libressl libcrypto.
+ #
+ HAVE_LIBCRYPTO=yes
+
+ else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+printf "%s\n" "not found" >&6; }
+ :
+ fi
+else
+ # No pkg-config, so obviously not found with pkg-config.
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: pkg-config not found" >&5
+printf "%s\n" "pkg-config not found" >&6; }
+ :
+fi
+
+ PKG_CONFIG_PATH="$save_PKG_CONFIG_PATH"
+
+ #
+ # If it wasn't found, and we have Homebrew installed, see
+ # if it's in Homebrew.
+ #
+ if test "x$HAVE_LIBCRYPTO" != "xyes" -a -n "$BREW"; then
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for openssl in Homebrew" >&5
+printf %s "checking for openssl in Homebrew... " >&6; }
+ #
+ # The brew man page lies when it speaks of
+ # $BREW --prefix --installed <formula>
+ # outputting nothing. In Homebrew 3.3.16,
+ # it produces output regardless of whether
+ # the formula is installed or not, so we
+ # send the standard output and error to
+ # the bit bucket.
+ #
+ # libcrypto isn't a formula, openssl is a formula.
+ #
+ if $BREW --prefix --installed openssl >/dev/null 2>&1; then
+ #
+ # Yes. Get the include directory and library
+ # directory. (No, we can't just assume it's
+ # under /usr/local; Homebrew have conveniently
+ # chosen to put it under /opt/homebrew on ARM.)
+ #
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+ HAVE_LIBCRYPTO=yes
+ openssl_path=`$BREW --prefix openssl`
+ LIBCRYPTO_CFLAGS="-I$openssl_path/include"
+ LIBCRYPTO_LIBS="-L$openssl_path/lib -lcrypto"
+ else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
+ fi
+ fi
+
+ #
+ # If it wasn't found, and /usr/local/include and /usr/local/lib
+ # exist, check if it's in /usr/local. (We check whether they
+ # exist because, if they don't exist, the compiler will warn
+ # about that and then ignore the argument, so they test
+ # using just the system header files and libraries.)
+ #
+ # We include the standard include file to 1) make sure that
+ # it's installed (if it's just a shared library for the
+ # benefit of existing programs, that's not useful) and 2)
+ # because SSL_library_init() is a library routine in some
+ # versions and a #defined wrapper around OPENSSL_init_ssl()
+ # in others.
+ #
+ if test "x$HAVE_LIBCRYPTO" != "xyes" -a -d "/usr/local/include" -a -d "/usr/local/lib"; then
+
+ save_CFLAGS="$CFLAGS"
+ save_LIBS="$LIBS"
+ save_LDFLAGS="$LDFLAGS"
+
+ CFLAGS="$CFLAGS -I/usr/local/include"
+ LIBS="$LIBS -L/usr/local/lib -lcrypto"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we have an OpenSSL/libressl libcrypto in /usr/local that we can use" >&5
+printf %s "checking whether we have an OpenSSL/libressl libcrypto in /usr/local that we can use... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char DES_cbc_encrypt ();
+#include <openssl/evp.h>
+
int
-main ()
+main (void)
{
-return DES_cbc_encrypt ();
+
+EVP_CIPHER_CTX_block_size((EVP_CIPHER_CTX *)0);
+return 0;
+
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_crypto_DES_cbc_encrypt=yes
-else
- ac_cv_lib_crypto_DES_cbc_encrypt=no
+if ac_fn_c_try_link "$LINENO"
+then :
+
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+ HAVE_LIBCRYPTO=yes
+ LIBCRYPTO_CFLAGS="-I/usr/local/include"
+ LIBCRYPTO_LIBS="-L/usr/local/lib -lcrypto"
+
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_DES_cbc_encrypt" >&5
-$as_echo "$ac_cv_lib_crypto_DES_cbc_encrypt" >&6; }
-if test "x$ac_cv_lib_crypto_DES_cbc_encrypt" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBCRYPTO 1
-_ACEOF
- LIBS="-lcrypto $LIBS"
+ CFLAGS="$save_CFLAGS"
+ LIBS="$save_LIBS"
+ LDFLAGS="$save_LDFLAGS"
-fi
+ fi
- if test "$ac_cv_lib_crypto_DES_cbc_encrypt" = "yes"; then
- for ac_header in openssl/evp.h
-do :
- ac_fn_c_check_header_mongrel "$LINENO" "openssl/evp.h" "ac_cv_header_openssl_evp_h" "$ac_includes_default"
-if test "x$ac_cv_header_openssl_evp_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_OPENSSL_EVP_H 1
+ #
+ # If it wasn't found, check if it's a system library.
+ #
+ # We include the standard include file to 1) make sure that
+ # it's installed (if it's just a shared library for the
+ # benefit of existing programs, that's not useful) and 2)
+ # make sure this isn't a newer macOS that provides libcrypto
+ # as a shared library but doesn't provide headers - Apple,
+ # bless their pointy little heads, apparently ship libcrypto
+ # as a library, but not the header files, in El Capitan and
+ # later, probably because they don't want you writing nasty
+ # portable code that could run on other UN*Xes, they want you
+ # writing code that uses their Shiny New Crypto Library and
+ # that thus only runs on macOS.
+ #
+ if test "x$HAVE_LIBCRYPTO" != "xyes"; then
+
+ save_CFLAGS="$CFLAGS"
+ save_LIBS="$LIBS"
+ save_LDFLAGS="$LDFLAGS"
+
+ LIBS="$LIBS -lcrypto"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we have a system OpenSSL/libressl that we can use" >&5
+printf %s "checking whether we have a system OpenSSL/libressl that we can use... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <openssl/evp.h>
+
+int
+main (void)
+{
+
+EVP_CIPHER_CTX_block_size((EVP_CIPHER_CTX *)0);
+return 0;
+
+ ;
+ return 0;
+}
_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+ HAVE_LIBCRYPTO=yes
+ LIBCRYPTO_LIBS="-lcrypto"
+
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
-done
+ CFLAGS="$save_CFLAGS"
+ LIBS="$save_LIBS"
+ LDFLAGS="$save_LDFLAGS"
- #
- # OK, then:
- #
- # 1) do we have EVP_CIPHER_CTX_new?
- # If so, we use it to allocate an
- # EVP_CIPHER_CTX, as EVP_CIPHER_CTX may be
- # opaque; otherwise, we allocate it ourselves.
- #
- # 2) do we have EVP_DecryptInit_ex()?
- # If so, we use it, because we need to be
- # able to make two "initialize the cipher"
- # calls, one with the cipher and key, and
- # one with the IV, and, as of OpenSSL 1.1,
- # You Can't Do That with EVP_DecryptInit(),
- # because a call to EVP_DecryptInit() will
- # unconditionally clear the context, and
- # if you don't supply a cipher, it'll
- # clear the cipher, rendering the context
- # unusable and causing a crash.
- #
- for ac_func in EVP_CIPHER_CTX_new EVP_DecryptInit_ex
-do :
- as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
-ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
-if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
- cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+ fi
+ else
+ #
+ # Yes.
+ #
+ # Look for it there.
+ #
+
+ save_CFLAGS="$CFLAGS"
+ save_LIBS="$LIBS"
+ save_LDFLAGS="$LDFLAGS"
+
+ CFLAGS="$CFLAGS -I$libcrypto_root/include"
+ LIBS="$LIBS -L$libcrypto_root/lib -lcrypto"
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we have a system OpenSSL/libressl that we can use" >&5
+printf %s "checking whether we have a system OpenSSL/libressl that we can use... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <openssl/evp.h>
+
+int
+main (void)
+{
+
+EVP_CIPHER_CTX_block_size((EVP_CIPHER_CTX *)0);
+return 0;
+
+ ;
+ return 0;
+}
_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
+ HAVE_LIBCRYPTO=yes
+ LIBCRYPTO_CFLAGS="-I$libcrypto_root/include"
+ LIBCRYPTO_LIBS="-L$libcrypto_root/lib -lcrypto"
+
+else $as_nop
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
fi
-done
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+ conftest$ac_exeext conftest.$ac_ext
- fi
+ CFLAGS="$save_CFLAGS"
+ LIBS="$save_LIBS"
+ LDFLAGS="$save_LDFLAGS"
+
+ fi
+
+ #
+ # OK, did we find it?
+ #
+ if test "x$HAVE_LIBCRYPTO" = "xyes"; then
+
+printf "%s\n" "#define HAVE_LIBCRYPTO 1" >>confdefs.h
+
+
+ #
+ # Put the subdirectories of the libcrypto root directory
+ # at the end of the header and library search path, to
+ # make sure they come after any -I or -L flags for
+ # a local libpcap - those must take precedence of any
+ # directory that might contain an installed version of
+ # libpcap.
+ #
+ V_INCLS="$V_INCLS $LIBCRYPTO_CFLAGS"
+ LIBS="$LIBS $LIBCRYPTO_LIBS"
+
+ #
+ # OK, then:
+ #
+ # 1) do we have EVP_CIPHER_CTX_new?
+ # If so, we use it to allocate an EVP_CIPHER_CTX, as
+ # EVP_CIPHER_CTX may be opaque; otherwise, we allocate it
+ # ourselves.
+ #
+ # 2) do we have EVP_DecryptInit_ex()?
+ # If so, we use it, because we need to be able to make
+ # two "initialize the cipher" calls, one with the cipher
+ # and key, and one with the IV, and, as of OpenSSL 1.1,
+ # You Can't Do That with EVP_DecryptInit(), because a
+ # call to EVP_DecryptInit() will unconditionally clear
+ # the context, and if you don't supply a cipher, it'll
+ # clear the cipher, rendering the context unusable and
+ # causing a crash.
+ #
+ ac_fn_c_check_func "$LINENO" "EVP_CIPHER_CTX_new" "ac_cv_func_EVP_CIPHER_CTX_new"
+if test "x$ac_cv_func_EVP_CIPHER_CTX_new" = xyes
+then :
+ printf "%s\n" "#define HAVE_EVP_CIPHER_CTX_NEW 1" >>confdefs.h
fi
+ac_fn_c_check_func "$LINENO" "EVP_DecryptInit_ex" "ac_cv_func_EVP_DecryptInit_ex"
+if test "x$ac_cv_func_EVP_DecryptInit_ex" = xyes
+then :
+ printf "%s\n" "#define HAVE_EVP_DECRYPTINIT_EX 1" >>confdefs.h
+fi
+ else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: OpenSSL/libressl libcrypto not found" >&5
+printf "%s\n" "$as_me: OpenSSL/libressl libcrypto not found" >&6;}
+ fi
fi
# Check for libcap-ng
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use libcap-ng" >&5
-$as_echo_n "checking whether to use libcap-ng... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to use libcap-ng" >&5
+printf %s "checking whether to use libcap-ng... " >&6; }
# Specify location for both includes and libraries.
want_libcap_ng=ifavailable
# Check whether --with-cap_ng was given.
-if test "${with_cap_ng+set}" = set; then :
+if test ${with_cap_ng+y}
+then :
withval=$with_cap_ng;
if test $withval = no
then
want_libcap_ng=no
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+printf "%s\n" "no" >&6; }
elif test $withval = yes
then
want_libcap_ng=yes
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+printf "%s\n" "yes" >&6; }
fi
-else
+else $as_nop
#
# Use libcap-ng if it's present, otherwise don't.
#
want_libcap_ng=ifavailable
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, if available" >&5
-$as_echo "yes, if available" >&6; }
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes, if available" >&5
+printf "%s\n" "yes, if available" >&6; }
fi
if test "$want_libcap_ng" != "no"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for capng_change_id in -lcap-ng" >&5
-$as_echo_n "checking for capng_change_id in -lcap-ng... " >&6; }
-if ${ac_cv_lib_cap_ng_capng_change_id+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for capng_change_id in -lcap-ng" >&5
+printf %s "checking for capng_change_id in -lcap-ng... " >&6; }
+if test ${ac_cv_lib_cap_ng_capng_change_id+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lcap-ng $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
char capng_change_id ();
int
-main ()
+main (void)
{
return capng_change_id ();
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
+if ac_fn_c_try_link "$LINENO"
+then :
ac_cv_lib_cap_ng_capng_change_id=yes
-else
+else $as_nop
ac_cv_lib_cap_ng_capng_change_id=no
fi
-rm -f core conftest.err conftest.$ac_objext \
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_cap_ng_capng_change_id" >&5
-$as_echo "$ac_cv_lib_cap_ng_capng_change_id" >&6; }
-if test "x$ac_cv_lib_cap_ng_capng_change_id" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBCAP_NG 1
-_ACEOF
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_cap_ng_capng_change_id" >&5
+printf "%s\n" "$ac_cv_lib_cap_ng_capng_change_id" >&6; }
+if test "x$ac_cv_lib_cap_ng_capng_change_id" = xyes
+then :
+ printf "%s\n" "#define HAVE_LIBCAP_NG 1" >>confdefs.h
LIBS="-lcap-ng $LIBS"
fi
- for ac_header in cap-ng.h
-do :
- ac_fn_c_check_header_mongrel "$LINENO" "cap-ng.h" "ac_cv_header_cap_ng_h" "$ac_includes_default"
-if test "x$ac_cv_header_cap_ng_h" = xyes; then :
- cat >>confdefs.h <<_ACEOF
-#define HAVE_CAP_NG_H 1
-_ACEOF
+ ac_fn_c_check_header_compile "$LINENO" "cap-ng.h" "ac_cv_header_cap_ng_h" "$ac_includes_default"
+if test "x$ac_cv_header_cap_ng_h" = xyes
+then :
+ printf "%s\n" "#define HAVE_CAP_NG_H 1" >>confdefs.h
fi
-done
-
fi
if test "$missing_includes" = "yes"; then
CPPFLAGS="$CPPFLAGS -I$srcdir/missing"
V_INCLS="$V_INCLS -I$srcdir/missing"
fi
-# Find a good install program. We prefer a C program (faster),
+ # Find a good install program. We prefer a C program (faster),
# so one script is as good as another. But avoid the broken or
# incompatible versions:
# SysV /etc/install, /usr/sbin/install
# SunOS /usr/etc/install
# IRIX /sbin/install
# AIX /bin/install
# AmigaOS /C/install, which installs bootblocks on floppy discs
# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
# AFS /usr/afsws/bin/install, which mishandles nonexistent args
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# OS/2's system install, which has a completely different semantic
# ./install, which can be erroneously created by make from ./install.sh.
# Reject install programs that cannot install multiple files.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
-$as_echo_n "checking for a BSD-compatible install... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+printf %s "checking for a BSD-compatible install... " >&6; }
if test -z "$INSTALL"; then
-if ${ac_cv_path_install+:} false; then :
- $as_echo_n "(cached) " >&6
-else
+if test ${ac_cv_path_install+y}
+then :
+ printf %s "(cached) " >&6
+else $as_nop
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- # Account for people who put trailing slashes in PATH elements.
-case $as_dir/ in #((
- ./ | .// | /[cC]/* | \
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ # Account for fact that we put trailing slashes in our PATH walk.
+case $as_dir in #((
+ ./ | /[cC]/* | \
/etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
/usr/ucb/* ) ;;
*)
# OSF1 and SCO ODT 3.0 have their own names for install.
# Don't use installbsd from OSF since it installs stuff as root
# by default.
for ac_prog in ginstall scoinst install; do
for ac_exec_ext in '' $ac_executable_extensions; do
- if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+ if as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext"; then
if test $ac_prog = install &&
- grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ grep dspmsg "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
# AIX install. It has an incompatible calling convention.
:
elif test $ac_prog = install &&
- grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ grep pwplus "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
# program-specific install script used by HP pwplus--don't use.
:
else
rm -rf conftest.one conftest.two conftest.dir
echo one > conftest.one
echo two > conftest.two
mkdir conftest.dir
- if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+ if "$as_dir$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir/" &&
test -s conftest.one && test -s conftest.two &&
test -s conftest.dir/conftest.one &&
test -s conftest.dir/conftest.two
then
- ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ ac_cv_path_install="$as_dir$ac_prog$ac_exec_ext -c"
break 3
fi
fi
fi
done
done
;;
esac
done
IFS=$as_save_IFS
rm -rf conftest.one conftest.two conftest.dir
fi
- if test "${ac_cv_path_install+set}" = set; then
+ if test ${ac_cv_path_install+y}; then
INSTALL=$ac_cv_path_install
else
# As a last resort, use the slow shell script. Don't cache a
# value for INSTALL within a source directory, because that will
# break other packages using the cache if that directory is
# removed, or if the value is a relative name.
INSTALL=$ac_install_sh
fi
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
-$as_echo "$INSTALL" >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+printf "%s\n" "$INSTALL" >&6; }
# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
# It thinks the first close brace ends the variable substitution.
test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
ac_config_headers="$ac_config_headers config.h"
-ac_config_commands="$ac_config_commands default-1"
+ac_config_commands="$ac_config_commands .devel"
ac_config_files="$ac_config_files Makefile tcpdump.1"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
# tests run on this system so they can be shared between configure
# scripts and configure runs, see configure's option --config-cache.
# It is not useful on other systems. If it contains results you don't
# want to keep, you may remove or edit it.
#
# config.status only pays attention to the cache file if you give it
# the --recheck option to rerun configure.
#
# `ac_cv_env_foo' variables (set or unset) will be overridden when
# loading this file, other *unset* `ac_cv_foo' will be assigned the
# following values.
_ACEOF
# The following way of writing the cache mishandles newlines in values,
# but we know of no workaround that is simple, portable, and efficient.
# So, we kill variables containing newlines.
# Ultrix sh set writes to stderr and can't be redirected directly,
# and sets the high bit in the cache file unless we assign to the vars.
(
for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
eval ac_val=\$$ac_var
case $ac_val in #(
*${as_nl}*)
case $ac_var in #(
- *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
-$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
esac
case $ac_var in #(
_ | IFS | as_nl) ;; #(
BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
*) { eval $ac_var=; unset $ac_var;} ;;
esac ;;
esac
done
(set) 2>&1 |
case $as_nl`(ac_space=' '; set) 2>&1` in #(
*${as_nl}ac_space=\ *)
# `set' does not quote correctly, so add quotes: double-quote
# substitution turns \\\\ into \\, and sed turns \\ into \.
sed -n \
"s/'/'\\\\''/g;
s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
;; #(
*)
# `set' quotes correctly as required by POSIX, so do not add quotes.
sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
;;
esac |
sort
) |
sed '
/^ac_cv_env_/b end
t clear
:clear
- s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/
t end
s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
:end' >>confcache
if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
if test -w "$cache_file"; then
if test "x$cache_file" != "x/dev/null"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
-$as_echo "$as_me: updating cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+printf "%s\n" "$as_me: updating cache $cache_file" >&6;}
if test ! -f "$cache_file" || test -h "$cache_file"; then
cat confcache >"$cache_file"
else
case $cache_file in #(
*/* | ?:*)
mv -f confcache "$cache_file"$$ &&
mv -f "$cache_file"$$ "$cache_file" ;; #(
*)
mv -f confcache "$cache_file" ;;
esac
fi
fi
else
- { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
-$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;}
fi
fi
rm -f confcache
test "x$prefix" = xNONE && prefix=$ac_default_prefix
# Let make expand exec_prefix.
test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
DEFS=-DHAVE_CONFIG_H
ac_libobjs=
ac_ltlibobjs=
U=
for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
# 1. Remove the extension, and $U if already installed.
ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
- ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"`
# 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
# will be set to the directory where LIBOBJS objects are built.
as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
done
LIBOBJS=$ac_libobjs
LTLIBOBJS=$ac_ltlibobjs
: "${CONFIG_STATUS=./config.status}"
ac_write_fail=0
ac_clean_files_save=$ac_clean_files
ac_clean_files="$ac_clean_files $CONFIG_STATUS"
-{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
-$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;}
as_write_fail=0
cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
#! $SHELL
# Generated by $as_me.
# Run this file to recreate the current configuration.
# Compiler output produced by configure, useful for debugging
# configure, is in config.log if it exists.
debug=false
ac_cs_recheck=false
ac_cs_silent=false
SHELL=\${CONFIG_SHELL-$SHELL}
export SHELL
_ASEOF
cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
## -------------------- ##
## M4sh Initialization. ##
## -------------------- ##
# Be more Bourne compatible
DUALCASE=1; export DUALCASE # for MKS sh
-if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+as_nop=:
+if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1
+then :
emulate sh
NULLCMD=:
# Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
# is contrary to our usage. Disable this feature.
alias -g '${1+"$@"}'='"$@"'
setopt NO_GLOB_SUBST
-else
+else $as_nop
case `(set -o) 2>/dev/null` in #(
*posix*) :
set -o posix ;; #(
*) :
;;
esac
fi
+
+# Reset variables that may have inherited troublesome values from
+# the environment.
+
+# IFS needs to be set, to space, tab, and newline, in precisely that order.
+# (If _AS_PATH_WALK were called with IFS unset, it would have the
+# side effect of setting IFS to empty, thus disabling word splitting.)
+# Quoting is to prevent editors from complaining about space-tab.
as_nl='
'
export as_nl
-# Printing a long string crashes Solaris 7 /usr/bin/printf.
-as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
-as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
-# Prefer a ksh shell builtin over an external printf program on Solaris,
-# but without wasting forks for bash or zsh.
-if test -z "$BASH_VERSION$ZSH_VERSION" \
- && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='print -r --'
- as_echo_n='print -rn --'
-elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
- as_echo='printf %s\n'
- as_echo_n='printf %s'
-else
- if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
- as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
- as_echo_n='/usr/ucb/echo -n'
- else
- as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
- as_echo_n_body='eval
- arg=$1;
- case $arg in #(
- *"$as_nl"*)
- expr "X$arg" : "X\\(.*\\)$as_nl";
- arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
- esac;
- expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
- '
- export as_echo_n_body
- as_echo_n='sh -c $as_echo_n_body as_echo'
- fi
- export as_echo_body
- as_echo='sh -c $as_echo_body as_echo'
-fi
+IFS=" "" $as_nl"
+
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# Ensure predictable behavior from utilities with locale-dependent output.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# We cannot yet rely on "unset" to work, but we need these variables
+# to be unset--not just set to an empty or harmless value--now, to
+# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct
+# also avoids known problems related to "unset" and subshell syntax
+# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).
+for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH
+do eval test \${$as_var+y} \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+
+# Ensure that fds 0, 1, and 2 are open.
+if (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi
+if (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi
+if (exec 3>&2) ; then :; else exec 2>/dev/null; fi
# The user is always right.
-if test "${PATH_SEPARATOR+set}" != set; then
+if ${PATH_SEPARATOR+false} :; then
PATH_SEPARATOR=:
(PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
(PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
PATH_SEPARATOR=';'
}
fi
-# IFS
-# We need space, tab and new line, in precisely that order. Quoting is
-# there to prevent editors from complaining about space-tab.
-# (If _AS_PATH_WALK were called with IFS unset, it would disable word
-# splitting by setting IFS to empty value.)
-IFS=" "" $as_nl"
-
# Find who we are. Look in the path if we contain no directory separator.
as_myself=
case $0 in #((
*[\\/]* ) as_myself=$0 ;;
*) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
- test -z "$as_dir" && as_dir=.
- test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ case $as_dir in #(((
+ '') as_dir=./ ;;
+ */) ;;
+ *) as_dir=$as_dir/ ;;
+ esac
+ test -r "$as_dir$0" && as_myself=$as_dir$0 && break
done
IFS=$as_save_IFS
;;
esac
# We did not find ourselves, most probably we were run as `sh COMMAND'
# in which case we are not to be found in the path.
if test "x$as_myself" = x; then
as_myself=$0
fi
if test ! -f "$as_myself"; then
- $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
exit 1
fi
-# Unset variables that we do not need and which cause bugs (e.g. in
-# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
-# suppresses any "Segmentation fault" message there. '((' could
-# trigger a bug in pdksh 5.2.14.
-for as_var in BASH_ENV ENV MAIL MAILPATH
-do eval test x\${$as_var+set} = xset \
- && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
-done
-PS1='$ '
-PS2='> '
-PS4='+ '
-
-# NLS nuisances.
-LC_ALL=C
-export LC_ALL
-LANGUAGE=C
-export LANGUAGE
-
-# CDPATH.
-(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
# as_fn_error STATUS ERROR [LINENO LOG_FD]
# ----------------------------------------
# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
# script with STATUS, using 1 if that was 0.
as_fn_error ()
{
as_status=$1; test $as_status -eq 0 && as_status=1
if test "$4"; then
as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
fi
- $as_echo "$as_me: error: $2" >&2
+ printf "%s\n" "$as_me: error: $2" >&2
as_fn_exit $as_status
} # as_fn_error
+
# as_fn_set_status STATUS
# -----------------------
# Set $? to STATUS, without forking.
as_fn_set_status ()
{
return $1
} # as_fn_set_status
# as_fn_exit STATUS
# -----------------
# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
as_fn_exit ()
{
set +e
as_fn_set_status $1
exit $1
} # as_fn_exit
# as_fn_unset VAR
# ---------------
# Portably unset VAR.
as_fn_unset ()
{
{ eval $1=; unset $1;}
}
as_unset=as_fn_unset
+
# as_fn_append VAR VALUE
# ----------------------
# Append the text in VALUE to the end of the definition contained in VAR. Take
# advantage of any shell optimizations that allow amortized linear growth over
# repeated appends, instead of the typical quadratic growth present in naive
# implementations.
-if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null
+then :
eval 'as_fn_append ()
{
eval $1+=\$2
}'
-else
+else $as_nop
as_fn_append ()
{
eval $1=\$$1\$2
}
fi # as_fn_append
# as_fn_arith ARG...
# ------------------
# Perform arithmetic evaluation on the ARGs, and store the result in the
# global $as_val. Take advantage of shells that can avoid forks. The arguments
# must be portable across $(()) and expr.
-if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null
+then :
eval 'as_fn_arith ()
{
as_val=$(( $* ))
}'
-else
+else $as_nop
as_fn_arith ()
{
as_val=`expr "$@" || test $? -eq 1`
}
fi # as_fn_arith
if expr a : '\(a\)' >/dev/null 2>&1 &&
test "X`expr 00001 : '.*\(...\)'`" = X001; then
as_expr=expr
else
as_expr=false
fi
if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
as_basename=basename
else
as_basename=false
fi
if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
as_dirname=dirname
else
as_dirname=false
fi
as_me=`$as_basename -- "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
X"$0" : 'X\(//\)$' \| \
X"$0" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X/"$0" |
+printf "%s\n" X/"$0" |
sed '/^.*\/\([^/][^/]*\)\/*$/{
s//\1/
q
}
/^X\/\(\/\/\)$/{
s//\1/
q
}
/^X\/\(\/\).*/{
s//\1/
q
}
s/.*/./; q'`
# Avoid depending upon Character Ranges.
as_cr_letters='abcdefghijklmnopqrstuvwxyz'
as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
as_cr_Letters=$as_cr_letters$as_cr_LETTERS
as_cr_digits='0123456789'
as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# Determine whether it's possible to make 'echo' print without a newline.
+# These variables are no longer used directly by Autoconf, but are AC_SUBSTed
+# for compatibility with existing Makefiles.
ECHO_C= ECHO_N= ECHO_T=
case `echo -n x` in #(((((
-n*)
case `echo 'xy\c'` in
*c*) ECHO_T=' ';; # ECHO_T is single tab character.
xy) ECHO_C='\c';;
*) echo `echo ksh88 bug on AIX 6.1` > /dev/null
ECHO_T=' ';;
esac;;
*)
ECHO_N='-n';;
esac
+# For backward compatibility with old third-party macros, we provide
+# the shell variables $as_echo and $as_echo_n. New code should use
+# AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively.
+as_echo='printf %s\n'
+as_echo_n='printf %s'
+
rm -f conf$$ conf$$.exe conf$$.file
if test -d conf$$.dir; then
rm -f conf$$.dir/conf$$.file
else
rm -f conf$$.dir
mkdir conf$$.dir 2>/dev/null
fi
if (echo >conf$$.file) 2>/dev/null; then
if ln -s conf$$.file conf$$ 2>/dev/null; then
as_ln_s='ln -s'
# ... but there are two gotchas:
# 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
# 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
# In both cases, we have to default to `cp -pR'.
ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
as_ln_s='cp -pR'
elif ln conf$$.file conf$$ 2>/dev/null; then
as_ln_s=ln
else
as_ln_s='cp -pR'
fi
else
as_ln_s='cp -pR'
fi
rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
rmdir conf$$.dir 2>/dev/null
# as_fn_mkdir_p
# -------------
# Create "$as_dir" as a directory, including parents if necessary.
as_fn_mkdir_p ()
{
case $as_dir in #(
-*) as_dir=./$as_dir;;
esac
test -d "$as_dir" || eval $as_mkdir_p || {
as_dirs=
while :; do
case $as_dir in #(
- *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
*) as_qdir=$as_dir;;
esac
as_dirs="'$as_qdir' $as_dirs"
as_dir=`$as_dirname -- "$as_dir" ||
$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$as_dir" : 'X\(//\)[^/]' \| \
X"$as_dir" : 'X\(//\)$' \| \
X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$as_dir" |
+printf "%s\n" X"$as_dir" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
}
/^X\(\/\/\)[^/].*/{
s//\1/
q
}
/^X\(\/\/\)$/{
s//\1/
q
}
/^X\(\/\).*/{
s//\1/
q
}
s/.*/./; q'`
test -d "$as_dir" && break
done
test -z "$as_dirs" || eval "mkdir $as_dirs"
} || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
} # as_fn_mkdir_p
if mkdir -p . 2>/dev/null; then
as_mkdir_p='mkdir -p "$as_dir"'
else
test -d ./-p && rmdir ./-p
as_mkdir_p=false
fi
# as_fn_executable_p FILE
# -----------------------
# Test if FILE is an executable regular file.
as_fn_executable_p ()
{
test -f "$1" && test -x "$1"
} # as_fn_executable_p
as_test_x='test -x'
as_executable_p=as_fn_executable_p
# Sed expression to map a string onto a valid CPP name.
as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
# Sed expression to map a string onto a valid variable name.
as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
exec 6>&1
## ----------------------------------- ##
## Main body of $CONFIG_STATUS script. ##
## ----------------------------------- ##
_ASEOF
test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# Save the log message, to keep $0 and so on meaningful, and to
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by tcpdump $as_me 4.99.4, which was
-generated by GNU Autoconf 2.69. Invocation command line was
+This file was extended by tcpdump $as_me 4.99.5, which was
+generated by GNU Autoconf 2.71. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
CONFIG_HEADERS = $CONFIG_HEADERS
CONFIG_LINKS = $CONFIG_LINKS
CONFIG_COMMANDS = $CONFIG_COMMANDS
$ $0 $@
on `(hostname || uname -n) 2>/dev/null | sed 1q`
"
_ACEOF
case $ac_config_files in *"
"*) set x $ac_config_files; shift; ac_config_files=$*;;
esac
case $ac_config_headers in *"
"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
esac
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
# Files that config.status was made for.
config_files="$ac_config_files"
config_headers="$ac_config_headers"
config_commands="$ac_config_commands"
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
ac_cs_usage="\
\`$as_me' instantiates files and other configuration actions
from templates according to the current configuration. Unless the files
and actions are specified as TAGs, all are instantiated by default.
Usage: $0 [OPTION]... [TAG]...
-h, --help print this help, then exit
-V, --version print version number and configuration settings, then exit
--config print configuration, then exit
-q, --quiet, --silent
do not print progress messages
-d, --debug don't remove temporary files
--recheck update $as_me by reconfiguring in the same conditions
--file=FILE[:TEMPLATE]
instantiate the configuration file FILE
--header=FILE[:TEMPLATE]
instantiate the configuration header FILE
Configuration files:
$config_files
Configuration headers:
$config_headers
Configuration commands:
$config_commands
Report bugs to the package provider."
_ACEOF
+ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"`
+ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"`
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
-ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\
-tcpdump config.status 4.99.4
-configured by $0, generated by GNU Autoconf 2.69,
+tcpdump config.status 4.99.5
+configured by $0, generated by GNU Autoconf 2.71,
with options \\"\$ac_cs_config\\"
-Copyright (C) 2012 Free Software Foundation, Inc.
+Copyright (C) 2021 Free Software Foundation, Inc.
This config.status script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it."
ac_pwd='$ac_pwd'
srcdir='$srcdir'
INSTALL='$INSTALL'
test -n "\$AWK" || AWK=awk
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# The default lists apply if the user does not specify any file.
ac_need_defaults=:
while test $# != 0
do
case $1 in
--*=?*)
ac_option=`expr "X$1" : 'X\([^=]*\)='`
ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
ac_shift=:
;;
--*=)
ac_option=`expr "X$1" : 'X\([^=]*\)='`
ac_optarg=
ac_shift=:
;;
*)
ac_option=$1
ac_optarg=$2
ac_shift=shift
;;
esac
case $ac_option in
# Handling of the options.
-recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
ac_cs_recheck=: ;;
--version | --versio | --versi | --vers | --ver | --ve | --v | -V )
- $as_echo "$ac_cs_version"; exit ;;
+ printf "%s\n" "$ac_cs_version"; exit ;;
--config | --confi | --conf | --con | --co | --c )
- $as_echo "$ac_cs_config"; exit ;;
+ printf "%s\n" "$ac_cs_config"; exit ;;
--debug | --debu | --deb | --de | --d | -d )
debug=: ;;
--file | --fil | --fi | --f )
$ac_shift
case $ac_optarg in
- *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
'') as_fn_error $? "missing file argument" ;;
esac
as_fn_append CONFIG_FILES " '$ac_optarg'"
ac_need_defaults=false;;
--header | --heade | --head | --hea )
$ac_shift
case $ac_optarg in
- *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
esac
as_fn_append CONFIG_HEADERS " '$ac_optarg'"
ac_need_defaults=false;;
--he | --h)
# Conflict between --help and --header
as_fn_error $? "ambiguous option: \`$1'
Try \`$0 --help' for more information.";;
--help | --hel | -h )
- $as_echo "$ac_cs_usage"; exit ;;
+ printf "%s\n" "$ac_cs_usage"; exit ;;
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
| -silent | --silent | --silen | --sile | --sil | --si | --s)
ac_cs_silent=: ;;
# This is an error.
-*) as_fn_error $? "unrecognized option: \`$1'
Try \`$0 --help' for more information." ;;
*) as_fn_append ac_config_targets " $1"
ac_need_defaults=false ;;
esac
shift
done
ac_configure_extra_args=
if $ac_cs_silent; then
exec 6>/dev/null
ac_configure_extra_args="$ac_configure_extra_args --silent"
fi
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
if \$ac_cs_recheck; then
set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
shift
- \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6
CONFIG_SHELL='$SHELL'
export CONFIG_SHELL
exec "\$@"
fi
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
exec 5>>config.log
{
echo
sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
## Running $as_me. ##
_ASBOX
- $as_echo "$ac_log"
+ printf "%s\n" "$ac_log"
} >&5
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
#
# INIT-COMMANDS
#
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# Handling of arguments.
for ac_config_target in $ac_config_targets
do
case $ac_config_target in
"config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
- "default-1") CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;;
+ ".devel") CONFIG_COMMANDS="$CONFIG_COMMANDS .devel" ;;
"Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
"tcpdump.1") CONFIG_FILES="$CONFIG_FILES tcpdump.1" ;;
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
esac
done
# If the user did not use the arguments to specify the items to instantiate,
# then the envvar interface is used. Set only those that are not.
# We use the long form for the default assignment because of an extremely
# bizarre bug on SunOS 4.1.3.
if $ac_need_defaults; then
- test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
- test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
- test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+ test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files
+ test ${CONFIG_HEADERS+y} || CONFIG_HEADERS=$config_headers
+ test ${CONFIG_COMMANDS+y} || CONFIG_COMMANDS=$config_commands
fi
# Have a temporary directory for convenience. Make it in the build tree
# simply because there is no reason against having it here, and in addition,
# creating and moving files from /tmp can sometimes cause problems.
# Hook for its removal unless debugging.
# Note that there is a small window in which the directory will not be cleaned:
# after its creation but before its name has been assigned to `$tmp'.
$debug ||
{
tmp= ac_tmp=
trap 'exit_status=$?
: "${ac_tmp:=$tmp}"
{ test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
' 0
trap 'as_fn_exit 1' 1 2 13 15
}
# Create a (secure) tmp directory for tmp files.
{
tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
test -d "$tmp"
} ||
{
tmp=./conf$$-$RANDOM
(umask 077 && mkdir "$tmp")
} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
ac_tmp=$tmp
# Set up the scripts for CONFIG_FILES section.
# No need to generate them if there are no CONFIG_FILES.
# This happens for instance with `./config.status config.h'.
if test -n "$CONFIG_FILES"; then
ac_cr=`echo X | tr X '\015'`
# On cygwin, bash can eat \r inside `` if the user requested igncr.
# But we know of no other shell where ac_cr would be empty at this
# point, so we can use a bashism as a fallback.
if test "x$ac_cr" = x; then
eval ac_cr=\$\'\\r\'
fi
ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
ac_cs_awk_cr='\\r'
else
ac_cs_awk_cr=$ac_cr
fi
echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
_ACEOF
{
echo "cat >conf$$subs.awk <<_ACEOF" &&
echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
echo "_ACEOF"
} >conf$$subs.sh ||
as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
ac_delim='%!_!# '
for ac_last_try in false false false false false :; do
. ./conf$$subs.sh ||
as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
if test $ac_delim_n = $ac_delim_num; then
break
elif $ac_last_try; then
as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
else
ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
fi
done
rm -f conf$$subs.sh
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
_ACEOF
sed -n '
h
s/^/S["/; s/!.*/"]=/
p
g
s/^[^!]*!//
:repl
t repl
s/'"$ac_delim"'$//
t delim
:nl
h
s/\(.\{148\}\)..*/\1/
t more1
s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
p
n
b repl
:more1
s/["\\]/\\&/g; s/^/"/; s/$/"\\/
p
g
s/.\{148\}//
t nl
:delim
h
s/\(.\{148\}\)..*/\1/
t more2
s/["\\]/\\&/g; s/^/"/; s/$/"/
p
b
:more2
s/["\\]/\\&/g; s/^/"/; s/$/"\\/
p
g
s/.\{148\}//
t delim
' <conf$$subs.awk | sed '
/^[^""]/{
N
s/\n//
}
' >>$CONFIG_STATUS || ac_write_fail=1
rm -f conf$$subs.awk
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
_ACAWK
cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
for (key in S) S_is_set[key] = 1
FS = ""
}
{
line = $ 0
nfields = split(line, field, "@")
substed = 0
len = length(field[1])
for (i = 2; i < nfields; i++) {
key = field[i]
keylen = length(key)
if (S_is_set[key]) {
value = S[key]
line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
len += length(value) + length(field[++i])
substed = 1
} else
len += 1 + keylen
}
print line
}
_ACAWK
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
else
cat
fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
|| as_fn_error $? "could not setup config files machinery" "$LINENO" 5
_ACEOF
# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
# trailing colons and then remove the whole line if VPATH becomes empty
# (actually we leave an empty line to preserve line numbers).
if test "x$srcdir" = x.; then
ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
h
s///
s/^/:/
s/[ ]*$/:/
s/:\$(srcdir):/:/g
s/:\${srcdir}:/:/g
s/:@srcdir@:/:/g
s/^:*//
s/:*$//
x
s/\(=[ ]*\).*/\1/
G
s/\n//
s/^[^=]*=[ ]*$//
}'
fi
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
fi # test -n "$CONFIG_FILES"
# Set up the scripts for CONFIG_HEADERS section.
# No need to generate them if there are no CONFIG_HEADERS.
# This happens for instance with `./config.status Makefile'.
if test -n "$CONFIG_HEADERS"; then
cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
BEGIN {
_ACEOF
# Transform confdefs.h into an awk script `defines.awk', embedded as
# here-document in config.status, that substitutes the proper values into
# config.h.in to produce config.h.
# Create a delimiter string that does not exist in confdefs.h, to ease
# handling of long lines.
ac_delim='%!_!# '
for ac_last_try in false false :; do
ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
if test -z "$ac_tt"; then
break
elif $ac_last_try; then
as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
else
ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
fi
done
# For the awk script, D is an array of macro values keyed by name,
# likewise P contains macro parameters if any. Preserve backslash
# newline sequences.
ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
sed -n '
s/.\{148\}/&'"$ac_delim"'/g
t rset
:rset
s/^[ ]*#[ ]*define[ ][ ]*/ /
t def
d
:def
s/\\$//
t bsnl
s/["\\]/\\&/g
s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
D["\1"]=" \3"/p
s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p
d
:bsnl
s/["\\]/\\&/g
s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
D["\1"]=" \3\\\\\\n"\\/p
t cont
s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
t cont
d
:cont
n
s/.\{148\}/&'"$ac_delim"'/g
t clear
:clear
s/\\$//
t bsnlc
s/["\\]/\\&/g; s/^/"/; s/$/"/p
d
:bsnlc
s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
b cont
' <confdefs.h | sed '
s/'"$ac_delim"'/"\\\
"/g' >>$CONFIG_STATUS || ac_write_fail=1
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
for (key in D) D_is_set[key] = 1
FS = ""
}
/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
line = \$ 0
split(line, arg, " ")
if (arg[1] == "#") {
defundef = arg[2]
mac1 = arg[3]
} else {
defundef = substr(arg[1], 2)
mac1 = arg[2]
}
split(mac1, mac2, "(") #)
macro = mac2[1]
prefix = substr(line, 1, index(line, defundef) - 1)
if (D_is_set[macro]) {
# Preserve the white space surrounding the "#".
print prefix "define", macro P[macro] D[macro]
next
} else {
# Replace #undef with comments. This is necessary, for example,
# in the case of _POSIX_SOURCE, which is predefined and required
# on some systems where configure will not decide to define it.
if (defundef == "undef") {
print "/*", prefix defundef, macro, "*/"
next
}
}
}
{ print }
_ACAWK
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
fi # test -n "$CONFIG_HEADERS"
eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS"
shift
for ac_tag
do
case $ac_tag in
:[FHLC]) ac_mode=$ac_tag; continue;;
esac
case $ac_mode$ac_tag in
:[FHL]*:*);;
:L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
:[FH]-) ac_tag=-:-;;
:[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
esac
ac_save_IFS=$IFS
IFS=:
set x $ac_tag
IFS=$ac_save_IFS
shift
ac_file=$1
shift
case $ac_mode in
:L) ac_source=$1;;
:[FH])
ac_file_inputs=
for ac_f
do
case $ac_f in
-) ac_f="$ac_tmp/stdin";;
*) # Look for the file first in the build tree, then in the source tree
# (if the path is not absolute). The absolute path cannot be DOS-style,
# because $ac_f cannot contain `:'.
test -f "$ac_f" ||
case $ac_f in
[\\/$]*) false;;
*) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
esac ||
as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
esac
- case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
as_fn_append ac_file_inputs " '$ac_f'"
done
# Let's still pretend it is `configure' which instantiates (i.e., don't
# use $as_me), people would be surprised to read:
# /* config.h. Generated by config.status. */
configure_input='Generated from '`
- $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
`' by configure.'
if test x"$ac_file" != x-; then
configure_input="$ac_file. $configure_input"
- { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
-$as_echo "$as_me: creating $ac_file" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+printf "%s\n" "$as_me: creating $ac_file" >&6;}
fi
# Neutralize special characters interpreted by sed in replacement strings.
case $configure_input in #(
*\&* | *\|* | *\\* )
- ac_sed_conf_input=`$as_echo "$configure_input" |
+ ac_sed_conf_input=`printf "%s\n" "$configure_input" |
sed 's/[\\\\&|]/\\\\&/g'`;; #(
*) ac_sed_conf_input=$configure_input;;
esac
case $ac_tag in
*:-:* | *:-) cat >"$ac_tmp/stdin" \
|| as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
esac
;;
esac
ac_dir=`$as_dirname -- "$ac_file" ||
$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$ac_file" : 'X\(//\)[^/]' \| \
X"$ac_file" : 'X\(//\)$' \| \
X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
-$as_echo X"$ac_file" |
+printf "%s\n" X"$ac_file" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
}
/^X\(\/\/\)[^/].*/{
s//\1/
q
}
/^X\(\/\/\)$/{
s//\1/
q
}
/^X\(\/\).*/{
s//\1/
q
}
s/.*/./; q'`
as_dir="$ac_dir"; as_fn_mkdir_p
ac_builddir=.
case "$ac_dir" in
.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
*)
- ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'`
# A ".." for each directory in $ac_dir_suffix.
- ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
case $ac_top_builddir_sub in
"") ac_top_builddir_sub=. ac_top_build_prefix= ;;
*) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
esac ;;
esac
ac_abs_top_builddir=$ac_pwd
ac_abs_builddir=$ac_pwd$ac_dir_suffix
# for backward compatibility:
ac_top_builddir=$ac_top_build_prefix
case $srcdir in
.) # We are building in place.
ac_srcdir=.
ac_top_srcdir=$ac_top_builddir_sub
ac_abs_top_srcdir=$ac_pwd ;;
[\\/]* | ?:[\\/]* ) # Absolute name.
ac_srcdir=$srcdir$ac_dir_suffix;
ac_top_srcdir=$srcdir
ac_abs_top_srcdir=$srcdir ;;
*) # Relative name.
ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
ac_top_srcdir=$ac_top_build_prefix$srcdir
ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
esac
ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
case $ac_mode in
:F)
#
# CONFIG_FILE
#
case $INSTALL in
[\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
*) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
esac
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# If the template does not know about datarootdir, expand it.
# FIXME: This hack should be removed a few years after 2.60.
ac_datarootdir_hack=; ac_datarootdir_seen=
ac_sed_dataroot='
/datarootdir/ {
p
q
}
/@datadir@/p
/@docdir@/p
/@infodir@/p
/@localedir@/p
/@mandir@/p'
case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
*datarootdir*) ac_datarootdir_seen=yes;;
*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
-$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_datarootdir_hack='
s&@datadir@&$datadir&g
s&@docdir@&$docdir&g
s&@infodir@&$infodir&g
s&@localedir@&$localedir&g
s&@mandir@&$mandir&g
s&\\\${datarootdir}&$datarootdir&g' ;;
esac
_ACEOF
# Neutralize VPATH when `$srcdir' = `.'.
# Shell code in configure.ac might set extrasub.
# FIXME: do we really want to maintain this feature?
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_sed_extra="$ac_vpsub
$extrasub
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
:t
/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
s|@configure_input@|$ac_sed_conf_input|;t t
s&@top_builddir@&$ac_top_builddir_sub&;t t
s&@top_build_prefix@&$ac_top_build_prefix&;t t
s&@srcdir@&$ac_srcdir&;t t
s&@abs_srcdir@&$ac_abs_srcdir&;t t
s&@top_srcdir@&$ac_top_srcdir&;t t
s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
s&@builddir@&$ac_builddir&;t t
s&@abs_builddir@&$ac_abs_builddir&;t t
s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
s&@INSTALL@&$ac_INSTALL&;t t
$ac_datarootdir_hack
"
eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
>$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
{ ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
{ ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
"$ac_tmp/out"`; test -z "$ac_out"; } &&
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined. Please make sure it is defined" >&5
-$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
which seems to be undefined. Please make sure it is defined" >&2;}
rm -f "$ac_tmp/stdin"
case $ac_file in
-) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
*) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
esac \
|| as_fn_error $? "could not create $ac_file" "$LINENO" 5
;;
:H)
#
# CONFIG_HEADER
#
if test x"$ac_file" != x-; then
{
- $as_echo "/* $configure_input */" \
+ printf "%s\n" "/* $configure_input */" >&1 \
&& eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
} >"$ac_tmp/config.h" \
|| as_fn_error $? "could not create $ac_file" "$LINENO" 5
if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
-$as_echo "$as_me: $ac_file is unchanged" >&6;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+printf "%s\n" "$as_me: $ac_file is unchanged" >&6;}
else
rm -f "$ac_file"
mv "$ac_tmp/config.h" "$ac_file" \
|| as_fn_error $? "could not create $ac_file" "$LINENO" 5
fi
else
- $as_echo "/* $configure_input */" \
+ printf "%s\n" "/* $configure_input */" >&1 \
&& eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
|| as_fn_error $? "could not create -" "$LINENO" 5
fi
;;
- :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
-$as_echo "$as_me: executing $ac_file commands" >&6;}
+ :C) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
+printf "%s\n" "$as_me: executing $ac_file commands" >&6;}
;;
esac
case $ac_file$ac_mode in
- "default-1":C) if test -f .devel; then
+ ".devel":C) if test -f .devel; then
echo timestamp > stamp-h
cat $srcdir/Makefile-devel-adds >> Makefile
make depend || exit 1
fi ;;
esac
done # for ac_tag
as_fn_exit 0
_ACEOF
ac_clean_files=$ac_clean_files_save
test $ac_write_fail = 0 ||
as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
# configure is writing to config.log, and then calls config.status.
# config.status does its own redirection, appending to config.log.
# Unfortunately, on DOS this fails, as config.log is still kept open
# by configure, so config.status won't be able to write to it; its
# output is simply discarded. So we exec the FD to /dev/null,
# effectively closing config.log, so it can be properly (re)opened and
# appended to by config.status. When coming back to configure, we
# need to make the FD available again.
if test "$no_create" != yes; then
ac_cs_success=:
ac_config_status_args=
test "$silent" = yes &&
ac_config_status_args="$ac_config_status_args --quiet"
exec 5>/dev/null
$SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
exec 5>>config.log
# Use ||, not &&, to avoid exiting from the if with $? = 1, which
# would make configure fail if this is the last instruction.
$ac_cs_success || as_fn_exit 1
fi
if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
-$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
fi
exit 0
+
diff --git a/contrib/tcpdump/configure.ac b/contrib/tcpdump/configure.ac
index 18d59b6d709f..1f2e4d7854a0 100644
--- a/contrib/tcpdump/configure.ac
+++ b/contrib/tcpdump/configure.ac
@@ -1,1027 +1,1287 @@
dnl Copyright (c) 1994, 1995, 1996, 1997
dnl The Regents of the University of California. All rights reserved.
dnl
dnl Process this file with autoconf to produce a configure script.
dnl
#
# See
#
# https://ftp.gnu.org/gnu/config/README
#
# for the URLs to use to fetch new versions of config.guess and
# config.sub.
#
-AC_PREREQ(2.69)
-AC_INIT(tcpdump, m4_esyscmd_s([cat VERSION]))
+AC_PREREQ([2.69])
+AC_INIT([tcpdump],[m4_esyscmd_s(cat VERSION)])
AC_CONFIG_SRCDIR(tcpdump.c)
AC_CANONICAL_HOST
AC_LBL_C_INIT_BEFORE_CC(V_INCLS)
#
# Try to enable as many C99 features as we can.
# At minimum, we want C++/C99-style // comments.
#
AC_PROG_CC_C99
if test "$ac_cv_prog_cc_c99" = "no"; then
AC_MSG_WARN([The C compiler does not support C99; there may be compiler errors])
fi
AC_LBL_C_INIT(V_CCOPT, V_INCLS)
AC_LBL_C_INLINE
-AC_CHECK_HEADERS(fcntl.h rpc/rpc.h rpc/rpcent.h net/if.h)
+AC_CHECK_HEADERS(rpc/rpc.h rpc/rpcent.h net/if.h)
+#
+# Get the size of a void *, to know whether this is a 32-bit or 64-bit build.
+#
+AC_CHECK_SIZEOF([void *])
+
+#
+# Get the size of a time_t, to know whether it's 32-bit or 64-bit.
+#
+AC_CHECK_SIZEOF([time_t],,[#include <time.h>])
case "$host_os" in
darwin*)
AC_ARG_ENABLE(universal,
AS_HELP_STRING([--disable-universal],[don't build universal on macOS]))
if test "$enable_universal" != "no"; then
case "$host_os" in
darwin9.*)
#
# Leopard. Build for x86 and 32-bit PowerPC, with
# x86 first. (That's what Apple does.)
#
V_CCOPT="$V_CCOPT -arch i386 -arch ppc"
LDFLAGS="$LDFLAGS -arch i386 -arch ppc"
;;
darwin10.*)
#
# Snow Leopard. Build for x86-64 and x86, with
# x86-64 first. (That's what Apple does.)
#
V_CCOPT="$V_CCOPT -arch x86_64 -arch i386"
LDFLAGS="$LDFLAGS -arch x86_64 -arch i386"
;;
esac
fi
;;
esac
+#
+# Do we have pkg-config?
+#
+PKG_PROG_PKG_CONFIG
+
+#
+# Do we have the brew command from Homebrew?
+#
+AC_PATH_PROG([BREW], [brew])
AC_ARG_WITH([smi],
[AS_HELP_STRING([--with-smi],
[link with libsmi (allows to load MIBs on the fly to decode SNMP packets) [default=yes, if available]])],
[],
[with_smi=yes])
if test "x$with_smi" != "xno" ; then
AC_CHECK_HEADER(smi.h,
[
#
# OK, we found smi.h. Do we have libsmi with smiInit?
#
AC_CHECK_LIB(smi, smiInit,
[
#
# OK, we have libsmi with smiInit. Can we use it?
#
AC_MSG_CHECKING([whether to enable libsmi])
savedlibs="$LIBS"
LIBS="-lsmi $LIBS"
- AC_TRY_RUN(
- [
+ AC_RUN_IFELSE([AC_LANG_SOURCE([[
/* libsmi available check */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <smi.h>
int main()
{
int current, revision, age, n;
const int required = 2;
if (smiInit(""))
exit(1);
if (strcmp(SMI_LIBRARY_VERSION, smi_library_version))
exit(2);
n = sscanf(smi_library_version, "%d:%d:%d", &current, &revision, &age);
if (n != 3)
exit(3);
if (required < current - age || required > current)
exit(4);
exit(0);
}
+ ]])
],
[
AC_MSG_RESULT(yes)
AC_DEFINE(USE_LIBSMI, 1,
[Define if you enable support for libsmi])
],
[
dnl autoconf documentation says that
dnl $? contains the exit value.
dnl reality is that it does not.
dnl We leave this in just in case
dnl autoconf ever comes back to
dnl match the documentation.
case $? in
1) AC_MSG_RESULT(no - smiInit failed) ;;
2) AC_MSG_RESULT(no - header/library version mismatch) ;;
3) AC_MSG_RESULT(no - can't determine library version) ;;
4) AC_MSG_RESULT(no - too old) ;;
*) AC_MSG_RESULT(no) ;;
esac
LIBS="$savedlibs"
],
[
AC_MSG_RESULT(not when cross-compiling)
LIBS="$savedlibs"
]
)
])
])
fi
+AC_MSG_CHECKING([whether to enable the instrument functions code])
+AC_ARG_ENABLE([instrument-functions],
+ [AS_HELP_STRING([--enable-instrument-functions],
+ [enable instrument functions code [default=no]])],
+ [],
+ [enableval=no])
+case "$enableval" in
+yes) AC_MSG_RESULT(yes)
+ AC_CHECK_LIB([bfd], [bfd_init],
+ [true],
+ [AC_MSG_ERROR(
+ [--enable-instrument-functions was given, but test for library libbfd failed. Please install the 'binutils-dev' package.])],
+ [])
+ AC_DEFINE(ENABLE_INSTRUMENT_FUNCTIONS, 1,
+ [define if you want to build the instrument functions code])
+ LOCALSRC="$LOCALSRC instrument-functions.c"
+ # Add '-finstrument-functions' instrumentation option to generate
+ # instrumentation calls for entry and exit to functions.
+ # Try to avoid Address Space Layout Randomization (ALSR).
+ CFLAGS="$CFLAGS -O0 -ggdb -finstrument-functions -fno-stack-protector -fno-pic"
+ LDFLAGS="$LDFLAGS -O0 -ggdb -fno-stack-protector -no-pie"
+ LIBS="$LIBS -lbfd"
+ ;;
+*) AC_MSG_RESULT(no)
+ ;;
+esac
+
AC_MSG_CHECKING([whether to enable the possibly-buggy SMB printer])
AC_ARG_ENABLE([smb],
[AS_HELP_STRING([--enable-smb],
[enable possibly-buggy SMB printer [default=no]])],
[],
[enableval=no])
case "$enableval" in
yes) AC_MSG_RESULT(yes)
AC_DEFINE(ENABLE_SMB, 1,
[define if you want to build the possibly-buggy SMB printer])
LOCALSRC="print-smb.c smbutil.c $LOCALSRC"
;;
*) AC_MSG_RESULT(no)
;;
esac
-AC_ARG_WITH(user, [ --with-user=USERNAME drop privileges by default to USERNAME])
AC_MSG_CHECKING([whether to drop root privileges by default])
-if test ! -z "$with_user" ; then
- AC_DEFINE_UNQUOTED(WITH_USER, "$withval",
- [define if should drop privileges by default])
- AC_MSG_RESULT(to \"$withval\")
-else
- AC_MSG_RESULT(no)
-fi
+AC_ARG_WITH(
+ [user],
+ [AS_HELP_STRING([--with-user=USERNAME],
+ [drop privileges by default to USERNAME]
+ )],
+ [],
+ [withval=no])
+AS_CASE(["$withval"],
+ [no], [AC_MSG_RESULT(no)],
+ [''|yes], [AC_MSG_ERROR([--with-user requires a username])],
+ [
+ AC_DEFINE_UNQUOTED(WITH_USER, "$withval",
+ [define if should drop privileges by default])
+ AC_MSG_RESULT([yes, to user "$withval"])
+ ]
+)
-AC_ARG_WITH(chroot, [ --with-chroot=DIRECTORY when dropping privileges, chroot to DIRECTORY])
AC_MSG_CHECKING([whether to chroot])
-if test ! -z "$with_chroot" && test "$with_chroot" != "no" ; then
- AC_DEFINE_UNQUOTED(WITH_CHROOT, "$withval",
- [define if should chroot when dropping privileges])
- AC_MSG_RESULT(to \"$withval\")
-else
- AC_MSG_RESULT(no)
-fi
+AC_ARG_WITH(
+ [chroot],
+ [AS_HELP_STRING([--with-chroot=DIRECTORY],
+ [when dropping privileges, chroot to DIRECTORY]
+ )],
+ [],
+ [withval=no]
+)
+AS_CASE(["$withval"],
+ [no], [AC_MSG_RESULT(no)],
+ [''|yes], [AC_MSG_ERROR([--with-chroot requires a directory])],
+ [
+ AC_DEFINE_UNQUOTED(WITH_CHROOT, "$withval",
+ [define if should chroot when dropping privileges])
+ AC_MSG_RESULT([yes, to directory "$withval"])
+ ]
+)
AC_ARG_WITH(sandbox-capsicum,
AS_HELP_STRING([--with-sandbox-capsicum],
[use Capsicum security functions @<:@default=yes, if available@:>@]))
#
# Check whether various functions are available. If any are, set
# ac_lbl_capsicum_function_seen to yes; if any are not, set
# ac_lbl_capsicum_function_not_seen to yes.
#
# We don't check cap_rights_init(), as it's a macro, wrapping another
# function, in at least some versions of FreeBSD, and AC_CHECK_FUNCS()
# doesn't handle that.
#
# All of the ones we check for must be available in order to enable
# capsicum sandboxing.
#
# XXX - do we need to check for all of them, or are there some that, if
# present, imply others are present?
#
if test -z "$with_sandbox_capsicum" || test "$with_sandbox_capsicum" != "no" ; then
#
# First, make sure we have the required header.
#
AC_CHECK_HEADER(sys/capsicum.h,
[
#
# We do; now make sure we have the required functions.
#
AC_CHECK_FUNCS(cap_enter cap_rights_limit cap_ioctls_limit openat,
ac_lbl_capsicum_function_seen=yes,
ac_lbl_capsicum_function_not_seen=yes)
])
AC_CHECK_LIB(casper, cap_init, LIBS="$LIBS -lcasper")
AC_CHECK_LIB(cap_dns, cap_gethostbyaddr, LIBS="$LIBS -lcap_dns")
fi
AC_MSG_CHECKING([whether to sandbox using capsicum])
if test "x$ac_lbl_capsicum_function_seen" = "xyes" -a "x$ac_lbl_capsicum_function_not_seen" != "xyes"; then
AC_DEFINE(HAVE_CAPSICUM, 1, [capsicum support available])
AC_MSG_RESULT(yes)
else
AC_MSG_RESULT(no)
fi
AC_MSG_CHECKING([whether to sandbox using Casper library])
if test "x$ac_cv_lib_casper_cap_init" = "xyes" -a "x$ac_cv_lib_cap_dns_cap_gethostbyaddr" = "xyes"; then
AC_DEFINE(HAVE_CASPER, 1, [Casper support available])
AC_MSG_RESULT(yes)
else
AC_MSG_RESULT(no)
fi
#
# We must check this before checking whether to check the OS's IPv6,
# support because, on some platforms (such as SunOS 5.x), the test
# program requires the extra networking libraries.
#
AC_LBL_LIBRARY_NET
#
# Check whether AF_INET6 and struct in6_addr are defined.
# If they aren't both defined, we don't have sufficient OS
# support for IPv6, so we don't look for IPv6 support libraries,
# and we define AF_INET6 and struct in6_addr ourselves.
#
AC_MSG_CHECKING([whether the operating system supports IPv6])
AC_COMPILE_IFELSE(
[
AC_LANG_SOURCE(
[[
#include <string.h>
/* AF_INET6 available check */
#include <sys/types.h>
#ifdef _WIN32
#include <ws2tcpip.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#endif
#ifdef AF_INET6
void
foo(struct in6_addr *addr)
{
memset(addr, 0, sizeof (struct in6_addr));
}
#else
#error "AF_INET6 not defined"
#endif
]])
],
[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_OS_IPV6_SUPPORT, 1,
[define if the OS provides AF_INET6 and struct in6_addr])
ipv6=yes
],
[
AC_MSG_RESULT(no)
ipv6=no
]
)
ipv6type=unknown
ipv6lib=none
ipv6trylibc=no
if test "$ipv6" = "yes"; then
AC_MSG_CHECKING([ipv6 stack type])
for i in inria kame linux-glibc linux-libinet6 toshiba v6d zeta; do
case $i in
inria)
dnl http://www.kame.net/
AC_EGREP_CPP(yes,
[#include <netinet/in.h>
#ifdef IPV6_INRIA_VERSION
yes
#endif],
[ipv6type=$i])
;;
kame)
dnl http://www.kame.net/
AC_EGREP_CPP(yes,
[#include <netinet/in.h>
#ifdef __KAME__
yes
#endif],
[ipv6type=$i;
ipv6lib=inet6;
ipv6libdir=/usr/local/v6/lib;
ipv6trylibc=yes])
;;
linux-glibc)
dnl http://www.v6.linux.or.jp/
AC_EGREP_CPP(yes,
[#include <features.h>
#if defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1
yes
#endif],
[ipv6type=$i])
;;
linux-libinet6)
dnl http://www.v6.linux.or.jp/
dnl
dnl This also matches Solaris 8 and Tru64 UNIX 5.1,
dnl and possibly other versions of those OSes
dnl
if test -d /usr/inet6 -o -f /usr/include/netinet/ip6.h; then
ipv6type=$i
ipv6lib=inet6
ipv6libdir=/usr/inet6/lib
ipv6trylibc=yes;
CFLAGS="-I/usr/inet6/include $CFLAGS"
fi
;;
toshiba)
AC_EGREP_CPP(yes,
[#include <sys/param.h>
#ifdef _TOSHIBA_INET6
yes
#endif],
[ipv6type=$i;
ipv6lib=inet6;
ipv6libdir=/usr/local/v6/lib])
;;
v6d)
AC_EGREP_CPP(yes,
[#include </usr/local/v6/include/sys/v6config.h>
#ifdef __V6D__
yes
#endif],
[ipv6type=$i;
ipv6lib=v6;
ipv6libdir=/usr/local/v6/lib;
CFLAGS="-I/usr/local/v6/include $CFLAGS"])
;;
zeta)
AC_EGREP_CPP(yes,
[#include <sys/param.h>
#ifdef _ZETA_MINAMI_INET6
yes
#endif],
[ipv6type=$i;
ipv6lib=inet6;
ipv6libdir=/usr/local/v6/lib])
;;
esac
if test "$ipv6type" != "unknown"; then
break
fi
done
AC_MSG_RESULT($ipv6type)
fi
if test "$ipv6" = "yes" -a "$ipv6lib" != "none"; then
if test -d $ipv6libdir -a -f $ipv6libdir/lib$ipv6lib.a; then
LIBS="-L$ipv6libdir -l$ipv6lib $LIBS"
echo "You have $ipv6lib library, using it"
else
if test "$ipv6trylibc" = "yes"; then
echo "You do not have $ipv6lib library, using libc"
else
echo 'Fatal: no $ipv6lib library found. cannot continue.'
echo "You need to fetch lib$ipv6lib.a from appropriate"
echo 'ipv6 kit and compile beforehand.'
exit 1
fi
fi
fi
AC_REPLACE_FUNCS(strlcat strlcpy strdup strsep getservent getopt_long)
AC_CHECK_FUNCS(fork vfork)
AC_CHECK_FUNCS(setlinebuf)
#
-# Make sure we have vsnprintf() and snprintf(); we require them.
+# Make sure we have snprintf(); we require it.
#
-AC_CHECK_FUNC(vsnprintf,,
- AC_MSG_ERROR([vsnprintf() is required but wasn't found]))
AC_CHECK_FUNC(snprintf,,
AC_MSG_ERROR([snprintf() is required but wasn't found]))
#
-# Define HAVE_NO_PRINTF_Z to make it possible to disable test cases that
-# depend on %zu.
+# It became apparent at some point that using a suitable C99 compiler does not
+# automatically mean snprintf(3) implementation in the libc supports all the
+# modifiers and specifiers used in the project, so let's test that before the
+# build, not after.
+#
+# Testing the sizeof_t length modifier takes making an snprintf() call and
+# comparing the actual result with the expected result. If this fails, it will
+# most likely happen at run time, not compile time.
#
-AC_MSG_CHECKING([whether printf(3) supports the z length modifier])
+# Testing the 64-bit conversion specifiers in addition to that requires the
+# <inttypes.h> header to be present and the macros to be defined, so if this
+# fails, it will more likely happen at compile time.
+#
+AC_MSG_CHECKING([whether snprintf is suitable])
AC_RUN_IFELSE(
[
AC_LANG_SOURCE([[
#include <stdio.h>
#include <string.h>
+#include <inttypes.h>
+#include <sys/types.h>
int main()
{
char buf[100];
+ uint64_t t = (uint64_t)1 << 32;
+
snprintf(buf, sizeof(buf), "%zu", sizeof(buf));
- return strncmp(buf, "100", sizeof(buf)) ? 1 : 0;
+ if (strncmp(buf, "100", sizeof(buf)))
+ return 1;
+
+ snprintf(buf, sizeof(buf), "%zd", -sizeof(buf));
+ if (strncmp(buf, "-100", sizeof(buf)))
+ return 2;
+
+ snprintf(buf, sizeof(buf), "%" PRId64, -t);
+ if (strncmp(buf, "-4294967296", sizeof(buf)))
+ return 3;
+
+ snprintf(buf, sizeof(buf), "0o%" PRIo64, t);
+ if (strncmp(buf, "0o40000000000", sizeof(buf)))
+ return 4;
+
+ snprintf(buf, sizeof(buf), "0x%" PRIx64, t);
+ if (strncmp(buf, "0x100000000", sizeof(buf)))
+ return 5;
+
+ snprintf(buf, sizeof(buf), "%" PRIu64, t);
+ if (strncmp(buf, "4294967296", sizeof(buf)))
+ return 6;
+
+ return 0;
}
]])
],
[
AC_MSG_RESULT(yes)
],
[
AC_MSG_RESULT(no)
- AC_DEFINE(HAVE_NO_PRINTF_Z, 1,
- [Define to 1 if printf(3) does not support the z length modifier.])
+ AC_MSG_ERROR(
+[The snprintf(3) implementation in this libc is not suitable,
+tcpdump would not work correctly even if it managed to compile.])
],
[
AC_MSG_RESULT(not while cross-compiling)
]
)
AC_CHECK_LIB(rpc, main) dnl It's unclear why we might need -lrpc
dnl Some platforms may need -lnsl for getrpcbynumber.
AC_SEARCH_LIBS(getrpcbynumber, nsl,
AC_DEFINE(HAVE_GETRPCBYNUMBER, 1, [define if you have getrpcbynumber()]))
AC_LBL_LIBPCAP(V_PCAPDEP, V_INCLS)
#
# Check for these after AC_LBL_LIBPCAP, so we link with the appropriate
# libraries (e.g., "-lsocket -lnsl" on Solaris).
#
# You are in a twisty little maze of UN*Xes, all different.
# Some might not have ether_ntohost().
# Some might have it and declare it in <net/ethernet.h>.
# Some might have it and declare it in <netinet/ether.h>
# Some might have it and declare it in <sys/ethernet.h>.
# Some might have it and declare it in <arpa/inet.h>.
# Some might have it and declare it in <netinet/if_ether.h>.
# Some might have it and not declare it in any header file.
#
# Before you is a C compiler.
#
AC_CHECK_FUNCS(ether_ntohost, [
AC_CACHE_CHECK(for buggy ether_ntohost, ac_cv_buggy_ether_ntohost, [
- AC_TRY_RUN([
+ AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include <netdb.h>
#include <netinet/ether.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
int
main(int argc, char **argv)
{
u_char ea[6] = { 0xff, 0xff, 0xff, 0xff, 0xff };
char name[MAXHOSTNAMELEN];
ether_ntohost(name, (struct ether_addr *)ea);
exit(0);
}
+ ]])
], [ac_cv_buggy_ether_ntohost=no],
[ac_cv_buggy_ether_ntohost=yes],
[ac_cv_buggy_ether_ntohost="not while cross-compiling"])])
if test "$ac_cv_buggy_ether_ntohost" = "no"; then
AC_DEFINE(USE_ETHER_NTOHOST, 1,
[define if you have ether_ntohost() and it works])
fi
])
if test "$ac_cv_func_ether_ntohost" = yes -a \
"$ac_cv_buggy_ether_ntohost" = "no"; then
#
# OK, we have ether_ntohost(). Is it declared in <net/ethernet.h>?
#
# This test fails if we don't have <net/ethernet.h> or if we do
# but it doesn't declare ether_ntohost().
#
AC_CHECK_DECL(ether_ntohost,
[
AC_DEFINE(NET_ETHERNET_H_DECLARES_ETHER_NTOHOST,,
[Define to 1 if net/ethernet.h declares `ether_ntohost'])
],,
[
#include <net/ethernet.h>
])
#
# Did that succeed?
#
if test "$ac_cv_have_decl_ether_ntohost" != yes; then
#
# No, how about <netinet/ether.h>, as on Linux?
#
# This test fails if we don't have <netinet/ether.h>
# or if we do but it doesn't declare ether_ntohost().
#
# Unset ac_cv_have_decl_ether_ntohost so we don't
# treat the previous failure as a cached value and
# suppress the next test.
#
unset ac_cv_have_decl_ether_ntohost
AC_CHECK_DECL(ether_ntohost,
[
- AC_DEFINE(NETINET_ETHER_H_DECLARES_ETHER_NTOHOST,,
+ AC_DEFINE(NETINET_ETHER_H_DECLARES_ETHER_NTOHOST,1,
[Define to 1 if netinet/ether.h declares `ether_ntohost'])
],,
[
#include <netinet/ether.h>
])
fi
#
# Did that succeed?
#
if test "$ac_cv_have_decl_ether_ntohost" != yes; then
#
# No, how about <sys/ethernet.h>, as on Solaris 10
# and later?
#
# This test fails if we don't have <sys/ethernet.h>
# or if we do but it doesn't declare ether_ntohost().
#
# Unset ac_cv_have_decl_ether_ntohost so we don't
# treat the previous failure as a cached value and
# suppress the next test.
#
unset ac_cv_have_decl_ether_ntohost
AC_CHECK_DECL(ether_ntohost,
[
AC_DEFINE(SYS_ETHERNET_H_DECLARES_ETHER_NTOHOST,,
[Define to 1 if sys/ethernet.h declares `ether_ntohost'])
],,
[
#include <sys/ethernet.h>
])
fi
#
# Did that succeed?
#
if test "$ac_cv_have_decl_ether_ntohost" != yes; then
#
# No, how about <arpa/inet.h>, as in AIX?
#
# This test fails if we don't have <arpa/inet.h>
# (if we have ether_ntohost(), we should have
# networking, and if we have networking, we should
# have <arpa/inet.h>) or if we do but it doesn't
# declare ether_ntohost().
#
# Unset ac_cv_have_decl_ether_ntohost so we don't
# treat the previous failure as a cached value and
# suppress the next test.
#
unset ac_cv_have_decl_ether_ntohost
AC_CHECK_DECL(ether_ntohost,
[
AC_DEFINE(ARPA_INET_H_DECLARES_ETHER_NTOHOST,,
[Define to 1 if arpa/inet.h declares `ether_ntohost'])
],,
[
#include <arpa/inet.h>
])
fi
#
# Did that succeed?
#
if test "$ac_cv_have_decl_ether_ntohost" != yes; then
#
# No, how about <netinet/if_ether.h>?
# On some platforms, it requires <net/if.h> and
# <netinet/in.h>, and we always include it with
# both of them, so test it with both of them.
#
# This test fails if we don't have <netinet/if_ether.h>
# and the headers we include before it, or if we do but
# <netinet/if_ether.h> doesn't declare ether_hostton().
#
# Unset ac_cv_have_decl_ether_ntohost so we don't
# treat the previous failure as a cached value and
# suppress the next test.
#
unset ac_cv_have_decl_ether_ntohost
AC_CHECK_DECL(ether_ntohost,
[
AC_DEFINE(NETINET_IF_ETHER_H_DECLARES_ETHER_NTOHOST,,
[Define to 1 if netinet/if_ether.h declares `ether_ntohost'])
],,
[
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
])
fi
#
# After all that, is ether_ntohost() declared?
#
if test "$ac_cv_have_decl_ether_ntohost" = yes; then
#
# Yes.
#
AC_DEFINE(HAVE_DECL_ETHER_NTOHOST, 1,
[Define to 1 if you have the declaration of `ether_ntohost'])
else
#
# No, we'll have to declare it ourselves.
# Do we have "struct ether_addr" if we include
# <netinet/if_ether.h>?
#
AC_CHECK_TYPES(struct ether_addr,,,
[
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
])
fi
fi
dnl
dnl Check for "pcap_list_datalinks()" and use a substitute version if
dnl it's not present. If it is present, check for "pcap_free_datalinks()";
dnl if it's not present, we don't replace it for now. (We could do so
dnl on UN*X, but not on Windows, where hilarity ensues if a program
dnl built with one version of the MSVC support library tries to free
dnl something allocated by a library built with another version of
dnl the MSVC support library.)
dnl
AC_CHECK_FUNC(pcap_list_datalinks,
[
AC_DEFINE(HAVE_PCAP_LIST_DATALINKS, 1,
[define if libpcap has pcap_list_datalinks()])
AC_CHECK_FUNCS(pcap_free_datalinks)
],
[
AC_LIBOBJ(datalinks)
])
dnl
dnl Check for "pcap_datalink_name_to_val()", and use a substitute
dnl version if it's not present. If it is present, check for
dnl "pcap_datalink_val_to_description()", and if we don't have it,
dnl use a substitute version.
dnl
AC_CHECK_FUNC(pcap_datalink_name_to_val,
[
AC_DEFINE(HAVE_PCAP_DATALINK_NAME_TO_VAL, 1,
[define if libpcap has pcap_datalink_name_to_val()])
AC_CHECK_FUNC(pcap_datalink_val_to_description,
AC_DEFINE(HAVE_PCAP_DATALINK_VAL_TO_DESCRIPTION, 1,
[define if libpcap has pcap_datalink_val_to_description()]),
[
AC_LIBOBJ(dlnames)
])
],
[
AC_LIBOBJ(dlnames)
])
dnl
dnl Check for "pcap_set_datalink()"; you can't substitute for it if
dnl it's absent (it has hooks into libpcap), so just define the
dnl HAVE_ value if it's there.
dnl
AC_CHECK_FUNCS(pcap_set_datalink)
dnl
dnl Check for "pcap_breakloop()"; you can't substitute for it if
dnl it's absent (it has hooks into the live capture routines),
dnl so just define the HAVE_ value if it's there.
dnl
AC_CHECK_FUNCS(pcap_breakloop)
#
# Do we have the new open API? Check for pcap_create, and assume that,
# if we do, we also have pcap_activate() and the other new routines
# introduced in libpcap 1.0.0.
#
AC_CHECK_FUNCS(pcap_create)
if test $ac_cv_func_pcap_create = "yes" ; then
#
# OK, do we have pcap_set_tstamp_type? If so, assume we have
# pcap_list_tstamp_types and pcap_free_tstamp_types as well.
#
AC_CHECK_FUNCS(pcap_set_tstamp_type)
#
# And do we have pcap_set_tstamp_precision? If so, we assume
# we also have pcap_open_offline_with_tstamp_precision.
#
AC_CHECK_FUNCS(pcap_set_tstamp_precision)
fi
#
# Check for a miscellaneous collection of functions which we use
# if we have them.
#
AC_CHECK_FUNCS(pcap_findalldevs)
-if test $ac_cv_func_pcap_findalldevs = "yes" ; then
-dnl Check for libpcap having pcap_findalldevs() but the pcap.h header
-dnl not having pcap_if_t; some versions of Mac OS X shipped with pcap.h
-dnl from 0.6 and libpcap 0.8, so that libpcap had pcap_findalldevs but
-dnl pcap.h didn't have pcap_if_t.
- savedcppflags="$CPPFLAGS"
- CPPFLAGS="$CPPFLAGS $V_INCLS"
- AC_CHECK_TYPES(pcap_if_t, , , [#include <pcap.h>])
- CPPFLAGS="$savedcppflags"
-fi
AC_CHECK_FUNCS(pcap_dump_flush pcap_lib_version)
if test $ac_cv_func_pcap_lib_version = "no" ; then
AC_MSG_CHECKING(whether pcap_version is defined by libpcap)
- AC_TRY_LINK([],
- [
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
extern char pcap_version[];
return (int)pcap_version;
+ ]])
],
- ac_lbl_cv_pcap_version_defined=yes,
- ac_lbl_cv_pcap_version_defined=no)
+ [ac_lbl_cv_pcap_version_defined=yes],
+ [ac_lbl_cv_pcap_version_defined=no])
if test "$ac_lbl_cv_pcap_version_defined" = yes ; then
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_PCAP_VERSION, 1, [define if libpcap has pcap_version])
else
AC_MSG_RESULT(no)
fi
fi
AC_CHECK_FUNCS(pcap_setdirection pcap_set_immediate_mode pcap_dump_ftell64)
-AC_CHECK_FUNCS(pcap_open pcap_findalldevs_ex)
+#
+# See the comment in AC_LBL_LIBPCAP in aclocal.m4 for the reason
+# why we don't check for remote-capture APIs if we're building
+# with the system libpcap on macOS.
+#
+if test "$_dont_check_for_remote_apis" != "yes"; then
+ AC_CHECK_FUNCS(pcap_open pcap_findalldevs_ex)
+fi
AC_REPLACE_FUNCS(pcap_dump_ftell)
#
# Check for special debugging functions
#
AC_CHECK_FUNCS(pcap_set_parser_debug)
if test "$ac_cv_func_pcap_set_parser_debug" = "no" ; then
#
# OK, we don't have pcap_set_parser_debug() to set the libpcap
# filter expression parser debug flag; can we directly set the
# flag?
AC_MSG_CHECKING(whether pcap_debug is defined by libpcap)
- AC_TRY_LINK([],
- [
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
extern int pcap_debug;
return pcap_debug;
+ ]])
],
- ac_lbl_cv_pcap_debug_defined=yes,
- ac_lbl_cv_pcap_debug_defined=no)
+ [ac_lbl_cv_pcap_debug_defined=yes],
+ [ac_lbl_cv_pcap_debug_defined=no])
if test "$ac_lbl_cv_pcap_debug_defined" = yes ; then
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_PCAP_DEBUG, 1, [define if libpcap has pcap_debug])
else
AC_MSG_RESULT(no)
#
# OK, what about "yydebug"?
#
AC_MSG_CHECKING(whether yydebug is defined by libpcap)
- AC_TRY_LINK([],
- [
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
extern int yydebug;
return yydebug;
+ ]])
],
- ac_lbl_cv_yydebug_defined=yes,
- ac_lbl_cv_yydebug_defined=no)
+ [ac_lbl_cv_yydebug_defined=yes],
+ [ac_lbl_cv_yydebug_defined=no])
if test "$ac_lbl_cv_yydebug_defined" = yes ; then
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_YYDEBUG, 1, [define if libpcap has yydebug])
else
AC_MSG_RESULT(no)
fi
fi
fi
AC_CHECK_FUNCS(pcap_set_optimizer_debug)
AC_REPLACE_FUNCS(bpf_dump) dnl moved to libpcap in 0.6
-V_GROUP=0
-if test -f /etc/group -a ! -z "`grep '^wheel:' /etc/group`" ; then
- V_GROUP=wheel
-fi
#
# Assume V7/BSD convention for man pages (file formats in section 5,
# miscellaneous info in section 7).
#
MAN_FILE_FORMATS=5
MAN_MISC_INFO=7
case "$host_os" in
aix*)
dnl Workaround to enable certain features
AC_DEFINE(_SUN,1,[define on AIX to get certain functions])
;;
hpux*)
#
# Use System V conventions for man pages.
#
MAN_FILE_FORMATS=4
MAN_MISC_INFO=5
;;
irix*)
V_GROUP=sys
#
# Use System V conventions for man pages.
#
MAN_FILE_FORMATS=4
MAN_MISC_INFO=5
;;
osf*)
V_GROUP=system
#
# Use System V conventions for man pages.
#
MAN_FILE_FORMATS=4
MAN_MISC_INFO=5
;;
solaris*)
- V_GROUP=sys
-
#
# Use System V conventions for man pages.
#
MAN_FILE_FORMATS=4
MAN_MISC_INFO=5
;;
esac
-if test -f /dev/bpf0 ; then
- V_GROUP=bpf
-fi
-
#
# Make sure we have a definition for C99's uintptr_t (regardless of
# whether the environment is a C99 environment or not).
#
AC_TYPE_UINTPTR_T
+savedcppflags="$CPPFLAGS"
+CPPFLAGS="$CPPFLAGS $V_INCLS"
+
#
# Check whether we have pcap/pcap-inttypes.h.
# If we do, we use that to get the C99 types defined.
#
-savedcppflags="$CPPFLAGS"
-CPPFLAGS="$CPPFLAGS $V_INCLS"
AC_CHECK_HEADERS(pcap/pcap-inttypes.h)
+
+#
+# At compile time HAVE_PCAP_FINDALLDEVS depends on HAVE_PCAP_IF_T.
+#
+AC_CHECK_TYPES(pcap_if_t, , , [#include <pcap.h>])
+
CPPFLAGS="$savedcppflags"
#
# Define the old BSD specified-width types in terms of the C99 types;
# we may need them with libpcap include files.
#
AC_CHECK_TYPE([u_int8_t], ,
[AC_DEFINE([u_int8_t], [uint8_t],
[Define to `uint8_t' if u_int8_t not defined.])],
[AC_INCLUDES_DEFAULT
#include <sys/types.h>
])
AC_CHECK_TYPE([u_int16_t], ,
[AC_DEFINE([u_int16_t], [uint16_t],
[Define to `uint16_t' if u_int16_t not defined.])],
[AC_INCLUDES_DEFAULT
#include <sys/types.h>
])
AC_CHECK_TYPE([u_int32_t], ,
[AC_DEFINE([u_int32_t], [uint32_t],
[Define to `uint32_t' if u_int32_t not defined.])],
[AC_INCLUDES_DEFAULT
#include <sys/types.h>
])
AC_CHECK_TYPE([u_int64_t], ,
[AC_DEFINE([u_int64_t], [uint64_t],
[Define to `uint64_t' if u_int64_t not defined.])],
[AC_INCLUDES_DEFAULT
#include <sys/types.h>
])
AC_PROG_RANLIB
AC_CHECK_TOOL([AR], [ar])
AC_LBL_DEVEL(V_CCOPT)
# Check for OpenSSL/libressl libcrypto
AC_MSG_CHECKING(whether to use OpenSSL/libressl libcrypto)
# Specify location for both includes and libraries.
want_libcrypto=ifavailable
AC_ARG_WITH(crypto,
AS_HELP_STRING([--with-crypto]@<:@=DIR@:>@,
[use OpenSSL/libressl libcrypto (located in directory DIR, if specified) @<:@default=yes, if available@:>@]),
[
if test $withval = no
then
# User doesn't want to link with libcrypto.
want_libcrypto=no
AC_MSG_RESULT(no)
elif test $withval = yes
then
# User wants to link with libcrypto but hasn't specified
# a directory.
want_libcrypto=yes
AC_MSG_RESULT(yes)
else
# User wants to link with libcrypto and has specified
# a directory, so use the provided value.
want_libcrypto=yes
libcrypto_root=$withval
AC_MSG_RESULT([yes, using the version installed in $withval])
-
- #
- # Put the subdirectories of the libcrypto root directory
- # at the front of the header and library search path.
- #
- CFLAGS="-I$withval/include $CFLAGS"
- LIBS="-L$withval/lib $LIBS"
fi
],[
#
# Use libcrypto if it's present, otherwise don't; no directory
# was specified.
#
want_libcrypto=ifavailable
AC_MSG_RESULT([yes, if available])
])
if test "$want_libcrypto" != "no"; then
#
- # Don't check for libcrypto unless we have its headers;
- # Apple, bless their pointy little heads, apparently ship
- # libcrypto as a library, but not the header files, in
- # El Capitan, probably because they don't want you writing
- # nasty portable code that could run on other UN*Xes, they
- # want you writing code that uses their Shiny New Crypto
- # Library and that only runs on macOS.
+ # Were we told where to look for libcrypto?
#
- AC_CHECK_HEADER(openssl/crypto.h,
- [
- AC_CHECK_LIB(crypto, DES_cbc_encrypt)
- if test "$ac_cv_lib_crypto_DES_cbc_encrypt" = "yes"; then
- AC_CHECK_HEADERS(openssl/evp.h)
+ if test -z "$libcrypto_root"; then
+ #
+ # No.
+ #
+ # First, try looking for it with pkg-config, if we have it.
+ #
+ # Homebrew's pkg-config does not, by default, look for
+ # pkg-config files for packages it has installed.
+ # Furthermore, at least for OpenSSL, they appear to be
+ # dumped in package-specific directories whose paths are
+ # not only package-specific but package-version-specific.
+ #
+ # So the only way to find openssl is to get the value of
+ # PKG_CONFIG_PATH from "brew --env openssl" and add that
+ # to PKG_CONFIG_PATH. (No, we can't just assume it's under
+ # /usr/local; Homebrew have conveniently chosen to put it
+ # under /opt/homebrew on ARM.)
+ #
+ # That's the nice thing about Homebrew - it makes things easier!
+ # Thanks!
+ #
+ save_PKG_CONFIG_PATH="$PKG_CONFIG_PATH"
+ if test -n "$BREW"; then
+ openssl_pkgconfig_dir=`$BREW --env --plain openssl | sed -n 's/PKG_CONFIG_PATH: //p'`
+ PKG_CONFIG_PATH="$openssl_pkgconfig_dir:$PKG_CONFIG_PATH"
+ fi
+ PKG_CHECK_MODULE(LIBCRYPTO, libcrypto,
+ [
#
- # OK, then:
+ # We found OpenSSL/libressl libcrypto.
+ #
+ HAVE_LIBCRYPTO=yes
+ ])
+ PKG_CONFIG_PATH="$save_PKG_CONFIG_PATH"
+
+ #
+ # If it wasn't found, and we have Homebrew installed, see
+ # if it's in Homebrew.
+ #
+ if test "x$HAVE_LIBCRYPTO" != "xyes" -a -n "$BREW"; then
+ AC_MSG_CHECKING(for openssl in Homebrew)
#
- # 1) do we have EVP_CIPHER_CTX_new?
- # If so, we use it to allocate an
- # EVP_CIPHER_CTX, as EVP_CIPHER_CTX may be
- # opaque; otherwise, we allocate it ourselves.
+ # The brew man page lies when it speaks of
+ # $BREW --prefix --installed <formula>
+ # outputting nothing. In Homebrew 3.3.16,
+ # it produces output regardless of whether
+ # the formula is installed or not, so we
+ # send the standard output and error to
+ # the bit bucket.
#
- # 2) do we have EVP_DecryptInit_ex()?
- # If so, we use it, because we need to be
- # able to make two "initialize the cipher"
- # calls, one with the cipher and key, and
- # one with the IV, and, as of OpenSSL 1.1,
- # You Can't Do That with EVP_DecryptInit(),
- # because a call to EVP_DecryptInit() will
- # unconditionally clear the context, and
- # if you don't supply a cipher, it'll
- # clear the cipher, rendering the context
- # unusable and causing a crash.
+ # libcrypto isn't a formula, openssl is a formula.
#
- AC_CHECK_FUNCS(EVP_CIPHER_CTX_new EVP_DecryptInit_ex)
+ if $BREW --prefix --installed openssl >/dev/null 2>&1; then
+ #
+ # Yes. Get the include directory and library
+ # directory. (No, we can't just assume it's
+ # under /usr/local; Homebrew have conveniently
+ # chosen to put it under /opt/homebrew on ARM.)
+ #
+ AC_MSG_RESULT(yes)
+ HAVE_LIBCRYPTO=yes
+ openssl_path=`$BREW --prefix openssl`
+ LIBCRYPTO_CFLAGS="-I$openssl_path/include"
+ LIBCRYPTO_LIBS="-L$openssl_path/lib -lcrypto"
+ else
+ AC_MSG_RESULT(no)
+ fi
fi
- ])
+
+ #
+ # If it wasn't found, and /usr/local/include and /usr/local/lib
+ # exist, check if it's in /usr/local. (We check whether they
+ # exist because, if they don't exist, the compiler will warn
+ # about that and then ignore the argument, so they test
+ # using just the system header files and libraries.)
+ #
+ # We include the standard include file to 1) make sure that
+ # it's installed (if it's just a shared library for the
+ # benefit of existing programs, that's not useful) and 2)
+ # because SSL_library_init() is a library routine in some
+ # versions and a #defined wrapper around OPENSSL_init_ssl()
+ # in others.
+ #
+ if test "x$HAVE_LIBCRYPTO" != "xyes" -a -d "/usr/local/include" -a -d "/usr/local/lib"; then
+ AC_LBL_SAVE_CHECK_STATE
+ CFLAGS="$CFLAGS -I/usr/local/include"
+ LIBS="$LIBS -L/usr/local/lib -lcrypto"
+ AC_MSG_CHECKING(whether we have an OpenSSL/libressl libcrypto in /usr/local that we can use)
+ AC_LINK_IFELSE([AC_LANG_PROGRAM(
+ [[
+#include <openssl/evp.h>
+ ]],
+ [[
+EVP_CIPHER_CTX_block_size((EVP_CIPHER_CTX *)0);
+return 0;
+ ]])],
+ [
+ AC_MSG_RESULT(yes)
+ HAVE_LIBCRYPTO=yes
+ LIBCRYPTO_CFLAGS="-I/usr/local/include"
+ LIBCRYPTO_LIBS="-L/usr/local/lib -lcrypto"
+ ],
+ AC_MSG_RESULT(no))
+ AC_LBL_RESTORE_CHECK_STATE
+ fi
+
+ #
+ # If it wasn't found, check if it's a system library.
+ #
+ # We include the standard include file to 1) make sure that
+ # it's installed (if it's just a shared library for the
+ # benefit of existing programs, that's not useful) and 2)
+ # make sure this isn't a newer macOS that provides libcrypto
+ # as a shared library but doesn't provide headers - Apple,
+ # bless their pointy little heads, apparently ship libcrypto
+ # as a library, but not the header files, in El Capitan and
+ # later, probably because they don't want you writing nasty
+ # portable code that could run on other UN*Xes, they want you
+ # writing code that uses their Shiny New Crypto Library and
+ # that thus only runs on macOS.
+ #
+ if test "x$HAVE_LIBCRYPTO" != "xyes"; then
+ AC_LBL_SAVE_CHECK_STATE
+ LIBS="$LIBS -lcrypto"
+ AC_MSG_CHECKING(whether we have a system OpenSSL/libressl that we can use)
+ AC_LINK_IFELSE([AC_LANG_PROGRAM(
+ [[
+#include <openssl/evp.h>
+ ]],
+ [[
+EVP_CIPHER_CTX_block_size((EVP_CIPHER_CTX *)0);
+return 0;
+ ]])],
+ [
+ AC_MSG_RESULT(yes)
+ HAVE_LIBCRYPTO=yes
+ LIBCRYPTO_LIBS="-lcrypto"
+ ],
+ AC_MSG_RESULT(no))
+ AC_LBL_RESTORE_CHECK_STATE
+ fi
+ else
+ #
+ # Yes.
+ #
+ # Look for it there.
+ #
+ AC_LBL_SAVE_CHECK_STATE
+ CFLAGS="$CFLAGS -I$libcrypto_root/include"
+ LIBS="$LIBS -L$libcrypto_root/lib -lcrypto"
+ AC_MSG_CHECKING(whether we have a system OpenSSL/libressl that we can use)
+ AC_LINK_IFELSE([AC_LANG_PROGRAM(
+ [[
+#include <openssl/evp.h>
+ ]],
+ [[
+EVP_CIPHER_CTX_block_size((EVP_CIPHER_CTX *)0);
+return 0;
+ ]])],
+ [
+ AC_MSG_RESULT(yes)
+ HAVE_LIBCRYPTO=yes
+ LIBCRYPTO_CFLAGS="-I$libcrypto_root/include"
+ LIBCRYPTO_LIBS="-L$libcrypto_root/lib -lcrypto"
+ ],
+ AC_MSG_RESULT(no))
+ AC_LBL_RESTORE_CHECK_STATE
+ fi
+
+ #
+ # OK, did we find it?
+ #
+ if test "x$HAVE_LIBCRYPTO" = "xyes"; then
+ AC_DEFINE([HAVE_LIBCRYPTO], [1], [Define to 1 if you have a usable `crypto' library (-lcrypto).])
+
+ #
+ # Put the subdirectories of the libcrypto root directory
+ # at the end of the header and library search path, to
+ # make sure they come after any -I or -L flags for
+ # a local libpcap - those must take precedence of any
+ # directory that might contain an installed version of
+ # libpcap.
+ #
+ V_INCLS="$V_INCLS $LIBCRYPTO_CFLAGS"
+ LIBS="$LIBS $LIBCRYPTO_LIBS"
+
+ #
+ # OK, then:
+ #
+ # 1) do we have EVP_CIPHER_CTX_new?
+ # If so, we use it to allocate an EVP_CIPHER_CTX, as
+ # EVP_CIPHER_CTX may be opaque; otherwise, we allocate it
+ # ourselves.
+ #
+ # 2) do we have EVP_DecryptInit_ex()?
+ # If so, we use it, because we need to be able to make
+ # two "initialize the cipher" calls, one with the cipher
+ # and key, and one with the IV, and, as of OpenSSL 1.1,
+ # You Can't Do That with EVP_DecryptInit(), because a
+ # call to EVP_DecryptInit() will unconditionally clear
+ # the context, and if you don't supply a cipher, it'll
+ # clear the cipher, rendering the context unusable and
+ # causing a crash.
+ #
+ AC_CHECK_FUNCS(EVP_CIPHER_CTX_new EVP_DecryptInit_ex)
+ else
+ AC_MSG_NOTICE(OpenSSL/libressl libcrypto not found)
+ fi
fi
# Check for libcap-ng
AC_MSG_CHECKING(whether to use libcap-ng)
# Specify location for both includes and libraries.
want_libcap_ng=ifavailable
AC_ARG_WITH(cap_ng,
AS_HELP_STRING([--with-cap-ng],
[use libcap-ng @<:@default=yes, if available@:>@]),
[
if test $withval = no
then
want_libcap_ng=no
AC_MSG_RESULT(no)
elif test $withval = yes
then
want_libcap_ng=yes
AC_MSG_RESULT(yes)
fi
],[
#
# Use libcap-ng if it's present, otherwise don't.
#
want_libcap_ng=ifavailable
AC_MSG_RESULT([yes, if available])
])
if test "$want_libcap_ng" != "no"; then
AC_CHECK_LIB(cap-ng, capng_change_id)
AC_CHECK_HEADERS(cap-ng.h)
fi
dnl
dnl set additional include path if necessary
if test "$missing_includes" = "yes"; then
CPPFLAGS="$CPPFLAGS -I$srcdir/missing"
V_INCLS="$V_INCLS -I$srcdir/missing"
fi
AC_SUBST(V_CCOPT)
AC_SUBST(V_DEFS)
-AC_SUBST(V_GROUP)
AC_SUBST(V_INCLS)
AC_SUBST(V_PCAPDEP)
AC_SUBST(LOCALSRC)
AC_SUBST(MAN_FILE_FORMATS)
AC_SUBST(MAN_MISC_INFO)
AC_PROG_INSTALL
AC_CONFIG_HEADER(config.h)
-AC_OUTPUT_COMMANDS([if test -f .devel; then
+AC_CONFIG_COMMANDS([.devel],[[if test -f .devel; then
echo timestamp > stamp-h
cat $srcdir/Makefile-devel-adds >> Makefile
make depend || exit 1
-fi])
-AC_OUTPUT(Makefile tcpdump.1)
+fi]],[[]])
+AC_CONFIG_FILES([Makefile tcpdump.1])
+AC_OUTPUT
exit 0
diff --git a/contrib/tcpdump/cpack.c b/contrib/tcpdump/cpack.c
index 9be7b47d8512..84d24009faa7 100644
--- a/contrib/tcpdump/cpack.c
+++ b/contrib/tcpdump/cpack.c
@@ -1,220 +1,218 @@
/*-
* Copyright (c) 2003, 2004 David Young. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of David Young may not be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID
* YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include <stdlib.h>
#include <string.h>
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "extract.h"
#include "cpack.h"
const uint8_t *
nd_cpack_next_boundary(const uint8_t *buf, const uint8_t *p, size_t alignment)
{
size_t misalignment = (size_t)(p - buf) % alignment;
if (misalignment == 0)
return p;
return p + (alignment - misalignment);
}
/* Advance to the next wordsize boundary. Return NULL if fewer than
* wordsize bytes remain in the buffer after the boundary. Otherwise,
* return a pointer to the boundary.
*/
const uint8_t *
nd_cpack_align_and_reserve(struct cpack_state *cs, size_t wordsize)
{
const uint8_t *next;
/* Ensure alignment. */
next = nd_cpack_next_boundary(cs->c_buf, cs->c_next, wordsize);
/* Too little space for wordsize bytes? */
if (next - cs->c_buf + wordsize > cs->c_len)
return NULL;
return next;
}
/* Advance by N bytes without returning them. */
int
nd_cpack_advance(struct cpack_state *cs, const size_t toskip)
{
/* No space left? */
if (cs->c_next - cs->c_buf + toskip > cs->c_len)
return -1;
cs->c_next += toskip;
return 0;
}
int
nd_cpack_init(struct cpack_state *cs, const uint8_t *buf, size_t buflen)
{
memset(cs, 0, sizeof(*cs));
cs->c_buf = buf;
cs->c_len = buflen;
cs->c_next = cs->c_buf;
return 0;
}
/* Unpack a 64-bit unsigned integer. */
int
nd_cpack_uint64(netdissect_options *ndo, struct cpack_state *cs, uint64_t *u)
{
const uint8_t *next;
if ((next = nd_cpack_align_and_reserve(cs, sizeof(*u))) == NULL)
return -1;
*u = GET_LE_U_8(next);
/* Move pointer past the uint64_t. */
cs->c_next = next + sizeof(*u);
return 0;
}
/* Unpack a 64-bit signed integer. */
int
nd_cpack_int64(netdissect_options *ndo, struct cpack_state *cs, int64_t *u)
{
const uint8_t *next;
if ((next = nd_cpack_align_and_reserve(cs, sizeof(*u))) == NULL)
return -1;
*u = GET_LE_S_8(next);
/* Move pointer past the int64_t. */
cs->c_next = next + sizeof(*u);
return 0;
}
/* Unpack a 32-bit unsigned integer. */
int
nd_cpack_uint32(netdissect_options *ndo, struct cpack_state *cs, uint32_t *u)
{
const uint8_t *next;
if ((next = nd_cpack_align_and_reserve(cs, sizeof(*u))) == NULL)
return -1;
*u = GET_LE_U_4(next);
/* Move pointer past the uint32_t. */
cs->c_next = next + sizeof(*u);
return 0;
}
/* Unpack a 32-bit signed integer. */
int
nd_cpack_int32(netdissect_options *ndo, struct cpack_state *cs, int32_t *u)
{
const uint8_t *next;
if ((next = nd_cpack_align_and_reserve(cs, sizeof(*u))) == NULL)
return -1;
*u = GET_LE_S_4(next);
/* Move pointer past the int32_t. */
cs->c_next = next + sizeof(*u);
return 0;
}
/* Unpack a 16-bit unsigned integer. */
int
nd_cpack_uint16(netdissect_options *ndo, struct cpack_state *cs, uint16_t *u)
{
const uint8_t *next;
if ((next = nd_cpack_align_and_reserve(cs, sizeof(*u))) == NULL)
return -1;
*u = GET_LE_U_2(next);
/* Move pointer past the uint16_t. */
cs->c_next = next + sizeof(*u);
return 0;
}
/* Unpack a 16-bit signed integer. */
int
nd_cpack_int16(netdissect_options *ndo, struct cpack_state *cs, int16_t *u)
{
const uint8_t *next;
if ((next = nd_cpack_align_and_reserve(cs, sizeof(*u))) == NULL)
return -1;
*u = GET_LE_S_2(next);
/* Move pointer past the int16_t. */
cs->c_next = next + sizeof(*u);
return 0;
}
/* Unpack an 8-bit unsigned integer. */
int
nd_cpack_uint8(netdissect_options *ndo, struct cpack_state *cs, uint8_t *u)
{
/* No space left? */
if ((size_t)(cs->c_next - cs->c_buf) >= cs->c_len)
return -1;
*u = GET_U_1(cs->c_next);
/* Move pointer past the uint8_t. */
cs->c_next++;
return 0;
}
/* Unpack an 8-bit signed integer. */
int
nd_cpack_int8(netdissect_options *ndo, struct cpack_state *cs, int8_t *u)
{
/* No space left? */
if ((size_t)(cs->c_next - cs->c_buf) >= cs->c_len)
return -1;
*u = GET_S_1(cs->c_next);
/* Move pointer past the int8_t. */
cs->c_next++;
return 0;
}
diff --git a/contrib/tcpdump/diag-control.h b/contrib/tcpdump/diag-control.h
index 3eb6bcaaf020..5e5a2dfe461a 100644
--- a/contrib/tcpdump/diag-control.h
+++ b/contrib/tcpdump/diag-control.h
@@ -1,186 +1,235 @@
/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
/*
* Copyright (c) 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 the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the Computer Systems
* Engineering Group at Lawrence Berkeley Laboratory.
* 4. Neither the name of the University nor of the Laboratory may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _diag_control_h
#define _diag_control_h
#include "compiler-tests.h"
#ifndef _MSC_VER
/*
* Clang and GCC both support this way of putting pragmas into #defines.
* We don't use it unless we have a compiler that supports it; the
* warning-suppressing pragmas differ between Clang and GCC, so we test
* for both of those separately.
*/
#define DIAG_DO_PRAGMA(x) _Pragma (#x)
#endif
/*
* XL C 12.1 and 13.1 for AIX require no attention in this department.
* XL C 16.1 defines both __GNUC__ and __clang__, so has to be tested first.
*/
#if ND_IS_AT_LEAST_XL_C_VERSION(16,1)
/*
* See respective Clang note below.
*/
#define DIAG_OFF_ASSIGN_ENUM \
DIAG_DO_PRAGMA(clang diagnostic push) \
DIAG_DO_PRAGMA(clang diagnostic ignored "-Wassign-enum")
#define DIAG_ON_ASSIGN_ENUM \
DIAG_DO_PRAGMA(clang diagnostic pop)
-
- #define DIAG_OFF_CAST_QUAL
- #define DIAG_ON_CAST_QUAL
- #define DIAG_OFF_DEPRECATION
- #define DIAG_ON_DEPRECATION
/*
* The current clang compilers also define __GNUC__ and __GNUC_MINOR__
* thus we need to test the clang case before the GCC one
*/
#elif ND_IS_AT_LEAST_CLANG_VERSION(2,8)
/*
* Clang complains if you OR together multiple enum values of a
* given enum type and them pass it as an argument of that enum
* type. Some libcap-ng routines use enums to define bit flags;
* we want to squelch the warnings that produces.
*/
#define DIAG_OFF_ASSIGN_ENUM \
DIAG_DO_PRAGMA(clang diagnostic push) \
DIAG_DO_PRAGMA(clang diagnostic ignored "-Wassign-enum")
#define DIAG_ON_ASSIGN_ENUM \
DIAG_DO_PRAGMA(clang diagnostic pop)
/*
* It also legitimately complains about some code in the BSD
* getopt_long() - that code explicitly and deliberately
* violates the contract by permuting the argument vector
* (declared as char const *argv[], meaning "I won't change
* the vector by changing any of its elements), as do the
* GNU and Solaris getopt_long(). This is documented in the
* man pages for all versions; it can be suppressed by setting
* the environment variable POSIXLY_CORRECT or by putting a "+"
* at the beginning of the option string.
*
* We suppress the warning.
*/
#define DIAG_OFF_CAST_QUAL \
DIAG_DO_PRAGMA(clang diagnostic push) \
DIAG_DO_PRAGMA(clang diagnostic ignored "-Wcast-qual")
#define DIAG_ON_CAST_QUAL \
DIAG_DO_PRAGMA(clang diagnostic pop)
/*
* Suppress deprecation warnings.
*/
#define DIAG_OFF_DEPRECATION \
DIAG_DO_PRAGMA(clang diagnostic push) \
DIAG_DO_PRAGMA(clang diagnostic ignored "-Wdeprecated-declarations")
#define DIAG_ON_DEPRECATION \
DIAG_DO_PRAGMA(clang diagnostic pop)
/*
* Clang supports the generic C11 extension even if run with the -std=gnu99
* flag, which leads FreeBSD <sys/cdefs.h> to use the extension, which
* results in Clang emitting a -Wc11-extensions warning. The warning is not
* documented in the user manual, but it happens with Clang 10.0.1 on
* FreeBSD 12.2, so let's use that as a reference.
*/
#if ND_IS_AT_LEAST_CLANG_VERSION(10,0)
#define DIAG_OFF_C11_EXTENSIONS \
DIAG_DO_PRAGMA(clang diagnostic push) \
DIAG_DO_PRAGMA(clang diagnostic ignored "-Wc11-extensions")
#define DIAG_ON_C11_EXTENSIONS \
DIAG_DO_PRAGMA(clang diagnostic pop)
#endif
+
+ /*
+ * When Clang correctly detects an old-style function prototype after
+ * preprocessing, the warning can be irrelevant to this source tree because
+ * the prototype comes from a system header macro.
+ */
+ #if ND_IS_AT_LEAST_CLANG_VERSION(5,0)
+ #define DIAG_OFF_STRICT_PROTOTYPES \
+ DIAG_DO_PRAGMA(clang diagnostic push) \
+ DIAG_DO_PRAGMA(clang diagnostic ignored "-Wstrict-prototypes")
+ #define DIAG_ON_STRICT_PROTOTYPES \
+ DIAG_DO_PRAGMA(clang diagnostic pop)
+ #endif
#elif ND_IS_AT_LEAST_GNUC_VERSION(4,2)
/* GCC apparently doesn't complain about ORing enums together. */
- #define DIAG_OFF_ASSIGN_ENUM
- #define DIAG_ON_ASSIGN_ENUM
/*
* It does, however, complain about casting away constness in
* missing/getopt_long.c.
*/
#define DIAG_OFF_CAST_QUAL \
DIAG_DO_PRAGMA(GCC diagnostic push) \
DIAG_DO_PRAGMA(GCC diagnostic ignored "-Wcast-qual")
#define DIAG_ON_CAST_QUAL \
DIAG_DO_PRAGMA(GCC diagnostic pop)
+ #if ND_IS_AT_LEAST_GNUC_VERSION(4,5)
+ /*
+ * GCC warns about unused return values if a function is marked as
+ * "warn about ignoring this function's return value".
+ *
+ * Clang appears to let you ignore a result without a warning by
+ * casting the function result to void, so we don't appear to
+ * need this for Clang.
+ */
+ #define DIAG_OFF_WARN_UNUSED_RESULT \
+ DIAG_DO_PRAGMA(GCC diagnostic push) \
+ DIAG_DO_PRAGMA(GCC diagnostic ignored "-Wunused-result")
+ #define DIAG_ON_WARN_UNUSED_RESULT \
+ DIAG_DO_PRAGMA(GCC diagnostic pop)
+ #endif
+
/*
* Suppress deprecation warnings.
*/
#define DIAG_OFF_DEPRECATION \
DIAG_DO_PRAGMA(GCC diagnostic push) \
DIAG_DO_PRAGMA(GCC diagnostic ignored "-Wdeprecated-declarations")
#define DIAG_ON_DEPRECATION \
DIAG_DO_PRAGMA(GCC diagnostic pop)
/*
* GCC supports -Wc99-c11-compat since version 5.1.0, but the warning does
* not trigger for now, so let's just leave it be.
+ *
+ * GCC does not currently generate any -Wstrict-prototypes warnings that
+ * would need silencing as is done for Clang above.
*/
-#else
- #define DIAG_OFF_ASSIGN_ENUM
- #define DIAG_ON_ASSIGN_ENUM
- #define DIAG_OFF_CAST_QUAL
- #define DIAG_ON_CAST_QUAL
- #define DIAG_OFF_DEPRECATION
- #define DIAG_ON_DEPRECATION
-#endif
-
-#ifndef DIAG_OFF_C11_EXTENSIONS
-#define DIAG_OFF_C11_EXTENSIONS
-#endif
-#ifndef DIAG_ON_C11_EXTENSIONS
-#define DIAG_ON_C11_EXTENSIONS
#endif
/*
* GCC needs this on AIX for longjmp().
*/
#if ND_IS_AT_LEAST_GNUC_VERSION(5,1)
/*
* Beware that the effect of this builtin is more than just squelching the
* warning! GCC trusts it enough for the process to segfault if the control
* flow reaches the builtin (an infinite empty loop in the same context would
* squelch the warning and ruin the process too, albeit in a different way).
* So please remember to use this very carefully.
*/
#define ND_UNREACHABLE __builtin_unreachable();
-#else
- #define ND_UNREACHABLE
+#endif
+
+#ifndef DIAG_OFF_ASSIGN_ENUM
+#define DIAG_OFF_ASSIGN_ENUM
+#endif
+#ifndef DIAG_ON_ASSIGN_ENUM
+#define DIAG_ON_ASSIGN_ENUM
+#endif
+#ifndef DIAG_OFF_CAST_QUAL
+#define DIAG_OFF_CAST_QUAL
+#endif
+#ifndef DIAG_ON_CAST_QUAL
+#define DIAG_ON_CAST_QUAL
+#endif
+#ifndef DIAG_OFF_WARN_UNUSED_RESULT
+#define DIAG_OFF_WARN_UNUSED_RESULT
+#endif
+#ifndef DIAG_ON_WARN_UNUSED_RESULT
+#define DIAG_ON_WARN_UNUSED_RESULT
+#endif
+#ifndef DIAG_OFF_DEPRECATION
+#define DIAG_OFF_DEPRECATION
+#endif
+#ifndef DIAG_ON_DEPRECATION
+#define DIAG_ON_DEPRECATION
+#endif
+#ifndef DIAG_OFF_C11_EXTENSIONS
+#define DIAG_OFF_C11_EXTENSIONS
+#endif
+#ifndef DIAG_ON_C11_EXTENSIONS
+#define DIAG_ON_C11_EXTENSIONS
+#endif
+#ifndef DIAG_OFF_STRICT_PROTOTYPES
+#define DIAG_OFF_STRICT_PROTOTYPES
+#endif
+#ifndef DIAG_ON_STRICT_PROTOTYPES
+#define DIAG_ON_STRICT_PROTOTYPES
+#endif
+#ifndef ND_UNREACHABLE
+#define ND_UNREACHABLE
#endif
#endif /* _diag_control_h */
diff --git a/contrib/tcpdump/doc/README.Win32.md b/contrib/tcpdump/doc/README.Win32.md
deleted file mode 100644
index b7e81d1cf1c4..000000000000
--- a/contrib/tcpdump/doc/README.Win32.md
+++ /dev/null
@@ -1,200 +0,0 @@
-Building tcpdump on Windows with Visual Studio
-==============================================
-
-Unlike the UN*Xes on which libpcap can capture network traffic, Windows
-has no network traffic capture mechanism that libpcap can use.
-Therefore, libpcap requires a driver, and a library to access the
-driver, provided by the Npcap or WinPcap projects.
-
-Those projects include versions of libpcap built to use that driver and
-library; these instructions are for people who want to build libpcap
-source releases, or libpcap from the Git repository, as a replacement
-for the version provided with Npcap or WinPcap.
-
-Npcap and WinPcap SDK
----------------------
-
-In order to build tcpdump, you will need to download Npcap and its
-software development kit (SDK) or WinPcap and its software development
-kit.
-
-Npcap is currently being developed and maintained, and offers many
-additional capabilities that WinPcap does not.
-
-WinPcap is no longer being developed or maintained; it should be used
-only if there is some other requirement to use it rather than Npcap,
-such as a requirement to support versions of Windows earlier than
-Windows Vista, which is the earliest version supported by Npcap.
-
-Npcap and its SDK can be downloaded from its [home page](https://npcap.com).
-The SDK is a ZIP archive; create a folder on your `C:` drive, e.g.
-`C:\npcap-sdk`, and put the contents of the ZIP archive into that folder.
-
-The WinPcap installer can be downloaded from
-[here](https://www.winpcap.org/install/default.htm)
-and the WinPcap Developer's Kit can be downloaded from
-[here](https://www.winpcap.org/devel.htm).
-
-Required build tools
---------------------
-
-The Developer's Kit is a ZIP archive; it contains a folder named
-`WpdPack`, which you should place on your `C:` drive, e.g. `C:\WpdPack`.
-
-Building tcpdump on Windows requires Visual Studio 2015 or later. The
-Community Edition of Visual Studio can be downloaded at no cost from
-[here](https://visualstudio.microsoft.com).
-
-Additional tools are also required. Chocolatey is a package manager for
-Windows with which those tools, and other tools, can be installed; it
-can be downloaded from [here](https://chocolatey.org).
-
-It is a command-line tool; a GUI tool, Chocolatey GUI, is provided as a
-Chocolatey package, which can be installed from the command line:
-
-```
-choco install chocolateygui
-```
-
-For convenience, the `choco install` command can be run with the `-y`
-flag, forcing it to automatically answer all questions asked of the user
-with "yes":
-
-```
-choco install -y chocolateygui
-```
-
-The required tools are:
-
-### CMake ###
-
-libpcap does not provide supported project files for Visual Studio
-(there are currently unsupported project files provided, but we do not
-guarantee that they will work or that we will continue to provide them).
-It does provide files for CMake, which is a cross-platform tool that
-runs on UN\*Xes and on Windows and that can generate project files for
-UN\*X Make, the Ninja build system, and Visual Studio, among other build
-systems.
-
-Visual Studio 2015 does not provide CMake; an installer can be
-downloaded from [here](https://cmake.org/download/).
-
-When you run the installer, you should choose to add CMake to the system
-`PATH` for all users and to create the desktop icon.
-
-CMake can also be installed as the Chocolatey package `cmake`:
-
-```
-choco install -y cmake
-```
-
-Visual Studio 2017 and later provide CMake, so you will not need to
-install CMake if you have installed Visual Studio 2017 or later. They
-include built-in support for CMake-based projects as described
-[here](https://devblogs.microsoft.com/cppblog/cmake-support-in-visual-studio/).
-
-For Visual Studio 2017, make sure "Visual C++ tools for CMake" is
-installed; for Visual Studio 2019, make sure "C++ CMake tools for
-Windows" is installed.
-
-Git
----
-
-An optional tool, required only if you will be building from a Git
-repository rather than from a release source tarball, is Git. Git is
-provided as an optional installation component, "Git for Windows", with
-Visual Studio 2017 and later.
-
-Building from the Visual Studio GUI
------------------------------------
-
-### Visual Studio 2017 ###
-
-Open the folder containing the libpcap source with Open > Folder.
-Visual Studio will run CMake; however, you will need to indicate where
-the Npcap or WinPcap SDK is installed.
-
-To do this, go to Project > "Change CMake Settings" > tcpdump and:
-
-Choose which configuration type to build, if you don't want the default
-Debug build.
-
-In the CMakeSettings.json tab, change cmakeCommandArgs to include
-
-```
--DPacket_ROOT={path-to-sdk}
-```
-
-where `{path-to-sdk}` is the path of the directory containing the Npcap or
-WinPcap SDK. Note that backslashes in the path must be specified as two
-backslashes.
-
-Save the configuration changes with File > "Save CMakeSettings.json" or
-with Control-S.
-
-Visual Studio will then re-run CMake. If that completes without errors,
-you can build with CMake > "Build All".
-
-### Visual Studio 2019 ###
-
-Open the folder containing the libpcap source with Open > Folder.
-Visual Studio will run CMake; however, you will need to indicate where
-the Npcap or WinPcap SDK is installed.
-
-To do this, go to Project > "CMake Settings for tcpdump" and:
-
-Choose which configuration type to build, if you don't want the default
-Debug build.
-
-Scroll down to "Cmake variables and cache", scroll through the list
-looking for the entry for Packet_ROOT, and either type in the path of
-the directory containing the Npcap or WinPcap SDK or use the "Browse..."
-button to browse for that directory.
-
-Save the configuration changes with File > "Save CMakeSettings.json" or
-with Control-S.
-
-Visual Studio will then re-run CMake. If that completes without errors,
-you can build with Build > "Build All".
-
-Building from the command line
-------------------------------
-
-Start the appropriate Native Tools command line prompt.
-
-Change to the directory into which you want to build tcpdump, possibly
-after creating it first. One choice is to create it as a subdirectory
-of the tcpdump source directory.
-
-Run the command
-
-```
-cmake "-DPacket_ROOT={path-to-sdk}" -G {generator} {path-to-tcpdump-source}
-```
-
-`{path-to-sdk}` is the path of the directory containing the Npcap or
-WinPcap SDK.
-
-`{generator}` is the string "Visual Studio N YYYY", where `N` is the
-version of Visual Studio and `YYYY` is the year number for that version;
-if you are building a 64-bit version of tcpdump, `YYYY` must be followed
-by a space and "Win64". For example, to build a 32-bit version of
-tcpdump with Visual Studio 2017, `{generator}` would be "Visual Studio
-15 2017" and to build a 64-bit version of tcpdump with Visual Studio
-2017, `{generator}` would be "Visual Studio 15 2017 Win64".
-
-`{path-to-tcpdump-source}` is the pathname of the top-level source
-directory for tcpdump.
-
-Run the command
-
-```
-msbuild /m /nologo /p:Configuration={configuration} tcpdump.sln
-```
-
-where `{configuration}` can be "Release", "Debug", or "RelWithDebInfo".
-
-Building with MinGW
--------------------
-
-(XXX - this should be added)
diff --git a/contrib/tcpdump/doc/README.haiku.md b/contrib/tcpdump/doc/README.haiku.md
new file mode 100644
index 000000000000..f9341523b7b2
--- /dev/null
+++ b/contrib/tcpdump/doc/README.haiku.md
@@ -0,0 +1,33 @@
+# Compiling tcpdump on Haiku
+
+## 64-bit x86 R1/beta4
+
+* Both system and local libpcap are suitable.
+* Autoconf 2.71 works.
+* CMake 3.24.2 works.
+* GCC 11.2.0 works.
+* Clang 12.0.1 works with the latest llvm12_clang-12.0.1-5 version.
+
+The following command will install respective non-default packages:
+```
+pkgman install libpcap_devel cmake llvm12_clang
+```
+
+For reference, the tests were done using a system installed from
+`haiku-r1beta4-x86_64-anyboot.iso`.
+
+## 32-bit x86 R1/beta4
+
+* Both system and local libpcap are suitable.
+* Autoconf 2.71 works.
+* CMake 3.24.2 works.
+* GCC 11.2.0 works.
+* Clang does not work.
+
+The following command will install respective non-default packages:
+```
+pkgman install libpcap_x86_devel cmake_x86
+```
+
+For reference, the tests were done using a system installed from
+`haiku-r1beta4-x86_gcc2h-anyboot.iso`.
diff --git a/contrib/tcpdump/doc/README.solaris.md b/contrib/tcpdump/doc/README.solaris.md
index afdd8f7356e1..86571e21ae11 100644
--- a/contrib/tcpdump/doc/README.solaris.md
+++ b/contrib/tcpdump/doc/README.solaris.md
@@ -1,41 +1,46 @@
# Compiling tcpdump on Solaris and related OSes
* Autoconf works everywhere.
## OmniOS r151042/AMD64
* Both system and local libpcap are suitable.
* CMake 3.23.1 works.
* GCC 11.2.0 and Clang 14.0.3 work.
## OpenIndiana 2021.04/AMD64
* Both system and local libpcap are suitable.
* CMake 3.21.1 works.
* GCC 7.5.0 and GCC 10.3.0 work, Clang 9.0.1 works.
For reference, the tests were done using a system installed from
`OI-hipster-text-20210430.iso` plus the following packages:
```shell
xargs -L1 pkg install <<ENDOFTEXT
developer/build/autoconf
developer/build/cmake
developer/gcc-10
developer/clang-90
ENDOFTEXT
```
## Oracle Solaris 11.4.42/AMD64
* Both system and local libpcap are suitable.
* GCC 11.2 and Clang 11.0 work.
For reference, the tests were done on a VM booted from `sol-11_4-vbox.ova`
and updated to 11.4.42.111.0 plus the following packages:
```shell
xargs -L1 pkg install <<ENDOFTEXT
developer/build/autoconf
developer/gcc
developer/llvm/clang
ENDOFTEXT
```
+
+## Solaris 9
+
+This version of this OS is not supported because the snprintf(3) implementation
+in its libc is not suitable.
diff --git a/contrib/tcpdump/extract.h b/contrib/tcpdump/extract.h
index d7d803dfb277..c1b486d37a7e 100644
--- a/contrib/tcpdump/extract.h
+++ b/contrib/tcpdump/extract.h
@@ -1,910 +1,910 @@
/*
* Copyright (c) 1992, 1993, 1994, 1995, 1996
* 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.
*/
#ifndef EXTRACT_H
#define EXTRACT_H
#include <string.h>
/*
* For 8-bit values; needed to fetch a one-byte value. Byte order
* isn't relevant, and alignment isn't an issue.
*/
#define EXTRACT_U_1(p) ((uint8_t)(*(p)))
#define EXTRACT_S_1(p) ((int8_t)(*(p)))
/*
* Inline functions or macros to extract possibly-unaligned big-endian
* integral values.
*/
#include "funcattrs.h"
#include "netdissect.h"
#include "diag-control.h"
/*
* If we have versions of GCC or Clang that support an __attribute__
* to say "if we're building with unsigned behavior sanitization,
* don't complain about undefined behavior in this function", we
* label these functions with that attribute - we *know* it's undefined
* in the C standard, but we *also* know it does what we want with
* the ISA we're targeting and the compiler we're using.
*
* For GCC 4.9.0 and later, we use __attribute__((no_sanitize_undefined));
* pre-5.0 GCC doesn't have __has_attribute, and I'm not sure whether
* GCC or Clang first had __attribute__((no_sanitize(XXX)).
*
* For Clang, we check for __attribute__((no_sanitize(XXX)) with
* __has_attribute, as there are versions of Clang that support
* __attribute__((no_sanitize("undefined")) but don't support
* __attribute__((no_sanitize_undefined)).
*
* We define this here, rather than in funcattrs.h, because we
* only want it used here, we don't want it to be broadly used.
* (Any printer will get this defined, but this should at least
* make it harder for people to find.)
*/
#if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 409)
#define UNALIGNED_OK __attribute__((no_sanitize_undefined))
#elif __has_attribute(no_sanitize)
#define UNALIGNED_OK __attribute__((no_sanitize("undefined")))
#else
#define UNALIGNED_OK
#endif
#if (defined(__i386__) || defined(_M_IX86) || defined(__X86__) || defined(__x86_64__) || defined(_M_X64)) || \
(defined(__m68k__) && (!defined(__mc68000__) && !defined(__mc68010__))) || \
(defined(__ppc__) || defined(__ppc64__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PPC64)) || \
(defined(__s390__) || defined(__s390x__) || defined(__zarch__))
/*
* The processor natively handles unaligned loads, so we can just
* cast the pointer and fetch through it.
*
* XXX - are those all the x86 tests we need?
* XXX - are those the only 68k tests we need not to generated
* unaligned accesses if the target is the 68000 or 68010?
* XXX - are there any tests we don't need, because some definitions are for
* compilers that also predefine the GCC symbols?
* XXX - do we need to test for both 32-bit and 64-bit versions of those
* architectures in all cases?
*/
UNALIGNED_OK static inline uint16_t
EXTRACT_BE_U_2(const void *p)
{
return ((uint16_t)ntohs(*(const uint16_t *)(p)));
}
UNALIGNED_OK static inline int16_t
EXTRACT_BE_S_2(const void *p)
{
return ((int16_t)ntohs(*(const int16_t *)(p)));
}
UNALIGNED_OK static inline uint32_t
EXTRACT_BE_U_4(const void *p)
{
return ((uint32_t)ntohl(*(const uint32_t *)(p)));
}
UNALIGNED_OK static inline int32_t
EXTRACT_BE_S_4(const void *p)
{
return ((int32_t)ntohl(*(const int32_t *)(p)));
}
UNALIGNED_OK static inline uint64_t
EXTRACT_BE_U_8(const void *p)
{
return ((uint64_t)(((uint64_t)ntohl(*((const uint32_t *)(p) + 0))) << 32 |
((uint64_t)ntohl(*((const uint32_t *)(p) + 1))) << 0));
}
UNALIGNED_OK static inline int64_t
EXTRACT_BE_S_8(const void *p)
{
return ((int64_t)(((int64_t)ntohl(*((const uint32_t *)(p) + 0))) << 32 |
((uint64_t)ntohl(*((const uint32_t *)(p) + 1))) << 0));
}
/*
* Extract an IPv4 address, which is in network byte order, and not
* necessarily aligned, and provide the result in host byte order.
*/
UNALIGNED_OK static inline uint32_t
EXTRACT_IPV4_TO_HOST_ORDER(const void *p)
{
return ((uint32_t)ntohl(*(const uint32_t *)(p)));
}
#elif ND_IS_AT_LEAST_GNUC_VERSION(2,0) && \
(defined(__alpha) || defined(__alpha__) || \
defined(__mips) || defined(__mips__))
/*
* This is MIPS or Alpha, which don't natively handle unaligned loads,
* but which have instructions that can help when doing unaligned
* loads, and this is GCC 2.0 or later or a compiler that claims to
* be GCC 2.0 or later, which we assume that mean we have
* __attribute__((packed)), which we can use to convince the compiler
* to generate those instructions.
*
* Declare packed structures containing a uint16_t and a uint32_t,
* cast the pointer to point to one of those, and fetch through it;
* the GCC manual doesn't appear to explicitly say that
* __attribute__((packed)) causes the compiler to generate unaligned-safe
* code, but it appears to do so.
*
* We do this in case the compiler can generate code using those
* instructions to do an unaligned load and pass stuff to "ntohs()" or
* "ntohl()", which might be better than the code to fetch the
* bytes one at a time and assemble them. (That might not be the
* case on a little-endian platform, such as DEC's MIPS machines and
* Alpha machines, where "ntohs()" and "ntohl()" might not be done
* inline.)
*
* We do this only for specific architectures because, for example,
* at least some versions of GCC, when compiling for 64-bit SPARC,
* generate code that assumes alignment if we do this.
*
* XXX - add other architectures and compilers as possible and
* appropriate.
*
* HP's C compiler, indicated by __HP_cc being defined, supports
* "#pragma unaligned N" in version A.05.50 and later, where "N"
* specifies a number of bytes at which the typedef on the next
* line is aligned, e.g.
*
* #pragma unalign 1
* typedef uint16_t unaligned_uint16_t;
*
* to define unaligned_uint16_t as a 16-bit unaligned data type.
* This could be presumably used, in sufficiently recent versions of
* the compiler, with macros similar to those below. This would be
* useful only if that compiler could generate better code for PA-RISC
* or Itanium than would be generated by a bunch of shifts-and-ORs.
*
* DEC C, indicated by __DECC being defined, has, at least on Alpha,
* an __unaligned qualifier that can be applied to pointers to get the
* compiler to generate code that does unaligned loads and stores when
* dereferencing the pointer in question.
*
* XXX - what if the native C compiler doesn't support
* __attribute__((packed))? How can we get it to generate unaligned
* accesses for *specific* items?
*/
typedef struct {
uint16_t val;
} __attribute__((packed)) unaligned_uint16_t;
typedef struct {
int16_t val;
} __attribute__((packed)) unaligned_int16_t;
typedef struct {
uint32_t val;
} __attribute__((packed)) unaligned_uint32_t;
typedef struct {
int32_t val;
} __attribute__((packed)) unaligned_int32_t;
UNALIGNED_OK static inline uint16_t
EXTRACT_BE_U_2(const void *p)
{
return ((uint16_t)ntohs(((const unaligned_uint16_t *)(p))->val));
}
UNALIGNED_OK static inline int16_t
EXTRACT_BE_S_2(const void *p)
{
return ((int16_t)ntohs(((const unaligned_int16_t *)(p))->val));
}
UNALIGNED_OK static inline uint32_t
EXTRACT_BE_U_4(const void *p)
{
return ((uint32_t)ntohl(((const unaligned_uint32_t *)(p))->val));
}
UNALIGNED_OK static inline int32_t
EXTRACT_BE_S_4(const void *p)
{
return ((int32_t)ntohl(((const unaligned_int32_t *)(p))->val));
}
UNALIGNED_OK static inline uint64_t
EXTRACT_BE_U_8(const void *p)
{
return ((uint64_t)(((uint64_t)ntohl(((const unaligned_uint32_t *)(p) + 0)->val)) << 32 |
((uint64_t)ntohl(((const unaligned_uint32_t *)(p) + 1)->val)) << 0));
}
UNALIGNED_OK static inline int64_t
EXTRACT_BE_S_8(const void *p)
{
return ((int64_t)(((uint64_t)ntohl(((const unaligned_uint32_t *)(p) + 0)->val)) << 32 |
((uint64_t)ntohl(((const unaligned_uint32_t *)(p) + 1)->val)) << 0));
}
/*
* Extract an IPv4 address, which is in network byte order, and not
* necessarily aligned, and provide the result in host byte order.
*/
UNALIGNED_OK static inline uint32_t
EXTRACT_IPV4_TO_HOST_ORDER(const void *p)
{
return ((uint32_t)ntohl(((const unaligned_uint32_t *)(p))->val));
}
#else
/*
* This architecture doesn't natively support unaligned loads, and either
* this isn't a GCC-compatible compiler, we don't have __attribute__,
* or we do but we don't know of any better way with this instruction
* set to do unaligned loads, so do unaligned loads of big-endian
* quantities the hard way - fetch the bytes one at a time and
* assemble them.
*
- * XXX - ARM is a special case. ARMv1 through ARMv5 didn't suppory
+ * XXX - ARM is a special case. ARMv1 through ARMv5 didn't support
* unaligned loads; ARMv6 and later support it *but* have a bit in
* the system control register that the OS can set and that causes
* unaligned loads to fault rather than succeeding.
*
* At least some OSes may set that flag, so we do *not* treat ARM
* as supporting unaligned loads. If your OS supports them on ARM,
* and you want to use them, please update the tests in the #if above
* to check for ARM *and* for your OS.
*/
#define EXTRACT_BE_U_2(p) \
((uint16_t)(((uint16_t)(*((const uint8_t *)(p) + 0)) << 8) | \
((uint16_t)(*((const uint8_t *)(p) + 1)) << 0)))
#define EXTRACT_BE_S_2(p) \
((int16_t)(((uint16_t)(*((const uint8_t *)(p) + 0)) << 8) | \
((uint16_t)(*((const uint8_t *)(p) + 1)) << 0)))
#define EXTRACT_BE_U_4(p) \
((uint32_t)(((uint32_t)(*((const uint8_t *)(p) + 0)) << 24) | \
((uint32_t)(*((const uint8_t *)(p) + 1)) << 16) | \
((uint32_t)(*((const uint8_t *)(p) + 2)) << 8) | \
((uint32_t)(*((const uint8_t *)(p) + 3)) << 0)))
#define EXTRACT_BE_S_4(p) \
((int32_t)(((uint32_t)(*((const uint8_t *)(p) + 0)) << 24) | \
((uint32_t)(*((const uint8_t *)(p) + 1)) << 16) | \
((uint32_t)(*((const uint8_t *)(p) + 2)) << 8) | \
((uint32_t)(*((const uint8_t *)(p) + 3)) << 0)))
#define EXTRACT_BE_U_8(p) \
((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 0)) << 56) | \
((uint64_t)(*((const uint8_t *)(p) + 1)) << 48) | \
((uint64_t)(*((const uint8_t *)(p) + 2)) << 40) | \
((uint64_t)(*((const uint8_t *)(p) + 3)) << 32) | \
((uint64_t)(*((const uint8_t *)(p) + 4)) << 24) | \
((uint64_t)(*((const uint8_t *)(p) + 5)) << 16) | \
((uint64_t)(*((const uint8_t *)(p) + 6)) << 8) | \
((uint64_t)(*((const uint8_t *)(p) + 7)) << 0)))
#define EXTRACT_BE_S_8(p) \
((int64_t)(((uint64_t)(*((const uint8_t *)(p) + 0)) << 56) | \
((uint64_t)(*((const uint8_t *)(p) + 1)) << 48) | \
((uint64_t)(*((const uint8_t *)(p) + 2)) << 40) | \
((uint64_t)(*((const uint8_t *)(p) + 3)) << 32) | \
((uint64_t)(*((const uint8_t *)(p) + 4)) << 24) | \
((uint64_t)(*((const uint8_t *)(p) + 5)) << 16) | \
((uint64_t)(*((const uint8_t *)(p) + 6)) << 8) | \
((uint64_t)(*((const uint8_t *)(p) + 7)) << 0)))
/*
* Extract an IPv4 address, which is in network byte order, and not
* necessarily aligned, and provide the result in host byte order.
*/
#define EXTRACT_IPV4_TO_HOST_ORDER(p) \
((uint32_t)(((uint32_t)(*((const uint8_t *)(p) + 0)) << 24) | \
((uint32_t)(*((const uint8_t *)(p) + 1)) << 16) | \
((uint32_t)(*((const uint8_t *)(p) + 2)) << 8) | \
((uint32_t)(*((const uint8_t *)(p) + 3)) << 0)))
#endif /* unaligned access checks */
/*
* Extract numerical values in *host* byte order. (Some metadata
* headers are in the byte order of the host that wrote the file,
* and libpcap translate them to the byte order of the host
* reading the file. This means that if a program on that host
* reads with libpcap and writes to a new file, the new file will
* be written in the byte order of the host writing the file. Thus,
* the magic number in pcap files and byte-order magic in pcapng
* files can be used to determine the byte order in those metadata
* headers.)
*
* XXX - on platforms that can do unaligned accesses, just cast and
* dereference the pointer.
*/
static inline uint16_t
EXTRACT_HE_U_2(const void *p)
{
uint16_t val;
UNALIGNED_MEMCPY(&val, p, sizeof(uint16_t));
return val;
}
static inline int16_t
EXTRACT_HE_S_2(const void *p)
{
int16_t val;
UNALIGNED_MEMCPY(&val, p, sizeof(int16_t));
return val;
}
static inline uint32_t
EXTRACT_HE_U_4(const void *p)
{
uint32_t val;
UNALIGNED_MEMCPY(&val, p, sizeof(uint32_t));
return val;
}
static inline int32_t
EXTRACT_HE_S_4(const void *p)
{
int32_t val;
UNALIGNED_MEMCPY(&val, p, sizeof(int32_t));
return val;
}
/*
* Extract an IPv4 address, which is in network byte order, and which
* is not necessarily aligned on a 4-byte boundary, and provide the
* result in network byte order.
*
* This works the same way regardless of the host's byte order.
*/
static inline uint32_t
EXTRACT_IPV4_TO_NETWORK_ORDER(const void *p)
{
uint32_t addr;
UNALIGNED_MEMCPY(&addr, p, sizeof(uint32_t));
return addr;
}
/*
* Non-power-of-2 sizes.
*/
#define EXTRACT_BE_U_3(p) \
((uint32_t)(((uint32_t)(*((const uint8_t *)(p) + 0)) << 16) | \
((uint32_t)(*((const uint8_t *)(p) + 1)) << 8) | \
((uint32_t)(*((const uint8_t *)(p) + 2)) << 0)))
#define EXTRACT_BE_S_3(p) \
(((*((const uint8_t *)(p) + 0)) & 0x80) ? \
((int32_t)(((uint32_t)(*((const uint8_t *)(p) + 0)) << 16) | \
((uint32_t)(*((const uint8_t *)(p) + 1)) << 8) | \
((uint32_t)(*((const uint8_t *)(p) + 2)) << 0))) : \
((int32_t)(0xFF000000U | \
((uint32_t)(*((const uint8_t *)(p) + 0)) << 16) | \
((uint32_t)(*((const uint8_t *)(p) + 1)) << 8) | \
((uint32_t)(*((const uint8_t *)(p) + 2)) << 0))))
#define EXTRACT_BE_U_5(p) \
((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 0)) << 32) | \
((uint64_t)(*((const uint8_t *)(p) + 1)) << 24) | \
((uint64_t)(*((const uint8_t *)(p) + 2)) << 16) | \
((uint64_t)(*((const uint8_t *)(p) + 3)) << 8) | \
((uint64_t)(*((const uint8_t *)(p) + 4)) << 0)))
#define EXTRACT_BE_S_5(p) \
(((*((const uint8_t *)(p) + 0)) & 0x80) ? \
((int64_t)(((uint64_t)(*((const uint8_t *)(p) + 0)) << 32) | \
((uint64_t)(*((const uint8_t *)(p) + 1)) << 24) | \
((uint64_t)(*((const uint8_t *)(p) + 2)) << 16) | \
((uint64_t)(*((const uint8_t *)(p) + 3)) << 8) | \
((uint64_t)(*((const uint8_t *)(p) + 4)) << 0))) : \
((int64_t)(INT64_T_CONSTANT(0xFFFFFF0000000000U) | \
((uint64_t)(*((const uint8_t *)(p) + 0)) << 32) | \
((uint64_t)(*((const uint8_t *)(p) + 1)) << 24) | \
((uint64_t)(*((const uint8_t *)(p) + 2)) << 16) | \
((uint64_t)(*((const uint8_t *)(p) + 3)) << 8) | \
((uint64_t)(*((const uint8_t *)(p) + 4)) << 0))))
#define EXTRACT_BE_U_6(p) \
((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 0)) << 40) | \
((uint64_t)(*((const uint8_t *)(p) + 1)) << 32) | \
((uint64_t)(*((const uint8_t *)(p) + 2)) << 24) | \
((uint64_t)(*((const uint8_t *)(p) + 3)) << 16) | \
((uint64_t)(*((const uint8_t *)(p) + 4)) << 8) | \
((uint64_t)(*((const uint8_t *)(p) + 5)) << 0)))
#define EXTRACT_BE_S_6(p) \
(((*((const uint8_t *)(p) + 0)) & 0x80) ? \
((int64_t)(((uint64_t)(*((const uint8_t *)(p) + 0)) << 40) | \
((uint64_t)(*((const uint8_t *)(p) + 1)) << 32) | \
((uint64_t)(*((const uint8_t *)(p) + 2)) << 24) | \
((uint64_t)(*((const uint8_t *)(p) + 3)) << 16) | \
((uint64_t)(*((const uint8_t *)(p) + 4)) << 8) | \
((uint64_t)(*((const uint8_t *)(p) + 5)) << 0))) : \
((int64_t)(INT64_T_CONSTANT(0xFFFFFFFF00000000U) | \
((uint64_t)(*((const uint8_t *)(p) + 0)) << 40) | \
((uint64_t)(*((const uint8_t *)(p) + 1)) << 32) | \
((uint64_t)(*((const uint8_t *)(p) + 2)) << 24) | \
((uint64_t)(*((const uint8_t *)(p) + 3)) << 16) | \
((uint64_t)(*((const uint8_t *)(p) + 4)) << 8) | \
((uint64_t)(*((const uint8_t *)(p) + 5)) << 0))))
#define EXTRACT_BE_U_7(p) \
((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 0)) << 48) | \
((uint64_t)(*((const uint8_t *)(p) + 1)) << 40) | \
((uint64_t)(*((const uint8_t *)(p) + 2)) << 32) | \
((uint64_t)(*((const uint8_t *)(p) + 3)) << 24) | \
((uint64_t)(*((const uint8_t *)(p) + 4)) << 16) | \
((uint64_t)(*((const uint8_t *)(p) + 5)) << 8) | \
((uint64_t)(*((const uint8_t *)(p) + 6)) << 0)))
#define EXTRACT_BE_S_7(p) \
(((*((const uint8_t *)(p) + 0)) & 0x80) ? \
((int64_t)(((uint64_t)(*((const uint8_t *)(p) + 0)) << 48) | \
((uint64_t)(*((const uint8_t *)(p) + 1)) << 40) | \
((uint64_t)(*((const uint8_t *)(p) + 2)) << 32) | \
((uint64_t)(*((const uint8_t *)(p) + 3)) << 24) | \
((uint64_t)(*((const uint8_t *)(p) + 4)) << 16) | \
((uint64_t)(*((const uint8_t *)(p) + 5)) << 8) | \
((uint64_t)(*((const uint8_t *)(p) + 6)) << 0))) : \
((int64_t)(INT64_T_CONSTANT(0xFFFFFFFFFF000000U) | \
((uint64_t)(*((const uint8_t *)(p) + 0)) << 48) | \
((uint64_t)(*((const uint8_t *)(p) + 1)) << 40) | \
((uint64_t)(*((const uint8_t *)(p) + 2)) << 32) | \
((uint64_t)(*((const uint8_t *)(p) + 3)) << 24) | \
((uint64_t)(*((const uint8_t *)(p) + 4)) << 16) | \
((uint64_t)(*((const uint8_t *)(p) + 5)) << 8) | \
((uint64_t)(*((const uint8_t *)(p) + 6)) << 0))))
/*
* Macros to extract possibly-unaligned little-endian integral values.
* XXX - do loads on little-endian machines that support unaligned loads?
*/
#define EXTRACT_LE_U_2(p) \
((uint16_t)(((uint16_t)(*((const uint8_t *)(p) + 1)) << 8) | \
((uint16_t)(*((const uint8_t *)(p) + 0)) << 0)))
#define EXTRACT_LE_S_2(p) \
((int16_t)(((uint16_t)(*((const uint8_t *)(p) + 1)) << 8) | \
((uint16_t)(*((const uint8_t *)(p) + 0)) << 0)))
#define EXTRACT_LE_U_4(p) \
((uint32_t)(((uint32_t)(*((const uint8_t *)(p) + 3)) << 24) | \
((uint32_t)(*((const uint8_t *)(p) + 2)) << 16) | \
((uint32_t)(*((const uint8_t *)(p) + 1)) << 8) | \
((uint32_t)(*((const uint8_t *)(p) + 0)) << 0)))
#define EXTRACT_LE_S_4(p) \
((int32_t)(((uint32_t)(*((const uint8_t *)(p) + 3)) << 24) | \
((uint32_t)(*((const uint8_t *)(p) + 2)) << 16) | \
((uint32_t)(*((const uint8_t *)(p) + 1)) << 8) | \
((uint32_t)(*((const uint8_t *)(p) + 0)) << 0)))
#define EXTRACT_LE_U_8(p) \
((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 7)) << 56) | \
((uint64_t)(*((const uint8_t *)(p) + 6)) << 48) | \
((uint64_t)(*((const uint8_t *)(p) + 5)) << 40) | \
((uint64_t)(*((const uint8_t *)(p) + 4)) << 32) | \
((uint64_t)(*((const uint8_t *)(p) + 3)) << 24) | \
((uint64_t)(*((const uint8_t *)(p) + 2)) << 16) | \
((uint64_t)(*((const uint8_t *)(p) + 1)) << 8) | \
((uint64_t)(*((const uint8_t *)(p) + 0)) << 0)))
#define EXTRACT_LE_S_8(p) \
((int64_t)(((uint64_t)(*((const uint8_t *)(p) + 7)) << 56) | \
((uint64_t)(*((const uint8_t *)(p) + 6)) << 48) | \
((uint64_t)(*((const uint8_t *)(p) + 5)) << 40) | \
((uint64_t)(*((const uint8_t *)(p) + 4)) << 32) | \
((uint64_t)(*((const uint8_t *)(p) + 3)) << 24) | \
((uint64_t)(*((const uint8_t *)(p) + 2)) << 16) | \
((uint64_t)(*((const uint8_t *)(p) + 1)) << 8) | \
((uint64_t)(*((const uint8_t *)(p) + 0)) << 0)))
/*
* Non-power-of-2 sizes.
*/
#define EXTRACT_LE_U_3(p) \
((uint32_t)(((uint32_t)(*((const uint8_t *)(p) + 2)) << 16) | \
((uint32_t)(*((const uint8_t *)(p) + 1)) << 8) | \
((uint32_t)(*((const uint8_t *)(p) + 0)) << 0)))
#define EXTRACT_LE_S_3(p) \
((int32_t)(((uint32_t)(*((const uint8_t *)(p) + 2)) << 16) | \
((uint32_t)(*((const uint8_t *)(p) + 1)) << 8) | \
((uint32_t)(*((const uint8_t *)(p) + 0)) << 0)))
#define EXTRACT_LE_U_5(p) \
((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 4)) << 32) | \
((uint64_t)(*((const uint8_t *)(p) + 3)) << 24) | \
((uint64_t)(*((const uint8_t *)(p) + 2)) << 16) | \
((uint64_t)(*((const uint8_t *)(p) + 1)) << 8) | \
((uint64_t)(*((const uint8_t *)(p) + 0)) << 0)))
#define EXTRACT_LE_U_6(p) \
((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 5)) << 40) | \
((uint64_t)(*((const uint8_t *)(p) + 4)) << 32) | \
((uint64_t)(*((const uint8_t *)(p) + 3)) << 24) | \
((uint64_t)(*((const uint8_t *)(p) + 2)) << 16) | \
((uint64_t)(*((const uint8_t *)(p) + 1)) << 8) | \
((uint64_t)(*((const uint8_t *)(p) + 0)) << 0)))
#define EXTRACT_LE_U_7(p) \
((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 6)) << 48) | \
((uint64_t)(*((const uint8_t *)(p) + 5)) << 40) | \
((uint64_t)(*((const uint8_t *)(p) + 4)) << 32) | \
((uint64_t)(*((const uint8_t *)(p) + 3)) << 24) | \
((uint64_t)(*((const uint8_t *)(p) + 2)) << 16) | \
((uint64_t)(*((const uint8_t *)(p) + 1)) << 8) | \
((uint64_t)(*((const uint8_t *)(p) + 0)) << 0)))
/*
* Macros to check the presence of the values in question.
*/
#define ND_TTEST_1(p) ND_TTEST_LEN((p), 1)
#define ND_TCHECK_1(p) ND_TCHECK_LEN((p), 1)
#define ND_TTEST_2(p) ND_TTEST_LEN((p), 2)
#define ND_TCHECK_2(p) ND_TCHECK_LEN((p), 2)
#define ND_TTEST_3(p) ND_TTEST_LEN((p), 3)
#define ND_TCHECK_3(p) ND_TCHECK_LEN((p), 3)
#define ND_TTEST_4(p) ND_TTEST_LEN((p), 4)
#define ND_TCHECK_4(p) ND_TCHECK_LEN((p), 4)
#define ND_TTEST_5(p) ND_TTEST_LEN((p), 5)
#define ND_TCHECK_5(p) ND_TCHECK_LEN((p), 5)
#define ND_TTEST_6(p) ND_TTEST_LEN((p), 6)
#define ND_TCHECK_6(p) ND_TCHECK_LEN((p), 6)
#define ND_TTEST_7(p) ND_TTEST_LEN((p), 7)
#define ND_TCHECK_7(p) ND_TCHECK_LEN((p), 7)
#define ND_TTEST_8(p) ND_TTEST_LEN((p), 8)
#define ND_TCHECK_8(p) ND_TCHECK_LEN((p), 8)
#define ND_TTEST_16(p) ND_TTEST_LEN((p), 16)
#define ND_TCHECK_16(p) ND_TCHECK_LEN((p), 16)
/* get_u_1 and get_s_1 */
static inline uint8_t
get_u_1(netdissect_options *ndo, const u_char *p)
{
if (!ND_TTEST_1(p))
nd_trunc_longjmp(ndo);
return EXTRACT_U_1(p);
}
static inline int8_t
get_s_1(netdissect_options *ndo, const u_char *p)
{
if (!ND_TTEST_1(p))
nd_trunc_longjmp(ndo);
return EXTRACT_S_1(p);
}
/* get_be_u_N */
static inline uint16_t
get_be_u_2(netdissect_options *ndo, const u_char *p)
{
if (!ND_TTEST_2(p))
nd_trunc_longjmp(ndo);
return EXTRACT_BE_U_2(p);
}
static inline uint32_t
get_be_u_3(netdissect_options *ndo, const u_char *p)
{
if (!ND_TTEST_3(p))
nd_trunc_longjmp(ndo);
return EXTRACT_BE_U_3(p);
}
static inline uint32_t
get_be_u_4(netdissect_options *ndo, const u_char *p)
{
if (!ND_TTEST_4(p))
nd_trunc_longjmp(ndo);
return EXTRACT_BE_U_4(p);
}
static inline uint64_t
get_be_u_5(netdissect_options *ndo, const u_char *p)
{
if (!ND_TTEST_5(p))
nd_trunc_longjmp(ndo);
return EXTRACT_BE_U_5(p);
}
static inline uint64_t
get_be_u_6(netdissect_options *ndo, const u_char *p)
{
if (!ND_TTEST_6(p))
nd_trunc_longjmp(ndo);
return EXTRACT_BE_U_6(p);
}
static inline uint64_t
get_be_u_7(netdissect_options *ndo, const u_char *p)
{
if (!ND_TTEST_7(p))
nd_trunc_longjmp(ndo);
return EXTRACT_BE_U_7(p);
}
static inline uint64_t
get_be_u_8(netdissect_options *ndo, const u_char *p)
{
if (!ND_TTEST_8(p))
nd_trunc_longjmp(ndo);
return EXTRACT_BE_U_8(p);
}
/* get_be_s_N */
static inline int16_t
get_be_s_2(netdissect_options *ndo, const u_char *p)
{
if (!ND_TTEST_2(p))
nd_trunc_longjmp(ndo);
return EXTRACT_BE_S_2(p);
}
static inline int32_t
get_be_s_3(netdissect_options *ndo, const u_char *p)
{
if (!ND_TTEST_3(p))
nd_trunc_longjmp(ndo);
return EXTRACT_BE_S_3(p);
}
static inline int32_t
get_be_s_4(netdissect_options *ndo, const u_char *p)
{
if (!ND_TTEST_4(p))
nd_trunc_longjmp(ndo);
return EXTRACT_BE_S_4(p);
}
static inline int64_t
get_be_s_5(netdissect_options *ndo, const u_char *p)
{
if (!ND_TTEST_5(p))
nd_trunc_longjmp(ndo);
return EXTRACT_BE_S_5(p);
}
static inline int64_t
get_be_s_6(netdissect_options *ndo, const u_char *p)
{
if (!ND_TTEST_6(p))
nd_trunc_longjmp(ndo);
return EXTRACT_BE_S_6(p);
}
static inline int64_t
get_be_s_7(netdissect_options *ndo, const u_char *p)
{
if (!ND_TTEST_7(p))
nd_trunc_longjmp(ndo);
return EXTRACT_BE_S_7(p);
}
static inline int64_t
get_be_s_8(netdissect_options *ndo, const u_char *p)
{
if (!ND_TTEST_8(p))
nd_trunc_longjmp(ndo);
return EXTRACT_BE_S_8(p);
}
/* get_he_u_N */
static inline uint16_t
get_he_u_2(netdissect_options *ndo, const u_char *p)
{
if (!ND_TTEST_2(p))
nd_trunc_longjmp(ndo);
return EXTRACT_HE_U_2(p);
}
static inline uint32_t
get_he_u_4(netdissect_options *ndo, const u_char *p)
{
if (!ND_TTEST_4(p))
nd_trunc_longjmp(ndo);
return EXTRACT_HE_U_4(p);
}
/* get_he_s_N */
static inline int16_t
get_he_s_2(netdissect_options *ndo, const u_char *p)
{
if (!ND_TTEST_2(p))
nd_trunc_longjmp(ndo);
return EXTRACT_HE_S_2(p);
}
static inline int32_t
get_he_s_4(netdissect_options *ndo, const u_char *p)
{
if (!ND_TTEST_4(p))
nd_trunc_longjmp(ndo);
return EXTRACT_HE_S_4(p);
}
/* get_le_u_N */
static inline uint16_t
get_le_u_2(netdissect_options *ndo, const u_char *p)
{
if (!ND_TTEST_2(p))
nd_trunc_longjmp(ndo);
return EXTRACT_LE_U_2(p);
}
static inline uint32_t
get_le_u_3(netdissect_options *ndo, const u_char *p)
{
if (!ND_TTEST_3(p))
nd_trunc_longjmp(ndo);
return EXTRACT_LE_U_3(p);
}
static inline uint32_t
get_le_u_4(netdissect_options *ndo, const u_char *p)
{
if (!ND_TTEST_4(p))
nd_trunc_longjmp(ndo);
return EXTRACT_LE_U_4(p);
}
static inline uint64_t
get_le_u_5(netdissect_options *ndo, const u_char *p)
{
if (!ND_TTEST_5(p))
nd_trunc_longjmp(ndo);
return EXTRACT_LE_U_5(p);
}
static inline uint64_t
get_le_u_6(netdissect_options *ndo, const u_char *p)
{
if (!ND_TTEST_6(p))
nd_trunc_longjmp(ndo);
return EXTRACT_LE_U_6(p);
}
static inline uint64_t
get_le_u_7(netdissect_options *ndo, const u_char *p)
{
if (!ND_TTEST_7(p))
nd_trunc_longjmp(ndo);
return EXTRACT_LE_U_7(p);
}
static inline uint64_t
get_le_u_8(netdissect_options *ndo, const u_char *p)
{
if (!ND_TTEST_8(p))
nd_trunc_longjmp(ndo);
return EXTRACT_LE_U_8(p);
}
/* get_le_s_N */
static inline int16_t
get_le_s_2(netdissect_options *ndo, const u_char *p)
{
if (!ND_TTEST_2(p))
nd_trunc_longjmp(ndo);
return EXTRACT_LE_S_2(p);
}
static inline int32_t
get_le_s_3(netdissect_options *ndo, const u_char *p)
{
if (!ND_TTEST_3(p))
nd_trunc_longjmp(ndo);
return EXTRACT_LE_S_3(p);
}
static inline int32_t
get_le_s_4(netdissect_options *ndo, const u_char *p)
{
if (!ND_TTEST_4(p))
nd_trunc_longjmp(ndo);
return EXTRACT_LE_S_4(p);
}
static inline int64_t
get_le_s_8(netdissect_options *ndo, const u_char *p)
{
if (!ND_TTEST_8(p))
nd_trunc_longjmp(ndo);
return EXTRACT_LE_S_8(p);
}
/* get_ipv4_to_{host|network]_order */
static inline uint32_t
get_ipv4_to_host_order(netdissect_options *ndo, const u_char *p)
{
if (!ND_TTEST_4(p))
nd_trunc_longjmp(ndo);
return EXTRACT_IPV4_TO_HOST_ORDER(p);
}
static inline uint32_t
get_ipv4_to_network_order(netdissect_options *ndo, const u_char *p)
{
if (!ND_TTEST_4(p))
nd_trunc_longjmp(ndo);
return EXTRACT_IPV4_TO_NETWORK_ORDER(p);
}
static inline void
get_cpy_bytes(netdissect_options *ndo, u_char *dst, const u_char *p, size_t len)
{
if (!ND_TTEST_LEN(p, len))
nd_trunc_longjmp(ndo);
UNALIGNED_MEMCPY(dst, p, len);
}
#define GET_U_1(p) get_u_1(ndo, (const u_char *)(p))
#define GET_S_1(p) get_s_1(ndo, (const u_char *)(p))
#define GET_BE_U_2(p) get_be_u_2(ndo, (const u_char *)(p))
#define GET_BE_U_3(p) get_be_u_3(ndo, (const u_char *)(p))
#define GET_BE_U_4(p) get_be_u_4(ndo, (const u_char *)(p))
#define GET_BE_U_5(p) get_be_u_5(ndo, (const u_char *)(p))
#define GET_BE_U_6(p) get_be_u_6(ndo, (const u_char *)(p))
#define GET_BE_U_7(p) get_be_u_7(ndo, (const u_char *)(p))
#define GET_BE_U_8(p) get_be_u_8(ndo, (const u_char *)(p))
#define GET_BE_S_2(p) get_be_s_2(ndo, (const u_char *)(p))
#define GET_BE_S_3(p) get_be_s_3(ndo, (const u_char *)(p))
#define GET_BE_S_4(p) get_be_s_4(ndo, (const u_char *)(p))
#define GET_BE_S_5(p) get_be_s_5(ndo, (const u_char *)(p))
#define GET_BE_S_6(p) get_be_s_6(ndo, (const u_char *)(p))
#define GET_BE_S_7(p) get_be_s_7(ndo, (const u_char *)(p))
#define GET_BE_S_8(p) get_be_s_8(ndo, (const u_char *)(p))
#define GET_HE_U_2(p) get_he_u_2(ndo, (const u_char *)(p))
#define GET_HE_U_4(p) get_he_u_4(ndo, (const u_char *)(p))
#define GET_HE_S_2(p) get_he_s_2(ndo, (const u_char *)(p))
#define GET_HE_S_4(p) get_he_s_4(ndo, (const u_char *)(p))
#define GET_LE_U_2(p) get_le_u_2(ndo, (const u_char *)(p))
#define GET_LE_U_3(p) get_le_u_3(ndo, (const u_char *)(p))
#define GET_LE_U_4(p) get_le_u_4(ndo, (const u_char *)(p))
#define GET_LE_U_5(p) get_le_u_5(ndo, (const u_char *)(p))
#define GET_LE_U_6(p) get_le_u_6(ndo, (const u_char *)(p))
#define GET_LE_U_7(p) get_le_u_7(ndo, (const u_char *)(p))
#define GET_LE_U_8(p) get_le_u_8(ndo, (const u_char *)(p))
#define GET_LE_S_2(p) get_le_s_2(ndo, (const u_char *)(p))
#define GET_LE_S_3(p) get_le_s_3(ndo, (const u_char *)(p))
#define GET_LE_S_4(p) get_le_s_4(ndo, (const u_char *)(p))
#define GET_LE_S_8(p) get_le_s_8(ndo, (const u_char *)(p))
#define GET_IPV4_TO_HOST_ORDER(p) get_ipv4_to_host_order(ndo, (const u_char *)(p))
#define GET_IPV4_TO_NETWORK_ORDER(p) get_ipv4_to_network_order(ndo, (const u_char *)(p))
#define GET_CPY_BYTES(dst, p, len) get_cpy_bytes(ndo, (u_char *)(dst), (const u_char *)(p), len)
#endif /* EXTRACT_H */
diff --git a/contrib/tcpdump/ftmacros.h b/contrib/tcpdump/ftmacros.h
index 7975463b3a69..ba95c4aac1bf 100644
--- a/contrib/tcpdump/ftmacros.h
+++ b/contrib/tcpdump/ftmacros.h
@@ -1,127 +1,127 @@
/*
* Copyright (c) 1994, 1995, 1996
* 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 the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the Computer Systems
* Engineering Group at Lawrence Berkeley Laboratory.
* 4. Neither the name of the University nor of the Laboratory may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef ftmacros_h
#define ftmacros_h
/*
* Define some feature test macros to make sure that everything we want
* to be declared gets declared.
*
* On some UN*Xes we need to force strtok_r() to be declared.
* We do *NOT* want to define _POSIX_C_SOURCE, as that tends
* to make non-POSIX APIs that we use unavailable.
* XXX - is there no portable way to say "please pollute the
* namespace to the maximum extent possible"?
*/
#if defined(sun) || defined(__sun)
/*
* On Solaris Clang defines __EXTENSIONS__ automatically.
*/
#ifndef __EXTENSIONS__
#define __EXTENSIONS__
#endif
/*
* We also need to define _XPG4_2 in order to get
* the Single UNIX Specification version of
* recvmsg().
*/
#define _XPG4_2
#elif defined(_hpux) || defined(hpux) || defined(__hpux)
#define _REENTRANT
/*
* We need this to get the versions of socket functions that
* use socklen_t. Define it only if it's not already defined,
- * so we don't get redefiniton warnings.
+ * so we don't get redefinition warnings.
*/
#ifndef _XOPEN_SOURCE_EXTENDED
#define _XOPEN_SOURCE_EXTENDED
#endif
/*
* XXX - the list of PA-RISC options for GCC makes it sound as if
* building code that uses a particular vintage of UNIX API/ABI
* is complicated:
*
* https://gcc.gnu.org/onlinedocs/gcc/HPPA-Options.html
*
* See the description of the -munix flag.
*
* We probably want libpcap to work with programs built for any
* UN*X standard. I'm not sure whether that's possible and, if
* it is, what sort of stuff it'd have to do.
*
* It might also be a requirement that we build with a special
* flag to allow the library to be used with threaded code, at
* least with HP's C compiler; hopefully doing so won't make it
* *not* work with *un*-threaded code.
*/
#else
/*
* Turn on _GNU_SOURCE to get everything GNU libc has to offer,
* including asprintf(), if we're using GNU libc.
*
* Unfortunately, one thing it has to offer is a strerror_r()
* that's not POSIX-compliant, but we deal with that in
* pcap_fmt_errmsg_for_errno().
*
* We don't limit this to, for example, Linux and Cygwin, because
* this might, for example, be GNU/HURD or one of Debian's kFreeBSD
* OSes ("GNU/FreeBSD").
*/
#define _GNU_SOURCE
/*
* We turn on both _DEFAULT_SOURCE and _BSD_SOURCE to try to get
* the BSD u_XXX types, such as u_int and u_short, defined. We
* define _DEFAULT_SOURCE first, so that newer versions of GNU libc
* don't whine about _BSD_SOURCE being deprecated; we still have
* to define _BSD_SOURCE to handle older versions of GNU libc that
* don't support _DEFAULT_SOURCE.
*
* But, if it's already defined, don't define it, so that we don't
* get a warning of it being redefined if it's defined as, for
* example, 1.
*/
#ifndef _DEFAULT_SOURCE
#define _DEFAULT_SOURCE
#endif
/* Avoid redefining _BSD_SOURCE if it's already defined as for ex. 1 */
#ifndef _BSD_SOURCE
#define _BSD_SOURCE
#endif
#endif
#endif
diff --git a/contrib/tcpdump/funcattrs.h b/contrib/tcpdump/funcattrs.h
index 21f3cc1dafd0..28e4108b58c0 100644
--- a/contrib/tcpdump/funcattrs.h
+++ b/contrib/tcpdump/funcattrs.h
@@ -1,160 +1,161 @@
/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
/*
* Copyright (c) 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 the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the Computer Systems
* Engineering Group at Lawrence Berkeley Laboratory.
* 4. Neither the name of the University nor of the Laboratory may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lib_funcattrs_h
#define lib_funcattrs_h
#include "compiler-tests.h"
/*
* Attributes to apply to functions and their arguments, using various
* compiler-specific extensions.
*/
/*
* NORETURN, before a function declaration, means "this function
* never returns". (It must go before the function declaration, e.g.
* "extern NORETURN func(...)" rather than after the function
* declaration, as the MSVC version has to go before the declaration.)
*/
#if __has_attribute(noreturn) \
|| ND_IS_AT_LEAST_GNUC_VERSION(2,5) \
|| ND_IS_AT_LEAST_SUNC_VERSION(5,9) \
|| ND_IS_AT_LEAST_XL_C_VERSION(10,1) \
- || ND_IS_AT_LEAST_HP_C_VERSION(6,10)
+ || ND_IS_AT_LEAST_HP_C_VERSION(6,10) \
+ || __TINYC__
/*
* Compiler with support for __attribute((noreturn)), or GCC 2.5 and
* later, or some compiler asserting compatibility with GCC 2.5 and
* later, or Solaris Studio 12 (Sun C 5.9) and later, or IBM XL C 10.1
* and later (do any earlier versions of XL C support this?), or HP aCC
- * A.06.10 and later.
+ * A.06.10 and later, or current TinyCC.
*/
#define NORETURN __attribute((noreturn))
/*
* However, GCC didn't support that for function *pointers* until GCC
* 4.1.0; see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3481.
*
* Sun C/Oracle Studio C doesn't seem to support it, either.
*/
#if (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) < 401)) \
|| (defined(__SUNPRO_C))
#define NORETURN_FUNCPTR
#else
#define NORETURN_FUNCPTR __attribute((noreturn))
#endif
#elif defined(_MSC_VER)
/*
* MSVC.
* It doesn't allow __declspec(noreturn) to be applied to function
* pointers.
*/
#define NORETURN __declspec(noreturn)
#define NORETURN_FUNCPTR
#else
#define NORETURN
#define NORETURN_FUNCPTR
#endif
/*
* WARN_UNUSED_RESULT, before a function declaration, means "the caller
* should use the result of this function" (even if it's just a success/
* failure indication).
*/
#if __has_attribute(warn_unused_result) \
|| ND_IS_AT_LEAST_GNUC_VERSION(3,4) \
|| ND_IS_AT_LEAST_HP_C_VERSION(6,25)
#define WARN_UNUSED_RESULT __attribute((warn_unused_result))
#else
#define WARN_UNUSED_RESULT
#endif
/*
* PRINTFLIKE(x,y), after a function declaration, means "this function
* does printf-style formatting, with the xth argument being the format
* string and the yth argument being the first argument for the format
* string".
*/
#if __has_attribute(__format__) \
|| ND_IS_AT_LEAST_GNUC_VERSION(2,3) \
|| ND_IS_AT_LEAST_XL_C_VERSION(10,1) \
|| ND_IS_AT_LEAST_HP_C_VERSION(6,10)
/*
* Compiler with support for it, or GCC 2.3 and later, or some compiler
* asserting compatibility with GCC 2.3 and later, or IBM XL C 10.1
* and later (do any earlier versions of XL C support this?),
* or HP aCC A.06.10 and later.
*/
#define PRINTFLIKE(x,y) __attribute__((__format__(__printf__,x,y)))
/*
* However, GCC didn't support that for function *pointers* until GCC
* 4.1.0; see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3481.
* XL C 16.1 (and possibly some earlier versions, but not 12.1 or 13.1) has
* a similar bug, the bugfix for which was made in:
* * version 16.1.1.8 for Linux (25 June 2020), which fixes
* https://www.ibm.com/support/pages/apar/LI81402
* * version 16.1.0.5 for AIX (5 May 2020), which fixes
* https://www.ibm.com/support/pages/apar/IJ24678
*
* When testing versions, keep in mind that XL C 16.1 pretends to be both
* GCC 4.2 and Clang 4.0 at once.
*/
#if (ND_IS_AT_LEAST_GNUC_VERSION(4,1) \
&& !ND_IS_AT_LEAST_XL_C_VERSION(10,1)) \
|| (ND_IS_AT_LEAST_XL_C_VERSION(16,1) \
&& (ND_IS_AT_LEAST_XL_C_MODFIX(1, 8) && defined(__linux__)) \
|| (ND_IS_AT_LEAST_XL_C_MODFIX(0, 5) && defined(_AIX)))
#define PRINTFLIKE_FUNCPTR(x,y) __attribute__((__format__(__printf__,x,y)))
#endif
#endif
#if !defined(PRINTFLIKE)
#define PRINTFLIKE(x,y)
#endif
#if !defined(PRINTFLIKE_FUNCPTR)
#define PRINTFLIKE_FUNCPTR(x,y)
#endif
/*
* For flagging arguments as format strings in MSVC.
*/
#ifdef _MSC_VER
#include <sal.h>
#define FORMAT_STRING(p) _Printf_format_string_ p
#else
#define FORMAT_STRING(p) p
#endif
#endif /* lib_funcattrs_h */
diff --git a/contrib/tcpdump/gmpls.c b/contrib/tcpdump/gmpls.c
index f0646f1bd22d..1bccd8029893 100644
--- a/contrib/tcpdump/gmpls.c
+++ b/contrib/tcpdump/gmpls.c
@@ -1,192 +1,190 @@
/*
* 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.
*
* Original code by Hannes Gredler (hannes@gredler.at)
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "gmpls.h"
/* rfc3471 */
const struct tok gmpls_link_prot_values[] = {
{ 0x01, "Extra Traffic"},
{ 0x02, "Unprotected"},
{ 0x04, "Shared"},
{ 0x08, "Dedicated 1:1"},
{ 0x10, "Dedicated 1+1"},
{ 0x20, "Enhanced"},
{ 0x40, "Reserved"},
{ 0x80, "Reserved"},
{ 0, NULL }
};
/* rfc3471 */
const struct tok gmpls_switch_cap_values[] = {
{ GMPLS_PSC1, "Packet-Switch Capable-1"},
{ GMPLS_PSC2, "Packet-Switch Capable-2"},
{ GMPLS_PSC3, "Packet-Switch Capable-3"},
{ GMPLS_PSC4, "Packet-Switch Capable-4"},
{ GMPLS_L2SC, "Layer-2 Switch Capable"},
{ GMPLS_TSC, "Time-Division-Multiplex"},
{ GMPLS_LSC, "Lambda-Switch Capable"},
{ GMPLS_FSC, "Fiber-Switch Capable"},
{ 0, NULL }
};
/* rfc4205 */
const struct tok gmpls_switch_cap_tsc_indication_values[] = {
{ 0, "Standard SONET/SDH" },
{ 1, "Arbitrary SONET/SDH" },
{ 0, NULL }
};
/* rfc3471 */
const struct tok gmpls_encoding_values[] = {
{ 1, "Packet"},
{ 2, "Ethernet V2/DIX"},
{ 3, "ANSI/ETSI PDH"},
{ 4, "Reserved"},
{ 5, "SDH ITU-T G.707/SONET ANSI T1.105"},
{ 6, "Reserved"},
{ 7, "Digital Wrapper"},
{ 8, "Lambda (photonic)"},
{ 9, "Fiber"},
{ 10, "Reserved"},
{ 11, "FiberChannel"},
{ 0, NULL }
};
/* rfc3471 */
const struct tok gmpls_payload_values[] = {
{ 0, "Unknown"},
{ 1, "Reserved"},
{ 2, "Reserved"},
{ 3, "Reserved"},
{ 4, "Reserved"},
{ 5, "Asynchronous mapping of E4"},
{ 6, "Asynchronous mapping of DS3/T3"},
{ 7, "Asynchronous mapping of E3"},
{ 8, "Bit synchronous mapping of E3"},
{ 9, "Byte synchronous mapping of E3"},
{ 10, "Asynchronous mapping of DS2/T2"},
{ 11, "Bit synchronous mapping of DS2/T2"},
{ 12, "Reserved"},
{ 13, "Asynchronous mapping of E1"},
{ 14, "Byte synchronous mapping of E1"},
{ 15, "Byte synchronous mapping of 31 * DS0"},
{ 16, "Asynchronous mapping of DS1/T1"},
{ 17, "Bit synchronous mapping of DS1/T1"},
{ 18, "Byte synchronous mapping of DS1/T1"},
{ 19, "VC-11 in VC-12"},
{ 20, "Reserved"},
{ 21, "Reserved"},
{ 22, "DS1 SF Asynchronous"},
{ 23, "DS1 ESF Asynchronous"},
{ 24, "DS3 M23 Asynchronous"},
{ 25, "DS3 C-Bit Parity Asynchronous"},
{ 26, "VT/LOVC"},
{ 27, "STS SPE/HOVC"},
{ 28, "POS - No Scrambling, 16 bit CRC"},
{ 29, "POS - No Scrambling, 32 bit CRC"},
{ 30, "POS - Scrambling, 16 bit CRC"},
{ 31, "POS - Scrambling, 32 bit CRC"},
{ 32, "ATM mapping"},
{ 33, "Ethernet PHY"},
{ 34, "SONET/SDH"},
{ 35, "Reserved (SONET deprecated)"},
{ 36, "Digital Wrapper"},
{ 37, "Lambda"},
{ 38, "ANSI/ETSI PDH"},
{ 39, "Reserved"},
{ 40, "Link Access Protocol SDH (X.85 and X.86)"},
{ 41, "FDDI"},
{ 42, "DQDB (ETSI ETS 300 216)"},
{ 43, "FiberChannel-3 (Services)"},
{ 44, "HDLC"},
{ 45, "Ethernet V2/DIX (only)"},
{ 46, "Ethernet 802.3 (only)"},
/* draft-ietf-ccamp-gmpls-g709-04.txt */
{ 47, "G.709 ODUj"},
{ 48, "G.709 OTUk(v)"},
{ 49, "CBR/CBRa"},
{ 50, "CBRb"},
{ 51, "BSOT"},
{ 52, "BSNT"},
{ 53, "IP/PPP (GFP)"},
{ 54, "Ethernet MAC (framed GFP)"},
{ 55, "Ethernet PHY (transparent GFP)"},
{ 56, "ESCON"},
{ 57, "FICON"},
{ 58, "Fiber Channel"},
{ 0, NULL }
};
/*
* Link Type values used by LMP Service Discovery (specifically, the Client
* Port Service Attributes Object). See UNI 1.0 section 9.4.2 for details.
*/
const struct tok lmp_sd_service_config_cpsa_link_type_values[] = {
{ 5, "SDH ITU-T G.707"},
{ 6, "SONET ANSI T1.105"},
{ 0, NULL}
};
/*
* Signal Type values for SDH links used by LMP Service Discovery (specifically,
* the Client Port Service Attributes Object). See UNI 1.0 section 9.4.2 for
* details.
*/
const struct tok lmp_sd_service_config_cpsa_signal_type_sdh_values[] = {
{ 5, "VC-3"},
{ 6, "VC-4"},
{ 7, "STM-0"},
{ 8, "STM-1"},
{ 9, "STM-4"},
{ 10, "STM-16"},
{ 11, "STM-64"},
{ 12, "STM-256"},
{ 0, NULL}
};
/*
* Signal Type values for SONET links used by LMP Service Discovery (specifically,
* the Client Port Service Attributes Object). See UNI 1.0 section 9.4.2 for
* details.
*/
const struct tok lmp_sd_service_config_cpsa_signal_type_sonet_values[] = {
{ 5, "STS-1 SPE"},
{ 6, "STS-3c SPE"},
{ 7, "STS-1"},
{ 8, "STM-3"},
{ 9, "STM-12"},
{ 10, "STM-48"},
{ 11, "STM-192"},
{ 12, "STM-768"},
{ 0, NULL}
};
#define DIFFSERV_BC_MODEL_RDM 0 /* draft-ietf-tewg-diff-te-proto-07 */
#define DIFFSERV_BC_MODEL_MAM 1 /* draft-ietf-tewg-diff-te-proto-07 */
#define DIFFSERV_BC_MODEL_EXTD_MAM 254 /* experimental */
const struct tok diffserv_te_bc_values[] = {
{ DIFFSERV_BC_MODEL_RDM, "Russian dolls"},
{ DIFFSERV_BC_MODEL_MAM, "Maximum allocation"},
{ DIFFSERV_BC_MODEL_EXTD_MAM, "Maximum allocation with E-LSP support"},
{ 0, NULL }
};
diff --git a/contrib/tcpdump/in_cksum.c b/contrib/tcpdump/in_cksum.c
index eb7c634f0ab0..46dfb958d007 100644
--- a/contrib/tcpdump/in_cksum.c
+++ b/contrib/tcpdump/in_cksum.c
@@ -1,200 +1,198 @@
/* in_cksum.c
* 4.4-Lite-2 Internet checksum routine, modified to take a vector of
* pointers/lengths giving the pieces to be checksummed. Also using
* Tahoe/CGI version of ADDCARRY(x) macro instead of from portable version.
*/
/*
* Copyright (c) 1988, 1992, 1993
* 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 the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. 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 BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)in_cksum.c 8.1 (Berkeley) 6/10/93
*/
-#ifdef HAVE_CONFIG_H
# include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
/*
* Checksum routine for Internet Protocol family headers (Portable Version).
*
* This routine is very heavily used in the network
* code and should be modified for each CPU to be as fast as possible.
*/
#define ADDCARRY(x) {if ((x) > 65535) (x) -= 65535;}
#define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);}
uint16_t
in_cksum(const struct cksum_vec *vec, int veclen)
{
const uint16_t *w;
int sum = 0;
int mlen = 0;
int byte_swapped = 0;
union {
uint8_t c[2];
uint16_t s;
} s_util;
union {
uint16_t s[2];
uint32_t l;
} l_util;
for (; veclen != 0; vec++, veclen--) {
if (vec->len == 0)
continue;
w = (const uint16_t *)(const void *)vec->ptr;
if (mlen == -1) {
/*
* The first byte of this chunk is the continuation
* of a word spanning between this chunk and the
* last chunk.
*
* s_util.c[0] is already saved when scanning previous
* chunk.
*/
s_util.c[1] = *(const uint8_t *)w;
sum += s_util.s;
w = (const uint16_t *)(const void *)((const uint8_t *)w + 1);
mlen = vec->len - 1;
} else
mlen = vec->len;
/*
* Force to even boundary.
*/
if ((1 & (uintptr_t) w) && (mlen > 0)) {
REDUCE;
sum <<= 8;
s_util.c[0] = *(const uint8_t *)w;
w = (const uint16_t *)(const void *)((const uint8_t *)w + 1);
mlen--;
byte_swapped = 1;
}
/*
* Unroll the loop to make overhead from
* branches &c small.
*/
while ((mlen -= 32) >= 0) {
sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];
sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];
w += 16;
}
mlen += 32;
while ((mlen -= 8) >= 0) {
sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
w += 4;
}
mlen += 8;
if (mlen == 0 && byte_swapped == 0)
continue;
REDUCE;
while ((mlen -= 2) >= 0) {
sum += *w++;
}
if (byte_swapped) {
REDUCE;
sum <<= 8;
byte_swapped = 0;
if (mlen == -1) {
s_util.c[1] = *(const uint8_t *)w;
sum += s_util.s;
mlen = 0;
} else
mlen = -1;
} else if (mlen == -1)
s_util.c[0] = *(const uint8_t *)w;
}
if (mlen == -1) {
/* The last mbuf has odd # of bytes. Follow the
standard (the odd byte may be shifted left by 8 bits
or not as determined by endian-ness of the machine) */
s_util.c[1] = 0;
sum += s_util.s;
}
REDUCE;
return (~sum & 0xffff);
}
/*
* Given the host-byte-order value of the checksum field in a packet
* header, and the network-byte-order computed checksum of the data
* that the checksum covers (including the checksum itself), compute
* what the checksum field *should* have been.
*/
uint16_t
in_cksum_shouldbe(uint16_t sum, uint16_t computed_sum)
{
uint32_t shouldbe;
/*
* The value that should have gone into the checksum field
* is the negative of the value gotten by summing up everything
* *but* the checksum field.
*
* We can compute that by subtracting the value of the checksum
* field from the sum of all the data in the packet, and then
* computing the negative of that value.
*
* "sum" is the value of the checksum field, and "computed_sum"
* is the negative of the sum of all the data in the packets,
* so that's -(-computed_sum - sum), or (sum + computed_sum).
*
* All the arithmetic in question is one's complement, so the
* addition must include an end-around carry; we do this by
* doing the arithmetic in 32 bits (with no sign-extension),
* and then adding the upper 16 bits of the sum, which contain
* the carry, to the lower 16 bits of the sum, and then do it
* again in case *that* sum produced a carry.
*
* As RFC 1071 notes, the checksum can be computed without
* byte-swapping the 16-bit words; summing 16-bit words
* on a big-endian machine gives a big-endian checksum, which
* can be directly stuffed into the big-endian checksum fields
* in protocol headers, and summing words on a little-endian
* machine gives a little-endian checksum, which must be
* byte-swapped before being stuffed into a big-endian checksum
* field.
*
* "computed_sum" is a network-byte-order value, so we must put
* it in host byte order before subtracting it from the
* host-byte-order value from the header; the adjusted checksum
* will be in host byte order, which is what we'll return.
*/
shouldbe = sum;
shouldbe += ntohs(computed_sum);
shouldbe = (shouldbe & 0xFFFF) + (shouldbe >> 16);
shouldbe = (shouldbe & 0xFFFF) + (shouldbe >> 16);
return (uint16_t)shouldbe;
}
diff --git a/contrib/tcpdump/install-sh b/contrib/tcpdump/install-sh
index b44de0989d2f..ec298b537402 100755
--- a/contrib/tcpdump/install-sh
+++ b/contrib/tcpdump/install-sh
@@ -1,250 +1,541 @@
-#! /bin/sh
-#
+#!/bin/sh
# install - install a program, script, or datafile
-# This comes from X11R5 (mit/util/scripts/install.sh).
+
+scriptversion=2020-11-14.01; # UTC
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
-# Copyright 1991 by the Massachusetts Institute of Technology
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
#
-# Permission to use, copy, modify, distribute, and sell this software and its
-# documentation for any purpose is hereby granted without fee, provided that
-# the above copyright notice appear in all copies and that both that
-# copyright notice and this permission notice appear in supporting
-# documentation, and that the name of M.I.T. not be used in advertising or
-# publicity pertaining to distribution of the software without specific,
-# written prior permission. M.I.T. makes no representations about the
-# suitability of this software for any purpose. It is provided "as is"
-# without express or implied warranty.
+#
+# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
-# `make' implicit rules from creating a file called install from it
+# 'make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
-# from scratch. It can only install one file at a time, a restriction
-# shared with many OS's install programs.
+# from scratch.
+
+tab=' '
+nl='
+'
+IFS=" $tab$nl"
+# Set DOITPROG to "echo" to test this script.
-# set DOITPROG to echo to test this script
+doit=${DOITPROG-}
+doit_exec=${doit:-exec}
-# Don't use :- since 4.3BSD and earlier shells don't like it.
-doit="${DOITPROG-}"
+# Put in absolute file names if you don't have them in your path;
+# or use environment vars.
+chgrpprog=${CHGRPPROG-chgrp}
+chmodprog=${CHMODPROG-chmod}
+chownprog=${CHOWNPROG-chown}
+cmpprog=${CMPPROG-cmp}
+cpprog=${CPPROG-cp}
+mkdirprog=${MKDIRPROG-mkdir}
+mvprog=${MVPROG-mv}
+rmprog=${RMPROG-rm}
+stripprog=${STRIPPROG-strip}
-# put in absolute paths if you don't have them in your path; or use env. vars.
+posix_mkdir=
-mvprog="${MVPROG-mv}"
-cpprog="${CPPROG-cp}"
-chmodprog="${CHMODPROG-chmod}"
-chownprog="${CHOWNPROG-chown}"
-chgrpprog="${CHGRPPROG-chgrp}"
-stripprog="${STRIPPROG-strip}"
-rmprog="${RMPROG-rm}"
-mkdirprog="${MKDIRPROG-mkdir}"
+# Desired mode of installed file.
+mode=0755
-transformbasename=""
-transform_arg=""
-instcmd="$mvprog"
-chmodcmd="$chmodprog 0755"
-chowncmd=""
-chgrpcmd=""
-stripcmd=""
+# Create dirs (including intermediate dirs) using mode 755.
+# This is like GNU 'install' as of coreutils 8.32 (2020).
+mkdir_umask=22
+
+backupsuffix=
+chgrpcmd=
+chmodcmd=$chmodprog
+chowncmd=
+mvcmd=$mvprog
rmcmd="$rmprog -f"
-mvcmd="$mvprog"
-src=""
-dst=""
-dir_arg=""
-
-while [ x"$1" != x ]; do
- case $1 in
- -c) instcmd="$cpprog"
- shift
- continue;;
-
- -d) dir_arg=true
- shift
- continue;;
-
- -m) chmodcmd="$chmodprog $2"
- shift
- shift
- continue;;
-
- -o) chowncmd="$chownprog $2"
- shift
- shift
- continue;;
-
- -g) chgrpcmd="$chgrpprog $2"
- shift
- shift
- continue;;
-
- -s) stripcmd="$stripprog"
- shift
- continue;;
-
- -t=*) transformarg=`echo $1 | sed 's/-t=//'`
- shift
- continue;;
-
- -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
- shift
- continue;;
-
- *) if [ x"$src" = x ]
- then
- src=$1
- else
- # this colon is to work around a 386BSD /bin/sh bug
- :
- dst=$1
- fi
- shift
- continue;;
- esac
-done
+stripcmd=
-if [ x"$src" = x ]
-then
- echo "install: no input file specified"
- exit 1
-else
- true
-fi
+src=
+dst=
+dir_arg=
+dst_arg=
-if [ x"$dir_arg" != x ]; then
- dst=$src
- src=""
+copy_on_change=false
+is_target_a_directory=possibly
- if [ -d $dst ]; then
- instcmd=:
- else
- instcmd=mkdir
- fi
-else
+usage="\
+Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+ or: $0 [OPTION]... SRCFILES... DIRECTORY
+ or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+ or: $0 [OPTION]... -d DIRECTORIES...
-# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
-# might cause directories to be created, which would be especially bad
-# if $src (and thus $dsttmp) contains '*'.
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
- if [ -f $src -o -d $src ]
- then
- true
- else
- echo "install: $src does not exist"
- exit 1
- fi
+Options:
+ --help display this help and exit.
+ --version display version info and exit.
- if [ x"$dst" = x ]
- then
- echo "install: no destination specified"
- exit 1
- else
- true
- fi
+ -c (ignored)
+ -C install only if different (preserve data modification time)
+ -d create directories instead of installing files.
+ -g GROUP $chgrpprog installed files to GROUP.
+ -m MODE $chmodprog installed files to MODE.
+ -o USER $chownprog installed files to USER.
+ -p pass -p to $cpprog.
+ -s $stripprog installed files.
+ -S SUFFIX attempt to back up existing files, with suffix SUFFIX.
+ -t DIRECTORY install into DIRECTORY.
+ -T report an error if DSTFILE is a directory.
-# If destination is a directory, append the input filename; if your system
-# does not like double slashes in filenames, you may need to add some logic
+Environment variables override the default commands:
+ CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
+ RMPROG STRIPPROG
- if [ -d $dst ]
- then
- dst="$dst"/`basename $src`
- else
- true
- fi
-fi
+By default, rm is invoked with -f; when overridden with RMPROG,
+it's up to you to specify -f if you want it.
-## this sed command emulates the dirname command
-dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+If -S is not specified, no backups are attempted.
-# Make sure that the destination directory exists.
-# this part is taken from Noah Friedman's mkinstalldirs script
+Email bug reports to bug-automake@gnu.org.
+Automake home page: https://www.gnu.org/software/automake/
+"
-# Skip lots of stat calls in the usual case.
-if [ ! -d "$dstdir" ]; then
-defaultIFS='
-'
-IFS="${IFS-${defaultIFS}}"
+while test $# -ne 0; do
+ case $1 in
+ -c) ;;
-oIFS="${IFS}"
-# Some sh's can't handle IFS=/ for some reason.
-IFS='%'
-set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
-IFS="${oIFS}"
+ -C) copy_on_change=true;;
-pathcomp=''
+ -d) dir_arg=true;;
-while [ $# -ne 0 ] ; do
- pathcomp="${pathcomp}${1}"
- shift
+ -g) chgrpcmd="$chgrpprog $2"
+ shift;;
- if [ ! -d "${pathcomp}" ] ;
- then
- $mkdirprog "${pathcomp}"
- else
- true
- fi
+ --help) echo "$usage"; exit $?;;
- pathcomp="${pathcomp}/"
-done
-fi
+ -m) mode=$2
+ case $mode in
+ *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
+ echo "$0: invalid mode: $mode" >&2
+ exit 1;;
+ esac
+ shift;;
-if [ x"$dir_arg" != x ]
-then
- $doit $instcmd $dst &&
+ -o) chowncmd="$chownprog $2"
+ shift;;
- if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
- if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
- if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
- if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
-else
+ -p) cpprog="$cpprog -p";;
-# If we're going to rename the final executable, determine the name now.
+ -s) stripcmd=$stripprog;;
- if [ x"$transformarg" = x ]
- then
- dstfile=`basename $dst`
- else
- dstfile=`basename $dst $transformbasename |
- sed $transformarg`$transformbasename
- fi
+ -S) backupsuffix="$2"
+ shift;;
-# don't allow the sed command to completely eliminate the filename
+ -t)
+ is_target_a_directory=always
+ dst_arg=$2
+ # Protect names problematic for 'test' and other utilities.
+ case $dst_arg in
+ -* | [=\(\)!]) dst_arg=./$dst_arg;;
+ esac
+ shift;;
- if [ x"$dstfile" = x ]
- then
- dstfile=`basename $dst`
- else
- true
- fi
+ -T) is_target_a_directory=never;;
-# Make a temp file name in the proper directory.
+ --version) echo "$0 $scriptversion"; exit $?;;
- dsttmp=$dstdir/#inst.$$#
+ --) shift
+ break;;
-# Move or copy the file name to the temp name
+ -*) echo "$0: invalid option: $1" >&2
+ exit 1;;
- $doit $instcmd $src $dsttmp &&
+ *) break;;
+ esac
+ shift
+done
- trap "rm -f ${dsttmp}" 0 &&
+# We allow the use of options -d and -T together, by making -d
+# take the precedence; this is for compatibility with GNU install.
-# and set any options; do chmod last to preserve setuid bits
+if test -n "$dir_arg"; then
+ if test -n "$dst_arg"; then
+ echo "$0: target directory not allowed when installing a directory." >&2
+ exit 1
+ fi
+fi
-# If any of these fail, we abort the whole thing. If we want to
-# ignore errors from any of these, just make sure not to ignore
-# errors from the above "$doit $instcmd $src $dsttmp" command.
+if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
+ # When -d is used, all remaining arguments are directories to create.
+ # When -t is used, the destination is already specified.
+ # Otherwise, the last argument is the destination. Remove it from $@.
+ for arg
+ do
+ if test -n "$dst_arg"; then
+ # $@ is not empty: it contains at least $arg.
+ set fnord "$@" "$dst_arg"
+ shift # fnord
+ fi
+ shift # arg
+ dst_arg=$arg
+ # Protect names problematic for 'test' and other utilities.
+ case $dst_arg in
+ -* | [=\(\)!]) dst_arg=./$dst_arg;;
+ esac
+ done
+fi
- if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
- if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
- if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
- if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+if test $# -eq 0; then
+ if test -z "$dir_arg"; then
+ echo "$0: no input file specified." >&2
+ exit 1
+ fi
+ # It's OK to call 'install-sh -d' without argument.
+ # This can happen when creating conditional directories.
+ exit 0
+fi
-# Now rename the file to the real destination.
+if test -z "$dir_arg"; then
+ if test $# -gt 1 || test "$is_target_a_directory" = always; then
+ if test ! -d "$dst_arg"; then
+ echo "$0: $dst_arg: Is not a directory." >&2
+ exit 1
+ fi
+ fi
+fi
- $doit $rmcmd -f $dstdir/$dstfile &&
- $doit $mvcmd $dsttmp $dstdir/$dstfile
+if test -z "$dir_arg"; then
+ do_exit='(exit $ret); exit $ret'
+ trap "ret=129; $do_exit" 1
+ trap "ret=130; $do_exit" 2
+ trap "ret=141; $do_exit" 13
+ trap "ret=143; $do_exit" 15
+
+ # Set umask so as not to create temps with too-generous modes.
+ # However, 'strip' requires both read and write access to temps.
+ case $mode in
+ # Optimize common cases.
+ *644) cp_umask=133;;
+ *755) cp_umask=22;;
+
+ *[0-7])
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw='% 200'
+ fi
+ cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
+ *)
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw=,u+rw
+ fi
+ cp_umask=$mode$u_plus_rw;;
+ esac
+fi
-fi &&
+for src
+do
+ # Protect names problematic for 'test' and other utilities.
+ case $src in
+ -* | [=\(\)!]) src=./$src;;
+ esac
+
+ if test -n "$dir_arg"; then
+ dst=$src
+ dstdir=$dst
+ test -d "$dstdir"
+ dstdir_status=$?
+ # Don't chown directories that already exist.
+ if test $dstdir_status = 0; then
+ chowncmd=""
+ fi
+ else
+
+ # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+ # might cause directories to be created, which would be especially bad
+ # if $src (and thus $dsttmp) contains '*'.
+ if test ! -f "$src" && test ! -d "$src"; then
+ echo "$0: $src does not exist." >&2
+ exit 1
+ fi
+
+ if test -z "$dst_arg"; then
+ echo "$0: no destination specified." >&2
+ exit 1
+ fi
+ dst=$dst_arg
+
+ # If destination is a directory, append the input filename.
+ if test -d "$dst"; then
+ if test "$is_target_a_directory" = never; then
+ echo "$0: $dst_arg: Is a directory" >&2
+ exit 1
+ fi
+ dstdir=$dst
+ dstbase=`basename "$src"`
+ case $dst in
+ */) dst=$dst$dstbase;;
+ *) dst=$dst/$dstbase;;
+ esac
+ dstdir_status=0
+ else
+ dstdir=`dirname "$dst"`
+ test -d "$dstdir"
+ dstdir_status=$?
+ fi
+ fi
+
+ case $dstdir in
+ */) dstdirslash=$dstdir;;
+ *) dstdirslash=$dstdir/;;
+ esac
+
+ obsolete_mkdir_used=false
+
+ if test $dstdir_status != 0; then
+ case $posix_mkdir in
+ '')
+ # With -d, create the new directory with the user-specified mode.
+ # Otherwise, rely on $mkdir_umask.
+ if test -n "$dir_arg"; then
+ mkdir_mode=-m$mode
+ else
+ mkdir_mode=
+ fi
+
+ posix_mkdir=false
+ # The $RANDOM variable is not portable (e.g., dash). Use it
+ # here however when possible just to lower collision chance.
+ tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+
+ trap '
+ ret=$?
+ rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
+ exit $ret
+ ' 0
+
+ # Because "mkdir -p" follows existing symlinks and we likely work
+ # directly in world-writeable /tmp, make sure that the '$tmpdir'
+ # directory is successfully created first before we actually test
+ # 'mkdir -p'.
+ if (umask $mkdir_umask &&
+ $mkdirprog $mkdir_mode "$tmpdir" &&
+ exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
+ then
+ if test -z "$dir_arg" || {
+ # Check for POSIX incompatibilities with -m.
+ # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+ # other-writable bit of parent directory when it shouldn't.
+ # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+ test_tmpdir="$tmpdir/a"
+ ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
+ case $ls_ld_tmpdir in
+ d????-?r-*) different_mode=700;;
+ d????-?--*) different_mode=755;;
+ *) false;;
+ esac &&
+ $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
+ ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
+ test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+ }
+ }
+ then posix_mkdir=:
+ fi
+ rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
+ else
+ # Remove any dirs left behind by ancient mkdir implementations.
+ rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
+ fi
+ trap '' 0;;
+ esac
+ if
+ $posix_mkdir && (
+ umask $mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+ )
+ then :
+ else
+
+ # mkdir does not conform to POSIX,
+ # or it failed possibly due to a race condition. Create the
+ # directory the slow way, step by step, checking for races as we go.
+
+ case $dstdir in
+ /*) prefix='/';;
+ [-=\(\)!]*) prefix='./';;
+ *) prefix='';;
+ esac
+
+ oIFS=$IFS
+ IFS=/
+ set -f
+ set fnord $dstdir
+ shift
+ set +f
+ IFS=$oIFS
+
+ prefixes=
+
+ for d
+ do
+ test X"$d" = X && continue
+
+ prefix=$prefix$d
+ if test -d "$prefix"; then
+ prefixes=
+ else
+ if $posix_mkdir; then
+ (umask $mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+ # Don't fail if two instances are running concurrently.
+ test -d "$prefix" || exit 1
+ else
+ case $prefix in
+ *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) qprefix=$prefix;;
+ esac
+ prefixes="$prefixes '$qprefix'"
+ fi
+ fi
+ prefix=$prefix/
+ done
+
+ if test -n "$prefixes"; then
+ # Don't fail if two instances are running concurrently.
+ (umask $mkdir_umask &&
+ eval "\$doit_exec \$mkdirprog $prefixes") ||
+ test -d "$dstdir" || exit 1
+ obsolete_mkdir_used=true
+ fi
+ fi
+ fi
+
+ if test -n "$dir_arg"; then
+ { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
+ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
+ { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
+ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
+ else
+
+ # Make a couple of temp file names in the proper directory.
+ dsttmp=${dstdirslash}_inst.$$_
+ rmtmp=${dstdirslash}_rm.$$_
+
+ # Trap to clean up those temp files at exit.
+ trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+
+ # Copy the file name to the temp name.
+ (umask $cp_umask &&
+ { test -z "$stripcmd" || {
+ # Create $dsttmp read-write so that cp doesn't create it read-only,
+ # which would cause strip to fail.
+ if test -z "$doit"; then
+ : >"$dsttmp" # No need to fork-exec 'touch'.
+ else
+ $doit touch "$dsttmp"
+ fi
+ }
+ } &&
+ $doit_exec $cpprog "$src" "$dsttmp") &&
+
+ # and set any options; do chmod last to preserve setuid bits.
+ #
+ # If any of these fail, we abort the whole thing. If we want to
+ # ignore errors from any of these, just make sure not to ignore
+ # errors from the above "$doit $cpprog $src $dsttmp" command.
+ #
+ { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
+ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
+ { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
+ { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
+
+ # If -C, don't bother to copy if it wouldn't change the file.
+ if $copy_on_change &&
+ old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
+ new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
+ set -f &&
+ set X $old && old=:$2:$4:$5:$6 &&
+ set X $new && new=:$2:$4:$5:$6 &&
+ set +f &&
+ test "$old" = "$new" &&
+ $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
+ then
+ rm -f "$dsttmp"
+ else
+ # If $backupsuffix is set, and the file being installed
+ # already exists, attempt a backup. Don't worry if it fails,
+ # e.g., if mv doesn't support -f.
+ if test -n "$backupsuffix" && test -f "$dst"; then
+ $doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
+ fi
+
+ # Rename the file to the real destination.
+ $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
+
+ # The rename failed, perhaps because mv can't rename something else
+ # to itself, or perhaps because mv is so ancient that it does not
+ # support -f.
+ {
+ # Now remove or move aside any old file at destination location.
+ # We try this two ways since rm can't unlink itself on some
+ # systems and the destination file might be busy for other
+ # reasons. In this case, the final cleanup might fail but the new
+ # file should still install successfully.
+ {
+ test ! -f "$dst" ||
+ $doit $rmcmd "$dst" 2>/dev/null ||
+ { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
+ { $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
+ } ||
+ { echo "$0: cannot unlink or rename $dst" >&2
+ (exit 1); exit 1
+ }
+ } &&
+
+ # Now rename the file to the real destination.
+ $doit $mvcmd "$dsttmp" "$dst"
+ }
+ fi || exit 1
+
+ trap '' 0
+ fi
+done
-exit 0
+# Local variables:
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC0"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/contrib/tcpdump/instrument-functions.c b/contrib/tcpdump/instrument-functions.c
new file mode 100644
index 000000000000..ba0a56a5309f
--- /dev/null
+++ b/contrib/tcpdump/instrument-functions.c
@@ -0,0 +1,250 @@
+/*
+ * 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.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <bfd.h>
+
+/*
+ * Generate instrumentation calls for entry and exit to functions.
+ * Just after function entry and just before function exit, the
+ * following profiling functions are called with the address of the
+ * current function and its call site (currently not use).
+ *
+ * The attribute 'no_instrument_function' causes this instrumentation is
+ * not done.
+ *
+ * These profiling functions call print_debug(). This function prints the
+ * current function name with indentation and call level.
+ * If entering in a function it prints also the calling function name with
+ * file name and line number.
+ *
+ * If the environment variable INSTRUMENT is
+ * unset or set to an empty string, print nothing, like with no instrumentation
+ * set to "all" or "a", print all the functions names
+ * set to "global" or "g", print only the global functions names
+ */
+
+#define ND_NO_INSTRUMENT __attribute__((no_instrument_function))
+
+/* Store the function call level, used also in pretty_print_packet() */
+extern int profile_func_level;
+int profile_func_level = -1;
+
+typedef enum {
+ ENTER,
+ EXIT
+} action_type;
+
+void __cyg_profile_func_enter(void *this_fn, void *call_site) ND_NO_INSTRUMENT;
+
+void __cyg_profile_func_exit(void *this_fn, void *call_site) ND_NO_INSTRUMENT;
+
+static void print_debug(void *this_fn, void *call_site, action_type action)
+ ND_NO_INSTRUMENT;
+
+void
+__cyg_profile_func_enter(void *this_fn, void *call_site)
+{
+ print_debug(this_fn, call_site, ENTER);
+}
+
+void
+__cyg_profile_func_exit(void *this_fn, void *call_site)
+{
+ print_debug(this_fn, call_site, EXIT);
+}
+
+static void print_debug(void *this_fn, void *call_site, action_type action)
+{
+ static bfd* abfd;
+ static asymbol **symtab;
+ static long symcount;
+ static asection *text;
+ static bfd_vma vma;
+ static int instrument_set;
+ static int instrument_off;
+ static int instrument_global;
+
+ if (!instrument_set) {
+ static char *instrument_type;
+
+ /* Get the configuration environment variable INSTRUMENT value if any */
+ instrument_type = getenv("INSTRUMENT");
+ /* unset or set to an empty string ? */
+ if (instrument_type == NULL ||
+ !strncmp(instrument_type, "", sizeof(""))) {
+ instrument_off = 1;
+ } else {
+ /* set to "global" or "g" ? */
+ if (!strncmp(instrument_type, "global", sizeof("global")) ||
+ !strncmp(instrument_type, "g", sizeof("g")))
+ instrument_global = 1;
+ else if (strncmp(instrument_type, "all", sizeof("all")) &&
+ strncmp(instrument_type, "a", sizeof("a"))) {
+ fprintf(stderr, "INSTRUMENT can be only \"\", \"all\", \"a\", "
+ "\"global\" or \"g\".\n");
+ exit(1);
+ }
+ }
+ instrument_set = 1;
+ }
+
+ if (instrument_off)
+ return;
+
+ /* If no errors, this block should be executed one time */
+ if (!abfd) {
+ char pgm_name[1024];
+ long symsize;
+
+ ssize_t ret = readlink("/proc/self/exe", pgm_name, sizeof(pgm_name));
+ if (ret == -1) {
+ perror("failed to find executable");
+ return;
+ }
+ if (ret == sizeof(pgm_name)) {
+ /* no space for the '\0' */
+ printf("truncation may have occurred\n");
+ return;
+ }
+ pgm_name[ret] = '\0';
+
+ bfd_init();
+
+ abfd = bfd_openr(pgm_name, NULL);
+ if (!abfd) {
+ bfd_perror("bfd_openr");
+ return;
+ }
+
+ if (!bfd_check_format(abfd, bfd_object)) {
+ bfd_perror("bfd_check_format");
+ return;
+ }
+
+ if((symsize = bfd_get_symtab_upper_bound(abfd)) == -1) {
+ bfd_perror("bfd_get_symtab_upper_bound");
+ return;
+ }
+
+ symtab = (asymbol **)malloc((size_t)symsize);
+ symcount = bfd_canonicalize_symtab(abfd, symtab);
+ if (symcount < 0) {
+ free(symtab);
+ bfd_perror("bfd_canonicalize_symtab");
+ return;
+ }
+
+ if ((text = bfd_get_section_by_name(abfd, ".text")) == NULL) {
+ bfd_perror("bfd_get_section_by_name");
+ return;
+ }
+ vma = text->vma;
+ }
+
+ if (instrument_global) {
+ symbol_info syminfo;
+ int found;
+ long i;
+
+ i = 0;
+ found = 0;
+ while (i < symcount && !found) {
+ bfd_get_symbol_info(abfd, symtab[i], &syminfo);
+ if ((void *)syminfo.value == this_fn) {
+ found = 1;
+ }
+ i++;
+ }
+ /* type == 'T' for a global function */
+ if (found == 1 && syminfo.type != 'T')
+ return;
+ }
+
+ /* Current function */
+ if ((bfd_vma)this_fn < vma) {
+ printf("[ERROR address this_fn]");
+ } else {
+ const char *file;
+ const char *func;
+ unsigned int line;
+
+ if (!bfd_find_nearest_line(abfd, text, symtab, (bfd_vma)this_fn - vma,
+ &file, &func, &line)) {
+ printf("[ERROR bfd_find_nearest_line this_fn]");
+ } else {
+ int i;
+
+ if (action == ENTER)
+ profile_func_level += 1;
+ /* Indentation */
+ for (i = 0 ; i < profile_func_level ; i++)
+ putchar(' ');
+ if (action == ENTER)
+ printf("[>> ");
+ else
+ printf("[<< ");
+ /* Function name */
+ if (func == NULL || *func == '\0')
+ printf("???");
+ else
+ printf("%s", func);
+ printf(" (%d)", profile_func_level);
+ /* Print the "from" part except for the main function) */
+ if (action == ENTER && func != NULL &&
+ strncmp(func, "main", sizeof("main"))) {
+ /* Calling function */
+ if ((bfd_vma)call_site < vma) {
+ printf("[ERROR address call_site]");
+ } else {
+ if (!bfd_find_nearest_line(abfd, text, symtab,
+ (bfd_vma)call_site - vma, &file,
+ &func, &line)) {
+ printf("[ERROR bfd_find_nearest_line call_site]");
+ } else {
+ printf(" from ");
+ /* Function name */
+ if (func == NULL || *func == '\0')
+ printf("???");
+ else
+ printf("%s", func);
+ /* File name */
+ if (file == NULL || *file == '\0')
+ printf(" ??:");
+ else {
+ char *slashp = strrchr(file, '/');
+ if (slashp != NULL)
+ file = slashp + 1;
+ printf(" %s:", file);
+ }
+ /* Line number */
+ if (line == 0)
+ printf("?");
+ else
+ printf("%u", line);
+ printf("]");
+ }
+ }
+ }
+ putchar('\n');
+ if (action == EXIT)
+ profile_func_level -= 1;
+ }
+ }
+ fflush(stdout);
+}
+
+/* vi: set tabstop=4 softtabstop=0 shiftwidth=4 smarttab autoindent : */
diff --git a/contrib/tcpdump/interface.h b/contrib/tcpdump/interface.h
index 58e5ab33e51f..c631c143bf65 100644
--- a/contrib/tcpdump/interface.h
+++ b/contrib/tcpdump/interface.h
@@ -1,69 +1,69 @@
/*
* Copyright (c) 1988-2002
* 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.
*/
#ifndef tcpdump_interface_h
#define tcpdump_interface_h
#ifdef HAVE_OS_PROTO_H
#include "os-proto.h"
#endif
#include "funcattrs.h"
#include <stdarg.h>
#if HAVE_STDINT_H
#include <stdint.h>
#endif
#ifndef HAVE_STRLCAT
extern size_t strlcat(char *, const char *, size_t);
#endif
#ifndef HAVE_STRLCPY
extern size_t strlcpy(char *, const char *, size_t);
#endif
#ifndef HAVE_STRDUP
extern char *strdup(const char *);
#endif
#ifndef HAVE_STRSEP
extern char *strsep(char **, const char *);
#endif
#endif
extern char *program_name; /* used to generate self-identifying messages */
#include <pcap.h>
#ifndef HAVE_BPF_DUMP
struct bpf_program;
#endif
/*
* With Capsicum bpf_dump() may be not declared even if HAVE_BPF_DUMP is set.
*/
#if !defined(HAVE_BPF_DUMP) || \
- (defined(HAVE_BPF_DUMP) && HAVE_CAPSICUM && !defined(bpf_dump))
+ (defined(HAVE_BPF_DUMP) && defined(HAVE_CAPSICUM) && !defined(bpf_dump))
extern void bpf_dump(const struct bpf_program *, int);
#endif
diff --git a/contrib/tcpdump/ip.h b/contrib/tcpdump/ip.h
index ca87548fd096..c1be0e66f177 100644
--- a/contrib/tcpdump/ip.h
+++ b/contrib/tcpdump/ip.h
@@ -1,164 +1,163 @@
/*
* Copyright (c) 1982, 1986, 1993
* 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 the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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 BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)ip.h 8.2 (Berkeley) 6/1/94
*/
#ifndef netdissect_ip_h
#define netdissect_ip_h
/*
* Definitions for internet protocol version 4.
* Per RFC 791, September 1981.
*/
#define IPVERSION 4
/*
* Structure of an internet header, naked of options.
*
* We declare ip_len and ip_off to be short, rather than u_short
* pragmatically since otherwise unsigned comparisons can result
* against negative integers quite easily, and fail in subtle ways.
*/
struct ip {
nd_uint8_t ip_vhl; /* header length, version */
#define IP_V(ip) ((GET_U_1((ip)->ip_vhl) & 0xf0) >> 4)
#define IP_HL(ip) (GET_U_1((ip)->ip_vhl) & 0x0f)
nd_uint8_t ip_tos; /* type of service */
nd_uint16_t ip_len; /* total length */
nd_uint16_t ip_id; /* identification */
nd_uint16_t ip_off; /* fragment offset field */
#define IP_DF 0x4000 /* don't fragment flag */
#define IP_MF 0x2000 /* more fragments flag */
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
nd_uint8_t ip_ttl; /* time to live */
nd_uint8_t ip_p; /* protocol */
nd_uint16_t ip_sum; /* checksum */
nd_ipv4 ip_src,ip_dst; /* source and dest address */
};
#define IP_MAXPACKET 65535 /* maximum packet size */
/*
* Definitions for IP type of service (ip_tos)
*/
#define IPTOS_LOWDELAY 0x10
#define IPTOS_THROUGHPUT 0x08
#define IPTOS_RELIABILITY 0x04
/*
* Definitions for IP precedence (also in ip_tos) (hopefully unused)
*/
#define IPTOS_PREC_NETCONTROL 0xe0
#define IPTOS_PREC_INTERNETCONTROL 0xc0
#define IPTOS_PREC_CRITIC_ECP 0xa0
#define IPTOS_PREC_FLASHOVERRIDE 0x80
#define IPTOS_PREC_FLASH 0x60
#define IPTOS_PREC_IMMEDIATE 0x40
#define IPTOS_PREC_PRIORITY 0x20
#define IPTOS_PREC_ROUTINE 0x00
/*
* Definitions for options.
*/
#define IPOPT_COPIED(o) ((o)&0x80)
#define IPOPT_CLASS(o) ((o)&0x60)
#define IPOPT_NUMBER(o) ((o)&0x1f)
#define IPOPT_CONTROL 0x00
#define IPOPT_RESERVED1 0x20
#define IPOPT_DEBMEAS 0x40
#define IPOPT_RESERVED2 0x60
#define IPOPT_EOL 0 /* end of option list */
#define IPOPT_NOP 1 /* no operation */
#define IPOPT_RR 7 /* record packet route */
#define IPOPT_TS 68 /* timestamp */
#define IPOPT_RFC1393 82 /* traceroute RFC 1393 */
#define IPOPT_SECURITY 130 /* provide s,c,h,tcc */
#define IPOPT_LSRR 131 /* loose source route */
-#define IPOPT_SATID 136 /* satnet id */
#define IPOPT_SSRR 137 /* strict source route */
#define IPOPT_RA 148 /* router-alert, rfc2113 */
/*
* Offsets to fields in options other than EOL and NOP.
*/
#define IPOPT_OPTVAL 0 /* option ID */
#define IPOPT_OLEN 1 /* option length */
#define IPOPT_OFFSET 2 /* offset within option */
#define IPOPT_MINOFF 4 /* min value of above */
/*
* Time stamp option structure.
*/
struct ip_timestamp {
nd_uint8_t ipt_code; /* IPOPT_TS */
nd_uint8_t ipt_len; /* size of structure (variable) */
nd_uint8_t ipt_ptr; /* index of current entry */
nd_uint8_t ipt_oflwflg; /* flags, overflow counter */
#define IPTS_OFLW(ip) (((ipt)->ipt_oflwflg & 0xf0) >> 4)
#define IPTS_FLG(ip) ((ipt)->ipt_oflwflg & 0x0f)
union ipt_timestamp {
nd_uint32_t ipt_time[1];
struct ipt_ta {
nd_ipv4 ipt_addr;
nd_uint32_t ipt_time;
} ipt_ta[1];
} ipt_timestamp;
};
/* flag bits for ipt_flg */
#define IPOPT_TS_TSONLY 0 /* timestamps only */
#define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */
#define IPOPT_TS_PRESPEC 3 /* specified modules only */
/* bits for security (not byte swapped) */
#define IPOPT_SECUR_UNCLASS 0x0000
#define IPOPT_SECUR_CONFID 0xf135
#define IPOPT_SECUR_EFTO 0x789a
#define IPOPT_SECUR_MMMM 0xbc4d
#define IPOPT_SECUR_RESTR 0xaf13
#define IPOPT_SECUR_SECRET 0xd788
#define IPOPT_SECUR_TOPSECRET 0x6bc5
/*
* Internet implementation parameters.
*/
#define MAXTTL 255 /* maximum time to live (seconds) */
#define IPDEFTTL 64 /* default ttl, from RFC 1340 */
#define IPFRAGTTL 60 /* time to live for frags, slowhz */
#define IPTTLDEC 1 /* subtracted when forwarding */
#define IP_MSS 576 /* default maximum segment size */
#endif /* netdissect_ip_h */
diff --git a/contrib/tcpdump/ipproto.c b/contrib/tcpdump/ipproto.c
index 53484549ee37..c34d1e2284ed 100644
--- a/contrib/tcpdump/ipproto.c
+++ b/contrib/tcpdump/ipproto.c
@@ -1,363 +1,361 @@
/*
* 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.
*
* Original code by Hannes Gredler (hannes@gredler.at)
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "ipproto.h"
const struct tok ipproto_values[] = {
{ IPPROTO_HOPOPTS, "Options" },
{ IPPROTO_ICMP, "ICMP" },
{ IPPROTO_IGMP, "IGMP" },
{ IPPROTO_IPV4, "IPIP" },
{ IPPROTO_TCP, "TCP" },
{ IPPROTO_EGP, "EGP" },
{ IPPROTO_PIGP, "IGRP" },
{ IPPROTO_UDP, "UDP" },
{ IPPROTO_DCCP, "DCCP" },
{ IPPROTO_IPV6, "IPv6" },
{ IPPROTO_ROUTING, "Routing" },
{ IPPROTO_FRAGMENT, "Fragment" },
{ IPPROTO_RSVP, "RSVP" },
{ IPPROTO_GRE, "GRE" },
{ IPPROTO_ESP, "ESP" },
{ IPPROTO_AH, "AH" },
{ IPPROTO_MOBILE, "Mobile IP" },
{ IPPROTO_ICMPV6, "ICMPv6" },
{ IPPROTO_MOBILITY_OLD, "Mobile IP (old)" },
{ IPPROTO_EIGRP, "EIGRP" },
{ IPPROTO_OSPF, "OSPF" },
{ IPPROTO_PIM, "PIM" },
{ IPPROTO_IPCOMP, "Compressed IP" },
{ IPPROTO_VRRP, "VRRP" }, /* See also CARP. */
{ IPPROTO_PGM, "PGM" },
{ IPPROTO_SCTP, "SCTP" },
{ IPPROTO_MOBILITY, "Mobility" },
{ IPPROTO_PFSYNC, "pfsync" },
{ IPPROTO_ETHERNET, "Ethernet" },
{ 0, NULL }
};
/*
* For completeness the number space in the array below comes from IANA:
* https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml
* However, the spelling tries to match that of /etc/protocols to achieve as
* much consistency as possible with the previously implemented behaviour,
* which was based on getprotobynumber (3).
*/
static const char *netdb_protocol_names[256] = {
"hopopt", /* 0 (IPPROTO_HOPOPTS, IPv6 Hop-by-Hop Option) */
"icmp", /* 1 (IPPROTO_ICMP, Internet Control Message) */
"igmp", /* 2 (IPPROTO_IGMP, Internet Group Management) */
"ggp", /* 3 (Gateway-to-Gateway) */
"ipencap", /* 4 (IPPROTO_IPV4, IPv4 encapsulation) */
"st", /* 5 (Stream, ST datagram mode) */
"tcp", /* 6 (IPPROTO_TCP, Transmission Control) */
"cbt", /* 7 (CBT) */
"egp", /* 8 (IPPROTO_EGP, Exterior Gateway Protocol) */
"igp", /* 9 (IPPROTO_PIGP, "any private interior gateway
* (used by Cisco for their IGRP)")
*/
"bbn-rcc-mon", /* 10 (BBN RCC Monitoring) */
"nvp-ii", /* 11 (Network Voice Protocol) */
"pup", /* 12 (PARC universal packet protocol) */
"argus", /* 13 (ARGUS) */
"emcon", /* 14 (EMCON) */
"xnet", /* 15 (Cross Net Debugger) */
"chaos", /* 16 (Chaos) */
"udp", /* 17 (IPPROTO_UDP, User Datagram) */
"mux", /* 18 (Multiplexing) */
"dcn-meas", /* 19 (DCN Measurement Subsystems) */
"hmp", /* 20 (Host Monitoring) */
"prm", /* 21 (Packet Radio Measurement) */
"xns-idp", /* 22 (XEROX NS IDP) */
"trunk-1", /* 23 (Trunk-1) */
"trunk-2", /* 24 (Trunk-2) */
"leaf-1", /* 25 (Leaf-1) */
"leaf-2", /* 26 (Leaf-2) */
"rdp", /* 27 (Reliable Data Protocol) */
"irtp", /* 28 (Internet Reliable Transaction) */
"iso-tp4", /* 29 (ISO Transport Protocol Class 4) */
"netblt", /* 30 (Bulk Data Transfer Protocol) */
"mfe-nsp", /* 31 (MFE Network Services Protocol) */
"merit-inp", /* 32 (MERIT Internodal Protocol) */
"dccp", /* 33 (IPPROTO_DCCP, Datagram Congestion
* Control Protocol)
*/
"3pc", /* 34 (Third Party Connect Protocol) */
"idpr", /* 35 (Inter-Domain Policy Routing Protocol) */
"xtp", /* 36 (Xpress Transfer Protocol) */
"ddp", /* 37 (Datagram Delivery Protocol) */
"idpr-cmtp", /* 38 (IDPR Control Message Transport Proto) */
"tp++", /* 39 (TP++ Transport Protocol) */
"il", /* 40 (IL Transport Protocol) */
"ipv6", /* 41 (IPPROTO_IPV6, IPv6 encapsulation) */
"sdrp", /* 42 (Source Demand Routing Protocol) */
"ipv6-route", /* 43 (IPPROTO_ROUTING, Routing Header for IPv6) */
"ipv6-frag", /* 44 (IPPROTO_FRAGMENT, Fragment Header for
* IPv6)
*/
"idrp", /* 45 (Inter-Domain Routing Protocol) */
"rsvp", /* 46 (IPPROTO_RSVP, Reservation Protocol) */
"gre", /* 47 (IPPROTO_GRE, Generic Routing
* Encapsulation)
*/
"dsr", /* 48 (Dynamic Source Routing Protocol) */
"bna", /* 49 (BNA) */
"esp", /* 50 (IPPROTO_ESP, Encap Security Payload) */
"ah", /* 51 (IPPROTO_AH, Authentication Header) */
"i-nlsp", /* 52 (Integrated Net Layer Security TUBA) */
"swipe", /* 53 (IP with Encryption) */
"narp", /* 54 (NBMA Address Resolution Protocol) */
"mobile", /* 55 (IPPROTO_MOBILE, IP Mobility) */
"tlsp", /* 56 (Transport Layer Security Protocol using
* Kryptonet key management)
*/
"skip", /* 57 (SKIP) */
"ipv6-icmp", /* 58 (IPPROTO_ICMPV6, ICMP for IPv6) */
"ipv6-nonxt", /* 59 (IPPROTO_NONE, No Next Header for IPv6) */
"ipv6-opts", /* 60 (IPPROTO_DSTOPTS, Destination Options for
* IPv6)
*/
NULL, /* 61 (any host internal protocol) */
"cftp", /* 62 (IPPROTO_MOBILITY_OLD, CFTP, see the note
* in ipproto.h)
*/
NULL, /* 63 (any local network) */
"sat-expak", /* 64 (SATNET and Backroom EXPAK) */
"kryptolan", /* 65 (Kryptolan) */
"rvd", /* 66 (MIT Remote Virtual Disk Protocol) */
"ippc", /* 67 (Internet Pluribus Packet Core) */
NULL, /* 68 (any distributed file system) */
"sat-mon", /* 69 (SATNET Monitoring) */
"visa", /* 70 (VISA Protocol) */
"ipcv", /* 71 (Internet Packet Core Utility) */
"cpnx", /* 72 (Computer Protocol Network Executive) */
"rspf", /* 73 (Radio Shortest Path First, CPHB -- Computer
* Protocol Heart Beat -- in IANA)
*/
"wsn", /* 74 (Wang Span Network) */
"pvp", /* 75 (Packet Video Protocol) */
"br-sat-mon", /* 76 (Backroom SATNET Monitoring) */
"sun-nd", /* 77 (IPPROTO_ND, SUN ND PROTOCOL-Temporary) */
"wb-mon", /* 78 (WIDEBAND Monitoring) */
"wb-expak", /* 79 (WIDEBAND EXPAK) */
"iso-ip", /* 80 (ISO Internet Protocol) */
"vmtp", /* 81 (Versatile Message Transport) */
"secure-vmtp", /* 82 (Secure VMTP) */
"vines", /* 83 (VINES) */
"ttp", /* 84 (Transaction Transport Protocol, also IPTM --
* Internet Protocol Traffic Manager)
*/
"nsfnet-igp", /* 85 (NSFNET-IGP) */
"dgp", /* 86 (Dissimilar Gateway Protocol) */
"tcf", /* 87 (TCF) */
"eigrp", /* 88 (IPPROTO_EIGRP, Cisco EIGRP) */
"ospf", /* 89 (IPPROTO_OSPF, Open Shortest Path First
* IGP)
*/
"sprite-rpc", /* 90 (Sprite RPC Protocol) */
"larp", /* 91 (Locus Address Resolution Protocol) */
"mtp", /* 92 (Multicast Transport Protocol) */
"ax.25", /* 93 (AX.25 Frames) */
"ipip", /* 94 (IP-within-IP Encapsulation Protocol) */
"micp", /* 95 (Mobile Internetworking Control Pro.) */
"scc-sp", /* 96 (Semaphore Communications Sec. Pro.) */
"etherip", /* 97 (Ethernet-within-IP Encapsulation) */
"encap", /* 98 (Encapsulation Header) */
NULL, /* 99 (any private encryption scheme) */
"gmtp", /* 100 (GMTP) */
"ifmp", /* 101 (Ipsilon Flow Management Protocol) */
"pnni", /* 102 (PNNI over IP) */
"pim", /* 103 (IPPROTO_PIM, Protocol Independent
* Multicast)
*/
"aris", /* 104 (ARIS) */
"scps", /* 105 (SCPS) */
"qnx", /* 106 (QNX) */
"a/n", /* 107 (Active Networks) */
"ipcomp", /* 108 (IPPROTO_IPCOMP, IP Payload Compression
* Protocol)
*/
"snp", /* 109 (Sitara Networks Protocol) */
"compaq-peer", /* 110 (Compaq Peer Protocol) */
"ipx-in-ip", /* 111 (IPX in IP) */
"vrrp", /* 112 (IPPROTO_VRRP, Virtual Router Redundancy
* Protocol)
*/
"pgm", /* 113 (IPPROTO_PGM, PGM Reliable Transport
* Protocol)
*/
NULL, /* 114 (any 0-hop protocol) */
"l2tp", /* 115 (Layer Two Tunneling Protocol) */
"ddx", /* 116 (D-II Data Exchange (DDX)) */
"iatp", /* 117 (Interactive Agent Transfer Protocol) */
"stp", /* 118 (Schedule Transfer Protocol) */
"srp", /* 119 (SpectraLink Radio Protocol) */
"uti", /* 120 (UTI) */
"smp", /* 121 (Simple Message Protocol) */
"sm", /* 122 (Simple Multicast Protocol) */
"ptp", /* 123 (Performance Transparency Protocol) */
"isis", /* 124 (ISIS over IPv4) */
"fire", /* 125 (FIRE) */
"crtp", /* 126 (Combat Radio Transport Protocol) */
"crudp", /* 127 (Combat Radio User Datagram) */
"sscopmce", /* 128 (SSCOPMCE) */
"iplt", /* 129 (IPLT) */
"sps", /* 130 (Secure Packet Shield) */
"pipe", /* 131 (Private IP Encapsulation within IP) */
"sctp", /* 132 (IPPROTO_SCTP, Stream Control Transmission
* Protocol)
*/
"fc", /* 133 (Fibre Channel) */
"rsvp-e2e-ignore", /* 134 (RSVP-E2E-IGNORE) */
"mobility-header", /* 135 (IPPROTO_MOBILITY, Mobility Header) */
"udplite", /* 136 (UDPLite) */
"mpls-in-ip", /* 137 (MPLS-in-IP) */
"manet", /* 138 (MANET Protocols) */
"hip", /* 139 (Host Identity Protocol) */
"shim6", /* 140 (Shim6 Protocol) */
"wesp", /* 141 (Wrapped Encapsulating Security Payload) */
"rohc", /* 142 (Robust Header Compression) */
NULL, /* 143 (unassigned) */
NULL, /* 144 (unassigned) */
NULL, /* 145 (unassigned) */
NULL, /* 146 (unassigned) */
NULL, /* 147 (unassigned) */
NULL, /* 148 (unassigned) */
NULL, /* 149 (unassigned) */
NULL, /* 150 (unassigned) */
NULL, /* 151 (unassigned) */
NULL, /* 152 (unassigned) */
NULL, /* 153 (unassigned) */
NULL, /* 154 (unassigned) */
NULL, /* 155 (unassigned) */
NULL, /* 156 (unassigned) */
NULL, /* 157 (unassigned) */
NULL, /* 158 (unassigned) */
NULL, /* 159 (unassigned) */
NULL, /* 160 (unassigned) */
NULL, /* 161 (unassigned) */
NULL, /* 162 (unassigned) */
NULL, /* 163 (unassigned) */
NULL, /* 164 (unassigned) */
NULL, /* 165 (unassigned) */
NULL, /* 166 (unassigned) */
NULL, /* 167 (unassigned) */
NULL, /* 168 (unassigned) */
NULL, /* 169 (unassigned) */
NULL, /* 170 (unassigned) */
NULL, /* 171 (unassigned) */
NULL, /* 172 (unassigned) */
NULL, /* 173 (unassigned) */
NULL, /* 174 (unassigned) */
NULL, /* 175 (unassigned) */
NULL, /* 176 (unassigned) */
NULL, /* 177 (unassigned) */
NULL, /* 178 (unassigned) */
NULL, /* 179 (unassigned) */
NULL, /* 180 (unassigned) */
NULL, /* 181 (unassigned) */
NULL, /* 182 (unassigned) */
NULL, /* 183 (unassigned) */
NULL, /* 184 (unassigned) */
NULL, /* 185 (unassigned) */
NULL, /* 186 (unassigned) */
NULL, /* 187 (unassigned) */
NULL, /* 188 (unassigned) */
NULL, /* 189 (unassigned) */
NULL, /* 190 (unassigned) */
NULL, /* 191 (unassigned) */
NULL, /* 192 (unassigned) */
NULL, /* 193 (unassigned) */
NULL, /* 194 (unassigned) */
NULL, /* 195 (unassigned) */
NULL, /* 196 (unassigned) */
NULL, /* 197 (unassigned) */
NULL, /* 198 (unassigned) */
NULL, /* 199 (unassigned) */
NULL, /* 200 (unassigned) */
NULL, /* 201 (unassigned) */
NULL, /* 202 (unassigned) */
NULL, /* 203 (unassigned) */
NULL, /* 204 (unassigned) */
NULL, /* 205 (unassigned) */
NULL, /* 206 (unassigned) */
NULL, /* 207 (unassigned) */
NULL, /* 208 (unassigned) */
NULL, /* 209 (unassigned) */
NULL, /* 210 (unassigned) */
NULL, /* 211 (unassigned) */
NULL, /* 212 (unassigned) */
NULL, /* 213 (unassigned) */
NULL, /* 214 (unassigned) */
NULL, /* 215 (unassigned) */
NULL, /* 216 (unassigned) */
NULL, /* 217 (unassigned) */
NULL, /* 218 (unassigned) */
NULL, /* 219 (unassigned) */
NULL, /* 220 (unassigned) */
NULL, /* 221 (unassigned) */
NULL, /* 222 (unassigned) */
NULL, /* 223 (unassigned) */
NULL, /* 224 (unassigned) */
NULL, /* 225 (unassigned) */
NULL, /* 226 (unassigned) */
NULL, /* 227 (unassigned) */
NULL, /* 228 (unassigned) */
NULL, /* 229 (unassigned) */
NULL, /* 230 (unassigned) */
NULL, /* 231 (unassigned) */
NULL, /* 232 (unassigned) */
NULL, /* 233 (unassigned) */
NULL, /* 234 (unassigned) */
NULL, /* 235 (unassigned) */
NULL, /* 236 (unassigned) */
NULL, /* 237 (unassigned) */
NULL, /* 238 (unassigned) */
NULL, /* 239 (unassigned) */
NULL, /* 240 (unassigned) */
NULL, /* 241 (unassigned) */
NULL, /* 242 (unassigned) */
NULL, /* 243 (unassigned) */
NULL, /* 244 (unassigned) */
NULL, /* 245 (unassigned) */
NULL, /* 246 (unassigned) */
NULL, /* 247 (unassigned) */
NULL, /* 248 (unassigned) */
NULL, /* 249 (unassigned) */
NULL, /* 250 (unassigned) */
NULL, /* 251 (unassigned) */
NULL, /* 252 (unassigned) */
"exptest-253", /* 253 (Use for experimentation and testing,
* RFC 3692)
*/
"exptest-254", /* 254 (Use for experimentation and testing,
* RFC 3692)
*/
"reserved", /* 255 (reserved) */
};
/* The function enforces the array index to be 8-bit. */
const char *
netdb_protoname (const uint8_t protoid)
{
return netdb_protocol_names[protoid];
}
diff --git a/contrib/tcpdump/l2vpn.c b/contrib/tcpdump/l2vpn.c
index 9111cf6d25d5..5e2e768f524f 100644
--- a/contrib/tcpdump/l2vpn.c
+++ b/contrib/tcpdump/l2vpn.c
@@ -1,95 +1,93 @@
/*
* 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.
*
* Original code by Hannes Gredler (hannes@gredler.at)
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "l2vpn.h"
/*
* BGP Layer 2 Encapsulation Types
*
* RFC 6624
*
* https://www.iana.org/assignments/bgp-parameters/bgp-parameters.xhtml#bgp-l2-encapsulation-types-registry
*/
const struct tok l2vpn_encaps_values[] = {
{ 0, "Reserved"},
{ 1, "Frame Relay"},
{ 2, "ATM AAL5 SDU VCC transport"},
{ 3, "ATM transparent cell transport"},
{ 4, "Ethernet (VLAN) Tagged Mode"},
{ 5, "Ethernet Raw Mode"},
{ 6, "Cisco HDLC"},
{ 7, "PPP"},
{ 8, "SONET/SDH Circuit Emulation Service over MPLS"},
{ 9, "ATM n-to-one VCC cell transport"},
{ 10, "ATM n-to-one VPC cell transport"},
{ 11, "IP layer 2 transport"},
{ 15, "Frame Relay Port mode"},
{ 17, "Structure-agnostic E1 over packet"},
{ 18, "Structure-agnostic T1 (DS1) over packet"},
{ 19, "VPLS"},
{ 20, "Structure-agnostic T3 (DS3) over packet"},
{ 21, "Nx64kbit/s Basic Service using Structure-aware"},
{ 25, "Frame Relay DLCI"},
{ 40, "Structure-agnostic E3 over packet"},
{ 41, "Octet-aligned playload for Structure-agnostic DS1 circuits"},
{ 42, "E1 Nx64kbit/s with CAS using Structure-aware"},
{ 43, "DS1 (ESF) Nx64kbit/s with CAS using Structure-aware"},
{ 44, "DS1 (SF) Nx64kbit/s with CAS using Structure-aware"},
{ 0, NULL}
};
/*
* MPLS Pseudowire Types
*
* RFC 4446
*
* https://www.iana.org/assignments/pwe3-parameters/pwe3-parameters.xhtml#pwe3-parameters-2
*/
const struct tok mpls_pw_types_values[] = {
{ 0x0000, "Reserved"},
{ 0x0001, "Frame Relay DLCI (Martini Mode)"},
{ 0x0002, "ATM AAL5 SDU VCC transport"},
{ 0x0003, "ATM transparent cell transport"},
{ 0x0004, "Ethernet VLAN"},
{ 0x0005, "Ethernet"},
{ 0x0006, "Cisco-HDLC"},
{ 0x0007, "PPP"},
{ 0x0008, "SONET/SDH Circuit Emulation Service over MPLS"},
{ 0x0009, "ATM n-to-one VCC cell transport"},
{ 0x000a, "ATM n-to-one VPC cell transport"},
{ 0x000b, "IP Layer2 Transport"},
{ 0x000c, "ATM one-to-one VCC Cell Mode"},
{ 0x000d, "ATM one-to-one VPC Cell Mode"},
{ 0x000e, "ATM AAL5 PDU VCC transport"},
{ 0x000f, "Frame-Relay Port mode"},
{ 0x0010, "SONET/SDH Circuit Emulation over Packet"},
{ 0x0011, "Structure-agnostic E1 over Packet"},
{ 0x0012, "Structure-agnostic T1 (DS1) over Packet"},
{ 0x0013, "Structure-agnostic E3 over Packet"},
{ 0x0014, "Structure-agnostic T3 (DS3) over Packet"},
{ 0x0015, "CESoPSN basic mode"},
{ 0x0016, "TDMoIP basic mode"},
{ 0x0017, "CESoPSN TDM with CAS"},
{ 0x0018, "TDMoIP TDM with CAS"},
{ 0x0019, "Frame Relay DLCI"},
{ 0x0040, "IP-interworking"},
{ 0, NULL}
};
diff --git a/contrib/tcpdump/machdep.c b/contrib/tcpdump/machdep.c
index 2578b73c0cb4..8ceb04a04370 100644
--- a/contrib/tcpdump/machdep.c
+++ b/contrib/tcpdump/machdep.c
@@ -1,58 +1,56 @@
/*
* Copyright (c) 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.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include <stddef.h>
#ifdef __osf__
#include <stdio.h>
#include <sys/sysinfo.h>
#include <sys/proc.h>
#endif /* __osf__ */
#include "varattrs.h"
#include "machdep.h"
/*
* 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.
*
* The only OS on which this is necessary is DEC OSF/1^W^WDigital
* UNIX^W^WTru64 UNIX.
*/
int
abort_on_misalignment(char *ebuf _U_, size_t ebufsiz _U_)
{
#ifdef __osf__
static int buf[2] = { SSIN_UACPROC, UAC_SIGBUS };
if (setsysinfo(SSI_NVPAIRS, (caddr_t)buf, 1, 0, 0) < 0) {
(void)snprintf(ebuf, ebufsiz, "setsysinfo: errno %d", errno);
return (-1);
}
#endif
return (0);
}
diff --git a/contrib/tcpdump/makemib b/contrib/tcpdump/makemib
index 97e78754ff7b..f734bb7333a0 100755
--- a/contrib/tcpdump/makemib
+++ b/contrib/tcpdump/makemib
@@ -1,247 +1,247 @@
#!/bin/sh
#
# Copyright (c) 1990, 1996
# John Robert LoVerso. All rights reserved.
# SMIv2 parsing copyright (c) 1999
# William C. Fenner.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notices, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notices, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# This script will read either ASN.1-style MIB files or the ".defs" files
# created by the ISODE "mosy" program on such files.
#
# The output of this script is the "mib.h" file used by tcpdumps' ASN.1/SNMP
# decoding code.
#
# This script needs to be run by "gawk" (GNU awk). "nawk" will work, but
# dump will get a recursion error if you process LARGE mibs. While it would
-# by farily easy to rewrite this not to use recursion (and also easy to
+# by fairly easy to rewrite this not to use recursion (and also easy to
# eliminate use of gsub and functions to use classic "awk"), you have to
# order the structure declarations in defined-first order for the compiler
# not to barf; too bad tsort doesn't take arguments.
#
cat << EOF
/*
* This file was generated by tcpdump/makemib on `date`
* You probably don't want to edit this by hand!
*
* struct mib somename = { desc, oid-octet, type, child-pointer, next-pointer
};
*/
EOF
awk '
BEGIN {
debug=0;
# for sanity, we prep the namespace with objects from RFC-1155
# (we manually establish the root)
oid["iso"]=1
oidadd("org", "iso", 3)
oidadd("dod", "org", 6)
oidadd("internet", "dod", 1)
oidadd("directory", "internet", 1)
oidadd("mgmt", "internet", 2)
#XXX oidadd("mib", "mgmt", 1)
oidadd("mib-2", "mgmt", 1)
oidadd("experimental", "internet", 3)
oidadd("private", "internet", 4)
oidadd("enterprises", "private", 1)
oidadd("ip", "mib-2", 4)
oidadd("transmission", "mib-2", 10)
holddesc="none"
}
#
# Read mosy "*.defs" file. mosy does all the parsing work; we just read
# its simple and straightforward output. It would not be too hard to make
# tcpdump directly read mosy output, but...
#
# Ignore these unless the current file is called something.defs; false
# positives are too common in DESCRIPTIONs.
NF > 1 && index($2,".")>0 && FILENAME ~ /\.defs/ {
# currently ignore items of the form "{ iso.3.6.1 }"
if (split($2, p, ".") == 2) {
oidadd($1, p[1], p[2])
}
next
}
#
# Must be a MIB file
# Make it easier to parse - used to be done by sed
{ sub(/--\*.*\*--/, ""); sub(/--.*/, ""); gsub(/[{}]/, " & "); }
#
# this next section is simple and naive, but does the job ok
#
# foo OBJECT IDENTIFIER ::= { baz 17 }
# or
# foo OBJECT IDENTIFIER ::=
# { baz 17 }
$2$3$4 == "OBJECTIDENTIFIER::=" {
holddesc="none"
if (NF == 8)
oidadd($1, $6, $7)
if (NF == 4)
holddesc=$1
next
}
$1 == "{" && holddesc != "none" && NF == 4 {
oidadd(holddesc, $2, $3)
holddesc="none"
}
#
# foo OBJECT IDENTIFIER
# ::= { bar 1 }
$2$3 == "OBJECTIDENTIFIER" && $1 != "SYNTAX" && NF == 3 {
holddesc=$1
}
#
# foo
# OBJECT IDENTIFIER ::= { bar 1 }
# a couple of heuristics to exclude single words in e.g. long
# DESCRIPTION clauses
NF == 1 && $1 ~ "[a-z][a-z]*[A-Z]" && $1 !~ /[(){}.,]/ && holddesc == "none" {
holddesc=$1
}
$1$2$3 == "OBJECTIDENTIFIER::=" && holddesc != "none" {
oidadd(holddesc, $5, $6)
holddesc="none"
}
#
# "normal" style
# foo OBJECT-TYPE ...
# ...
# ::= { baz 5 }
$2 == "MODULE-IDENTITY" || $2 == "MODULE-COMPLIANCE" ||
$2 == "OBJECT-IDENTITY" || $2 == "OBJECT-TYPE" ||
$2 == "OBJECT-GROUP" ||
$2 == "NOTIFICATION-TYPE" || $2 == "NOTIFICATION-GROUP" {
holddesc=$1
}
$1 == "::=" && holddesc != "none" && NF == 5 {
oidadd(holddesc, $3, $4)
holddesc="none"
}
#
# foo ::= { baz 17 }
$2$3 == "::={" {
oidadd($1,$4,$5)
holddesc="none"
}
#
# End of the road - output the data.
#
END {
print "struct obj"
dump("iso")
print "*mibroot = &_iso_obj;"
}
function inn(file) {
if (file == "" || file == "-")
return ""
return " in " file
}
#
# add a new object to the tree
#
# new OBJECT IDENTIFIER ::= { parent value }
#
function oidadd(new, parent, value) {
# Ignore 0.0
if (parent == "0" && value == 0)
return
if (debug)
print "/* oidadd" inn(FILENAME) ":", new, "in", parent, "as", value, "line", $0, "*/"
# use safe C identifiers
gsub(/[-&\/]/,"",new)
gsub(/[-&\/]/,"",parent)
# check if parent missing
if (oid[parent] == "") {
printf "/* parse problem%s: no parent for %s.%s(%d) */\n", \
inn(FILENAME), parent, new, value
return
}
# check if parent.value already exists
if (oid[new] > 0 && oid[new] != value) {
printf "/* parse problem%s: dup %s.%s(%d) != old (%d) */\n", \
inn(FILENAME), parent, new, value, oid[new]
return
}
# check for new name for parent.value
if (child[parent] != "") {
for (sib = child[parent]; sib != ""; sib = sibling[sib])
if (oid[sib] == value) {
if (new != sib)
printf "/* parse problem%s: new name" \
" \"%s\"" \
" for %s.%s(%d) ignored */\n", \
inn(FILENAME), new, parent, \
sib, value
return
}
}
oid[new]=value
if (child[parent] == "") {
child[parent] = new
} else {
sibling[new] = child[parent]
child[parent] = new
}
}
#
# old(?) routine to recurse down the tree (in postfix order for convenience)
#
function dump(item, c, s) {
# newitem=sofar"."item"("oid[item]")"
# printf "/* %s c=%s s=%s */\n", newitem, child[item], sibling[item]
c="NULL"
if (child[item] != "") {
dump(child[item])
c = "&_"child[item]"_obj"
}
s="NULL"
if (sibling[item] != "") {
dump(sibling[item])
s = "&_"sibling[item]"_obj"
}
printf "_%s_obj = {\n\t\"%s\", %d, 0,\n\t%s, %s\n},\n", \
item, item, oid[item], c, s
}
' $@
exit 0
diff --git a/contrib/tcpdump/mib.h b/contrib/tcpdump/mib.h
index 6c8e63c978b5..4f83e6b89125 100644
--- a/contrib/tcpdump/mib.h
+++ b/contrib/tcpdump/mib.h
@@ -1,1460 +1,1460 @@
/*
* This file was generated by tcpdump/makemib on Wed Sep 26 12:12:31 EDT 1990
* You probably don't want to edit this by hand!
*
* struct mib somename = { desc, oid-octet, type, child-pointer, next-pointer
};
*/
/* parse problem: new name "mib" for mgmt.mib(1) ignored */
/* parse problem: no parent for 0.nullSpecific(0) */
static struct obj
_proteon_obj = {
"proteon", 1, 0,
NULL, NULL
},
_ibm_obj = {
"ibm", 2, 0,
NULL, &_proteon_obj
},
_cmu_obj = {
"cmu", 3, 0,
NULL, &_ibm_obj
},
_unix_obj = {
"unix", 4, 0,
NULL, &_cmu_obj
},
_acc_obj = {
"acc", 5, 0,
NULL, &_unix_obj
},
_twg_obj = {
"twg", 6, 0,
NULL, &_acc_obj
},
_cayman_obj = {
"cayman", 7, 0,
NULL, &_twg_obj
},
_nysernet_obj = {
"nysernet", 8, 0,
NULL, &_cayman_obj
},
_cisco_obj = {
"cisco", 9, 0,
NULL, &_nysernet_obj
},
_nsc_obj = {
"nsc", 10, 0,
NULL, &_cisco_obj
},
_hp_obj = {
"hp", 11, 0,
NULL, &_nsc_obj
},
_epilogue_obj = {
"epilogue", 12, 0,
NULL, &_hp_obj
},
_utennessee_obj = {
"utennessee", 13, 0,
NULL, &_epilogue_obj
},
_bbn_obj = {
"bbn", 14, 0,
NULL, &_utennessee_obj
},
_xylogics_obj = {
"xylogics", 15, 0,
NULL, &_bbn_obj
},
_unisys_obj = {
"unisys", 16, 0,
NULL, &_xylogics_obj
},
_canstar_obj = {
"canstar", 17, 0,
NULL, &_unisys_obj
},
_wellfleet_obj = {
"wellfleet", 18, 0,
NULL, &_canstar_obj
},
_trw_obj = {
"trw", 19, 0,
NULL, &_wellfleet_obj
},
_mit_obj = {
"mit", 20, 0,
NULL, &_trw_obj
},
_eon_obj = {
"eon", 21, 0,
NULL, &_mit_obj
},
_spartacus_obj = {
"spartacus", 22, 0,
NULL, &_eon_obj
},
_excelan_obj = {
"excelan", 23, 0,
NULL, &_spartacus_obj
},
_spider_obj = {
"spider", 24, 0,
NULL, &_excelan_obj
},
_nsfnet_obj = {
"nsfnet", 25, 0,
NULL, &_spider_obj
},
_sytek_obj = {
"sytek", 26, 0,
NULL, &_nsfnet_obj
},
_intergraph_obj = {
"intergraph", 27, 0,
NULL, &_sytek_obj
},
_interlan_obj = {
"interlan", 28, 0,
NULL, &_intergraph_obj
},
_vitalink_obj = {
"vitalink", 29, 0,
NULL, &_interlan_obj
},
_ulana_obj = {
"ulana", 30, 0,
NULL, &_vitalink_obj
},
_nswc_obj = {
"nswc", 31, 0,
NULL, &_ulana_obj
},
_santacruzoperation_obj = {
"santacruzoperation", 32, 0,
NULL, &_nswc_obj
},
_xyplex_obj = {
"xyplex", 33, 0,
NULL, &_santacruzoperation_obj
},
_cray_obj = {
"cray", 34, 0,
NULL, &_xyplex_obj
},
_bellnorthernresearch_obj = {
"bellnorthernresearch", 35, 0,
NULL, &_cray_obj
},
_dec_obj = {
"dec", 36, 0,
NULL, &_bellnorthernresearch_obj
},
_touch_obj = {
"touch", 37, 0,
NULL, &_dec_obj
},
_networkresearchcorp_obj = {
"networkresearchcorp", 38, 0,
NULL, &_touch_obj
},
_baylor_obj = {
"baylor", 39, 0,
NULL, &_networkresearchcorp_obj
},
_nmfeccllnl_obj = {
"nmfeccllnl", 40, 0,
NULL, &_baylor_obj
},
_sri_obj = {
"sri", 41, 0,
NULL, &_nmfeccllnl_obj
},
_sun_obj = {
"sun", 42, 0,
NULL, &_sri_obj
},
_3com_obj = {
"3com", 43, 0,
NULL, &_sun_obj
},
_cmc_obj = {
"cmc", 44, 0,
NULL, &_3com_obj
},
_synoptics_obj = {
"synoptics", 45, 0,
NULL, &_cmc_obj
},
_cheyenne_obj = {
"cheyenne", 46, 0,
NULL, &_synoptics_obj
},
_prime_obj = {
"prime", 47, 0,
NULL, &_cheyenne_obj
},
_mcnc_obj = {
"mcnc", 48, 0,
NULL, &_prime_obj
},
_chipcom_obj = {
"chipcom", 49, 0,
NULL, &_mcnc_obj
},
_opticaldatasystems_obj = {
"opticaldatasystems", 50, 0,
NULL, &_chipcom_obj
},
_gated_obj = {
"gated", 51, 0,
NULL, &_opticaldatasystems_obj
},
_cabletron_obj = {
"cabletron", 52, 0,
NULL, &_gated_obj
},
_apollo_obj = {
"apollo", 53, 0,
NULL, &_cabletron_obj
},
_desktalksystems_obj = {
"desktalksystems", 54, 0,
NULL, &_apollo_obj
},
_ssds_obj = {
"ssds", 55, 0,
NULL, &_desktalksystems_obj
},
_castlerock_obj = {
"castlerock", 56, 0,
NULL, &_ssds_obj
},
_mips_obj = {
"mips", 57, 0,
NULL, &_castlerock_obj
},
_tgv_obj = {
"tgv", 58, 0,
NULL, &_mips_obj
},
_silicongraphics_obj = {
"silicongraphics", 59, 0,
NULL, &_tgv_obj
},
_ubc_obj = {
"ubc", 60, 0,
NULL, &_silicongraphics_obj
},
_merit_obj = {
"merit", 61, 0,
NULL, &_ubc_obj
},
_fibercom_obj = {
"fibercom", 62, 0,
NULL, &_merit_obj
},
_apple_obj = {
"apple", 63, 0,
NULL, &_fibercom_obj
},
_gandalf_obj = {
"gandalf", 64, 0,
NULL, &_apple_obj
},
_dartmouth_obj = {
"dartmouth", 65, 0,
NULL, &_gandalf_obj
},
_davidsystems_obj = {
"davidsystems", 66, 0,
NULL, &_dartmouth_obj
},
_reuter_obj = {
"reuter", 67, 0,
NULL, &_davidsystems_obj
},
_cornell_obj = {
"cornell", 68, 0,
NULL, &_reuter_obj
},
_tmac_obj = {
"tmac", 69, 0,
NULL, &_cornell_obj
},
_locus_obj = {
"locus", 70, 0,
NULL, &_tmac_obj
},
_nasa_obj = {
"nasa", 71, 0,
NULL, &_locus_obj
},
_retix_obj = {
"retix", 72, 0,
NULL, &_nasa_obj
},
_boeing_obj = {
"boeing", 73, 0,
NULL, &_retix_obj
},
_att_obj = {
"att", 74, 0,
NULL, &_boeing_obj
},
_ungermannbass_obj = {
"ungermannbass", 75, 0,
NULL, &_att_obj
},
_digitalanalysis_obj = {
"digitalanalysis", 76, 0,
NULL, &_ungermannbass_obj
},
_hplanman_obj = {
"hplanman", 77, 0,
NULL, &_digitalanalysis_obj
},
_netlabs_obj = {
"netlabs", 78, 0,
NULL, &_hplanman_obj
},
_icl_obj = {
"icl", 79, 0,
NULL, &_netlabs_obj
},
_auspex_obj = {
"auspex", 80, 0,
NULL, &_icl_obj
},
_lannet_obj = {
"lannet", 81, 0,
NULL, &_auspex_obj
},
_ncd_obj = {
"ncd", 82, 0,
NULL, &_lannet_obj
},
_raycom_obj = {
"raycom", 83, 0,
NULL, &_ncd_obj
},
_pirellifocom_obj = {
"pirellifocom", 84, 0,
NULL, &_raycom_obj
},
_datability_obj = {
"datability", 85, 0,
NULL, &_pirellifocom_obj
},
_networkappltech_obj = {
"networkappltech", 86, 0,
NULL, &_datability_obj
},
_link_obj = {
"link", 87, 0,
NULL, &_networkappltech_obj
},
_nyu_obj = {
"nyu", 88, 0,
NULL, &_link_obj
},
_rnd_obj = {
"rnd", 89, 0,
NULL, &_nyu_obj
},
_intercon_obj = {
"intercon", 90, 0,
NULL, &_rnd_obj
},
_learningtree_obj = {
"learningtree", 91, 0,
NULL, &_intercon_obj
},
_webstercomputer_obj = {
"webstercomputer", 92, 0,
NULL, &_learningtree_obj
},
_frontier_obj = {
"frontier", 93, 0,
NULL, &_webstercomputer_obj
},
_nokia_obj = {
"nokia", 94, 0,
NULL, &_frontier_obj
},
_allenbradley_obj = {
"allenbradley", 95, 0,
NULL, &_nokia_obj
},
_cern_obj = {
"cern", 96, 0,
NULL, &_allenbradley_obj
},
_sigma_obj = {
"sigma", 97, 0,
NULL, &_cern_obj
},
_emergingtech_obj = {
"emergingtech", 98, 0,
NULL, &_sigma_obj
},
_snmpresearch_obj = {
"snmpresearch", 99, 0,
NULL, &_emergingtech_obj
},
_ohiostate_obj = {
"ohiostate", 100, 0,
NULL, &_snmpresearch_obj
},
_ultra_obj = {
"ultra", 101, 0,
NULL, &_ohiostate_obj
},
_ccur_obj = {
"ccur", 136, 0,
NULL, &_ultra_obj
},
_enterprises_obj = {
"enterprises", 1, 0,
&_ccur_obj, NULL
},
_snmpInPkts_obj = {
"snmpInPkts", 1, 0,
NULL, NULL
},
_snmpOutPkts_obj = {
"snmpOutPkts", 2, 0,
NULL, &_snmpInPkts_obj
},
_snmpInBadVersions_obj = {
"snmpInBadVersions", 3, 0,
NULL, &_snmpOutPkts_obj
},
_snmpInBadCommunityNames_obj = {
"snmpInBadCommunityNames", 4, 0,
NULL, &_snmpInBadVersions_obj
},
_snmpInBadCommunityUses_obj = {
"snmpInBadCommunityUses", 5, 0,
NULL, &_snmpInBadCommunityNames_obj
},
_snmpInASNParseErrs_obj = {
"snmpInASNParseErrs", 6, 0,
NULL, &_snmpInBadCommunityUses_obj
},
_snmpInBadTypes_obj = {
"snmpInBadTypes", 7, 0,
NULL, &_snmpInASNParseErrs_obj
},
_snmpInTooBigs_obj = {
"snmpInTooBigs", 8, 0,
NULL, &_snmpInBadTypes_obj
},
_snmpInNoSuchNames_obj = {
"snmpInNoSuchNames", 9, 0,
NULL, &_snmpInTooBigs_obj
},
_snmpInBadValues_obj = {
"snmpInBadValues", 10, 0,
NULL, &_snmpInNoSuchNames_obj
},
_snmpInReadOnlys_obj = {
"snmpInReadOnlys", 11, 0,
NULL, &_snmpInBadValues_obj
},
_snmpInGenErrs_obj = {
"snmpInGenErrs", 12, 0,
NULL, &_snmpInReadOnlys_obj
},
_snmpInTotalReqVars_obj = {
"snmpInTotalReqVars", 13, 0,
NULL, &_snmpInGenErrs_obj
},
_snmpInTotalSetVars_obj = {
"snmpInTotalSetVars", 14, 0,
NULL, &_snmpInTotalReqVars_obj
},
_snmpInGetRequests_obj = {
"snmpInGetRequests", 15, 0,
NULL, &_snmpInTotalSetVars_obj
},
_snmpInGetNexts_obj = {
"snmpInGetNexts", 16, 0,
NULL, &_snmpInGetRequests_obj
},
_snmpInSetRequests_obj = {
"snmpInSetRequests", 17, 0,
NULL, &_snmpInGetNexts_obj
},
_snmpInGetResponses_obj = {
"snmpInGetResponses", 18, 0,
NULL, &_snmpInSetRequests_obj
},
_snmpInTraps_obj = {
"snmpInTraps", 19, 0,
NULL, &_snmpInGetResponses_obj
},
_snmpOutTooBigs_obj = {
"snmpOutTooBigs", 20, 0,
NULL, &_snmpInTraps_obj
},
_snmpOutNoSuchNames_obj = {
"snmpOutNoSuchNames", 21, 0,
NULL, &_snmpOutTooBigs_obj
},
_snmpOutBadValues_obj = {
"snmpOutBadValues", 22, 0,
NULL, &_snmpOutNoSuchNames_obj
},
_snmpOutReadOnlys_obj = {
"snmpOutReadOnlys", 23, 0,
NULL, &_snmpOutBadValues_obj
},
_snmpOutGenErrs_obj = {
"snmpOutGenErrs", 24, 0,
NULL, &_snmpOutReadOnlys_obj
},
_snmpOutGetRequests_obj = {
"snmpOutGetRequests", 25, 0,
NULL, &_snmpOutGenErrs_obj
},
_snmpOutGetNexts_obj = {
"snmpOutGetNexts", 26, 0,
NULL, &_snmpOutGetRequests_obj
},
_snmpOutSetRequests_obj = {
"snmpOutSetRequests", 27, 0,
NULL, &_snmpOutGetNexts_obj
},
_snmpOutGetResponses_obj = {
"snmpOutGetResponses", 28, 0,
NULL, &_snmpOutSetRequests_obj
},
_snmpOutTraps_obj = {
"snmpOutTraps", 29, 0,
NULL, &_snmpOutGetResponses_obj
},
_snmpEnableAuthTraps_obj = {
"snmpEnableAuthTraps", 30, 0,
NULL, &_snmpOutTraps_obj
},
_egpNeighState_obj = {
"egpNeighState", 1, 0,
NULL, NULL
},
_egpNeighAddr_obj = {
"egpNeighAddr", 2, 0,
NULL, &_egpNeighState_obj
},
_egpNeighAs_obj = {
"egpNeighAs", 3, 0,
NULL, &_egpNeighAddr_obj
},
_egpNeighInMsgs_obj = {
"egpNeighInMsgs", 4, 0,
NULL, &_egpNeighAs_obj
},
_egpNeighInErrs_obj = {
"egpNeighInErrs", 5, 0,
NULL, &_egpNeighInMsgs_obj
},
_egpNeighOutMsgs_obj = {
"egpNeighOutMsgs", 6, 0,
NULL, &_egpNeighInErrs_obj
},
_egpNeighOutErrs_obj = {
"egpNeighOutErrs", 7, 0,
NULL, &_egpNeighOutMsgs_obj
},
_egpNeighInErrMsgs_obj = {
"egpNeighInErrMsgs", 8, 0,
NULL, &_egpNeighOutErrs_obj
},
_egpNeighOutErrMsgs_obj = {
"egpNeighOutErrMsgs", 9, 0,
NULL, &_egpNeighInErrMsgs_obj
},
_egpNeighStateUps_obj = {
"egpNeighStateUps", 10, 0,
NULL, &_egpNeighOutErrMsgs_obj
},
_egpNeighStateDowns_obj = {
"egpNeighStateDowns", 11, 0,
NULL, &_egpNeighStateUps_obj
},
_egpNeighIntervalHello_obj = {
"egpNeighIntervalHello", 12, 0,
NULL, &_egpNeighStateDowns_obj
},
_egpNeighIntervalPoll_obj = {
"egpNeighIntervalPoll", 13, 0,
NULL, &_egpNeighIntervalHello_obj
},
_egpNeighMode_obj = {
"egpNeighMode", 14, 0,
NULL, &_egpNeighIntervalPoll_obj
},
_egpNeighEventTrigger_obj = {
"egpNeighEventTrigger", 15, 0,
NULL, &_egpNeighMode_obj
},
_egpNeighEntry_obj = {
"egpNeighEntry", 1, 0,
&_egpNeighEventTrigger_obj, NULL
},
_egpInMsgs_obj = {
"egpInMsgs", 1, 0,
NULL, NULL
},
_egpInErrors_obj = {
"egpInErrors", 2, 0,
NULL, &_egpInMsgs_obj
},
_egpOutMsgs_obj = {
"egpOutMsgs", 3, 0,
NULL, &_egpInErrors_obj
},
_egpOutErrors_obj = {
"egpOutErrors", 4, 0,
NULL, &_egpOutMsgs_obj
},
_egpNeighTable_obj = {
"egpNeighTable", 5, 0,
&_egpNeighEntry_obj, &_egpOutErrors_obj
},
_egpAs_obj = {
"egpAs", 6, 0,
NULL, &_egpNeighTable_obj
},
_udpLocalAddress_obj = {
"udpLocalAddress", 1, 0,
NULL, NULL
},
_udpLocalPort_obj = {
"udpLocalPort", 2, 0,
NULL, &_udpLocalAddress_obj
},
_udpEntry_obj = {
"udpEntry", 1, 0,
&_udpLocalPort_obj, NULL
},
_udpInDatagrams_obj = {
"udpInDatagrams", 1, 0,
NULL, NULL
},
_udpNoPorts_obj = {
"udpNoPorts", 2, 0,
NULL, &_udpInDatagrams_obj
},
_udpInErrors_obj = {
"udpInErrors", 3, 0,
NULL, &_udpNoPorts_obj
},
_udpOutDatagrams_obj = {
"udpOutDatagrams", 4, 0,
NULL, &_udpInErrors_obj
},
_udpTable_obj = {
"udpTable", 5, 0,
&_udpEntry_obj, &_udpOutDatagrams_obj
},
_tcpConnState_obj = {
"tcpConnState", 1, 0,
NULL, NULL
},
_tcpConnLocalAddress_obj = {
"tcpConnLocalAddress", 2, 0,
NULL, &_tcpConnState_obj
},
_tcpConnLocalPort_obj = {
"tcpConnLocalPort", 3, 0,
NULL, &_tcpConnLocalAddress_obj
},
_tcpConnRemAddress_obj = {
"tcpConnRemAddress", 4, 0,
NULL, &_tcpConnLocalPort_obj
},
_tcpConnRemPort_obj = {
"tcpConnRemPort", 5, 0,
NULL, &_tcpConnRemAddress_obj
},
_tcpConnEntry_obj = {
"tcpConnEntry", 1, 0,
&_tcpConnRemPort_obj, NULL
},
_tcpRtoAlgorithm_obj = {
"tcpRtoAlgorithm", 1, 0,
NULL, NULL
},
_tcpRtoMin_obj = {
"tcpRtoMin", 2, 0,
NULL, &_tcpRtoAlgorithm_obj
},
_tcpRtoMax_obj = {
"tcpRtoMax", 3, 0,
NULL, &_tcpRtoMin_obj
},
_tcpMaxConn_obj = {
"tcpMaxConn", 4, 0,
NULL, &_tcpRtoMax_obj
},
_tcpActiveOpens_obj = {
"tcpActiveOpens", 5, 0,
NULL, &_tcpMaxConn_obj
},
_tcpPassiveOpens_obj = {
"tcpPassiveOpens", 6, 0,
NULL, &_tcpActiveOpens_obj
},
_tcpAttemptFails_obj = {
"tcpAttemptFails", 7, 0,
NULL, &_tcpPassiveOpens_obj
},
_tcpEstabResets_obj = {
"tcpEstabResets", 8, 0,
NULL, &_tcpAttemptFails_obj
},
_tcpCurrEstab_obj = {
"tcpCurrEstab", 9, 0,
NULL, &_tcpEstabResets_obj
},
_tcpInSegs_obj = {
"tcpInSegs", 10, 0,
NULL, &_tcpCurrEstab_obj
},
_tcpOutSegs_obj = {
"tcpOutSegs", 11, 0,
NULL, &_tcpInSegs_obj
},
_tcpRetransSegs_obj = {
"tcpRetransSegs", 12, 0,
NULL, &_tcpOutSegs_obj
},
_tcpConnTable_obj = {
"tcpConnTable", 13, 0,
&_tcpConnEntry_obj, &_tcpRetransSegs_obj
},
_tcpInErrs_obj = {
"tcpInErrs", 14, 0,
NULL, &_tcpConnTable_obj
},
_tcpOutRsts_obj = {
"tcpOutRsts", 15, 0,
NULL, &_tcpInErrs_obj
},
_icmpInMsgs_obj = {
"icmpInMsgs", 1, 0,
NULL, NULL
},
_icmpInErrors_obj = {
"icmpInErrors", 2, 0,
NULL, &_icmpInMsgs_obj
},
_icmpInDestUnreachs_obj = {
"icmpInDestUnreachs", 3, 0,
NULL, &_icmpInErrors_obj
},
_icmpInTimeExcds_obj = {
"icmpInTimeExcds", 4, 0,
NULL, &_icmpInDestUnreachs_obj
},
_icmpInParmProbs_obj = {
"icmpInParmProbs", 5, 0,
NULL, &_icmpInTimeExcds_obj
},
-_icmpInSrcQuenchs_obj = {
- "icmpInSrcQuenchs", 6, 0,
+_icmpInSrcQuenches_obj = {
+ "icmpInSrcQuenches", 6, 0,
NULL, &_icmpInParmProbs_obj
},
_icmpInRedirects_obj = {
"icmpInRedirects", 7, 0,
- NULL, &_icmpInSrcQuenchs_obj
+ NULL, &_icmpInSrcQuenches_obj
},
_icmpInEchos_obj = {
"icmpInEchos", 8, 0,
NULL, &_icmpInRedirects_obj
},
_icmpInEchoReps_obj = {
"icmpInEchoReps", 9, 0,
NULL, &_icmpInEchos_obj
},
_icmpInTimestamps_obj = {
"icmpInTimestamps", 10, 0,
NULL, &_icmpInEchoReps_obj
},
_icmpInTimestampReps_obj = {
"icmpInTimestampReps", 11, 0,
NULL, &_icmpInTimestamps_obj
},
_icmpInAddrMasks_obj = {
"icmpInAddrMasks", 12, 0,
NULL, &_icmpInTimestampReps_obj
},
_icmpInAddrMaskReps_obj = {
"icmpInAddrMaskReps", 13, 0,
NULL, &_icmpInAddrMasks_obj
},
_icmpOutMsgs_obj = {
"icmpOutMsgs", 14, 0,
NULL, &_icmpInAddrMaskReps_obj
},
_icmpOutErrors_obj = {
"icmpOutErrors", 15, 0,
NULL, &_icmpOutMsgs_obj
},
_icmpOutDestUnreachs_obj = {
"icmpOutDestUnreachs", 16, 0,
NULL, &_icmpOutErrors_obj
},
_icmpOutTimeExcds_obj = {
"icmpOutTimeExcds", 17, 0,
NULL, &_icmpOutDestUnreachs_obj
},
_icmpOutParmProbs_obj = {
"icmpOutParmProbs", 18, 0,
NULL, &_icmpOutTimeExcds_obj
},
-_icmpOutSrcQuenchs_obj = {
- "icmpOutSrcQuenchs", 19, 0,
+_icmpOutSrcQuenches_obj = {
+ "icmpOutSrcQuenches", 19, 0,
NULL, &_icmpOutParmProbs_obj
},
_icmpOutRedirects_obj = {
"icmpOutRedirects", 20, 0,
- NULL, &_icmpOutSrcQuenchs_obj
+ NULL, &_icmpOutSrcQuenches_obj
},
_icmpOutEchos_obj = {
"icmpOutEchos", 21, 0,
NULL, &_icmpOutRedirects_obj
},
_icmpOutEchoReps_obj = {
"icmpOutEchoReps", 22, 0,
NULL, &_icmpOutEchos_obj
},
_icmpOutTimestamps_obj = {
"icmpOutTimestamps", 23, 0,
NULL, &_icmpOutEchoReps_obj
},
_icmpOutTimestampReps_obj = {
"icmpOutTimestampReps", 24, 0,
NULL, &_icmpOutTimestamps_obj
},
_icmpOutAddrMasks_obj = {
"icmpOutAddrMasks", 25, 0,
NULL, &_icmpOutTimestampReps_obj
},
_icmpOutAddrMaskReps_obj = {
"icmpOutAddrMaskReps", 26, 0,
NULL, &_icmpOutAddrMasks_obj
},
_ipNetToMediaIfIndex_obj = {
"ipNetToMediaIfIndex", 1, 0,
NULL, NULL
},
_ipNetToMediaPhysAddress_obj = {
"ipNetToMediaPhysAddress", 2, 0,
NULL, &_ipNetToMediaIfIndex_obj
},
_ipNetToMediaNetAddress_obj = {
"ipNetToMediaNetAddress", 3, 0,
NULL, &_ipNetToMediaPhysAddress_obj
},
_ipNetToMediaType_obj = {
"ipNetToMediaType", 4, 0,
NULL, &_ipNetToMediaNetAddress_obj
},
_ipNetToMediaEntry_obj = {
"ipNetToMediaEntry", 1, 0,
&_ipNetToMediaType_obj, NULL
},
_ipRouteDest_obj = {
"ipRouteDest", 1, 0,
NULL, NULL
},
_ipRouteIfIndex_obj = {
"ipRouteIfIndex", 2, 0,
NULL, &_ipRouteDest_obj
},
_ipRouteMetric1_obj = {
"ipRouteMetric1", 3, 0,
NULL, &_ipRouteIfIndex_obj
},
_ipRouteMetric2_obj = {
"ipRouteMetric2", 4, 0,
NULL, &_ipRouteMetric1_obj
},
_ipRouteMetric3_obj = {
"ipRouteMetric3", 5, 0,
NULL, &_ipRouteMetric2_obj
},
_ipRouteMetric4_obj = {
"ipRouteMetric4", 6, 0,
NULL, &_ipRouteMetric3_obj
},
_ipRouteNextHop_obj = {
"ipRouteNextHop", 7, 0,
NULL, &_ipRouteMetric4_obj
},
_ipRouteType_obj = {
"ipRouteType", 8, 0,
NULL, &_ipRouteNextHop_obj
},
_ipRouteProto_obj = {
"ipRouteProto", 9, 0,
NULL, &_ipRouteType_obj
},
_ipRouteAge_obj = {
"ipRouteAge", 10, 0,
NULL, &_ipRouteProto_obj
},
_ipRouteMask_obj = {
"ipRouteMask", 11, 0,
NULL, &_ipRouteAge_obj
},
_ipRouteEntry_obj = {
"ipRouteEntry", 1, 0,
&_ipRouteMask_obj, NULL
},
_ipAdEntAddr_obj = {
"ipAdEntAddr", 1, 0,
NULL, NULL
},
_ipAdEntIfIndex_obj = {
"ipAdEntIfIndex", 2, 0,
NULL, &_ipAdEntAddr_obj
},
_ipAdEntNetMask_obj = {
"ipAdEntNetMask", 3, 0,
NULL, &_ipAdEntIfIndex_obj
},
_ipAdEntBcastAddr_obj = {
"ipAdEntBcastAddr", 4, 0,
NULL, &_ipAdEntNetMask_obj
},
_ipAdEntReasmMaxSize_obj = {
"ipAdEntReasmMaxSize", 5, 0,
NULL, &_ipAdEntBcastAddr_obj
},
_ipAddrEntry_obj = {
"ipAddrEntry", 1, 0,
&_ipAdEntReasmMaxSize_obj, NULL
},
_ipForwarding_obj = {
"ipForwarding", 1, 0,
NULL, NULL
},
_ipDefaultTTL_obj = {
"ipDefaultTTL", 2, 0,
NULL, &_ipForwarding_obj
},
_ipInReceives_obj = {
"ipInReceives", 3, 0,
NULL, &_ipDefaultTTL_obj
},
_ipInHdrErrors_obj = {
"ipInHdrErrors", 4, 0,
NULL, &_ipInReceives_obj
},
_ipInAddrErrors_obj = {
"ipInAddrErrors", 5, 0,
NULL, &_ipInHdrErrors_obj
},
_ipForwDatagrams_obj = {
"ipForwDatagrams", 6, 0,
NULL, &_ipInAddrErrors_obj
},
_ipInUnknownProtos_obj = {
"ipInUnknownProtos", 7, 0,
NULL, &_ipForwDatagrams_obj
},
_ipInDiscards_obj = {
"ipInDiscards", 8, 0,
NULL, &_ipInUnknownProtos_obj
},
_ipInDelivers_obj = {
"ipInDelivers", 9, 0,
NULL, &_ipInDiscards_obj
},
_ipOutRequests_obj = {
"ipOutRequests", 10, 0,
NULL, &_ipInDelivers_obj
},
_ipOutDiscards_obj = {
"ipOutDiscards", 11, 0,
NULL, &_ipOutRequests_obj
},
_ipOutNoRoutes_obj = {
"ipOutNoRoutes", 12, 0,
NULL, &_ipOutDiscards_obj
},
_ipReasmTimeout_obj = {
"ipReasmTimeout", 13, 0,
NULL, &_ipOutNoRoutes_obj
},
_ipReasmReqds_obj = {
"ipReasmReqds", 14, 0,
NULL, &_ipReasmTimeout_obj
},
_ipReasmOKs_obj = {
"ipReasmOKs", 15, 0,
NULL, &_ipReasmReqds_obj
},
_ipReasmFails_obj = {
"ipReasmFails", 16, 0,
NULL, &_ipReasmOKs_obj
},
_ipFragOKs_obj = {
"ipFragOKs", 17, 0,
NULL, &_ipReasmFails_obj
},
_ipFragFails_obj = {
"ipFragFails", 18, 0,
NULL, &_ipFragOKs_obj
},
_ipFragCreates_obj = {
"ipFragCreates", 19, 0,
NULL, &_ipFragFails_obj
},
_ipAddrTable_obj = {
"ipAddrTable", 20, 0,
&_ipAddrEntry_obj, &_ipFragCreates_obj
},
_ipRoutingTable_obj = {
"ipRoutingTable", 21, 0,
&_ipRouteEntry_obj, &_ipAddrTable_obj
},
_ipNetToMediaTable_obj = {
"ipNetToMediaTable", 22, 0,
&_ipNetToMediaEntry_obj, &_ipRoutingTable_obj
},
_atIfIndex_obj = {
"atIfIndex", 1, 0,
NULL, NULL
},
_atPhysAddress_obj = {
"atPhysAddress", 2, 0,
NULL, &_atIfIndex_obj
},
_atNetAddress_obj = {
"atNetAddress", 3, 0,
NULL, &_atPhysAddress_obj
},
_atEntry_obj = {
"atEntry", 1, 0,
&_atNetAddress_obj, NULL
},
_atTable_obj = {
"atTable", 1, 0,
&_atEntry_obj, NULL
},
_ifIndex_obj = {
"ifIndex", 1, 0,
NULL, NULL
},
_ifDescr_obj = {
"ifDescr", 2, 0,
NULL, &_ifIndex_obj
},
_ifType_obj = {
"ifType", 3, 0,
NULL, &_ifDescr_obj
},
_ifMtu_obj = {
"ifMtu", 4, 0,
NULL, &_ifType_obj
},
_ifSpeed_obj = {
"ifSpeed", 5, 0,
NULL, &_ifMtu_obj
},
_ifPhysAddress_obj = {
"ifPhysAddress", 6, 0,
NULL, &_ifSpeed_obj
},
_ifAdminStatus_obj = {
"ifAdminStatus", 7, 0,
NULL, &_ifPhysAddress_obj
},
_ifOperStatus_obj = {
"ifOperStatus", 8, 0,
NULL, &_ifAdminStatus_obj
},
_ifLastChange_obj = {
"ifLastChange", 9, 0,
NULL, &_ifOperStatus_obj
},
_ifInOctets_obj = {
"ifInOctets", 10, 0,
NULL, &_ifLastChange_obj
},
_ifInUcastPkts_obj = {
"ifInUcastPkts", 11, 0,
NULL, &_ifInOctets_obj
},
_ifInNUcastPkts_obj = {
"ifInNUcastPkts", 12, 0,
NULL, &_ifInUcastPkts_obj
},
_ifInDiscards_obj = {
"ifInDiscards", 13, 0,
NULL, &_ifInNUcastPkts_obj
},
_ifInErrors_obj = {
"ifInErrors", 14, 0,
NULL, &_ifInDiscards_obj
},
_ifInUnknownProtos_obj = {
"ifInUnknownProtos", 15, 0,
NULL, &_ifInErrors_obj
},
_ifOutOctets_obj = {
"ifOutOctets", 16, 0,
NULL, &_ifInUnknownProtos_obj
},
_ifOutUcastPkts_obj = {
"ifOutUcastPkts", 17, 0,
NULL, &_ifOutOctets_obj
},
_ifOutNUcastPkts_obj = {
"ifOutNUcastPkts", 18, 0,
NULL, &_ifOutUcastPkts_obj
},
_ifOutDiscards_obj = {
"ifOutDiscards", 19, 0,
NULL, &_ifOutNUcastPkts_obj
},
_ifOutErrors_obj = {
"ifOutErrors", 20, 0,
NULL, &_ifOutDiscards_obj
},
_ifOutQLen_obj = {
"ifOutQLen", 21, 0,
NULL, &_ifOutErrors_obj
},
_ifSpecific_obj = {
"ifSpecific", 22, 0,
NULL, &_ifOutQLen_obj
},
_ifEntry_obj = {
"ifEntry", 1, 0,
&_ifSpecific_obj, NULL
},
_ifNumber_obj = {
"ifNumber", 1, 0,
NULL, NULL
},
_ifTable_obj = {
"ifTable", 2, 0,
&_ifEntry_obj, &_ifNumber_obj
},
_sysDescr_obj = {
"sysDescr", 1, 0,
NULL, NULL
},
_sysObjectID_obj = {
"sysObjectID", 2, 0,
NULL, &_sysDescr_obj
},
_sysUpTime_obj = {
"sysUpTime", 3, 0,
NULL, &_sysObjectID_obj
},
_sysContact_obj = {
"sysContact", 4, 0,
NULL, &_sysUpTime_obj
},
_sysName_obj = {
"sysName", 5, 0,
NULL, &_sysContact_obj
},
_sysLocation_obj = {
"sysLocation", 6, 0,
NULL, &_sysName_obj
},
_sysServices_obj = {
"sysServices", 7, 0,
NULL, &_sysLocation_obj
},
_system_obj = {
"system", 1, 0,
&_sysServices_obj, NULL
},
_interfaces_obj = {
"interfaces", 2, 0,
&_ifTable_obj, &_system_obj
},
_at_obj = {
"at", 3, 0,
&_atTable_obj, &_interfaces_obj
},
_ip_obj = {
"ip", 4, 0,
&_ipNetToMediaTable_obj, &_at_obj
},
_icmp_obj = {
"icmp", 5, 0,
&_icmpOutAddrMaskReps_obj, &_ip_obj
},
_tcp_obj = {
"tcp", 6, 0,
&_tcpOutRsts_obj, &_icmp_obj
},
_udp_obj = {
"udp", 7, 0,
&_udpTable_obj, &_tcp_obj
},
_egp_obj = {
"egp", 8, 0,
&_egpAs_obj, &_udp_obj
},
_transmission_obj = {
"transmission", 10, 0,
NULL, &_egp_obj
},
_snmp_obj = {
"snmp", 11, 0,
&_snmpEnableAuthTraps_obj, &_transmission_obj
},
_usmMIBCompliances_obj = {
"usmMIBCompliances", 1, 0,
NULL, NULL
},
_usmMIBGroups_obj = {
"usmMIBGroups", 2, 0,
NULL, &_usmMIBCompliances_obj
},
_usmUserEngineID_obj = {
"usmUserEngineID", 1, 0,
NULL, NULL
},
_usmUserName_obj = {
"usmUserName", 2, 0,
NULL, &_usmUserEngineID_obj
},
_usmUserSecurityName_obj = {
"usmUserSecurityName", 3, 0,
NULL, &_usmUserName_obj
},
_usmUserCloneFrom_obj = {
"usmUserCloneFrom", 4, 0,
NULL, &_usmUserSecurityName_obj
},
_usmUserAuthProtocol_obj = {
"usmUserAuthProtocol", 5, 0,
NULL, &_usmUserCloneFrom_obj
},
_usmUserAuthKeyChange_obj = {
"usmUserAuthKeyChange", 6, 0,
NULL, &_usmUserAuthProtocol_obj
},
_usmUserOwnAuthKeyChange_obj = {
"usmUserOwnAuthKeyChange", 7, 0,
NULL, &_usmUserAuthKeyChange_obj
},
_usmUserPrivProtocol_obj = {
"usmUserPrivProtocol", 8, 0,
NULL, &_usmUserOwnAuthKeyChange_obj
},
_usmUserPrivKeyChange_obj = {
"usmUserPrivKeyChange", 9, 0,
NULL, &_usmUserPrivProtocol_obj
},
_usmUserOwnPrivKeyChange_obj = {
"usmUserOwnPrivKeyChange", 10, 0,
NULL, &_usmUserPrivKeyChange_obj
},
_usmUserPublic_obj = {
"usmUserPublic", 11, 0,
NULL, &_usmUserOwnPrivKeyChange_obj
},
_usmUserStorageType_obj = {
"usmUserStorageType", 12, 0,
NULL, &_usmUserPublic_obj
},
_usmUserStatus_obj = {
"usmUserStatus", 13, 0,
NULL, &_usmUserStorageType_obj
},
_usmUserEntry_obj = {
"usmUserEntry", 1, 0,
&_usmUserStatus_obj, NULL
},
_usmUserSpinLock_obj = {
"usmUserSpinLock", 1, 0,
NULL, NULL
},
_usmUserTable_obj = {
"usmUserTable", 2, 0,
&_usmUserEntry_obj, &_usmUserSpinLock_obj
},
_usmStatsUnsupportedSecLevels_obj = {
"usmStatsUnsupportedSecLevels", 1, 0,
NULL, NULL
},
_usmStatsNotInTimeWindows_obj = {
"usmStatsNotInTimeWindows", 2, 0,
NULL, &_usmStatsUnsupportedSecLevels_obj
},
_usmStatsUnknownUserNames_obj = {
"usmStatsUnknownUserNames", 3, 0,
NULL, &_usmStatsNotInTimeWindows_obj
},
_usmStatsUnknownEngineIDs_obj = {
"usmStatsUnknownEngineIDs", 4, 0,
NULL, &_usmStatsUnknownUserNames_obj
},
_usmStatsWrongDigests_obj = {
"usmStatsWrongDigests", 5, 0,
NULL, &_usmStatsUnknownEngineIDs_obj
},
_usmStatsDecryptionErrors_obj = {
"usmStatsDecryptionErrors", 6, 0,
NULL, &_usmStatsWrongDigests_obj
},
_usmStats_obj = {
"usmStats", 1, 0,
&_usmStatsDecryptionErrors_obj, NULL
},
_usmUser_obj = {
"usmUser", 2, 0,
&_usmUserTable_obj, &_usmStats_obj
},
_usmMIBObjects_obj = {
"usmMIBObjects", 1, 0,
&_usmUser_obj, NULL
},
_usmMIBConformance_obj = {
"usmMIBConformance", 2, 0,
&_usmMIBGroups_obj, &_usmMIBObjects_obj
},
_snmpMPDMIBCompliances_obj = {
"snmpMPDMIBCompliances", 1, 0,
NULL, NULL
},
_snmpMPDMIBGroups_obj = {
"snmpMPDMIBGroups", 2, 0,
NULL, &_snmpMPDMIBCompliances_obj
},
_snmpUnknownSecurityModels_obj = {
"snmpUnknownSecurityModels", 1, 0,
NULL, NULL
},
_snmpInvalidMsgs_obj = {
"snmpInvalidMsgs", 2, 0,
NULL, &_snmpUnknownSecurityModels_obj
},
_snmpUnknownPDUHandlers_obj = {
"snmpUnknownPDUHandlers", 3, 0,
NULL, &_snmpInvalidMsgs_obj
},
_snmpMPDStats_obj = {
"snmpMPDStats", 1, 0,
&_snmpUnknownPDUHandlers_obj, NULL
},
_snmpMPDAdmin_obj = {
"snmpMPDAdmin", 1, 0,
NULL, NULL
},
_snmpMPDMIBObjects_obj = {
"snmpMPDMIBObjects", 2, 0,
&_snmpMPDStats_obj, &_snmpMPDAdmin_obj
},
_snmpMPDMIBConformance_obj = {
"snmpMPDMIBConformance", 3, 0,
&_snmpMPDMIBGroups_obj, &_snmpMPDMIBObjects_obj
},
_snmpEngineID_obj = {
"snmpEngineID", 1, 0,
NULL, NULL
},
_snmpEngineBoots_obj = {
"snmpEngineBoots", 2, 0,
NULL, &_snmpEngineID_obj
},
_snmpEngineTime_obj = {
"snmpEngineTime", 3, 0,
NULL, &_snmpEngineBoots_obj
},
_snmpEngineMaxMessageSize_obj = {
"snmpEngineMaxMessageSize", 4, 0,
NULL, &_snmpEngineTime_obj
},
_snmpEngine_obj = {
"snmpEngine", 1, 0,
&_snmpEngineMaxMessageSize_obj, NULL
},
_snmpFrameworkAdmin_obj = {
"snmpFrameworkAdmin", 1, 0,
NULL, NULL
},
_snmpFrameworkMIBObjects_obj = {
"snmpFrameworkMIBObjects", 2, 0,
&_snmpEngine_obj, &_snmpFrameworkAdmin_obj
},
_snmpFrameworkMIBConformance_obj = {
"snmpFrameworkMIBConformance", 3, 0,
NULL, &_snmpFrameworkMIBObjects_obj
},
_snmpFrameworkMIB_obj = {
"snmpFrameworkMIB", 10, 0,
&_snmpFrameworkMIBConformance_obj, NULL
},
_snmpMPDMIB_obj = {
"snmpMPDMIB", 11, 0,
&_snmpMPDMIBConformance_obj, &_snmpFrameworkMIB_obj
},
_snmpUsmMIB_obj = {
"snmpUsmMIB", 15, 0,
&_usmMIBConformance_obj, &_snmpMPDMIB_obj
},
_snmpModules_obj = {
"snmpModules", 3, 0,
&_snmpUsmMIB_obj, NULL
},
_mib_obj = {
"mib", 1, 0,
&_snmp_obj, NULL
},
_directory_obj = {
"directory", 1, 0,
NULL, NULL
},
_mgmt_obj = {
"mgmt", 2, 0,
&_mib_obj, &_directory_obj
},
_experimental_obj = {
"experimental", 3, 0,
NULL, &_mgmt_obj
},
_private_obj = {
"private", 4, 0,
&_enterprises_obj, &_experimental_obj
},
_security_obj = {
"security", 5, 0,
NULL, &_private_obj
},
_snmpV2_obj = {
"snmpV2", 6, 0,
&_snmpModules_obj, &_security_obj
},
_internet_obj = {
"internet", 1, 0,
&_snmpV2_obj, NULL
},
_dod_obj = {
"dod", 6, 0,
&_internet_obj, NULL
},
_org_obj = {
"org", 3, 0,
&_dod_obj, NULL
},
_iso_obj = {
"iso", 1, 0,
&_org_obj, NULL
},
*mibroot = &_iso_obj;
diff --git a/contrib/tcpdump/missing/datalinks.c b/contrib/tcpdump/missing/datalinks.c
index 17f60bec5b54..8b458363c430 100644
--- a/contrib/tcpdump/missing/datalinks.c
+++ b/contrib/tcpdump/missing/datalinks.c
@@ -1,62 +1,60 @@
/*
* Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998
* 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 the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the Computer Systems
* Engineering Group at Lawrence Berkeley Laboratory.
* 4. Neither the name of the University nor of the Laboratory may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include <netdissect-stdinc.h>
#include <pcap.h>
#include <stdlib.h>
#include <stdio.h>
#include "pcap-missing.h"
/*
* Stub versions for platforms that don't support them.
*/
int
pcap_list_datalinks(pcap_t *p, int **dlt_buffer)
{
/*
* This platform doesn't support changing the DLT for an
* interface. Return a list of DLTs containing only the
* DLT this device supports.
*/
*dlt_buffer = (int*)malloc(sizeof(**dlt_buffer));
if (*dlt_buffer == NULL)
return (-1);
**dlt_buffer = pcap_datalink(p);
return (1);
}
diff --git a/contrib/tcpdump/missing/dlnames.c b/contrib/tcpdump/missing/dlnames.c
index 03c2b38c1b7f..87cfb382865d 100644
--- a/contrib/tcpdump/missing/dlnames.c
+++ b/contrib/tcpdump/missing/dlnames.c
@@ -1,168 +1,166 @@
/*
* Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998
* 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 the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the Computer Systems
* Engineering Group at Lawrence Berkeley Laboratory.
* 4. Neither the name of the University nor of the Laboratory may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include <netdissect-stdinc.h>
#include <pcap.h>
#include <string.h>
#include "pcap-missing.h"
#include "ascii_strcasecmp.h"
struct dlt_choice {
const char *name;
const char *description;
int dlt;
};
#define DLT_CHOICE(code, description) { #code, description, code }
#define DLT_CHOICE_SENTINEL { NULL, NULL, 0 }
static struct dlt_choice dlt_choices[] = {
DLT_CHOICE(DLT_NULL, "BSD loopback"),
DLT_CHOICE(DLT_EN10MB, "Ethernet"),
DLT_CHOICE(DLT_IEEE802, "Token ring"),
DLT_CHOICE(DLT_ARCNET, "ARCNET"),
DLT_CHOICE(DLT_SLIP, "SLIP"),
DLT_CHOICE(DLT_PPP, "PPP"),
DLT_CHOICE(DLT_FDDI, "FDDI"),
DLT_CHOICE(DLT_ATM_RFC1483, "RFC 1483 IP-over-ATM"),
DLT_CHOICE(DLT_RAW, "Raw IP"),
#ifdef DLT_SLIP_BSDOS
DLT_CHOICE(DLT_SLIP_BSDOS, "BSD/OS SLIP"),
#endif
#ifdef DLT_PPP_BSDOS
DLT_CHOICE(DLT_PPP_BSDOS, "BSD/OS PPP"),
#endif
#ifdef DLT_ATM_CLIP
DLT_CHOICE(DLT_ATM_CLIP, "Linux Classical IP-over-ATM"),
#endif
#ifdef DLT_PPP_SERIAL
DLT_CHOICE(DLT_PPP_SERIAL, "PPP over serial"),
#endif
#ifdef DLT_PPP_ETHER
DLT_CHOICE(DLT_PPP_ETHER, "PPPoE"),
#endif
#ifdef DLT_C_HDLC
DLT_CHOICE(DLT_C_HDLC, "Cisco HDLC"),
#endif
#ifdef DLT_IEEE802_11
DLT_CHOICE(DLT_IEEE802_11, "802.11"),
#endif
#ifdef DLT_FRELAY
DLT_CHOICE(DLT_FRELAY, "Frame Relay"),
#endif
#ifdef DLT_LOOP
DLT_CHOICE(DLT_LOOP, "OpenBSD loopback"),
#endif
#ifdef DLT_ENC
DLT_CHOICE(DLT_ENC, "OpenBSD encapsulated IP"),
#endif
#ifdef DLT_LINUX_SLL
DLT_CHOICE(DLT_LINUX_SLL, "Linux cooked"),
#endif
#ifdef DLT_LTALK
DLT_CHOICE(DLT_LTALK, "Localtalk"),
#endif
#ifdef DLT_PFLOG
DLT_CHOICE(DLT_PFLOG, "OpenBSD pflog file"),
#endif
#ifdef DLT_PRISM_HEADER
DLT_CHOICE(DLT_PRISM_HEADER, "802.11 plus Prism header"),
#endif
#ifdef DLT_IP_OVER_FC
DLT_CHOICE(DLT_IP_OVER_FC, "RFC 2625 IP-over-Fibre Channel"),
#endif
#ifdef DLT_SUNATM
DLT_CHOICE(DLT_SUNATM, "Sun raw ATM"),
#endif
#ifdef DLT_IEEE802_11_RADIO
DLT_CHOICE(DLT_IEEE802_11_RADIO, "802.11 plus radio information header"),
#endif
#ifdef DLT_ARCNET_LINUX
DLT_CHOICE(DLT_ARCNET_LINUX, "Linux ARCNET"),
#endif
#ifdef DLT_LINUX_IRDA
DLT_CHOICE(DLT_LINUX_IRDA, "Linux IrDA"),
#endif
#ifdef DLT_CIP
DLT_CHOICE(DLT_CIP, "Linux Classical IP-over-ATM"),
#endif
#ifdef DLT_HDLC
DLT_CHOICE(DLT_HDLC, "Cisco HDLC"),
#endif
DLT_CHOICE_SENTINEL
};
#ifndef HAVE_PCAP_DATALINK_NAME_TO_VAL
int
pcap_datalink_name_to_val(const char *name)
{
int i;
for (i = 0; dlt_choices[i].name != NULL; i++) {
if (ascii_strcasecmp(dlt_choices[i].name + sizeof("DLT_") - 1,
name) == 0)
return (dlt_choices[i].dlt);
}
return (-1);
}
const char *
pcap_datalink_val_to_name(int dlt)
{
int i;
for (i = 0; dlt_choices[i].name != NULL; i++) {
if (dlt_choices[i].dlt == dlt)
return (dlt_choices[i].name + sizeof("DLT_") - 1);
}
return (NULL);
}
#endif
const char *
pcap_datalink_val_to_description(int dlt)
{
int i;
for (i = 0; dlt_choices[i].name != NULL; i++) {
if (dlt_choices[i].dlt == dlt)
return (dlt_choices[i].description);
}
return (NULL);
}
diff --git a/contrib/tcpdump/missing/getopt_long.c b/contrib/tcpdump/missing/getopt_long.c
index ece000623534..e9b1ef5770a1 100644
--- a/contrib/tcpdump/missing/getopt_long.c
+++ b/contrib/tcpdump/missing/getopt_long.c
@@ -1,636 +1,635 @@
/* $OpenBSD: getopt_long.c,v 1.22 2006/10/04 21:29:04 jmc Exp $ */
/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */
/*
* Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Sponsored in part by the Defense Advanced Research Projects
* Agency (DARPA) and Air Force Research Laboratory, Air Force
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
*/
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Dieter Baron and Thomas Klausner.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <errno.h>
#include "getopt_long.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include "diag-control.h"
#define GNU_COMPATIBLE /* Be more compatible, configure's use us! */
#define PRINT_ERROR ((opterr) && (*options != ':'))
#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */
#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */
#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */
/* return values */
#define BADCH (int)'?'
#define BADARG ((*options == ':') ? (int)':' : (int)'?')
#define INORDER (int)1
#define EMSG ""
#ifdef GNU_COMPATIBLE
#define NO_PREFIX (-1)
#define D_PREFIX 0
#define DD_PREFIX 1
#define W_PREFIX 2
#endif
char *optarg;
int optind, opterr = 1, optopt;
static int getopt_internal(int, char * const *, const char *,
const struct option *, int *, int);
static int parse_long_options(char * const *, const char *,
const struct option *, int *, int, int);
static int gcd(int, int);
static void permute_args(int, int, int, char * const *);
static const char *place = EMSG; /* option letter processing */
static int nonopt_start = -1; /* first non option argument (for permute) */
static int nonopt_end = -1; /* first option after non options (for permute) */
/* Error messages */
static const char recargchar[] = "option requires an argument -- %c";
static const char illoptchar[] = "illegal option -- %c"; /* From P1003.2 */
#ifdef GNU_COMPATIBLE
static int dash_prefix = NO_PREFIX;
static const char gnuoptchar[] = "invalid option -- %c";
static const char recargstring[] = "option `%s%s' requires an argument";
static const char ambig[] = "option `%s%.*s' is ambiguous";
static const char noarg[] = "option `%s%.*s' doesn't allow an argument";
static const char illoptstring[] = "unrecognized option `%s%s'";
#else
static const char recargstring[] = "option requires an argument -- %s";
static const char ambig[] = "ambiguous option -- %.*s";
static const char noarg[] = "option doesn't take an argument -- %.*s";
static const char illoptstring[] = "unknown option -- %s";
#endif
/*
* Compute the greatest common divisor of a and b.
*/
static int
gcd(int a, int b)
{
int c;
c = a % b;
while (c != 0) {
a = b;
b = c;
c = a % b;
}
return (b);
}
/*
* Exchange the block from nonopt_start to nonopt_end with the block
* from nonopt_end to opt_end (keeping the same order of arguments
* in each block).
*/
static void
permute_args(int panonopt_start, int panonopt_end, int opt_end,
char * const *nargv)
{
int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
char *swap;
/*
* compute lengths of blocks and number and size of cycles
*/
nnonopts = panonopt_end - panonopt_start;
nopts = opt_end - panonopt_end;
ncycle = gcd(nnonopts, nopts);
cyclelen = (opt_end - panonopt_start) / ncycle;
for (i = 0; i < ncycle; i++) {
cstart = panonopt_end+i;
pos = cstart;
for (j = 0; j < cyclelen; j++) {
if (pos >= panonopt_end)
pos -= nnonopts;
else
pos += nopts;
/*
* This is annoying - I guess the
* "char * const argv[]" in the declaration
* of getopt() - and thus getopt_long() -
* means that it makes a promise not to
* shuffle the arguments, but here we are,
* shuffling the arguments.
*
* (No, it's not a promise that it won't
* modify any of the argument strings.
* It's a promise that it won't modify
* the array of pointers to the argument
* strings.)
*
* So squelch the cast warnings.
*/
swap = nargv[pos];
DIAG_OFF_CAST_QUAL
/* LINTED const cast */
((char **) nargv)[pos] = nargv[cstart];
/* LINTED const cast */
((char **)nargv)[cstart] = swap;
DIAG_ON_CAST_QUAL
}
}
}
static void
warnx(const char *fmt, ...)
{
extern char *program_name;
va_list ap;
va_start(ap, fmt);
fprintf(stderr, "%s: ", program_name);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap);
}
/*
* parse_long_options --
* Parse long options in argc/argv argument vector.
* Returns -1 if short_too is set and the option does not match long_options.
*/
static int
parse_long_options(char * const *nargv, const char *options,
const struct option *long_options, int *idx, int short_too, int flags)
{
const char *current_argv, *has_equal;
#ifdef GNU_COMPATIBLE
const char *current_dash;
#endif
size_t current_argv_len;
int i, match, exact_match, second_partial_match;
current_argv = place;
#ifdef GNU_COMPATIBLE
switch (dash_prefix) {
case D_PREFIX:
current_dash = "-";
break;
case DD_PREFIX:
current_dash = "--";
break;
case W_PREFIX:
current_dash = "-W ";
break;
default:
current_dash = "";
break;
}
#endif
match = -1;
exact_match = 0;
second_partial_match = 0;
optind++;
if ((has_equal = strchr(current_argv, '=')) != NULL) {
/* argument found (--option=arg) */
current_argv_len = has_equal - current_argv;
has_equal++;
} else
current_argv_len = strlen(current_argv);
for (i = 0; long_options[i].name; i++) {
/* find matching long option */
if (strncmp(current_argv, long_options[i].name,
current_argv_len))
continue;
if (strlen(long_options[i].name) == current_argv_len) {
/* exact match */
match = i;
exact_match = 1;
break;
}
/*
* If this is a known short option, don't allow
* a partial match of a single character.
*/
if (short_too && current_argv_len == 1)
continue;
if (match == -1) /* first partial match */
match = i;
else if ((flags & FLAG_LONGONLY) ||
long_options[i].has_arg !=
long_options[match].has_arg ||
long_options[i].flag != long_options[match].flag ||
long_options[i].val != long_options[match].val)
second_partial_match = 1;
}
if (!exact_match && second_partial_match) {
/* ambiguous abbreviation */
if (PRINT_ERROR)
warnx(ambig,
#ifdef GNU_COMPATIBLE
current_dash,
#endif
(int)current_argv_len,
current_argv);
optopt = 0;
return (BADCH);
}
if (match != -1) { /* option found */
if (long_options[match].has_arg == no_argument
&& has_equal) {
if (PRINT_ERROR)
warnx(noarg,
#ifdef GNU_COMPATIBLE
current_dash,
#endif
(int)current_argv_len,
current_argv);
/*
* XXX: GNU sets optopt to val regardless of flag
*/
if (long_options[match].flag == NULL)
optopt = long_options[match].val;
else
optopt = 0;
#ifdef GNU_COMPATIBLE
return (BADCH);
#else
return (BADARG);
#endif
}
if (long_options[match].has_arg == required_argument ||
long_options[match].has_arg == optional_argument) {
DIAG_OFF_CAST_QUAL
if (has_equal)
optarg = (char *)has_equal;
else if (long_options[match].has_arg ==
required_argument) {
/*
* optional argument doesn't use next nargv
*/
optarg = nargv[optind++];
}
DIAG_ON_CAST_QUAL
}
if ((long_options[match].has_arg == required_argument)
&& (optarg == NULL)) {
/*
* Missing argument; leading ':' indicates no error
* should be generated.
*/
if (PRINT_ERROR)
warnx(recargstring,
#ifdef GNU_COMPATIBLE
current_dash,
#endif
current_argv);
/*
* XXX: GNU sets optopt to val regardless of flag
*/
if (long_options[match].flag == NULL)
optopt = long_options[match].val;
else
optopt = 0;
--optind;
return (BADARG);
}
} else { /* unknown option */
if (short_too) {
--optind;
return (-1);
}
if (PRINT_ERROR)
warnx(illoptstring,
#ifdef GNU_COMPATIBLE
current_dash,
#endif
current_argv);
optopt = 0;
return (BADCH);
}
if (idx)
*idx = match;
if (long_options[match].flag) {
*long_options[match].flag = long_options[match].val;
return (0);
} else
return (long_options[match].val);
}
/*
* getopt_internal --
* Parse argc/argv argument vector. Called by user level routines.
*/
static int
getopt_internal(int nargc, char * const *nargv, const char *options,
const struct option *long_options, int *idx, int flags)
{
char *oli; /* option letter list index */
int optchar, short_too;
int posixly_correct; /* no static, can be changed on the fly */
if (options == NULL)
return (-1);
/*
* Disable GNU extensions if POSIXLY_CORRECT is set or options
* string begins with a '+'.
*/
posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
#ifdef GNU_COMPATIBLE
if (*options == '-')
flags |= FLAG_ALLARGS;
else if (posixly_correct || *options == '+')
flags &= ~FLAG_PERMUTE;
#else
if (posixly_correct || *options == '+')
flags &= ~FLAG_PERMUTE;
else if (*options == '-')
flags |= FLAG_ALLARGS;
#endif
if (*options == '+' || *options == '-')
options++;
/*
* XXX Some GNU programs (like cvs) set optind to 0 instead of
* XXX using optreset. Work around this braindamage.
*/
if (optind == 0)
optind = 1;
optarg = NULL;
start:
if (!*place) { /* update scanning pointer */
if (optind >= nargc) { /* end of argument vector */
place = EMSG;
if (nonopt_end != -1) {
/* do permutation, if we have to */
permute_args(nonopt_start, nonopt_end,
optind, nargv);
optind -= nonopt_end - nonopt_start;
- }
- else if (nonopt_start != -1) {
+ } else if (nonopt_start != -1) {
/*
* If we skipped non-options, set optind
* to the first of them.
*/
optind = nonopt_start;
}
nonopt_start = nonopt_end = -1;
return (-1);
}
if (*(place = nargv[optind]) != '-' ||
#ifdef GNU_COMPATIBLE
place[1] == '\0') {
#else
(place[1] == '\0' && strchr(options, '-') == NULL)) {
#endif
place = EMSG; /* found non-option */
if (flags & FLAG_ALLARGS) {
/*
* GNU extension:
* return non-option as argument to option 1
*/
optarg = nargv[optind++];
return (INORDER);
}
if (!(flags & FLAG_PERMUTE)) {
/*
* If no permutation wanted, stop parsing
* at first non-option.
*/
return (-1);
}
/* do permutation */
if (nonopt_start == -1)
nonopt_start = optind;
else if (nonopt_end != -1) {
permute_args(nonopt_start, nonopt_end,
optind, nargv);
nonopt_start = optind -
(nonopt_end - nonopt_start);
nonopt_end = -1;
}
optind++;
/* process next argument */
goto start;
}
if (nonopt_start != -1 && nonopt_end == -1)
nonopt_end = optind;
/*
* If we have "-" do nothing, if "--" we are done.
*/
if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
optind++;
place = EMSG;
/*
* We found an option (--), so if we skipped
* non-options, we have to permute.
*/
if (nonopt_end != -1) {
permute_args(nonopt_start, nonopt_end,
optind, nargv);
optind -= nonopt_end - nonopt_start;
}
nonopt_start = nonopt_end = -1;
return (-1);
}
}
/*
* Check long options if:
* 1) we were passed some
* 2) the arg is not just "-"
* 3) either the arg starts with -- we are getopt_long_only()
*/
if (long_options != NULL && place != nargv[optind] &&
(*place == '-' || (flags & FLAG_LONGONLY))) {
short_too = 0;
#ifdef GNU_COMPATIBLE
dash_prefix = D_PREFIX;
#endif
if (*place == '-') {
place++; /* --foo long option */
#ifdef GNU_COMPATIBLE
dash_prefix = DD_PREFIX;
#endif
} else if (*place != ':' && strchr(options, *place) != NULL)
short_too = 1; /* could be short option too */
optchar = parse_long_options(nargv, options, long_options,
idx, short_too, flags);
if (optchar != -1) {
place = EMSG;
return (optchar);
}
}
if ((optchar = (int)*place++) == (int)':' ||
(optchar == (int)'-' && *place != '\0') ||
(oli = strchr(options, optchar)) == NULL) {
/*
* If the user specified "-" and '-' isn't listed in
* options, return -1 (non-option) as per POSIX.
* Otherwise, it is an unknown option character (or ':').
*/
if (optchar == (int)'-' && *place == '\0')
return (-1);
if (!*place)
++optind;
#ifdef GNU_COMPATIBLE
if (PRINT_ERROR)
warnx(posixly_correct ? illoptchar : gnuoptchar,
optchar);
#else
if (PRINT_ERROR)
warnx(illoptchar, optchar);
#endif
optopt = optchar;
return (BADCH);
}
if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
/* -W long-option */
if (*place) /* no space */
/* NOTHING */;
else if (++optind >= nargc) { /* no arg */
place = EMSG;
if (PRINT_ERROR)
warnx(recargchar, optchar);
optopt = optchar;
return (BADARG);
} else /* white space */
place = nargv[optind];
#ifdef GNU_COMPATIBLE
dash_prefix = W_PREFIX;
#endif
optchar = parse_long_options(nargv, options, long_options,
idx, 0, flags);
place = EMSG;
return (optchar);
}
if (*++oli != ':') { /* doesn't take argument */
if (!*place)
++optind;
} else { /* takes (optional) argument */
optarg = NULL;
if (*place) { /* no white space */
DIAG_OFF_CAST_QUAL
optarg = (char *)place;
DIAG_ON_CAST_QUAL
} else if (oli[1] != ':') { /* arg not optional */
if (++optind >= nargc) { /* no arg */
place = EMSG;
if (PRINT_ERROR)
warnx(recargchar, optchar);
optopt = optchar;
return (BADARG);
} else
optarg = nargv[optind];
}
place = EMSG;
++optind;
}
/* dump back option letter */
return (optchar);
}
#ifdef REPLACE_GETOPT
/*
* getopt --
* Parse argc/argv argument vector.
*
* [eventually this will replace the BSD getopt]
*/
int
getopt(int nargc, char * const *nargv, const char *options)
{
/*
* We don't pass FLAG_PERMUTE to getopt_internal() since
* the BSD getopt(3) (unlike GNU) has never done this.
*
* Furthermore, since many privileged programs call getopt()
* before dropping privileges it makes sense to keep things
* as simple (and bug-free) as possible.
*/
return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
}
#endif /* REPLACE_GETOPT */
/*
* getopt_long --
* Parse argc/argv argument vector.
*/
int
getopt_long(int nargc, char * const *nargv, const char *options,
const struct option *long_options, int *idx)
{
return (getopt_internal(nargc, nargv, options, long_options, idx,
FLAG_PERMUTE));
}
/*
* getopt_long_only --
* Parse argc/argv argument vector.
*/
int
getopt_long_only(int nargc, char * const *nargv, const char *options,
const struct option *long_options, int *idx)
{
return (getopt_internal(nargc, nargv, options, long_options, idx,
FLAG_PERMUTE|FLAG_LONGONLY));
}
diff --git a/contrib/tcpdump/missing/getservent.c b/contrib/tcpdump/missing/getservent.c
index 39cee068a69b..4da24800fd7d 100644
--- a/contrib/tcpdump/missing/getservent.c
+++ b/contrib/tcpdump/missing/getservent.c
@@ -1,143 +1,141 @@
/*
* Copyright (c) 1983, 1993 The Regents of the University of California.
* Copyright (c) 1993 Digital Equipment Corporation.
* Copyright (c) 2012 G. Vanem <gvanem@yahoo.no>.
* Copyright (c) 2017 Ali Abdulkadir <autostart.ini@gmail.com>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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 BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include <netdissect-stdinc.h>
#include <getservent.h>
static FILE *servf = NULL;
static char line[BUFSIZ+1];
static struct servent serv;
static char *serv_aliases[MAXALIASES];
int _serv_stayopen;
const char *etc_path(const char *file);
/*
* Check if <file> exists in the current directory and, if so, return it.
* Else return either "%SYSTEMROOT%\System32\drivers\etc\<file>"
* or $PREFIX/etc/<file>.
* "<file>" is aka __PATH_SERVICES (aka "services" on Windows and
* "/etc/services" on other platforms that would need this).
*/
const char *etc_path(const char *file)
{
const char *env = getenv(__PATH_SYSROOT);
static char path[_MAX_PATH];
/* see if "<file>" exists locally or whether __PATH_SYSROOT is valid */
if (fopen(file, "r") || !env)
return (file);
else
#ifdef _WIN32
snprintf(path, sizeof(path), "%s%s%s", env, __PATH_ETC_INET, file);
#else
snprintf(path, sizeof(path), "%s%s", env, file);
#endif
return (path);
}
void
setservent(int f)
{
if (servf == NULL)
servf = fopen(etc_path(__PATH_SERVICES), "r");
else
rewind(servf);
_serv_stayopen |= f;
}
void
endservent(void)
{
if (servf) {
fclose(servf);
servf = NULL;
}
_serv_stayopen = 0;
}
struct servent *
getservent(void)
{
char *p;
char *cp, **q;
if (servf == NULL && (servf = fopen(etc_path(__PATH_SERVICES), "r")) == NULL)
return (NULL);
again:
if ((p = fgets(line, BUFSIZ, servf)) == NULL)
return (NULL);
if (*p == '#')
goto again;
cp = strpbrk(p, "#\n");
if (cp == NULL)
goto again;
*cp = '\0';
serv.s_name = p;
p = strpbrk(p, " \t");
if (p == NULL)
goto again;
*p++ = '\0';
while (*p == ' ' || *p == '\t')
p++;
cp = strpbrk(p, ",/");
if (cp == NULL)
goto again;
*cp++ = '\0';
serv.s_port = htons((u_short)atoi(p));
serv.s_proto = cp;
q = serv.s_aliases = serv_aliases;
cp = strpbrk(cp, " \t");
if (cp != NULL)
*cp++ = '\0';
while (cp && *cp) {
if (*cp == ' ' || *cp == '\t') {
cp++;
continue;
}
if (q < &serv_aliases[MAXALIASES - 1])
*q++ = cp;
cp = strpbrk(cp, " \t");
if (cp != NULL)
*cp++ = '\0';
}
*q = NULL;
return (&serv);
}
diff --git a/contrib/tcpdump/missing/snprintf.c b/contrib/tcpdump/missing/snprintf.c
index dfff6ee08861..52eb9a61ca66 100644
--- a/contrib/tcpdump/missing/snprintf.c
+++ b/contrib/tcpdump/missing/snprintf.c
@@ -1,510 +1,508 @@
/*
* Copyright (c) 1995-1999 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute 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 BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include "netdissect.h"
enum format_flags {
minus_flag = 1,
plus_flag = 2,
space_flag = 4,
alternate_flag = 8,
zero_flag = 16
};
/*
* Common state
*/
struct state {
unsigned char *str;
unsigned char *s;
unsigned char *theend;
size_t sz;
size_t max_sz;
int (*append_char)(struct state *, unsigned char);
int (*reserve)(struct state *, size_t);
/* XXX - methods */
};
#if 0
static int
as_reserve (struct state *state, size_t n)
{
if (state->s + n > state->theend) {
int off = state->s - state->str;
unsigned char *tmp;
if (state->max_sz && state->sz >= state->max_sz)
return 1;
state->sz = max(state->sz * 2, state->sz + n);
if (state->max_sz)
state->sz = min(state->sz, state->max_sz);
tmp = realloc (state->str, state->sz);
if (tmp == NULL)
return 1;
state->str = tmp;
state->s = state->str + off;
state->theend = state->str + state->sz - 1;
}
return 0;
}
static int
as_append_char (struct state *state, unsigned char c)
{
if(as_reserve (state, 1))
return 1;
else {
*state->s++ = c;
return 0;
}
}
#endif
static int
append_number(struct state *state,
unsigned long num, unsigned base, char *rep,
int width, int prec, int flags, int minusp)
{
int len = 0;
int i;
/* given precision, ignore zero flag */
if(prec != -1)
flags &= ~zero_flag;
else
prec = 1;
/* zero value with zero precision -> "" */
if(prec == 0 && num == 0)
return 0;
do{
if((*state->append_char)(state, rep[num % base]))
return 1;
len++;
num /= base;
}while(num);
prec -= len;
/* pad with prec zeros */
while(prec-- > 0){
if((*state->append_char)(state, '0'))
return 1;
len++;
}
/* add length of alternate prefix (added later) to len */
if(flags & alternate_flag && (base == 16 || base == 8))
len += base / 8;
/* pad with zeros */
if(flags & zero_flag){
width -= len;
if(minusp || (flags & space_flag) || (flags & plus_flag))
width--;
while(width-- > 0){
if((*state->append_char)(state, '0'))
return 1;
len++;
}
}
/* add alternate prefix */
if(flags & alternate_flag && (base == 16 || base == 8)){
if(base == 16)
if((*state->append_char)(state, rep[10] + 23)) /* XXX */
return 1;
if((*state->append_char)(state, '0'))
return 1;
}
/* add sign */
if(minusp){
if((*state->append_char)(state, '-'))
return 1;
len++;
} else if(flags & plus_flag) {
if((*state->append_char)(state, '+'))
return 1;
len++;
} else if(flags & space_flag) {
if((*state->append_char)(state, ' '))
return 1;
len++;
}
if(flags & minus_flag)
/* swap before padding with spaces */
for(i = 0; i < len / 2; i++){
char c = state->s[-i-1];
state->s[-i-1] = state->s[-len+i];
state->s[-len+i] = c;
}
width -= len;
while(width-- > 0){
if((*state->append_char)(state, ' '))
return 1;
len++;
}
if(!(flags & minus_flag))
/* swap after padding with spaces */
for(i = 0; i < len / 2; i++){
char c = state->s[-i-1];
state->s[-i-1] = state->s[-len+i];
state->s[-len+i] = c;
}
return 0;
}
static int
append_string (struct state *state,
unsigned char *arg,
int width,
int prec,
int flags)
{
if(prec != -1)
width -= prec;
else
width -= strlen((char *)arg);
if(!(flags & minus_flag))
while(width-- > 0)
if((*state->append_char) (state, ' '))
return 1;
if (prec != -1) {
while (*arg && prec--)
if ((*state->append_char) (state, *arg++))
return 1;
} else {
while (*arg)
if ((*state->append_char) (state, *arg++))
return 1;
}
if(flags & minus_flag)
while(width-- > 0)
if((*state->append_char) (state, ' '))
return 1;
return 0;
}
static int
append_char(struct state *state,
unsigned char arg,
int width,
int flags)
{
while(!(flags & minus_flag) && --width > 0)
if((*state->append_char) (state, ' '))
return 1;
if((*state->append_char) (state, arg))
return 1;
while((flags & minus_flag) && --width > 0)
if((*state->append_char) (state, ' '))
return 1;
return 0;
}
/*
* This can't be made into a function...
*/
#define PARSE_INT_FORMAT(res, arg, unsig) \
if (long_flag) \
res = (unsig long)va_arg(arg, unsig long); \
else if (short_flag) \
res = (unsig short)va_arg(arg, unsig int); \
else \
res = (unsig int)va_arg(arg, unsig int)
/*
* zyxprintf - return 0 or -1
*/
static int
xyzprintf (struct state *state, const char *char_format, va_list ap)
{
const unsigned char *format = (const unsigned char *)char_format;
unsigned char c;
while((c = *format++)) {
if (c == '%') {
int flags = 0;
int width = 0;
int prec = -1;
int long_flag = 0;
int short_flag = 0;
/* flags */
while((c = *format++)){
if(c == '-')
flags |= minus_flag;
else if(c == '+')
flags |= plus_flag;
else if(c == ' ')
flags |= space_flag;
else if(c == '#')
flags |= alternate_flag;
else if(c == '0')
flags |= zero_flag;
else
break;
}
if((flags & space_flag) && (flags & plus_flag))
flags ^= space_flag;
if((flags & minus_flag) && (flags & zero_flag))
flags ^= zero_flag;
/* width */
if (isdigit(c))
do {
width = width * 10 + c - '0';
c = *format++;
} while(isdigit(c));
else if(c == '*') {
width = va_arg(ap, int);
c = *format++;
}
/* precision */
if (c == '.') {
prec = 0;
c = *format++;
if (isdigit(c))
do {
prec = prec * 10 + c - '0';
c = *format++;
} while(isdigit(c));
else if (c == '*') {
prec = va_arg(ap, int);
c = *format++;
}
}
/* size */
if (c == 'h') {
short_flag = 1;
c = *format++;
} else if (c == 'l') {
long_flag = 1;
c = *format++;
}
switch (c) {
case 'c' :
if(append_char(state, va_arg(ap, int), width, flags))
return -1;
break;
case 's' :
if (append_string(state,
va_arg(ap, unsigned char*),
width,
prec,
flags))
return -1;
break;
case 'd' :
case 'i' : {
long arg;
unsigned long num;
int minusp = 0;
PARSE_INT_FORMAT(arg, ap, signed);
if (arg < 0) {
minusp = 1;
num = -arg;
} else
num = arg;
if (append_number (state, num, 10, "0123456789",
width, prec, flags, minusp))
return -1;
break;
}
case 'u' : {
unsigned long arg;
PARSE_INT_FORMAT(arg, ap, unsigned);
if (append_number (state, arg, 10, "0123456789",
width, prec, flags, 0))
return -1;
break;
}
case 'o' : {
unsigned long arg;
PARSE_INT_FORMAT(arg, ap, unsigned);
if (append_number (state, arg, 010, "01234567",
width, prec, flags, 0))
return -1;
break;
}
case 'x' : {
unsigned long arg;
PARSE_INT_FORMAT(arg, ap, unsigned);
if (append_number (state, arg, 0x10, "0123456789abcdef",
width, prec, flags, 0))
return -1;
break;
}
case 'X' :{
unsigned long arg;
PARSE_INT_FORMAT(arg, ap, unsigned);
if (append_number (state, arg, 0x10, "0123456789ABCDEF",
width, prec, flags, 0))
return -1;
break;
}
case 'p' : {
unsigned long arg = (unsigned long)va_arg(ap, void*);
if (append_number (state, arg, 0x10, "0123456789ABCDEF",
width, prec, flags, 0))
return -1;
break;
}
case 'n' : {
int *arg = va_arg(ap, int *);
*arg = state->s - state->str;
break;
}
case '\0' :
--format;
/* FALLTHROUGH */
case '%' :
if ((*state->append_char)(state, c))
return -1;
break;
default :
if ( (*state->append_char)(state, '%')
|| (*state->append_char)(state, c))
return -1;
break;
}
} else
if ((*state->append_char) (state, c))
return -1;
}
return 0;
}
#if 0
#ifndef HAVE_ASPRINTF
int
asprintf (char **ret, const char *format, ...)
{
va_list args;
int val;
va_start(args, format);
val = vasprintf (ret, format, args);
#ifdef PARANOIA
{
int ret2;
char *tmp;
tmp = malloc (val + 1);
if (tmp == NULL)
abort ();
ret2 = vsprintf (tmp, format, args);
if (val != ret2 || strcmp(*ret, tmp))
abort ();
free (tmp);
}
#endif
va_end(args);
return val;
}
#endif
#ifndef HAVE_VASNPRINTF
int
nd_vasnprintf (char **ret, size_t max_sz, const char *format, va_list args)
{
int st;
size_t len;
struct state state;
state.max_sz = max_sz;
state.sz = 1;
state.str = malloc(state.sz);
if (state.str == NULL) {
*ret = NULL;
return -1;
}
state.s = state.str;
state.theend = state.s + state.sz - 1;
state.append_char = as_append_char;
state.reserve = as_reserve;
st = xyzprintf (&state, format, args);
if (st) {
free (state.str);
*ret = NULL;
return -1;
} else {
char *tmp;
*state.s = '\0';
len = state.s - state.str;
tmp = realloc (state.str, len+1);
if (tmp == NULL) {
free (state.str);
*ret = NULL;
return -1;
}
*ret = tmp;
return len;
}
}
#endif
#endif
diff --git a/contrib/tcpdump/missing/strlcat.c b/contrib/tcpdump/missing/strlcat.c
index fab7d04f3e8e..9b64465088c0 100644
--- a/contrib/tcpdump/missing/strlcat.c
+++ b/contrib/tcpdump/missing/strlcat.c
@@ -1,73 +1,71 @@
/* $NetBSD: strlcat.c,v 1.5 1999/09/20 04:39:47 lukem Exp $ */
/* from OpenBSD: strlcat.c,v 1.2 1999/06/17 16:28:58 millert Exp */
/*
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include <netdissect-stdinc.h>
#include <string.h>
#include "netdissect.h"
/*
* Appends src to string dst of size siz (unlike strncat, siz is the
* full size of dst, not space left). At most siz-1 characters
* will be copied. Always NUL terminates (unless siz == 0).
* Returns strlen(src); if retval >= siz, truncation occurred.
*/
size_t
strlcat(char *dst, const char *src, size_t siz)
{
char *d = dst;
const char *s = src;
size_t n = siz;
size_t dlen;
/* Find the end of dst and adjust bytes left but don't go past end */
while (*d != '\0' && n-- != 0)
d++;
dlen = d - dst;
n = siz - dlen;
if (n == 0)
return(dlen + strlen(s));
while (*s != '\0') {
if (n != 1) {
*d++ = *s;
n--;
}
s++;
}
*d = '\0';
return(dlen + (s - src)); /* count does not include NUL */
}
diff --git a/contrib/tcpdump/missing/strlcpy.c b/contrib/tcpdump/missing/strlcpy.c
index 9a0b6e6a54b7..00792bc1b9d5 100644
--- a/contrib/tcpdump/missing/strlcpy.c
+++ b/contrib/tcpdump/missing/strlcpy.c
@@ -1,70 +1,68 @@
/* $NetBSD: strlcpy.c,v 1.5 1999/09/20 04:39:47 lukem Exp $ */
/* from OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp */
/*
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include <netdissect-stdinc.h>
#include <string.h>
#include "netdissect.h"
/*
* Copy src to string dst of size siz. At most siz-1 characters
* will be copied. Always NUL terminates (unless siz == 0).
* Returns strlen(src); if retval >= siz, truncation occurred.
*/
size_t
strlcpy(char *dst, const char *src, size_t siz)
{
char *d = dst;
const char *s = src;
size_t n = siz;
/* Copy as many bytes as will fit */
if (n != 0 && --n != 0) {
do {
if ((*d++ = *s++) == 0)
break;
} while (--n != 0);
}
/* Not enough room in dst, add NUL and traverse rest of src */
if (n == 0) {
if (siz != 0)
*d = '\0'; /* NUL-terminate dst */
while (*s++)
;
}
return(s - src - 1); /* count does not include NUL */
}
diff --git a/contrib/tcpdump/missing/strsep.c b/contrib/tcpdump/missing/strsep.c
index 05f10bccff92..a07660c4bab2 100644
--- a/contrib/tcpdump/missing/strsep.c
+++ b/contrib/tcpdump/missing/strsep.c
@@ -1,80 +1,78 @@
/*-
* Copyright (c) 1990, 1993
* 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 the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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 BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include <netdissect-stdinc.h>
#include <string.h>
#include "netdissect.h"
/*
* Get next token from string *stringp, where tokens are possibly-empty
* strings separated by characters from delim.
*
* Writes NULs into the string at *stringp to end tokens.
* delim need not remain constant from call to call.
* On return, *stringp points past the last NUL written (if there might
* be further tokens), or is NULL (if there are definitely no more tokens).
*
* If *stringp is NULL, strsep returns NULL.
*/
char *
strsep(char **stringp, const char *delim)
{
char *s;
const char *spanp;
int c, sc;
char *tok;
if ((s = *stringp) == NULL)
return (NULL);
for (tok = s;;) {
c = *s++;
spanp = delim;
do {
if ((sc = *spanp++) == c) {
if (c == 0)
s = NULL;
else
s[-1] = 0;
*stringp = s;
return (tok);
}
} while (sc != 0);
}
/* NOTREACHED */
}
diff --git a/contrib/tcpdump/mkdep b/contrib/tcpdump/mkdep
index caf547e2f643..dc0a11ea9273 100755
--- a/contrib/tcpdump/mkdep
+++ b/contrib/tcpdump/mkdep
@@ -1,116 +1,118 @@
-#!/bin/sh -
+#!/bin/sh -e
#
# Copyright (c) 1994, 1996
# The Regents of the University of California. All rights reserved.
#
# Redistribution and use in source and binary forms are permitted
# provided that this notice is preserved and that due credit is given
# to the University of California at Berkeley. The name of the University
# may not be used to endorse or promote products derived from this
# software without specific prior written permission. This software
# is provided ``as is'' without express or implied warranty.
#
# @(#)mkdep.sh 5.11 (Berkeley) 5/5/88
#
MAKE=Makefile # default makefile name is "Makefile"
CC=cc # default C compiler is "cc"
DEPENDENCY_CFLAG=-M # default dependency-generation flag is -M
SOURCE_DIRECTORY=. # default source directory is the current directory
# No command-line flags seen yet.
flags=""
while :
do case "$1" in
# -c allows you to specify the C compiler
-c)
CC=$2
shift; shift ;;
# -f allows you to select a makefile name
-f)
MAKE=$2
shift; shift ;;
# -m allows you to specify the dependency-generation flag
-m)
DEPENDENCY_CFLAG=$2
shift; shift ;;
# the -p flag produces "program: program.c" style dependencies
# so .o's don't get produced
-p)
SED='s;\.o;;'
shift ;;
# -s allows you to specify the source directory
-s)
SOURCE_DIRECTORY=$2
shift; shift ;;
# other command-line flag
-*)
flags="$flags $1"
shift ;;
*)
break ;;
esac
done
if [ $# = 0 ] ; then
echo 'usage: mkdep [-p] [-c cc] [-f makefile] [-m dependency-cflag] [-s source-directory] [flags] file ...'
exit 1
fi
-if [ ! -w $MAKE ]; then
+if [ ! -w "$MAKE" ]; then
echo "mkdep: no writeable file \"$MAKE\""
exit 1
fi
-TMP=/tmp/mkdep$$
+TMP=${TMPDIR:-/tmp}/mkdep$$
-trap 'rm -f $TMP ; exit 1' 1 2 3 13 15
+trap 'rm -f "$TMP" ; exit 1' HUP INT QUIT PIPE TERM
-cp $MAKE ${MAKE}.bak
+cp "$MAKE" "${MAKE}.bak"
-sed -e '/DO NOT DELETE THIS LINE/,$d' < $MAKE > $TMP
+sed -e '/DO NOT DELETE THIS LINE/,$d' < "$MAKE" > "$TMP"
-cat << _EOF_ >> $TMP
+cat << _EOF_ >> "$TMP"
# DO NOT DELETE THIS LINE -- mkdep uses it.
# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
_EOF_
# If your compiler doesn't have -M, add it. If you can't, the next two
# lines will try and replace the "cc -M". The real problem is that this
# hack can't deal with anything that requires a search path, and doesn't
# even try for anything using bracket (<>) syntax.
#
# grep -E '^#include[[:blank:]]*".*"' /dev/null $* |
# sed -e 's/:[^"]*"\([^"]*\)".*/: \1/' -e 's/\.c/.o/' |
#
# Construct a list of source files with paths relative to the source directory.
#
sources=""
-for srcfile in $*
+for srcfile in "$@"
do
sources="$sources $SOURCE_DIRECTORY/$srcfile"
done
# XXX this doesn't work with things like "-DDECLWAITSTATUS=union\ wait"
-$CC $DEPENDENCY_CFLAG $flags $sources |
+# $flags and $sources are meant to expand
+# shellcheck disable=SC2086
+"$CC" "$DEPENDENCY_CFLAG" $flags $sources |
sed "
s; \./; ;g
- $SED" >> $TMP
+ $SED" >> "$TMP"
-cat << _EOF_ >> $TMP
+cat << _EOF_ >> "$TMP"
# IF YOU PUT ANYTHING HERE IT WILL GO AWAY
_EOF_
# copy to preserve permissions
-cp $TMP $MAKE
-rm -f ${MAKE}.bak $TMP
+cp "$TMP" "$MAKE"
+rm -f "${MAKE}.bak" "$TMP"
exit 0
diff --git a/contrib/tcpdump/nameser.h b/contrib/tcpdump/nameser.h
index 2a1854fdf4f1..08b680e01abc 100644
--- a/contrib/tcpdump/nameser.h
+++ b/contrib/tcpdump/nameser.h
@@ -1,331 +1,331 @@
/*
* Copyright (c) 1983, 1989, 1993
* 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 the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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 BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)nameser.h 8.2 (Berkeley) 2/16/94
* -
* Portions Copyright (c) 1993 by Digital Equipment Corporation.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies, and that
* the name of Digital Equipment Corporation not be used in advertising or
* publicity pertaining to distribution of the document or software without
* specific, written prior permission.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
* -
* --Copyright--
*/
#ifndef _NAMESER_H_
#define _NAMESER_H_
#include <sys/types.h>
/*
* Define constants based on rfc883
*/
#define PACKETSZ 512 /* maximum packet size */
#define MAXDNAME 256 /* maximum domain name */
#define MAXCDNAME 255 /* maximum compressed domain name */
#define MAXLABEL 63 /* maximum length of domain label */
/* Number of bytes of fixed size data in query structure */
#define QFIXEDSZ 4
/* number of bytes of fixed size data in resource record */
#define RRFIXEDSZ 10
/*
* Currently defined opcodes
*/
#define QUERY 0x0 /* standard query */
#define IQUERY 0x1 /* inverse query */
#define STATUS 0x2 /* nameserver status query */
#if 0
#define xxx 0x3 /* 0x3 reserved */
#endif
/* non standard - supports ALLOW_UPDATES stuff from Mike Schwartz */
#define UPDATEA 0x9 /* add resource record */
#define UPDATED 0xa /* delete a specific resource record */
#define UPDATEDA 0xb /* delete all named resource record */
#define UPDATEM 0xc /* modify a specific resource record */
#define UPDATEMA 0xd /* modify all named resource record */
#define ZONEINIT 0xe /* initial zone transfer */
-#define ZONEREF 0xf /* incremental zone referesh */
+#define ZONEREF 0xf /* incremental zone refresh */
/*
* Undefine various #defines from various System V-flavored OSes (Solaris,
* SINIX, HP-UX) so the compiler doesn't whine that we redefine them.
*/
#ifdef T_NULL
#undef T_NULL
#endif
#ifdef T_OPT
#undef T_OPT
#endif
#ifdef T_UNSPEC
#undef T_UNSPEC
#endif
#ifdef NOERROR
#undef NOERROR
#endif
/*
* Currently defined response codes
*/
#define NOERROR 0 /* no error */
#define FORMERR 1 /* format error */
#define SERVFAIL 2 /* server failure */
-#define NXDOMAIN 3 /* non existent domain */
+#define NXDOMAIN 3 /* nonexistent domain */
#define NOTIMP 4 /* not implemented */
#define REFUSED 5 /* query refused */
/* non standard */
#define NOCHANGE 0xf /* update failed to change db */
/*
* Type values for resources and queries
*/
#define T_A 1 /* host address */
#define T_NS 2 /* authoritative server */
#define T_MD 3 /* mail destination */
#define T_MF 4 /* mail forwarder */
-#define T_CNAME 5 /* connonical name */
+#define T_CNAME 5 /* canonical name */
#define T_SOA 6 /* start of authority zone */
#define T_MB 7 /* mailbox domain name */
#define T_MG 8 /* mail group member */
#define T_MR 9 /* mail rename name */
#define T_NULL 10 /* null resource record */
#define T_WKS 11 /* well known service */
#define T_PTR 12 /* domain name pointer */
#define T_HINFO 13 /* host information */
#define T_MINFO 14 /* mailbox information */
#define T_MX 15 /* mail routing information */
#define T_TXT 16 /* text strings */
#define T_RP 17 /* responsible person */
#define T_AFSDB 18 /* AFS cell database */
#define T_X25 19 /* X_25 calling address */
#define T_ISDN 20 /* ISDN calling address */
#define T_RT 21 /* router */
#define T_NSAP 22 /* NSAP address */
#define T_NSAP_PTR 23 /* reverse lookup for NSAP */
#define T_SIG 24 /* security signature */
#define T_KEY 25 /* security key */
#define T_PX 26 /* X.400 mail mapping */
#define T_GPOS 27 /* geographical position (withdrawn) */
#define T_AAAA 28 /* IP6 Address */
#define T_LOC 29 /* Location Information */
#define T_NXT 30 /* Next Valid Name in Zone */
#define T_EID 31 /* Endpoint identifier */
#define T_NIMLOC 32 /* Nimrod locator */
#define T_SRV 33 /* Server selection */
#define T_ATMA 34 /* ATM Address */
#define T_NAPTR 35 /* Naming Authority PoinTeR */
#define T_KX 36 /* Key Exchanger */
#define T_CERT 37 /* Certificates in the DNS */
#define T_A6 38 /* IP6 address */
#define T_DNAME 39 /* non-terminal redirection */
#define T_SINK 40 /* unknown */
#define T_OPT 41 /* EDNS0 option (meta-RR) */
#define T_APL 42 /* lists of address prefixes */
#define T_DS 43 /* Delegation Signer */
#define T_SSHFP 44 /* SSH Fingerprint */
#define T_IPSECKEY 45 /* IPsec keying material */
#define T_RRSIG 46 /* new security signature */
#define T_NSEC 47 /* provable insecure information */
#define T_DNSKEY 48 /* new security key */
#define T_DHCID 49 /* DHCP IDentifier */
#define T_NSEC3 50 /* Next SECure record v3 */
#define T_NSEC3PARAM 51 /* NSEC3 PARAMeter */
#define T_TLSA 52 /* TLS Authentication */
#define T_SMIMEA 53 /* S/MIME Authentication */
/* Unassigned */
#define T_HIP 55 /* Host Identity Protocol */
#define T_NINFO 56 /* zone status information */
#define T_RKEY 57 /* Record encryption KEY */
#define T_TALINK 58 /* Trust Anchor LINK */
#define T_CDS 59 /* Child Delegation Signer */
#define T_CDNSKEY 60 /* Child DNSKEY */
#define T_OPENPGPKEY 61 /* OpenPGP KEY */
-#define T_CSYNC 62 /* Child to parent SYNCronization */
+#define T_CSYNC 62 /* Child to parent SYNChronization */
#define T_ZONEMD 63 /* ZONE data Message Digest */
#define T_SVCB 64 /* SerViCe Binding */
#define T_HTTPS 65 /* HTTPS binding */
/* non standard */
#define T_SPF 99 /* sender policy framework */
#define T_UINFO 100 /* user (finger) information */
#define T_UID 101 /* user ID */
#define T_GID 102 /* group ID */
#define T_UNSPEC 103 /* Unspecified format (binary data) */
#define T_NID 104 /* Node IDentifier */
#define T_L32 105 /* Locator 32-bit */
#define T_L64 106 /* Locator 64-bit */
#define T_LP 107 /* Locator Pointer */
#define T_EUI48 108 /* an EUI-48 address */
#define T_EUI64 109 /* an EUI-64 address */
/* Query type values which do not appear in resource records */
#define T_TKEY 249 /* Transaction Key [RFC2930] */
#define T_TSIG 250 /* Transaction Signature [RFC2845] */
#define T_IXFR 251 /* incremental transfer [RFC1995] */
#define T_AXFR 252 /* transfer zone of authority */
#define T_MAILB 253 /* transfer mailbox records */
#define T_MAILA 254 /* transfer mail agent records */
#define T_ANY 255 /* wildcard match */
#define T_URI 256 /* uri records [RFC7553] */
#define T_CAA 257 /* Certification Authority Authorization */
#define T_AVC 258 /* Application Visibility and Control */
#define T_DOA 259 /* Digital Object Architecture */
#define T_AMTRELAY 260 /* Automatic Multicast Tunneling RELAY */
#define T_TA 32768 /* DNSSEC Trust Authorities */
#define T_DLV 32769 /* DNSSEC Lookaside Validation */
/*
* Values for class field
*/
#define C_IN 1 /* the arpa internet */
#define C_CHAOS 3 /* for chaos net (MIT) */
#define C_HS 4 /* for Hesiod name server (MIT) (XXX) */
/* Query class values which do not appear in resource records */
#define C_ANY 255 /* wildcard match */
#define C_QU 0x8000 /* mDNS QU flag in queries */
#define C_CACHE_FLUSH 0x8000 /* mDNS cache flush flag in replies */
/*
* Values for EDNS option types
*/
#define E_LLQ 1 /* long lived queries protocol */
#define E_UL 2 /* dynamic dns update leases */
#define E_NSID 3 /* name server identifier */
#define E_DAU 5 /* signal DNSSEC algorithm understood */
#define E_DHU 6 /* signal DS hash understood */
#define E_N3U 7 /* signal NSEC3 hash understood */
#define E_ECS 8 /* EDNS client subnet */
#define E_EXPIRE 9 /* zone expiration */
#define E_COOKIE 10 /* DNS cookies */
#define E_KEEPALIVE 11 /* TCP keepalive */
#define E_PADDING 12 /* pad DNS messages */
#define E_CHAIN 13 /* chain DNS queries */
#define E_KEYTAG 14 /* EDNS key tag */
#define E_CLIENTTAG 16 /* EDNS client tag */
#define E_SERVERTAG 17 /* EDNS server tag */
/*
* Values for DNSSEC Algorithms
* https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml
*/
#define A_DELETE 0
#define A_RSAMD5 1
#define A_DH 2
#define A_DSA 3
#define A_RSASHA1 5
#define A_DSA_NSEC3_SHA1 6
#define A_RSASHA1_NSEC3_SHA1 7
#define A_RSASHA256 8
#define A_RSASHA512 10
#define A_ECC_GOST 12
#define A_ECDSAP256SHA256 13
#define A_ECDSAP384SHA384 14
#define A_ED25519 15
#define A_ED448 16
#define A_INDIRECT 252
#define A_PRIVATEDNS 253
#define A_PRIVATEOID 254
/*
* Values for NSEC3 algorithms
* https://www.iana.org/assignments/dnssec-nsec3-parameters/dnssec-nsec3-parameters.xhtml
*/
#define NSEC_SHA1 1
/*
* Values for delegation signer algorithms
* https://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml
*/
#define DS_SHA1 1
#define DS_SHA256 2
#define DS_GOST 3
#define DS_SHA384 4
/*
* Status return codes for T_UNSPEC conversion routines
*/
#define CONV_SUCCESS 0
#define CONV_OVERFLOW -1
#define CONV_BADFMT -2
#define CONV_BADCKSUM -3
#define CONV_BADBUFLEN -4
/*
* Structure for query header.
*/
typedef struct {
nd_uint16_t id; /* query identification number */
nd_uint16_t flags; /* QR, Opcode, AA, TC, RD, RA, RCODE */
nd_uint16_t qdcount; /* number of question entries */
nd_uint16_t ancount; /* number of answer entries */
nd_uint16_t nscount; /* number of authority entries */
nd_uint16_t arcount; /* number of resource entries */
} dns_header_t;
/*
* Macros for subfields of flag fields.
*/
#define DNS_QR(flags) ((flags) & 0x8000) /* response flag */
#define DNS_OPCODE(flags) (((flags) >> 11) & 0xF) /* purpose of message */
#define DNS_AA(flags) (flags & 0x0400) /* authoritative answer */
#define DNS_TC(flags) (flags & 0x0200) /* truncated message */
#define DNS_RD(flags) (flags & 0x0100) /* recursion desired */
#define DNS_RA(flags) (flags & 0x0080) /* recursion available */
#define DNS_AD(flags) (flags & 0x0020) /* authentic data from named */
#define DNS_CD(flags) (flags & 0x0010) /* checking disabled by resolver */
#define DNS_RCODE(flags) (flags & 0x000F) /* response code */
/*
* Defines for handling compressed domain names, EDNS0 labels, etc.
*/
#define TYPE_MASK 0xc0 /* mask for the type bits of the item */
#define TYPE_INDIR 0xc0 /* 11.... - pointer */
#define TYPE_RESERVED 0x80 /* 10.... - reserved */
#define TYPE_EDNS0 0x40 /* 01.... - EDNS(0) label */
#define TYPE_LABEL 0x00 /* 00.... - regular label */
# define EDNS0_ELT_BITLABEL 0x01
#endif /* !_NAMESER_H_ */
diff --git a/contrib/tcpdump/netdissect-alloc.c b/contrib/tcpdump/netdissect-alloc.c
index c625d34ec3b0..a73c77f805a2 100644
--- a/contrib/tcpdump/netdissect-alloc.c
+++ b/contrib/tcpdump/netdissect-alloc.c
@@ -1,64 +1,62 @@
/*
* Copyright (c) 2018 The TCPDUMP project
* 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, 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 <stdlib.h>
#include "netdissect-alloc.h"
static void nd_add_alloc_list(netdissect_options *, nd_mem_chunk_t *);
/*
* nd_free_all() is intended to be used after a packet printing
*/
/* Add a memory chunk in allocation linked list */
static void
nd_add_alloc_list(netdissect_options *ndo, nd_mem_chunk_t *chunkp)
{
if (ndo->ndo_last_mem_p == NULL) /* first memory allocation */
chunkp->prev_mem_p = NULL;
else /* previous memory allocation */
chunkp->prev_mem_p = ndo->ndo_last_mem_p;
ndo->ndo_last_mem_p = chunkp;
}
/* malloc replacement, with tracking in a linked list */
void *
nd_malloc(netdissect_options *ndo, size_t size)
{
nd_mem_chunk_t *chunkp = malloc(sizeof(nd_mem_chunk_t) + size);
if (chunkp == NULL)
return NULL;
nd_add_alloc_list(ndo, chunkp);
return chunkp + 1;
}
/* Free chunks in allocation linked list from last to first */
void
nd_free_all(netdissect_options *ndo)
{
nd_mem_chunk_t *current, *previous;
current = ndo->ndo_last_mem_p;
while (current != NULL) {
previous = current->prev_mem_p;
free(current);
current = previous;
}
ndo->ndo_last_mem_p = NULL;
}
diff --git a/contrib/tcpdump/netdissect.c b/contrib/tcpdump/netdissect.c
index 000d1ffce8c2..e78ccbc72b52 100644
--- a/contrib/tcpdump/netdissect.c
+++ b/contrib/tcpdump/netdissect.c
@@ -1,301 +1,313 @@
/*
* Copyright (c) 1988-1997
* The Regents of the University of California. All rights reserved.
*
* Copyright (c) 1998-2012 Michael Richardson <mcr@tcpdump.org>
* The TCPDUMP project
*
* 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.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef USE_LIBSMI
#include <smi.h>
#endif
/*
* Initialize anything that must be initialized before dissecting
* packets.
*
* This should be called at the beginning of the program; it does
* not need to be called, and should not be called, for every
* netdissect_options structure.
*/
int
nd_init(char *errbuf, size_t errbuf_size)
{
#ifdef _WIN32
WORD wVersionRequested;
WSADATA wsaData;
int err;
/*
* Request Winsock 2.2; we expect Winsock 2.
*/
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
strlcpy(errbuf, "Attempting to initialize Winsock failed",
errbuf_size);
return (-1);
}
#endif /* _WIN32 */
#ifdef USE_LIBSMI
/*
* XXX - should we just fail if this fails? Some of the
* libsmi calls may fail.
*/
smiInit("tcpdump");
#endif
/*
* Clears the error buffer, and uses it so we don't get
* "unused argument" warnings at compile time.
*/
strlcpy(errbuf, "", errbuf_size);
return (0);
}
/*
* Clean up anything that ndo_init() did.
*/
void
nd_cleanup(void)
{
#ifdef USE_LIBSMI
/*
* This appears, in libsmi 0.4.8, to do nothing if smiInit()
* wasn't done or failed, so we call it unconditionally.
*/
smiExit();
#endif
#ifdef _WIN32
/*
* Undo the WSAStartup() call above.
*/
WSACleanup();
#endif
}
int
nd_have_smi_support(void)
{
#ifdef USE_LIBSMI
return (1);
#else
return (0);
#endif
}
/*
* Indicates whether an SMI module has been loaded, so that we can use
* libsmi to translate OIDs.
*/
int nd_smi_module_loaded;
int
nd_load_smi_module(const char *module, char *errbuf, size_t errbuf_size)
{
#ifdef USE_LIBSMI
if (smiLoadModule(module) == 0) {
snprintf(errbuf, errbuf_size, "could not load MIB module %s",
module);
return (-1);
}
nd_smi_module_loaded = 1;
return (0);
#else
snprintf(errbuf, errbuf_size, "MIB module %s not loaded: no libsmi support",
module);
return (-1);
#endif
}
const char *
nd_smi_version_string(void)
{
#ifdef USE_LIBSMI
return (smi_version_string);
#else
return (NULL);
#endif
}
int
nd_push_buffer(netdissect_options *ndo, u_char *new_buffer,
const u_char *new_packetp, const u_int newlen)
{
struct netdissect_saved_packet_info *ndspi;
ndspi = (struct netdissect_saved_packet_info *)malloc(sizeof(struct netdissect_saved_packet_info));
if (ndspi == NULL)
return (0); /* fail */
ndspi->ndspi_buffer = new_buffer;
ndspi->ndspi_packetp = ndo->ndo_packetp;
ndspi->ndspi_snapend = ndo->ndo_snapend;
ndspi->ndspi_prev = ndo->ndo_packet_info_stack;
ndo->ndo_packetp = new_packetp;
ndo->ndo_snapend = new_packetp + newlen;
ndo->ndo_packet_info_stack = ndspi;
return (1); /* success */
}
/*
* In a given netdissect_options structure:
*
* push the current packet information onto the packet information
* stack;
*
* given a pointer into the packet and a length past that point in
* the packet, calculate a new snapshot end that's at the lower
* of the current snapshot end and that point in the packet;
*
* set the snapshot end to that new value.
*/
int
nd_push_snaplen(netdissect_options *ndo, const u_char *bp, const u_int newlen)
{
struct netdissect_saved_packet_info *ndspi;
u_int snaplen_remaining;
ndspi = (struct netdissect_saved_packet_info *)malloc(sizeof(struct netdissect_saved_packet_info));
if (ndspi == NULL)
return (0); /* fail */
ndspi->ndspi_buffer = NULL; /* no new buffer */
ndspi->ndspi_packetp = ndo->ndo_packetp;
ndspi->ndspi_snapend = ndo->ndo_snapend;
ndspi->ndspi_prev = ndo->ndo_packet_info_stack;
/*
* Push the saved previous data onto the stack.
*/
ndo->ndo_packet_info_stack = ndspi;
/*
* Find out how many bytes remain after the current snapend.
*
* We're restricted to packets with at most UINT_MAX bytes;
* cast the result to u_int, so that we don't get truncation
* warnings on LP64 and LLP64 platforms. (ptrdiff_t is
* signed and we want an unsigned difference; the pointer
* should at most be equal to snapend, and must *never*
* be past snapend.)
*/
snaplen_remaining = (u_int)(ndo->ndo_snapend - bp);
/*
* If the new snapend is smaller than the one calculated
* above, set the snapend to that value, otherwise leave
* it unchanged.
*/
if (newlen <= snaplen_remaining) {
/* Snapend isn't past the previous snapend */
ndo->ndo_snapend = bp + newlen;
}
return (1); /* success */
}
/*
* In a given netdissect_options structure:
*
* given a pointer into the packet and a length past that point in
* the packet, calculate a new snapshot end that's at the lower
* of the previous snapshot end - or, if there is no previous
* snapshot end, the current snapshot end - and that point in the
* packet;
*
* set the snapshot end to that new value.
*
* This is to change the current snapshot end. This may increase the
* snapshot end, as it may be used, for example, for a Jumbo Payload
* option in IPv6. It must not increase it past the snapshot length
* atop which the current one was pushed, however.
*/
void
nd_change_snaplen(netdissect_options *ndo, const u_char *bp, const u_int newlen)
{
struct netdissect_saved_packet_info *ndspi;
const u_char *previous_snapend;
u_int snaplen_remaining;
ndspi = ndo->ndo_packet_info_stack;
if (ndspi->ndspi_prev != NULL)
previous_snapend = ndspi->ndspi_prev->ndspi_snapend;
else
previous_snapend = ndo->ndo_snapend;
/*
* Find out how many bytes remain after the previous
* snapend - or, if there is no previous snapend, after
* the current snapend.
*
* We're restricted to packets with at most UINT_MAX bytes;
* cast the result to u_int, so that we don't get truncation
* warnings on LP64 and LLP64 platforms. (ptrdiff_t is
* signed and we want an unsigned difference; the pointer
* should at most be equal to snapend, and must *never*
* be past snapend.)
*/
snaplen_remaining = (u_int)(previous_snapend - bp);
/*
* If the new snapend is smaller than the one calculated
* above, set the snapend to that value, otherwise leave
* it unchanged.
*/
if (newlen <= snaplen_remaining) {
/* Snapend isn't past the previous snapend */
ndo->ndo_snapend = bp + newlen;
}
}
void
nd_pop_packet_info(netdissect_options *ndo)
{
struct netdissect_saved_packet_info *ndspi;
ndspi = ndo->ndo_packet_info_stack;
ndo->ndo_packetp = ndspi->ndspi_packetp;
ndo->ndo_snapend = ndspi->ndspi_snapend;
ndo->ndo_packet_info_stack = ndspi->ndspi_prev;
free(ndspi->ndspi_buffer);
free(ndspi);
}
void
nd_pop_all_packet_info(netdissect_options *ndo)
{
while (ndo->ndo_packet_info_stack != NULL)
nd_pop_packet_info(ndo);
}
+
+NORETURN void
+nd_trunc_longjmp(netdissect_options *ndo)
+{
+ longjmp(ndo->ndo_early_end, ND_TRUNCATED);
+#ifdef _AIX
+ /*
+ * In AIX <setjmp.h> decorates longjmp() with "#pragma leaves", which tells
+ * XL C that the function is noreturn, but GCC remains unaware of that and
+ * yields a "'noreturn' function does return" warning.
+ */
+ ND_UNREACHABLE
+#endif /* _AIX */
+}
diff --git a/contrib/tcpdump/netdissect.h b/contrib/tcpdump/netdissect.h
index 7696c4e41cd8..95d17b3db8b7 100644
--- a/contrib/tcpdump/netdissect.h
+++ b/contrib/tcpdump/netdissect.h
@@ -1,796 +1,807 @@
/*
* Copyright (c) 1988-1997
* The Regents of the University of California. All rights reserved.
*
* Copyright (c) 1998-2012 Michael Richardson <mcr@tcpdump.org>
* The TCPDUMP project
*
* 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.
*/
#ifndef netdissect_h
#define netdissect_h
#ifdef HAVE_OS_PROTO_H
#include "os-proto.h"
#endif
#include <sys/types.h>
#include <setjmp.h>
+#include <time.h>
#include "status-exit-codes.h"
#include "funcattrs.h" /* for PRINTFLIKE_FUNCPTR() */
#include "diag-control.h" /* for ND_UNREACHABLE */
/*
* Data types corresponding to multi-byte integral values within data
* structures. These are defined as arrays of octets, so that they're
* not aligned on their "natural" boundaries, and so that you *must*
* use the EXTRACT_ macros to extract them (which you should be doing
* *anyway*, so as not to assume a particular byte order or alignment
* in your code).
*
* We even want EXTRACT_U_1 used for 8-bit integral values, so we
* define nd_uint8_t and nd_int8_t as arrays as well.
*/
typedef unsigned char nd_uint8_t[1];
typedef unsigned char nd_uint16_t[2];
typedef unsigned char nd_uint24_t[3];
typedef unsigned char nd_uint32_t[4];
typedef unsigned char nd_uint40_t[5];
typedef unsigned char nd_uint48_t[6];
typedef unsigned char nd_uint56_t[7];
typedef unsigned char nd_uint64_t[8];
typedef signed char nd_int8_t[1];
/*
* "unsigned char" so that sign extension isn't done on the
- * individual bytes while they're being assembled.
+ * individual bytes while they're being assembled. Use
+ * GET_S_BE_n() and GET_S_LE_n() macros to extract the value
+ * as a signed integer.
*/
+typedef unsigned char nd_int16_t[2];
+typedef unsigned char nd_int24_t[3];
typedef unsigned char nd_int32_t[4];
+typedef unsigned char nd_int40_t[5];
+typedef unsigned char nd_int48_t[6];
+typedef unsigned char nd_int56_t[7];
typedef unsigned char nd_int64_t[8];
#define FMAXINT (4294967296.0) /* floating point rep. of MAXINT */
/*
* Use this for IPv4 addresses and netmasks.
*
* It's defined as an array of octets, so that it's not guaranteed to
* be aligned on its "natural" boundary (in some packet formats, it
* *isn't* so aligned). We have separate EXTRACT_ calls for them;
* sometimes you want the host-byte-order value, other times you want
* the network-byte-order value.
*
* Don't use EXTRACT_BE_U_4() on them, use EXTRACT_IPV4_TO_HOST_ORDER()
* if you want them in host byte order and EXTRACT_IPV4_TO_NETWORK_ORDER()
* if you want them in network byte order (which you want with system APIs
* that expect network-order IPv4 addresses, such as inet_ntop()).
*
* If, on your little-endian machine (e.g., an "IBM-compatible PC", no matter
* what the OS, or an Intel Mac, no matter what the OS), you get the wrong
* answer, and you've used EXTRACT_BE_U_4(), do *N*O*T* "fix" this by using
* EXTRACT_LE_U_4(), fix it by using EXTRACT_IPV4_TO_NETWORK_ORDER(),
* otherwise you're breaking the result on big-endian machines (e.g.,
* most PowerPC/Power ISA machines, System/390 and z/Architecture, SPARC,
* etc.).
*
* Yes, people do this; that's why Wireshark has tvb_get_ipv4(), to extract
* an IPv4 address from a packet data buffer; it was introduced in reaction
* to somebody who *had* done that.
*/
typedef unsigned char nd_ipv4[4];
/*
* Use this for IPv6 addresses and netmasks.
*/
typedef unsigned char nd_ipv6[16];
/*
* Use this for MAC addresses.
*/
#define MAC_ADDR_LEN 6U /* length of MAC addresses */
typedef unsigned char nd_mac_addr[MAC_ADDR_LEN];
/*
* Use this for blobs of bytes; make them arrays of nd_byte.
*/
typedef unsigned char nd_byte;
/*
* Round up x to a multiple of y; y must be a power of 2.
*/
#ifndef roundup2
#define roundup2(x, y) (((x)+((u_int)((y)-1)))&(~((u_int)((y)-1))))
#endif
#include <stdarg.h>
#include <pcap.h>
#include "ip.h" /* struct ip for nextproto4_cksum() */
#include "ip6.h" /* struct ip6 for nextproto6_cksum() */
#ifndef HAVE_STRLCAT
extern size_t strlcat (char *, const char *, size_t);
#endif
#ifndef HAVE_STRLCPY
extern size_t strlcpy (char *, const char *, size_t);
#endif
#ifndef HAVE_STRDUP
extern char *strdup (const char *str);
#endif
#ifndef HAVE_STRSEP
extern char *strsep(char **, const char *);
#endif
struct tok {
u_int v; /* value */
const char *s; /* string */
};
/* tok2str is deprecated */
extern const char *tok2str(const struct tok *, const char *, u_int);
extern char *bittok2str(const struct tok *, const char *, u_int);
extern char *bittok2str_nosep(const struct tok *, const char *, u_int);
/* Initialize netdissect. */
extern int nd_init(char *, size_t);
/* Clean up netdissect. */
extern void nd_cleanup(void);
/* Do we have libsmi support? */
extern int nd_have_smi_support(void);
/* Load an SMI module. */
extern int nd_load_smi_module(const char *, char *, size_t);
/* Flag indicating whether an SMI module has been loaded. */
extern int nd_smi_module_loaded;
/* Version number of the SMI library, or NULL if we don't have libsmi support. */
extern const char *nd_smi_version_string(void);
typedef struct netdissect_options netdissect_options;
#define IF_PRINTER_ARGS (netdissect_options *, const struct pcap_pkthdr *, const u_char *)
typedef void (*if_printer) IF_PRINTER_ARGS;
/*
* In case the data in a buffer needs to be processed by being decrypted,
* decompressed, etc. before it's dissected, we can't process it in place,
* we have to allocate a new buffer for the processed data.
*
* We keep a stack of those buffers; when we allocate a new buffer, we
* push the current one onto a stack, and when we're done with the new
* buffer, we free the current buffer and pop the previous one off the
* stack.
*
* A buffer has a beginning and end pointer, and a link to the previous
* buffer on the stack.
*
* In other cases, we temporarily adjust the snapshot end to reflect a
* packet-length field in the packet data and, when finished dissecting
* that part of the packet, restore the old snapshot end. We keep that
* on the stack with null buffer pointer, meaning there's nothing to
* free.
*/
struct netdissect_saved_packet_info {
u_char *ndspi_buffer; /* pointer to allocated buffer data */
const u_char *ndspi_packetp; /* saved beginning of data */
const u_char *ndspi_snapend; /* saved end of data */
struct netdissect_saved_packet_info *ndspi_prev; /* previous buffer on the stack */
};
/* 'val' value(s) for longjmp */
#define ND_TRUNCATED 1
struct netdissect_options {
int ndo_bflag; /* print 4 byte ASes in ASDOT notation */
int ndo_eflag; /* print ethernet header */
int ndo_fflag; /* don't translate "foreign" IP address */
int ndo_Kflag; /* don't check IP, TCP or UDP checksums */
int ndo_nflag; /* leave addresses as numbers */
int ndo_Nflag; /* remove domains from printed host names */
int ndo_qflag; /* quick (shorter) output */
int ndo_Sflag; /* print raw TCP sequence numbers */
int ndo_tflag; /* print packet arrival time */
int ndo_uflag; /* Print undecoded NFS handles */
int ndo_vflag; /* verbosity level */
int ndo_xflag; /* print packet in hex */
int ndo_Xflag; /* print packet in hex/ASCII */
int ndo_Aflag; /* print packet only in ASCII observing TAB,
* LF, CR and SPACE as graphical chars
*/
int ndo_Hflag; /* dissect 802.11s draft mesh standard */
const char *ndo_protocol; /* protocol */
jmp_buf ndo_early_end; /* jmp_buf for setjmp()/longjmp() */
void *ndo_last_mem_p; /* pointer to the last allocated memory chunk */
int ndo_packet_number; /* print a packet number in the beginning of line */
int ndo_suppress_default_print; /* don't use default_print() for unknown packet types */
int ndo_tstamp_precision; /* requested time stamp precision */
const char *program_name; /* Name of the program using the library */
char *ndo_espsecret;
struct sa_list *ndo_sa_list_head; /* used by print-esp.c */
struct sa_list *ndo_sa_default;
char *ndo_sigsecret; /* Signature verification secret key */
int ndo_packettype; /* as specified by -T */
int ndo_snaplen;
int ndo_ll_hdr_len; /* link-layer header length */
/*global pointers to beginning and end of current packet (during printing) */
const u_char *ndo_packetp;
const u_char *ndo_snapend;
/* stack of saved packet boundary and buffer information */
struct netdissect_saved_packet_info *ndo_packet_info_stack;
/* pointer to the if_printer function */
if_printer ndo_if_printer;
/* pointer to void function to output stuff */
void (*ndo_default_print)(netdissect_options *,
const u_char *bp, u_int length);
/* pointer to function to do regular output */
int (*ndo_printf)(netdissect_options *,
const char *fmt, ...)
PRINTFLIKE_FUNCPTR(2, 3);
/* pointer to function to output errors */
void NORETURN_FUNCPTR (*ndo_error)(netdissect_options *,
status_exit_codes_t status,
const char *fmt, ...)
PRINTFLIKE_FUNCPTR(3, 4);
/* pointer to function to output warnings */
void (*ndo_warning)(netdissect_options *,
const char *fmt, ...)
PRINTFLIKE_FUNCPTR(2, 3);
};
extern WARN_UNUSED_RESULT int nd_push_buffer(netdissect_options *, u_char *, const u_char *, const u_int);
extern WARN_UNUSED_RESULT int nd_push_snaplen(netdissect_options *, const u_char *, const u_int);
extern void nd_change_snaplen(netdissect_options *, const u_char *, const u_int);
extern void nd_pop_packet_info(netdissect_options *);
extern void nd_pop_all_packet_info(netdissect_options *);
-static inline NORETURN void
-nd_trunc_longjmp(netdissect_options *ndo)
-{
- longjmp(ndo->ndo_early_end, ND_TRUNCATED);
-#ifdef _AIX
- /*
- * In AIX <setjmp.h> decorates longjmp() with "#pragma leaves", which tells
- * XL C that the function is noreturn, but GCC remains unaware of that and
- * yields a "'noreturn' function does return" warning.
- */
- ND_UNREACHABLE
-#endif /* _AIX */
-}
+/*
+ * Report a packet truncation with a longjmp().
+ */
+NORETURN void nd_trunc_longjmp(netdissect_options *ndo);
#define PT_VAT 1 /* Visual Audio Tool */
#define PT_WB 2 /* distributed White Board */
#define PT_RPC 3 /* Remote Procedure Call */
#define PT_RTP 4 /* Real-Time Applications protocol */
#define PT_RTCP 5 /* Real-Time Applications control protocol */
#define PT_SNMP 6 /* Simple Network Management Protocol */
#define PT_CNFP 7 /* Cisco NetFlow protocol */
#define PT_TFTP 8 /* trivial file transfer protocol */
#define PT_AODV 9 /* Ad-hoc On-demand Distance Vector Protocol */
#define PT_CARP 10 /* Common Address Redundancy Protocol */
#define PT_RADIUS 11 /* RADIUS authentication Protocol */
#define PT_ZMTP1 12 /* ZeroMQ Message Transport Protocol 1.0 */
#define PT_VXLAN 13 /* Virtual eXtensible Local Area Network */
#define PT_PGM 14 /* [UDP-encapsulated] Pragmatic General Multicast */
#define PT_PGM_ZMTP1 15 /* ZMTP/1.0 inside PGM (native or UDP-encapsulated) */
#define PT_LMP 16 /* Link Management Protocol */
#define PT_RESP 17 /* RESP */
#define PT_PTP 18 /* PTP */
#define PT_SOMEIP 19 /* Autosar SOME/IP Protocol */
#define PT_DOMAIN 20 /* Domain Name System (DNS) */
#define ND_MIN(a,b) ((a)>(b)?(b):(a))
#define ND_MAX(a,b) ((b)>(a)?(b):(a))
/* For source or destination ports tests (UDP, TCP, ...) */
#define IS_SRC_OR_DST_PORT(p) (sport == (p) || dport == (p))
/*
* Maximum snapshot length. This should be enough to capture the full
* packet on most network interfaces.
*
*
* Somewhat arbitrary, but chosen to be:
*
* 1) big enough for maximum-size Linux loopback packets (65549)
* and some USB packets captured with USBPcap:
*
* https://desowin.org/usbpcap/
*
* (> 131072, < 262144)
*
* and
*
* 2) small enough not to cause attempts to allocate huge amounts of
* memory; some applications might use the snapshot length in a
* savefile header to control the size of the buffer they allocate,
* so a size of, say, 2^31-1 might not work well.
*
* XXX - does it need to be bigger still? Note that, for versions of
* libpcap with pcap_create()/pcap_activate(), if no -s flag is specified
* or -s 0 is specified, we won't set the snapshot length at all, and will
* let libpcap choose a snapshot length; newer versions may choose a bigger
* value than 262144 for D-Bus, for example.
*/
#define MAXIMUM_SNAPLEN 262144
/*
* True if "l" bytes from "p" were captured.
*
* The "ndo->ndo_snapend - (l) <= ndo->ndo_snapend" checks to make sure
* "l" isn't so large that "ndo->ndo_snapend - (l)" underflows.
*
* The check is for <= rather than < because "l" might be 0.
*
* We cast the pointers to uintptr_t to make sure that the compiler
* doesn't optimize away any of these tests (which it is allowed to
* do, as adding an integer to, or subtracting an integer from, a
* pointer assumes that the pointer is a pointer to an element of an
* array and that the result of the addition or subtraction yields a
* pointer to another member of the array, so that, for example, if
* you subtract a positive integer from a pointer, the result is
* guaranteed to be less than the original pointer value). See
*
* https://www.kb.cert.org/vuls/id/162289
*/
/*
* Test in two parts to avoid these warnings:
* comparison of unsigned expression >= 0 is always true [-Wtype-limits],
* comparison is always true due to limited range of data type [-Wtype-limits].
*/
#define IS_NOT_NEGATIVE(x) (((x) > 0) || ((x) == 0))
#define ND_TTEST_LEN(p, l) \
(IS_NOT_NEGATIVE(l) && \
((uintptr_t)ndo->ndo_snapend - (l) <= (uintptr_t)ndo->ndo_snapend && \
(uintptr_t)(p) <= (uintptr_t)ndo->ndo_snapend - (l)))
/* True if "*(p)" was captured */
#define ND_TTEST_SIZE(p) ND_TTEST_LEN(p, sizeof(*(p)))
/* Bail out if "l" bytes from "p" were not captured */
#ifdef ND_LONGJMP_FROM_TCHECK
#define ND_TCHECK_LEN(p, l) if (!ND_TTEST_LEN(p, l)) nd_trunc_longjmp(ndo)
#else
#define ND_TCHECK_LEN(p, l) if (!ND_TTEST_LEN(p, l)) goto trunc
#endif
/* Bail out if "*(p)" was not captured */
#define ND_TCHECK_SIZE(p) ND_TCHECK_LEN(p, sizeof(*(p)))
/*
* Number of bytes between two pointers.
*/
-#define ND_BYTES_BETWEEN(p1, p2) ((u_int)(((const uint8_t *)(p1)) - (const uint8_t *)(p2)))
+#define ND_BYTES_BETWEEN(p1, p2) ((const u_char *)(p1) >= (const u_char *)(p2) ? 0 : ((u_int)(((const u_char *)(p2)) - (const u_char *)(p1))))
/*
* Number of bytes remaining in the captured data, starting at the
* byte pointed to by the argument.
*/
-#define ND_BYTES_AVAILABLE_AFTER(p) ND_BYTES_BETWEEN(ndo->ndo_snapend, (p))
+#define ND_BYTES_AVAILABLE_AFTER(p) ((const u_char *)(p) < ndo->ndo_packetp ? 0 : ND_BYTES_BETWEEN((p), ndo->ndo_snapend))
-/* Check length < minimum for invalid packet with a custom message, format %u */
-#define ND_LCHECKMSG_U(length, minimum, what) \
-if ((length) < (minimum)) { \
-ND_PRINT(" [%s %u < %u]", (what), (length), (minimum)); \
+/*
+ * Check (expression_1 operator expression_2) for invalid packet with
+ * a custom message, format %u
+ */
+#define ND_ICHECKMSG_U(message, expression_1, operator, expression_2) \
+if ((expression_1) operator (expression_2)) { \
+ND_PRINT(" [%s %u %s %u]", (message), (expression_1), (#operator), (expression_2)); \
goto invalid; \
}
-/* Check length < minimum for invalid packet with #length message, format %u */
-#define ND_LCHECK_U(length, minimum) \
-ND_LCHECKMSG_U((length), (minimum), (#length))
+/*
+ * Check (expression_1 operator expression_2) for invalid packet with
+ * "expression_1" message, format %u
+ */
+#define ND_ICHECK_U(expression_1, operator, expression_2) \
+ND_ICHECKMSG_U((#expression_1), (expression_1), operator, (expression_2))
-/* Check length < minimum for invalid packet with a custom message, format %zu */
-#define ND_LCHECKMSG_ZU(length, minimum, what) \
-if ((length) < (minimum)) { \
-ND_PRINT(" [%s %u < %zu]", (what), (length), (minimum)); \
+/*
+ * Check (expression_1 operator expression_2) for invalid packet with
+ * a custom message, format %zu
+ */
+#define ND_ICHECKMSG_ZU(message, expression_1, operator, expression_2) \
+if ((expression_1) operator (expression_2)) { \
+ND_PRINT(" [%s %u %s %zu]", (message), (expression_1), (#operator), (expression_2)); \
goto invalid; \
}
-/* Check length < minimum for invalid packet with #length message, format %zu */
-#define ND_LCHECK_ZU(length, minimum) \
-ND_LCHECKMSG_ZU((length), (minimum), (#length))
+/*
+ * Check (expression_1 operator expression_2) for invalid packet with
+ * "expression_1" message, format %zu
+ */
+#define ND_ICHECK_ZU(expression_1, operator, expression_2) \
+ND_ICHECKMSG_ZU((#expression_1), (expression_1), operator, (expression_2))
#define ND_PRINT(...) (ndo->ndo_printf)(ndo, __VA_ARGS__)
#define ND_DEFAULTPRINT(ap, length) (*ndo->ndo_default_print)(ndo, ap, length)
extern void ts_print(netdissect_options *, const struct timeval *);
extern void signed_relts_print(netdissect_options *, int32_t);
extern void unsigned_relts_print(netdissect_options *, uint32_t);
extern const char *nd_format_time(char *buf, size_t bufsize,
const char *format, const struct tm *timeptr);
extern void fn_print_char(netdissect_options *, u_char);
extern void fn_print_str(netdissect_options *, const u_char *);
extern u_int nd_printztn(netdissect_options *, const u_char *, u_int, const u_char *);
extern int nd_printn(netdissect_options *, const u_char *, u_int, const u_char *);
+extern void nd_printjn(netdissect_options *, const u_char *, u_int);
extern void nd_printjnp(netdissect_options *, const u_char *, u_int);
/*
* Flags for txtproto_print().
*/
#define RESP_CODE_SECOND_TOKEN 0x00000001 /* response code is second token in response line */
extern void txtproto_print(netdissect_options *, const u_char *, u_int,
const char **, u_int);
#if (defined(__i386__) || defined(_M_IX86) || defined(__X86__) || defined(__x86_64__) || defined(_M_X64)) || \
(defined(__arm__) || defined(_M_ARM) || defined(__aarch64__)) || \
(defined(__m68k__) && (!defined(__mc68000__) && !defined(__mc68010__))) || \
(defined(__ppc__) || defined(__ppc64__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PPC64)) || \
(defined(__s390__) || defined(__s390x__) || defined(__zarch__)) || \
defined(__vax__)
/*
* The processor natively handles unaligned loads, so just use memcpy()
* and memcmp(), to enable those optimizations.
*
* XXX - are those all the x86 tests we need?
* XXX - do we need to worry about ARMv1 through ARMv5, which didn't
* support unaligned loads, and, if so, do we need to worry about all
* of them, or just some of them, e.g. ARMv5?
* XXX - are those the only 68k tests we need not to generated
* unaligned accesses if the target is the 68000 or 68010?
* XXX - are there any tests we don't need, because some definitions are for
* compilers that also predefine the GCC symbols?
* XXX - do we need to test for both 32-bit and 64-bit versions of those
* architectures in all cases?
*/
#define UNALIGNED_MEMCPY(p, q, l) memcpy((p), (q), (l))
#define UNALIGNED_MEMCMP(p, q, l) memcmp((p), (q), (l))
#else
/*
* The processor doesn't natively handle unaligned loads,
* and the compiler might "helpfully" optimize memcpy()
* and memcmp(), when handed pointers that would normally
* be properly aligned, into sequences that assume proper
* alignment.
*
* Do copies and compares of possibly-unaligned data by
* calling routines that wrap memcpy() and memcmp(), to
* prevent that optimization.
*/
extern void unaligned_memcpy(void *, const void *, size_t);
extern int unaligned_memcmp(const void *, const void *, size_t);
#define UNALIGNED_MEMCPY(p, q, l) unaligned_memcpy((p), (q), (l))
#define UNALIGNED_MEMCMP(p, q, l) unaligned_memcmp((p), (q), (l))
#endif
#define PLURAL_SUFFIX(n) \
(((n) != 1) ? "s" : "")
extern const char *tok2strary_internal(const char **, int, const char *, int);
#define tok2strary(a,f,i) tok2strary_internal(a, sizeof(a)/sizeof(a[0]),f,i)
struct uint_tokary
{
u_int uintval;
const struct tok *tokary;
};
extern const struct tok *uint2tokary_internal(const struct uint_tokary[], const size_t, const u_int);
#define uint2tokary(a, i) uint2tokary_internal(a, sizeof(a)/sizeof(a[0]), i)
extern if_printer lookup_printer(int);
#define ND_DEBUG {printf(" [%s:%d %s] ", __FILE__, __LINE__, __func__); fflush(stdout);}
/* The DLT printer routines */
extern void ap1394_if_print IF_PRINTER_ARGS;
extern void arcnet_if_print IF_PRINTER_ARGS;
extern void arcnet_linux_if_print IF_PRINTER_ARGS;
extern void atm_if_print IF_PRINTER_ARGS;
extern void brcm_tag_if_print IF_PRINTER_ARGS;
extern void brcm_tag_prepend_if_print IF_PRINTER_ARGS;
extern void bt_if_print IF_PRINTER_ARGS;
extern void chdlc_if_print IF_PRINTER_ARGS;
extern void cip_if_print IF_PRINTER_ARGS;
extern void dsa_if_print IF_PRINTER_ARGS;
extern void edsa_if_print IF_PRINTER_ARGS;
extern void enc_if_print IF_PRINTER_ARGS;
extern void ether_if_print IF_PRINTER_ARGS;
extern void fddi_if_print IF_PRINTER_ARGS;
extern void fr_if_print IF_PRINTER_ARGS;
extern void ieee802_11_if_print IF_PRINTER_ARGS;
extern void ieee802_11_radio_avs_if_print IF_PRINTER_ARGS;
extern void ieee802_11_radio_if_print IF_PRINTER_ARGS;
extern void ieee802_15_4_if_print IF_PRINTER_ARGS;
extern void ieee802_15_4_tap_if_print IF_PRINTER_ARGS;
extern void ipfc_if_print IF_PRINTER_ARGS;
extern void ipnet_if_print IF_PRINTER_ARGS;
extern void ipoib_if_print IF_PRINTER_ARGS;
extern void juniper_atm1_if_print IF_PRINTER_ARGS;
extern void juniper_atm2_if_print IF_PRINTER_ARGS;
extern void juniper_chdlc_if_print IF_PRINTER_ARGS;
extern void juniper_es_if_print IF_PRINTER_ARGS;
extern void juniper_ether_if_print IF_PRINTER_ARGS;
extern void juniper_frelay_if_print IF_PRINTER_ARGS;
extern void juniper_ggsn_if_print IF_PRINTER_ARGS;
extern void juniper_mfr_if_print IF_PRINTER_ARGS;
extern void juniper_mlfr_if_print IF_PRINTER_ARGS;
extern void juniper_mlppp_if_print IF_PRINTER_ARGS;
extern void juniper_monitor_if_print IF_PRINTER_ARGS;
extern void juniper_ppp_if_print IF_PRINTER_ARGS;
extern void juniper_pppoe_atm_if_print IF_PRINTER_ARGS;
extern void juniper_pppoe_if_print IF_PRINTER_ARGS;
extern void juniper_services_if_print IF_PRINTER_ARGS;
extern void ltalk_if_print IF_PRINTER_ARGS;
extern void mfr_if_print IF_PRINTER_ARGS;
extern void netanalyzer_if_print IF_PRINTER_ARGS;
extern void netanalyzer_transparent_if_print IF_PRINTER_ARGS;
extern void nflog_if_print IF_PRINTER_ARGS;
extern void null_if_print IF_PRINTER_ARGS;
extern void pflog_if_print IF_PRINTER_ARGS;
extern void pktap_if_print IF_PRINTER_ARGS;
extern void ppi_if_print IF_PRINTER_ARGS;
extern void ppp_bsdos_if_print IF_PRINTER_ARGS;
extern void ppp_hdlc_if_print IF_PRINTER_ARGS;
extern void ppp_if_print IF_PRINTER_ARGS;
extern void pppoe_if_print IF_PRINTER_ARGS;
extern void prism_if_print IF_PRINTER_ARGS;
extern void raw_if_print IF_PRINTER_ARGS;
extern void sl_bsdos_if_print IF_PRINTER_ARGS;
extern void sl_if_print IF_PRINTER_ARGS;
extern void sll2_if_print IF_PRINTER_ARGS;
extern void sll_if_print IF_PRINTER_ARGS;
extern void sunatm_if_print IF_PRINTER_ARGS;
extern void symantec_if_print IF_PRINTER_ARGS;
extern void token_if_print IF_PRINTER_ARGS;
extern void unsupported_if_print IF_PRINTER_ARGS;
extern void usb_linux_48_byte_if_print IF_PRINTER_ARGS;
extern void usb_linux_64_byte_if_print IF_PRINTER_ARGS;
extern void vsock_if_print IF_PRINTER_ARGS;
/*
* Structure passed to some printers to allow them to print
* link-layer address information if ndo_eflag isn't set
* (because they are for protocols that don't have their
* own addresses, so that we'd want to report link-layer
* address information).
*
* This contains a pointer to an address and a pointer to a routine
* to which we pass that pointer in order to get a string.
*/
struct lladdr_info {
const char *(*addr_string)(netdissect_options *, const u_char *);
const u_char *addr;
};
/* The printer routines. */
extern void aarp_print(netdissect_options *, const u_char *, u_int);
extern int ah_print(netdissect_options *, const u_char *);
extern void ahcp_print(netdissect_options *, const u_char *, u_int);
extern void aodv_print(netdissect_options *, const u_char *, u_int, int);
extern void aoe_print(netdissect_options *, const u_char *, const u_int);
extern int arista_ethertype_print(netdissect_options *,const u_char *, u_int);
extern void arp_print(netdissect_options *, const u_char *, u_int, u_int);
extern void ascii_print(netdissect_options *, const u_char *, u_int);
extern void atalk_print(netdissect_options *, const u_char *, u_int);
extern void atm_print(netdissect_options *, u_int, u_int, u_int, const u_char *, u_int, u_int);
extern void babel_print(netdissect_options *, const u_char *, u_int);
extern void bcm_li_print(netdissect_options *, const u_char *, u_int);
extern void beep_print(netdissect_options *, const u_char *, u_int);
extern void bfd_print(netdissect_options *, const u_char *, u_int, u_int);
extern void bgp_print(netdissect_options *, const u_char *, u_int);
extern const char *bgp_vpn_rd_print(netdissect_options *, const u_char *);
extern void bootp_print(netdissect_options *, const u_char *, u_int);
extern void calm_fast_print(netdissect_options *, const u_char *, u_int, const struct lladdr_info *);
extern void carp_print(netdissect_options *, const u_char *, u_int, u_int);
extern void cdp_print(netdissect_options *, const u_char *, u_int);
extern void cfm_print(netdissect_options *, const u_char *, u_int);
extern u_int chdlc_print(netdissect_options *, const u_char *, u_int);
extern void cisco_autorp_print(netdissect_options *, const u_char *, u_int);
extern void cnfp_print(netdissect_options *, const u_char *);
extern void dccp_print(netdissect_options *, const u_char *, const u_char *, u_int);
extern void decnet_print(netdissect_options *, const u_char *, u_int, u_int);
extern void dhcp6_print(netdissect_options *, const u_char *, u_int);
extern int dstopt_process(netdissect_options *, const u_char *);
extern void dtp_print(netdissect_options *, const u_char *, u_int);
extern void dvmrp_print(netdissect_options *, const u_char *, u_int);
extern void eap_print(netdissect_options *, const u_char *, u_int);
extern void eapol_print(netdissect_options *, const u_char *);
extern void egp_print(netdissect_options *, const u_char *, u_int);
extern void eigrp_print(netdissect_options *, const u_char *, u_int);
extern void esp_print(netdissect_options *, const u_char *, u_int, const u_char *, u_int, int, u_int);
extern u_int ether_print(netdissect_options *, const u_char *, u_int, u_int, void (*)(netdissect_options *, const u_char *), const u_char *);
extern u_int ether_switch_tag_print(netdissect_options *, const u_char *, u_int, u_int, void (*)(netdissect_options *, const u_char *), u_int);
extern int ethertype_print(netdissect_options *, u_short, const u_char *, u_int, u_int, const struct lladdr_info *, const struct lladdr_info *);
extern u_int fddi_print(netdissect_options *, const u_char *, u_int, u_int);
extern void forces_print(netdissect_options *, const u_char *, u_int);
extern u_int fr_print(netdissect_options *, const u_char *, u_int);
extern int frag6_print(netdissect_options *, const u_char *, const u_char *);
extern void ftp_print(netdissect_options *, const u_char *, u_int);
extern void geneve_print(netdissect_options *, const u_char *, u_int);
extern void geonet_print(netdissect_options *, const u_char *, u_int, const struct lladdr_info *);
extern void gre_print(netdissect_options *, const u_char *, u_int);
extern int hbhopt_process(netdissect_options *, const u_char *, int *, uint32_t *);
extern void hex_and_ascii_print(netdissect_options *, const char *, const u_char *, u_int);
extern void hex_print(netdissect_options *, const char *ident, const u_char *cp, u_int);
extern void hex_print_with_offset(netdissect_options *, const char *ident, const u_char *cp, u_int, u_int);
extern void hncp_print(netdissect_options *, const u_char *, u_int);
extern void hsrp_print(netdissect_options *, const u_char *, u_int);
extern void http_print(netdissect_options *, const u_char *, u_int);
extern void icmp6_print(netdissect_options *, const u_char *, u_int, const u_char *, int);
extern void icmp_print(netdissect_options *, const u_char *, u_int, const u_char *, int);
extern u_int ieee802_15_4_print(netdissect_options *, const u_char *, u_int);
extern u_int ieee802_11_radio_print(netdissect_options *, const u_char *, u_int, u_int);
extern void igmp_print(netdissect_options *, const u_char *, u_int);
extern void igrp_print(netdissect_options *, const u_char *, u_int);
extern void ip6_print(netdissect_options *, const u_char *, u_int);
extern void ipN_print(netdissect_options *, const u_char *, u_int);
-extern void ip_print(netdissect_options *, const u_char *, u_int);
+extern void ip_print(netdissect_options *, const u_char *, const u_int);
extern void ipcomp_print(netdissect_options *, const u_char *);
extern void ipx_netbios_print(netdissect_options *, const u_char *, u_int);
extern void ipx_print(netdissect_options *, const u_char *, u_int);
extern void isakmp_print(netdissect_options *, const u_char *, u_int, const u_char *);
extern void isakmp_rfc3948_print(netdissect_options *, const u_char *, u_int, const u_char *, int, int, u_int);
extern void isoclns_print(netdissect_options *, const u_char *, u_int);
extern void krb_print(netdissect_options *, const u_char *);
extern void l2tp_print(netdissect_options *, const u_char *, u_int);
extern void lane_print(netdissect_options *, const u_char *, u_int, u_int);
extern void ldp_print(netdissect_options *, const u_char *, u_int);
extern void lisp_print(netdissect_options *, const u_char *, u_int);
extern u_int llap_print(netdissect_options *, const u_char *, u_int);
extern int llc_print(netdissect_options *, const u_char *, u_int, u_int, const struct lladdr_info *, const struct lladdr_info *);
extern void lldp_print(netdissect_options *, const u_char *, u_int);
extern void lmp_print(netdissect_options *, const u_char *, u_int);
extern void loopback_print(netdissect_options *, const u_char *, u_int);
extern void lspping_print(netdissect_options *, const u_char *, u_int);
extern void lwapp_control_print(netdissect_options *, const u_char *, u_int, int);
extern void lwapp_data_print(netdissect_options *, const u_char *, u_int);
extern void lwres_print(netdissect_options *, const u_char *, u_int);
extern void m3ua_print(netdissect_options *, const u_char *, const u_int);
extern int macsec_print(netdissect_options *, const u_char **,
u_int *, u_int *, u_int *, const struct lladdr_info *,
const struct lladdr_info *);
extern u_int mfr_print(netdissect_options *, const u_char *, u_int);
extern void mobile_print(netdissect_options *, const u_char *, u_int);
extern int mobility_print(netdissect_options *, const u_char *, const u_char *);
extern void mpcp_print(netdissect_options *, const u_char *, u_int);
extern void mpls_print(netdissect_options *, const u_char *, u_int);
extern int mptcp_print(netdissect_options *, const u_char *, u_int, u_char);
extern void msdp_print(netdissect_options *, const u_char *, u_int);
extern void msnlb_print(netdissect_options *, const u_char *);
extern void nbt_tcp_print(netdissect_options *, const u_char *, u_int);
extern void nbt_udp137_print(netdissect_options *, const u_char *, u_int);
extern void nbt_udp138_print(netdissect_options *, const u_char *, u_int);
extern void netbeui_print(netdissect_options *, u_short, const u_char *, u_int);
extern void nfsreply_print(netdissect_options *, const u_char *, u_int, const u_char *);
extern void nfsreply_noaddr_print(netdissect_options *, const u_char *, u_int, const u_char *);
extern void nfsreq_noaddr_print(netdissect_options *, const u_char *, u_int, const u_char *);
extern const u_char *fqdn_print(netdissect_options *, const u_char *, const u_char *);
extern void domain_print(netdissect_options *, const u_char *, u_int, int, int);
extern void nsh_print(netdissect_options *, const u_char *, u_int);
extern void ntp_print(netdissect_options *, const u_char *, u_int);
extern void oam_print(netdissect_options *, const u_char *, u_int, u_int);
extern void olsr_print(netdissect_options *, const u_char *, u_int, int);
extern void openflow_print(netdissect_options *, const u_char *, u_int);
extern void ospf6_print(netdissect_options *, const u_char *, u_int);
extern void ospf_print(netdissect_options *, const u_char *, u_int, const u_char *);
extern int ospf_grace_lsa_print(netdissect_options *, const u_char *, u_int);
extern int ospf_te_lsa_print(netdissect_options *, const u_char *, u_int);
extern void otv_print(netdissect_options *, const u_char *, u_int);
extern void pfsync_ip_print(netdissect_options *, const u_char *, u_int);
extern void pfsync_if_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *);
extern void pgm_print(netdissect_options *, const u_char *, u_int, const u_char *);
extern void pim_print(netdissect_options *, const u_char *, u_int, const u_char *);
extern void pimv1_print(netdissect_options *, const u_char *, u_int);
extern u_int ppp_print(netdissect_options *, const u_char *, u_int);
extern u_int pppoe_print(netdissect_options *, const u_char *, u_int);
extern void pptp_print(netdissect_options *, const u_char *);
extern void ptp_print(netdissect_options *, const u_char *, u_int);
extern int print_unknown_data(netdissect_options *, const u_char *, const char *, u_int);
extern const char *q922_string(netdissect_options *, const u_char *, u_int);
extern void q933_print(netdissect_options *, const u_char *, u_int);
extern void radius_print(netdissect_options *, const u_char *, u_int);
extern void resp_print(netdissect_options *, const u_char *, u_int);
extern void rip_print(netdissect_options *, const u_char *, u_int);
extern void ripng_print(netdissect_options *, const u_char *, unsigned int);
extern void rpki_rtr_print(netdissect_options *, const u_char *, u_int);
extern void rsvp_print(netdissect_options *, const u_char *, u_int);
extern int rt6_print(netdissect_options *, const u_char *, const u_char *);
extern void rtl_print(netdissect_options *, const u_char *, u_int, const struct lladdr_info *, const struct lladdr_info *);
extern void rtsp_print(netdissect_options *, const u_char *, u_int);
extern void rx_print(netdissect_options *, const u_char *, u_int, uint16_t, uint16_t, const u_char *);
extern void sctp_print(netdissect_options *, const u_char *, const u_char *, u_int);
extern void sflow_print(netdissect_options *, const u_char *, u_int);
extern void ssh_print(netdissect_options *, const u_char *, u_int);
extern void sip_print(netdissect_options *, const u_char *, u_int);
extern void slow_print(netdissect_options *, const u_char *, u_int);
extern void smb_tcp_print(netdissect_options *, const u_char *, u_int);
extern void smtp_print(netdissect_options *, const u_char *, u_int);
extern int snap_print(netdissect_options *, const u_char *, u_int, u_int, const struct lladdr_info *, const struct lladdr_info *, u_int);
extern void snmp_print(netdissect_options *, const u_char *, u_int);
extern void stp_print(netdissect_options *, const u_char *, u_int);
extern void sunrpc_print(netdissect_options *, const u_char *, u_int, const u_char *);
extern void syslog_print(netdissect_options *, const u_char *, u_int);
extern void tcp_print(netdissect_options *, const u_char *, u_int, const u_char *, int);
extern void telnet_print(netdissect_options *, const u_char *, u_int);
extern void tftp_print(netdissect_options *, const u_char *, u_int);
extern void timed_print(netdissect_options *, const u_char *);
extern void tipc_print(netdissect_options *, const u_char *, u_int, u_int);
extern u_int token_print(netdissect_options *, const u_char *, u_int, u_int);
extern void udld_print(netdissect_options *, const u_char *, u_int);
extern void udp_print(netdissect_options *, const u_char *, u_int, const u_char *, int, u_int);
extern int vjc_print(netdissect_options *, const u_char *, u_short);
extern void vqp_print(netdissect_options *, const u_char *, u_int);
extern void vrrp_print(netdissect_options *, const u_char *, u_int, const u_char *, int, int);
extern void vtp_print(netdissect_options *, const u_char *, const u_int);
extern void vxlan_gpe_print(netdissect_options *, const u_char *, u_int);
extern void vxlan_print(netdissect_options *, const u_char *, u_int);
extern void wb_print(netdissect_options *, const u_char *, u_int);
extern void whois_print(netdissect_options *, const u_char *, u_int);
extern void zep_print(netdissect_options *, const u_char *, u_int);
extern void zephyr_print(netdissect_options *, const u_char *, u_int);
extern void zmtp1_print(netdissect_options *, const u_char *, u_int);
extern void zmtp1_datagram_print(netdissect_options *, const u_char *, const u_int);
extern void someip_print(netdissect_options *, const u_char *, const u_int);
/* checksum routines */
-extern void init_checksum(void);
extern uint16_t verify_crc10_cksum(uint16_t, const u_char *, int);
extern uint16_t create_osi_cksum(const uint8_t *, int, int);
struct cksum_vec {
const uint8_t *ptr;
int len;
};
extern uint16_t in_cksum(const struct cksum_vec *, int);
extern uint16_t in_cksum_shouldbe(uint16_t, uint16_t);
/* IP protocol demuxing routines */
extern void ip_demux_print(netdissect_options *, const u_char *, u_int, u_int, int, u_int, uint8_t, const u_char *);
extern uint16_t nextproto4_cksum(netdissect_options *, const struct ip *, const uint8_t *, u_int, u_int, uint8_t);
/* in print-ip6.c */
extern uint16_t nextproto6_cksum(netdissect_options *, const struct ip6_hdr *, const uint8_t *, u_int, u_int, uint8_t);
/* Utilities */
extern void nd_print_trunc(netdissect_options *);
extern void nd_print_protocol(netdissect_options *);
extern void nd_print_protocol_caps(netdissect_options *);
extern void nd_print_invalid(netdissect_options *);
extern int mask2plen(uint32_t);
extern int mask62plen(const u_char *);
extern const char *dnnum_string(netdissect_options *, u_short);
extern int decode_prefix4(netdissect_options *, const u_char *, u_int, char *, size_t);
extern int decode_prefix6(netdissect_options *, const u_char *, u_int, char *, size_t);
extern void esp_decodesecret_print(netdissect_options *);
extern int esp_decrypt_buffer_by_ikev2_print(netdissect_options *, int,
const u_char spii[8],
const u_char spir[8],
const u_char *, const u_char *);
#endif /* netdissect_h */
diff --git a/contrib/tcpdump/nlpid.c b/contrib/tcpdump/nlpid.c
index 59f6e598aad5..3f431e73d68a 100644
--- a/contrib/tcpdump/nlpid.c
+++ b/contrib/tcpdump/nlpid.c
@@ -1,41 +1,39 @@
/*
* 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.
*
* Original code by Hannes Gredler (hannes@gredler.at)
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "nlpid.h"
const struct tok nlpid_values[] = {
{ NLPID_NULLNS, "NULL" },
{ NLPID_Q933, "Q.933" },
{ NLPID_LMI, "LMI" },
{ NLPID_SNAP, "SNAP" },
{ NLPID_CLNP, "CLNP" },
{ NLPID_ESIS, "ES-IS" },
{ NLPID_ISIS, "IS-IS" },
{ NLPID_CONS, "CONS" },
{ NLPID_IDRP, "IDRP" },
{ NLPID_SPB, "ISIS_SPB" },
{ NLPID_MFR, "FRF.15" },
{ NLPID_IP, "IPv4" },
{ NLPID_PPP, "PPP" },
{ NLPID_X25_ESIS, "X25 ES-IS" },
{ NLPID_IP6, "IPv6" },
{ 0, NULL }
};
diff --git a/contrib/tcpdump/ntp.c b/contrib/tcpdump/ntp.c
index ec8f659a4eb0..967644e0e1b9 100644
--- a/contrib/tcpdump/ntp.c
+++ b/contrib/tcpdump/ntp.c
@@ -1,74 +1,72 @@
/*
* 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.
*
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "ntp.h"
#include "extract.h"
#define JAN_1970 INT64_T_CONSTANT(2208988800) /* 1970 - 1900 in seconds */
void
p_ntp_time(netdissect_options *ndo,
const struct l_fixedpt *lfp)
{
uint32_t i;
uint32_t uf;
uint32_t f;
double ff;
i = GET_BE_U_4(lfp->int_part);
uf = GET_BE_U_4(lfp->fraction);
ff = uf;
if (ff < 0.0) /* some compilers are buggy */
ff += FMAXINT;
ff = ff / FMAXINT; /* shift radix point by 32 bits */
f = (uint32_t)(ff * 1000000000.0); /* treat fraction as parts per billion */
ND_PRINT("%u.%09u", i, f);
/*
* print the UTC time in human-readable format.
*/
if (i) {
int64_t seconds_64bit = (int64_t)i - JAN_1970;
time_t seconds;
char time_buf[128];
const char *time_string;
seconds = (time_t)seconds_64bit;
if (seconds != seconds_64bit) {
/*
* It doesn't fit into a time_t, so we can't hand it
* to gmtime.
*/
time_string = "[Time is too large to fit into a time_t]";
} else {
/* use ISO 8601 (RFC3339) format */
time_string = nd_format_time(time_buf, sizeof (time_buf),
"%Y-%m-%dT%H:%M:%SZ", gmtime(&seconds));
}
ND_PRINT(" (%s)", time_string);
}
}
diff --git a/contrib/tcpdump/oui.c b/contrib/tcpdump/oui.c
index 25d08e213ece..9b9c71cafb20 100644
--- a/contrib/tcpdump/oui.c
+++ b/contrib/tcpdump/oui.c
@@ -1,131 +1,129 @@
/*
* 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.
*
* Original code by Hannes Gredler (hannes@gredler.at)
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "oui.h"
/* FIXME complete OUI list using a script */
const struct tok oui_values[] = {
{ OUI_ENCAP_ETHER, "Ethernet" },
{ OUI_CISCO, "Cisco" },
{ OUI_IANA, "IANA" },
{ OUI_NORTEL, "Nortel Networks SONMP" },
{ OUI_CISCO_90, "Cisco bridged" },
{ OUI_RFC2684, "Ethernet bridged" },
{ OUI_ATM_FORUM, "ATM Forum" },
{ OUI_CABLE_BPDU, "DOCSIS Spanning Tree" },
{ OUI_APPLETALK, "Appletalk" },
{ OUI_JUNIPER, "Juniper" },
{ OUI_HP, "Hewlett-Packard" },
{ OUI_IEEE_8021_PRIVATE, "IEEE 802.1 Private"},
{ OUI_IEEE_8023_PRIVATE, "IEEE 802.3 Private"},
{ OUI_TIA, "ANSI/TIA"},
{ OUI_DCBX, "DCBX"},
{ OUI_NICIRA, "Nicira Networks" },
{ OUI_BSN, "Big Switch Networks" },
{ OUI_VELLO, "Vello Systems" },
{ OUI_HP2, "HP" },
{ OUI_HPLABS, "HP-Labs" },
{ OUI_INFOBLOX, "Infoblox Inc" },
{ OUI_ONLAB, "Open Networking Lab" },
{ OUI_FREESCALE, "Freescale" },
{ OUI_NETRONOME, "Netronome" },
{ OUI_BROADCOM, "Broadcom" },
{ OUI_PMC_SIERRA, "PMC-Sierra" },
{ OUI_ERICSSON, "Ericsson" },
{ 0, NULL }
};
/*
* SMI Network Management Private Enterprise Codes for organizations.
*
* XXX - these also appear in FreeRadius dictionary files, with items such
* as
*
* VENDOR Cisco 9
*
* List taken from Ethereal's epan/sminmpec.c.
*/
const struct tok smi_values[] = {
{ SMI_IETF, "IETF (reserved)"},
{ SMI_ACC, "ACC"},
{ SMI_CISCO, "Cisco"},
{ SMI_HEWLETT_PACKARD, "Hewlett Packard"},
{ SMI_SUN_MICROSYSTEMS, "Sun Microsystems"},
{ SMI_MERIT, "Merit"},
{ SMI_AT_AND_T, "AT&T"},
{ SMI_MOTOROLA, "Motorola"},
{ SMI_SHIVA, "Shiva"},
{ SMI_ERICSSON, "Ericsson AB"},
{ SMI_CISCO_VPN5000, "Cisco VPN 5000"},
{ SMI_LIVINGSTON, "Livingston"},
{ SMI_MICROSOFT, "Microsoft"},
{ SMI_3COM, "3Com"},
{ SMI_ASCEND, "Ascend"},
{ SMI_BAY, "Bay Networks"},
{ SMI_FOUNDRY, "Foundry"},
{ SMI_VERSANET, "Versanet"},
{ SMI_REDBACK, "Redback"},
{ SMI_JUNIPER, "Juniper Networks"},
{ SMI_APTIS, "Aptis"},
{ SMI_DT_AG, "Deutsche Telekom AG"},
{ SMI_IXIA, "Ixia Communications"},
{ SMI_CISCO_VPN3000, "Cisco VPN 3000"},
{ SMI_COSINE, "CoSine Communications"},
{ SMI_NETSCREEN, "Netscreen"},
{ SMI_SHASTA, "Shasta"},
{ SMI_NOMADIX, "Nomadix"},
{ SMI_T_MOBILE, "T-Mobile"},
{ SMI_BROADBAND_FORUM, "The Broadband Forum"},
{ SMI_ZTE, "ZTE"},
{ SMI_SIEMENS, "Siemens"},
{ SMI_CABLELABS, "CableLabs"},
{ SMI_UNISPHERE, "Unisphere Networks"},
{ SMI_CISCO_BBSM, "Cisco BBSM"},
{ SMI_THE3GPP2, "3rd Generation Partnership Project 2 (3GPP2)"},
{ SMI_SKT_TELECOM, "SK Telecom"},
{ SMI_IP_UNPLUGGED, "ipUnplugged"},
{ SMI_ISSANNI, "Issanni Communications"},
{ SMI_NETSCALER, "Netscaler"},
{ SMI_DE_TE_MOBIL, "T-Mobile"},
{ SMI_QUINTUM, "Quintum"},
{ SMI_INTERLINK, "Interlink"},
{ SMI_CNCTC, "CNCTC"},
{ SMI_STARENT_NETWORKS, "Starent Networks"},
{ SMI_COLUBRIS, "Colubris"},
{ SMI_THE3GPP, "3GPP"},
{ SMI_GEMTEK_SYSTEMS, "Gemtek-Systems"},
{ SMI_BARRACUDA, "Barracuda Networks"},
{ SMI_ERICSSON_PKT_CORE, "Ericsson AB - Packet Core Networks"},
{ SMI_DACOM, "dacom"},
{ SMI_COLUMBIA_UNIVERSITY, "Columbia University"},
{ SMI_FORTINET, "Fortinet"},
{ SMI_VERIZON, "Verizon Wireless"},
{ SMI_PLIXER, "Plixer"},
{ SMI_WIFI_ALLIANCE, "Wi-Fi Alliance"},
{ SMI_T_SYSTEMS_NOVA, "T-Systems Nova"},
{ SMI_CHINATELECOM_GUANZHOU, "China Telecom - Guangzhou Research Institute"},
{ SMI_GIGAMON, "Gigamon Systems"},
{ SMI_CACE, "CACE Technologies"},
{ SMI_NTOP, "ntop"},
{ SMI_ERICSSON_CANADA_INC, "Ericsson Canada"},
{ 0, NULL}
};
diff --git a/contrib/tcpdump/parsenfsfh.c b/contrib/tcpdump/parsenfsfh.c
index cd9436992d77..15e9bcd01634 100644
--- a/contrib/tcpdump/parsenfsfh.c
+++ b/contrib/tcpdump/parsenfsfh.c
@@ -1,462 +1,449 @@
/*
* Copyright (c) 1993, 1994 Jeffrey C. Mogul, Digital Equipment Corporation,
* Western Research Laboratory. All rights reserved.
* Copyright (c) 2001 Compaq Computer Corporation. All rights reserved.
*
* Permission to use, copy, and modify this software and its
* documentation is hereby granted only under the following terms and
* conditions. Both the above copyright notice and this permission
* notice must appear in all copies of the software, derivative works
* or modified versions, and any portions thereof, and both notices
* must appear in supporting documentation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND COMPAQ COMPUTER CORPORATION
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
* EVENT SHALL COMPAQ COMPUTER CORPORATION BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
/*
* parsenfsfh.c - portable parser for NFS file handles
* uses all sorts of heuristics
*
* Jeffrey C. Mogul
* Digital Equipment Corporation
* Western Research Laboratory
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <stdio.h>
#include <string.h>
+#include <limits.h>
#include "netdissect-ctype.h"
#include "netdissect.h"
#include "extract.h"
#include "nfsfh.h"
/*
* This routine attempts to parse a file handle (in network byte order),
* using heuristics to guess what kind of format it is in. See the
* file "fhandle_layouts" for a detailed description of the various
* patterns we know about.
*
* The file handle is parsed into our internal representation of a
* file-system id, and an internal representation of an inode-number.
*/
#define FHT_UNKNOWN 0
#define FHT_AUSPEX 1
#define FHT_DECOSF 2
#define FHT_IRIX4 3
#define FHT_IRIX5 4
#define FHT_SUNOS3 5
#define FHT_SUNOS4 6
#define FHT_ULTRIX 7
#define FHT_VMSUCX 8
#define FHT_SUNOS5 9
#define FHT_AIX32 10
#define FHT_HPUX9 11
#define FHT_BSD44 12
static int is_UCX(netdissect_options *, const unsigned char *, u_int);
void
Parse_fh(netdissect_options *ndo, const unsigned char *fh, u_int len,
my_fsid *fsidp, uint32_t *inop,
const char **osnamep, /* if non-NULL, return OS name here */
const char **fsnamep, /* if non-NULL, return server fs name here (for VMS) */
int ourself) /* true if file handle was generated on this host */
{
const unsigned char *fhp = fh;
uint32_t temp;
int fhtype = FHT_UNKNOWN;
u_int i;
/*
* Require at least 16 bytes of file handle; it's variable-length
* in NFSv3. "len" is in units of 32-bit words, not bytes.
*/
if (len < 16/4)
fhtype = FHT_UNKNOWN;
else {
if (ourself) {
/* File handle generated on this host, no need for guessing */
#if defined(IRIX40)
fhtype = FHT_IRIX4;
#endif
#if defined(IRIX50)
fhtype = FHT_IRIX5;
#endif
#if defined(IRIX51)
fhtype = FHT_IRIX5;
#endif
#if defined(SUNOS4)
fhtype = FHT_SUNOS4;
#endif
#if defined(SUNOS5)
fhtype = FHT_SUNOS5;
#endif
#if defined(ultrix)
fhtype = FHT_ULTRIX;
#endif
#if defined(__osf__)
fhtype = FHT_DECOSF;
#endif
#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) \
|| defined(__OpenBSD__)
fhtype = FHT_BSD44;
#endif
}
/*
* This is basically a big decision tree
*/
else if ((GET_U_1(fhp) == 0) && (GET_U_1(fhp + 1) == 0)) {
/* bytes[0,1] == (0,0); rules out Ultrix, IRIX5, SUNOS5 */
/* probably rules out HP-UX, AIX unless they allow major=0 */
if ((GET_U_1(fhp + 2) == 0) && (GET_U_1(fhp + 3) == 0)) {
/* bytes[2,3] == (0,0); must be Auspex */
/* XXX or could be Ultrix+MASSBUS "hp" disk? */
fhtype = FHT_AUSPEX;
- }
- else {
+ } else {
/*
* bytes[2,3] != (0,0); rules out Auspex, could be
* DECOSF, SUNOS4, or IRIX4
*/
if ((GET_U_1(fhp + 4) != 0) && (GET_U_1(fhp + 5) == 0) &&
(GET_U_1(fhp + 8) == 12) && (GET_U_1(fhp + 9) == 0)) {
/* seems to be DECOSF, with minor == 0 */
fhtype = FHT_DECOSF;
- }
- else {
+ } else {
/* could be SUNOS4 or IRIX4 */
/* XXX the test of fhp[5] == 8 could be wrong */
if ((GET_U_1(fhp + 4) == 0) && (GET_U_1(fhp + 5) == 8) && (GET_U_1(fhp + 6) == 0) &&
(GET_U_1(fhp + 7) == 0)) {
/* looks like a length, not a file system typecode */
fhtype = FHT_IRIX4;
- }
- else {
+ } else {
/* by elimination */
fhtype = FHT_SUNOS4;
}
}
}
- }
- else {
+ } else {
/*
* bytes[0,1] != (0,0); rules out Auspex, IRIX4, SUNOS4
* could be IRIX5, DECOSF, UCX, Ultrix, SUNOS5
* could be AIX, HP-UX
*/
if ((GET_U_1(fhp + 2) == 0) && (GET_U_1(fhp + 3) == 0)) {
/*
* bytes[2,3] == (0,0); rules out OSF, probably not UCX
* (unless the exported device name is just one letter!),
* could be Ultrix, IRIX5, AIX, or SUNOS5
* might be HP-UX (depends on their values for minor devs)
*/
if ((GET_U_1(fhp + 6) == 0) && (GET_U_1(fhp + 7) == 0)) {
fhtype = FHT_BSD44;
}
/*XXX we probably only need to test of these two bytes */
else if ((len >= 24/4) && (GET_U_1(fhp + 21) == 0) && (GET_U_1(fhp + 23) == 0)) {
fhtype = FHT_ULTRIX;
- }
- else {
+ } else {
/* Could be SUNOS5/IRIX5, maybe AIX */
/* XXX no obvious difference between SUNOS5 and IRIX5 */
if (GET_U_1(fhp + 9) == 10)
fhtype = FHT_SUNOS5;
/* XXX what about AIX? */
}
- }
- else {
+ } else {
/*
* bytes[2,3] != (0,0); rules out Ultrix, could be
* DECOSF, SUNOS5, IRIX5, AIX, HP-UX, or UCX
*/
if ((GET_U_1(fhp + 8) == 12) && (GET_U_1(fhp + 9) == 0)) {
fhtype = FHT_DECOSF;
- }
- else if ((GET_U_1(fhp + 8) == 0) && (GET_U_1(fhp + 9) == 10)) {
+ } else if ((GET_U_1(fhp + 8) == 0) && (GET_U_1(fhp + 9) == 10)) {
/* could be SUNOS5/IRIX5, AIX, HP-UX */
if ((GET_U_1(fhp + 7) == 0) && (GET_U_1(fhp + 6) == 0) &&
(GET_U_1(fhp + 5) == 0) && (GET_U_1(fhp + 4) == 0)) {
/* XXX is this always true of HP-UX? */
fhtype = FHT_HPUX9;
- }
- else if (GET_U_1(fhp + 7) == 2) {
+ } else if (GET_U_1(fhp + 7) == 2) {
/* This would be MNT_NFS on AIX, which is impossible */
fhtype = FHT_SUNOS5; /* or maybe IRIX5 */
- }
- else {
+ } else {
/*
* XXX Could be SUNOS5/IRIX5 or AIX. I don't
* XXX see any way to disambiguate these, so
* XXX I'm going with the more likely guess.
* XXX Sorry, Big Blue.
*/
fhtype = FHT_SUNOS5; /* or maybe IRIX5 */
}
- }
- else {
+ } else {
if (is_UCX(ndo, fhp, len)) {
fhtype = FHT_VMSUCX;
- }
- else {
+ } else {
fhtype = FHT_UNKNOWN;
}
}
}
}
}
/* XXX still needs to handle SUNOS3 */
switch (fhtype) {
case FHT_AUSPEX:
fsidp->Fsid_dev.Minor = GET_U_1(fhp + 7);
fsidp->Fsid_dev.Major = GET_U_1(fhp + 6);
fsidp->fsid_code = 0;
*inop = GET_BE_U_4(fhp + 12);
if (osnamep)
*osnamep = "Auspex";
break;
case FHT_BSD44:
fsidp->Fsid_dev.Minor = GET_U_1(fhp);
fsidp->Fsid_dev.Major = GET_U_1(fhp + 1);
fsidp->fsid_code = 0;
*inop = GET_LE_U_4(fhp + 12);
if (osnamep)
*osnamep = "BSD 4.4";
break;
case FHT_DECOSF:
fsidp->fsid_code = GET_LE_U_4(fhp + 4);
/* XXX could ignore 3 high-order bytes */
temp = GET_LE_U_4(fhp);
fsidp->Fsid_dev.Minor = temp & 0xFFFFF;
fsidp->Fsid_dev.Major = (temp>>20) & 0xFFF;
*inop = GET_LE_U_4(fhp + 12);
if (osnamep)
*osnamep = "OSF";
break;
case FHT_IRIX4:
fsidp->Fsid_dev.Minor = GET_U_1(fhp + 3);
fsidp->Fsid_dev.Major = GET_U_1(fhp + 2);
fsidp->fsid_code = 0;
*inop = GET_BE_U_4(fhp + 8);
if (osnamep)
*osnamep = "IRIX4";
break;
case FHT_IRIX5:
fsidp->Fsid_dev.Minor = GET_BE_U_2(fhp + 2);
fsidp->Fsid_dev.Major = GET_BE_U_2(fhp);
fsidp->fsid_code = GET_BE_U_4(fhp + 4);
*inop = GET_BE_U_4(fhp + 12);
if (osnamep)
*osnamep = "IRIX5";
break;
#ifdef notdef
case FHT_SUNOS3:
/*
* XXX - none of the heuristics above return this.
* Are there any SunOS 3.x systems around to care about?
*/
if (osnamep)
*osnamep = "SUNOS3";
break;
#endif
case FHT_SUNOS4:
fsidp->Fsid_dev.Minor = GET_U_1(fhp + 3);
fsidp->Fsid_dev.Major = GET_U_1(fhp + 2);
fsidp->fsid_code = GET_BE_U_4(fhp + 4);
*inop = GET_BE_U_4(fhp + 12);
if (osnamep)
*osnamep = "SUNOS4";
break;
case FHT_SUNOS5:
temp = GET_BE_U_2(fhp);
fsidp->Fsid_dev.Major = (temp>>2) & 0x3FFF;
temp = GET_BE_U_3(fhp + 1);
fsidp->Fsid_dev.Minor = temp & 0x3FFFF;
fsidp->fsid_code = GET_BE_U_4(fhp + 4);
*inop = GET_BE_U_4(fhp + 12);
if (osnamep)
*osnamep = "SUNOS5";
break;
case FHT_ULTRIX:
fsidp->fsid_code = 0;
fsidp->Fsid_dev.Minor = GET_U_1(fhp);
fsidp->Fsid_dev.Major = GET_U_1(fhp + 1);
temp = GET_LE_U_4(fhp + 4);
*inop = temp;
if (osnamep)
*osnamep = "Ultrix";
break;
case FHT_VMSUCX:
/* No numeric file system ID, so hash on the device-name */
if (sizeof(*fsidp) >= 14) {
if (sizeof(*fsidp) > 14)
memset((char *)fsidp, 0, sizeof(*fsidp));
/* just use the whole thing */
memcpy((char *)fsidp, (const char *)fh, 14);
- }
- else {
+ } else {
uint32_t tempa[4]; /* at least 16 bytes, maybe more */
memset((char *)tempa, 0, sizeof(tempa));
memcpy((char *)tempa, (const char *)fh, 14); /* ensure alignment */
fsidp->Fsid_dev.Minor = tempa[0] + (tempa[1]<<1);
fsidp->Fsid_dev.Major = tempa[2] + (tempa[3]<<1);
fsidp->fsid_code = 0;
}
/* VMS file ID is: (RVN, FidHi, FidLo) */
*inop = (((uint32_t) GET_U_1(fhp + 26)) << 24) |
(((uint32_t) GET_U_1(fhp + 27)) << 16) |
(GET_LE_U_2(fhp + 22) << 0);
/* Caller must save (and null-terminate?) this value */
if (fsnamep)
*fsnamep = (const char *)(fhp + 1);
if (osnamep)
*osnamep = "VMS";
break;
case FHT_AIX32:
fsidp->Fsid_dev.Minor = GET_BE_U_2(fhp + 2);
fsidp->Fsid_dev.Major = GET_BE_U_2(fhp);
fsidp->fsid_code = GET_BE_U_4(fhp + 4);
*inop = GET_BE_U_4(fhp + 12);
if (osnamep)
*osnamep = "AIX32";
break;
case FHT_HPUX9:
fsidp->Fsid_dev.Major = GET_U_1(fhp);
temp = GET_BE_U_3(fhp + 1);
fsidp->Fsid_dev.Minor = temp;
fsidp->fsid_code = GET_BE_U_4(fhp + 4);
*inop = GET_BE_U_4(fhp + 12);
if (osnamep)
*osnamep = "HPUX9";
break;
case FHT_UNKNOWN:
#ifdef DEBUG
/* XXX debugging */
for (i = 0; i < len*4; i++)
(void)fprintf(stderr, "%x.", GET_U_1(fhp + i));
(void)fprintf(stderr, "\n");
#endif
/* Save the actual handle, so it can be display with -u */
+ /* XXX really ? When -u is used this function is not called */
for (i = 0; i < len*4 && i*2 < sizeof(fsidp->Opaque_Handle) - 1; i++)
(void)snprintf(&(fsidp->Opaque_Handle[i*2]), 3, "%.2X",
GET_U_1(fhp + i));
fsidp->Opaque_Handle[i*2] = '\0';
/* XXX for now, give "bogus" values to aid debugging */
fsidp->fsid_code = 0;
- fsidp->Fsid_dev.Minor = 257;
- fsidp->Fsid_dev.Major = 257;
+ fsidp->Fsid_dev.Minor = UINT_MAX;
+ fsidp->Fsid_dev.Major = UINT_MAX;
*inop = 1;
- /* display will show this string instead of (257,257) */
+ /* display will show this string instead of (UINT_MAX,UINT_MAX) */
+ /* XXX really ? */
if (fsnamep)
*fsnamep = "Unknown";
if (osnamep)
*osnamep = "Unknown";
break;
}
}
/*
* Is this a VMS UCX file handle?
* Check for:
* (1) leading code byte [XXX not yet]
* (2) followed by string of printing chars & spaces
* (3) followed by string of nulls
*/
static int
is_UCX(netdissect_options *ndo, const unsigned char *fhp, u_int len)
{
u_int i;
int seen_null = 0;
/*
* Require at least 28 bytes of file handle; it's variable-length
* in NFSv3. "len" is in units of 32-bit words, not bytes.
*/
if (len < 28/4)
return(0);
for (i = 1; i < 14; i++) {
if (ND_ASCII_ISPRINT(GET_U_1(fhp + i))) {
if (seen_null)
return(0);
else
continue;
- }
- else if (GET_U_1(fhp + i) == 0) {
+ } else if (GET_U_1(fhp + i) == 0) {
seen_null = 1;
continue;
- }
- else
+ } else
return(0);
}
return(1);
}
diff --git a/contrib/tcpdump/pflog.h b/contrib/tcpdump/pflog.h
index aae7d06f746f..f5ffebf50b4a 100644
--- a/contrib/tcpdump/pflog.h
+++ b/contrib/tcpdump/pflog.h
@@ -1,152 +1,151 @@
/*
* Copyright (c) 1982, 1986, 1993
* 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 the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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 BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* pflog headers, at least as they exist now.
*/
#define PFLOG_IFNAMSIZ 16
#define PFLOG_RULESET_NAME_SIZE 16
/*
* Direction values.
*/
#define PF_INOUT 0
#define PF_IN 1
#define PF_OUT 2
#if defined(__OpenBSD__)
#define PF_FWD 3
#endif
/*
* Reason values.
*/
#define PFRES_MATCH 0
#define PFRES_BADOFF 1
#define PFRES_FRAG 2
#define PFRES_SHORT 3
#define PFRES_NORM 4
#define PFRES_MEMORY 5
#define PFRES_TS 6
#define PFRES_CONGEST 7
#define PFRES_IPOPTIONS 8
#define PFRES_PROTCKSUM 9
#define PFRES_BADSTATE 10
#define PFRES_STATEINS 11
#define PFRES_MAXSTATES 12
#define PFRES_SRCLIMIT 13
#define PFRES_SYNPROXY 14
#if defined(__FreeBSD__)
#define PFRES_MAPFAILED 15
#elif defined(__NetBSD__)
#define PFRES_STATELOCKED 15
#elif defined(__OpenBSD__)
#define PFRES_TRANSLATE 15
#define PFRES_NOROUTE 16
#elif defined(__APPLE__)
#define PFRES_DUMMYNET 15
#endif
/*
* Action values.
*/
#define PF_PASS 0
#define PF_DROP 1
#define PF_SCRUB 2
#define PF_NOSCRUB 3
#define PF_NAT 4
#define PF_NONAT 5
#define PF_BINAT 6
#define PF_NOBINAT 7
#define PF_RDR 8
#define PF_NORDR 9
#define PF_SYNPROXY_DROP 10
#if defined(__FreeBSD__)
#define PF_DEFER 11
#define PF_MATCH 12
#elif defined(__OpenBSD__)
#define PF_DEFER 11
#define PF_MATCH 12
#define PF_DIVERT 13
#define PF_RT 14
#define PF_AFRT 15
#elif defined(__APPLE__)
#define PF_DUMMYNET 11
#define PF_NODUMMYNET 12
#define PF_NAT64 13
#define PF_NONAT64 14
#endif
struct pf_addr {
union {
nd_ipv4 v4;
nd_ipv6 v6;
} pfa; /* 128-bit address */
#define v4 pfa.v4
#define v6 pfa.v6
};
struct pfloghdr {
- uint8_t length;
- uint8_t af;
- uint8_t action;
- uint8_t reason;
+ nd_uint8_t length;
+ nd_uint8_t af;
+ nd_uint8_t action;
+ nd_uint8_t reason;
char ifname[PFLOG_IFNAMSIZ];
char ruleset[PFLOG_RULESET_NAME_SIZE];
- uint32_t rulenr;
- uint32_t subrulenr;
- uint32_t uid;
- int32_t pid;
- uint32_t rule_uid;
- int32_t rule_pid;
- uint8_t dir;
+ nd_uint32_t rulenr;
+ nd_uint32_t subrulenr;
+ nd_uint32_t uid;
+ nd_int32_t pid;
+ nd_uint32_t rule_uid;
+ nd_int32_t rule_pid;
+ nd_uint8_t dir;
+/* Minimum header length (without padding): 61 */
+#define MIN_PFLOG_HDRLEN 61
#if defined(__OpenBSD__)
- uint8_t rewritten;
- uint8_t naf;
- uint8_t pad[1];
+ nd_uint8_t rewritten;
+ nd_uint8_t naf;
+ nd_uint8_t pad[1];
#else
- uint8_t pad[3];
+ nd_uint8_t pad[3];
#endif
#if defined(__FreeBSD__)
- uint32_t ridentifier;
- uint8_t reserve;
- uint8_t pad2[3];
+ nd_uint32_t ridentifier;
+ nd_uint8_t reserve;
+ nd_uint8_t pad2[3];
#elif defined(__OpenBSD__)
struct pf_addr saddr;
struct pf_addr daddr;
- uint16_t sport;
- uint16_t dport;
+ nd_uint16_t sport;
+ nd_uint16_t dport;
#endif
};
-
-
-
diff --git a/contrib/tcpdump/print-802_11.c b/contrib/tcpdump/print-802_11.c
index 737b15028a67..31c23bfca02f 100644
--- a/contrib/tcpdump/print-802_11.c
+++ b/contrib/tcpdump/print-802_11.c
@@ -1,3533 +1,3527 @@
/*
* Copyright (c) 2001
* Fortress Technologies, Inc. All rights reserved.
* Charlie Lenahan (clenahan@fortresstech.com)
*
* 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.
*/
/* \summary: IEEE 802.11 printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <string.h>
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#include "cpack.h"
/* Lengths of 802.11 header components. */
#define IEEE802_11_FC_LEN 2
#define IEEE802_11_DUR_LEN 2
#define IEEE802_11_DA_LEN 6
#define IEEE802_11_SA_LEN 6
#define IEEE802_11_BSSID_LEN 6
#define IEEE802_11_RA_LEN 6
#define IEEE802_11_TA_LEN 6
#define IEEE802_11_ADDR1_LEN 6
#define IEEE802_11_SEQ_LEN 2
#define IEEE802_11_CTL_LEN 2
#define IEEE802_11_CARRIED_FC_LEN 2
#define IEEE802_11_HT_CONTROL_LEN 4
#define IEEE802_11_IV_LEN 3
#define IEEE802_11_KID_LEN 1
/* Frame check sequence length. */
#define IEEE802_11_FCS_LEN 4
/* Lengths of beacon components. */
#define IEEE802_11_TSTAMP_LEN 8
#define IEEE802_11_BCNINT_LEN 2
#define IEEE802_11_CAPINFO_LEN 2
#define IEEE802_11_LISTENINT_LEN 2
#define IEEE802_11_AID_LEN 2
#define IEEE802_11_STATUS_LEN 2
#define IEEE802_11_REASON_LEN 2
-/* Length of previous AP in reassocation frame */
+/* Length of previous AP in reassociation frame */
#define IEEE802_11_AP_LEN 6
#define T_MGMT 0x0 /* management */
#define T_CTRL 0x1 /* control */
#define T_DATA 0x2 /* data */
#define T_RESV 0x3 /* reserved */
#define ST_ASSOC_REQUEST 0x0
#define ST_ASSOC_RESPONSE 0x1
#define ST_REASSOC_REQUEST 0x2
#define ST_REASSOC_RESPONSE 0x3
#define ST_PROBE_REQUEST 0x4
#define ST_PROBE_RESPONSE 0x5
/* RESERVED 0x6 */
/* RESERVED 0x7 */
#define ST_BEACON 0x8
#define ST_ATIM 0x9
#define ST_DISASSOC 0xA
#define ST_AUTH 0xB
#define ST_DEAUTH 0xC
#define ST_ACTION 0xD
/* RESERVED 0xE */
/* RESERVED 0xF */
static const struct tok st_str[] = {
{ ST_ASSOC_REQUEST, "Assoc Request" },
{ ST_ASSOC_RESPONSE, "Assoc Response" },
{ ST_REASSOC_REQUEST, "ReAssoc Request" },
{ ST_REASSOC_RESPONSE, "ReAssoc Response" },
{ ST_PROBE_REQUEST, "Probe Request" },
{ ST_PROBE_RESPONSE, "Probe Response" },
{ ST_BEACON, "Beacon" },
{ ST_ATIM, "ATIM" },
{ ST_DISASSOC, "Disassociation" },
{ ST_AUTH, "Authentication" },
{ ST_DEAUTH, "DeAuthentication" },
{ ST_ACTION, "Action" },
{ 0, NULL }
};
#define CTRL_CONTROL_WRAPPER 0x7
#define CTRL_BAR 0x8
#define CTRL_BA 0x9
#define CTRL_PS_POLL 0xA
#define CTRL_RTS 0xB
#define CTRL_CTS 0xC
#define CTRL_ACK 0xD
#define CTRL_CF_END 0xE
#define CTRL_END_ACK 0xF
static const struct tok ctrl_str[] = {
{ CTRL_CONTROL_WRAPPER, "Control Wrapper" },
{ CTRL_BAR, "BAR" },
{ CTRL_BA, "BA" },
{ CTRL_PS_POLL, "Power Save-Poll" },
{ CTRL_RTS, "Request-To-Send" },
{ CTRL_CTS, "Clear-To-Send" },
{ CTRL_ACK, "Acknowledgment" },
{ CTRL_CF_END, "CF-End" },
{ CTRL_END_ACK, "CF-End+CF-Ack" },
{ 0, NULL }
};
#define DATA_DATA 0x0
#define DATA_DATA_CF_ACK 0x1
#define DATA_DATA_CF_POLL 0x2
#define DATA_DATA_CF_ACK_POLL 0x3
#define DATA_NODATA 0x4
#define DATA_NODATA_CF_ACK 0x5
#define DATA_NODATA_CF_POLL 0x6
#define DATA_NODATA_CF_ACK_POLL 0x7
#define DATA_QOS_DATA 0x8
#define DATA_QOS_DATA_CF_ACK 0x9
#define DATA_QOS_DATA_CF_POLL 0xA
#define DATA_QOS_DATA_CF_ACK_POLL 0xB
#define DATA_QOS_NODATA 0xC
#define DATA_QOS_CF_POLL_NODATA 0xE
#define DATA_QOS_CF_ACK_POLL_NODATA 0xF
/*
* The subtype field of a data frame is, in effect, composed of 4 flag
* bits - CF-Ack, CF-Poll, Null (means the frame doesn't actually have
* any data), and QoS.
*/
#define DATA_FRAME_IS_CF_ACK(x) ((x) & 0x01)
#define DATA_FRAME_IS_CF_POLL(x) ((x) & 0x02)
#define DATA_FRAME_IS_NULL(x) ((x) & 0x04)
#define DATA_FRAME_IS_QOS(x) ((x) & 0x08)
/*
* Bits in the frame control field.
*/
#define FC_VERSION(fc) ((fc) & 0x3)
#define FC_TYPE(fc) (((fc) >> 2) & 0x3)
#define FC_SUBTYPE(fc) (((fc) >> 4) & 0xF)
#define FC_TO_DS(fc) ((fc) & 0x0100)
#define FC_FROM_DS(fc) ((fc) & 0x0200)
#define FC_MORE_FLAG(fc) ((fc) & 0x0400)
#define FC_RETRY(fc) ((fc) & 0x0800)
#define FC_POWER_MGMT(fc) ((fc) & 0x1000)
#define FC_MORE_DATA(fc) ((fc) & 0x2000)
#define FC_PROTECTED(fc) ((fc) & 0x4000)
#define FC_ORDER(fc) ((fc) & 0x8000)
struct mgmt_header_t {
nd_uint16_t fc;
nd_uint16_t duration;
nd_mac_addr da;
nd_mac_addr sa;
nd_mac_addr bssid;
nd_uint16_t seq_ctrl;
};
#define MGMT_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
IEEE802_11_DA_LEN+IEEE802_11_SA_LEN+\
IEEE802_11_BSSID_LEN+IEEE802_11_SEQ_LEN)
#define CAPABILITY_ESS(cap) ((cap) & 0x0001)
#define CAPABILITY_IBSS(cap) ((cap) & 0x0002)
#define CAPABILITY_CFP(cap) ((cap) & 0x0004)
#define CAPABILITY_CFP_REQ(cap) ((cap) & 0x0008)
#define CAPABILITY_PRIVACY(cap) ((cap) & 0x0010)
struct ssid_t {
- uint8_t element_id;
- uint8_t length;
+ u_int length;
u_char ssid[33]; /* 32 + 1 for null */
};
struct rates_t {
- uint8_t element_id;
- uint8_t length;
+ u_int length;
uint8_t rate[16];
};
struct challenge_t {
- uint8_t element_id;
- uint8_t length;
+ u_int length;
uint8_t text[254]; /* 1-253 + 1 for null */
};
struct fh_t {
- uint8_t element_id;
- uint8_t length;
+ u_int length;
uint16_t dwell_time;
uint8_t hop_set;
uint8_t hop_pattern;
uint8_t hop_index;
};
struct ds_t {
- uint8_t element_id;
- uint8_t length;
+ u_int length;
uint8_t channel;
};
struct cf_t {
- uint8_t element_id;
- uint8_t length;
+ u_int length;
uint8_t count;
uint8_t period;
uint16_t max_duration;
uint16_t dur_remaining;
};
struct tim_t {
- uint8_t element_id;
- uint8_t length;
+ u_int length;
uint8_t count;
uint8_t period;
uint8_t bitmap_control;
uint8_t bitmap[251];
};
#define E_SSID 0
#define E_RATES 1
#define E_FH 2
#define E_DS 3
#define E_CF 4
#define E_TIM 5
#define E_IBSS 6
/* reserved 7 */
/* reserved 8 */
/* reserved 9 */
/* reserved 10 */
/* reserved 11 */
/* reserved 12 */
/* reserved 13 */
/* reserved 14 */
/* reserved 15 */
/* reserved 16 */
#define E_CHALLENGE 16
/* reserved 17 */
/* reserved 18 */
/* reserved 19 */
/* reserved 16 */
/* reserved 16 */
struct mgmt_body_t {
uint8_t timestamp[IEEE802_11_TSTAMP_LEN];
uint16_t beacon_interval;
uint16_t listen_interval;
uint16_t status_code;
uint16_t aid;
u_char ap[IEEE802_11_AP_LEN];
uint16_t reason_code;
uint16_t auth_alg;
uint16_t auth_trans_seq_num;
int challenge_present;
struct challenge_t challenge;
uint16_t capability_info;
int ssid_present;
struct ssid_t ssid;
int rates_present;
struct rates_t rates;
int ds_present;
struct ds_t ds;
int cf_present;
struct cf_t cf;
int fh_present;
struct fh_t fh;
int tim_present;
struct tim_t tim;
};
struct ctrl_control_wrapper_hdr_t {
nd_uint16_t fc;
nd_uint16_t duration;
nd_mac_addr addr1;
nd_uint16_t carried_fc[IEEE802_11_CARRIED_FC_LEN];
nd_uint16_t ht_control[IEEE802_11_HT_CONTROL_LEN];
};
#define CTRL_CONTROL_WRAPPER_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
IEEE802_11_ADDR1_LEN+\
IEEE802_11_CARRIED_FC_LEN+\
IEEE802_11_HT_CONTROL_LEN)
struct ctrl_rts_hdr_t {
nd_uint16_t fc;
nd_uint16_t duration;
nd_mac_addr ra;
nd_mac_addr ta;
};
#define CTRL_RTS_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
IEEE802_11_RA_LEN+IEEE802_11_TA_LEN)
struct ctrl_cts_hdr_t {
nd_uint16_t fc;
nd_uint16_t duration;
nd_mac_addr ra;
};
#define CTRL_CTS_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+IEEE802_11_RA_LEN)
struct ctrl_ack_hdr_t {
nd_uint16_t fc;
nd_uint16_t duration;
nd_mac_addr ra;
};
#define CTRL_ACK_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+IEEE802_11_RA_LEN)
struct ctrl_ps_poll_hdr_t {
nd_uint16_t fc;
nd_uint16_t aid;
nd_mac_addr bssid;
nd_mac_addr ta;
};
#define CTRL_PS_POLL_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_AID_LEN+\
IEEE802_11_BSSID_LEN+IEEE802_11_TA_LEN)
struct ctrl_end_hdr_t {
nd_uint16_t fc;
nd_uint16_t duration;
nd_mac_addr ra;
nd_mac_addr bssid;
};
#define CTRL_END_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
IEEE802_11_RA_LEN+IEEE802_11_BSSID_LEN)
struct ctrl_end_ack_hdr_t {
nd_uint16_t fc;
nd_uint16_t duration;
nd_mac_addr ra;
nd_mac_addr bssid;
};
#define CTRL_END_ACK_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
IEEE802_11_RA_LEN+IEEE802_11_BSSID_LEN)
struct ctrl_ba_hdr_t {
nd_uint16_t fc;
nd_uint16_t duration;
nd_mac_addr ra;
+ nd_mac_addr ta;
};
-#define CTRL_BA_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+IEEE802_11_RA_LEN)
+#define CTRL_BA_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
+ IEEE802_11_RA_LEN+IEEE802_11_TA_LEN)
struct ctrl_bar_hdr_t {
nd_uint16_t fc;
nd_uint16_t dur;
nd_mac_addr ra;
nd_mac_addr ta;
nd_uint16_t ctl;
nd_uint16_t seq;
};
#define CTRL_BAR_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
IEEE802_11_RA_LEN+IEEE802_11_TA_LEN+\
IEEE802_11_CTL_LEN+IEEE802_11_SEQ_LEN)
struct meshcntl_t {
nd_uint8_t flags;
nd_uint8_t ttl;
nd_uint32_t seq;
nd_mac_addr addr4;
nd_mac_addr addr5;
nd_mac_addr addr6;
};
#define IV_IV(iv) ((iv) & 0xFFFFFF)
#define IV_PAD(iv) (((iv) >> 24) & 0x3F)
#define IV_KEYID(iv) (((iv) >> 30) & 0x03)
#define PRINT_SSID(p) \
if (p.ssid_present) { \
ND_PRINT(" ("); \
fn_print_str(ndo, p.ssid.ssid); \
ND_PRINT(")"); \
}
#define PRINT_RATE(_sep, _r, _suf) \
ND_PRINT("%s%2.1f%s", _sep, (.5 * ((_r) & 0x7f)), _suf)
#define PRINT_RATES(p) \
if (p.rates_present) { \
- int z; \
const char *sep = " ["; \
- for (z = 0; z < p.rates.length ; z++) { \
- PRINT_RATE(sep, p.rates.rate[z], \
- (p.rates.rate[z] & 0x80 ? "*" : "")); \
- sep = " "; \
- } \
- if (p.rates.length != 0) \
+ if (p.rates.length != 0) { \
+ for (u_int z = 0; z < p.rates.length ; z++) { \
+ PRINT_RATE(sep, p.rates.rate[z], \
+ (p.rates.rate[z] & 0x80 ? "*" : "")); \
+ sep = " "; \
+ } \
ND_PRINT(" Mbit]"); \
+ } \
}
#define PRINT_DS_CHANNEL(p) \
if (p.ds_present) \
ND_PRINT(" CH: %u", p.ds.channel); \
ND_PRINT("%s", \
CAPABILITY_PRIVACY(p.capability_info) ? ", PRIVACY" : "");
#define MAX_MCS_INDEX 76
/*
* Indices are:
*
* the MCS index (0-76);
*
* 0 for 20 MHz, 1 for 40 MHz;
*
* 0 for a long guard interval, 1 for a short guard interval.
*/
static const float ieee80211_float_htrates[MAX_MCS_INDEX+1][2][2] = {
/* MCS 0 */
{ /* 20 Mhz */ { 6.5f, /* SGI */ 7.2f, },
/* 40 Mhz */ { 13.5f, /* SGI */ 15.0f, },
},
/* MCS 1 */
{ /* 20 Mhz */ { 13.0f, /* SGI */ 14.4f, },
/* 40 Mhz */ { 27.0f, /* SGI */ 30.0f, },
},
/* MCS 2 */
{ /* 20 Mhz */ { 19.5f, /* SGI */ 21.7f, },
/* 40 Mhz */ { 40.5f, /* SGI */ 45.0f, },
},
/* MCS 3 */
{ /* 20 Mhz */ { 26.0f, /* SGI */ 28.9f, },
/* 40 Mhz */ { 54.0f, /* SGI */ 60.0f, },
},
/* MCS 4 */
{ /* 20 Mhz */ { 39.0f, /* SGI */ 43.3f, },
/* 40 Mhz */ { 81.0f, /* SGI */ 90.0f, },
},
/* MCS 5 */
{ /* 20 Mhz */ { 52.0f, /* SGI */ 57.8f, },
/* 40 Mhz */ { 108.0f, /* SGI */ 120.0f, },
},
/* MCS 6 */
{ /* 20 Mhz */ { 58.5f, /* SGI */ 65.0f, },
/* 40 Mhz */ { 121.5f, /* SGI */ 135.0f, },
},
/* MCS 7 */
{ /* 20 Mhz */ { 65.0f, /* SGI */ 72.2f, },
/* 40 Mhz */ { 135.0f, /* SGI */ 150.0f, },
},
/* MCS 8 */
{ /* 20 Mhz */ { 13.0f, /* SGI */ 14.4f, },
/* 40 Mhz */ { 27.0f, /* SGI */ 30.0f, },
},
/* MCS 9 */
{ /* 20 Mhz */ { 26.0f, /* SGI */ 28.9f, },
/* 40 Mhz */ { 54.0f, /* SGI */ 60.0f, },
},
/* MCS 10 */
{ /* 20 Mhz */ { 39.0f, /* SGI */ 43.3f, },
/* 40 Mhz */ { 81.0f, /* SGI */ 90.0f, },
},
/* MCS 11 */
{ /* 20 Mhz */ { 52.0f, /* SGI */ 57.8f, },
/* 40 Mhz */ { 108.0f, /* SGI */ 120.0f, },
},
/* MCS 12 */
{ /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, },
/* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, },
},
/* MCS 13 */
{ /* 20 Mhz */ { 104.0f, /* SGI */ 115.6f, },
/* 40 Mhz */ { 216.0f, /* SGI */ 240.0f, },
},
/* MCS 14 */
{ /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, },
/* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, },
},
/* MCS 15 */
{ /* 20 Mhz */ { 130.0f, /* SGI */ 144.4f, },
/* 40 Mhz */ { 270.0f, /* SGI */ 300.0f, },
},
/* MCS 16 */
{ /* 20 Mhz */ { 19.5f, /* SGI */ 21.7f, },
/* 40 Mhz */ { 40.5f, /* SGI */ 45.0f, },
},
/* MCS 17 */
{ /* 20 Mhz */ { 39.0f, /* SGI */ 43.3f, },
/* 40 Mhz */ { 81.0f, /* SGI */ 90.0f, },
},
/* MCS 18 */
{ /* 20 Mhz */ { 58.5f, /* SGI */ 65.0f, },
/* 40 Mhz */ { 121.5f, /* SGI */ 135.0f, },
},
/* MCS 19 */
{ /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, },
/* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, },
},
/* MCS 20 */
{ /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, },
/* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, },
},
/* MCS 21 */
{ /* 20 Mhz */ { 156.0f, /* SGI */ 173.3f, },
/* 40 Mhz */ { 324.0f, /* SGI */ 360.0f, },
},
/* MCS 22 */
{ /* 20 Mhz */ { 175.5f, /* SGI */ 195.0f, },
/* 40 Mhz */ { 364.5f, /* SGI */ 405.0f, },
},
/* MCS 23 */
{ /* 20 Mhz */ { 195.0f, /* SGI */ 216.7f, },
/* 40 Mhz */ { 405.0f, /* SGI */ 450.0f, },
},
/* MCS 24 */
{ /* 20 Mhz */ { 26.0f, /* SGI */ 28.9f, },
/* 40 Mhz */ { 54.0f, /* SGI */ 60.0f, },
},
/* MCS 25 */
{ /* 20 Mhz */ { 52.0f, /* SGI */ 57.8f, },
/* 40 Mhz */ { 108.0f, /* SGI */ 120.0f, },
},
/* MCS 26 */
{ /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, },
/* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, },
},
/* MCS 27 */
{ /* 20 Mhz */ { 104.0f, /* SGI */ 115.6f, },
/* 40 Mhz */ { 216.0f, /* SGI */ 240.0f, },
},
/* MCS 28 */
{ /* 20 Mhz */ { 156.0f, /* SGI */ 173.3f, },
/* 40 Mhz */ { 324.0f, /* SGI */ 360.0f, },
},
/* MCS 29 */
{ /* 20 Mhz */ { 208.0f, /* SGI */ 231.1f, },
/* 40 Mhz */ { 432.0f, /* SGI */ 480.0f, },
},
/* MCS 30 */
{ /* 20 Mhz */ { 234.0f, /* SGI */ 260.0f, },
/* 40 Mhz */ { 486.0f, /* SGI */ 540.0f, },
},
/* MCS 31 */
{ /* 20 Mhz */ { 260.0f, /* SGI */ 288.9f, },
/* 40 Mhz */ { 540.0f, /* SGI */ 600.0f, },
},
/* MCS 32 */
{ /* 20 Mhz */ { 0.0f, /* SGI */ 0.0f, }, /* not valid */
/* 40 Mhz */ { 6.0f, /* SGI */ 6.7f, },
},
/* MCS 33 */
{ /* 20 Mhz */ { 39.0f, /* SGI */ 43.3f, },
/* 40 Mhz */ { 81.0f, /* SGI */ 90.0f, },
},
/* MCS 34 */
{ /* 20 Mhz */ { 52.0f, /* SGI */ 57.8f, },
/* 40 Mhz */ { 108.0f, /* SGI */ 120.0f, },
},
/* MCS 35 */
{ /* 20 Mhz */ { 65.0f, /* SGI */ 72.2f, },
/* 40 Mhz */ { 135.0f, /* SGI */ 150.0f, },
},
/* MCS 36 */
{ /* 20 Mhz */ { 58.5f, /* SGI */ 65.0f, },
/* 40 Mhz */ { 121.5f, /* SGI */ 135.0f, },
},
/* MCS 37 */
{ /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, },
/* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, },
},
/* MCS 38 */
{ /* 20 Mhz */ { 97.5f, /* SGI */ 108.3f, },
/* 40 Mhz */ { 202.5f, /* SGI */ 225.0f, },
},
/* MCS 39 */
{ /* 20 Mhz */ { 52.0f, /* SGI */ 57.8f, },
/* 40 Mhz */ { 108.0f, /* SGI */ 120.0f, },
},
/* MCS 40 */
{ /* 20 Mhz */ { 65.0f, /* SGI */ 72.2f, },
/* 40 Mhz */ { 135.0f, /* SGI */ 150.0f, },
},
/* MCS 41 */
{ /* 20 Mhz */ { 65.0f, /* SGI */ 72.2f, },
/* 40 Mhz */ { 135.0f, /* SGI */ 150.0f, },
},
/* MCS 42 */
{ /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, },
/* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, },
},
/* MCS 43 */
{ /* 20 Mhz */ { 91.0f, /* SGI */ 101.1f, },
/* 40 Mhz */ { 189.0f, /* SGI */ 210.0f, },
},
/* MCS 44 */
{ /* 20 Mhz */ { 91.0f, /* SGI */ 101.1f, },
/* 40 Mhz */ { 189.0f, /* SGI */ 210.0f, },
},
/* MCS 45 */
{ /* 20 Mhz */ { 104.0f, /* SGI */ 115.6f, },
/* 40 Mhz */ { 216.0f, /* SGI */ 240.0f, },
},
/* MCS 46 */
{ /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, },
/* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, },
},
/* MCS 47 */
{ /* 20 Mhz */ { 97.5f, /* SGI */ 108.3f, },
/* 40 Mhz */ { 202.5f, /* SGI */ 225.0f, },
},
/* MCS 48 */
{ /* 20 Mhz */ { 97.5f, /* SGI */ 108.3f, },
/* 40 Mhz */ { 202.5f, /* SGI */ 225.0f, },
},
/* MCS 49 */
{ /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, },
/* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, },
},
/* MCS 50 */
{ /* 20 Mhz */ { 136.5f, /* SGI */ 151.7f, },
/* 40 Mhz */ { 283.5f, /* SGI */ 315.0f, },
},
/* MCS 51 */
{ /* 20 Mhz */ { 136.5f, /* SGI */ 151.7f, },
/* 40 Mhz */ { 283.5f, /* SGI */ 315.0f, },
},
/* MCS 52 */
{ /* 20 Mhz */ { 156.0f, /* SGI */ 173.3f, },
/* 40 Mhz */ { 324.0f, /* SGI */ 360.0f, },
},
/* MCS 53 */
{ /* 20 Mhz */ { 65.0f, /* SGI */ 72.2f, },
/* 40 Mhz */ { 135.0f, /* SGI */ 150.0f, },
},
/* MCS 54 */
{ /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, },
/* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, },
},
/* MCS 55 */
{ /* 20 Mhz */ { 91.0f, /* SGI */ 101.1f, },
/* 40 Mhz */ { 189.0f, /* SGI */ 210.0f, },
},
/* MCS 56 */
{ /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, },
/* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, },
},
/* MCS 57 */
{ /* 20 Mhz */ { 91.0f, /* SGI */ 101.1f, },
/* 40 Mhz */ { 189.0f, /* SGI */ 210.0f, },
},
/* MCS 58 */
{ /* 20 Mhz */ { 104.0f, /* SGI */ 115.6f, },
/* 40 Mhz */ { 216.0f, /* SGI */ 240.0f, },
},
/* MCS 59 */
{ /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, },
/* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, },
},
/* MCS 60 */
{ /* 20 Mhz */ { 104.0f, /* SGI */ 115.6f, },
/* 40 Mhz */ { 216.0f, /* SGI */ 240.0f, },
},
/* MCS 61 */
{ /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, },
/* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, },
},
/* MCS 62 */
{ /* 20 Mhz */ { 130.0f, /* SGI */ 144.4f, },
/* 40 Mhz */ { 270.0f, /* SGI */ 300.0f, },
},
/* MCS 63 */
{ /* 20 Mhz */ { 130.0f, /* SGI */ 144.4f, },
/* 40 Mhz */ { 270.0f, /* SGI */ 300.0f, },
},
/* MCS 64 */
{ /* 20 Mhz */ { 143.0f, /* SGI */ 158.9f, },
/* 40 Mhz */ { 297.0f, /* SGI */ 330.0f, },
},
/* MCS 65 */
{ /* 20 Mhz */ { 97.5f, /* SGI */ 108.3f, },
/* 40 Mhz */ { 202.5f, /* SGI */ 225.0f, },
},
/* MCS 66 */
{ /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, },
/* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, },
},
/* MCS 67 */
{ /* 20 Mhz */ { 136.5f, /* SGI */ 151.7f, },
/* 40 Mhz */ { 283.5f, /* SGI */ 315.0f, },
},
/* MCS 68 */
{ /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, },
/* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, },
},
/* MCS 69 */
{ /* 20 Mhz */ { 136.5f, /* SGI */ 151.7f, },
/* 40 Mhz */ { 283.5f, /* SGI */ 315.0f, },
},
/* MCS 70 */
{ /* 20 Mhz */ { 156.0f, /* SGI */ 173.3f, },
/* 40 Mhz */ { 324.0f, /* SGI */ 360.0f, },
},
/* MCS 71 */
{ /* 20 Mhz */ { 175.5f, /* SGI */ 195.0f, },
/* 40 Mhz */ { 364.5f, /* SGI */ 405.0f, },
},
/* MCS 72 */
{ /* 20 Mhz */ { 156.0f, /* SGI */ 173.3f, },
/* 40 Mhz */ { 324.0f, /* SGI */ 360.0f, },
},
/* MCS 73 */
{ /* 20 Mhz */ { 175.5f, /* SGI */ 195.0f, },
/* 40 Mhz */ { 364.5f, /* SGI */ 405.0f, },
},
/* MCS 74 */
{ /* 20 Mhz */ { 195.0f, /* SGI */ 216.7f, },
/* 40 Mhz */ { 405.0f, /* SGI */ 450.0f, },
},
/* MCS 75 */
{ /* 20 Mhz */ { 195.0f, /* SGI */ 216.7f, },
/* 40 Mhz */ { 405.0f, /* SGI */ 450.0f, },
},
/* MCS 76 */
{ /* 20 Mhz */ { 214.5f, /* SGI */ 238.3f, },
/* 40 Mhz */ { 445.5f, /* SGI */ 495.0f, },
},
};
static const char *auth_alg_text[]={"Open System","Shared Key","EAP"};
#define NUM_AUTH_ALGS (sizeof(auth_alg_text) / sizeof(auth_alg_text[0]))
static const char *status_text[] = {
"Successful", /* 0 */
"Unspecified failure", /* 1 */
"TDLS wakeup schedule rejected but alternative schedule "
"provided", /* 2 */
"TDLS wakeup schedule rejected",/* 3 */
"Reserved", /* 4 */
"Security disabled", /* 5 */
"Unacceptable lifetime", /* 6 */
"Not in same BSS", /* 7 */
"Reserved", /* 8 */
"Reserved", /* 9 */
"Cannot Support all requested capabilities in the Capability "
"Information field", /* 10 */
"Reassociation denied due to inability to confirm that association "
"exists", /* 11 */
"Association denied due to reason outside the scope of this "
"standard", /* 12 */
"Responding STA does not support the specified authentication "
"algorithm", /* 13 */
"Received an Authentication frame with authentication transaction "
"sequence number out of expected sequence", /* 14 */
"Authentication rejected because of challenge failure", /* 15 */
"Authentication rejected due to timeout waiting for next frame in "
"sequence", /* 16 */
"Association denied because AP is unable to handle "
"additional associated STAs", /* 17 */
"Association denied due to requesting STA not supporting "
"all of the data rates in the BSSBasicRateSet parameter, "
"the Basic HT-MCS Set field of the HT Operation "
"parameter, or the Basic VHT-MCS and NSS Set field in "
"the VHT Operation parameter", /* 18 */
"Association denied due to requesting STA not supporting "
"the short preamble option", /* 19 */
"Reserved", /* 20 */
"Reserved", /* 21 */
"Association request rejected because Spectrum Management "
"capability is required", /* 22 */
"Association request rejected because the information in the "
"Power Capability element is unacceptable", /* 23 */
"Association request rejected because the information in the "
"Supported Channels element is unacceptable", /* 24 */
"Association denied due to requesting STA not supporting "
"the Short Slot Time option", /* 25 */
"Reserved", /* 26 */
"Association denied because the requested STA does not support HT "
"features", /* 27 */
"R0KH unreachable", /* 28 */
"Association denied because the requesting STA does not "
"support the phased coexistence operation (PCO) "
"transition time required by the AP", /* 29 */
"Association request rejected temporarily; try again "
"later", /* 30 */
"Robust management frame policy violation", /* 31 */
"Unspecified, QoS-related failure", /* 32 */
"Association denied because QoS AP or PCP has "
"insufficient bandwidth to handle another QoS "
"STA", /* 33 */
"Association denied due to excessive frame loss rates and/or "
"poor conditions on current operating channel", /* 34 */
"Association (with QoS BSS) denied because the requesting STA "
"does not support the QoS facility", /* 35 */
"Reserved", /* 36 */
"The request has been declined", /* 37 */
"The request has not been successful as one or more parameters "
"have invalid values", /* 38 */
"The allocation or TS has not been created because the request "
"cannot be honored; however, a suggested TSPEC/DMG TSPEC is "
"provided so that the initiating STA can attempt to set "
"another allocation or TS with the suggested changes to the "
"TSPEC/DMG TSPEC", /* 39 */
"Invalid element, i.e., an element defined in this standard "
"for which the content does not meet the specifications in "
"Clause 9", /* 40 */
"Invalid group cipher", /* 41 */
"Invalid pairwise cipher", /* 42 */
"Invalid AKMP", /* 43 */
"Unsupported RSNE version", /* 44 */
"Invalid RSNE capabilities", /* 45 */
"Cipher suite rejected because of security policy", /* 46 */
"The TS or allocation has not been created; however, the "
"HC or PCP might be capable of creating a TS or "
"allocation, in response to a request, after the time "
"indicated in the TS Delay element", /* 47 */
"Direct Link is not allowed in the BSS by policy", /* 48 */
"The Destination STA is not present within this BSS", /* 49 */
"The Destination STA is not a QoS STA", /* 50 */
"Association denied because the listen interval is "
"too large", /* 51 */
"Invalid FT Action frame count", /* 52 */
"Invalid pairwise master key identifier (PMKID)", /* 53 */
"Invalid MDE", /* 54 */
"Invalid FTE", /* 55 */
"Requested TCLAS processing is not supported by the AP "
"or PCP", /* 56 */
"The AP or PCP has insufficient TCLAS processing "
"resources to satisfy the request", /* 57 */
"The TS has not been created because the request "
"cannot be honored; however, the HC or PCP suggests "
"that the STA transition to a different BSS to set up "
"the TS", /* 58 */
"GAS Advertisement Protocol not supported", /* 59 */
"No outstanding GAS request", /* 60 */
"GAS Response not received from the Advertisement "
"Server", /* 61 */
"STA timed out waiting for GAS Query Response", /* 62 */
"LARGE GAS Response is larger than query response "
"length limit", /* 63 */
"Request refused because home network does not support "
"request", /* 64 */
"Advertisement Server in the network is not currently "
"reachable", /* 65 */
"Reserved", /* 66 */
"Request refused due to permissions received via SSPN "
"interface", /* 67 */
"Request refused because the AP or PCP does not "
"support unauthenticated access", /* 68 */
"Reserved", /* 69 */
"Reserved", /* 70 */
"Reserved", /* 71 */
"Invalid contents of RSNE", /* 72 */
"U-APSD coexistence is not supported", /* 73 */
"Requested U-APSD coexistence mode is not supported", /* 74 */
"Requested Interval/Duration value cannot be "
"supported with U-APSD coexistence", /* 75 */
"Authentication is rejected because an Anti-Clogging "
"Token is required", /* 76 */
"Authentication is rejected because the offered "
"finite cyclic group is not supported", /* 77 */
"The TBTT adjustment request has not been successful "
"because the STA could not find an alternative TBTT", /* 78 */
"Transmission failure", /* 79 */
"Requested TCLAS Not Supported", /* 80 */
"TCLAS Resources Exhausted", /* 81 */
"Rejected with Suggested BSS transition", /* 82 */
"Reject with recommended schedule", /* 83 */
"Reject because no wakeup schedule specified", /* 84 */
"Success, the destination STA is in power save mode", /* 85 */
"FST pending, in process of admitting FST session", /* 86 */
"Performing FST now", /* 87 */
"FST pending, gap(s) in block ack window", /* 88 */
"Reject because of U-PID setting", /* 89 */
"Reserved", /* 90 */
"Reserved", /* 91 */
"(Re)Association refused for some external reason", /* 92 */
"(Re)Association refused because of memory limits "
"at the AP", /* 93 */
"(Re)Association refused because emergency services "
"are not supported at the AP", /* 94 */
"GAS query response not yet received", /* 95 */
"Reject since the request is for transition to a "
"frequency band subject to DSE procedures and "
"FST Initiator is a dependent STA", /* 96 */
"Requested TCLAS processing has been terminated by "
"the AP", /* 97 */
"The TS schedule conflicts with an existing "
"schedule; an alternative schedule is provided", /* 98 */
"The association has been denied; however, one or "
"more Multi-band elements are included that can "
"be used by the receiving STA to join the BSS", /* 99 */
"The request failed due to a reservation conflict", /* 100 */
"The request failed due to exceeded MAF limit", /* 101 */
"The request failed due to exceeded MCCA track "
"limit", /* 102 */
"Association denied because the information in the"
"Spectrum Management field is unacceptable", /* 103 */
"Association denied because the requesting STA "
"does not support VHT features", /* 104 */
"Enablement denied", /* 105 */
"Enablement denied due to restriction from an "
"authorized GDB", /* 106 */
"Authorization deenabled", /* 107 */
};
#define NUM_STATUSES (sizeof(status_text) / sizeof(status_text[0]))
static const char *reason_text[] = {
"Reserved", /* 0 */
"Unspecified reason", /* 1 */
"Previous authentication no longer valid", /* 2 */
"Deauthenticated because sending STA is leaving (or has left) "
"IBSS or ESS", /* 3 */
"Disassociated due to inactivity", /* 4 */
"Disassociated because AP is unable to handle all currently "
" associated STAs", /* 5 */
"Class 2 frame received from nonauthenticated STA", /* 6 */
"Class 3 frame received from nonassociated STA", /* 7 */
"Disassociated because sending STA is leaving "
"(or has left) BSS", /* 8 */
"STA requesting (re)association is not authenticated with "
"responding STA", /* 9 */
"Disassociated because the information in the Power Capability "
"element is unacceptable", /* 10 */
"Disassociated because the information in the Supported Channels "
"element is unacceptable", /* 11 */
"Disassociated due to BSS transition management", /* 12 */
"Invalid element, i.e., an element defined in this standard for "
"which the content does not meet the specifications "
"in Clause 9", /* 13 */
"Message integrity code (MIC) failure", /* 14 */
"4-Way Handshake timeout", /* 15 */
"Group key handshake timeout", /* 16 */
"Information element in 4-Way Handshake different from (Re)Association"
"Request/Probe Response/Beacon frame", /* 17 */
"Invalid group cipher", /* 18 */
"Invalid pairwise cipher", /* 19 */
"Invalid AKMP", /* 20 */
"Unsupported RSNE version", /* 21 */
"Invalid RSNE capabilities", /* 22 */
"IEEE 802.1X authentication failed", /* 23 */
"Cipher suite rejected because of the security policy", /* 24 */
"TDLS direct-link teardown due to TDLS peer STA "
"unreachable via the TDLS direct link", /* 25 */
"TDLS direct-link teardown for unspecified reason", /* 26 */
"Disassociated because session terminated by SSP request",/* 27 */
"Disassociated because of lack of SSP roaming agreement",/* 28 */
"Requested service rejected because of SSP cipher suite or "
"AKM requirement", /* 29 */
"Requested service not authorized in this location", /* 30 */
"TS deleted because QoS AP lacks sufficient bandwidth for this "
"QoS STA due to a change in BSS service characteristics or "
"operational mode (e.g. an HT BSS change from 40 MHz channel "
"to 20 MHz channel)", /* 31 */
"Disassociated for unspecified, QoS-related reason", /* 32 */
"Disassociated because QoS AP lacks sufficient bandwidth for this "
"QoS STA", /* 33 */
"Disassociated because of excessive number of frames that need to be "
"acknowledged, but are not acknowledged due to AP transmissions "
"and/or poor channel conditions", /* 34 */
"Disassociated because STA is transmitting outside the limits "
"of its TXOPs", /* 35 */
"Requested from peer STA as the STA is leaving the BSS "
"(or resetting)", /* 36 */
"Requested from peer STA as it does not want to use the "
"mechanism", /* 37 */
"Requested from peer STA as the STA received frames using the "
"mechanism for which a set up is required", /* 38 */
"Requested from peer STA due to time out", /* 39 */
"Reserved", /* 40 */
"Reserved", /* 41 */
"Reserved", /* 42 */
"Reserved", /* 43 */
"Reserved", /* 44 */
"Peer STA does not support the requested cipher suite", /* 45 */
"In a DLS Teardown frame: The teardown was initiated by the "
"DLS peer. In a Disassociation frame: Disassociated because "
"authorized access limit reached", /* 46 */
"In a DLS Teardown frame: The teardown was initiated by the "
"AP. In a Disassociation frame: Disassociated due to external "
"service requirements", /* 47 */
"Invalid FT Action frame count", /* 48 */
"Invalid pairwise master key identifier (PMKID)", /* 49 */
"Invalid MDE", /* 50 */
"Invalid FTE", /* 51 */
"Mesh peering canceled for unknown reasons", /* 52 */
"The mesh STA has reached the supported maximum number of "
"peer mesh STAs", /* 53 */
"The received information violates the Mesh Configuration "
"policy configured in the mesh STA profile", /* 54 */
"The mesh STA has received a Mesh Peering Close frame "
"requesting to close the mesh peering", /* 55 */
"The mesh STA has resent dot11MeshMaxRetries Mesh "
"Peering Open frames, without receiving a Mesh Peering "
"Confirm frame", /* 56 */
"The confirmTimer for the mesh peering instance times out", /* 57 */
"The mesh STA fails to unwrap the GTK or the values in the "
"wrapped contents do not match", /* 58 */
"The mesh STA receives inconsistent information about the "
"mesh parameters between mesh peering Management frames", /* 59 */
"The mesh STA fails the authenticated mesh peering exchange "
"because due to failure in selecting either the pairwise "
"ciphersuite or group ciphersuite", /* 60 */
"The mesh STA does not have proxy information for this "
"external destination", /* 61 */
"The mesh STA does not have forwarding information for this "
"destination", /* 62 */
"The mesh STA determines that the link to the next hop of an "
"active path in its forwarding information is no longer "
"usable", /* 63 */
"The Deauthentication frame was sent because the MAC "
"address of the STA already exists in the mesh BSS", /* 64 */
"The mesh STA performs channel switch to meet regulatory "
"requirements", /* 65 */
"The mesh STA performs channel switching with unspecified "
"reason", /* 66 */
};
#define NUM_REASONS (sizeof(reason_text) / sizeof(reason_text[0]))
static int
wep_print(netdissect_options *ndo,
const u_char *p)
{
uint32_t iv;
ND_TCHECK_LEN(p, IEEE802_11_IV_LEN + IEEE802_11_KID_LEN);
iv = GET_LE_U_4(p);
ND_PRINT(" IV:%3x Pad %x KeyID %x", IV_IV(iv), IV_PAD(iv),
IV_KEYID(iv));
return 1;
trunc:
return 0;
}
static int
parse_elements(netdissect_options *ndo,
struct mgmt_body_t *pbody, const u_char *p, int offset,
u_int length)
{
u_int elementlen;
struct ssid_t ssid;
struct challenge_t challenge;
struct rates_t rates;
struct ds_t ds;
struct cf_t cf;
struct tim_t tim;
/*
* We haven't seen any elements yet.
*/
pbody->challenge_present = 0;
pbody->ssid_present = 0;
pbody->rates_present = 0;
pbody->ds_present = 0;
pbody->cf_present = 0;
pbody->tim_present = 0;
while (length != 0) {
/* Make sure we at least have the element ID and length. */
ND_TCHECK_2(p + offset);
if (length < 2)
goto trunc;
elementlen = GET_U_1(p + offset + 1);
/* Make sure we have the entire element. */
ND_TCHECK_LEN(p + offset + 2, elementlen);
if (length < elementlen + 2)
goto trunc;
switch (GET_U_1(p + offset)) {
case E_SSID:
- memcpy(&ssid, p + offset, 2);
+ ssid.length = elementlen;
offset += 2;
length -= 2;
if (ssid.length != 0) {
if (ssid.length > sizeof(ssid.ssid) - 1)
return 0;
memcpy(&ssid.ssid, p + offset, ssid.length);
offset += ssid.length;
length -= ssid.length;
}
ssid.ssid[ssid.length] = '\0';
/*
* Present and not truncated.
*
* If we haven't already seen an SSID IE,
* copy this one, otherwise ignore this one,
* so we later report the first one we saw.
*/
if (!pbody->ssid_present) {
pbody->ssid = ssid;
pbody->ssid_present = 1;
}
break;
case E_CHALLENGE:
- memcpy(&challenge, p + offset, 2);
+ challenge.length = elementlen;
offset += 2;
length -= 2;
if (challenge.length != 0) {
if (challenge.length >
sizeof(challenge.text) - 1)
return 0;
memcpy(&challenge.text, p + offset,
challenge.length);
offset += challenge.length;
length -= challenge.length;
}
challenge.text[challenge.length] = '\0';
/*
* Present and not truncated.
*
* If we haven't already seen a challenge IE,
* copy this one, otherwise ignore this one,
* so we later report the first one we saw.
*/
if (!pbody->challenge_present) {
pbody->challenge = challenge;
pbody->challenge_present = 1;
}
break;
case E_RATES:
- memcpy(&rates, p + offset, 2);
+ rates.length = elementlen;
offset += 2;
length -= 2;
if (rates.length != 0) {
if (rates.length > sizeof(rates.rate))
return 0;
memcpy(&rates.rate, p + offset, rates.length);
offset += rates.length;
length -= rates.length;
}
/*
* Present and not truncated.
*
* If we haven't already seen a rates IE,
* copy this one if it's not zero-length,
* otherwise ignore this one, so we later
* report the first one we saw.
*
* We ignore zero-length rates IEs as some
* devices seem to put a zero-length rates
* IE, followed by an SSID IE, followed by
* a non-zero-length rates IE into frames,
* even though IEEE Std 802.11-2007 doesn't
* seem to indicate that a zero-length rates
* IE is valid.
*/
if (!pbody->rates_present && rates.length != 0) {
pbody->rates = rates;
pbody->rates_present = 1;
}
break;
case E_DS:
- memcpy(&ds, p + offset, 2);
+ ds.length = elementlen;
offset += 2;
length -= 2;
if (ds.length != 1) {
offset += ds.length;
length -= ds.length;
break;
}
ds.channel = GET_U_1(p + offset);
offset += 1;
length -= 1;
/*
* Present and not truncated.
*
* If we haven't already seen a DS IE,
* copy this one, otherwise ignore this one,
* so we later report the first one we saw.
*/
if (!pbody->ds_present) {
pbody->ds = ds;
pbody->ds_present = 1;
}
break;
case E_CF:
- memcpy(&cf, p + offset, 2);
+ cf.length = elementlen;
offset += 2;
length -= 2;
if (cf.length != 6) {
offset += cf.length;
length -= cf.length;
break;
}
cf.count = GET_U_1(p + offset);
offset += 1;
length -= 1;
cf.period = GET_U_1(p + offset);
offset += 1;
length -= 1;
cf.max_duration = GET_LE_U_2(p + offset);
offset += 2;
length -= 2;
cf.dur_remaining = GET_LE_U_2(p + offset);
offset += 2;
length -= 2;
/*
* Present and not truncated.
*
* If we haven't already seen a CF IE,
* copy this one, otherwise ignore this one,
* so we later report the first one we saw.
*/
if (!pbody->cf_present) {
pbody->cf = cf;
pbody->cf_present = 1;
}
break;
case E_TIM:
- memcpy(&tim, p + offset, 2);
+ tim.length = elementlen;
offset += 2;
length -= 2;
if (tim.length <= 3U) {
offset += tim.length;
length -= tim.length;
break;
}
if (tim.length - 3U > sizeof(tim.bitmap))
return 0;
tim.count = GET_U_1(p + offset);
offset += 1;
length -= 1;
tim.period = GET_U_1(p + offset);
offset += 1;
length -= 1;
tim.bitmap_control = GET_U_1(p + offset);
offset += 1;
length -= 1;
memcpy(tim.bitmap, p + offset, tim.length - 3);
offset += tim.length - 3;
length -= tim.length - 3;
/*
* Present and not truncated.
*
* If we haven't already seen a TIM IE,
* copy this one, otherwise ignore this one,
* so we later report the first one we saw.
*/
if (!pbody->tim_present) {
pbody->tim = tim;
pbody->tim_present = 1;
}
break;
default:
#if 0
ND_PRINT("(1) unhandled element_id (%u) ",
GET_U_1(p + offset));
#endif
offset += 2 + elementlen;
length -= 2 + elementlen;
break;
}
}
/* No problems found. */
return 1;
trunc:
return 0;
}
/*********************************************************************************
* Print Handle functions for the management frame types
*********************************************************************************/
static int
handle_beacon(netdissect_options *ndo,
const u_char *p, u_int length)
{
struct mgmt_body_t pbody;
int offset = 0;
int ret;
memset(&pbody, 0, sizeof(pbody));
ND_TCHECK_LEN(p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
IEEE802_11_CAPINFO_LEN);
if (length < IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
IEEE802_11_CAPINFO_LEN)
goto trunc;
memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN);
offset += IEEE802_11_TSTAMP_LEN;
length -= IEEE802_11_TSTAMP_LEN;
pbody.beacon_interval = GET_LE_U_2(p + offset);
offset += IEEE802_11_BCNINT_LEN;
length -= IEEE802_11_BCNINT_LEN;
pbody.capability_info = GET_LE_U_2(p + offset);
offset += IEEE802_11_CAPINFO_LEN;
length -= IEEE802_11_CAPINFO_LEN;
ret = parse_elements(ndo, &pbody, p, offset, length);
PRINT_SSID(pbody);
PRINT_RATES(pbody);
ND_PRINT(" %s",
CAPABILITY_ESS(pbody.capability_info) ? "ESS" : "IBSS");
PRINT_DS_CHANNEL(pbody);
return ret;
trunc:
return 0;
}
static int
handle_assoc_request(netdissect_options *ndo,
const u_char *p, u_int length)
{
struct mgmt_body_t pbody;
int offset = 0;
int ret;
memset(&pbody, 0, sizeof(pbody));
ND_TCHECK_LEN(p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN);
if (length < IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN)
goto trunc;
pbody.capability_info = GET_LE_U_2(p);
offset += IEEE802_11_CAPINFO_LEN;
length -= IEEE802_11_CAPINFO_LEN;
pbody.listen_interval = GET_LE_U_2(p + offset);
offset += IEEE802_11_LISTENINT_LEN;
length -= IEEE802_11_LISTENINT_LEN;
ret = parse_elements(ndo, &pbody, p, offset, length);
PRINT_SSID(pbody);
PRINT_RATES(pbody);
return ret;
trunc:
return 0;
}
static int
handle_assoc_response(netdissect_options *ndo,
const u_char *p, u_int length)
{
struct mgmt_body_t pbody;
int offset = 0;
int ret;
memset(&pbody, 0, sizeof(pbody));
ND_TCHECK_LEN(p, IEEE802_11_CAPINFO_LEN + IEEE802_11_STATUS_LEN +
IEEE802_11_AID_LEN);
if (length < IEEE802_11_CAPINFO_LEN + IEEE802_11_STATUS_LEN +
IEEE802_11_AID_LEN)
goto trunc;
pbody.capability_info = GET_LE_U_2(p);
offset += IEEE802_11_CAPINFO_LEN;
length -= IEEE802_11_CAPINFO_LEN;
pbody.status_code = GET_LE_U_2(p + offset);
offset += IEEE802_11_STATUS_LEN;
length -= IEEE802_11_STATUS_LEN;
pbody.aid = GET_LE_U_2(p + offset);
offset += IEEE802_11_AID_LEN;
length -= IEEE802_11_AID_LEN;
ret = parse_elements(ndo, &pbody, p, offset, length);
ND_PRINT(" AID(%x) :%s: %s", ((uint16_t)(pbody.aid << 2 )) >> 2 ,
CAPABILITY_PRIVACY(pbody.capability_info) ? " PRIVACY " : "",
(pbody.status_code < NUM_STATUSES
? status_text[pbody.status_code]
: "n/a"));
return ret;
trunc:
return 0;
}
static int
handle_reassoc_request(netdissect_options *ndo,
const u_char *p, u_int length)
{
struct mgmt_body_t pbody;
int offset = 0;
int ret;
memset(&pbody, 0, sizeof(pbody));
ND_TCHECK_LEN(p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN +
IEEE802_11_AP_LEN);
if (length < IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN +
IEEE802_11_AP_LEN)
goto trunc;
pbody.capability_info = GET_LE_U_2(p);
offset += IEEE802_11_CAPINFO_LEN;
length -= IEEE802_11_CAPINFO_LEN;
pbody.listen_interval = GET_LE_U_2(p + offset);
offset += IEEE802_11_LISTENINT_LEN;
length -= IEEE802_11_LISTENINT_LEN;
memcpy(&pbody.ap, p+offset, IEEE802_11_AP_LEN);
offset += IEEE802_11_AP_LEN;
length -= IEEE802_11_AP_LEN;
ret = parse_elements(ndo, &pbody, p, offset, length);
PRINT_SSID(pbody);
ND_PRINT(" AP : %s", etheraddr_string(ndo, pbody.ap ));
return ret;
trunc:
return 0;
}
static int
handle_reassoc_response(netdissect_options *ndo,
const u_char *p, u_int length)
{
/* Same as a Association Response */
return handle_assoc_response(ndo, p, length);
}
static int
handle_probe_request(netdissect_options *ndo,
const u_char *p, u_int length)
{
struct mgmt_body_t pbody;
int offset = 0;
int ret;
memset(&pbody, 0, sizeof(pbody));
ret = parse_elements(ndo, &pbody, p, offset, length);
PRINT_SSID(pbody);
PRINT_RATES(pbody);
return ret;
}
static int
handle_probe_response(netdissect_options *ndo,
const u_char *p, u_int length)
{
struct mgmt_body_t pbody;
int offset = 0;
int ret;
memset(&pbody, 0, sizeof(pbody));
ND_TCHECK_LEN(p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
IEEE802_11_CAPINFO_LEN);
if (length < IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN +
IEEE802_11_CAPINFO_LEN)
goto trunc;
memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN);
offset += IEEE802_11_TSTAMP_LEN;
length -= IEEE802_11_TSTAMP_LEN;
pbody.beacon_interval = GET_LE_U_2(p + offset);
offset += IEEE802_11_BCNINT_LEN;
length -= IEEE802_11_BCNINT_LEN;
pbody.capability_info = GET_LE_U_2(p + offset);
offset += IEEE802_11_CAPINFO_LEN;
length -= IEEE802_11_CAPINFO_LEN;
ret = parse_elements(ndo, &pbody, p, offset, length);
PRINT_SSID(pbody);
PRINT_RATES(pbody);
PRINT_DS_CHANNEL(pbody);
return ret;
trunc:
return 0;
}
static int
handle_atim(void)
{
/* the frame body for ATIM is null. */
return 1;
}
static int
handle_disassoc(netdissect_options *ndo,
const u_char *p, u_int length)
{
struct mgmt_body_t pbody;
memset(&pbody, 0, sizeof(pbody));
ND_TCHECK_LEN(p, IEEE802_11_REASON_LEN);
if (length < IEEE802_11_REASON_LEN)
goto trunc;
pbody.reason_code = GET_LE_U_2(p);
ND_PRINT(": %s",
(pbody.reason_code < NUM_REASONS)
? reason_text[pbody.reason_code]
: "Reserved");
return 1;
trunc:
return 0;
}
static int
handle_auth(netdissect_options *ndo,
const u_char *p, u_int length)
{
struct mgmt_body_t pbody;
int offset = 0;
int ret;
memset(&pbody, 0, sizeof(pbody));
ND_TCHECK_6(p);
if (length < 6)
goto trunc;
pbody.auth_alg = GET_LE_U_2(p);
offset += 2;
length -= 2;
pbody.auth_trans_seq_num = GET_LE_U_2(p + offset);
offset += 2;
length -= 2;
pbody.status_code = GET_LE_U_2(p + offset);
offset += 2;
length -= 2;
ret = parse_elements(ndo, &pbody, p, offset, length);
if ((pbody.auth_alg == 1) &&
((pbody.auth_trans_seq_num == 2) ||
(pbody.auth_trans_seq_num == 3))) {
ND_PRINT(" (%s)-%x [Challenge Text] %s",
(pbody.auth_alg < NUM_AUTH_ALGS)
? auth_alg_text[pbody.auth_alg]
: "Reserved",
pbody.auth_trans_seq_num,
((pbody.auth_trans_seq_num % 2)
? ((pbody.status_code < NUM_STATUSES)
? status_text[pbody.status_code]
: "n/a") : ""));
return ret;
}
ND_PRINT(" (%s)-%x: %s",
(pbody.auth_alg < NUM_AUTH_ALGS)
? auth_alg_text[pbody.auth_alg]
: "Reserved",
pbody.auth_trans_seq_num,
(pbody.auth_trans_seq_num % 2)
? ((pbody.status_code < NUM_STATUSES)
? status_text[pbody.status_code]
: "n/a")
: "");
return ret;
trunc:
return 0;
}
static int
handle_deauth(netdissect_options *ndo,
const uint8_t *src, const u_char *p, u_int length)
{
struct mgmt_body_t pbody;
const char *reason = NULL;
memset(&pbody, 0, sizeof(pbody));
ND_TCHECK_LEN(p, IEEE802_11_REASON_LEN);
if (length < IEEE802_11_REASON_LEN)
goto trunc;
pbody.reason_code = GET_LE_U_2(p);
reason = (pbody.reason_code < NUM_REASONS)
? reason_text[pbody.reason_code]
: "Reserved";
if (ndo->ndo_eflag) {
ND_PRINT(": %s", reason);
} else {
ND_PRINT(" (%s): %s", GET_ETHERADDR_STRING(src), reason);
}
return 1;
trunc:
return 0;
}
#define PRINT_HT_ACTION(v) (\
(v) == 0 ? ND_PRINT("TxChWidth"): \
(v) == 1 ? ND_PRINT("MIMOPwrSave"): \
ND_PRINT("Act#%u", (v)))
#define PRINT_BA_ACTION(v) (\
(v) == 0 ? ND_PRINT("ADDBA Request"): \
(v) == 1 ? ND_PRINT("ADDBA Response"): \
(v) == 2 ? ND_PRINT("DELBA"): \
ND_PRINT("Act#%u", (v)))
#define PRINT_MESHLINK_ACTION(v) (\
(v) == 0 ? ND_PRINT("Request"): \
(v) == 1 ? ND_PRINT("Report"): \
ND_PRINT("Act#%u", (v)))
#define PRINT_MESHPEERING_ACTION(v) (\
(v) == 0 ? ND_PRINT("Open"): \
(v) == 1 ? ND_PRINT("Confirm"): \
(v) == 2 ? ND_PRINT("Close"): \
ND_PRINT("Act#%u", (v)))
#define PRINT_MESHPATH_ACTION(v) (\
(v) == 0 ? ND_PRINT("Request"): \
(v) == 1 ? ND_PRINT("Report"): \
(v) == 2 ? ND_PRINT("Error"): \
(v) == 3 ? ND_PRINT("RootAnnouncement"): \
ND_PRINT("Act#%u", (v)))
#define PRINT_MESH_ACTION(v) (\
(v) == 0 ? ND_PRINT("MeshLink"): \
(v) == 1 ? ND_PRINT("HWMP"): \
(v) == 2 ? ND_PRINT("Gate Announcement"): \
(v) == 3 ? ND_PRINT("Congestion Control"): \
(v) == 4 ? ND_PRINT("MCCA Setup Request"): \
(v) == 5 ? ND_PRINT("MCCA Setup Reply"): \
(v) == 6 ? ND_PRINT("MCCA Advertisement Request"): \
(v) == 7 ? ND_PRINT("MCCA Advertisement"): \
(v) == 8 ? ND_PRINT("MCCA Teardown"): \
(v) == 9 ? ND_PRINT("TBTT Adjustment Request"): \
(v) == 10 ? ND_PRINT("TBTT Adjustment Response"): \
ND_PRINT("Act#%u", (v)))
#define PRINT_MULTIHOP_ACTION(v) (\
(v) == 0 ? ND_PRINT("Proxy Update"): \
(v) == 1 ? ND_PRINT("Proxy Update Confirmation"): \
ND_PRINT("Act#%u", (v)))
#define PRINT_SELFPROT_ACTION(v) (\
(v) == 1 ? ND_PRINT("Peering Open"): \
(v) == 2 ? ND_PRINT("Peering Confirm"): \
(v) == 3 ? ND_PRINT("Peering Close"): \
(v) == 4 ? ND_PRINT("Group Key Inform"): \
(v) == 5 ? ND_PRINT("Group Key Acknowledge"): \
ND_PRINT("Act#%u", (v)))
static int
handle_action(netdissect_options *ndo,
const uint8_t *src, const u_char *p, u_int length)
{
ND_TCHECK_2(p);
if (length < 2)
goto trunc;
if (ndo->ndo_eflag) {
ND_PRINT(": ");
} else {
ND_PRINT(" (%s): ", GET_ETHERADDR_STRING(src));
}
switch (GET_U_1(p)) {
case 0: ND_PRINT("Spectrum Management Act#%u", GET_U_1(p + 1)); break;
case 1: ND_PRINT("QoS Act#%u", GET_U_1(p + 1)); break;
case 2: ND_PRINT("DLS Act#%u", GET_U_1(p + 1)); break;
case 3: ND_PRINT("BA "); PRINT_BA_ACTION(GET_U_1(p + 1)); break;
case 7: ND_PRINT("HT "); PRINT_HT_ACTION(GET_U_1(p + 1)); break;
case 13: ND_PRINT("MeshAction "); PRINT_MESH_ACTION(GET_U_1(p + 1)); break;
case 14:
- ND_PRINT("MultiohopAction ");
+ ND_PRINT("MultihopAction");
PRINT_MULTIHOP_ACTION(GET_U_1(p + 1)); break;
case 15:
ND_PRINT("SelfprotectAction ");
PRINT_SELFPROT_ACTION(GET_U_1(p + 1)); break;
case 127: ND_PRINT("Vendor Act#%u", GET_U_1(p + 1)); break;
default:
ND_PRINT("Reserved(%u) Act#%u", GET_U_1(p), GET_U_1(p + 1));
break;
}
return 1;
trunc:
return 0;
}
/*********************************************************************************
* Print Body funcs
*********************************************************************************/
static int
mgmt_body_print(netdissect_options *ndo,
uint16_t fc, const uint8_t *src, const u_char *p, u_int length)
{
ND_PRINT("%s", tok2str(st_str, "Unhandled Management subtype(%x)", FC_SUBTYPE(fc)));
/* There may be a problem w/ AP not having this bit set */
if (FC_PROTECTED(fc))
return wep_print(ndo, p);
switch (FC_SUBTYPE(fc)) {
case ST_ASSOC_REQUEST:
return handle_assoc_request(ndo, p, length);
case ST_ASSOC_RESPONSE:
return handle_assoc_response(ndo, p, length);
case ST_REASSOC_REQUEST:
return handle_reassoc_request(ndo, p, length);
case ST_REASSOC_RESPONSE:
return handle_reassoc_response(ndo, p, length);
case ST_PROBE_REQUEST:
return handle_probe_request(ndo, p, length);
case ST_PROBE_RESPONSE:
return handle_probe_response(ndo, p, length);
case ST_BEACON:
return handle_beacon(ndo, p, length);
case ST_ATIM:
return handle_atim();
case ST_DISASSOC:
return handle_disassoc(ndo, p, length);
case ST_AUTH:
return handle_auth(ndo, p, length);
case ST_DEAUTH:
return handle_deauth(ndo, src, p, length);
case ST_ACTION:
return handle_action(ndo, src, p, length);
default:
return 1;
}
}
/*********************************************************************************
* Handles printing all the control frame types
*********************************************************************************/
static int
ctrl_body_print(netdissect_options *ndo,
uint16_t fc, const u_char *p)
{
ND_PRINT("%s", tok2str(ctrl_str, "Unknown Ctrl Subtype", FC_SUBTYPE(fc)));
switch (FC_SUBTYPE(fc)) {
case CTRL_CONTROL_WRAPPER:
/* XXX - requires special handling */
break;
case CTRL_BAR:
ND_TCHECK_LEN(p, CTRL_BAR_HDRLEN);
if (!ndo->ndo_eflag)
ND_PRINT(" RA:%s TA:%s CTL(%x) SEQ(%u) ",
GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ra),
GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ta),
GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->ctl),
GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->seq));
break;
case CTRL_BA:
ND_TCHECK_LEN(p, CTRL_BA_HDRLEN);
if (!ndo->ndo_eflag)
ND_PRINT(" RA:%s ",
GET_ETHERADDR_STRING(((const struct ctrl_ba_hdr_t *)p)->ra));
break;
case CTRL_PS_POLL:
ND_TCHECK_LEN(p, CTRL_PS_POLL_HDRLEN);
ND_PRINT(" AID(%x)",
GET_LE_U_2(((const struct ctrl_ps_poll_hdr_t *)p)->aid));
break;
case CTRL_RTS:
ND_TCHECK_LEN(p, CTRL_RTS_HDRLEN);
if (!ndo->ndo_eflag)
ND_PRINT(" TA:%s ",
GET_ETHERADDR_STRING(((const struct ctrl_rts_hdr_t *)p)->ta));
break;
case CTRL_CTS:
ND_TCHECK_LEN(p, CTRL_CTS_HDRLEN);
if (!ndo->ndo_eflag)
ND_PRINT(" RA:%s ",
GET_ETHERADDR_STRING(((const struct ctrl_cts_hdr_t *)p)->ra));
break;
case CTRL_ACK:
ND_TCHECK_LEN(p, CTRL_ACK_HDRLEN);
if (!ndo->ndo_eflag)
ND_PRINT(" RA:%s ",
GET_ETHERADDR_STRING(((const struct ctrl_ack_hdr_t *)p)->ra));
break;
case CTRL_CF_END:
ND_TCHECK_LEN(p, CTRL_END_HDRLEN);
if (!ndo->ndo_eflag)
ND_PRINT(" RA:%s ",
GET_ETHERADDR_STRING(((const struct ctrl_end_hdr_t *)p)->ra));
break;
case CTRL_END_ACK:
ND_TCHECK_LEN(p, CTRL_END_ACK_HDRLEN);
if (!ndo->ndo_eflag)
ND_PRINT(" RA:%s ",
GET_ETHERADDR_STRING(((const struct ctrl_end_ack_hdr_t *)p)->ra));
break;
}
return 1;
trunc:
return 0;
}
/*
* Data Frame - Address field contents
*
* To Ds | From DS | Addr 1 | Addr 2 | Addr 3 | Addr 4
* 0 | 0 | DA | SA | BSSID | n/a
* 0 | 1 | DA | BSSID | SA | n/a
* 1 | 0 | BSSID | SA | DA | n/a
* 1 | 1 | RA | TA | DA | SA
*/
/*
* Function to get source and destination MAC addresses for a data frame.
*/
static void
get_data_src_dst_mac(uint16_t fc, const u_char *p, const uint8_t **srcp,
const uint8_t **dstp)
{
#define ADDR1 (p + 4)
#define ADDR2 (p + 10)
#define ADDR3 (p + 16)
#define ADDR4 (p + 24)
if (!FC_TO_DS(fc)) {
if (!FC_FROM_DS(fc)) {
/* not To DS and not From DS */
*srcp = ADDR2;
*dstp = ADDR1;
} else {
/* not To DS and From DS */
*srcp = ADDR3;
*dstp = ADDR1;
}
} else {
if (!FC_FROM_DS(fc)) {
/* To DS and not From DS */
*srcp = ADDR2;
*dstp = ADDR3;
} else {
/* To DS and From DS */
*srcp = ADDR4;
*dstp = ADDR3;
}
}
#undef ADDR1
#undef ADDR2
#undef ADDR3
#undef ADDR4
}
static void
get_mgmt_src_dst_mac(const u_char *p, const uint8_t **srcp, const uint8_t **dstp)
{
const struct mgmt_header_t *hp = (const struct mgmt_header_t *) p;
if (srcp != NULL)
*srcp = hp->sa;
if (dstp != NULL)
*dstp = hp->da;
}
/*
* Print Header funcs
*/
static void
data_header_print(netdissect_options *ndo, uint16_t fc, const u_char *p)
{
u_int subtype = FC_SUBTYPE(fc);
if (DATA_FRAME_IS_CF_ACK(subtype) || DATA_FRAME_IS_CF_POLL(subtype) ||
DATA_FRAME_IS_QOS(subtype)) {
ND_PRINT("CF ");
if (DATA_FRAME_IS_CF_ACK(subtype)) {
if (DATA_FRAME_IS_CF_POLL(subtype))
ND_PRINT("Ack/Poll");
else
ND_PRINT("Ack");
} else {
if (DATA_FRAME_IS_CF_POLL(subtype))
ND_PRINT("Poll");
}
if (DATA_FRAME_IS_QOS(subtype))
ND_PRINT("+QoS");
ND_PRINT(" ");
}
#define ADDR1 (p + 4)
#define ADDR2 (p + 10)
#define ADDR3 (p + 16)
#define ADDR4 (p + 24)
if (!FC_TO_DS(fc) && !FC_FROM_DS(fc)) {
ND_PRINT("DA:%s SA:%s BSSID:%s ",
GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2),
GET_ETHERADDR_STRING(ADDR3));
} else if (!FC_TO_DS(fc) && FC_FROM_DS(fc)) {
ND_PRINT("DA:%s BSSID:%s SA:%s ",
GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2),
GET_ETHERADDR_STRING(ADDR3));
} else if (FC_TO_DS(fc) && !FC_FROM_DS(fc)) {
ND_PRINT("BSSID:%s SA:%s DA:%s ",
GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2),
GET_ETHERADDR_STRING(ADDR3));
} else if (FC_TO_DS(fc) && FC_FROM_DS(fc)) {
ND_PRINT("RA:%s TA:%s DA:%s SA:%s ",
GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2),
GET_ETHERADDR_STRING(ADDR3), GET_ETHERADDR_STRING(ADDR4));
}
#undef ADDR1
#undef ADDR2
#undef ADDR3
#undef ADDR4
}
static void
mgmt_header_print(netdissect_options *ndo, const u_char *p)
{
const struct mgmt_header_t *hp = (const struct mgmt_header_t *) p;
ND_PRINT("BSSID:%s DA:%s SA:%s ",
GET_ETHERADDR_STRING((hp)->bssid), GET_ETHERADDR_STRING((hp)->da),
GET_ETHERADDR_STRING((hp)->sa));
}
static void
ctrl_header_print(netdissect_options *ndo, uint16_t fc, const u_char *p)
{
switch (FC_SUBTYPE(fc)) {
case CTRL_BAR:
ND_PRINT(" RA:%s TA:%s CTL(%x) SEQ(%u) ",
GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ra),
GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ta),
GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->ctl),
GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->seq));
break;
case CTRL_BA:
- ND_PRINT("RA:%s ",
- GET_ETHERADDR_STRING(((const struct ctrl_ba_hdr_t *)p)->ra));
+ ND_PRINT("RA:%s TA:%s ",
+ GET_ETHERADDR_STRING(((const struct ctrl_ba_hdr_t *)p)->ra),
+ GET_ETHERADDR_STRING(((const struct ctrl_ba_hdr_t *)p)->ta));
break;
case CTRL_PS_POLL:
ND_PRINT("BSSID:%s TA:%s ",
GET_ETHERADDR_STRING(((const struct ctrl_ps_poll_hdr_t *)p)->bssid),
GET_ETHERADDR_STRING(((const struct ctrl_ps_poll_hdr_t *)p)->ta));
break;
case CTRL_RTS:
ND_PRINT("RA:%s TA:%s ",
GET_ETHERADDR_STRING(((const struct ctrl_rts_hdr_t *)p)->ra),
GET_ETHERADDR_STRING(((const struct ctrl_rts_hdr_t *)p)->ta));
break;
case CTRL_CTS:
ND_PRINT("RA:%s ",
GET_ETHERADDR_STRING(((const struct ctrl_cts_hdr_t *)p)->ra));
break;
case CTRL_ACK:
ND_PRINT("RA:%s ",
GET_ETHERADDR_STRING(((const struct ctrl_ack_hdr_t *)p)->ra));
break;
case CTRL_CF_END:
ND_PRINT("RA:%s BSSID:%s ",
GET_ETHERADDR_STRING(((const struct ctrl_end_hdr_t *)p)->ra),
GET_ETHERADDR_STRING(((const struct ctrl_end_hdr_t *)p)->bssid));
break;
case CTRL_END_ACK:
ND_PRINT("RA:%s BSSID:%s ",
GET_ETHERADDR_STRING(((const struct ctrl_end_ack_hdr_t *)p)->ra),
GET_ETHERADDR_STRING(((const struct ctrl_end_ack_hdr_t *)p)->bssid));
break;
default:
/* We shouldn't get here - we should already have quit */
break;
}
}
static int
extract_header_length(netdissect_options *ndo,
uint16_t fc)
{
int len;
switch (FC_TYPE(fc)) {
case T_MGMT:
return MGMT_HDRLEN;
case T_CTRL:
switch (FC_SUBTYPE(fc)) {
case CTRL_CONTROL_WRAPPER:
return CTRL_CONTROL_WRAPPER_HDRLEN;
case CTRL_BAR:
return CTRL_BAR_HDRLEN;
case CTRL_BA:
return CTRL_BA_HDRLEN;
case CTRL_PS_POLL:
return CTRL_PS_POLL_HDRLEN;
case CTRL_RTS:
return CTRL_RTS_HDRLEN;
case CTRL_CTS:
return CTRL_CTS_HDRLEN;
case CTRL_ACK:
return CTRL_ACK_HDRLEN;
case CTRL_CF_END:
return CTRL_END_HDRLEN;
case CTRL_END_ACK:
return CTRL_END_ACK_HDRLEN;
default:
ND_PRINT("unknown 802.11 ctrl frame subtype (%u)", FC_SUBTYPE(fc));
return 0;
}
case T_DATA:
len = (FC_TO_DS(fc) && FC_FROM_DS(fc)) ? 30 : 24;
if (DATA_FRAME_IS_QOS(FC_SUBTYPE(fc)))
len += 2;
return len;
default:
ND_PRINT("unknown 802.11 frame type (%u)", FC_TYPE(fc));
return 0;
}
}
static int
extract_mesh_header_length(netdissect_options *ndo, const u_char *p)
{
return (GET_U_1(p) &~ 3) ? 0 : 6*(1 + (GET_U_1(p) & 3));
}
/*
* Print the 802.11 MAC header.
*/
static void
ieee_802_11_hdr_print(netdissect_options *ndo,
uint16_t fc, const u_char *p, u_int hdrlen,
u_int meshdrlen)
{
if (ndo->ndo_vflag) {
if (FC_MORE_DATA(fc))
ND_PRINT("More Data ");
if (FC_MORE_FLAG(fc))
ND_PRINT("More Fragments ");
if (FC_POWER_MGMT(fc))
ND_PRINT("Pwr Mgmt ");
if (FC_RETRY(fc))
ND_PRINT("Retry ");
if (FC_ORDER(fc))
ND_PRINT("Strictly Ordered ");
if (FC_PROTECTED(fc))
ND_PRINT("Protected ");
if (FC_TYPE(fc) != T_CTRL || FC_SUBTYPE(fc) != CTRL_PS_POLL)
ND_PRINT("%uus ",
GET_LE_U_2(((const struct mgmt_header_t *)p)->duration));
}
if (meshdrlen != 0) {
const struct meshcntl_t *mc =
(const struct meshcntl_t *)(p + hdrlen - meshdrlen);
u_int ae = GET_U_1(mc->flags) & 3;
ND_PRINT("MeshData (AE %u TTL %u seq %u", ae,
GET_U_1(mc->ttl), GET_LE_U_4(mc->seq));
if (ae > 0)
ND_PRINT(" A4:%s", GET_ETHERADDR_STRING(mc->addr4));
if (ae > 1)
ND_PRINT(" A5:%s", GET_ETHERADDR_STRING(mc->addr5));
if (ae > 2)
ND_PRINT(" A6:%s", GET_ETHERADDR_STRING(mc->addr6));
ND_PRINT(") ");
}
switch (FC_TYPE(fc)) {
case T_MGMT:
mgmt_header_print(ndo, p);
break;
case T_CTRL:
ctrl_header_print(ndo, fc, p);
break;
case T_DATA:
data_header_print(ndo, fc, p);
break;
default:
break;
}
}
static u_int
ieee802_11_print(netdissect_options *ndo,
const u_char *p, u_int length, u_int orig_caplen, int pad,
u_int fcslen)
{
uint16_t fc;
u_int caplen, hdrlen, meshdrlen;
struct lladdr_info src, dst;
int llc_hdrlen;
ndo->ndo_protocol = "802.11";
caplen = orig_caplen;
/* Remove FCS, if present */
if (length < fcslen) {
nd_print_trunc(ndo);
return caplen;
}
length -= fcslen;
if (caplen > length) {
/* Amount of FCS in actual packet data, if any */
fcslen = caplen - length;
caplen -= fcslen;
ndo->ndo_snapend -= fcslen;
}
if (caplen < IEEE802_11_FC_LEN) {
nd_print_trunc(ndo);
return orig_caplen;
}
fc = GET_LE_U_2(p);
hdrlen = extract_header_length(ndo, fc);
if (hdrlen == 0) {
/* Unknown frame type or control frame subtype; quit. */
return (0);
}
if (pad)
hdrlen = roundup2(hdrlen, 4);
if (ndo->ndo_Hflag && FC_TYPE(fc) == T_DATA &&
DATA_FRAME_IS_QOS(FC_SUBTYPE(fc))) {
if(!ND_TTEST_1(p + hdrlen)) {
nd_print_trunc(ndo);
return hdrlen;
}
meshdrlen = extract_mesh_header_length(ndo, p + hdrlen);
hdrlen += meshdrlen;
} else
meshdrlen = 0;
if (caplen < hdrlen) {
nd_print_trunc(ndo);
return hdrlen;
}
if (ndo->ndo_eflag)
ieee_802_11_hdr_print(ndo, fc, p, hdrlen, meshdrlen);
/*
* Go past the 802.11 header.
*/
length -= hdrlen;
caplen -= hdrlen;
p += hdrlen;
src.addr_string = etheraddr_string;
dst.addr_string = etheraddr_string;
switch (FC_TYPE(fc)) {
case T_MGMT:
get_mgmt_src_dst_mac(p - hdrlen, &src.addr, &dst.addr);
if (!mgmt_body_print(ndo, fc, src.addr, p, length)) {
nd_print_trunc(ndo);
return hdrlen;
}
break;
case T_CTRL:
if (!ctrl_body_print(ndo, fc, p - hdrlen)) {
nd_print_trunc(ndo);
return hdrlen;
}
break;
case T_DATA:
if (DATA_FRAME_IS_NULL(FC_SUBTYPE(fc)))
return hdrlen; /* no-data frame */
/* There may be a problem w/ AP not having this bit set */
if (FC_PROTECTED(fc)) {
ND_PRINT("Data");
if (!wep_print(ndo, p)) {
nd_print_trunc(ndo);
return hdrlen;
}
} else {
get_data_src_dst_mac(fc, p - hdrlen, &src.addr, &dst.addr);
llc_hdrlen = llc_print(ndo, p, length, caplen, &src, &dst);
if (llc_hdrlen < 0) {
/*
* Some kinds of LLC packet we cannot
* handle intelligently
*/
if (!ndo->ndo_suppress_default_print)
ND_DEFAULTPRINT(p, caplen);
llc_hdrlen = -llc_hdrlen;
}
hdrlen += llc_hdrlen;
}
break;
default:
/* We shouldn't get here - we should already have quit */
break;
}
return hdrlen;
}
/*
* This is the top level routine of the printer. 'p' points
* to the 802.11 header of the packet, 'h->ts' is the timestamp,
* 'h->len' is the length of the packet off the wire, and 'h->caplen'
* is the number of bytes actually captured.
*/
void
ieee802_11_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h, const u_char *p)
{
ndo->ndo_protocol = "802.11";
ndo->ndo_ll_hdr_len += ieee802_11_print(ndo, p, h->len, h->caplen, 0, 0);
}
/* $FreeBSD: projects/clang400-import/contrib/tcpdump/print-802_11.c 276788 2015-01-07 19:55:18Z delphij $ */
/* NetBSD: ieee802_11_radio.h,v 1.2 2006/02/26 03:04:03 dyoung Exp */
/*-
* Copyright (c) 2003, 2004 David Young. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of David Young may not be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID
* YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/
/* A generic radio capture format is desirable. It must be
* rigidly defined (e.g., units for fields should be given),
* and easily extensible.
*
* The following is an extensible radio capture format. It is
* based on a bitmap indicating which fields are present.
*
* I am trying to describe precisely what the application programmer
* should expect in the following, and for that reason I tell the
* units and origin of each measurement (where it applies), or else I
* use sufficiently weaselly language ("is a monotonically nondecreasing
* function of...") that I cannot set false expectations for lawyerly
* readers.
*/
/*
* The radio capture header precedes the 802.11 header.
*
* Note well: all radiotap fields are little-endian.
*/
struct ieee80211_radiotap_header {
nd_uint8_t it_version; /* Version 0. Only increases
* for drastic changes,
* introduction of compatible
* new fields does not count.
*/
nd_uint8_t it_pad;
nd_uint16_t it_len; /* length of the whole
* header in bytes, including
* it_version, it_pad,
* it_len, and data fields.
*/
nd_uint32_t it_present; /* A bitmap telling which
* fields are present. Set bit 31
* (0x80000000) to extend the
* bitmap by another 32 bits.
* Additional extensions are made
* by setting bit 31.
*/
};
/* Name Data type Units
* ---- --------- -----
*
* IEEE80211_RADIOTAP_TSFT uint64_t microseconds
*
* Value in microseconds of the MAC's 64-bit 802.11 Time
* Synchronization Function timer when the first bit of the
* MPDU arrived at the MAC. For received frames, only.
*
* IEEE80211_RADIOTAP_CHANNEL 2 x uint16_t MHz, bitmap
*
* Tx/Rx frequency in MHz, followed by flags (see below).
* Note that IEEE80211_RADIOTAP_XCHANNEL must be used to
* represent an HT channel as there is not enough room in
* the flags word.
*
* IEEE80211_RADIOTAP_FHSS uint16_t see below
*
* For frequency-hopping radios, the hop set (first byte)
* and pattern (second byte).
*
* IEEE80211_RADIOTAP_RATE uint8_t 500kb/s or index
*
* Tx/Rx data rate. If bit 0x80 is set then it represents an
* an MCS index and not an IEEE rate.
*
* IEEE80211_RADIOTAP_DBM_ANTSIGNAL int8_t decibels from
* one milliwatt (dBm)
*
* RF signal power at the antenna, decibel difference from
* one milliwatt.
*
* IEEE80211_RADIOTAP_DBM_ANTNOISE int8_t decibels from
* one milliwatt (dBm)
*
* RF noise power at the antenna, decibel difference from one
* milliwatt.
*
* IEEE80211_RADIOTAP_DB_ANTSIGNAL uint8_t decibel (dB)
*
* RF signal power at the antenna, decibel difference from an
* arbitrary, fixed reference.
*
* IEEE80211_RADIOTAP_DB_ANTNOISE uint8_t decibel (dB)
*
* RF noise power at the antenna, decibel difference from an
* arbitrary, fixed reference point.
*
* IEEE80211_RADIOTAP_LOCK_QUALITY uint16_t unitless
*
* Quality of Barker code lock. Unitless. Monotonically
* nondecreasing with "better" lock strength. Called "Signal
* Quality" in datasheets. (Is there a standard way to measure
* this?)
*
* IEEE80211_RADIOTAP_TX_ATTENUATION uint16_t unitless
*
* Transmit power expressed as unitless distance from max
* power set at factory calibration. 0 is max power.
* Monotonically nondecreasing with lower power levels.
*
* IEEE80211_RADIOTAP_DB_TX_ATTENUATION uint16_t decibels (dB)
*
* Transmit power expressed as decibel distance from max power
* set at factory calibration. 0 is max power. Monotonically
* nondecreasing with lower power levels.
*
* IEEE80211_RADIOTAP_DBM_TX_POWER int8_t decibels from
* one milliwatt (dBm)
*
* Transmit power expressed as dBm (decibels from a 1 milliwatt
* reference). This is the absolute power level measured at
* the antenna port.
*
* IEEE80211_RADIOTAP_FLAGS uint8_t bitmap
*
* Properties of transmitted and received frames. See flags
* defined below.
*
* IEEE80211_RADIOTAP_ANTENNA uint8_t antenna index
*
* Unitless indication of the Rx/Tx antenna for this packet.
* The first antenna is antenna 0.
*
* IEEE80211_RADIOTAP_RX_FLAGS uint16_t bitmap
*
* Properties of received frames. See flags defined below.
*
* IEEE80211_RADIOTAP_XCHANNEL uint32_t bitmap
* uint16_t MHz
* uint8_t channel number
* uint8_t .5 dBm
*
* Extended channel specification: flags (see below) followed by
* frequency in MHz, the corresponding IEEE channel number, and
* finally the maximum regulatory transmit power cap in .5 dBm
* units. This property supersedes IEEE80211_RADIOTAP_CHANNEL
* and only one of the two should be present.
*
* IEEE80211_RADIOTAP_MCS uint8_t known
* uint8_t flags
* uint8_t mcs
*
* Bitset indicating which fields have known values, followed
* by bitset of flag values, followed by the MCS rate index as
* in IEEE 802.11n.
*
*
* IEEE80211_RADIOTAP_AMPDU_STATUS u32, u16, u8, u8 unitless
*
* Contains the AMPDU information for the subframe.
*
* IEEE80211_RADIOTAP_VHT u16, u8, u8, u8[4], u8, u8, u16
*
* Contains VHT information about this frame.
*
* IEEE80211_RADIOTAP_VENDOR_NAMESPACE
* uint8_t OUI[3]
* uint8_t subspace
* uint16_t length
*
* The Vendor Namespace Field contains three sub-fields. The first
* sub-field is 3 bytes long. It contains the vendor's IEEE 802
* Organizationally Unique Identifier (OUI). The fourth byte is a
* vendor-specific "namespace selector."
*
*/
enum ieee80211_radiotap_type {
IEEE80211_RADIOTAP_TSFT = 0,
IEEE80211_RADIOTAP_FLAGS = 1,
IEEE80211_RADIOTAP_RATE = 2,
IEEE80211_RADIOTAP_CHANNEL = 3,
IEEE80211_RADIOTAP_FHSS = 4,
IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5,
IEEE80211_RADIOTAP_DBM_ANTNOISE = 6,
IEEE80211_RADIOTAP_LOCK_QUALITY = 7,
IEEE80211_RADIOTAP_TX_ATTENUATION = 8,
IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9,
IEEE80211_RADIOTAP_DBM_TX_POWER = 10,
IEEE80211_RADIOTAP_ANTENNA = 11,
IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
IEEE80211_RADIOTAP_RX_FLAGS = 14,
/* NB: gap for netbsd definitions */
IEEE80211_RADIOTAP_XCHANNEL = 18,
IEEE80211_RADIOTAP_MCS = 19,
IEEE80211_RADIOTAP_AMPDU_STATUS = 20,
IEEE80211_RADIOTAP_VHT = 21,
IEEE80211_RADIOTAP_NAMESPACE = 29,
IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30,
IEEE80211_RADIOTAP_EXT = 31
};
/* channel attributes */
#define IEEE80211_CHAN_TURBO 0x00010 /* Turbo channel */
#define IEEE80211_CHAN_CCK 0x00020 /* CCK channel */
#define IEEE80211_CHAN_OFDM 0x00040 /* OFDM channel */
#define IEEE80211_CHAN_2GHZ 0x00080 /* 2 GHz spectrum channel. */
#define IEEE80211_CHAN_5GHZ 0x00100 /* 5 GHz spectrum channel */
#define IEEE80211_CHAN_PASSIVE 0x00200 /* Only passive scan allowed */
#define IEEE80211_CHAN_DYN 0x00400 /* Dynamic CCK-OFDM channel */
#define IEEE80211_CHAN_GFSK 0x00800 /* GFSK channel (FHSS PHY) */
#define IEEE80211_CHAN_GSM 0x01000 /* 900 MHz spectrum channel */
#define IEEE80211_CHAN_STURBO 0x02000 /* 11a static turbo channel only */
#define IEEE80211_CHAN_HALF 0x04000 /* Half rate channel */
#define IEEE80211_CHAN_QUARTER 0x08000 /* Quarter rate channel */
#define IEEE80211_CHAN_HT20 0x10000 /* HT 20 channel */
#define IEEE80211_CHAN_HT40U 0x20000 /* HT 40 channel w/ ext above */
#define IEEE80211_CHAN_HT40D 0x40000 /* HT 40 channel w/ ext below */
/* Useful combinations of channel characteristics, borrowed from Ethereal */
#define IEEE80211_CHAN_A \
(IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM)
#define IEEE80211_CHAN_B \
(IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK)
#define IEEE80211_CHAN_G \
(IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN)
#define IEEE80211_CHAN_TA \
(IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM | IEEE80211_CHAN_TURBO)
#define IEEE80211_CHAN_TG \
(IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN | IEEE80211_CHAN_TURBO)
/* For IEEE80211_RADIOTAP_FLAGS */
#define IEEE80211_RADIOTAP_F_CFP 0x01 /* sent/received
* during CFP
*/
#define IEEE80211_RADIOTAP_F_SHORTPRE 0x02 /* sent/received
* with short
* preamble
*/
#define IEEE80211_RADIOTAP_F_WEP 0x04 /* sent/received
* with WEP encryption
*/
#define IEEE80211_RADIOTAP_F_FRAG 0x08 /* sent/received
* with fragmentation
*/
#define IEEE80211_RADIOTAP_F_FCS 0x10 /* frame includes FCS */
#define IEEE80211_RADIOTAP_F_DATAPAD 0x20 /* frame has padding between
* 802.11 header and payload
* (to 32-bit boundary)
*/
#define IEEE80211_RADIOTAP_F_BADFCS 0x40 /* does not pass FCS check */
/* For IEEE80211_RADIOTAP_RX_FLAGS */
#define IEEE80211_RADIOTAP_F_RX_BADFCS 0x0001 /* frame failed crc check */
#define IEEE80211_RADIOTAP_F_RX_PLCP_CRC 0x0002 /* frame failed PLCP CRC check */
/* For IEEE80211_RADIOTAP_MCS known */
#define IEEE80211_RADIOTAP_MCS_BANDWIDTH_KNOWN 0x01
#define IEEE80211_RADIOTAP_MCS_MCS_INDEX_KNOWN 0x02 /* MCS index field */
#define IEEE80211_RADIOTAP_MCS_GUARD_INTERVAL_KNOWN 0x04
#define IEEE80211_RADIOTAP_MCS_HT_FORMAT_KNOWN 0x08
#define IEEE80211_RADIOTAP_MCS_FEC_TYPE_KNOWN 0x10
#define IEEE80211_RADIOTAP_MCS_STBC_KNOWN 0x20
#define IEEE80211_RADIOTAP_MCS_NESS_KNOWN 0x40
#define IEEE80211_RADIOTAP_MCS_NESS_BIT_1 0x80
/* For IEEE80211_RADIOTAP_MCS flags */
#define IEEE80211_RADIOTAP_MCS_BANDWIDTH_MASK 0x03
#define IEEE80211_RADIOTAP_MCS_BANDWIDTH_20 0
#define IEEE80211_RADIOTAP_MCS_BANDWIDTH_40 1
#define IEEE80211_RADIOTAP_MCS_BANDWIDTH_20L 2
#define IEEE80211_RADIOTAP_MCS_BANDWIDTH_20U 3
#define IEEE80211_RADIOTAP_MCS_SHORT_GI 0x04 /* short guard interval */
#define IEEE80211_RADIOTAP_MCS_HT_GREENFIELD 0x08
#define IEEE80211_RADIOTAP_MCS_FEC_LDPC 0x10
#define IEEE80211_RADIOTAP_MCS_STBC_MASK 0x60
#define IEEE80211_RADIOTAP_MCS_STBC_1 1
#define IEEE80211_RADIOTAP_MCS_STBC_2 2
#define IEEE80211_RADIOTAP_MCS_STBC_3 3
#define IEEE80211_RADIOTAP_MCS_STBC_SHIFT 5
#define IEEE80211_RADIOTAP_MCS_NESS_BIT_0 0x80
/* For IEEE80211_RADIOTAP_AMPDU_STATUS */
#define IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN 0x0001
#define IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN 0x0002
#define IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN 0x0004
#define IEEE80211_RADIOTAP_AMPDU_IS_LAST 0x0008
#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR 0x0010
#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN 0x0020
/* For IEEE80211_RADIOTAP_VHT known */
#define IEEE80211_RADIOTAP_VHT_STBC_KNOWN 0x0001
#define IEEE80211_RADIOTAP_VHT_TXOP_PS_NA_KNOWN 0x0002
#define IEEE80211_RADIOTAP_VHT_GUARD_INTERVAL_KNOWN 0x0004
#define IEEE80211_RADIOTAP_VHT_SGI_NSYM_DIS_KNOWN 0x0008
#define IEEE80211_RADIOTAP_VHT_LDPC_EXTRA_OFDM_SYM_KNOWN 0x0010
#define IEEE80211_RADIOTAP_VHT_BEAMFORMED_KNOWN 0x0020
#define IEEE80211_RADIOTAP_VHT_BANDWIDTH_KNOWN 0x0040
#define IEEE80211_RADIOTAP_VHT_GROUP_ID_KNOWN 0x0080
#define IEEE80211_RADIOTAP_VHT_PARTIAL_AID_KNOWN 0x0100
/* For IEEE80211_RADIOTAP_VHT flags */
#define IEEE80211_RADIOTAP_VHT_STBC 0x01
#define IEEE80211_RADIOTAP_VHT_TXOP_PS_NA 0x02
#define IEEE80211_RADIOTAP_VHT_SHORT_GI 0x04
#define IEEE80211_RADIOTAP_VHT_SGI_NSYM_M10_9 0x08
#define IEEE80211_RADIOTAP_VHT_LDPC_EXTRA_OFDM_SYM 0x10
#define IEEE80211_RADIOTAP_VHT_BEAMFORMED 0x20
#define IEEE80211_RADIOTAP_VHT_BANDWIDTH_MASK 0x1f
#define IEEE80211_RADIOTAP_VHT_NSS_MASK 0x0f
#define IEEE80211_RADIOTAP_VHT_MCS_MASK 0xf0
#define IEEE80211_RADIOTAP_VHT_MCS_SHIFT 4
#define IEEE80211_RADIOTAP_CODING_LDPC_USERn 0x01
#define IEEE80211_CHAN_FHSS \
(IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_GFSK)
#define IEEE80211_CHAN_A \
(IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM)
#define IEEE80211_CHAN_B \
(IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK)
#define IEEE80211_CHAN_PUREG \
(IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_OFDM)
#define IEEE80211_CHAN_G \
(IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN)
#define IS_CHAN_FHSS(flags) \
((flags & IEEE80211_CHAN_FHSS) == IEEE80211_CHAN_FHSS)
#define IS_CHAN_A(flags) \
((flags & IEEE80211_CHAN_A) == IEEE80211_CHAN_A)
#define IS_CHAN_B(flags) \
((flags & IEEE80211_CHAN_B) == IEEE80211_CHAN_B)
#define IS_CHAN_PUREG(flags) \
((flags & IEEE80211_CHAN_PUREG) == IEEE80211_CHAN_PUREG)
#define IS_CHAN_G(flags) \
((flags & IEEE80211_CHAN_G) == IEEE80211_CHAN_G)
#define IS_CHAN_ANYG(flags) \
(IS_CHAN_PUREG(flags) || IS_CHAN_G(flags))
static void
print_chaninfo(netdissect_options *ndo,
uint16_t freq, uint32_t flags, uint32_t presentflags)
{
ND_PRINT("%u MHz", freq);
if (presentflags & (1 << IEEE80211_RADIOTAP_MCS)) {
/*
* We have the MCS field, so this is 11n, regardless
* of what the channel flags say.
*/
ND_PRINT(" 11n");
} else {
if (IS_CHAN_FHSS(flags))
ND_PRINT(" FHSS");
if (IS_CHAN_A(flags)) {
if (flags & IEEE80211_CHAN_HALF)
ND_PRINT(" 11a/10Mhz");
else if (flags & IEEE80211_CHAN_QUARTER)
ND_PRINT(" 11a/5Mhz");
else
ND_PRINT(" 11a");
}
if (IS_CHAN_ANYG(flags)) {
if (flags & IEEE80211_CHAN_HALF)
ND_PRINT(" 11g/10Mhz");
else if (flags & IEEE80211_CHAN_QUARTER)
ND_PRINT(" 11g/5Mhz");
else
ND_PRINT(" 11g");
} else if (IS_CHAN_B(flags))
ND_PRINT(" 11b");
if (flags & IEEE80211_CHAN_TURBO)
ND_PRINT(" Turbo");
}
/*
* These apply to 11n.
*/
if (flags & IEEE80211_CHAN_HT20)
ND_PRINT(" ht/20");
else if (flags & IEEE80211_CHAN_HT40D)
ND_PRINT(" ht/40-");
else if (flags & IEEE80211_CHAN_HT40U)
ND_PRINT(" ht/40+");
ND_PRINT(" ");
}
static int
print_radiotap_field(netdissect_options *ndo,
struct cpack_state *s, uint32_t bit, uint8_t *flagsp,
uint32_t presentflags)
{
u_int i;
int rc;
switch (bit) {
case IEEE80211_RADIOTAP_TSFT: {
uint64_t tsft;
rc = nd_cpack_uint64(ndo, s, &tsft);
if (rc != 0)
goto trunc;
ND_PRINT("%" PRIu64 "us tsft ", tsft);
break;
}
case IEEE80211_RADIOTAP_FLAGS: {
uint8_t flagsval;
rc = nd_cpack_uint8(ndo, s, &flagsval);
if (rc != 0)
goto trunc;
*flagsp = flagsval;
if (flagsval & IEEE80211_RADIOTAP_F_CFP)
ND_PRINT("cfp ");
if (flagsval & IEEE80211_RADIOTAP_F_SHORTPRE)
ND_PRINT("short preamble ");
if (flagsval & IEEE80211_RADIOTAP_F_WEP)
ND_PRINT("wep ");
if (flagsval & IEEE80211_RADIOTAP_F_FRAG)
ND_PRINT("fragmented ");
if (flagsval & IEEE80211_RADIOTAP_F_BADFCS)
ND_PRINT("bad-fcs ");
break;
}
case IEEE80211_RADIOTAP_RATE: {
uint8_t rate;
rc = nd_cpack_uint8(ndo, s, &rate);
if (rc != 0)
goto trunc;
/*
* XXX On FreeBSD rate & 0x80 means we have an MCS. On
* Linux and AirPcap it does not. (What about
* macOS, NetBSD, OpenBSD, and DragonFly BSD?)
*
* This is an issue either for proprietary extensions
* to 11a or 11g, which do exist, or for 11n
* implementations that stuff a rate value into
* this field, which also appear to exist.
*
* We currently handle that by assuming that
* if the 0x80 bit is set *and* the remaining
* bits have a value between 0 and 15 it's
* an MCS value, otherwise it's a rate. If
* there are cases where systems that use
* "0x80 + MCS index" for MCS indices > 15,
* or stuff a rate value here between 64 and
* 71.5 Mb/s in here, we'll need a preference
* setting. Such rates do exist, e.g. 11n
* MCS 7 at 20 MHz with a long guard interval.
*/
if (rate >= 0x80 && rate <= 0x8f) {
/*
* XXX - we don't know the channel width
* or guard interval length, so we can't
* convert this to a data rate.
*
* If you want us to show a data rate,
* use the MCS field, not the Rate field;
* the MCS field includes not only the
* MCS index, it also includes bandwidth
* and guard interval information.
*
* XXX - can we get the channel width
* from XChannel and the guard interval
* information from Flags, at least on
* FreeBSD?
*/
ND_PRINT("MCS %u ", rate & 0x7f);
} else
ND_PRINT("%2.1f Mb/s ", .5 * rate);
break;
}
case IEEE80211_RADIOTAP_CHANNEL: {
uint16_t frequency;
uint16_t flags;
rc = nd_cpack_uint16(ndo, s, &frequency);
if (rc != 0)
goto trunc;
rc = nd_cpack_uint16(ndo, s, &flags);
if (rc != 0)
goto trunc;
/*
* If CHANNEL and XCHANNEL are both present, skip
* CHANNEL.
*/
if (presentflags & (1 << IEEE80211_RADIOTAP_XCHANNEL))
break;
print_chaninfo(ndo, frequency, flags, presentflags);
break;
}
case IEEE80211_RADIOTAP_FHSS: {
uint8_t hopset;
uint8_t hoppat;
rc = nd_cpack_uint8(ndo, s, &hopset);
if (rc != 0)
goto trunc;
rc = nd_cpack_uint8(ndo, s, &hoppat);
if (rc != 0)
goto trunc;
ND_PRINT("fhset %u fhpat %u ", hopset, hoppat);
break;
}
case IEEE80211_RADIOTAP_DBM_ANTSIGNAL: {
int8_t dbm_antsignal;
rc = nd_cpack_int8(ndo, s, &dbm_antsignal);
if (rc != 0)
goto trunc;
ND_PRINT("%ddBm signal ", dbm_antsignal);
break;
}
case IEEE80211_RADIOTAP_DBM_ANTNOISE: {
int8_t dbm_antnoise;
rc = nd_cpack_int8(ndo, s, &dbm_antnoise);
if (rc != 0)
goto trunc;
ND_PRINT("%ddBm noise ", dbm_antnoise);
break;
}
case IEEE80211_RADIOTAP_LOCK_QUALITY: {
uint16_t lock_quality;
rc = nd_cpack_uint16(ndo, s, &lock_quality);
if (rc != 0)
goto trunc;
ND_PRINT("%u sq ", lock_quality);
break;
}
case IEEE80211_RADIOTAP_TX_ATTENUATION: {
int16_t tx_attenuation;
rc = nd_cpack_int16(ndo, s, &tx_attenuation);
if (rc != 0)
goto trunc;
ND_PRINT("%d tx power ", -tx_attenuation);
break;
}
case IEEE80211_RADIOTAP_DB_TX_ATTENUATION: {
int8_t db_tx_attenuation;
rc = nd_cpack_int8(ndo, s, &db_tx_attenuation);
if (rc != 0)
goto trunc;
ND_PRINT("%ddB tx attenuation ", -db_tx_attenuation);
break;
}
case IEEE80211_RADIOTAP_DBM_TX_POWER: {
int8_t dbm_tx_power;
rc = nd_cpack_int8(ndo, s, &dbm_tx_power);
if (rc != 0)
goto trunc;
ND_PRINT("%ddBm tx power ", dbm_tx_power);
break;
}
case IEEE80211_RADIOTAP_ANTENNA: {
uint8_t antenna;
rc = nd_cpack_uint8(ndo, s, &antenna);
if (rc != 0)
goto trunc;
ND_PRINT("antenna %u ", antenna);
break;
}
case IEEE80211_RADIOTAP_DB_ANTSIGNAL: {
uint8_t db_antsignal;
rc = nd_cpack_uint8(ndo, s, &db_antsignal);
if (rc != 0)
goto trunc;
ND_PRINT("%udB signal ", db_antsignal);
break;
}
case IEEE80211_RADIOTAP_DB_ANTNOISE: {
uint8_t db_antnoise;
rc = nd_cpack_uint8(ndo, s, &db_antnoise);
if (rc != 0)
goto trunc;
ND_PRINT("%udB noise ", db_antnoise);
break;
}
case IEEE80211_RADIOTAP_RX_FLAGS: {
uint16_t rx_flags;
rc = nd_cpack_uint16(ndo, s, &rx_flags);
if (rc != 0)
goto trunc;
/* Do nothing for now */
break;
}
case IEEE80211_RADIOTAP_XCHANNEL: {
uint32_t flags;
uint16_t frequency;
uint8_t channel;
uint8_t maxpower;
rc = nd_cpack_uint32(ndo, s, &flags);
if (rc != 0)
goto trunc;
rc = nd_cpack_uint16(ndo, s, &frequency);
if (rc != 0)
goto trunc;
rc = nd_cpack_uint8(ndo, s, &channel);
if (rc != 0)
goto trunc;
rc = nd_cpack_uint8(ndo, s, &maxpower);
if (rc != 0)
goto trunc;
print_chaninfo(ndo, frequency, flags, presentflags);
break;
}
case IEEE80211_RADIOTAP_MCS: {
uint8_t known;
uint8_t flags;
uint8_t mcs_index;
static const char *ht_bandwidth[4] = {
"20 MHz",
"40 MHz",
"20 MHz (L)",
"20 MHz (U)"
};
float htrate;
rc = nd_cpack_uint8(ndo, s, &known);
if (rc != 0)
goto trunc;
rc = nd_cpack_uint8(ndo, s, &flags);
if (rc != 0)
goto trunc;
rc = nd_cpack_uint8(ndo, s, &mcs_index);
if (rc != 0)
goto trunc;
if (known & IEEE80211_RADIOTAP_MCS_MCS_INDEX_KNOWN) {
/*
* We know the MCS index.
*/
if (mcs_index <= MAX_MCS_INDEX) {
/*
* And it's in-range.
*/
if (known & (IEEE80211_RADIOTAP_MCS_BANDWIDTH_KNOWN|IEEE80211_RADIOTAP_MCS_GUARD_INTERVAL_KNOWN)) {
/*
* And we know both the bandwidth and
* the guard interval, so we can look
* up the rate.
*/
htrate =
ieee80211_float_htrates
[mcs_index]
[((flags & IEEE80211_RADIOTAP_MCS_BANDWIDTH_MASK) == IEEE80211_RADIOTAP_MCS_BANDWIDTH_40 ? 1 : 0)]
[((flags & IEEE80211_RADIOTAP_MCS_SHORT_GI) ? 1 : 0)];
} else {
/*
* We don't know both the bandwidth
* and the guard interval, so we can
* only report the MCS index.
*/
htrate = 0.0;
}
} else {
/*
* The MCS value is out of range.
*/
htrate = 0.0;
}
if (htrate != 0.0) {
/*
* We have the rate.
* Print it.
*/
ND_PRINT("%.1f Mb/s MCS %u ", htrate, mcs_index);
} else {
/*
* We at least have the MCS index.
* Print it.
*/
ND_PRINT("MCS %u ", mcs_index);
}
}
if (known & IEEE80211_RADIOTAP_MCS_BANDWIDTH_KNOWN) {
ND_PRINT("%s ",
ht_bandwidth[flags & IEEE80211_RADIOTAP_MCS_BANDWIDTH_MASK]);
}
if (known & IEEE80211_RADIOTAP_MCS_GUARD_INTERVAL_KNOWN) {
ND_PRINT("%s GI ",
(flags & IEEE80211_RADIOTAP_MCS_SHORT_GI) ?
"short" : "long");
}
if (known & IEEE80211_RADIOTAP_MCS_HT_FORMAT_KNOWN) {
ND_PRINT("%s ",
(flags & IEEE80211_RADIOTAP_MCS_HT_GREENFIELD) ?
"greenfield" : "mixed");
}
if (known & IEEE80211_RADIOTAP_MCS_FEC_TYPE_KNOWN) {
ND_PRINT("%s FEC ",
(flags & IEEE80211_RADIOTAP_MCS_FEC_LDPC) ?
"LDPC" : "BCC");
}
if (known & IEEE80211_RADIOTAP_MCS_STBC_KNOWN) {
ND_PRINT("RX-STBC%u ",
(flags & IEEE80211_RADIOTAP_MCS_STBC_MASK) >> IEEE80211_RADIOTAP_MCS_STBC_SHIFT);
}
break;
}
case IEEE80211_RADIOTAP_AMPDU_STATUS: {
uint32_t reference_num;
uint16_t flags;
uint8_t delim_crc;
uint8_t reserved;
rc = nd_cpack_uint32(ndo, s, &reference_num);
if (rc != 0)
goto trunc;
rc = nd_cpack_uint16(ndo, s, &flags);
if (rc != 0)
goto trunc;
rc = nd_cpack_uint8(ndo, s, &delim_crc);
if (rc != 0)
goto trunc;
rc = nd_cpack_uint8(ndo, s, &reserved);
if (rc != 0)
goto trunc;
/* Do nothing for now */
break;
}
case IEEE80211_RADIOTAP_VHT: {
uint16_t known;
uint8_t flags;
uint8_t bandwidth;
uint8_t mcs_nss[4];
uint8_t coding;
uint8_t group_id;
uint16_t partial_aid;
static const char *vht_bandwidth[32] = {
"20 MHz",
"40 MHz",
"20 MHz (L)",
"20 MHz (U)",
"80 MHz",
"80 MHz (L)",
"80 MHz (U)",
"80 MHz (LL)",
"80 MHz (LU)",
"80 MHz (UL)",
"80 MHz (UU)",
"160 MHz",
"160 MHz (L)",
"160 MHz (U)",
"160 MHz (LL)",
"160 MHz (LU)",
"160 MHz (UL)",
"160 MHz (UU)",
"160 MHz (LLL)",
"160 MHz (LLU)",
"160 MHz (LUL)",
"160 MHz (UUU)",
"160 MHz (ULL)",
"160 MHz (ULU)",
"160 MHz (UUL)",
"160 MHz (UUU)",
"unknown (26)",
"unknown (27)",
"unknown (28)",
"unknown (29)",
"unknown (30)",
"unknown (31)"
};
rc = nd_cpack_uint16(ndo, s, &known);
if (rc != 0)
goto trunc;
rc = nd_cpack_uint8(ndo, s, &flags);
if (rc != 0)
goto trunc;
rc = nd_cpack_uint8(ndo, s, &bandwidth);
if (rc != 0)
goto trunc;
for (i = 0; i < 4; i++) {
rc = nd_cpack_uint8(ndo, s, &mcs_nss[i]);
if (rc != 0)
goto trunc;
}
rc = nd_cpack_uint8(ndo, s, &coding);
if (rc != 0)
goto trunc;
rc = nd_cpack_uint8(ndo, s, &group_id);
if (rc != 0)
goto trunc;
rc = nd_cpack_uint16(ndo, s, &partial_aid);
if (rc != 0)
goto trunc;
for (i = 0; i < 4; i++) {
u_int nss, mcs;
nss = mcs_nss[i] & IEEE80211_RADIOTAP_VHT_NSS_MASK;
mcs = (mcs_nss[i] & IEEE80211_RADIOTAP_VHT_MCS_MASK) >> IEEE80211_RADIOTAP_VHT_MCS_SHIFT;
if (nss == 0)
continue;
ND_PRINT("User %u MCS %u ", i, mcs);
ND_PRINT("%s FEC ",
(coding & (IEEE80211_RADIOTAP_CODING_LDPC_USERn << i)) ?
"LDPC" : "BCC");
}
if (known & IEEE80211_RADIOTAP_VHT_BANDWIDTH_KNOWN) {
ND_PRINT("%s ",
vht_bandwidth[bandwidth & IEEE80211_RADIOTAP_VHT_BANDWIDTH_MASK]);
}
if (known & IEEE80211_RADIOTAP_VHT_GUARD_INTERVAL_KNOWN) {
ND_PRINT("%s GI ",
(flags & IEEE80211_RADIOTAP_VHT_SHORT_GI) ?
"short" : "long");
}
break;
}
default:
/* this bit indicates a field whose
* size we do not know, so we cannot
* proceed. Just print the bit number.
*/
ND_PRINT("[bit %u] ", bit);
return -1;
}
return 0;
trunc:
nd_print_trunc(ndo);
return rc;
}
static int
print_in_radiotap_namespace(netdissect_options *ndo,
struct cpack_state *s, uint8_t *flags,
uint32_t presentflags, int bit0)
{
#define BITNO_32(x) (((x) >> 16) ? 16 + BITNO_16((x) >> 16) : BITNO_16((x)))
#define BITNO_16(x) (((x) >> 8) ? 8 + BITNO_8((x) >> 8) : BITNO_8((x)))
#define BITNO_8(x) (((x) >> 4) ? 4 + BITNO_4((x) >> 4) : BITNO_4((x)))
#define BITNO_4(x) (((x) >> 2) ? 2 + BITNO_2((x) >> 2) : BITNO_2((x)))
#define BITNO_2(x) (((x) & 2) ? 1 : 0)
uint32_t present, next_present;
int bitno;
enum ieee80211_radiotap_type bit;
int rc;
for (present = presentflags; present; present = next_present) {
/*
* Clear the least significant bit that is set.
*/
next_present = present & (present - 1);
/*
* Get the bit number, within this presence word,
* of the remaining least significant bit that
* is set.
*/
bitno = BITNO_32(present ^ next_present);
/*
* Stop if this is one of the "same meaning
* in all presence flags" bits.
*/
if (bitno >= IEEE80211_RADIOTAP_NAMESPACE)
break;
/*
* Get the radiotap bit number of that bit.
*/
bit = (enum ieee80211_radiotap_type)(bit0 + bitno);
rc = print_radiotap_field(ndo, s, bit, flags, presentflags);
if (rc != 0)
return rc;
}
return 0;
}
u_int
ieee802_11_radio_print(netdissect_options *ndo,
const u_char *p, u_int length, u_int caplen)
{
#define BIT(n) (1U << n)
#define IS_EXTENDED(__p) \
(GET_LE_U_4(__p) & BIT(IEEE80211_RADIOTAP_EXT)) != 0
struct cpack_state cpacker;
const struct ieee80211_radiotap_header *hdr;
uint32_t presentflags;
const nd_uint32_t *presentp, *last_presentp;
int vendor_namespace;
uint8_t vendor_oui[3];
uint8_t vendor_subnamespace;
uint16_t skip_length;
int bit0;
u_int len;
uint8_t flags;
int pad;
u_int fcslen;
ndo->ndo_protocol = "802.11_radio";
if (caplen < sizeof(*hdr)) {
nd_print_trunc(ndo);
return caplen;
}
hdr = (const struct ieee80211_radiotap_header *)p;
len = GET_LE_U_2(hdr->it_len);
if (len < sizeof(*hdr)) {
/*
* The length is the length of the entire header, so
* it must be as large as the fixed-length part of
* the header.
*/
nd_print_trunc(ndo);
return caplen;
}
/*
* If we don't have the entire radiotap header, just give up.
*/
if (caplen < len) {
nd_print_trunc(ndo);
return caplen;
}
nd_cpack_init(&cpacker, (const uint8_t *)hdr, len); /* align against header start */
nd_cpack_advance(&cpacker, sizeof(*hdr)); /* includes the 1st bitmap */
for (last_presentp = &hdr->it_present;
(const u_char*)(last_presentp + 1) <= p + len &&
IS_EXTENDED(last_presentp);
last_presentp++)
nd_cpack_advance(&cpacker, sizeof(hdr->it_present)); /* more bitmaps */
/* are there more bitmap extensions than bytes in header? */
if ((const u_char*)(last_presentp + 1) > p + len) {
nd_print_trunc(ndo);
return caplen;
}
/*
* Start out at the beginning of the default radiotap namespace.
*/
bit0 = 0;
vendor_namespace = 0;
memset(vendor_oui, 0, 3);
vendor_subnamespace = 0;
skip_length = 0;
/* Assume no flags */
flags = 0;
/* Assume no Atheros padding between 802.11 header and body */
pad = 0;
/* Assume no FCS at end of frame */
fcslen = 0;
for (presentp = &hdr->it_present; presentp <= last_presentp;
presentp++) {
presentflags = GET_LE_U_4(presentp);
/*
* If this is a vendor namespace, we don't handle it.
*/
if (vendor_namespace) {
/*
* Skip past the stuff we don't understand.
* If we add support for any vendor namespaces,
* it'd be added here; use vendor_oui and
* vendor_subnamespace to interpret the fields.
*/
if (nd_cpack_advance(&cpacker, skip_length) != 0) {
/*
* Ran out of space in the packet.
*/
break;
}
/*
* We've skipped it all; nothing more to
* skip.
*/
skip_length = 0;
} else {
if (print_in_radiotap_namespace(ndo, &cpacker,
&flags, presentflags, bit0) != 0) {
/*
* Fatal error - can't process anything
* more in the radiotap header.
*/
break;
}
}
/*
* Handle the namespace switch bits; we've already handled
* the extension bit in all but the last word above.
*/
switch (presentflags &
(BIT(IEEE80211_RADIOTAP_NAMESPACE)|BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE))) {
case 0:
/*
* We're not changing namespaces.
* advance to the next 32 bits in the current
* namespace.
*/
bit0 += 32;
break;
case BIT(IEEE80211_RADIOTAP_NAMESPACE):
/*
* We're switching to the radiotap namespace.
* Reset the presence-bitmap index to 0, and
* reset the namespace to the default radiotap
* namespace.
*/
bit0 = 0;
vendor_namespace = 0;
memset(vendor_oui, 0, 3);
vendor_subnamespace = 0;
skip_length = 0;
break;
case BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE):
/*
* We're switching to a vendor namespace.
* Reset the presence-bitmap index to 0,
* note that we're in a vendor namespace,
* and fetch the fields of the Vendor Namespace
* item.
*/
bit0 = 0;
vendor_namespace = 1;
if ((nd_cpack_align_and_reserve(&cpacker, 2)) == NULL) {
nd_print_trunc(ndo);
break;
}
if (nd_cpack_uint8(ndo, &cpacker, &vendor_oui[0]) != 0) {
nd_print_trunc(ndo);
break;
}
if (nd_cpack_uint8(ndo, &cpacker, &vendor_oui[1]) != 0) {
nd_print_trunc(ndo);
break;
}
if (nd_cpack_uint8(ndo, &cpacker, &vendor_oui[2]) != 0) {
nd_print_trunc(ndo);
break;
}
if (nd_cpack_uint8(ndo, &cpacker, &vendor_subnamespace) != 0) {
nd_print_trunc(ndo);
break;
}
if (nd_cpack_uint16(ndo, &cpacker, &skip_length) != 0) {
nd_print_trunc(ndo);
break;
}
break;
default:
/*
* Illegal combination. The behavior in this
* case is undefined by the radiotap spec; we
* just ignore both bits.
*/
break;
}
}
if (flags & IEEE80211_RADIOTAP_F_DATAPAD)
pad = 1; /* Atheros padding */
if (flags & IEEE80211_RADIOTAP_F_FCS)
fcslen = 4; /* FCS at end of packet */
return len + ieee802_11_print(ndo, p + len, length - len, caplen - len, pad,
fcslen);
#undef BITNO_32
#undef BITNO_16
#undef BITNO_8
#undef BITNO_4
#undef BITNO_2
#undef BIT
}
static u_int
ieee802_11_radio_avs_print(netdissect_options *ndo,
const u_char *p, u_int length, u_int caplen)
{
uint32_t caphdr_len;
ndo->ndo_protocol = "802.11_radio_avs";
if (caplen < 8) {
nd_print_trunc(ndo);
return caplen;
}
caphdr_len = GET_BE_U_4(p + 4);
if (caphdr_len < 8) {
/*
* Yow! The capture header length is claimed not
* to be large enough to include even the version
* cookie or capture header length!
*/
nd_print_trunc(ndo);
return caplen;
}
if (caplen < caphdr_len) {
nd_print_trunc(ndo);
return caplen;
}
return caphdr_len + ieee802_11_print(ndo, p + caphdr_len,
length - caphdr_len, caplen - caphdr_len, 0, 0);
}
#define PRISM_HDR_LEN 144
#define WLANCAP_MAGIC_COOKIE_BASE 0x80211000
#define WLANCAP_MAGIC_COOKIE_V1 0x80211001
#define WLANCAP_MAGIC_COOKIE_V2 0x80211002
/*
* For DLT_PRISM_HEADER; like DLT_IEEE802_11, but with an extra header,
* containing information such as radio information, which we
* currently ignore.
*
* If, however, the packet begins with WLANCAP_MAGIC_COOKIE_V1 or
* WLANCAP_MAGIC_COOKIE_V2, it's really DLT_IEEE802_11_RADIO_AVS
* (currently, on Linux, there's no ARPHRD_ type for
* DLT_IEEE802_11_RADIO_AVS, as there is a ARPHRD_IEEE80211_PRISM
* for DLT_PRISM_HEADER, so ARPHRD_IEEE80211_PRISM is used for
* the AVS header, and the first 4 bytes of the header are used to
* indicate whether it's a Prism header or an AVS header).
*/
void
prism_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h, const u_char *p)
{
u_int caplen = h->caplen;
u_int length = h->len;
uint32_t msgcode;
ndo->ndo_protocol = "prism";
if (caplen < 4) {
nd_print_trunc(ndo);
ndo->ndo_ll_hdr_len += caplen;
return;
}
msgcode = GET_BE_U_4(p);
if (msgcode == WLANCAP_MAGIC_COOKIE_V1 ||
msgcode == WLANCAP_MAGIC_COOKIE_V2) {
ndo->ndo_ll_hdr_len += ieee802_11_radio_avs_print(ndo, p, length, caplen);
return;
}
if (caplen < PRISM_HDR_LEN) {
nd_print_trunc(ndo);
ndo->ndo_ll_hdr_len += caplen;
return;
}
p += PRISM_HDR_LEN;
length -= PRISM_HDR_LEN;
caplen -= PRISM_HDR_LEN;
ndo->ndo_ll_hdr_len += PRISM_HDR_LEN;
ndo->ndo_ll_hdr_len += ieee802_11_print(ndo, p, length, caplen, 0, 0);
}
/*
* For DLT_IEEE802_11_RADIO; like DLT_IEEE802_11, but with an extra
* header, containing information such as radio information.
*/
void
ieee802_11_radio_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h, const u_char *p)
{
ndo->ndo_protocol = "802.11_radio";
ndo->ndo_ll_hdr_len += ieee802_11_radio_print(ndo, p, h->len, h->caplen);
}
/*
* For DLT_IEEE802_11_RADIO_AVS; like DLT_IEEE802_11, but with an
* extra header, containing information such as radio information,
* which we currently ignore.
*/
void
ieee802_11_radio_avs_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h, const u_char *p)
{
ndo->ndo_protocol = "802.11_radio_avs";
ndo->ndo_ll_hdr_len += ieee802_11_radio_avs_print(ndo, p, h->len, h->caplen);
}
diff --git a/contrib/tcpdump/print-802_15_4.c b/contrib/tcpdump/print-802_15_4.c
index fd75b1595622..2efcf94b4c77 100644
--- a/contrib/tcpdump/print-802_15_4.c
+++ b/contrib/tcpdump/print-802_15_4.c
@@ -1,2556 +1,2554 @@
/*
* Copyright (c) 2009
* Siemens AG, All rights reserved.
* Dmitry Eremin-Solenikov (dbaryshkov@gmail.com)
*
* 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.
*/
/* \summary: IEEE 802.15.4 printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#define CHECK_BIT(num,bit) (((num) >> (bit)) & 0x1)
#define BROKEN_6TISCH_PAN_ID_COMPRESSION 0
/* Frame types from Table 7-1 of 802.15.4-2015 */
static const char *ftypes[] = {
"Beacon", /* 0 */
"Data", /* 1 */
"ACK", /* 2 */
"Command", /* 3 */
"Reserved", /* 4 */
"Multipurpose", /* 5 */
"Fragment", /* 6 */
"Extended" /* 7 */
};
/* Element IDs for Header IEs from Table 7-7 of 802.15.4-2015 */
static const char *h_ie_names[] = {
"Vendor Specific Header IE", /* 0x00 */
"Reserved 0x01", /* 0x01 */
"Reserved 0x02", /* 0x02 */
"Reserved 0x03", /* 0x03 */
"Reserved 0x04", /* 0x04 */
"Reserved 0x05", /* 0x05 */
"Reserved 0x06", /* 0x06 */
"Reserved 0x07", /* 0x07 */
"Reserved 0x08", /* 0x08 */
"Reserved 0x09", /* 0x09 */
"Reserved 0x0a", /* 0x0a */
"Reserved 0x0b", /* 0x0b */
"Reserved 0x0c", /* 0x0c */
"Reserved 0x0d", /* 0x0d */
"Reserved 0x0e", /* 0x0e */
"Reserved 0x0f", /* 0x0f */
"Reserved 0x10", /* 0x10 */
"Reserved 0x11", /* 0x11 */
"Reserved 0x12", /* 0x12 */
"Reserved 0x13", /* 0x13 */
"Reserved 0x14", /* 0x14 */
"Reserved 0x15", /* 0x15 */
"Reserved 0x16", /* 0x16 */
"Reserved 0x17", /* 0x17 */
"Reserved 0x18", /* 0x18 */
"Reserved 0x19", /* 0x19 */
"LE CSL IE", /* 0x1a */
"LE RIT IE", /* 0x1b */
"DSME PAN descriptor IE", /* 0x1c */
"Rendezvous Time IE", /* 0x1d */
"Time Correction IE", /* 0x1e */
"Reserved 0x1f", /* 0x1f */
"Reserved 0x20", /* 0x20 */
"Extended DSME PAN descriptor IE", /* 0x21 */
"Fragment Sequence Context Description IE", /* 0x22 */
"Simplified Superframe Specification IE", /* 0x23 */
"Simplified GTS Specification IE", /* 0x24 */
"LECIM Capabilities IE", /* 0x25 */
"TRLE Descriptor IE", /* 0x26 */
"RCC Capabilities IE", /* 0x27 */
"RCCN Descriptor IE", /* 0x28 */
"Global Time IE", /* 0x29 */
"Omnibus Header IE", /* 0x2a */
"DA IE", /* 0x2b */
"Reserved 0x2c", /* 0x2c */
"Reserved 0x2d", /* 0x2d */
"Reserved 0x2e", /* 0x2e */
"Reserved 0x2f", /* 0x2f */
"Reserved 0x30", /* 0x30 */
"Reserved 0x31", /* 0x31 */
"Reserved 0x32", /* 0x32 */
"Reserved 0x33", /* 0x33 */
"Reserved 0x34", /* 0x34 */
"Reserved 0x35", /* 0x35 */
"Reserved 0x36", /* 0x36 */
"Reserved 0x37", /* 0x37 */
"Reserved 0x38", /* 0x38 */
"Reserved 0x39", /* 0x39 */
"Reserved 0x3a", /* 0x3a */
"Reserved 0x3b", /* 0x3b */
"Reserved 0x3c", /* 0x3c */
"Reserved 0x3d", /* 0x3d */
"Reserved 0x3e", /* 0x3e */
"Reserved 0x3f", /* 0x3f */
"Reserved 0x40", /* 0x40 */
"Reserved 0x41", /* 0x41 */
"Reserved 0x42", /* 0x42 */
"Reserved 0x43", /* 0x43 */
"Reserved 0x44", /* 0x44 */
"Reserved 0x45", /* 0x45 */
"Reserved 0x46", /* 0x46 */
"Reserved 0x47", /* 0x47 */
"Reserved 0x48", /* 0x48 */
"Reserved 0x49", /* 0x49 */
"Reserved 0x4a", /* 0x4a */
"Reserved 0x4b", /* 0x4b */
"Reserved 0x4c", /* 0x4c */
"Reserved 0x4d", /* 0x4d */
"Reserved 0x4e", /* 0x4e */
"Reserved 0x4f", /* 0x4f */
"Reserved 0x50", /* 0x50 */
"Reserved 0x51", /* 0x51 */
"Reserved 0x52", /* 0x52 */
"Reserved 0x53", /* 0x53 */
"Reserved 0x54", /* 0x54 */
"Reserved 0x55", /* 0x55 */
"Reserved 0x56", /* 0x56 */
"Reserved 0x57", /* 0x57 */
"Reserved 0x58", /* 0x58 */
"Reserved 0x59", /* 0x59 */
"Reserved 0x5a", /* 0x5a */
"Reserved 0x5b", /* 0x5b */
"Reserved 0x5c", /* 0x5c */
"Reserved 0x5d", /* 0x5d */
"Reserved 0x5e", /* 0x5e */
"Reserved 0x5f", /* 0x5f */
"Reserved 0x60", /* 0x60 */
"Reserved 0x61", /* 0x61 */
"Reserved 0x62", /* 0x62 */
"Reserved 0x63", /* 0x63 */
"Reserved 0x64", /* 0x64 */
"Reserved 0x65", /* 0x65 */
"Reserved 0x66", /* 0x66 */
"Reserved 0x67", /* 0x67 */
"Reserved 0x68", /* 0x68 */
"Reserved 0x69", /* 0x69 */
"Reserved 0x6a", /* 0x6a */
"Reserved 0x6b", /* 0x6b */
"Reserved 0x6c", /* 0x6c */
"Reserved 0x6d", /* 0x6d */
"Reserved 0x6e", /* 0x6e */
"Reserved 0x6f", /* 0x6f */
"Reserved 0x70", /* 0x70 */
"Reserved 0x71", /* 0x71 */
"Reserved 0x72", /* 0x72 */
"Reserved 0x73", /* 0x73 */
"Reserved 0x74", /* 0x74 */
"Reserved 0x75", /* 0x75 */
"Reserved 0x76", /* 0x76 */
"Reserved 0x77", /* 0x77 */
"Reserved 0x78", /* 0x78 */
"Reserved 0x79", /* 0x79 */
"Reserved 0x7a", /* 0x7a */
"Reserved 0x7b", /* 0x7b */
"Reserved 0x7c", /* 0x7c */
"Reserved 0x7d", /* 0x7d */
"Header Termination 1 IE", /* 0x7e */
"Header Termination 2 IE" /* 0x7f */
};
/* Payload IE Group IDs from Table 7-15 of 802.15.4-2015 */
static const char *p_ie_names[] = {
"ESDU IE", /* 0x00 */
"MLME IE", /* 0x01 */
"Vendor Specific Nested IE", /* 0x02 */
"Multiplexed IE (802.15.9)", /* 0x03 */
"Omnibus Payload Group IE", /* 0x04 */
"IETF IE", /* 0x05 */
"Reserved 0x06", /* 0x06 */
"Reserved 0x07", /* 0x07 */
"Reserved 0x08", /* 0x08 */
"Reserved 0x09", /* 0x09 */
"Reserved 0x0a", /* 0x0a */
"Reserved 0x0b", /* 0x0b */
"Reserved 0x0c", /* 0x0c */
"Reserved 0x0d", /* 0x0d */
"Reserved 0x0e", /* 0x0e */
"List termination" /* 0x0f */
};
/* Sub-ID for short format from Table 7-16 of 802.15.4-2015 */
static const char *p_mlme_short_names[] = {
"Reserved for long format 0x0", /* 0x00 */
"Reserved for long format 0x1", /* 0x01 */
"Reserved for long format 0x2", /* 0x02 */
"Reserved for long format 0x3", /* 0x03 */
"Reserved for long format 0x4", /* 0x04 */
"Reserved for long format 0x5", /* 0x05 */
"Reserved for long format 0x6", /* 0x06 */
"Reserved for long format 0x7", /* 0x07 */
"Reserved for long format 0x8", /* 0x08 */
"Reserved for long format 0x9", /* 0x09 */
"Reserved for long format 0xa", /* 0x0a */
"Reserved for long format 0xb", /* 0x0b */
"Reserved for long format 0xc", /* 0x0c */
"Reserved for long format 0xd", /* 0x0d */
"Reserved for long format 0xe", /* 0x0e */
"Reserved for long format 0xf", /* 0x0f */
"Reserved 0x10", /* 0x10 */
"Reserved 0x11", /* 0x11 */
"Reserved 0x12", /* 0x12 */
"Reserved 0x13", /* 0x13 */
"Reserved 0x14", /* 0x14 */
"Reserved 0x15", /* 0x15 */
"Reserved 0x16", /* 0x16 */
"Reserved 0x17", /* 0x17 */
"Reserved 0x18", /* 0x18 */
"Reserved 0x19", /* 0x19 */
"TSCH Synchronization IE", /* 0x1a */
"TSCH Slotframe and Link IE", /* 0x1b */
"TSCH Timeslot IE", /* 0x1c */
"Hopping timing IE", /* 0x1d */
"Enhanced Beacon Filter IE", /* 0x1e */
"MAC Metrics IE", /* 0x1f */
"All MAC Metrics IE", /* 0x20 */
"Coexistence Specification IE", /* 0x21 */
"SUN Device Capabilities IE", /* 0x22 */
"SUN FSK Generic PHY IE", /* 0x23 */
"Mode Switch Parameter IE", /* 0x24 */
"PHY Parameter Change IE", /* 0x25 */
"O-QPSK PHY Mode IE", /* 0x26 */
"PCA Allocation IE", /* 0x27 */
"LECIM DSSS Operating Mode IE", /* 0x28 */
"LECIM FSK Operating Mode IE", /* 0x29 */
"Reserved 0x2a", /* 0x2a */
"TVWS PHY Operating Mode Description IE", /* 0x2b */
"TVWS Device Capabilities IE", /* 0x2c */
"TVWS Device Category IE", /* 0x2d */
- "TVWS Device Identiication IE", /* 0x2e */
+ "TVWS Device Identification IE", /* 0x2e */
"TVWS Device Location IE", /* 0x2f */
"TVWS Channel Information Query IE", /* 0x30 */
"TVWS Channel Information Source IE", /* 0x31 */
"CTM IE", /* 0x32 */
"Timestamp IE", /* 0x33 */
"Timestamp Difference IE", /* 0x34 */
"TMCTP Specification IE", /* 0x35 */
"RCC PHY Operating Mode IE", /* 0x36 */
"Reserved 0x37", /* 0x37 */
"Reserved 0x38", /* 0x38 */
"Reserved 0x39", /* 0x39 */
"Reserved 0x3a", /* 0x3a */
"Reserved 0x3b", /* 0x3b */
"Reserved 0x3c", /* 0x3c */
"Reserved 0x3d", /* 0x3d */
"Reserved 0x3e", /* 0x3e */
"Reserved 0x3f", /* 0x3f */
"Reserved 0x40", /* 0x40 */
"Reserved 0x41", /* 0x41 */
"Reserved 0x42", /* 0x42 */
"Reserved 0x43", /* 0x43 */
"Reserved 0x44", /* 0x44 */
"Reserved 0x45", /* 0x45 */
"Reserved 0x46", /* 0x46 */
"Reserved 0x47", /* 0x47 */
"Reserved 0x48", /* 0x48 */
"Reserved 0x49", /* 0x49 */
"Reserved 0x4a", /* 0x4a */
"Reserved 0x4b", /* 0x4b */
"Reserved 0x4c", /* 0x4c */
"Reserved 0x4d", /* 0x4d */
"Reserved 0x4e", /* 0x4e */
"Reserved 0x4f", /* 0x4f */
"Reserved 0x50", /* 0x50 */
"Reserved 0x51", /* 0x51 */
"Reserved 0x52", /* 0x52 */
"Reserved 0x53", /* 0x53 */
"Reserved 0x54", /* 0x54 */
"Reserved 0x55", /* 0x55 */
"Reserved 0x56", /* 0x56 */
"Reserved 0x57", /* 0x57 */
"Reserved 0x58", /* 0x58 */
"Reserved 0x59", /* 0x59 */
"Reserved 0x5a", /* 0x5a */
"Reserved 0x5b", /* 0x5b */
"Reserved 0x5c", /* 0x5c */
"Reserved 0x5d", /* 0x5d */
"Reserved 0x5e", /* 0x5e */
"Reserved 0x5f", /* 0x5f */
"Reserved 0x60", /* 0x60 */
"Reserved 0x61", /* 0x61 */
"Reserved 0x62", /* 0x62 */
"Reserved 0x63", /* 0x63 */
"Reserved 0x64", /* 0x64 */
"Reserved 0x65", /* 0x65 */
"Reserved 0x66", /* 0x66 */
"Reserved 0x67", /* 0x67 */
"Reserved 0x68", /* 0x68 */
"Reserved 0x69", /* 0x69 */
"Reserved 0x6a", /* 0x6a */
"Reserved 0x6b", /* 0x6b */
"Reserved 0x6c", /* 0x6c */
"Reserved 0x6d", /* 0x6d */
"Reserved 0x6e", /* 0x6e */
"Reserved 0x6f", /* 0x6f */
"Reserved 0x70", /* 0x70 */
"Reserved 0x71", /* 0x71 */
"Reserved 0x72", /* 0x72 */
"Reserved 0x73", /* 0x73 */
"Reserved 0x74", /* 0x74 */
"Reserved 0x75", /* 0x75 */
"Reserved 0x76", /* 0x76 */
"Reserved 0x77", /* 0x77 */
"Reserved 0x78", /* 0x78 */
"Reserved 0x79", /* 0x79 */
"Reserved 0x7a", /* 0x7a */
"Reserved 0x7b", /* 0x7b */
"Reserved 0x7c", /* 0x7c */
"Reserved 0x7d", /* 0x7d */
"Reserved 0x7e", /* 0x7e */
"Reserved 0x7f" /* 0x7f */
};
/* Sub-ID for long format from Table 7-17 of 802.15.4-2015 */
static const char *p_mlme_long_names[] = {
"Reserved 0x00", /* 0x00 */
"Reserved 0x01", /* 0x01 */
"Reserved 0x02", /* 0x02 */
"Reserved 0x03", /* 0x03 */
"Reserved 0x04", /* 0x04 */
"Reserved 0x05", /* 0x05 */
"Reserved 0x06", /* 0x06 */
"Reserved 0x07", /* 0x07 */
"Vendor Specific MLME Nested IE", /* 0x08 */
"Channel Hopping IE", /* 0x09 */
"Reserved 0x0a", /* 0x0a */
"Reserved 0x0b", /* 0x0b */
"Reserved 0x0c", /* 0x0c */
"Reserved 0x0d", /* 0x0d */
"Reserved 0x0e", /* 0x0e */
"Reserved 0x0f" /* 0x0f */
};
/* MAC commands from Table 7-49 of 802.15.4-2015 */
static const char *mac_c_names[] = {
"Reserved 0x00", /* 0x00 */
"Association Request command", /* 0x01 */
"Association Response command", /* 0x02 */
"Disassociation Notification command", /* 0x03 */
"Data Request command", /* 0x04 */
"PAN ID Conflict Notification command", /* 0x05 */
"Orphan Notification command", /* 0x06 */
"Beacon Request command", /* 0x07 */
"Coordinator realignment command", /* 0x08 */
"GTS request command", /* 0x09 */
"TRLE Management Request command", /* 0x0a */
"TRLE Management Response command", /* 0x0b */
"Reserved 0x0c", /* 0x0c */
"Reserved 0x0d", /* 0x0d */
"Reserved 0x0e", /* 0x0e */
"Reserved 0x0f", /* 0x0f */
"Reserved 0x10", /* 0x10 */
"Reserved 0x11", /* 0x11 */
"Reserved 0x12", /* 0x12 */
"DSME Association Request command", /* 0x13 */
"DSME Association Response command", /* 0x14 */
"DSME GTS Request command", /* 0x15 */
"DSME GTS Response command", /* 0x16 */
"DSME GTS Notify command", /* 0x17 */
"DSME Information Request command", /* 0x18 */
"DSME Information Response command", /* 0x19 */
"DSME Beacon Allocation Notification command", /* 0x1a */
"DSME Beacon Collision Notification command", /* 0x1b */
"DSME Link Report command", /* 0x1c */
"Reserved 0x1d", /* 0x1d */
"Reserved 0x1e", /* 0x1e */
"Reserved 0x1f", /* 0x1f */
"RIT Data Request command", /* 0x20 */
"DBS Request command", /* 0x21 */
"DBS Response command", /* 0x22 */
"RIT Data Response command", /* 0x23 */
"Vendor Specific command", /* 0x24 */
"Reserved 0x25", /* 0x25 */
"Reserved 0x26", /* 0x26 */
"Reserved 0x27", /* 0x27 */
"Reserved 0x28", /* 0x28 */
"Reserved 0x29", /* 0x29 */
"Reserved 0x2a", /* 0x2a */
"Reserved 0x2b", /* 0x2b */
"Reserved 0x2c", /* 0x2c */
"Reserved 0x2d", /* 0x2d */
"Reserved 0x2e", /* 0x2e */
"Reserved 0x2f" /* 0x2f */
};
/*
* Frame Control subfields.
*/
#define FC_FRAME_TYPE(fc) ((fc) & 0x7)
#define FC_FRAME_VERSION(fc) (((fc) >> 12) & 0x3)
#define FC_ADDRESSING_MODE_NONE 0x00
#define FC_ADDRESSING_MODE_RESERVED 0x01
#define FC_ADDRESSING_MODE_SHORT 0x02
#define FC_ADDRESSING_MODE_LONG 0x03
/*
- * IEEE 802.15.4 CRC 16 function. This is using CCITT polynomical of 0x1021,
+ * IEEE 802.15.4 CRC 16 function. This is using the CCITT polynomial of 0x1021,
* but the initial value is 0, and the bits are reversed for both in and out.
* See section 7.2.10 of 802.15.4-2015 for more information.
*/
static uint16_t
ieee802_15_4_crc16(netdissect_options *ndo, const u_char *p,
u_int data_len)
{
uint16_t crc;
u_char x, y;
crc = 0x0000; /* Note, initial value is 0x0000 not 0xffff. */
while (data_len != 0){
y = GET_U_1(p);
p++;
/* Reverse bits on input */
y = (((y & 0xaa) >> 1) | ((y & 0x55) << 1));
y = (((y & 0xcc) >> 2) | ((y & 0x33) << 2));
y = (((y & 0xf0) >> 4) | ((y & 0x0f) << 4));
/* Update CRC */
x = crc >> 8 ^ y;
x ^= x >> 4;
crc = ((uint16_t)(crc << 8)) ^
((uint16_t)(x << 12)) ^
((uint16_t)(x << 5)) ^
((uint16_t)x);
data_len--;
}
/* Reverse bits on output */
crc = (((crc & 0xaaaa) >> 1) | ((crc & 0x5555) << 1));
crc = (((crc & 0xcccc) >> 2) | ((crc & 0x3333) << 2));
crc = (((crc & 0xf0f0) >> 4) | ((crc & 0x0f0f) << 4));
crc = (((crc & 0xff00) >> 8) | ((crc & 0x00ff) << 8));
return crc;
}
/*
* Reverses the bits of the 32-bit word.
*/
static uint32_t
ieee802_15_4_reverse32(uint32_t x)
{
x = ((x & 0x55555555) << 1) | ((x >> 1) & 0x55555555);
x = ((x & 0x33333333) << 2) | ((x >> 2) & 0x33333333);
x = ((x & 0x0F0F0F0F) << 4) | ((x >> 4) & 0x0F0F0F0F);
x = (x << 24) | ((x & 0xFF00) << 8) |
((x >> 8) & 0xFF00) | (x >> 24);
return x;
}
/*
- * IEEE 802.15.4 CRC 32 function. This is using ANSI X3.66-1979 polynomical of
+ * IEEE 802.15.4 CRC 32 function. This is using the ANSI X3.66-1979 polynomial of
* 0x04C11DB7, but the initial value is 0, and the bits are reversed for both
* in and out. See section 7.2.10 of 802.15.4-2015 for more information.
*/
static uint32_t
ieee802_15_4_crc32(netdissect_options *ndo, const u_char *p,
u_int data_len)
{
uint32_t crc, byte;
int b;
crc = 0x00000000; /* Note, initial value is 0x00000000 not 0xffffffff */
while (data_len != 0){
byte = GET_U_1(p);
p++;
/* Reverse bits on input */
byte = ieee802_15_4_reverse32(byte);
/* Update CRC */
for(b = 0; b <= 7; b++) {
if ((int) (crc ^ byte) < 0)
crc = (crc << 1) ^ 0x04C11DB7;
else
crc = crc << 1;
byte = byte << 1;
}
data_len--;
}
/* Reverse bits on output */
crc = ieee802_15_4_reverse32(crc);
return crc;
}
/*
* Find out the address length based on the address type. See table 7-3 of
* 802.15.4-2015. Returns the address length.
*/
static int
ieee802_15_4_addr_len(uint16_t addr_type)
{
switch (addr_type) {
case FC_ADDRESSING_MODE_NONE: /* None. */
return 0;
break;
case FC_ADDRESSING_MODE_RESERVED: /* Reserved, there used to be 8-bit
* address type in one amendment, but
* that and the feature using it was
* removed during 802.15.4-2015
* maintenance process. */
return -1;
break;
case FC_ADDRESSING_MODE_SHORT: /* Short. */
return 2;
break;
case FC_ADDRESSING_MODE_LONG: /* Extended. */
return 8;
break;
}
return 0;
}
/*
* Print out the ieee 802.15.4 address.
*/
static void
ieee802_15_4_print_addr(netdissect_options *ndo, const u_char *p,
int dst_addr_len)
{
switch (dst_addr_len) {
case 0:
ND_PRINT("none");
break;
case 2:
ND_PRINT("%04x", GET_LE_U_2(p));
break;
case 8:
ND_PRINT("%s", GET_LE64ADDR_STRING(p));
break;
}
}
/*
* Beacon frame superframe specification structure. Used in the old Beacon
* frames, and in the DSME PAN Descriptor IE. See section 7.3.1.3 of the
* 802.15.4-2015.
*/
static void
ieee802_15_4_print_superframe_specification(netdissect_options *ndo,
uint16_t ss)
{
if (ndo->ndo_vflag < 1) {
return;
}
ND_PRINT("\n\tBeacon order = %d, Superframe order = %d, ",
(ss & 0xf), ((ss >> 4) & 0xf));
ND_PRINT("Final CAP Slot = %d",
((ss >> 8) & 0xf));
if (CHECK_BIT(ss, 12)) { ND_PRINT(", BLE enabled"); }
if (CHECK_BIT(ss, 14)) { ND_PRINT(", PAN Coordinator"); }
if (CHECK_BIT(ss, 15)) { ND_PRINT(", Association Permit"); }
}
/*
* Beacon frame gts info structure. Used in the old Beacon frames, and
* in the DSME PAN Descriptor IE. See section 7.3.1.4 of 802.15.4-2015.
*
* Returns number of byts consumed from the packet or -1 in case of error.
*/
static int
ieee802_15_4_print_gts_info(netdissect_options *ndo,
const u_char *p,
u_int data_len)
{
uint8_t gts_spec, gts_cnt;
u_int len;
int i;
gts_spec = GET_U_1(p);
gts_cnt = gts_spec & 0x7;
if (gts_cnt == 0) {
if (ndo->ndo_vflag > 0) {
ND_PRINT("\n\tGTS Descriptor Count = %d, ", gts_cnt);
}
return 1;
}
len = 1 + 1 + gts_cnt * 3;
if (data_len < len) {
ND_PRINT(" [ERROR: Truncated GTS Info List]");
return -1;
}
if (ndo->ndo_vflag < 2) {
return len;
}
ND_PRINT("GTS Descriptor Count = %d, ", gts_cnt);
ND_PRINT("GTS Directions Mask = %02x, [ ",
GET_U_1(p + 1) & 0x7f);
for(i = 0; i < gts_cnt; i++) {
ND_PRINT("[ ");
ieee802_15_4_print_addr(ndo, p + 2 + i * 3, 2);
ND_PRINT(", Start slot = %d, Length = %d ] ",
GET_U_1(p + 2 + i * 3 + 1) & 0x0f,
(GET_U_1(p + 2 + i * 3 + 1) >> 4) & 0x0f);
}
ND_PRINT("]");
return len;
}
/*
* Beacon frame pending address structure. Used in the old Beacon frames, and
* in the DSME PAN Descriptor IE. See section 7.3.1.5 of 802.15.4-2015.
*
* Returns number of byts consumed from the packet or -1 in case of error.
*/
static int16_t
ieee802_15_4_print_pending_addresses(netdissect_options *ndo,
const u_char *p,
u_int data_len)
{
uint8_t pas, s_cnt, e_cnt, len, i;
pas = GET_U_1(p);
s_cnt = pas & 0x7;
e_cnt = (pas >> 4) & 0x7;
len = 1 + s_cnt * 2 + e_cnt * 8;
if (ndo->ndo_vflag > 0) {
ND_PRINT("\n\tPending address list, "
"# short addresses = %d, # extended addresses = %d",
s_cnt, e_cnt);
}
if (data_len < len) {
ND_PRINT(" [ERROR: Pending address list truncated]");
return -1;
}
if (ndo->ndo_vflag < 2) {
return len;
}
if (s_cnt != 0) {
ND_PRINT(", Short address list = [ ");
for(i = 0; i < s_cnt; i++) {
ieee802_15_4_print_addr(ndo, p + 1 + i * 2, 2);
ND_PRINT(" ");
}
ND_PRINT("]");
}
if (e_cnt != 0) {
ND_PRINT(", Extended address list = [ ");
for(i = 0; i < e_cnt; i++) {
ieee802_15_4_print_addr(ndo, p + 1 + s_cnt * 2 +
i * 8, 8);
ND_PRINT(" ");
}
ND_PRINT("]");
}
return len;
}
/*
* Print header ie content.
*/
static void
ieee802_15_4_print_header_ie(netdissect_options *ndo,
const u_char *p,
uint16_t ie_len,
int element_id)
{
int i;
switch (element_id) {
case 0x00: /* Vendor Specific Header IE */
if (ie_len < 3) {
ND_PRINT("[ERROR: Vendor OUI missing]");
} else {
ND_PRINT("OUI = 0x%02x%02x%02x, ", GET_U_1(p),
GET_U_1(p + 1), GET_U_1(p + 2));
ND_PRINT("Data = ");
for(i = 3; i < ie_len; i++) {
ND_PRINT("%02x ", GET_U_1(p + i));
}
}
break;
case 0x1a: /* LE CSL IE */
if (ie_len < 4) {
ND_PRINT("[ERROR: Truncated CSL IE]");
} else {
ND_PRINT("CSL Phase = %d, CSL Period = %d",
GET_LE_U_2(p), GET_LE_U_2(p + 2));
if (ie_len >= 6) {
ND_PRINT(", Rendezvous time = %d",
GET_LE_U_2(p + 4));
}
if (ie_len != 4 && ie_len != 6) {
ND_PRINT(" [ERROR: CSL IE length wrong]");
}
}
break;
case 0x1b: /* LE RIT IE */
if (ie_len < 4) {
ND_PRINT("[ERROR: Truncated RIT IE]");
} else {
ND_PRINT("Time to First Listen = %d, # of Repeat Listen = %d, Repeat Listen Interval = %d",
GET_U_1(p),
GET_U_1(p + 1),
GET_LE_U_2(p + 2));
}
break;
case 0x1c: /* DSME PAN Descriptor IE */
/*FALLTHROUGH*/
case 0x21: /* Extended DSME PAN descriptor IE */
if (ie_len < 2) {
ND_PRINT("[ERROR: Truncated DSME PAN IE]");
} else {
uint16_t ss, ptr, ulen;
int16_t len;
int hopping_present;
hopping_present = 0;
ss = GET_LE_U_2(p);
ieee802_15_4_print_superframe_specification(ndo, ss);
if (ie_len < 3) {
ND_PRINT("[ERROR: Truncated before pending addresses field]");
break;
}
ptr = 2;
len = ieee802_15_4_print_pending_addresses(ndo,
p + ptr,
ie_len -
ptr);
if (len < 0) {
break;
}
ptr += len;
if (element_id == 0x21) {
/* Extended version. */
if (ie_len < ptr + 2) {
ND_PRINT("[ERROR: Truncated before DSME Superframe Specification]");
break;
}
ss = GET_LE_U_2(p + ptr);
ptr += 2;
ND_PRINT("Multi-superframe Order = %d", ss & 0xff);
ND_PRINT(", %s", ((ss & 0x100) ?
"Channel hopping mode" :
"Channel adaptation mode"));
if (ss & 0x400) {
ND_PRINT(", CAP reduction enabled");
}
if (ss & 0x800) {
ND_PRINT(", Deferred beacon enabled");
}
if (ss & 0x1000) {
ND_PRINT(", Hopping Sequence Present");
hopping_present = 1;
}
} else {
if (ie_len < ptr + 1) {
ND_PRINT("[ERROR: Truncated before DSME Superframe Specification]");
break;
}
ss = GET_U_1(p + ptr);
ptr++;
ND_PRINT("Multi-superframe Order = %d",
ss & 0x0f);
ND_PRINT(", %s", ((ss & 0x10) ?
"Channel hopping mode" :
"Channel adaptation mode"));
if (ss & 0x40) {
ND_PRINT(", CAP reduction enabled");
}
if (ss & 0x80) {
ND_PRINT(", Deferred beacon enabled");
}
}
if (ie_len < ptr + 8) {
ND_PRINT(" [ERROR: Truncated before Time synchronization specification]");
break;
}
ND_PRINT("Beacon timestamp = %" PRIu64 ", offset = %d",
GET_LE_U_6(p + ptr),
GET_LE_U_2(p + ptr + 6));
ptr += 8;
if (ie_len < ptr + 4) {
ND_PRINT(" [ERROR: Truncated before Beacon Bitmap]");
break;
}
ulen = GET_LE_U_2(p + ptr + 2);
ND_PRINT("SD Index = %d, Bitmap len = %d, ",
GET_LE_U_2(p + ptr), ulen);
ptr += 4;
if (ie_len < ptr + ulen) {
ND_PRINT(" [ERROR: Truncated in SD bitmap]");
break;
}
ND_PRINT(" SD Bitmap = ");
for(i = 0; i < ulen; i++) {
ND_PRINT("%02x ", GET_U_1(p + ptr + i));
}
ptr += ulen;
if (ie_len < ptr + 5) {
ND_PRINT(" [ERROR: Truncated before Channel hopping specification]");
break;
}
ulen = GET_LE_U_2(p + ptr + 4);
ND_PRINT("Hopping Seq ID = %d, PAN Coordinator BSN = %d, "
"Channel offset = %d, Bitmap length = %d, ",
GET_U_1(p + ptr),
GET_U_1(p + ptr + 1),
GET_LE_U_2(p + ptr + 2),
ulen);
ptr += 5;
if (ie_len < ptr + ulen) {
ND_PRINT(" [ERROR: Truncated in Channel offset bitmap]");
break;
}
ND_PRINT(" Channel offset bitmap = ");
for(i = 0; i < ulen; i++) {
ND_PRINT("%02x ", GET_U_1(p + ptr + i));
}
ptr += ulen;
if (hopping_present) {
if (ie_len < ptr + 1) {
ND_PRINT(" [ERROR: Truncated in Hopping Sequence length]");
break;
}
ulen = GET_U_1(p + ptr);
ptr++;
ND_PRINT("Hopping Seq length = %d [ ", ulen);
/* The specification is not clear how the
hopping sequence is encoded, I assume two
octet unsigned integers for each channel. */
if (ie_len < ptr + ulen * 2) {
ND_PRINT(" [ERROR: Truncated in Channel offset bitmap]");
break;
}
for(i = 0; i < ulen; i++) {
ND_PRINT("%02x ",
GET_LE_U_2(p + ptr + i * 2));
}
ND_PRINT("]");
ptr += ulen * 2;
}
}
break;
case 0x1d: /* Rendezvous Tome IE */
if (ie_len != 4) {
ND_PRINT("[ERROR: Length != 2]");
} else {
uint16_t r_time, w_u_interval;
r_time = GET_LE_U_2(p);
w_u_interval = GET_LE_U_2(p + 2);
ND_PRINT("Rendezvous time = %d, Wake-up Interval = %d",
r_time, w_u_interval);
}
break;
case 0x1e: /* Time correction IE */
if (ie_len != 2) {
ND_PRINT("[ERROR: Length != 2]");
} else {
uint16_t val;
int16_t timecorr;
val = GET_LE_U_2(p);
if (val & 0x8000) { ND_PRINT("Negative "); }
val &= 0xfff;
val <<= 4;
timecorr = val;
timecorr >>= 4;
ND_PRINT("Ack time correction = %d, ", timecorr);
}
break;
case 0x22: /* Fragment Sequence Content Description IE */
/* XXX Not implemented */
case 0x23: /* Simplified Superframe Specification IE */
/* XXX Not implemented */
case 0x24: /* Simplified GTS Specification IE */
/* XXX Not implemented */
case 0x25: /* LECIM Capabilities IE */
/* XXX Not implemented */
case 0x26: /* TRLE Descriptor IE */
/* XXX Not implemented */
case 0x27: /* RCC Capabilities IE */
/* XXX Not implemented */
case 0x28: /* RCCN Descriptor IE */
/* XXX Not implemented */
case 0x29: /* Global Time IE */
/* XXX Not implemented */
case 0x2b: /* DA IE */
/* XXX Not implemented */
default:
ND_PRINT("IE Data = ");
for(i = 0; i < ie_len; i++) {
ND_PRINT("%02x ", GET_U_1(p + i));
}
break;
}
}
/*
* Parse and print Header IE list. See 7.4.2 of 802.15.4-2015 for
* more information.
*
* Returns number of byts consumed from the packet or -1 in case of error.
*/
static int
ieee802_15_4_print_header_ie_list(netdissect_options *ndo,
const u_char *p,
u_int caplen,
int *payload_ie_present)
{
int len, ie, element_id, i;
uint16_t ie_len;
*payload_ie_present = 0;
len = 0;
do {
if (caplen < 2) {
ND_PRINT("[ERROR: Truncated header IE]");
return -1;
}
/* Extract IE Header */
ie = GET_LE_U_2(p);
if (CHECK_BIT(ie, 15)) {
ND_PRINT("[ERROR: Header IE with type 1] ");
}
/* Get length and Element ID */
ie_len = ie & 0x7f;
element_id = (ie >> 7) & 0xff;
if (element_id > 127) {
ND_PRINT("Reserved Element ID %02x, length = %d ",
element_id, ie_len);
} else {
if (ie_len == 0) {
ND_PRINT("\n\t%s [", h_ie_names[element_id]);
} else {
ND_PRINT("\n\t%s [ length = %d, ",
h_ie_names[element_id], ie_len);
}
}
if (caplen < 2U + ie_len) {
ND_PRINT("[ERROR: Truncated IE data]");
return -1;
}
/* Skip header */
p += 2;
/* Parse and print content. */
if (ndo->ndo_vflag > 3 && ie_len != 0) {
ieee802_15_4_print_header_ie(ndo, p,
ie_len, element_id);
} else {
if (ie_len != 0) {
ND_PRINT("IE Data = ");
for(i = 0; i < ie_len; i++) {
ND_PRINT("%02x ", GET_U_1(p + i));
}
}
}
ND_PRINT("] ");
len += 2 + ie_len;
p += ie_len;
caplen -= 2 + ie_len;
if (element_id == 0x7e) {
*payload_ie_present = 1;
break;
}
if (element_id == 0x7f) {
break;
}
} while (caplen != 0);
return len;
}
/*
* Print MLME ie content.
*/
static void
ieee802_15_4_print_mlme_ie(netdissect_options *ndo,
const u_char *p,
uint16_t sub_ie_len,
int sub_id)
{
int i, j;
uint16_t len;
/* Note, as there is no overlap with the long and short
MLME sub IDs, we can just use one switch here. */
switch (sub_id) {
case 0x08: /* Vendor Specific Nested IE */
if (sub_ie_len < 3) {
ND_PRINT("[ERROR: Vendor OUI missing]");
} else {
ND_PRINT("OUI = 0x%02x%02x%02x, ",
GET_U_1(p),
GET_U_1(p + 1),
GET_U_1(p + 2));
ND_PRINT("Data = ");
for(i = 3; i < sub_ie_len; i++) {
ND_PRINT("%02x ", GET_U_1(p + i));
}
}
break;
case 0x09: /* Channel Hopping IE */
if (sub_ie_len < 1) {
ND_PRINT("[ERROR: Hopping sequence ID missing]");
} else if (sub_ie_len == 1) {
ND_PRINT("Hopping Sequence ID = %d", GET_U_1(p));
p++;
sub_ie_len--;
} else {
uint16_t channel_page, number_of_channels;
ND_PRINT("Hopping Sequence ID = %d", GET_U_1(p));
p++;
sub_ie_len--;
if (sub_ie_len < 7) {
ND_PRINT("[ERROR: IE truncated]");
break;
}
channel_page = GET_U_1(p);
number_of_channels = GET_LE_U_2(p + 1);
ND_PRINT("Channel Page = %d, Number of Channels = %d, ",
channel_page, number_of_channels);
ND_PRINT("Phy Configuration = 0x%08x, ",
GET_LE_U_4(p + 3));
p += 7;
sub_ie_len -= 7;
if (channel_page == 9 || channel_page == 10) {
len = (number_of_channels + 7) / 8;
if (sub_ie_len < len) {
ND_PRINT("[ERROR: IE truncated]");
break;
}
ND_PRINT("Extended bitmap = 0x");
for(i = 0; i < len; i++) {
ND_PRINT("%02x", GET_U_1(p + i));
}
ND_PRINT(", ");
p += len;
sub_ie_len -= len;
}
if (sub_ie_len < 2) {
ND_PRINT("[ERROR: IE truncated]");
break;
}
len = GET_LE_U_2(p);
p += 2;
sub_ie_len -= 2;
ND_PRINT("Hopping Seq length = %d [ ", len);
if (sub_ie_len < len * 2) {
ND_PRINT(" [ERROR: IE truncated]");
break;
}
for(i = 0; i < len; i++) {
ND_PRINT("%02x ", GET_LE_U_2(p + i * 2));
}
ND_PRINT("]");
p += len * 2;
sub_ie_len -= len * 2;
if (sub_ie_len < 2) {
ND_PRINT("[ERROR: IE truncated]");
break;
}
ND_PRINT("Current hop = %d", GET_LE_U_2(p));
}
break;
case 0x1a: /* TSCH Synchronization IE. */
if (sub_ie_len < 6) {
ND_PRINT("[ERROR: Length != 6]");
}
ND_PRINT("ASN = %010" PRIx64 ", Join Metric = %d ",
GET_LE_U_5(p), GET_U_1(p + 5));
break;
case 0x1b: /* TSCH Slotframe and Link IE. */
{
int sf_num, off, links, opts;
if (sub_ie_len < 1) {
ND_PRINT("[ERROR: Truncated IE]");
break;
}
sf_num = GET_U_1(p);
ND_PRINT("Slotframes = %d ", sf_num);
off = 1;
for(i = 0; i < sf_num; i++) {
if (sub_ie_len < off + 4) {
ND_PRINT("[ERROR: Truncated IE before slotframes]");
break;
}
links = GET_U_1(p + off + 3);
ND_PRINT("\n\t\t\t[ Handle %d, size = %d, links = %d ",
GET_U_1(p + off),
GET_LE_U_2(p + off + 1),
links);
off += 4;
for(j = 0; j < links; j++) {
if (sub_ie_len < off + 5) {
ND_PRINT("[ERROR: Truncated IE links]");
break;
}
opts = GET_U_1(p + off + 4);
ND_PRINT("\n\t\t\t\t[ Timeslot = %d, Offset = %d, Options = ",
GET_LE_U_2(p + off),
GET_LE_U_2(p + off + 2));
if (opts & 0x1) { ND_PRINT("TX "); }
if (opts & 0x2) { ND_PRINT("RX "); }
if (opts & 0x4) { ND_PRINT("Shared "); }
if (opts & 0x8) {
ND_PRINT("Timekeeping ");
}
if (opts & 0x10) {
ND_PRINT("Priority ");
}
off += 5;
ND_PRINT("] ");
}
ND_PRINT("] ");
}
}
break;
case 0x1c: /* TSCH Timeslot IE. */
if (sub_ie_len == 1) {
ND_PRINT("Time slot ID = %d ", GET_U_1(p));
} else if (sub_ie_len == 25) {
ND_PRINT("Time slot ID = %d, CCA Offset = %d, CCA = %d, TX Offset = %d, RX Offset = %d, RX Ack Delay = %d, TX Ack Delay = %d, RX Wait = %d, Ack Wait = %d, RX TX = %d, Max Ack = %d, Max TX = %d, Time slot Length = %d ",
GET_U_1(p),
GET_LE_U_2(p + 1),
GET_LE_U_2(p + 3),
GET_LE_U_2(p + 5),
GET_LE_U_2(p + 7),
GET_LE_U_2(p + 9),
GET_LE_U_2(p + 11),
GET_LE_U_2(p + 13),
GET_LE_U_2(p + 15),
GET_LE_U_2(p + 17),
GET_LE_U_2(p + 19),
GET_LE_U_2(p + 21),
GET_LE_U_2(p + 23));
} else if (sub_ie_len == 27) {
ND_PRINT("Time slot ID = %d, CCA Offset = %d, CCA = %d, TX Offset = %d, RX Offset = %d, RX Ack Delay = %d, TX Ack Delay = %d, RX Wait = %d, Ack Wait = %d, RX TX = %d, Max Ack = %d, Max TX = %d, Time slot Length = %d ",
GET_U_1(p),
GET_LE_U_2(p + 1),
GET_LE_U_2(p + 3),
GET_LE_U_2(p + 5),
GET_LE_U_2(p + 7),
GET_LE_U_2(p + 9),
GET_LE_U_2(p + 11),
GET_LE_U_2(p + 13),
GET_LE_U_2(p + 15),
GET_LE_U_2(p + 17),
GET_LE_U_2(p + 19),
GET_LE_U_3(p + 21),
GET_LE_U_3(p + 24));
} else {
ND_PRINT("[ERROR: Length not 1, 25, or 27]");
ND_PRINT("\n\t\t\tIE Data = ");
for(i = 0; i < sub_ie_len; i++) {
ND_PRINT("%02x ", GET_U_1(p + i));
}
}
break;
case 0x1d: /* Hopping timing IE */
/* XXX Not implemented */
case 0x1e: /* Enhanced Beacon Filter IE */
/* XXX Not implemented */
case 0x1f: /* MAC Metrics IE */
/* XXX Not implemented */
case 0x20: /* All MAC Metrics IE */
/* XXX Not implemented */
case 0x21: /* Coexistence Specification IE */
/* XXX Not implemented */
case 0x22: /* SUN Device Capabilities IE */
/* XXX Not implemented */
case 0x23: /* SUN FSK Generic PHY IE */
/* XXX Not implemented */
case 0x24: /* Mode Switch Parameter IE */
/* XXX Not implemented */
case 0x25: /* PHY Parameter Change IE */
/* XXX Not implemented */
case 0x26: /* O-QPSK PHY Mode IE */
/* XXX Not implemented */
case 0x27: /* PCA Allocation IE */
/* XXX Not implemented */
case 0x28: /* LECIM DSSS Operating Mode IE */
/* XXX Not implemented */
case 0x29: /* LECIM FSK Operating Mode IE */
/* XXX Not implemented */
case 0x2b: /* TVWS PHY Operating Mode Description IE */
/* XXX Not implemented */
case 0x2c: /* TVWS Device Capabilities IE */
/* XXX Not implemented */
case 0x2d: /* TVWS Device Category IE */
/* XXX Not implemented */
case 0x2e: /* TVWS Device Identification IE */
/* XXX Not implemented */
case 0x2f: /* TVWS Device Location IE */
/* XXX Not implemented */
case 0x30: /* TVWS Channel Information Query IE */
/* XXX Not implemented */
case 0x31: /* TVWS Channel Information Source IE */
/* XXX Not implemented */
case 0x32: /* CTM IE */
/* XXX Not implemented */
case 0x33: /* Timestamp IE */
/* XXX Not implemented */
case 0x34: /* Timestamp Difference IE */
/* XXX Not implemented */
case 0x35: /* TMCTP Specification IE */
/* XXX Not implemented */
case 0x36: /* TCC PHY Operating Mode IE */
/* XXX Not implemented */
default:
ND_PRINT("IE Data = ");
for(i = 0; i < sub_ie_len; i++) {
ND_PRINT("%02x ", GET_U_1(p + i));
}
break;
}
}
/*
* MLME IE list parsing and printing. See 7.4.3.2 of 802.15.4-2015
* for more information.
*/
static void
ieee802_15_4_print_mlme_ie_list(netdissect_options *ndo,
const u_char *p,
uint16_t ie_len)
{
int ie, sub_id, i, type;
uint16_t sub_ie_len;
do {
if (ie_len < 2) {
ND_PRINT("[ERROR: Truncated MLME IE]");
return;
}
/* Extract IE header */
ie = GET_LE_U_2(p);
type = CHECK_BIT(ie, 15);
if (type) {
/* Long type */
sub_ie_len = ie & 0x3ff;
sub_id = (ie >> 11) & 0x0f;
} else {
sub_ie_len = ie & 0xff;
sub_id = (ie >> 8) & 0x7f;
}
/* Skip the IE header */
p += 2;
if (type == 0) {
ND_PRINT("\n\t\t%s [ length = %d, ",
p_mlme_short_names[sub_id], sub_ie_len);
} else {
ND_PRINT("\n\t\t%s [ length = %d, ",
p_mlme_long_names[sub_id], sub_ie_len);
}
if (ie_len < 2 + sub_ie_len) {
ND_PRINT("[ERROR: Truncated IE data]");
return;
}
if (sub_ie_len != 0) {
if (ndo->ndo_vflag > 3) {
ieee802_15_4_print_mlme_ie(ndo, p, sub_ie_len, sub_id);
} else if (ndo->ndo_vflag > 2) {
ND_PRINT("IE Data = ");
for(i = 0; i < sub_ie_len; i++) {
ND_PRINT("%02x ", GET_U_1(p + i));
}
}
}
ND_PRINT("] ");
p += sub_ie_len;
ie_len -= 2 + sub_ie_len;
- } while (ie_len > 0);
+ } while (ie_len != 0);
}
/*
- * Multiplexd IE (802.15.9) parsing and printing.
+ * Multiplexed IE (802.15.9) parsing and printing.
*
* Returns number of bytes consumed from packet or -1 in case of error.
*/
static void
ieee802_15_4_print_mpx_ie(netdissect_options *ndo,
const u_char *p,
uint16_t ie_len)
{
int transfer_type, tid;
int fragment_number, data_start;
int i;
data_start = 0;
if (ie_len < 1) {
ND_PRINT("[ERROR: Transaction control byte missing]");
return;
}
transfer_type = GET_U_1(p) & 0x7;
tid = GET_U_1(p) >> 3;
switch (transfer_type) {
case 0x00: /* Full upper layer frame. */
case 0x01: /* Full upper layer frame with small Multiplex ID. */
ND_PRINT("Type = Full upper layer fragment%s, ",
(transfer_type == 0x01 ?
" with small Multiplex ID" : ""));
if (transfer_type == 0x00) {
if (ie_len < 3) {
ND_PRINT("[ERROR: Multiplex ID missing]");
return;
}
data_start = 3;
ND_PRINT("tid = 0x%02x, Multiplex ID = 0x%04x, ",
tid, GET_LE_U_2(p + 1));
} else {
data_start = 1;
ND_PRINT("Multiplex ID = 0x%04x, ", tid);
}
break;
case 0x02: /* First, or middle, Fragments */
case 0x04: /* Last fragment */
if (ie_len < 2) {
ND_PRINT("[ERROR: fragment number missing]");
return;
}
fragment_number = GET_U_1(p + 1);
ND_PRINT("Type = %s, tid = 0x%02x, fragment = 0x%02x, ",
(transfer_type == 0x02 ?
(fragment_number == 0 ?
"First fragment" : "Middle fragment") :
"Last fragment"), tid,
fragment_number);
data_start = 2;
if (fragment_number == 0) {
int total_size, multiplex_id;
if (ie_len < 6) {
ND_PRINT("[ERROR: Total upper layer size or multiplex ID missing]");
return;
}
total_size = GET_LE_U_2(p + 2);
multiplex_id = GET_LE_U_2(p + 4);
ND_PRINT("Total upper layer size = 0x%04x, Multiplex ID = 0x%04x, ",
total_size, multiplex_id);
data_start = 6;
}
break;
case 0x06: /* Abort code */
if (ie_len == 1) {
ND_PRINT("Type = Abort, tid = 0x%02x, no max size given",
tid);
} else if (ie_len == 3) {
ND_PRINT("Type = Abort, tid = 0x%02x, max size = 0x%04x",
tid, GET_LE_U_2(p + 1));
} else {
ND_PRINT("Type = Abort, tid = 0x%02x, invalid length = %d (not 1 or 3)",
tid, ie_len);
ND_PRINT("Abort data = ");
for(i = 1; i < ie_len; i++) {
ND_PRINT("%02x ", GET_U_1(p + i));
}
}
return;
/* NOTREACHED */
break;
case 0x03: /* Reserved */
case 0x05: /* Reserved */
case 0x07: /* Reserved */
ND_PRINT("Type = %d (Reserved), tid = 0x%02x, ",
transfer_type, tid);
data_start = 1;
break;
}
ND_PRINT("Upper layer data = ");
for(i = data_start; i < ie_len; i++) {
ND_PRINT("%02x ", GET_U_1(p + i));
}
}
/*
* Payload IE list parsing and printing. See 7.4.3 of 802.15.4-2015
* for more information.
*
* Returns number of byts consumed from the packet or -1 in case of error.
*/
static int
ieee802_15_4_print_payload_ie_list(netdissect_options *ndo,
const u_char *p,
u_int caplen)
{
int len, ie, group_id, i;
uint16_t ie_len;
len = 0;
do {
if (caplen < 2) {
ND_PRINT("[ERROR: Truncated header IE]");
return -1;
}
/* Extract IE header */
ie = GET_LE_U_2(p);
if ((CHECK_BIT(ie, 15)) == 0) {
ND_PRINT("[ERROR: Payload IE with type 0] ");
}
ie_len = ie & 0x3ff;
group_id = (ie >> 11) & 0x0f;
/* Skip the IE header */
p += 2;
if (ie_len == 0) {
ND_PRINT("\n\t%s [", p_ie_names[group_id]);
} else {
ND_PRINT("\n\t%s [ length = %d, ",
p_ie_names[group_id], ie_len);
}
if (caplen < 2U + ie_len) {
ND_PRINT("[ERROR: Truncated IE data]");
return -1;
}
if (ndo->ndo_vflag > 3 && ie_len != 0) {
switch (group_id) {
case 0x1: /* MLME IE */
ieee802_15_4_print_mlme_ie_list(ndo, p, ie_len);
break;
case 0x2: /* Vendor Specific Nested IE */
if (ie_len < 3) {
ND_PRINT("[ERROR: Vendor OUI missing]");
} else {
ND_PRINT("OUI = 0x%02x%02x%02x, ",
GET_U_1(p),
GET_U_1(p + 1),
GET_U_1(p + 2));
ND_PRINT("Data = ");
for(i = 3; i < ie_len; i++) {
ND_PRINT("%02x ",
GET_U_1(p + i));
}
}
break;
case 0x3: /* Multiplexed IE (802.15.9) */
ieee802_15_4_print_mpx_ie(ndo, p, ie_len);
break;
case 0x5: /* IETF IE */
if (ie_len < 1) {
ND_PRINT("[ERROR: Subtype ID missing]");
} else {
ND_PRINT("Subtype ID = 0x%02x, Subtype content = ",
GET_U_1(p));
for(i = 1; i < ie_len; i++) {
ND_PRINT("%02x ",
GET_U_1(p + i));
}
}
break;
default:
ND_PRINT("IE Data = ");
for(i = 0; i < ie_len; i++) {
ND_PRINT("%02x ", GET_U_1(p + i));
}
break;
}
} else {
if (ie_len != 0) {
ND_PRINT("IE Data = ");
for(i = 0; i < ie_len; i++) {
ND_PRINT("%02x ", GET_U_1(p + i));
}
}
}
ND_PRINT("]\n\t");
len += 2 + ie_len;
p += ie_len;
caplen -= 2 + ie_len;
if (group_id == 0xf) {
break;
}
- } while (caplen > 0);
+ } while (caplen != 0);
return len;
}
/*
* Parse and print auxiliary security header.
*
* Returns number of byts consumed from the packet or -1 in case of error.
*/
static int
ieee802_15_4_print_aux_sec_header(netdissect_options *ndo,
const u_char *p,
u_int caplen,
int *security_level)
{
int sc, key_id_mode, len;
if (caplen < 1) {
ND_PRINT("[ERROR: Truncated before Aux Security Header]");
return -1;
}
sc = GET_U_1(p);
len = 1;
*security_level = sc & 0x7;
key_id_mode = (sc >> 3) & 0x3;
caplen -= 1;
p += 1;
if (ndo->ndo_vflag > 0) {
ND_PRINT("\n\tSecurity Level %d, Key Id Mode %d, ",
*security_level, key_id_mode);
}
if ((CHECK_BIT(sc, 5)) == 0) {
if (caplen < 4) {
ND_PRINT("[ERROR: Truncated before Frame Counter]");
return -1;
}
if (ndo->ndo_vflag > 1) {
ND_PRINT("Frame Counter 0x%08x ",
GET_LE_U_4(p));
}
p += 4;
caplen -= 4;
len += 4;
}
switch (key_id_mode) {
case 0x00: /* Implicit. */
if (ndo->ndo_vflag > 1) {
ND_PRINT("Implicit");
}
return len;
break;
case 0x01: /* Key Index, nothing to print here. */
break;
case 0x02: /* PAN and Short address Key Source, and Key Index. */
if (caplen < 4) {
ND_PRINT("[ERROR: Truncated before Key Source]");
return -1;
}
if (ndo->ndo_vflag > 1) {
ND_PRINT("KeySource 0x%04x:%0x4x, ",
GET_LE_U_2(p), GET_LE_U_2(p + 2));
}
p += 4;
caplen -= 4;
len += 4;
break;
case 0x03: /* Extended address and Key Index. */
if (caplen < 8) {
ND_PRINT("[ERROR: Truncated before Key Source]");
return -1;
}
if (ndo->ndo_vflag > 1) {
ND_PRINT("KeySource %s, ", GET_LE64ADDR_STRING(p));
}
p += 4;
caplen -= 4;
len += 4;
break;
}
if (caplen < 1) {
ND_PRINT("[ERROR: Truncated before Key Index]");
return -1;
}
if (ndo->ndo_vflag > 1) {
ND_PRINT("KeyIndex 0x%02x, ", GET_U_1(p));
}
caplen -= 1;
p += 1;
len += 1;
return len;
}
/*
* Print command data.
*
* Returns number of byts consumed from the packet or -1 in case of error.
*/
static int
ieee802_15_4_print_command_data(netdissect_options *ndo,
uint8_t command_id,
const u_char *p,
u_int caplen)
{
u_int i;
switch (command_id) {
case 0x01: /* Association Request */
if (caplen != 1) {
ND_PRINT("Invalid Association request command length");
return -1;
} else {
uint8_t cap_info;
cap_info = GET_U_1(p);
ND_PRINT("%s%s%s%s%s%s",
((cap_info & 0x02) ?
"FFD, " : "RFD, "),
((cap_info & 0x04) ?
"AC powered, " : ""),
((cap_info & 0x08) ?
"Receiver on when idle, " : ""),
((cap_info & 0x10) ?
"Fast association, " : ""),
((cap_info & 0x40) ?
"Security supported, " : ""),
((cap_info & 0x80) ?
"Allocate address, " : ""));
return caplen;
}
break;
case 0x02: /* Association Response */
if (caplen != 3) {
ND_PRINT("Invalid Association response command length");
return -1;
} else {
ND_PRINT("Short address = ");
ieee802_15_4_print_addr(ndo, p, 2);
switch (GET_U_1(p + 2)) {
case 0x00:
ND_PRINT(", Association successful");
break;
case 0x01:
ND_PRINT(", PAN at capacity");
break;
case 0x02:
ND_PRINT(", PAN access denied");
break;
case 0x03:
ND_PRINT(", Hooping sequence offset duplication");
break;
case 0x80:
ND_PRINT(", Fast association successful");
break;
default:
ND_PRINT(", Status = 0x%02x",
GET_U_1(p + 2));
break;
}
return caplen;
}
break;
- case 0x03: /* Diassociation Notification command */
+ case 0x03: /* Disassociation Notification command */
if (caplen != 1) {
ND_PRINT("Invalid Disassociation Notification command length");
return -1;
} else {
switch (GET_U_1(p)) {
case 0x00:
ND_PRINT("Reserved");
break;
case 0x01:
ND_PRINT("Reason = The coordinator wishes the device to leave PAN");
break;
case 0x02:
ND_PRINT("Reason = The device wishes to leave the PAN");
break;
default:
ND_PRINT("Reason = 0x%02x", GET_U_1(p + 2));
break;
}
return caplen;
}
/* Following ones do not have any data. */
case 0x04: /* Data Request command */
case 0x05: /* PAN ID Conflict Notification command */
case 0x06: /* Orphan Notification command */
case 0x07: /* Beacon Request command */
/* Should not have any data. */
return 0;
case 0x08: /* Coordinator Realignment command */
if (caplen < 7 || caplen > 8) {
ND_PRINT("Invalid Coordinator Realignment command length");
return -1;
} else {
uint16_t channel, page;
ND_PRINT("Pan ID = 0x%04x, Coordinator short address = ",
GET_LE_U_2(p));
ieee802_15_4_print_addr(ndo, p + 2, 2);
channel = GET_U_1(p + 4);
if (caplen == 8) {
page = GET_U_1(p + 7);
} else {
page = 0x80;
}
if (CHECK_BIT(page, 7)) {
/* No page present, instead we have msb of
channel in the page. */
channel |= (page & 0x7f) << 8;
ND_PRINT(", Channel Number = %d", channel);
} else {
ND_PRINT(", Channel Number = %d, page = %d",
channel, page);
}
ND_PRINT(", Short address = ");
ieee802_15_4_print_addr(ndo, p + 5, 2);
return caplen;
}
break;
case 0x09: /* GTS Request command */
if (caplen != 1) {
ND_PRINT("Invalid GTS Request command length");
return -1;
} else {
uint8_t gts;
gts = GET_U_1(p);
ND_PRINT("GTS Length = %d, %s, %s",
gts & 0xf,
(CHECK_BIT(gts, 4) ?
"Receive-only GTS" : "Transmit-only GTS"),
(CHECK_BIT(gts, 5) ?
"GTS allocation" : "GTS deallocations"));
return caplen;
}
break;
case 0x13: /* DSME Association Request command */
/* XXX Not implemented */
case 0x14: /* DSME Association Response command */
/* XXX Not implemented */
case 0x15: /* DSME GTS Request command */
/* XXX Not implemented */
case 0x16: /* DSME GTS Response command */
/* XXX Not implemented */
case 0x17: /* DSME GTS Notify command */
/* XXX Not implemented */
case 0x18: /* DSME Information Request command */
/* XXX Not implemented */
case 0x19: /* DSME Information Response command */
/* XXX Not implemented */
case 0x1a: /* DSME Beacon Allocation Notification command */
/* XXX Not implemented */
case 0x1b: /* DSME Beacon Collision Notification command */
/* XXX Not implemented */
case 0x1c: /* DSME Link Report command */
/* XXX Not implemented */
case 0x20: /* RIT Data Request command */
/* XXX Not implemented */
case 0x21: /* DBS Request command */
/* XXX Not implemented */
case 0x22: /* DBS Response command */
/* XXX Not implemented */
case 0x23: /* RIT Data Response command */
/* XXX Not implemented */
case 0x24: /* Vendor Specific command */
/* XXX Not implemented */
case 0x0a: /* TRLE Management Request command */
/* XXX Not implemented */
case 0x0b: /* TRLE Management Response command */
/* XXX Not implemented */
default:
ND_PRINT("Command Data = ");
for(i = 0; i < caplen; i++) {
ND_PRINT("%02x ", GET_U_1(p + i));
}
break;
}
return 0;
}
/*
* Parse and print frames following standard format.
*
* Returns FALSE in case of error.
*/
static u_int
ieee802_15_4_std_frames(netdissect_options *ndo,
const u_char *p, u_int caplen,
uint16_t fc)
{
int len, frame_version, pan_id_comp;
int frame_type;
int src_pan, dst_pan, src_addr_len, dst_addr_len;
int security_level;
u_int miclen = 0;
int payload_ie_present;
uint8_t seq;
uint32_t fcs, crc_check;
const u_char *mic_start = NULL;
payload_ie_present = 0;
crc_check = 0;
/* Assume 2 octet FCS, the FCS length depends on the PHY, and we do not
know about that. */
if (caplen < 4) {
/* Cannot have FCS, assume no FCS. */
fcs = 0;
} else {
/* Test for 4 octet FCS. */
fcs = GET_LE_U_4(p + caplen - 4);
crc_check = ieee802_15_4_crc32(ndo, p, caplen - 4);
if (crc_check == fcs) {
/* Remove FCS */
caplen -= 4;
} else {
/* Test for 2 octet FCS. */
fcs = GET_LE_U_2(p + caplen - 2);
crc_check = ieee802_15_4_crc16(ndo, p, caplen - 2);
if (crc_check == fcs) {
/* Remove FCS */
caplen -= 2;
} else {
/* Wrong FCS, FCS might not be included in the
captured frame, do not remove it. */
}
}
}
/* Frame version. */
frame_version = FC_FRAME_VERSION(fc);
frame_type = FC_FRAME_TYPE(fc);
ND_PRINT("v%d ", frame_version);
if (ndo->ndo_vflag > 2) {
if (CHECK_BIT(fc, 3)) { ND_PRINT("Security Enabled, "); }
if (CHECK_BIT(fc, 4)) { ND_PRINT("Frame Pending, "); }
if (CHECK_BIT(fc, 5)) { ND_PRINT("AR, "); }
if (CHECK_BIT(fc, 6)) { ND_PRINT("PAN ID Compression, "); }
if (CHECK_BIT(fc, 8)) { ND_PRINT("Sequence Number Suppression, "); }
if (CHECK_BIT(fc, 9)) { ND_PRINT("IE present, "); }
}
/* Check for the sequence number suppression. */
if (CHECK_BIT(fc, 8)) {
/* Sequence number is suppressed. */
if (frame_version < 2) {
/* Sequence number can only be suppressed for frame
version 2 or higher, this is invalid frame. */
ND_PRINT("[ERROR: Sequence number suppressed on frames where version < 2]");
}
if (ndo->ndo_vflag)
ND_PRINT("seq suppressed ");
if (caplen < 2) {
nd_print_trunc(ndo);
return 0;
}
p += 2;
caplen -= 2;
} else {
seq = GET_U_1(p + 2);
if (ndo->ndo_vflag)
ND_PRINT("seq %02x ", seq);
if (caplen < 3) {
nd_print_trunc(ndo);
return 0;
}
p += 3;
caplen -= 3;
}
/* See which parts of addresses we have. */
dst_addr_len = ieee802_15_4_addr_len((fc >> 10) & 0x3);
src_addr_len = ieee802_15_4_addr_len((fc >> 14) & 0x3);
if (src_addr_len < 0) {
ND_PRINT("[ERROR: Invalid src address mode]");
return 0;
}
if (dst_addr_len < 0) {
ND_PRINT("[ERROR: Invalid dst address mode]");
return 0;
}
src_pan = 0;
dst_pan = 0;
pan_id_comp = CHECK_BIT(fc, 6);
/* The PAN ID Compression rules are complicated. */
/* First check old versions, where the rules are simple. */
if (frame_version < 2) {
if (pan_id_comp) {
src_pan = 0;
dst_pan = 1;
if (dst_addr_len <= 0 || src_addr_len <= 0) {
/* Invalid frame, PAN ID Compression must be 0
if only one address in the frame. */
ND_PRINT("[ERROR: PAN ID Compression != 0, and only one address with frame version < 2]");
}
} else {
src_pan = 1;
dst_pan = 1;
}
if (dst_addr_len <= 0) {
dst_pan = 0;
}
if (src_addr_len <= 0) {
src_pan = 0;
}
} else {
/* Frame version 2 rules are more complicated, and they depend
on the address modes of the frame, generic rules are same,
but then there are some special cases. */
if (pan_id_comp) {
src_pan = 0;
dst_pan = 1;
} else {
src_pan = 1;
dst_pan = 1;
}
if (dst_addr_len <= 0) {
dst_pan = 0;
}
if (src_addr_len <= 0) {
src_pan = 0;
}
if (pan_id_comp) {
if (src_addr_len == 0 &&
dst_addr_len == 0) {
/* Both addresses are missing, but PAN ID
compression set, special case we have
destination PAN but no addresses. */
dst_pan = 1;
} else if ((src_addr_len == 0 &&
dst_addr_len > 0) ||
(src_addr_len > 0 &&
dst_addr_len == 0)) {
/* Only one address present, and PAN ID
compression is set, we do not have PAN id at
all. */
dst_pan = 0;
src_pan = 0;
} else if (src_addr_len == 8 &&
dst_addr_len == 8) {
/* Both addresses are Extended, and PAN ID
compression set, we do not have PAN ID at
all. */
dst_pan = 0;
src_pan = 0;
}
} else {
/* Special cases where PAN ID Compression is not set. */
if (src_addr_len == 8 &&
dst_addr_len == 8) {
/* Both addresses are Extended, and PAN ID
compression not set, we do have only one PAN
ID (destination). */
dst_pan = 1;
src_pan = 0;
}
#ifdef BROKEN_6TISCH_PAN_ID_COMPRESSION
if (src_addr_len == 8 &&
dst_addr_len == 2) {
/* Special case for the broken 6tisch
implementations. */
src_pan = 0;
}
#endif /* BROKEN_6TISCH_PAN_ID_COMPRESSION */
}
}
/* Print dst PAN and address. */
if (dst_pan) {
if (caplen < 2) {
ND_PRINT("[ERROR: Truncated before dst_pan]");
return 0;
}
ND_PRINT("%04x:", GET_LE_U_2(p));
p += 2;
caplen -= 2;
} else {
ND_PRINT("-:");
}
if (caplen < (u_int) dst_addr_len) {
ND_PRINT("[ERROR: Truncated before dst_addr]");
return 0;
}
ieee802_15_4_print_addr(ndo, p, dst_addr_len);
p += dst_addr_len;
caplen -= dst_addr_len;
ND_PRINT(" < ");
/* Print src PAN and address. */
if (src_pan) {
if (caplen < 2) {
ND_PRINT("[ERROR: Truncated before dst_pan]");
return 0;
}
ND_PRINT("%04x:", GET_LE_U_2(p));
p += 2;
caplen -= 2;
} else {
ND_PRINT("-:");
}
if (caplen < (u_int) src_addr_len) {
ND_PRINT("[ERROR: Truncated before dst_addr]");
return 0;
}
ieee802_15_4_print_addr(ndo, p, src_addr_len);
ND_PRINT(" ");
p += src_addr_len;
caplen -= src_addr_len;
if (CHECK_BIT(fc, 3)) {
/*
* XXX - if frame_version is 0, this is the 2003
* spec, and you don't have the auxiliary security
* header, you have a frame counter and key index
* for the AES-CTR and AES-CCM security suites but
* not for the AES-CBC-MAC security suite.
*/
len = ieee802_15_4_print_aux_sec_header(ndo, p, caplen,
&security_level);
if (len < 0) {
return 0;
}
ND_TCHECK_LEN(p, len);
p += len;
caplen -= len;
} else {
security_level = 0;
}
switch (security_level) {
- case 0: /*FALLTHOUGH */
+ case 0: /*FALLTHROUGH */
case 4:
miclen = 0;
break;
- case 1: /*FALLTHOUGH */
+ case 1: /*FALLTHROUGH */
case 5:
miclen = 4;
break;
- case 2: /*FALLTHOUGH */
+ case 2: /*FALLTHROUGH */
case 6:
miclen = 8;
break;
- case 3: /*FALLTHOUGH */
+ case 3: /*FALLTHROUGH */
case 7:
miclen = 16;
break;
}
/* Remove MIC */
if (miclen != 0) {
if (caplen < miclen) {
ND_PRINT("[ERROR: Truncated before MIC]");
return 0;
}
caplen -= miclen;
mic_start = p + caplen;
}
/* Parse Information elements if present */
if (CHECK_BIT(fc, 9)) {
/* Yes we have those. */
len = ieee802_15_4_print_header_ie_list(ndo, p, caplen,
&payload_ie_present);
if (len < 0) {
return 0;
}
p += len;
caplen -= len;
}
if (payload_ie_present) {
if (security_level >= 4) {
ND_PRINT("Payload IEs present, but encrypted, cannot print ");
} else {
len = ieee802_15_4_print_payload_ie_list(ndo, p, caplen);
if (len < 0) {
return 0;
}
p += len;
caplen -= len;
}
}
/* Print MIC */
if (ndo->ndo_vflag > 2 && miclen != 0) {
ND_PRINT("\n\tMIC ");
for (u_int micoffset = 0; micoffset < miclen; micoffset++) {
ND_PRINT("%02x", GET_U_1(mic_start + micoffset));
}
ND_PRINT(" ");
}
/* Print FCS */
if (ndo->ndo_vflag > 2) {
if (crc_check == fcs) {
ND_PRINT("FCS %x ", fcs);
} else {
ND_PRINT("wrong FCS %x vs %x (assume no FCS stored) ",
fcs, crc_check);
}
}
/* Payload print */
switch (frame_type) {
case 0x00: /* Beacon */
if (frame_version < 2) {
if (caplen < 2) {
ND_PRINT("[ERROR: Truncated before beacon information]");
break;
} else {
uint16_t ss;
ss = GET_LE_U_2(p);
ieee802_15_4_print_superframe_specification(ndo, ss);
p += 2;
caplen -= 2;
/* GTS */
if (caplen < 1) {
ND_PRINT("[ERROR: Truncated before GTS info]");
break;
}
len = ieee802_15_4_print_gts_info(ndo, p, caplen);
if (len < 0) {
break;
}
p += len;
caplen -= len;
/* Pending Addresses */
if (caplen < 1) {
ND_PRINT("[ERROR: Truncated before pending addresses]");
break;
}
len = ieee802_15_4_print_pending_addresses(ndo, p, caplen);
if (len < 0) {
break;
}
ND_TCHECK_LEN(p, len);
p += len;
caplen -= len;
}
}
if (!ndo->ndo_suppress_default_print)
ND_DEFAULTPRINT(p, caplen);
break;
case 0x01: /* Data */
case 0x02: /* Acknowledgement */
if (!ndo->ndo_suppress_default_print)
ND_DEFAULTPRINT(p, caplen);
break;
case 0x03: /* MAC Command */
if (caplen < 1) {
ND_PRINT("[ERROR: Truncated before Command ID]");
} else {
uint8_t command_id;
command_id = GET_U_1(p);
if (command_id >= 0x30) {
ND_PRINT("Command ID = Reserved 0x%02x ",
command_id);
} else {
ND_PRINT("Command ID = %s ",
mac_c_names[command_id]);
}
p++;
caplen--;
if (caplen != 0) {
len = ieee802_15_4_print_command_data(ndo, command_id, p, caplen);
if (len >= 0) {
p += len;
caplen -= len;
}
}
}
if (!ndo->ndo_suppress_default_print)
ND_DEFAULTPRINT(p, caplen);
break;
}
return 1;
}
/*
* Print and parse Multipurpose frames.
*
* Returns FALSE in case of error.
*/
static u_int
ieee802_15_4_mp_frame(netdissect_options *ndo,
const u_char *p, u_int caplen,
uint16_t fc)
{
int len, frame_version, pan_id_present;
int src_addr_len, dst_addr_len;
int security_level;
u_int miclen = 0;
int ie_present, payload_ie_present, security_enabled;
uint8_t seq;
uint32_t fcs, crc_check;
const u_char *mic_start = NULL;
pan_id_present = 0;
ie_present = 0;
payload_ie_present = 0;
security_enabled = 0;
crc_check = 0;
/* Assume 2 octet FCS, the FCS length depends on the PHY, and we do not
know about that. */
if (caplen < 3) {
/* Cannot have FCS, assume no FCS. */
fcs = 0;
} else {
if (caplen > 4) {
/* Test for 4 octet FCS. */
fcs = GET_LE_U_4(p + caplen - 4);
crc_check = ieee802_15_4_crc32(ndo, p, caplen - 4);
if (crc_check == fcs) {
/* Remove FCS */
caplen -= 4;
} else {
fcs = GET_LE_U_2(p + caplen - 2);
crc_check = ieee802_15_4_crc16(ndo, p, caplen - 2);
if (crc_check == fcs) {
/* Remove FCS */
caplen -= 2;
}
}
} else {
fcs = GET_LE_U_2(p + caplen - 2);
crc_check = ieee802_15_4_crc16(ndo, p, caplen - 2);
if (crc_check == fcs) {
/* Remove FCS */
caplen -= 2;
}
}
}
if (CHECK_BIT(fc, 3)) {
/* Long Frame Control */
/* Frame version. */
frame_version = FC_FRAME_VERSION(fc);
ND_PRINT("v%d ", frame_version);
pan_id_present = CHECK_BIT(fc, 8);
ie_present = CHECK_BIT(fc, 15);
security_enabled = CHECK_BIT(fc, 9);
if (ndo->ndo_vflag > 2) {
if (security_enabled) { ND_PRINT("Security Enabled, "); }
if (CHECK_BIT(fc, 11)) { ND_PRINT("Frame Pending, "); }
if (CHECK_BIT(fc, 14)) { ND_PRINT("AR, "); }
if (pan_id_present) { ND_PRINT("PAN ID Present, "); }
if (CHECK_BIT(fc, 10)) {
ND_PRINT("Sequence Number Suppression, ");
}
if (ie_present) { ND_PRINT("IE present, "); }
}
/* Check for the sequence number suppression. */
if (CHECK_BIT(fc, 10)) {
/* Sequence number is suppressed, but long version. */
if (caplen < 2) {
nd_print_trunc(ndo);
return 0;
}
p += 2;
caplen -= 2;
} else {
seq = GET_U_1(p + 2);
if (ndo->ndo_vflag)
ND_PRINT("seq %02x ", seq);
if (caplen < 3) {
nd_print_trunc(ndo);
return 0;
}
p += 3;
caplen -= 3;
}
} else {
/* Short format of header, but with seq no */
seq = GET_U_1(p + 1);
p += 2;
caplen -= 2;
if (ndo->ndo_vflag)
ND_PRINT("seq %02x ", seq);
}
/* See which parts of addresses we have. */
dst_addr_len = ieee802_15_4_addr_len((fc >> 4) & 0x3);
src_addr_len = ieee802_15_4_addr_len((fc >> 6) & 0x3);
if (src_addr_len < 0) {
ND_PRINT("[ERROR: Invalid src address mode]");
return 0;
}
if (dst_addr_len < 0) {
ND_PRINT("[ERROR: Invalid dst address mode]");
return 0;
}
/* Print dst PAN and address. */
if (pan_id_present) {
if (caplen < 2) {
ND_PRINT("[ERROR: Truncated before dst_pan]");
return 0;
}
ND_PRINT("%04x:", GET_LE_U_2(p));
p += 2;
caplen -= 2;
} else {
ND_PRINT("-:");
}
if (caplen < (u_int) dst_addr_len) {
ND_PRINT("[ERROR: Truncated before dst_addr]");
return 0;
}
ieee802_15_4_print_addr(ndo, p, dst_addr_len);
p += dst_addr_len;
caplen -= dst_addr_len;
ND_PRINT(" < ");
/* Print src PAN and address. */
ND_PRINT(" -:");
if (caplen < (u_int) src_addr_len) {
ND_PRINT("[ERROR: Truncated before dst_addr]");
return 0;
}
ieee802_15_4_print_addr(ndo, p, src_addr_len);
ND_PRINT(" ");
p += src_addr_len;
caplen -= src_addr_len;
if (security_enabled) {
len = ieee802_15_4_print_aux_sec_header(ndo, p, caplen,
&security_level);
if (len < 0) {
return 0;
}
ND_TCHECK_LEN(p, len);
p += len;
caplen -= len;
} else {
security_level = 0;
}
switch (security_level) {
- case 0: /*FALLTHOUGH */
+ case 0: /*FALLTHROUGH */
case 4:
miclen = 0;
break;
- case 1: /*FALLTHOUGH */
+ case 1: /*FALLTHROUGH */
case 5:
miclen = 4;
break;
- case 2: /*FALLTHOUGH */
+ case 2: /*FALLTHROUGH */
case 6:
miclen = 8;
break;
- case 3: /*FALLTHOUGH */
+ case 3: /*FALLTHROUGH */
case 7:
miclen = 16;
break;
}
/* Remove MIC */
if (miclen != 0) {
if (caplen < miclen) {
ND_PRINT("[ERROR: Truncated before MIC]");
return 0;
}
caplen -= miclen;
mic_start = p + caplen;
}
/* Parse Information elements if present */
if (ie_present) {
/* Yes we have those. */
len = ieee802_15_4_print_header_ie_list(ndo, p, caplen,
&payload_ie_present);
if (len < 0) {
return 0;
}
p += len;
caplen -= len;
}
if (payload_ie_present) {
if (security_level >= 4) {
ND_PRINT("Payload IEs present, but encrypted, cannot print ");
} else {
len = ieee802_15_4_print_payload_ie_list(ndo, p,
caplen);
if (len < 0) {
return 0;
}
p += len;
caplen -= len;
}
}
/* Print MIC */
if (ndo->ndo_vflag > 2 && miclen != 0) {
ND_PRINT("\n\tMIC ");
for (u_int micoffset = 0; micoffset < miclen; micoffset++) {
ND_PRINT("%02x", GET_U_1(mic_start + micoffset));
}
ND_PRINT(" ");
}
/* Print FCS */
if (ndo->ndo_vflag > 2) {
if (crc_check == fcs) {
ND_PRINT("FCS %x ", fcs);
} else {
ND_PRINT("wrong FCS %x vs %x (assume no FCS stored) ",
fcs, crc_check);
}
}
if (!ndo->ndo_suppress_default_print)
ND_DEFAULTPRINT(p, caplen);
return 1;
}
/*
* Print frag frame.
*
* Returns FALSE in case of error.
*/
static u_int
ieee802_15_4_frag_frame(netdissect_options *ndo _U_,
const u_char *p _U_,
u_int caplen _U_,
uint16_t fc _U_)
{
/* Not implement yet, might be bit hard to implement, as the
* information to set up the fragment is coming in the previous frame
* in the Fragment Sequence Context Description IE, thus we need to
* store information from there, so we can use it here. */
return 0;
}
/*
* Internal call to dissector taking packet + len instead of pcap_pkthdr.
*
* Returns FALSE in case of error.
*/
u_int
ieee802_15_4_print(netdissect_options *ndo,
const u_char *p, u_int caplen)
{
int frame_type;
uint16_t fc;
ndo->ndo_protocol = "802.15.4";
if (caplen < 2) {
nd_print_trunc(ndo);
return caplen;
}
fc = GET_LE_U_2(p);
/* First we need to check the frame type to know how to parse the rest
of the FC. Frame type is the first 3 bit of the frame control field.
*/
frame_type = FC_FRAME_TYPE(fc);
ND_PRINT("IEEE 802.15.4 %s packet ", ftypes[frame_type]);
switch (frame_type) {
case 0x00: /* Beacon */
case 0x01: /* Data */
case 0x02: /* Acknowledgement */
case 0x03: /* MAC Command */
return ieee802_15_4_std_frames(ndo, p, caplen, fc);
break;
case 0x04: /* Reserved */
return 0;
break;
case 0x05: /* Multipurpose */
return ieee802_15_4_mp_frame(ndo, p, caplen, fc);
break;
case 0x06: /* Fragment or Frak */
return ieee802_15_4_frag_frame(ndo, p, caplen, fc);
break;
case 0x07: /* Extended */
return 0;
break;
}
return 0;
}
/*
* Main function to print packets.
*/
void
ieee802_15_4_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h, const u_char *p)
{
u_int caplen = h->caplen;
ndo->ndo_protocol = "802.15.4";
ndo->ndo_ll_hdr_len += ieee802_15_4_print(ndo, p, caplen);
}
/* For DLT_IEEE802_15_4_TAP */
/* https://github.com/jkcko/ieee802.15.4-tap */
void
ieee802_15_4_tap_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h, const u_char *p)
{
uint8_t version;
uint16_t length;
ndo->ndo_protocol = "802.15.4_tap";
if (h->caplen < 4) {
nd_print_trunc(ndo);
ndo->ndo_ll_hdr_len += h->caplen;
return;
}
version = GET_U_1(p);
length = GET_LE_U_2(p + 2);
if (version != 0 || length < 4) {
nd_print_invalid(ndo);
return;
}
if (h->caplen < length) {
nd_print_trunc(ndo);
ndo->ndo_ll_hdr_len += h->caplen;
return;
}
ndo->ndo_ll_hdr_len += ieee802_15_4_print(ndo, p+length, h->caplen-length) + length;
}
diff --git a/contrib/tcpdump/print-ah.c b/contrib/tcpdump/print-ah.c
index a3d05544c2d7..3b3a792133c2 100644
--- a/contrib/tcpdump/print-ah.c
+++ b/contrib/tcpdump/print-ah.c
@@ -1,75 +1,73 @@
/* $NetBSD: print-ah.c,v 1.4 1996/05/20 00:41:16 fvdl Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994
* 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.
*/
/* \summary: IPSEC Authentication Header printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "extract.h"
#include "ah.h"
int
ah_print(netdissect_options *ndo, const u_char *bp)
{
const struct ah *ah;
uint8_t ah_len;
u_int ah_hdr_len;
uint16_t reserved;
const u_char *p;
ndo->ndo_protocol = "ah";
ah = (const struct ah *)bp;
nd_print_protocol_caps(ndo);
/*
* RFC4302
*
* 2.2. Payload Length
*
* This 8-bit field specifies the length of AH in 32-bit words (4-byte
* units), minus "2".
*/
ah_len = GET_U_1(ah->ah_len);
ah_hdr_len = (ah_len + 2) * 4;
ND_PRINT("(");
if (ndo->ndo_vflag)
ND_PRINT("length=%u(%u-bytes),", ah_len, ah_hdr_len);
reserved = GET_BE_U_2(ah->ah_reserved);
if (reserved)
ND_PRINT("reserved=0x%x[MustBeZero],", reserved);
ND_PRINT("spi=0x%08x,", GET_BE_U_4(ah->ah_spi));
ND_PRINT("seq=0x%x,", GET_BE_U_4(ah->ah_seq));
ND_PRINT("icv=0x");
for (p = (const u_char *)(ah + 1); p < bp + ah_hdr_len; p++)
ND_PRINT("%02x", GET_U_1(p));
ND_PRINT("): ");
return ah_hdr_len;
}
diff --git a/contrib/tcpdump/print-ahcp.c b/contrib/tcpdump/print-ahcp.c
index d57edda9e090..d2efc7f86bd8 100644
--- a/contrib/tcpdump/print-ahcp.c
+++ b/contrib/tcpdump/print-ahcp.c
@@ -1,384 +1,382 @@
/*
* Copyright (c) 2013 The TCPDUMP project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* \summary: Ad Hoc Configuration Protocol (AHCP) printer */
/* Based on draft-chroboczek-ahcp-00 and source code of ahcpd-0.53 */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
#include "addrtoname.h"
#define AHCP_MAGIC_NUMBER 43
#define AHCP_VERSION_1 1
#define AHCP1_HEADER_FIX_LEN 24
#define AHCP1_BODY_MIN_LEN 4
#define AHCP1_MSG_DISCOVER 0
#define AHCP1_MSG_OFFER 1
#define AHCP1_MSG_REQUEST 2
#define AHCP1_MSG_ACK 3
#define AHCP1_MSG_NACK 4
#define AHCP1_MSG_RELEASE 5
static const struct tok ahcp1_msg_str[] = {
{ AHCP1_MSG_DISCOVER, "Discover" },
{ AHCP1_MSG_OFFER, "Offer" },
{ AHCP1_MSG_REQUEST, "Request" },
{ AHCP1_MSG_ACK, "Ack" },
{ AHCP1_MSG_NACK, "Nack" },
{ AHCP1_MSG_RELEASE, "Release" },
{ 0, NULL }
};
#define AHCP1_OPT_PAD 0
#define AHCP1_OPT_MANDATORY 1
#define AHCP1_OPT_ORIGIN_TIME 2
#define AHCP1_OPT_EXPIRES 3
#define AHCP1_OPT_MY_IPV6_ADDRESS 4
#define AHCP1_OPT_MY_IPV4_ADDRESS 5
#define AHCP1_OPT_IPV6_PREFIX 6
#define AHCP1_OPT_IPV4_PREFIX 7
#define AHCP1_OPT_IPV6_ADDRESS 8
#define AHCP1_OPT_IPV4_ADDRESS 9
#define AHCP1_OPT_IPV6_PREFIX_DELEGATION 10
#define AHCP1_OPT_IPV4_PREFIX_DELEGATION 11
#define AHCP1_OPT_NAME_SERVER 12
#define AHCP1_OPT_NTP_SERVER 13
#define AHCP1_OPT_MAX 13
static const struct tok ahcp1_opt_str[] = {
{ AHCP1_OPT_PAD, "Pad" },
{ AHCP1_OPT_MANDATORY, "Mandatory" },
{ AHCP1_OPT_ORIGIN_TIME, "Origin Time" },
{ AHCP1_OPT_EXPIRES, "Expires" },
{ AHCP1_OPT_MY_IPV6_ADDRESS, "My-IPv6-Address" },
{ AHCP1_OPT_MY_IPV4_ADDRESS, "My-IPv4-Address" },
{ AHCP1_OPT_IPV6_PREFIX, "IPv6 Prefix" },
{ AHCP1_OPT_IPV4_PREFIX, "IPv4 Prefix" },
{ AHCP1_OPT_IPV6_ADDRESS, "IPv6 Address" },
{ AHCP1_OPT_IPV4_ADDRESS, "IPv4 Address" },
{ AHCP1_OPT_IPV6_PREFIX_DELEGATION, "IPv6 Prefix Delegation" },
{ AHCP1_OPT_IPV4_PREFIX_DELEGATION, "IPv4 Prefix Delegation" },
{ AHCP1_OPT_NAME_SERVER, "Name Server" },
{ AHCP1_OPT_NTP_SERVER, "NTP Server" },
{ 0, NULL }
};
static void
ahcp_time_print(netdissect_options *ndo,
const u_char *cp, uint8_t len)
{
time_t t;
char buf[sizeof("-yyyyyyyyyy-mm-dd hh:mm:ss UTC")];
if (len != 4)
goto invalid;
t = GET_BE_U_4(cp);
ND_PRINT(": %s",
nd_format_time(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S UTC",
gmtime(&t)));
return;
invalid:
nd_print_invalid(ndo);
ND_TCHECK_LEN(cp, len);
}
static void
ahcp_seconds_print(netdissect_options *ndo,
const u_char *cp, uint8_t len)
{
if (len != 4)
goto invalid;
ND_PRINT(": %us", GET_BE_U_4(cp));
return;
invalid:
nd_print_invalid(ndo);
ND_TCHECK_LEN(cp, len);
}
static void
ahcp_ipv6_addresses_print(netdissect_options *ndo,
const u_char *cp, uint8_t len)
{
const char *sep = ": ";
while (len) {
if (len < 16)
goto invalid;
ND_PRINT("%s%s", sep, GET_IP6ADDR_STRING(cp));
cp += 16;
len -= 16;
sep = ", ";
}
return;
invalid:
nd_print_invalid(ndo);
ND_TCHECK_LEN(cp, len);
}
static void
ahcp_ipv4_addresses_print(netdissect_options *ndo,
const u_char *cp, uint8_t len)
{
const char *sep = ": ";
while (len) {
if (len < 4)
goto invalid;
ND_PRINT("%s%s", sep, GET_IPADDR_STRING(cp));
cp += 4;
len -= 4;
sep = ", ";
}
return;
invalid:
nd_print_invalid(ndo);
ND_TCHECK_LEN(cp, len);
}
static void
ahcp_ipv6_prefixes_print(netdissect_options *ndo,
const u_char *cp, uint8_t len)
{
const char *sep = ": ";
while (len) {
if (len < 17)
goto invalid;
ND_PRINT("%s%s/%u", sep, GET_IP6ADDR_STRING(cp), GET_U_1(cp + 16));
cp += 17;
len -= 17;
sep = ", ";
}
return;
invalid:
nd_print_invalid(ndo);
ND_TCHECK_LEN(cp, len);
}
static void
ahcp_ipv4_prefixes_print(netdissect_options *ndo,
const u_char *cp, uint8_t len)
{
const char *sep = ": ";
while (len) {
if (len < 5)
goto invalid;
ND_PRINT("%s%s/%u", sep, GET_IPADDR_STRING(cp), GET_U_1(cp + 4));
cp += 5;
len -= 5;
sep = ", ";
}
return;
invalid:
nd_print_invalid(ndo);
ND_TCHECK_LEN(cp, len);
}
static void
(* const data_decoders[AHCP1_OPT_MAX + 1])(netdissect_options *, const u_char *, uint8_t) = {
/* [AHCP1_OPT_PAD] = */ NULL,
/* [AHCP1_OPT_MANDATORY] = */ NULL,
/* [AHCP1_OPT_ORIGIN_TIME] = */ ahcp_time_print,
/* [AHCP1_OPT_EXPIRES] = */ ahcp_seconds_print,
/* [AHCP1_OPT_MY_IPV6_ADDRESS] = */ ahcp_ipv6_addresses_print,
/* [AHCP1_OPT_MY_IPV4_ADDRESS] = */ ahcp_ipv4_addresses_print,
/* [AHCP1_OPT_IPV6_PREFIX] = */ ahcp_ipv6_prefixes_print,
/* [AHCP1_OPT_IPV4_PREFIX] = */ NULL,
/* [AHCP1_OPT_IPV6_ADDRESS] = */ ahcp_ipv6_addresses_print,
/* [AHCP1_OPT_IPV4_ADDRESS] = */ ahcp_ipv4_addresses_print,
/* [AHCP1_OPT_IPV6_PREFIX_DELEGATION] = */ ahcp_ipv6_prefixes_print,
/* [AHCP1_OPT_IPV4_PREFIX_DELEGATION] = */ ahcp_ipv4_prefixes_print,
/* [AHCP1_OPT_NAME_SERVER] = */ ahcp_ipv6_addresses_print,
/* [AHCP1_OPT_NTP_SERVER] = */ ahcp_ipv6_addresses_print,
};
static void
ahcp1_options_print(netdissect_options *ndo,
const u_char *cp, uint16_t len)
{
while (len) {
uint8_t option_no, option_len;
/* Option no */
option_no = GET_U_1(cp);
cp += 1;
len -= 1;
ND_PRINT("\n\t %s", tok2str(ahcp1_opt_str, "Unknown-%u", option_no));
if (option_no == AHCP1_OPT_PAD || option_no == AHCP1_OPT_MANDATORY)
continue;
/* Length */
if (!len)
goto invalid;
option_len = GET_U_1(cp);
cp += 1;
len -= 1;
if (option_len > len)
goto invalid;
/* Value */
if (option_no <= AHCP1_OPT_MAX && data_decoders[option_no] != NULL) {
data_decoders[option_no](ndo, cp, option_len);
} else {
ND_PRINT(" (Length %u)", option_len);
ND_TCHECK_LEN(cp, option_len);
}
cp += option_len;
len -= option_len;
}
return;
invalid:
nd_print_invalid(ndo);
ND_TCHECK_LEN(cp, len);
}
static void
ahcp1_body_print(netdissect_options *ndo,
const u_char *cp, u_int len)
{
uint8_t type, mbz;
uint16_t body_len;
if (len < AHCP1_BODY_MIN_LEN)
goto invalid;
/* Type */
type = GET_U_1(cp);
cp += 1;
len -= 1;
/* MBZ */
mbz = GET_U_1(cp);
cp += 1;
len -= 1;
/* Length */
body_len = GET_BE_U_2(cp);
cp += 2;
len -= 2;
if (ndo->ndo_vflag) {
ND_PRINT("\n\t%s", tok2str(ahcp1_msg_str, "Unknown-%u", type));
if (mbz != 0)
ND_PRINT(", MBZ %u", mbz);
ND_PRINT(", Length %u", body_len);
}
if (body_len > len)
goto invalid;
/* Options */
/* Here use "body_len", not "len" (ignore any extra data). */
if (ndo->ndo_vflag >= 2)
ahcp1_options_print(ndo, cp, body_len);
else
ND_TCHECK_LEN(cp, body_len);
return;
invalid:
nd_print_invalid(ndo);
ND_TCHECK_LEN(cp, len);
}
void
ahcp_print(netdissect_options *ndo,
const u_char *cp, u_int len)
{
uint8_t version;
ndo->ndo_protocol = "ahcp";
nd_print_protocol_caps(ndo);
if (len < 2)
goto invalid;
/* Magic */
if (GET_U_1(cp) != AHCP_MAGIC_NUMBER)
goto invalid;
cp += 1;
len -= 1;
/* Version */
version = GET_U_1(cp);
cp += 1;
len -= 1;
switch (version) {
case AHCP_VERSION_1: {
ND_PRINT(" Version 1");
if (len < AHCP1_HEADER_FIX_LEN - 2)
goto invalid;
if (!ndo->ndo_vflag) {
ND_TCHECK_LEN(cp, AHCP1_HEADER_FIX_LEN - 2);
cp += AHCP1_HEADER_FIX_LEN - 2;
len -= AHCP1_HEADER_FIX_LEN - 2;
} else {
/* Hopcount */
ND_PRINT("\n\tHopcount %u", GET_U_1(cp));
cp += 1;
len -= 1;
/* Original Hopcount */
ND_PRINT(", Original Hopcount %u", GET_U_1(cp));
cp += 1;
len -= 1;
/* Nonce */
ND_PRINT(", Nonce 0x%08x", GET_BE_U_4(cp));
cp += 4;
len -= 4;
/* Source Id */
ND_PRINT(", Source Id %s", GET_LINKADDR_STRING(cp, LINKADDR_OTHER, 8));
cp += 8;
len -= 8;
/* Destination Id */
ND_PRINT(", Destination Id %s", GET_LINKADDR_STRING(cp, LINKADDR_OTHER, 8));
cp += 8;
len -= 8;
}
/* Body */
ahcp1_body_print(ndo, cp, len);
break;
}
default:
ND_PRINT(" Version %u (unknown)", version);
ND_TCHECK_LEN(cp, len);
break;
}
return;
invalid:
nd_print_invalid(ndo);
ND_TCHECK_LEN(cp, len);
}
diff --git a/contrib/tcpdump/print-aodv.c b/contrib/tcpdump/print-aodv.c
index 97421433f7f4..b69f546e0bcf 100644
--- a/contrib/tcpdump/print-aodv.c
+++ b/contrib/tcpdump/print-aodv.c
@@ -1,537 +1,535 @@
/*
* Copyright (c) 2003 Bruce M. Simpson <bms@spc.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Bruce M. Simpson.
* 4. Neither the name of Bruce M. Simpson nor the names of co-
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Bruce M. Simpson AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Bruce M. Simpson OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* \summary: Ad hoc On-Demand Distance Vector (AODV) Routing printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
/*
* RFC 3561
*/
struct aodv_rreq {
nd_uint8_t rreq_type; /* AODV message type (1) */
nd_uint8_t rreq_flags; /* various flags */
nd_uint8_t rreq_zero0; /* reserved, set to zero */
nd_uint8_t rreq_hops; /* number of hops from originator */
nd_uint32_t rreq_id; /* request ID */
nd_ipv4 rreq_da; /* destination IPv4 address */
nd_uint32_t rreq_ds; /* destination sequence number */
nd_ipv4 rreq_oa; /* originator IPv4 address */
nd_uint32_t rreq_os; /* originator sequence number */
};
struct aodv_rreq6 {
nd_uint8_t rreq_type; /* AODV message type (1) */
nd_uint8_t rreq_flags; /* various flags */
nd_uint8_t rreq_zero0; /* reserved, set to zero */
nd_uint8_t rreq_hops; /* number of hops from originator */
nd_uint32_t rreq_id; /* request ID */
nd_ipv6 rreq_da; /* destination IPv6 address */
nd_uint32_t rreq_ds; /* destination sequence number */
nd_ipv6 rreq_oa; /* originator IPv6 address */
nd_uint32_t rreq_os; /* originator sequence number */
};
struct aodv_rreq6_draft_01 {
nd_uint8_t rreq_type; /* AODV message type (16) */
nd_uint8_t rreq_flags; /* various flags */
nd_uint8_t rreq_zero0; /* reserved, set to zero */
nd_uint8_t rreq_hops; /* number of hops from originator */
nd_uint32_t rreq_id; /* request ID */
nd_uint32_t rreq_ds; /* destination sequence number */
nd_uint32_t rreq_os; /* originator sequence number */
nd_ipv6 rreq_da; /* destination IPv6 address */
nd_ipv6 rreq_oa; /* originator IPv6 address */
};
#define RREQ_JOIN 0x80 /* join (reserved for multicast */
#define RREQ_REPAIR 0x40 /* repair (reserved for multicast */
#define RREQ_GRAT 0x20 /* gratuitous RREP */
#define RREQ_DEST 0x10 /* destination only */
#define RREQ_UNKNOWN 0x08 /* unknown destination sequence num */
#define RREQ_FLAGS_MASK 0xF8 /* mask for rreq_flags */
struct aodv_rrep {
nd_uint8_t rrep_type; /* AODV message type (2) */
nd_uint8_t rrep_flags; /* various flags */
nd_uint8_t rrep_ps; /* prefix size */
nd_uint8_t rrep_hops; /* number of hops from o to d */
nd_ipv4 rrep_da; /* destination IPv4 address */
nd_uint32_t rrep_ds; /* destination sequence number */
nd_ipv4 rrep_oa; /* originator IPv4 address */
nd_uint32_t rrep_life; /* lifetime of this route */
};
struct aodv_rrep6 {
nd_uint8_t rrep_type; /* AODV message type (2) */
nd_uint8_t rrep_flags; /* various flags */
nd_uint8_t rrep_ps; /* prefix size */
nd_uint8_t rrep_hops; /* number of hops from o to d */
nd_ipv6 rrep_da; /* destination IPv6 address */
nd_uint32_t rrep_ds; /* destination sequence number */
nd_ipv6 rrep_oa; /* originator IPv6 address */
nd_uint32_t rrep_life; /* lifetime of this route */
};
struct aodv_rrep6_draft_01 {
nd_uint8_t rrep_type; /* AODV message type (17) */
nd_uint8_t rrep_flags; /* various flags */
nd_uint8_t rrep_ps; /* prefix size */
nd_uint8_t rrep_hops; /* number of hops from o to d */
nd_uint32_t rrep_ds; /* destination sequence number */
nd_ipv6 rrep_da; /* destination IPv6 address */
nd_ipv6 rrep_oa; /* originator IPv6 address */
nd_uint32_t rrep_life; /* lifetime of this route */
};
#define RREP_REPAIR 0x80 /* repair (reserved for multicast */
#define RREP_ACK 0x40 /* acknowledgement required */
#define RREP_FLAGS_MASK 0xC0 /* mask for rrep_flags */
#define RREP_PREFIX_MASK 0x1F /* mask for prefix size */
struct rerr_unreach {
nd_ipv4 u_da; /* IPv4 address */
nd_uint32_t u_ds; /* sequence number */
};
struct rerr_unreach6 {
nd_ipv6 u_da; /* IPv6 address */
nd_uint32_t u_ds; /* sequence number */
};
struct rerr_unreach6_draft_01 {
nd_ipv6 u_da; /* IPv6 address */
nd_uint32_t u_ds; /* sequence number */
};
struct aodv_rerr {
nd_uint8_t rerr_type; /* AODV message type (3 or 18) */
nd_uint8_t rerr_flags; /* various flags */
nd_uint8_t rerr_zero0; /* reserved, set to zero */
nd_uint8_t rerr_dc; /* destination count */
};
#define RERR_NODELETE 0x80 /* don't delete the link */
#define RERR_FLAGS_MASK 0x80 /* mask for rerr_flags */
struct aodv_rrep_ack {
nd_uint8_t ra_type;
nd_uint8_t ra_zero0;
};
#define AODV_RREQ 1 /* route request */
#define AODV_RREP 2 /* route response */
#define AODV_RERR 3 /* error report */
#define AODV_RREP_ACK 4 /* route response acknowledgement */
#define AODV_V6_DRAFT_01_RREQ 16 /* IPv6 route request */
#define AODV_V6_DRAFT_01_RREP 17 /* IPv6 route response */
#define AODV_V6_DRAFT_01_RERR 18 /* IPv6 error report */
#define AODV_V6_DRAFT_01_RREP_ACK 19 /* IPV6 route response acknowledgment */
struct aodv_ext {
nd_uint8_t type; /* extension type */
nd_uint8_t length; /* extension length */
};
struct aodv_hello {
struct aodv_ext eh; /* extension header */
nd_uint32_t interval; /* expect my next hello in
* (n) ms
* NOTE: this is not aligned */
};
#define AODV_EXT_HELLO 1
static void
aodv_extension(netdissect_options *ndo,
const struct aodv_ext *ep, u_int length)
{
const struct aodv_hello *ah;
ND_TCHECK_SIZE(ep);
switch (GET_U_1(ep->type)) {
case AODV_EXT_HELLO:
ah = (const struct aodv_hello *)(const void *)ep;
ND_TCHECK_SIZE(ah);
if (length < sizeof(struct aodv_hello))
goto trunc;
if (GET_U_1(ep->length) < 4) {
ND_PRINT("\n\text HELLO - bad length %u",
GET_U_1(ep->length));
break;
}
ND_PRINT("\n\text HELLO %u ms",
GET_BE_U_4(ah->interval));
break;
default:
ND_PRINT("\n\text %u %u", GET_U_1(ep->type),
GET_U_1(ep->length));
break;
}
return;
trunc:
nd_print_trunc(ndo);
}
static void
aodv_rreq(netdissect_options *ndo, const u_char *dat, u_int length)
{
u_int i;
const struct aodv_rreq *ap = (const struct aodv_rreq *)dat;
ND_TCHECK_SIZE(ap);
if (length < sizeof(*ap))
goto trunc;
ND_PRINT(" rreq %u %s%s%s%s%shops %u id 0x%08x\n"
"\tdst %s seq %u src %s seq %u", length,
GET_U_1(ap->rreq_type) & RREQ_JOIN ? "[J]" : "",
GET_U_1(ap->rreq_type) & RREQ_REPAIR ? "[R]" : "",
GET_U_1(ap->rreq_type) & RREQ_GRAT ? "[G]" : "",
GET_U_1(ap->rreq_type) & RREQ_DEST ? "[D]" : "",
GET_U_1(ap->rreq_type) & RREQ_UNKNOWN ? "[U] " : " ",
GET_U_1(ap->rreq_hops),
GET_BE_U_4(ap->rreq_id),
GET_IPADDR_STRING(ap->rreq_da),
GET_BE_U_4(ap->rreq_ds),
GET_IPADDR_STRING(ap->rreq_oa),
GET_BE_U_4(ap->rreq_os));
i = length - sizeof(*ap);
if (i >= sizeof(struct aodv_ext))
aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i);
return;
trunc:
nd_print_trunc(ndo);
}
static void
aodv_rrep(netdissect_options *ndo, const u_char *dat, u_int length)
{
u_int i;
const struct aodv_rrep *ap = (const struct aodv_rrep *)dat;
ND_TCHECK_SIZE(ap);
if (length < sizeof(*ap))
goto trunc;
ND_PRINT(" rrep %u %s%sprefix %u hops %u\n"
"\tdst %s dseq %u src %s %u ms", length,
GET_U_1(ap->rrep_type) & RREP_REPAIR ? "[R]" : "",
GET_U_1(ap->rrep_type) & RREP_ACK ? "[A] " : " ",
GET_U_1(ap->rrep_ps) & RREP_PREFIX_MASK,
GET_U_1(ap->rrep_hops),
GET_IPADDR_STRING(ap->rrep_da),
GET_BE_U_4(ap->rrep_ds),
GET_IPADDR_STRING(ap->rrep_oa),
GET_BE_U_4(ap->rrep_life));
i = length - sizeof(*ap);
if (i >= sizeof(struct aodv_ext))
aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i);
return;
trunc:
nd_print_trunc(ndo);
}
static void
aodv_rerr(netdissect_options *ndo, const u_char *dat, u_int length)
{
u_int i, dc;
const struct aodv_rerr *ap = (const struct aodv_rerr *)dat;
const struct rerr_unreach *dp;
ND_TCHECK_SIZE(ap);
if (length < sizeof(*ap))
goto trunc;
ND_PRINT(" rerr %s [items %u] [%u]:",
GET_U_1(ap->rerr_flags) & RERR_NODELETE ? "[D]" : "",
GET_U_1(ap->rerr_dc), length);
dp = (const struct rerr_unreach *)(dat + sizeof(*ap));
i = length - sizeof(*ap);
for (dc = GET_U_1(ap->rerr_dc); dc != 0; dc--) {
ND_TCHECK_SIZE(dp);
if (i < sizeof(*dp))
goto trunc;
ND_PRINT(" {%s}(%u)", GET_IPADDR_STRING(dp->u_da),
GET_BE_U_4(dp->u_ds));
dp++;
i -= sizeof(*dp);
}
return;
trunc:
nd_print_trunc(ndo);
}
static void
aodv_v6_rreq(netdissect_options *ndo, const u_char *dat, u_int length)
{
u_int i;
const struct aodv_rreq6 *ap = (const struct aodv_rreq6 *)dat;
ND_TCHECK_SIZE(ap);
if (length < sizeof(*ap))
goto trunc;
ND_PRINT(" v6 rreq %u %s%s%s%s%shops %u id 0x%08x\n"
"\tdst %s seq %u src %s seq %u", length,
GET_U_1(ap->rreq_type) & RREQ_JOIN ? "[J]" : "",
GET_U_1(ap->rreq_type) & RREQ_REPAIR ? "[R]" : "",
GET_U_1(ap->rreq_type) & RREQ_GRAT ? "[G]" : "",
GET_U_1(ap->rreq_type) & RREQ_DEST ? "[D]" : "",
GET_U_1(ap->rreq_type) & RREQ_UNKNOWN ? "[U] " : " ",
GET_U_1(ap->rreq_hops),
GET_BE_U_4(ap->rreq_id),
GET_IP6ADDR_STRING(ap->rreq_da),
GET_BE_U_4(ap->rreq_ds),
GET_IP6ADDR_STRING(ap->rreq_oa),
GET_BE_U_4(ap->rreq_os));
i = length - sizeof(*ap);
if (i >= sizeof(struct aodv_ext))
aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i);
return;
trunc:
nd_print_trunc(ndo);
}
static void
aodv_v6_rrep(netdissect_options *ndo, const u_char *dat, u_int length)
{
u_int i;
const struct aodv_rrep6 *ap = (const struct aodv_rrep6 *)dat;
ND_TCHECK_SIZE(ap);
if (length < sizeof(*ap))
goto trunc;
ND_PRINT(" rrep %u %s%sprefix %u hops %u\n"
"\tdst %s dseq %u src %s %u ms", length,
GET_U_1(ap->rrep_type) & RREP_REPAIR ? "[R]" : "",
GET_U_1(ap->rrep_type) & RREP_ACK ? "[A] " : " ",
GET_U_1(ap->rrep_ps) & RREP_PREFIX_MASK,
GET_U_1(ap->rrep_hops),
GET_IP6ADDR_STRING(ap->rrep_da),
GET_BE_U_4(ap->rrep_ds),
GET_IP6ADDR_STRING(ap->rrep_oa),
GET_BE_U_4(ap->rrep_life));
i = length - sizeof(*ap);
if (i >= sizeof(struct aodv_ext))
aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i);
return;
trunc:
nd_print_trunc(ndo);
}
static void
aodv_v6_rerr(netdissect_options *ndo, const u_char *dat, u_int length)
{
u_int i, dc;
const struct aodv_rerr *ap = (const struct aodv_rerr *)dat;
const struct rerr_unreach6 *dp6;
ND_TCHECK_SIZE(ap);
if (length < sizeof(*ap))
goto trunc;
ND_PRINT(" rerr %s [items %u] [%u]:",
GET_U_1(ap->rerr_flags) & RERR_NODELETE ? "[D]" : "",
GET_U_1(ap->rerr_dc), length);
dp6 = (const struct rerr_unreach6 *)(const void *)(ap + 1);
i = length - sizeof(*ap);
for (dc = GET_U_1(ap->rerr_dc); dc != 0; dc--) {
ND_TCHECK_SIZE(dp6);
if (i < sizeof(*dp6))
goto trunc;
ND_PRINT(" {%s}(%u)", GET_IP6ADDR_STRING(dp6->u_da),
GET_BE_U_4(dp6->u_ds));
dp6++;
i -= sizeof(*dp6);
}
return;
trunc:
nd_print_trunc(ndo);
}
static void
aodv_v6_draft_01_rreq(netdissect_options *ndo, const u_char *dat, u_int length)
{
u_int i;
const struct aodv_rreq6_draft_01 *ap = (const struct aodv_rreq6_draft_01 *)dat;
ND_TCHECK_SIZE(ap);
if (length < sizeof(*ap))
goto trunc;
ND_PRINT(" rreq %u %s%s%s%s%shops %u id 0x%08x\n"
"\tdst %s seq %u src %s seq %u", length,
GET_U_1(ap->rreq_type) & RREQ_JOIN ? "[J]" : "",
GET_U_1(ap->rreq_type) & RREQ_REPAIR ? "[R]" : "",
GET_U_1(ap->rreq_type) & RREQ_GRAT ? "[G]" : "",
GET_U_1(ap->rreq_type) & RREQ_DEST ? "[D]" : "",
GET_U_1(ap->rreq_type) & RREQ_UNKNOWN ? "[U] " : " ",
GET_U_1(ap->rreq_hops),
GET_BE_U_4(ap->rreq_id),
GET_IP6ADDR_STRING(ap->rreq_da),
GET_BE_U_4(ap->rreq_ds),
GET_IP6ADDR_STRING(ap->rreq_oa),
GET_BE_U_4(ap->rreq_os));
i = length - sizeof(*ap);
if (i >= sizeof(struct aodv_ext))
aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i);
return;
trunc:
nd_print_trunc(ndo);
}
static void
aodv_v6_draft_01_rrep(netdissect_options *ndo, const u_char *dat, u_int length)
{
u_int i;
const struct aodv_rrep6_draft_01 *ap = (const struct aodv_rrep6_draft_01 *)dat;
ND_TCHECK_SIZE(ap);
if (length < sizeof(*ap))
goto trunc;
ND_PRINT(" rrep %u %s%sprefix %u hops %u\n"
"\tdst %s dseq %u src %s %u ms", length,
GET_U_1(ap->rrep_type) & RREP_REPAIR ? "[R]" : "",
GET_U_1(ap->rrep_type) & RREP_ACK ? "[A] " : " ",
GET_U_1(ap->rrep_ps) & RREP_PREFIX_MASK,
GET_U_1(ap->rrep_hops),
GET_IP6ADDR_STRING(ap->rrep_da),
GET_BE_U_4(ap->rrep_ds),
GET_IP6ADDR_STRING(ap->rrep_oa),
GET_BE_U_4(ap->rrep_life));
i = length - sizeof(*ap);
if (i >= sizeof(struct aodv_ext))
aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i);
return;
trunc:
nd_print_trunc(ndo);
}
static void
aodv_v6_draft_01_rerr(netdissect_options *ndo, const u_char *dat, u_int length)
{
u_int i, dc;
const struct aodv_rerr *ap = (const struct aodv_rerr *)dat;
const struct rerr_unreach6_draft_01 *dp6;
ND_TCHECK_SIZE(ap);
if (length < sizeof(*ap))
goto trunc;
ND_PRINT(" rerr %s [items %u] [%u]:",
GET_U_1(ap->rerr_flags) & RERR_NODELETE ? "[D]" : "",
GET_U_1(ap->rerr_dc), length);
dp6 = (const struct rerr_unreach6_draft_01 *)(const void *)(ap + 1);
i = length - sizeof(*ap);
for (dc = GET_U_1(ap->rerr_dc); dc != 0; dc--) {
ND_TCHECK_SIZE(dp6);
if (i < sizeof(*dp6))
goto trunc;
ND_PRINT(" {%s}(%u)", GET_IP6ADDR_STRING(dp6->u_da),
GET_BE_U_4(dp6->u_ds));
dp6++;
i -= sizeof(*dp6);
}
return;
trunc:
nd_print_trunc(ndo);
}
void
aodv_print(netdissect_options *ndo,
const u_char *dat, u_int length, int is_ip6)
{
uint8_t msg_type;
ndo->ndo_protocol = "aodv";
/*
* The message type is the first byte; make sure we have it
* and then fetch it.
*/
msg_type = GET_U_1(dat);
ND_PRINT(" aodv");
switch (msg_type) {
case AODV_RREQ:
if (is_ip6)
aodv_v6_rreq(ndo, dat, length);
else
aodv_rreq(ndo, dat, length);
break;
case AODV_RREP:
if (is_ip6)
aodv_v6_rrep(ndo, dat, length);
else
aodv_rrep(ndo, dat, length);
break;
case AODV_RERR:
if (is_ip6)
aodv_v6_rerr(ndo, dat, length);
else
aodv_rerr(ndo, dat, length);
break;
case AODV_RREP_ACK:
ND_PRINT(" rrep-ack %u", length);
break;
case AODV_V6_DRAFT_01_RREQ:
aodv_v6_draft_01_rreq(ndo, dat, length);
break;
case AODV_V6_DRAFT_01_RREP:
aodv_v6_draft_01_rrep(ndo, dat, length);
break;
case AODV_V6_DRAFT_01_RERR:
aodv_v6_draft_01_rerr(ndo, dat, length);
break;
case AODV_V6_DRAFT_01_RREP_ACK:
ND_PRINT(" rrep-ack %u", length);
break;
default:
ND_PRINT(" type %u %u", msg_type, length);
}
}
diff --git a/contrib/tcpdump/print-aoe.c b/contrib/tcpdump/print-aoe.c
index 0cd4299a7a6b..cca8c79108fd 100644
--- a/contrib/tcpdump/print-aoe.c
+++ b/contrib/tcpdump/print-aoe.c
@@ -1,413 +1,411 @@
/*
* Copyright (c) 2014 The TCPDUMP project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* \summary: ATA over Ethernet (AoE) protocol printer */
/* specification:
* https://web.archive.org/web/20161025044402/http://brantleycoilecompany.com/AoEr11.pdf
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
#include "addrtoname.h"
#define AOE_V1 1
#define ATA_SECTOR_SIZE 512
#define AOEV1_CMD_ISSUE_ATA_COMMAND 0
#define AOEV1_CMD_QUERY_CONFIG_INFORMATION 1
#define AOEV1_CMD_MAC_MASK_LIST 2
#define AOEV1_CMD_RESERVE_RELEASE 3
static const struct tok cmdcode_str[] = {
{ AOEV1_CMD_ISSUE_ATA_COMMAND, "Issue ATA Command" },
{ AOEV1_CMD_QUERY_CONFIG_INFORMATION, "Query Config Information" },
{ AOEV1_CMD_MAC_MASK_LIST, "MAC Mask List" },
{ AOEV1_CMD_RESERVE_RELEASE, "Reserve/Release" },
{ 0, NULL }
};
#define AOEV1_COMMON_HDR_LEN 10U /* up to but w/o Arg */
#define AOEV1_ISSUE_ARG_LEN 12U /* up to but w/o Data */
#define AOEV1_QUERY_ARG_LEN 8U /* up to but w/o Config String */
#define AOEV1_MAC_ARG_LEN 4U /* up to but w/o Directive 0 */
#define AOEV1_RESERVE_ARG_LEN 2U /* up to but w/o Ethernet address 0 */
#define AOEV1_MAX_CONFSTR_LEN 1024U
#define AOEV1_FLAG_R 0x08
#define AOEV1_FLAG_E 0x04
static const struct tok aoev1_flag_str[] = {
{ AOEV1_FLAG_R, "Response" },
{ AOEV1_FLAG_E, "Error" },
{ 0x02, "MBZ-1" },
{ 0x01, "MBZ-0" },
{ 0, NULL }
};
static const struct tok aoev1_errcode_str[] = {
{ 1, "Unrecognized command code" },
{ 2, "Bad argument parameter" },
{ 3, "Device unavailable" },
{ 4, "Config string present" },
{ 5, "Unsupported version" },
{ 6, "Target is reserved" },
{ 0, NULL }
};
#define AOEV1_AFLAG_E 0x40
#define AOEV1_AFLAG_D 0x10
#define AOEV1_AFLAG_A 0x02
#define AOEV1_AFLAG_W 0x01
static const struct tok aoev1_aflag_bitmap_str[] = {
{ 0x80, "MBZ-7" },
{ AOEV1_AFLAG_E, "Ext48" },
{ 0x20, "MBZ-5" },
{ AOEV1_AFLAG_D, "Device" },
{ 0x08, "MBZ-3" },
{ 0x04, "MBZ-2" },
{ AOEV1_AFLAG_A, "Async" },
{ AOEV1_AFLAG_W, "Write" },
{ 0, NULL }
};
static const struct tok aoev1_ccmd_str[] = {
{ 0, "read config string" },
{ 1, "test config string" },
{ 2, "test config string prefix" },
{ 3, "set config string" },
{ 4, "force set config string" },
{ 0, NULL }
};
static const struct tok aoev1_mcmd_str[] = {
{ 0, "Read Mac Mask List" },
{ 1, "Edit Mac Mask List" },
{ 0, NULL }
};
static const struct tok aoev1_merror_str[] = {
{ 1, "Unspecified Error" },
{ 2, "Bad DCmd directive" },
{ 3, "Mask list full" },
{ 0, NULL }
};
static const struct tok aoev1_dcmd_str[] = {
{ 0, "No Directive" },
{ 1, "Add mac address to mask list" },
{ 2, "Delete mac address from mask list" },
{ 0, NULL }
};
static const struct tok aoev1_rcmd_str[] = {
{ 0, "Read reserve list" },
{ 1, "Set reserve list" },
{ 2, "Force set reserve list" },
{ 0, NULL }
};
static void
aoev1_issue_print(netdissect_options *ndo,
const u_char *cp, u_int len)
{
if (len < AOEV1_ISSUE_ARG_LEN)
goto invalid;
/* AFlags */
ND_PRINT("\n\tAFlags: [%s]",
bittok2str(aoev1_aflag_bitmap_str, "none", GET_U_1(cp)));
cp += 1;
len -= 1;
/* Err/Feature */
ND_PRINT(", Err/Feature: %u", GET_U_1(cp));
cp += 1;
len -= 1;
/* Sector Count (not correlated with the length) */
ND_PRINT(", Sector Count: %u", GET_U_1(cp));
cp += 1;
len -= 1;
/* Cmd/Status */
ND_PRINT(", Cmd/Status: %u", GET_U_1(cp));
cp += 1;
len -= 1;
/* lba0 */
ND_PRINT("\n\tlba0: %u", GET_U_1(cp));
cp += 1;
len -= 1;
/* lba1 */
ND_PRINT(", lba1: %u", GET_U_1(cp));
cp += 1;
len -= 1;
/* lba2 */
ND_PRINT(", lba2: %u", GET_U_1(cp));
cp += 1;
len -= 1;
/* lba3 */
ND_PRINT(", lba3: %u", GET_U_1(cp));
cp += 1;
len -= 1;
/* lba4 */
ND_PRINT(", lba4: %u", GET_U_1(cp));
cp += 1;
len -= 1;
/* lba5 */
ND_PRINT(", lba5: %u", GET_U_1(cp));
cp += 1;
len -= 1;
/* Reserved */
ND_TCHECK_2(cp);
cp += 2;
len -= 2;
/* Data */
if (len)
ND_PRINT("\n\tData: %u bytes", len);
return;
invalid:
nd_print_invalid(ndo);
ND_TCHECK_LEN(cp, len);
}
static void
aoev1_query_print(netdissect_options *ndo,
const u_char *cp, u_int len)
{
uint16_t cslen;
if (len < AOEV1_QUERY_ARG_LEN)
goto invalid;
/* Buffer Count */
ND_PRINT("\n\tBuffer Count: %u", GET_BE_U_2(cp));
cp += 2;
len -= 2;
/* Firmware Version */
ND_PRINT(", Firmware Version: %u", GET_BE_U_2(cp));
cp += 2;
len -= 2;
/* Sector Count */
ND_PRINT(", Sector Count: %u", GET_U_1(cp));
cp += 1;
len -= 1;
/* AoE/CCmd */
ND_PRINT(", AoE: %u, CCmd: %s", (GET_U_1(cp) & 0xF0) >> 4,
tok2str(aoev1_ccmd_str, "Unknown (0x02x)", GET_U_1(cp) & 0x0F));
cp += 1;
len -= 1;
/* Config String Length */
cslen = GET_BE_U_2(cp);
cp += 2;
len -= 2;
if (cslen > AOEV1_MAX_CONFSTR_LEN || cslen > len)
goto invalid;
/* Config String */
if (cslen) {
ND_PRINT("\n\tConfig String (length %u): ", cslen);
(void)nd_printn(ndo, cp, cslen, NULL);
}
return;
invalid:
nd_print_invalid(ndo);
ND_TCHECK_LEN(cp, len);
}
static void
aoev1_mac_print(netdissect_options *ndo,
const u_char *cp, u_int len)
{
uint8_t dircount, i;
if (len < AOEV1_MAC_ARG_LEN)
goto invalid;
/* Reserved */
cp += 1;
len -= 1;
/* MCmd */
ND_PRINT("\n\tMCmd: %s",
tok2str(aoev1_mcmd_str, "Unknown (0x%02x)", GET_U_1(cp)));
cp += 1;
len -= 1;
/* MError */
ND_PRINT(", MError: %s",
tok2str(aoev1_merror_str, "Unknown (0x%02x)", GET_U_1(cp)));
cp += 1;
len -= 1;
/* Dir Count */
dircount = GET_U_1(cp);
cp += 1;
len -= 1;
ND_PRINT(", Dir Count: %u", dircount);
if (dircount * 8U > len)
goto invalid;
/* directives */
for (i = 0; i < dircount; i++) {
/* Reserved */
cp += 1;
len -= 1;
/* DCmd */
ND_PRINT("\n\t DCmd: %s",
tok2str(aoev1_dcmd_str, "Unknown (0x%02x)", GET_U_1(cp)));
cp += 1;
len -= 1;
/* Ethernet Address */
ND_PRINT(", Ethernet Address: %s", GET_ETHERADDR_STRING(cp));
cp += MAC_ADDR_LEN;
len -= MAC_ADDR_LEN;
}
return;
invalid:
nd_print_invalid(ndo);
ND_TCHECK_LEN(cp, len);
}
static void
aoev1_reserve_print(netdissect_options *ndo,
const u_char *cp, u_int len)
{
uint8_t nmacs, i;
if (len < AOEV1_RESERVE_ARG_LEN || (len - AOEV1_RESERVE_ARG_LEN) % MAC_ADDR_LEN)
goto invalid;
/* RCmd */
ND_PRINT("\n\tRCmd: %s",
tok2str(aoev1_rcmd_str, "Unknown (0x%02x)", GET_U_1(cp)));
cp += 1;
len -= 1;
/* NMacs (correlated with the length) */
nmacs = GET_U_1(cp);
cp += 1;
len -= 1;
ND_PRINT(", NMacs: %u", nmacs);
if (nmacs * MAC_ADDR_LEN != len)
goto invalid;
/* addresses */
for (i = 0; i < nmacs; i++) {
ND_PRINT("\n\tEthernet Address %u: %s", i, GET_ETHERADDR_STRING(cp));
cp += MAC_ADDR_LEN;
len -= MAC_ADDR_LEN;
}
return;
invalid:
nd_print_invalid(ndo);
ND_TCHECK_LEN(cp, len);
}
/* cp points to the Ver/Flags octet */
static void
aoev1_print(netdissect_options *ndo,
const u_char *cp, u_int len)
{
uint8_t flags, command;
void (*cmd_decoder)(netdissect_options *, const u_char *, u_int);
if (len < AOEV1_COMMON_HDR_LEN)
goto invalid;
/* Flags */
flags = GET_U_1(cp) & 0x0F;
ND_PRINT(", Flags: [%s]", bittok2str(aoev1_flag_str, "none", flags));
cp += 1;
len -= 1;
if (! ndo->ndo_vflag)
return;
/* Error */
if (flags & AOEV1_FLAG_E)
ND_PRINT("\n\tError: %s",
tok2str(aoev1_errcode_str, "Invalid (%u)", GET_U_1(cp)));
cp += 1;
len -= 1;
/* Major */
ND_PRINT("\n\tMajor: 0x%04x", GET_BE_U_2(cp));
cp += 2;
len -= 2;
/* Minor */
ND_PRINT(", Minor: 0x%02x", GET_U_1(cp));
cp += 1;
len -= 1;
/* Command */
command = GET_U_1(cp);
cp += 1;
len -= 1;
ND_PRINT(", Command: %s", tok2str(cmdcode_str, "Unknown (0x%02x)", command));
/* Tag */
ND_PRINT(", Tag: 0x%08x", GET_BE_U_4(cp));
cp += 4;
len -= 4;
/* Arg */
cmd_decoder =
command == AOEV1_CMD_ISSUE_ATA_COMMAND ? aoev1_issue_print :
command == AOEV1_CMD_QUERY_CONFIG_INFORMATION ? aoev1_query_print :
command == AOEV1_CMD_MAC_MASK_LIST ? aoev1_mac_print :
command == AOEV1_CMD_RESERVE_RELEASE ? aoev1_reserve_print :
NULL;
if (cmd_decoder != NULL)
cmd_decoder(ndo, cp, len);
return;
invalid:
nd_print_invalid(ndo);
ND_TCHECK_LEN(cp, len);
}
void
aoe_print(netdissect_options *ndo,
const u_char *cp, const u_int len)
{
uint8_t ver;
ndo->ndo_protocol = "aoe";
ND_PRINT("AoE length %u", len);
if (len < 1)
goto invalid;
/* Ver/Flags */
ver = (GET_U_1(cp) & 0xF0) >> 4;
/* Don't advance cp yet: low order 4 bits are version-specific. */
ND_PRINT(", Ver %u", ver);
switch (ver) {
case AOE_V1:
aoev1_print(ndo, cp, len);
break;
}
return;
invalid:
nd_print_invalid(ndo);
ND_TCHECK_LEN(cp, len);
}
diff --git a/contrib/tcpdump/print-ap1394.c b/contrib/tcpdump/print-ap1394.c
index b1988f270650..3e0cd19f8758 100644
--- a/contrib/tcpdump/print-ap1394.c
+++ b/contrib/tcpdump/print-ap1394.c
@@ -1,123 +1,121 @@
/*
* 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.
*/
/* \summary: Apple IP-over-IEEE 1394 printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
#include "addrtoname.h"
#include "ethertype.h"
/*
* Structure of a header for Apple's IP-over-IEEE 1384 BPF header.
*/
#define FIREWIRE_EUI64_LEN 8
struct firewire_header {
nd_byte firewire_dhost[FIREWIRE_EUI64_LEN];
nd_byte firewire_shost[FIREWIRE_EUI64_LEN];
nd_uint16_t firewire_type;
};
/*
* Length of that header; note that some compilers may pad
* "struct firewire_header" to a multiple of 4 bytes, for example, so
* "sizeof (struct firewire_header)" may not give the right answer.
*/
#define FIREWIRE_HDRLEN 18
static const char *
fwaddr_string(netdissect_options *ndo, const u_char *addr)
{
return GET_LINKADDR_STRING(addr, LINKADDR_IEEE1394, FIREWIRE_EUI64_LEN);
}
static void
ap1394_hdr_print(netdissect_options *ndo, const u_char *bp, u_int length)
{
const struct firewire_header *fp;
uint16_t firewire_type;
fp = (const struct firewire_header *)bp;
ND_PRINT("%s > %s",
fwaddr_string(ndo, fp->firewire_shost),
fwaddr_string(ndo, fp->firewire_dhost));
firewire_type = GET_BE_U_2(fp->firewire_type);
if (!ndo->ndo_qflag) {
ND_PRINT(", ethertype %s (0x%04x)",
tok2str(ethertype_values,"Unknown", firewire_type),
firewire_type);
} else {
ND_PRINT(", %s", tok2str(ethertype_values,"Unknown Ethertype (0x%04x)", firewire_type));
}
ND_PRINT(", length %u: ", length);
}
/*
* This is the top level routine of the printer. 'p' points
* to the ether header of the packet, 'h->ts' is the timestamp,
* 'h->len' is the length of the packet off the wire, and 'h->caplen'
* is the number of bytes actually captured.
*/
void
ap1394_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
{
u_int length = h->len;
u_int caplen = h->caplen;
const struct firewire_header *fp;
u_short ether_type;
struct lladdr_info src, dst;
ndo->ndo_protocol = "ap1394";
ND_TCHECK_LEN(p, FIREWIRE_HDRLEN);
ndo->ndo_ll_hdr_len += FIREWIRE_HDRLEN;
if (ndo->ndo_eflag)
ap1394_hdr_print(ndo, p, length);
length -= FIREWIRE_HDRLEN;
caplen -= FIREWIRE_HDRLEN;
fp = (const struct firewire_header *)p;
p += FIREWIRE_HDRLEN;
ether_type = GET_BE_U_2(fp->firewire_type);
src.addr = fp->firewire_shost;
src.addr_string = fwaddr_string;
dst.addr = fp->firewire_dhost;
dst.addr_string = fwaddr_string;
if (ethertype_print(ndo, ether_type, p, length, caplen, &src, &dst) == 0) {
/* ether_type not known, print raw packet */
if (!ndo->ndo_eflag)
ap1394_hdr_print(ndo, (const u_char *)fp, length + FIREWIRE_HDRLEN);
if (!ndo->ndo_suppress_default_print)
ND_DEFAULTPRINT(p, caplen);
}
}
diff --git a/contrib/tcpdump/print-arcnet.c b/contrib/tcpdump/print-arcnet.c
index 5f6aaf9c4308..d7fce713a525 100644
--- a/contrib/tcpdump/print-arcnet.c
+++ b/contrib/tcpdump/print-arcnet.c
@@ -1,366 +1,364 @@
/*
* Copyright (c) 1988, 1989, 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.
*
* From: NetBSD: print-arcnet.c,v 1.2 2000/04/24 13:02:28 itojun Exp
*/
/* \summary: Attached Resource Computer NETwork (ARCNET) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "extract.h"
/*
* from: NetBSD: if_arc.h,v 1.13 1999/11/19 20:41:19 thorpej Exp
*/
/*
* Structure of a 2.5MB/s Arcnet header on the BSDs,
* as given to interface code.
*/
struct arc_header {
nd_uint8_t arc_shost;
nd_uint8_t arc_dhost;
nd_uint8_t arc_type;
/*
* only present for newstyle encoding with LL fragmentation.
* Don't use sizeof(anything), use ARC_HDR{,NEW}LEN instead.
*/
nd_uint8_t arc_flag;
nd_uint16_t arc_seqid;
/*
* only present in exception packets (arc_flag == 0xff)
*/
nd_uint8_t arc_type2; /* same as arc_type */
nd_uint8_t arc_flag2; /* real flag value */
nd_uint16_t arc_seqid2; /* real seqid value */
};
#define ARC_HDRLEN 3
#define ARC_HDRNEWLEN 6
#define ARC_HDRNEWLEN_EXC 10
/* RFC 1051 */
#define ARCTYPE_IP_OLD 240 /* IP protocol */
#define ARCTYPE_ARP_OLD 241 /* address resolution protocol */
/* RFC 1201 */
#define ARCTYPE_IP 212 /* IP protocol */
#define ARCTYPE_ARP 213 /* address resolution protocol */
#define ARCTYPE_REVARP 214 /* reverse addr resolution protocol */
#define ARCTYPE_ATALK 221 /* Appletalk */
#define ARCTYPE_BANIAN 247 /* Banyan Vines */
#define ARCTYPE_IPX 250 /* Novell IPX */
#define ARCTYPE_INET6 0xc4 /* IPng */
#define ARCTYPE_DIAGNOSE 0x80 /* as per ANSI/ATA 878.1 */
/*
* Structure of a 2.5MB/s Arcnet header on Linux. Linux has
* an extra "offset" field when given to interface code, and
* never presents packets that look like exception frames.
*/
struct arc_linux_header {
nd_uint8_t arc_shost;
nd_uint8_t arc_dhost;
nd_uint16_t arc_offset;
nd_uint8_t arc_type;
/*
* only present for newstyle encoding with LL fragmentation.
* Don't use sizeof(anything), use ARC_LINUX_HDR{,NEW}LEN
* instead.
*/
nd_uint8_t arc_flag;
nd_uint16_t arc_seqid;
};
#define ARC_LINUX_HDRLEN 5
#define ARC_LINUX_HDRNEWLEN 8
static int arcnet_encap_print(netdissect_options *, u_char arctype, const u_char *p,
u_int length, u_int caplen);
static const struct tok arctypemap[] = {
{ ARCTYPE_IP_OLD, "oldip" },
{ ARCTYPE_ARP_OLD, "oldarp" },
{ ARCTYPE_IP, "ip" },
{ ARCTYPE_ARP, "arp" },
{ ARCTYPE_REVARP, "rarp" },
{ ARCTYPE_ATALK, "atalk" },
{ ARCTYPE_BANIAN, "banyan" },
{ ARCTYPE_IPX, "ipx" },
{ ARCTYPE_INET6, "ipv6" },
{ ARCTYPE_DIAGNOSE, "diag" },
{ 0, NULL }
};
static void
arcnet_print(netdissect_options *ndo, const u_char *bp, u_int length, int phds,
u_int flag, u_int seqid)
{
const struct arc_header *ap;
const char *arctypename;
ndo->ndo_protocol = "arcnet";
ap = (const struct arc_header *)bp;
if (ndo->ndo_qflag) {
ND_PRINT("%02x %02x %u: ",
GET_U_1(ap->arc_shost),
GET_U_1(ap->arc_dhost),
length);
return;
}
arctypename = tok2str(arctypemap, "%02x", GET_U_1(ap->arc_type));
if (!phds) {
ND_PRINT("%02x %02x %s %u: ",
GET_U_1(ap->arc_shost),
GET_U_1(ap->arc_dhost),
arctypename,
length);
return;
}
if (flag == 0) {
ND_PRINT("%02x %02x %s seqid %04x %u: ",
GET_U_1(ap->arc_shost),
GET_U_1(ap->arc_dhost),
arctypename, seqid,
length);
return;
}
if (flag & 1)
ND_PRINT("%02x %02x %s seqid %04x "
"(first of %u fragments) %u: ",
GET_U_1(ap->arc_shost),
GET_U_1(ap->arc_dhost),
arctypename, seqid,
(flag + 3) / 2, length);
else
ND_PRINT("%02x %02x %s seqid %04x "
"(fragment %u) %u: ",
GET_U_1(ap->arc_shost),
GET_U_1(ap->arc_dhost),
arctypename, seqid,
flag/2 + 1, length);
}
/*
* This is the top level routine of the printer. 'p' points
* to the ARCNET header of the packet, 'h->ts' is the timestamp,
* 'h->len' is the length of the packet off the wire, and 'h->caplen'
* is the number of bytes actually captured.
*/
void
arcnet_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
{
u_int caplen = h->caplen;
u_int length = h->len;
const struct arc_header *ap;
int phds;
u_int flag = 0, archdrlen = 0;
u_int seqid = 0;
u_char arc_type;
ndo->ndo_protocol = "arcnet";
if (caplen < ARC_HDRLEN) {
ndo->ndo_ll_hdr_len += caplen;
nd_trunc_longjmp(ndo);
}
ap = (const struct arc_header *)p;
arc_type = GET_U_1(ap->arc_type);
switch (arc_type) {
default:
phds = 1;
break;
case ARCTYPE_IP_OLD:
case ARCTYPE_ARP_OLD:
case ARCTYPE_DIAGNOSE:
phds = 0;
archdrlen = ARC_HDRLEN;
break;
}
if (phds) {
if (caplen < ARC_HDRNEWLEN) {
arcnet_print(ndo, p, length, 0, 0, 0);
ND_PRINT(" phds");
ndo->ndo_ll_hdr_len += caplen;
nd_trunc_longjmp(ndo);
}
flag = GET_U_1(ap->arc_flag);
if (flag == 0xff) {
if (caplen < ARC_HDRNEWLEN_EXC) {
arcnet_print(ndo, p, length, 0, 0, 0);
ND_PRINT(" phds extended");
ndo->ndo_ll_hdr_len += caplen;
nd_trunc_longjmp(ndo);
}
flag = GET_U_1(ap->arc_flag2);
seqid = GET_BE_U_2(ap->arc_seqid2);
archdrlen = ARC_HDRNEWLEN_EXC;
} else {
seqid = GET_BE_U_2(ap->arc_seqid);
archdrlen = ARC_HDRNEWLEN;
}
}
if (ndo->ndo_eflag)
arcnet_print(ndo, p, length, phds, flag, seqid);
/*
* Go past the ARCNET header.
*/
length -= archdrlen;
caplen -= archdrlen;
p += archdrlen;
if (phds && flag && (flag & 1) == 0) {
/*
* This is a middle fragment.
*/
ndo->ndo_ll_hdr_len += archdrlen;
return;
}
if (!arcnet_encap_print(ndo, arc_type, p, length, caplen))
ND_DEFAULTPRINT(p, caplen);
ndo->ndo_ll_hdr_len += archdrlen;
}
/*
* This is the top level routine of the printer. 'p' points
* to the ARCNET header of the packet, 'h->ts' is the timestamp,
* 'h->len' is the length of the packet off the wire, and 'h->caplen'
* is the number of bytes actually captured. It is quite similar
* to the non-Linux style printer except that Linux doesn't ever
* supply packets that look like exception frames, it always supplies
* reassembled packets rather than raw frames, and headers have an
* extra "offset" field between the src/dest and packet type.
*/
void
arcnet_linux_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
{
u_int caplen = h->caplen;
u_int length = h->len;
const struct arc_linux_header *ap;
int archdrlen = 0;
u_char arc_type;
ndo->ndo_protocol = "arcnet_linux";
if (caplen < ARC_LINUX_HDRLEN) {
ndo->ndo_ll_hdr_len += caplen;
nd_trunc_longjmp(ndo);
}
ap = (const struct arc_linux_header *)p;
arc_type = GET_U_1(ap->arc_type);
switch (arc_type) {
default:
archdrlen = ARC_LINUX_HDRNEWLEN;
if (caplen < ARC_LINUX_HDRNEWLEN) {
ndo->ndo_ll_hdr_len += caplen;
nd_trunc_longjmp(ndo);
}
break;
case ARCTYPE_IP_OLD:
case ARCTYPE_ARP_OLD:
case ARCTYPE_DIAGNOSE:
archdrlen = ARC_LINUX_HDRLEN;
break;
}
if (ndo->ndo_eflag)
arcnet_print(ndo, p, length, 0, 0, 0);
/*
* Go past the ARCNET header.
*/
length -= archdrlen;
caplen -= archdrlen;
p += archdrlen;
if (!arcnet_encap_print(ndo, arc_type, p, length, caplen))
ND_DEFAULTPRINT(p, caplen);
ndo->ndo_ll_hdr_len += archdrlen;
}
/*
* Prints the packet encapsulated in an ARCnet data field,
* given the ARCnet system code.
*
* Returns non-zero if it can do so, zero if the system code is unknown.
*/
static int
arcnet_encap_print(netdissect_options *ndo, u_char arctype, const u_char *p,
u_int length, u_int caplen)
{
switch (arctype) {
case ARCTYPE_IP_OLD:
case ARCTYPE_IP:
ip_print(ndo, p, length);
return (1);
case ARCTYPE_INET6:
ip6_print(ndo, p, length);
return (1);
case ARCTYPE_ARP_OLD:
case ARCTYPE_ARP:
case ARCTYPE_REVARP:
arp_print(ndo, p, length, caplen);
return (1);
case ARCTYPE_ATALK: /* XXX was this ever used? */
if (ndo->ndo_vflag)
ND_PRINT("et1 ");
atalk_print(ndo, p, length);
return (1);
case ARCTYPE_IPX:
ipx_print(ndo, p, length);
return (1);
default:
return (0);
}
}
diff --git a/contrib/tcpdump/print-arista.c b/contrib/tcpdump/print-arista.c
index 079ad684bc11..6d00956aeeb0 100644
--- a/contrib/tcpdump/print-arista.c
+++ b/contrib/tcpdump/print-arista.c
@@ -1,165 +1,163 @@
// Copyright (c) 2018 Arista Networks, Inc. All rights reserved.
/* \summary: EtherType protocol for Arista Networks printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "extract.h"
/*
From Bill Fenner:
The Arista timestamp header consists of the following fields:
1. The Arista ethertype (0xd28b)
2. A 2-byte subtype field; 0x01 indicates the timestamp header
3. A 2-byte version field, described below.
4. A 48-bit or 64-bit timestamp field, depending on the contents of the version field
This header is then followed by the original ethertype and the remainder of the original packet.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| dst mac |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
| src mac |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ethertype 0xd28b | subtype 0x1 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| version | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
| timestamp... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
The two-byte version value is split into 3 fields:
1. The timescale in use. Currently assigned values include:
0 = TAI
1 = UTC
2. The timestamp format and length. Currently assigned values include:
1 = 64-bit timestamp
2 = 48-bit timestamp
3. The hardware info
0 = R/R2 series
1 = R3 series
0 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| timescale | format|hw info|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
See also: https://www.arista.com/assets/data/pdf/Whitepapers/Overview_Arista_Timestamps.pdf
*/
#define ARISTA_SUBTYPE_TIMESTAMP 0x0001
static const struct tok subtype_str[] = {
{ ARISTA_SUBTYPE_TIMESTAMP, "Timestamp" },
{ 0, NULL }
};
static const struct tok ts_timescale_str[] = {
{ 0, "TAI" },
{ 1, "UTC" },
{ 0, NULL }
};
#define FORMAT_64BIT 0x1
#define FORMAT_48BIT 0x2
static const struct tok ts_format_str[] = {
{ FORMAT_64BIT, "64-bit" },
{ FORMAT_48BIT, "48-bit" },
{ 0, NULL }
};
static const struct tok hw_info_str[] = {
{ 0, "R/R2" },
{ 1, "R3" },
{ 0, NULL }
};
static inline void
arista_print_date_hms_time(netdissect_options *ndo, uint32_t seconds,
uint32_t nanoseconds)
{
time_t ts;
char buf[sizeof("-yyyyyyyyyy-mm-dd hh:mm:ss")];
ts = seconds + (nanoseconds / 1000000000);
nanoseconds %= 1000000000;
ND_PRINT("%s.%09u",
nd_format_time(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S",
gmtime(&ts)), nanoseconds);
}
int
arista_ethertype_print(netdissect_options *ndo, const u_char *bp, u_int len _U_)
{
uint16_t subTypeId;
u_short bytesConsumed = 0;
ndo->ndo_protocol = "arista";
subTypeId = GET_BE_U_2(bp);
bp += 2;
bytesConsumed += 2;
ND_PRINT("SubType %s (0x%04x), ",
tok2str(subtype_str, "Unknown", subTypeId),
subTypeId);
// TapAgg Header Timestamping
if (subTypeId == ARISTA_SUBTYPE_TIMESTAMP) {
uint64_t seconds;
uint32_t nanoseconds;
uint8_t ts_timescale = GET_U_1(bp);
bp += 1;
bytesConsumed += 1;
ND_PRINT("Timescale %s (%u), ",
tok2str(ts_timescale_str, "Unknown", ts_timescale),
ts_timescale);
uint8_t ts_format = GET_U_1(bp) >> 4;
uint8_t hw_info = GET_U_1(bp) & 0x0f;
bp += 1;
bytesConsumed += 1;
// Timestamp has 32-bit lsb in nanosec and remaining msb in sec
ND_PRINT("Format %s (%u), HwInfo %s (%u), Timestamp ",
tok2str(ts_format_str, "Unknown", ts_format),
ts_format,
tok2str(hw_info_str, "Unknown", hw_info),
hw_info);
switch (ts_format) {
case FORMAT_64BIT:
seconds = GET_BE_U_4(bp);
nanoseconds = GET_BE_U_4(bp + 4);
arista_print_date_hms_time(ndo, seconds, nanoseconds);
bytesConsumed += 8;
break;
case FORMAT_48BIT:
seconds = GET_BE_U_2(bp);
nanoseconds = GET_BE_U_4(bp + 2);
seconds += nanoseconds / 1000000000;
nanoseconds %= 1000000000;
ND_PRINT("%" PRIu64 ".%09u", seconds, nanoseconds);
bytesConsumed += 6;
break;
default:
return -1;
}
} else {
return -1;
}
ND_PRINT(": ");
return bytesConsumed;
}
diff --git a/contrib/tcpdump/print-arp.c b/contrib/tcpdump/print-arp.c
index 9c085029242c..dd4cf3b5507a 100644
--- a/contrib/tcpdump/print-arp.c
+++ b/contrib/tcpdump/print-arp.c
@@ -1,473 +1,471 @@
/*
* Copyright (c) 1988, 1989, 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.
*/
/* \summary: Address Resolution Protocol (ARP) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "addrtoname.h"
#include "ethertype.h"
#include "extract.h"
/*
* Address Resolution Protocol.
*
* See RFC 826 for protocol description. ARP packets are variable
* in size; the arphdr structure defines the fixed-length portion.
* Protocol type values are the same as those for 10 Mb/s Ethernet.
* It is followed by the variable-sized fields ar_sha, arp_spa,
* arp_tha and arp_tpa in that order, according to the lengths
* specified. Field names used correspond to RFC 826.
*/
struct arp_pkthdr {
nd_uint16_t ar_hrd; /* format of hardware address */
#define ARPHRD_ETHER 1 /* ethernet hardware format */
#define ARPHRD_IEEE802 6 /* token-ring hardware format */
#define ARPHRD_ARCNET 7 /* arcnet hardware format */
#define ARPHRD_FRELAY 15 /* frame relay hardware format */
#define ARPHRD_ATM2225 19 /* ATM (RFC 2225) */
#define ARPHRD_STRIP 23 /* Ricochet Starmode Radio hardware format */
#define ARPHRD_IEEE1394 24 /* IEEE 1394 (FireWire) hardware format */
#define ARPHRD_INFINIBAND 32 /* InfiniBand RFC 4391 */
nd_uint16_t ar_pro; /* format of protocol address */
nd_uint8_t ar_hln; /* length of hardware address */
nd_uint8_t ar_pln; /* length of protocol address */
nd_uint16_t ar_op; /* one of: */
#define ARPOP_REQUEST 1 /* request to resolve address */
#define ARPOP_REPLY 2 /* response to previous request */
#define ARPOP_REVREQUEST 3 /* request protocol address given hardware */
#define ARPOP_REVREPLY 4 /* response giving protocol address */
#define ARPOP_INVREQUEST 8 /* request to identify peer */
#define ARPOP_INVREPLY 9 /* response identifying peer */
#define ARPOP_NAK 10 /* NAK - only valid for ATM ARP */
/*
* The remaining fields are variable in size,
* according to the sizes above.
*/
#ifdef COMMENT_ONLY
nd_byte ar_sha[]; /* sender hardware address */
nd_byte ar_spa[]; /* sender protocol address */
nd_byte ar_tha[]; /* target hardware address */
nd_byte ar_tpa[]; /* target protocol address */
#endif
#define ar_sha(ap) (((const u_char *)((ap)+1))+ 0)
#define ar_spa(ap) (((const u_char *)((ap)+1))+ GET_U_1((ap)->ar_hln))
#define ar_tha(ap) (((const u_char *)((ap)+1))+ GET_U_1((ap)->ar_hln)+GET_U_1((ap)->ar_pln))
#define ar_tpa(ap) (((const u_char *)((ap)+1))+2*GET_U_1((ap)->ar_hln)+GET_U_1((ap)->ar_pln))
};
#define ARP_HDRLEN 8
#define HRD(ap) GET_BE_U_2((ap)->ar_hrd)
#define HRD_LEN(ap) GET_U_1((ap)->ar_hln)
#define PROTO_LEN(ap) GET_U_1((ap)->ar_pln)
#define OP(ap) GET_BE_U_2((ap)->ar_op)
#define PRO(ap) GET_BE_U_2((ap)->ar_pro)
#define SHA(ap) (ar_sha(ap))
#define SPA(ap) (ar_spa(ap))
#define THA(ap) (ar_tha(ap))
#define TPA(ap) (ar_tpa(ap))
static const struct tok arpop_values[] = {
{ ARPOP_REQUEST, "Request" },
{ ARPOP_REPLY, "Reply" },
{ ARPOP_REVREQUEST, "Reverse Request" },
{ ARPOP_REVREPLY, "Reverse Reply" },
{ ARPOP_INVREQUEST, "Inverse Request" },
{ ARPOP_INVREPLY, "Inverse Reply" },
{ ARPOP_NAK, "NACK Reply" },
{ 0, NULL }
};
static const struct tok arphrd_values[] = {
{ ARPHRD_ETHER, "Ethernet" },
{ ARPHRD_IEEE802, "TokenRing" },
{ ARPHRD_ARCNET, "ArcNet" },
{ ARPHRD_FRELAY, "FrameRelay" },
{ ARPHRD_STRIP, "Strip" },
{ ARPHRD_IEEE1394, "IEEE 1394" },
{ ARPHRD_ATM2225, "ATM" },
{ ARPHRD_INFINIBAND, "InfiniBand" },
{ 0, NULL }
};
/*
* ATM Address Resolution Protocol.
*
* See RFC 2225 for protocol description. ATMARP packets are similar
* to ARP packets, except that there are no length fields for the
* protocol address - instead, there are type/length fields for
* the ATM number and subaddress - and the hardware addresses consist
* of an ATM number and an ATM subaddress.
*/
struct atmarp_pkthdr {
nd_uint16_t aar_hrd; /* format of hardware address */
nd_uint16_t aar_pro; /* format of protocol address */
nd_uint8_t aar_shtl; /* length of source ATM number */
nd_uint8_t aar_sstl; /* length of source ATM subaddress */
#define ATMARP_IS_E164 0x40 /* bit in type/length for E.164 format */
#define ATMARP_LEN_MASK 0x3F /* length of {sub}address in type/length */
nd_uint16_t aar_op; /* same as regular ARP */
nd_uint8_t aar_spln; /* length of source protocol address */
nd_uint8_t aar_thtl; /* length of target ATM number */
nd_uint8_t aar_tstl; /* length of target ATM subaddress */
nd_uint8_t aar_tpln; /* length of target protocol address */
/*
* The remaining fields are variable in size,
* according to the sizes above.
*/
#ifdef COMMENT_ONLY
nd_byte aar_sha[]; /* source ATM number */
nd_byte aar_ssa[]; /* source ATM subaddress */
nd_byte aar_spa[]; /* sender protocol address */
nd_byte aar_tha[]; /* target ATM number */
nd_byte aar_tsa[]; /* target ATM subaddress */
nd_byte aar_tpa[]; /* target protocol address */
#endif
#define ATMHRD(ap) GET_BE_U_2((ap)->aar_hrd)
#define ATMSHRD_LEN(ap) (GET_U_1((ap)->aar_shtl) & ATMARP_LEN_MASK)
#define ATMSSLN(ap) (GET_U_1((ap)->aar_sstl) & ATMARP_LEN_MASK)
#define ATMSPROTO_LEN(ap) GET_U_1((ap)->aar_spln)
#define ATMOP(ap) GET_BE_U_2((ap)->aar_op)
#define ATMPRO(ap) GET_BE_U_2((ap)->aar_pro)
#define ATMTHRD_LEN(ap) (GET_U_1((ap)->aar_thtl) & ATMARP_LEN_MASK)
#define ATMTSLN(ap) (GET_U_1((ap)->aar_tstl) & ATMARP_LEN_MASK)
#define ATMTPROTO_LEN(ap) GET_U_1((ap)->aar_tpln)
#define aar_sha(ap) ((const u_char *)((ap)+1))
#define aar_ssa(ap) (aar_sha(ap) + ATMSHRD_LEN(ap))
#define aar_spa(ap) (aar_ssa(ap) + ATMSSLN(ap))
#define aar_tha(ap) (aar_spa(ap) + ATMSPROTO_LEN(ap))
#define aar_tsa(ap) (aar_tha(ap) + ATMTHRD_LEN(ap))
#define aar_tpa(ap) (aar_tsa(ap) + ATMTSLN(ap))
};
#define ATMSHA(ap) (aar_sha(ap))
#define ATMSSA(ap) (aar_ssa(ap))
#define ATMSPA(ap) (aar_spa(ap))
#define ATMTHA(ap) (aar_tha(ap))
#define ATMTSA(ap) (aar_tsa(ap))
#define ATMTPA(ap) (aar_tpa(ap))
static int
isnonzero(netdissect_options *ndo, const u_char *a, size_t len)
{
while (len > 0) {
if (GET_U_1(a) != 0)
return (1);
a++;
len--;
}
return (0);
}
static void
tpaddr_print_ip(netdissect_options *ndo,
const struct arp_pkthdr *ap, u_short pro)
{
if (pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL)
ND_PRINT("<wrong proto type>");
else if (PROTO_LEN(ap) != 4)
ND_PRINT("<wrong len>");
else
ND_PRINT("%s", GET_IPADDR_STRING(TPA(ap)));
}
static void
spaddr_print_ip(netdissect_options *ndo,
const struct arp_pkthdr *ap, u_short pro)
{
if (pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL)
ND_PRINT("<wrong proto type>");
else if (PROTO_LEN(ap) != 4)
ND_PRINT("<wrong len>");
else
ND_PRINT("%s", GET_IPADDR_STRING(SPA(ap)));
}
static void
atmarp_addr_print(netdissect_options *ndo,
const u_char *ha, u_int ha_len, const u_char *srca,
u_int srca_len)
{
if (ha_len == 0)
ND_PRINT("<No address>");
else {
ND_PRINT("%s", GET_LINKADDR_STRING(ha, LINKADDR_ATM, ha_len));
if (srca_len != 0)
ND_PRINT(",%s",
GET_LINKADDR_STRING(srca, LINKADDR_ATM, srca_len));
}
}
static void
atmarp_tpaddr_print(netdissect_options *ndo,
const struct atmarp_pkthdr *ap, u_short pro)
{
if (pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL)
ND_PRINT("<wrong proto type>");
else if (ATMTPROTO_LEN(ap) != 4)
ND_PRINT("<wrong tplen>");
else
ND_PRINT("%s", GET_IPADDR_STRING(ATMTPA(ap)));
}
static void
atmarp_spaddr_print(netdissect_options *ndo,
const struct atmarp_pkthdr *ap, u_short pro)
{
if (pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL)
ND_PRINT("<wrong proto type>");
else if (ATMSPROTO_LEN(ap) != 4)
ND_PRINT("<wrong splen>");
else
ND_PRINT("%s", GET_IPADDR_STRING(ATMSPA(ap)));
}
static void
atmarp_print(netdissect_options *ndo,
const u_char *bp, u_int length, u_int caplen)
{
const struct atmarp_pkthdr *ap;
u_short pro, hrd, op;
ap = (const struct atmarp_pkthdr *)bp;
ND_TCHECK_SIZE(ap);
hrd = ATMHRD(ap);
pro = ATMPRO(ap);
op = ATMOP(ap);
ND_TCHECK_LEN(ATMTPA(ap), ATMTPROTO_LEN(ap));
if (!ndo->ndo_eflag) {
ND_PRINT("ARP, ");
}
if ((pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL) ||
ATMSPROTO_LEN(ap) != 4 ||
ATMTPROTO_LEN(ap) != 4 ||
ndo->ndo_vflag) {
ND_PRINT("%s, %s (len %u/%u)",
tok2str(arphrd_values, "Unknown Hardware (%u)", hrd),
tok2str(ethertype_values, "Unknown Protocol (0x%04x)", pro),
ATMSPROTO_LEN(ap),
ATMTPROTO_LEN(ap));
/* don't know about the address formats */
if (!ndo->ndo_vflag) {
goto out;
}
}
/* print operation */
ND_PRINT("%s%s ",
ndo->ndo_vflag ? ", " : "",
tok2str(arpop_values, "Unknown (%u)", op));
switch (op) {
case ARPOP_REQUEST:
ND_PRINT("who-has ");
atmarp_tpaddr_print(ndo, ap, pro);
if (ATMTHRD_LEN(ap) != 0) {
ND_PRINT(" (");
atmarp_addr_print(ndo, ATMTHA(ap), ATMTHRD_LEN(ap),
ATMTSA(ap), ATMTSLN(ap));
ND_PRINT(")");
}
ND_PRINT(" tell ");
atmarp_spaddr_print(ndo, ap, pro);
break;
case ARPOP_REPLY:
atmarp_spaddr_print(ndo, ap, pro);
ND_PRINT(" is-at ");
atmarp_addr_print(ndo, ATMSHA(ap), ATMSHRD_LEN(ap), ATMSSA(ap),
ATMSSLN(ap));
break;
case ARPOP_INVREQUEST:
ND_PRINT("who-is ");
atmarp_addr_print(ndo, ATMTHA(ap), ATMTHRD_LEN(ap), ATMTSA(ap),
ATMTSLN(ap));
ND_PRINT(" tell ");
atmarp_addr_print(ndo, ATMSHA(ap), ATMSHRD_LEN(ap), ATMSSA(ap),
ATMSSLN(ap));
break;
case ARPOP_INVREPLY:
atmarp_addr_print(ndo, ATMSHA(ap), ATMSHRD_LEN(ap), ATMSSA(ap),
ATMSSLN(ap));
ND_PRINT("at ");
atmarp_spaddr_print(ndo, ap, pro);
break;
case ARPOP_NAK:
ND_PRINT("for ");
atmarp_spaddr_print(ndo, ap, pro);
break;
default:
ND_DEFAULTPRINT((const u_char *)ap, caplen);
return;
}
out:
ND_PRINT(", length %u", length);
}
void
arp_print(netdissect_options *ndo,
const u_char *bp, u_int length, u_int caplen)
{
const struct arp_pkthdr *ap;
u_short pro, hrd, op, linkaddr;
ndo->ndo_protocol = "arp";
ap = (const struct arp_pkthdr *)bp;
ND_TCHECK_SIZE(ap);
hrd = HRD(ap);
pro = PRO(ap);
op = OP(ap);
/* if its ATM then call the ATM ARP printer
for Frame-relay ARP most of the fields
are similar to Ethernet so overload the Ethernet Printer
and set the linkaddr type for GET_LINKADDR_STRING() accordingly */
switch(hrd) {
case ARPHRD_ATM2225:
atmarp_print(ndo, bp, length, caplen);
return;
case ARPHRD_FRELAY:
linkaddr = LINKADDR_FRELAY;
break;
default:
linkaddr = LINKADDR_ETHER;
break;
}
ND_TCHECK_LEN(TPA(ap), PROTO_LEN(ap));
if (!ndo->ndo_eflag) {
ND_PRINT("ARP, ");
}
/* print hardware type/len and proto type/len */
if ((pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL) ||
PROTO_LEN(ap) != 4 ||
HRD_LEN(ap) == 0 ||
ndo->ndo_vflag) {
ND_PRINT("%s (len %u), %s (len %u)",
tok2str(arphrd_values, "Unknown Hardware (%u)", hrd),
HRD_LEN(ap),
tok2str(ethertype_values, "Unknown Protocol (0x%04x)", pro),
PROTO_LEN(ap));
/* don't know about the address formats */
if (!ndo->ndo_vflag) {
goto out;
}
}
/* print operation */
ND_PRINT("%s%s ",
ndo->ndo_vflag ? ", " : "",
tok2str(arpop_values, "Unknown (%u)", op));
switch (op) {
case ARPOP_REQUEST:
ND_PRINT("who-has ");
tpaddr_print_ip(ndo, ap, pro);
if (isnonzero(ndo, (const u_char *)THA(ap), HRD_LEN(ap)))
ND_PRINT(" (%s)",
GET_LINKADDR_STRING(THA(ap), linkaddr, HRD_LEN(ap)));
ND_PRINT(" tell ");
spaddr_print_ip(ndo, ap, pro);
break;
case ARPOP_REPLY:
spaddr_print_ip(ndo, ap, pro);
ND_PRINT(" is-at %s",
GET_LINKADDR_STRING(SHA(ap), linkaddr, HRD_LEN(ap)));
break;
case ARPOP_REVREQUEST:
/*
* XXX - GET_LINKADDR_STRING() may return a pointer to
* a static buffer, so we only have one call to it per
* ND_PRINT() call.
*
* This should be done in a cleaner fashion.
*/
ND_PRINT("who-is %s",
GET_LINKADDR_STRING(THA(ap), linkaddr, HRD_LEN(ap)));
ND_PRINT(" tell %s",
GET_LINKADDR_STRING(SHA(ap), linkaddr, HRD_LEN(ap)));
break;
case ARPOP_REVREPLY:
ND_PRINT("%s at ",
GET_LINKADDR_STRING(THA(ap), linkaddr, HRD_LEN(ap)));
tpaddr_print_ip(ndo, ap, pro);
break;
case ARPOP_INVREQUEST:
/*
* XXX - GET_LINKADDR_STRING() may return a pointer to
* a static buffer, so we only have one call to it per
* ND_PRINT() call.
*
* This should be done in a cleaner fashion.
*/
ND_PRINT("who-is %s",
GET_LINKADDR_STRING(THA(ap), linkaddr, HRD_LEN(ap)));
ND_PRINT(" tell %s",
GET_LINKADDR_STRING(SHA(ap), linkaddr, HRD_LEN(ap)));
break;
case ARPOP_INVREPLY:
ND_PRINT("%s at ",
GET_LINKADDR_STRING(SHA(ap), linkaddr, HRD_LEN(ap)));
spaddr_print_ip(ndo, ap, pro);
break;
default:
ND_DEFAULTPRINT((const u_char *)ap, caplen);
return;
}
out:
ND_PRINT(", length %u", length);
}
diff --git a/contrib/tcpdump/print-ascii.c b/contrib/tcpdump/print-ascii.c
index a1dc4eb15ac0..f379c6c43678 100644
--- a/contrib/tcpdump/print-ascii.c
+++ b/contrib/tcpdump/print-ascii.c
@@ -1,235 +1,233 @@
/* $NetBSD: print-ascii.c,v 1.1 1999/09/30 14:49:12 sjg Exp $ */
/*-
* Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Alan Barrett and Simon J. Gerraty.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation 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 BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* \summary: ASCII packet dump printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <stdio.h>
#include "netdissect-ctype.h"
#include "netdissect.h"
#include "extract.h"
#define ASCII_LINELENGTH 300
#define HEXDUMP_BYTES_PER_LINE 16
#define HEXDUMP_SHORTS_PER_LINE (HEXDUMP_BYTES_PER_LINE / 2)
#define HEXDUMP_HEXSTUFF_PER_SHORT 5 /* 4 hex digits and a space */
#define HEXDUMP_HEXSTUFF_PER_LINE \
(HEXDUMP_HEXSTUFF_PER_SHORT * HEXDUMP_SHORTS_PER_LINE)
void
ascii_print(netdissect_options *ndo,
const u_char *cp, u_int length)
{
u_int caplength;
u_char s;
int truncated = FALSE;
ndo->ndo_protocol = "ascii";
- caplength = (ndo->ndo_snapend > cp) ? ND_BYTES_AVAILABLE_AFTER(cp) : 0;
+ caplength = ND_BYTES_AVAILABLE_AFTER(cp);
if (length > caplength) {
length = caplength;
truncated = TRUE;
}
ND_PRINT("\n");
while (length > 0) {
s = GET_U_1(cp);
cp++;
length--;
if (s == '\r') {
/*
* Don't print CRs at the end of the line; they
* don't belong at the ends of lines on UN*X,
* and the standard I/O library will give us one
* on Windows so we don't need to print one
* ourselves.
*
* In the middle of a line, just print a '.'.
*/
if (length > 1 && GET_U_1(cp) != '\n')
ND_PRINT(".");
} else {
if (!ND_ASCII_ISGRAPH(s) &&
(s != '\t' && s != ' ' && s != '\n'))
ND_PRINT(".");
else
ND_PRINT("%c", s);
}
}
if (truncated)
nd_trunc_longjmp(ndo);
}
static void
hex_and_ascii_print_with_offset(netdissect_options *ndo, const char *ident,
const u_char *cp, u_int length, u_int oset)
{
u_int caplength;
u_int i;
u_int s1, s2;
u_int nshorts;
int truncated = FALSE;
char hexstuff[HEXDUMP_SHORTS_PER_LINE*HEXDUMP_HEXSTUFF_PER_SHORT+1], *hsp;
char asciistuff[ASCII_LINELENGTH+1], *asp;
- caplength = (ndo->ndo_snapend > cp) ? ND_BYTES_AVAILABLE_AFTER(cp) : 0;
+ caplength = ND_BYTES_AVAILABLE_AFTER(cp);
if (length > caplength) {
length = caplength;
truncated = TRUE;
}
nshorts = length / sizeof(u_short);
i = 0;
hsp = hexstuff; asp = asciistuff;
while (nshorts != 0) {
s1 = GET_U_1(cp);
cp++;
s2 = GET_U_1(cp);
cp++;
(void)snprintf(hsp, sizeof(hexstuff) - (hsp - hexstuff),
" %02x%02x", s1, s2);
hsp += HEXDUMP_HEXSTUFF_PER_SHORT;
*(asp++) = (char)(ND_ASCII_ISGRAPH(s1) ? s1 : '.');
*(asp++) = (char)(ND_ASCII_ISGRAPH(s2) ? s2 : '.');
i++;
if (i >= HEXDUMP_SHORTS_PER_LINE) {
*hsp = *asp = '\0';
ND_PRINT("%s0x%04x: %-*s %s",
ident, oset, HEXDUMP_HEXSTUFF_PER_LINE,
hexstuff, asciistuff);
i = 0; hsp = hexstuff; asp = asciistuff;
oset += HEXDUMP_BYTES_PER_LINE;
}
nshorts--;
}
if (length & 1) {
s1 = GET_U_1(cp);
cp++;
(void)snprintf(hsp, sizeof(hexstuff) - (hsp - hexstuff),
" %02x", s1);
hsp += 3;
*(asp++) = (char)(ND_ASCII_ISGRAPH(s1) ? s1 : '.');
++i;
}
if (i > 0) {
*hsp = *asp = '\0';
ND_PRINT("%s0x%04x: %-*s %s",
ident, oset, HEXDUMP_HEXSTUFF_PER_LINE,
hexstuff, asciistuff);
}
if (truncated)
nd_trunc_longjmp(ndo);
}
void
hex_and_ascii_print(netdissect_options *ndo, const char *ident,
const u_char *cp, u_int length)
{
hex_and_ascii_print_with_offset(ndo, ident, cp, length, 0);
}
/*
* telnet_print() wants this. It is essentially default_print_unaligned()
*/
void
hex_print_with_offset(netdissect_options *ndo,
const char *ident, const u_char *cp, u_int length,
u_int oset)
{
u_int caplength;
u_int i, s;
u_int nshorts;
int truncated = FALSE;
- caplength = (ndo->ndo_snapend > cp) ? ND_BYTES_AVAILABLE_AFTER(cp) : 0;
+ caplength = ND_BYTES_AVAILABLE_AFTER(cp);
if (length > caplength) {
length = caplength;
truncated = TRUE;
}
nshorts = length / sizeof(u_short);
i = 0;
while (nshorts != 0) {
if ((i++ % 8) == 0) {
ND_PRINT("%s0x%04x: ", ident, oset);
oset += HEXDUMP_BYTES_PER_LINE;
}
s = GET_U_1(cp);
cp++;
ND_PRINT(" %02x%02x", s, GET_U_1(cp));
cp++;
nshorts--;
}
if (length & 1) {
if ((i % 8) == 0)
ND_PRINT("%s0x%04x: ", ident, oset);
ND_PRINT(" %02x", GET_U_1(cp));
}
if (truncated)
nd_trunc_longjmp(ndo);
}
void
hex_print(netdissect_options *ndo,
const char *ident, const u_char *cp, u_int length)
{
hex_print_with_offset(ndo, ident, cp, length, 0);
}
#ifdef MAIN
int
main(int argc, char *argv[])
{
hex_print("\n\t", "Hello, World!\n", 14);
printf("\n");
hex_and_ascii_print("\n\t", "Hello, World!\n", 14);
printf("\n");
ascii_print("Hello, World!\n", 14);
printf("\n");
#define TMSG "Now is the winter of our discontent...\n"
hex_print_with_offset("\n\t", TMSG, sizeof(TMSG) - 1, 0x100);
printf("\n");
hex_and_ascii_print_with_offset("\n\t", TMSG, sizeof(TMSG) - 1, 0x100);
printf("\n");
exit(0);
}
#endif /* MAIN */
diff --git a/contrib/tcpdump/print-atalk.c b/contrib/tcpdump/print-atalk.c
index d9f86c7255b0..1f067ed6053e 100644
--- a/contrib/tcpdump/print-atalk.c
+++ b/contrib/tcpdump/print-atalk.c
@@ -1,701 +1,699 @@
/*
* Copyright (c) 1988, 1989, 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.
*/
/* \summary: AppleTalk printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <stdio.h>
#include <string.h>
#include "netdissect.h"
#include "addrtoname.h"
#include "ethertype.h"
#include "extract.h"
#include "appletalk.h"
static const struct tok type2str[] = {
{ ddpRTMP, "rtmp" },
{ ddpRTMPrequest, "rtmpReq" },
{ ddpECHO, "echo" },
{ ddpIP, "IP" },
{ ddpARP, "ARP" },
{ ddpKLAP, "KLAP" },
{ 0, NULL }
};
struct aarp {
nd_uint16_t htype, ptype;
nd_uint8_t halen, palen;
nd_uint16_t op;
nd_mac_addr hsaddr;
uint8_t psaddr[4];
nd_mac_addr hdaddr;
uint8_t pdaddr[4];
};
static void atp_print(netdissect_options *, const struct atATP *, u_int);
static void atp_bitmap_print(netdissect_options *, u_char);
static void nbp_print(netdissect_options *, const struct atNBP *, u_int, u_short, u_char, u_char);
static const struct atNBPtuple *nbp_tuple_print(netdissect_options *ndo, const struct atNBPtuple *,
const u_char *,
u_short, u_char, u_char);
static const struct atNBPtuple *nbp_name_print(netdissect_options *, const struct atNBPtuple *,
const u_char *);
static const char *ataddr_string(netdissect_options *, u_short, u_char);
static void ddp_print(netdissect_options *, const u_char *, u_int, u_int, u_short, u_char, u_char);
static const char *ddpskt_string(netdissect_options *, u_int);
/*
* Print LLAP packets received on a physical LocalTalk interface.
*/
void
ltalk_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h, const u_char *p)
{
u_int hdrlen;
ndo->ndo_protocol = "ltalk";
hdrlen = llap_print(ndo, p, h->len);
if (hdrlen == 0) {
/* Cut short by the snapshot length. */
ndo->ndo_ll_hdr_len += h->caplen;
return;
}
ndo->ndo_ll_hdr_len += hdrlen;
}
/*
* Print AppleTalk LLAP packets.
*/
u_int
llap_print(netdissect_options *ndo,
const u_char *bp, u_int length)
{
const struct LAP *lp;
const struct atDDP *dp;
const struct atShortDDP *sdp;
u_short snet;
u_int hdrlen;
ndo->ndo_protocol = "llap";
if (length < sizeof(*lp)) {
ND_PRINT(" [|llap %u]", length);
return (length);
}
if (!ND_TTEST_LEN(bp, sizeof(*lp))) {
nd_print_trunc(ndo);
return (0); /* cut short by the snapshot length */
}
lp = (const struct LAP *)bp;
bp += sizeof(*lp);
length -= sizeof(*lp);
hdrlen = sizeof(*lp);
switch (GET_U_1(lp->type)) {
case lapShortDDP:
if (length < ddpSSize) {
ND_PRINT(" [|sddp %u]", length);
return (length);
}
if (!ND_TTEST_LEN(bp, ddpSSize)) {
ND_PRINT(" [|sddp]");
return (0); /* cut short by the snapshot length */
}
sdp = (const struct atShortDDP *)bp;
ND_PRINT("%s.%s",
ataddr_string(ndo, 0, GET_U_1(lp->src)),
ddpskt_string(ndo, GET_U_1(sdp->srcSkt)));
ND_PRINT(" > %s.%s:",
ataddr_string(ndo, 0, GET_U_1(lp->dst)),
ddpskt_string(ndo, GET_U_1(sdp->dstSkt)));
bp += ddpSSize;
length -= ddpSSize;
hdrlen += ddpSSize;
ddp_print(ndo, bp, length, GET_U_1(sdp->type), 0,
GET_U_1(lp->src), GET_U_1(sdp->srcSkt));
break;
case lapDDP:
if (length < ddpSize) {
ND_PRINT(" [|ddp %u]", length);
return (length);
}
if (!ND_TTEST_LEN(bp, ddpSize)) {
ND_PRINT(" [|ddp]");
return (0); /* cut short by the snapshot length */
}
dp = (const struct atDDP *)bp;
snet = GET_BE_U_2(dp->srcNet);
ND_PRINT("%s.%s",
ataddr_string(ndo, snet, GET_U_1(dp->srcNode)),
ddpskt_string(ndo, GET_U_1(dp->srcSkt)));
ND_PRINT(" > %s.%s:",
ataddr_string(ndo, GET_BE_U_2(dp->dstNet), GET_U_1(dp->dstNode)),
ddpskt_string(ndo, GET_U_1(dp->dstSkt)));
bp += ddpSize;
length -= ddpSize;
hdrlen += ddpSize;
ddp_print(ndo, bp, length, GET_U_1(dp->type), snet,
GET_U_1(dp->srcNode), GET_U_1(dp->srcSkt));
break;
#ifdef notdef
case lapKLAP:
klap_print(bp, length);
break;
#endif
default:
ND_PRINT("%u > %u at-lap#%u %u",
GET_U_1(lp->src), GET_U_1(lp->dst), GET_U_1(lp->type),
length);
break;
}
return (hdrlen);
}
/*
* Print EtherTalk/TokenTalk packets (or FDDITalk, or whatever it's called
* when it runs over FDDI; yes, I've seen FDDI captures with AppleTalk
* packets in them).
*/
void
atalk_print(netdissect_options *ndo,
const u_char *bp, u_int length)
{
const struct atDDP *dp;
u_short snet;
ndo->ndo_protocol = "atalk";
if(!ndo->ndo_eflag)
ND_PRINT("AT ");
if (length < ddpSize) {
ND_PRINT(" [|ddp %u]", length);
return;
}
if (!ND_TTEST_LEN(bp, ddpSize)) {
ND_PRINT(" [|ddp]");
return;
}
dp = (const struct atDDP *)bp;
snet = GET_BE_U_2(dp->srcNet);
ND_PRINT("%s.%s", ataddr_string(ndo, snet, GET_U_1(dp->srcNode)),
ddpskt_string(ndo, GET_U_1(dp->srcSkt)));
ND_PRINT(" > %s.%s: ",
ataddr_string(ndo, GET_BE_U_2(dp->dstNet), GET_U_1(dp->dstNode)),
ddpskt_string(ndo, GET_U_1(dp->dstSkt)));
bp += ddpSize;
length -= ddpSize;
ddp_print(ndo, bp, length, GET_U_1(dp->type), snet,
GET_U_1(dp->srcNode), GET_U_1(dp->srcSkt));
}
/* XXX should probably pass in the snap header and do checks like arp_print() */
void
aarp_print(netdissect_options *ndo,
const u_char *bp, u_int length)
{
const struct aarp *ap;
#define AT(member) ataddr_string(ndo, (ap->member[1]<<8)|ap->member[2],ap->member[3])
ndo->ndo_protocol = "aarp";
ND_PRINT("aarp ");
ap = (const struct aarp *)bp;
if (!ND_TTEST_SIZE(ap)) {
/* Just bail if we don't have the whole chunk. */
nd_print_trunc(ndo);
return;
}
if (length < sizeof(*ap)) {
ND_PRINT(" [|aarp %u]", length);
return;
}
if (GET_BE_U_2(ap->htype) == 1 &&
GET_BE_U_2(ap->ptype) == ETHERTYPE_ATALK &&
GET_U_1(ap->halen) == MAC_ADDR_LEN && GET_U_1(ap->palen) == 4)
switch (GET_BE_U_2(ap->op)) {
case 1: /* request */
ND_PRINT("who-has %s tell %s", AT(pdaddr), AT(psaddr));
return;
case 2: /* response */
ND_PRINT("reply %s is-at %s", AT(psaddr), GET_ETHERADDR_STRING(ap->hsaddr));
return;
case 3: /* probe (oy!) */
ND_PRINT("probe %s tell %s", AT(pdaddr), AT(psaddr));
return;
}
ND_PRINT("len %u op %u htype %u ptype %#x halen %u palen %u",
length, GET_BE_U_2(ap->op), GET_BE_U_2(ap->htype),
GET_BE_U_2(ap->ptype), GET_U_1(ap->halen), GET_U_1(ap->palen));
}
/*
* Print AppleTalk Datagram Delivery Protocol packets.
*/
static void
ddp_print(netdissect_options *ndo,
const u_char *bp, u_int length, u_int t,
u_short snet, u_char snode, u_char skt)
{
switch (t) {
case ddpNBP:
nbp_print(ndo, (const struct atNBP *)bp, length, snet, snode, skt);
break;
case ddpATP:
atp_print(ndo, (const struct atATP *)bp, length);
break;
case ddpEIGRP:
eigrp_print(ndo, bp, length);
break;
default:
ND_PRINT(" at-%s %u", tok2str(type2str, NULL, t), length);
break;
}
}
static void
atp_print(netdissect_options *ndo,
const struct atATP *ap, u_int length)
{
uint8_t control;
uint32_t data;
if ((const u_char *)(ap + 1) > ndo->ndo_snapend) {
/* Just bail if we don't have the whole chunk. */
nd_print_trunc(ndo);
return;
}
if (length < sizeof(*ap)) {
ND_PRINT(" [|atp %u]", length);
return;
}
length -= sizeof(*ap);
control = GET_U_1(ap->control);
switch (control & 0xc0) {
case atpReqCode:
ND_PRINT(" atp-req%s %u",
control & atpXO? " " : "*",
GET_BE_U_2(ap->transID));
atp_bitmap_print(ndo, GET_U_1(ap->bitmap));
if (length != 0)
ND_PRINT(" [len=%u]", length);
switch (control & (atpEOM|atpSTS)) {
case atpEOM:
ND_PRINT(" [EOM]");
break;
case atpSTS:
ND_PRINT(" [STS]");
break;
case atpEOM|atpSTS:
ND_PRINT(" [EOM,STS]");
break;
}
break;
case atpRspCode:
ND_PRINT(" atp-resp%s%u:%u (%u)",
control & atpEOM? "*" : " ",
GET_BE_U_2(ap->transID), GET_U_1(ap->bitmap),
length);
switch (control & (atpXO|atpSTS)) {
case atpXO:
ND_PRINT(" [XO]");
break;
case atpSTS:
ND_PRINT(" [STS]");
break;
case atpXO|atpSTS:
ND_PRINT(" [XO,STS]");
break;
}
break;
case atpRelCode:
ND_PRINT(" atp-rel %u", GET_BE_U_2(ap->transID));
atp_bitmap_print(ndo, GET_U_1(ap->bitmap));
/* length should be zero */
if (length)
ND_PRINT(" [len=%u]", length);
/* there shouldn't be any control flags */
if (control & (atpXO|atpEOM|atpSTS)) {
char c = '[';
if (control & atpXO) {
ND_PRINT("%cXO", c);
c = ',';
}
if (control & atpEOM) {
ND_PRINT("%cEOM", c);
c = ',';
}
if (control & atpSTS) {
ND_PRINT("%cSTS", c);
}
ND_PRINT("]");
}
break;
default:
ND_PRINT(" atp-0x%x %u (%u)", control,
GET_BE_U_2(ap->transID), length);
break;
}
data = GET_BE_U_4(ap->userData);
if (data != 0)
ND_PRINT(" 0x%x", data);
}
static void
atp_bitmap_print(netdissect_options *ndo,
u_char bm)
{
u_int i;
/*
* The '& 0xff' below is needed for compilers that want to sign
* extend a u_char, which is the case with the Ultrix compiler.
* (gcc is smart enough to eliminate it, at least on the Sparc).
*/
if ((bm + 1) & (bm & 0xff)) {
char c = '<';
for (i = 0; bm; ++i) {
if (bm & 1) {
ND_PRINT("%c%u", c, i);
c = ',';
}
bm >>= 1;
}
ND_PRINT(">");
} else {
for (i = 0; bm; ++i)
bm >>= 1;
if (i > 1)
ND_PRINT("<0-%u>", i - 1);
else
ND_PRINT("<0>");
}
}
static void
nbp_print(netdissect_options *ndo,
const struct atNBP *np, u_int length, u_short snet,
u_char snode, u_char skt)
{
const struct atNBPtuple *tp =
(const struct atNBPtuple *)((const u_char *)np + nbpHeaderSize);
uint8_t control;
u_int i;
const u_char *ep;
if (length < nbpHeaderSize) {
ND_PRINT(" truncated-nbp %u", length);
return;
}
length -= nbpHeaderSize;
if (length < 8) {
/* must be room for at least one tuple */
ND_PRINT(" truncated-nbp %u", length + nbpHeaderSize);
return;
}
/* ep points to end of available data */
ep = ndo->ndo_snapend;
if ((const u_char *)tp > ep) {
nd_print_trunc(ndo);
return;
}
control = GET_U_1(np->control);
switch (i = (control & 0xf0)) {
case nbpBrRq:
case nbpLkUp:
ND_PRINT(i == nbpLkUp? " nbp-lkup %u:":" nbp-brRq %u:",
GET_U_1(np->id));
if ((const u_char *)(tp + 1) > ep) {
nd_print_trunc(ndo);
return;
}
(void)nbp_name_print(ndo, tp, ep);
/*
* look for anomalies: the spec says there can only
* be one tuple, the address must match the source
* address and the enumerator should be zero.
*/
if ((control & 0xf) != 1)
ND_PRINT(" [ntup=%u]", control & 0xf);
if (GET_U_1(tp->enumerator))
ND_PRINT(" [enum=%u]", GET_U_1(tp->enumerator));
if (GET_BE_U_2(tp->net) != snet ||
GET_U_1(tp->node) != snode ||
GET_U_1(tp->skt) != skt)
ND_PRINT(" [addr=%s.%u]",
ataddr_string(ndo, GET_BE_U_2(tp->net),
GET_U_1(tp->node)),
GET_U_1(tp->skt));
break;
case nbpLkUpReply:
ND_PRINT(" nbp-reply %u:", GET_U_1(np->id));
/* print each of the tuples in the reply */
for (i = control & 0xf; i != 0 && tp; i--)
tp = nbp_tuple_print(ndo, tp, ep, snet, snode, skt);
break;
default:
ND_PRINT(" nbp-0x%x %u (%u)", control, GET_U_1(np->id),
length);
break;
}
}
/* print a counted string */
static const u_char *
print_cstring(netdissect_options *ndo,
const u_char *cp, const u_char *ep)
{
u_int length;
if (cp >= ep) {
nd_print_trunc(ndo);
return (0);
}
length = GET_U_1(cp);
cp++;
/* Spec says string can be at most 32 bytes long */
if (length > 32) {
ND_PRINT("[len=%u]", length);
return (0);
}
while (length != 0) {
if (cp >= ep) {
nd_print_trunc(ndo);
return (0);
}
fn_print_char(ndo, GET_U_1(cp));
cp++;
length--;
}
return (cp);
}
static const struct atNBPtuple *
nbp_tuple_print(netdissect_options *ndo,
const struct atNBPtuple *tp, const u_char *ep,
u_short snet, u_char snode, u_char skt)
{
const struct atNBPtuple *tpn;
if ((const u_char *)(tp + 1) > ep) {
nd_print_trunc(ndo);
return 0;
}
tpn = nbp_name_print(ndo, tp, ep);
/* if the enumerator isn't 1, print it */
if (GET_U_1(tp->enumerator) != 1)
ND_PRINT("(%u)", GET_U_1(tp->enumerator));
/* if the socket doesn't match the src socket, print it */
if (GET_U_1(tp->skt) != skt)
ND_PRINT(" %u", GET_U_1(tp->skt));
/* if the address doesn't match the src address, it's an anomaly */
if (GET_BE_U_2(tp->net) != snet ||
GET_U_1(tp->node) != snode)
ND_PRINT(" [addr=%s]",
ataddr_string(ndo, GET_BE_U_2(tp->net), GET_U_1(tp->node)));
return (tpn);
}
static const struct atNBPtuple *
nbp_name_print(netdissect_options *ndo,
const struct atNBPtuple *tp, const u_char *ep)
{
const u_char *cp = (const u_char *)tp + nbpTupleSize;
ND_PRINT(" ");
/* Object */
ND_PRINT("\"");
if ((cp = print_cstring(ndo, cp, ep)) != NULL) {
/* Type */
ND_PRINT(":");
if ((cp = print_cstring(ndo, cp, ep)) != NULL) {
/* Zone */
ND_PRINT("@");
if ((cp = print_cstring(ndo, cp, ep)) != NULL)
ND_PRINT("\"");
}
}
return ((const struct atNBPtuple *)cp);
}
#define HASHNAMESIZE 4096
struct hnamemem {
u_int addr;
char *name;
struct hnamemem *nxt;
};
static struct hnamemem hnametable[HASHNAMESIZE];
static const char *
ataddr_string(netdissect_options *ndo,
u_short atnet, u_char athost)
{
struct hnamemem *tp, *tp2;
u_int i = (atnet << 8) | athost;
char nambuf[256+1];
static int first = 1;
FILE *fp;
/*
* Are we doing address to name resolution?
*/
if (!ndo->ndo_nflag) {
/*
* Yes. Have we tried to open and read an AppleTalk
* number to name map file?
*/
if (!first) {
/*
* No; try to do so.
*/
first = 0;
fp = fopen("/etc/atalk.names", "r");
if (fp != NULL) {
char line[256];
u_int i1, i2;
while (fgets(line, sizeof(line), fp)) {
if (line[0] == '\n' || line[0] == 0 ||
line[0] == '#')
continue;
if (sscanf(line, "%u.%u %256s", &i1,
&i2, nambuf) == 3)
/* got a hostname. */
i2 |= (i1 << 8);
else if (sscanf(line, "%u %256s", &i1,
nambuf) == 2)
/* got a net name */
i2 = (i1 << 8) | 255;
else
continue;
for (tp = &hnametable[i2 & (HASHNAMESIZE-1)];
tp->nxt; tp = tp->nxt)
;
tp->addr = i2;
tp->nxt = newhnamemem(ndo);
tp->name = strdup(nambuf);
if (tp->name == NULL)
(*ndo->ndo_error)(ndo,
S_ERR_ND_MEM_ALLOC,
"%s: strdup(nambuf)", __func__);
}
fclose(fp);
}
}
}
/*
* Now try to look up the address in the table.
*/
for (tp = &hnametable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
if (tp->addr == i)
return (tp->name);
/* didn't have the node name -- see if we've got the net name */
i |= 255;
for (tp2 = &hnametable[i & (HASHNAMESIZE-1)]; tp2->nxt; tp2 = tp2->nxt)
if (tp2->addr == i) {
tp->addr = (atnet << 8) | athost;
tp->nxt = newhnamemem(ndo);
(void)snprintf(nambuf, sizeof(nambuf), "%s.%u",
tp2->name, athost);
tp->name = strdup(nambuf);
if (tp->name == NULL)
(*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC,
"%s: strdup(nambuf)", __func__);
return (tp->name);
}
tp->addr = (atnet << 8) | athost;
tp->nxt = newhnamemem(ndo);
if (athost != 255)
(void)snprintf(nambuf, sizeof(nambuf), "%u.%u", atnet, athost);
else
(void)snprintf(nambuf, sizeof(nambuf), "%u", atnet);
tp->name = strdup(nambuf);
if (tp->name == NULL)
(*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC,
"%s: strdup(nambuf)", __func__);
return (tp->name);
}
static const struct tok skt2str[] = {
{ rtmpSkt, "rtmp" }, /* routing table maintenance */
{ nbpSkt, "nis" }, /* name info socket */
{ echoSkt, "echo" }, /* AppleTalk echo protocol */
{ zipSkt, "zip" }, /* zone info protocol */
{ 0, NULL }
};
static const char *
ddpskt_string(netdissect_options *ndo,
u_int skt)
{
static char buf[8];
if (ndo->ndo_nflag) {
(void)snprintf(buf, sizeof(buf), "%u", skt);
return (buf);
}
return (tok2str(skt2str, "%u", skt));
}
diff --git a/contrib/tcpdump/print-atm.c b/contrib/tcpdump/print-atm.c
index 904fc4792e92..2dee4e65e97a 100644
--- a/contrib/tcpdump/print-atm.c
+++ b/contrib/tcpdump/print-atm.c
@@ -1,530 +1,528 @@
/*
* Copyright (c) 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.
*/
/* \summary: Asynchronous Transfer Mode (ATM) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
#include "addrtoname.h"
#include "atm.h"
#include "llc.h"
/* start of the original atmuni31.h */
/*
* Copyright (c) 1997 Yen Yen Lim and North Dakota State University
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Yen Yen Lim and
North Dakota State University
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* Based on UNI3.1 standard by ATM Forum */
/* ATM traffic types based on VPI=0 and (the following VCI */
#define VCI_PPC 0x05 /* Point-to-point signal msg */
#define VCI_BCC 0x02 /* Broadcast signal msg */
#define VCI_OAMF4SC 0x03 /* Segment OAM F4 flow cell */
#define VCI_OAMF4EC 0x04 /* End-to-end OAM F4 flow cell */
#define VCI_METAC 0x01 /* Meta signal msg */
#define VCI_ILMIC 0x10 /* ILMI msg */
/* Q.2931 signalling messages */
#define CALL_PROCEED 0x02 /* call proceeding */
#define CONNECT 0x07 /* connect */
#define CONNECT_ACK 0x0f /* connect_ack */
#define SETUP 0x05 /* setup */
#define RELEASE 0x4d /* release */
#define RELEASE_DONE 0x5a /* release_done */
#define RESTART 0x46 /* restart */
#define RESTART_ACK 0x4e /* restart ack */
#define STATUS 0x7d /* status */
#define STATUS_ENQ 0x75 /* status ack */
#define ADD_PARTY 0x80 /* add party */
#define ADD_PARTY_ACK 0x81 /* add party ack */
#define ADD_PARTY_REJ 0x82 /* add party rej */
#define DROP_PARTY 0x83 /* drop party */
#define DROP_PARTY_ACK 0x84 /* drop party ack */
/* Information Element Parameters in the signalling messages */
#define CAUSE 0x08 /* cause */
#define ENDPT_REF 0x54 /* endpoint reference */
#define AAL_PARA 0x58 /* ATM adaptation layer parameters */
#define TRAFF_DESCRIP 0x59 /* atm traffic descriptors */
#define CONNECT_ID 0x5a /* connection identifier */
#define QOS_PARA 0x5c /* quality of service parameters */
#define B_HIGHER 0x5d /* broadband higher layer information */
#define B_BEARER 0x5e /* broadband bearer capability */
#define B_LOWER 0x5f /* broadband lower information */
#define CALLING_PARTY 0x6c /* calling party number */
-#define CALLED_PARTY 0x70 /* called party nmber */
+#define CALLED_PARTY 0x70 /* called party number */
#define Q2931 0x09
/* Q.2931 signalling general messages format */
#define PROTO_POS 0 /* offset of protocol discriminator */
#define CALL_REF_POS 2 /* offset of call reference value */
#define MSG_TYPE_POS 5 /* offset of message type */
#if 0
#define MSG_LEN_POS 7 /* offset of message length */
#define IE_BEGIN_POS 9 /* offset of first information element */
/* format of signalling messages */
#define TYPE_POS 0
#define LEN_POS 2
#define FIELD_BEGIN_POS 4
#endif
/* end of the original atmuni31.h */
#define OAM_CRC10_MASK 0x3ff
#define OAM_PAYLOAD_LEN 48
#define OAM_FUNCTION_SPECIFIC_LEN 45 /* this excludes crc10 and cell-type/function-type */
#define OAM_CELLTYPE_FUNCTYPE_LEN 1
static const struct tok oam_f_values[] = {
{ VCI_OAMF4SC, "OAM F4 (segment)" },
{ VCI_OAMF4EC, "OAM F4 (end)" },
{ 0, NULL }
};
static const struct tok atm_pty_values[] = {
{ 0x0, "user data, uncongested, SDU 0" },
{ 0x1, "user data, uncongested, SDU 1" },
{ 0x2, "user data, congested, SDU 0" },
{ 0x3, "user data, congested, SDU 1" },
{ 0x4, "VCC OAM F5 flow segment" },
{ 0x5, "VCC OAM F5 flow end-to-end" },
{ 0x6, "Traffic Control and resource Mgmt" },
{ 0, NULL }
};
#define OAM_CELLTYPE_FM 0x1
#define OAM_CELLTYPE_PM 0x2
#define OAM_CELLTYPE_AD 0x8
#define OAM_CELLTYPE_SM 0xf
static const struct tok oam_celltype_values[] = {
{ OAM_CELLTYPE_FM, "Fault Management" },
{ OAM_CELLTYPE_PM, "Performance Management" },
{ OAM_CELLTYPE_AD, "activate/deactivate" },
{ OAM_CELLTYPE_SM, "System Management" },
{ 0, NULL }
};
#define OAM_FM_FUNCTYPE_AIS 0x0
#define OAM_FM_FUNCTYPE_RDI 0x1
#define OAM_FM_FUNCTYPE_CONTCHECK 0x4
#define OAM_FM_FUNCTYPE_LOOPBACK 0x8
static const struct tok oam_fm_functype_values[] = {
{ OAM_FM_FUNCTYPE_AIS, "AIS" },
{ OAM_FM_FUNCTYPE_RDI, "RDI" },
{ OAM_FM_FUNCTYPE_CONTCHECK, "Continuity Check" },
{ OAM_FM_FUNCTYPE_LOOPBACK, "Loopback" },
{ 0, NULL }
};
static const struct tok oam_pm_functype_values[] = {
{ 0x0, "Forward Monitoring" },
{ 0x1, "Backward Reporting" },
{ 0x2, "Monitoring and Reporting" },
{ 0, NULL }
};
static const struct tok oam_ad_functype_values[] = {
{ 0x0, "Performance Monitoring" },
{ 0x1, "Continuity Check" },
{ 0, NULL }
};
#define OAM_FM_LOOPBACK_INDICATOR_MASK 0x1
static const struct tok oam_fm_loopback_indicator_values[] = {
{ 0x0, "Reply" },
{ 0x1, "Request" },
{ 0, NULL }
};
static const struct uint_tokary oam_celltype2tokary[] = {
{ OAM_CELLTYPE_FM, oam_fm_functype_values },
{ OAM_CELLTYPE_PM, oam_pm_functype_values },
{ OAM_CELLTYPE_AD, oam_ad_functype_values },
/* uint2tokary() does not use array termination. */
};
/*
* Print an RFC 1483 LLC-encapsulated ATM frame.
*/
static u_int
atm_llc_print(netdissect_options *ndo,
const u_char *p, int length, int caplen)
{
int llc_hdrlen;
llc_hdrlen = llc_print(ndo, p, length, caplen, NULL, NULL);
if (llc_hdrlen < 0) {
/* packet not known, print raw packet */
if (!ndo->ndo_suppress_default_print)
ND_DEFAULTPRINT(p, caplen);
llc_hdrlen = -llc_hdrlen;
}
return (llc_hdrlen);
}
/*
* Given a SAP value, generate the LLC header value for a UI packet
* with that SAP as the source and destination SAP.
*/
#define LLC_UI_HDR(sap) ((sap)<<16 | (sap<<8) | 0x03)
/*
* This is the top level routine of the printer. 'p' points
* to the LLC/SNAP header of the packet, 'h->ts' is the timestamp,
* 'h->len' is the length of the packet off the wire, and 'h->caplen'
* is the number of bytes actually captured.
*/
void
atm_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h, const u_char *p)
{
u_int caplen = h->caplen;
u_int length = h->len;
uint32_t llchdr;
u_int hdrlen = 0;
ndo->ndo_protocol = "atm";
/* Cisco Style NLPID ? */
if (GET_U_1(p) == LLC_UI) {
if (ndo->ndo_eflag)
ND_PRINT("CNLPID ");
ndo->ndo_ll_hdr_len += 1;
isoclns_print(ndo, p + 1, length - 1);
return;
}
/*
* Must have at least a DSAP, an SSAP, and the first byte of the
* control field.
*/
/*
* Extract the presumed LLC header into a variable, for quick
* testing.
* Then check for a header that's neither a header for a SNAP
* packet nor an RFC 2684 routed NLPID-formatted PDU nor
* an 802.2-but-no-SNAP IP packet.
*/
llchdr = GET_BE_U_3(p);
if (llchdr != LLC_UI_HDR(LLCSAP_SNAP) &&
llchdr != LLC_UI_HDR(LLCSAP_ISONS) &&
llchdr != LLC_UI_HDR(LLCSAP_IP)) {
/*
* XXX - assume 802.6 MAC header from Fore driver.
*
* Unfortunately, the above list doesn't check for
* all known SAPs, doesn't check for headers where
* the source and destination SAP aren't the same,
* and doesn't check for non-UI frames. It also
* runs the risk of an 802.6 MAC header that happens
* to begin with one of those values being
* incorrectly treated as an 802.2 header.
*
* So is that Fore driver still around? And, if so,
* is it still putting 802.6 MAC headers on ATM
* packets? If so, could it be changed to use a
* new DLT_IEEE802_6 value if we added it?
*/
if (ndo->ndo_eflag)
ND_PRINT("%08x%08x %08x%08x ",
GET_BE_U_4(p),
GET_BE_U_4(p + 4),
GET_BE_U_4(p + 8),
GET_BE_U_4(p + 12));
/* Always cover the full header. */
ND_TCHECK_LEN(p, 20);
p += 20;
length -= 20;
caplen -= 20;
hdrlen += 20;
}
ndo->ndo_ll_hdr_len += hdrlen;
ndo->ndo_ll_hdr_len += atm_llc_print(ndo, p, length, caplen);
}
/*
* ATM signalling.
*/
static const struct tok msgtype2str[] = {
{ CALL_PROCEED, "Call_proceeding" },
{ CONNECT, "Connect" },
{ CONNECT_ACK, "Connect_ack" },
{ SETUP, "Setup" },
{ RELEASE, "Release" },
{ RELEASE_DONE, "Release_complete" },
{ RESTART, "Restart" },
{ RESTART_ACK, "Restart_ack" },
{ STATUS, "Status" },
{ STATUS_ENQ, "Status_enquiry" },
{ ADD_PARTY, "Add_party" },
{ ADD_PARTY_ACK, "Add_party_ack" },
{ ADD_PARTY_REJ, "Add_party_reject" },
{ DROP_PARTY, "Drop_party" },
{ DROP_PARTY_ACK, "Drop_party_ack" },
{ 0, NULL }
};
static void
sig_print(netdissect_options *ndo,
const u_char *p)
{
uint32_t call_ref;
if (GET_U_1(p + PROTO_POS) == Q2931) {
/*
* protocol:Q.2931 for User to Network Interface
* (UNI 3.1) signalling
*/
ND_PRINT("Q.2931");
ND_PRINT(":%s ",
tok2str(msgtype2str, "msgtype#%u", GET_U_1(p + MSG_TYPE_POS)));
/*
* The call reference comes before the message type,
* so if we know we have the message type, which we
* do from the caplen test above, we also know we have
* the call reference.
*/
call_ref = GET_BE_U_3(p + CALL_REF_POS);
ND_PRINT("CALL_REF:0x%06x", call_ref);
} else {
/* SSCOP with some unknown protocol atop it */
ND_PRINT("SSCOP, proto %u ", GET_U_1(p + PROTO_POS));
}
}
/*
* Print an ATM PDU (such as an AAL5 PDU).
*/
void
atm_print(netdissect_options *ndo,
u_int vpi, u_int vci, u_int traftype, const u_char *p, u_int length,
u_int caplen)
{
ndo->ndo_protocol = "atm";
if (ndo->ndo_eflag)
ND_PRINT("VPI:%u VCI:%u ", vpi, vci);
if (vpi == 0) {
switch (vci) {
case VCI_PPC:
sig_print(ndo, p);
return;
case VCI_BCC:
ND_PRINT("broadcast sig: ");
return;
case VCI_OAMF4SC: /* fall through */
case VCI_OAMF4EC:
oam_print(ndo, p, length, ATM_OAM_HEC);
return;
case VCI_METAC:
ND_PRINT("meta: ");
return;
case VCI_ILMIC:
ND_PRINT("ilmi: ");
snmp_print(ndo, p, length);
return;
}
}
switch (traftype) {
case ATM_LLC:
default:
/*
* Assumes traffic is LLC if unknown.
*/
atm_llc_print(ndo, p, length, caplen);
break;
case ATM_LANE:
lane_print(ndo, p, length, caplen);
break;
}
}
struct oam_fm_loopback_t {
nd_uint8_t loopback_indicator;
nd_uint32_t correlation_tag;
nd_byte loopback_id[12];
nd_byte source_id[12];
nd_byte unused[16];
};
struct oam_fm_ais_rdi_t {
nd_uint8_t failure_type;
nd_byte failure_location[16];
nd_byte unused[28];
};
void
oam_print(netdissect_options *ndo,
const u_char *p, u_int length, u_int hec)
{
uint32_t cell_header;
uint16_t vpi, vci, cksum, cksum_shouldbe, idx;
uint8_t cell_type, func_type, payload, clp;
const struct tok *oam_functype_str;
union {
const struct oam_fm_loopback_t *oam_fm_loopback;
const struct oam_fm_ais_rdi_t *oam_fm_ais_rdi;
} oam_ptr;
ndo->ndo_protocol = "oam";
cell_header = GET_BE_U_4(p + hec);
cell_type = (GET_U_1((p + ATM_HDR_LEN_NOHEC + hec)) >> 4) & 0x0f;
func_type = GET_U_1((p + ATM_HDR_LEN_NOHEC + hec)) & 0x0f;
vpi = (cell_header>>20)&0xff;
vci = (cell_header>>4)&0xffff;
payload = (cell_header>>1)&0x7;
clp = cell_header&0x1;
ND_PRINT("%s, vpi %u, vci %u, payload [ %s ], clp %u, length %u",
tok2str(oam_f_values, "OAM F5", vci),
vpi, vci,
tok2str(atm_pty_values, "Unknown", payload),
clp, length);
if (!ndo->ndo_vflag) {
return;
}
ND_PRINT("\n\tcell-type %s (%u)",
tok2str(oam_celltype_values, "unknown", cell_type),
cell_type);
oam_functype_str = uint2tokary(oam_celltype2tokary, cell_type);
if (oam_functype_str == NULL)
ND_PRINT(", func-type unknown (%u)", func_type);
else
ND_PRINT(", func-type %s (%u)",
tok2str(oam_functype_str, "none", func_type),
func_type);
p += ATM_HDR_LEN_NOHEC + hec;
switch (cell_type << 4 | func_type) {
case (OAM_CELLTYPE_FM << 4 | OAM_FM_FUNCTYPE_LOOPBACK):
oam_ptr.oam_fm_loopback = (const struct oam_fm_loopback_t *)(p + OAM_CELLTYPE_FUNCTYPE_LEN);
ND_TCHECK_SIZE(oam_ptr.oam_fm_loopback);
ND_PRINT("\n\tLoopback-Indicator %s, Correlation-Tag 0x%08x",
tok2str(oam_fm_loopback_indicator_values,
"Unknown",
GET_U_1(oam_ptr.oam_fm_loopback->loopback_indicator) & OAM_FM_LOOPBACK_INDICATOR_MASK),
GET_BE_U_4(oam_ptr.oam_fm_loopback->correlation_tag));
ND_PRINT("\n\tLocation-ID ");
for (idx = 0; idx < sizeof(oam_ptr.oam_fm_loopback->loopback_id); idx++) {
if (idx % 2) {
ND_PRINT("%04x ",
GET_BE_U_2(&oam_ptr.oam_fm_loopback->loopback_id[idx]));
}
}
ND_PRINT("\n\tSource-ID ");
for (idx = 0; idx < sizeof(oam_ptr.oam_fm_loopback->source_id); idx++) {
if (idx % 2) {
ND_PRINT("%04x ",
GET_BE_U_2(&oam_ptr.oam_fm_loopback->source_id[idx]));
}
}
break;
case (OAM_CELLTYPE_FM << 4 | OAM_FM_FUNCTYPE_AIS):
case (OAM_CELLTYPE_FM << 4 | OAM_FM_FUNCTYPE_RDI):
oam_ptr.oam_fm_ais_rdi = (const struct oam_fm_ais_rdi_t *)(p + OAM_CELLTYPE_FUNCTYPE_LEN);
ND_TCHECK_SIZE(oam_ptr.oam_fm_ais_rdi);
ND_PRINT("\n\tFailure-type 0x%02x",
GET_U_1(oam_ptr.oam_fm_ais_rdi->failure_type));
ND_PRINT("\n\tLocation-ID ");
for (idx = 0; idx < sizeof(oam_ptr.oam_fm_ais_rdi->failure_location); idx++) {
if (idx % 2) {
ND_PRINT("%04x ",
GET_BE_U_2(&oam_ptr.oam_fm_ais_rdi->failure_location[idx]));
}
}
break;
case (OAM_CELLTYPE_FM << 4 | OAM_FM_FUNCTYPE_CONTCHECK):
/* FIXME */
break;
default:
break;
}
/* crc10 checksum verification */
cksum = GET_BE_U_2(p + OAM_CELLTYPE_FUNCTYPE_LEN + OAM_FUNCTION_SPECIFIC_LEN)
& OAM_CRC10_MASK;
cksum_shouldbe = verify_crc10_cksum(0, p, OAM_PAYLOAD_LEN);
ND_PRINT("\n\tcksum 0x%03x (%scorrect)",
cksum,
cksum_shouldbe == 0 ? "" : "in");
}
diff --git a/contrib/tcpdump/print-babel.c b/contrib/tcpdump/print-babel.c
index d802a720f12f..cea7eedf0772 100644
--- a/contrib/tcpdump/print-babel.c
+++ b/contrib/tcpdump/print-babel.c
@@ -1,863 +1,861 @@
/*
* Copyright (c) 2007-2011 Grégoire Henry, Juliusz Chroboczek
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* \summary: Babel Routing Protocol printer */
/* Specifications:
*
* RFC 6126
* RFC 7298
* RFC 7557
* draft-ietf-babel-rfc6126bis-17
* draft-ietf-babel-hmac-10
* draft-ietf-babel-source-specific-0
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <stdio.h>
#include <string.h>
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
static void babel_print_v2(netdissect_options *, const u_char *cp, u_int length);
void
babel_print(netdissect_options *ndo,
const u_char *cp, u_int length)
{
ndo->ndo_protocol = "babel";
ND_PRINT("babel");
ND_TCHECK_4(cp);
if(GET_U_1(cp) != 42) {
ND_PRINT(" invalid header");
return;
} else {
ND_PRINT(" %u", GET_U_1(cp + 1));
}
switch(GET_U_1(cp + 1)) {
case 2:
babel_print_v2(ndo, cp, length);
break;
default:
ND_PRINT(" unknown version");
break;
}
return;
trunc:
nd_print_trunc(ndo);
}
/* TLVs */
#define MESSAGE_PAD1 0
#define MESSAGE_PADN 1
#define MESSAGE_ACK_REQ 2
#define MESSAGE_ACK 3
#define MESSAGE_HELLO 4
#define MESSAGE_IHU 5
#define MESSAGE_ROUTER_ID 6
#define MESSAGE_NH 7
#define MESSAGE_UPDATE 8
#define MESSAGE_ROUTE_REQUEST 9
#define MESSAGE_SEQNO_REQUEST 10
#define MESSAGE_TSPC 11
#define MESSAGE_HMAC 12
#define MESSAGE_UPDATE_SRC_SPECIFIC 13 /* last appearance in draft-boutier-babel-source-specific-01 */
#define MESSAGE_REQUEST_SRC_SPECIFIC 14 /* idem */
#define MESSAGE_MH_REQUEST_SRC_SPECIFIC 15 /* idem */
#define MESSAGE_MAC 16
#define MESSAGE_PC 17
#define MESSAGE_CHALLENGE_REQUEST 18
#define MESSAGE_CHALLENGE_REPLY 19
/* sub-TLVs */
#define MESSAGE_SUB_PAD1 0
#define MESSAGE_SUB_PADN 1
#define MESSAGE_SUB_DIVERSITY 2
#define MESSAGE_SUB_TIMESTAMP 3
/* "Mandatory" bit in sub-TLV types */
#define MANDATORY_MASK 0x80
/* Flags for the Hello TLV */
#define UNICAST_MASK 0x8000
/* Diversity sub-TLV channel codes */
static const struct tok diversity_str[] = {
{ 0, "reserved" },
{ 255, "all" },
{ 0, NULL }
};
static const char *
format_id(netdissect_options *ndo, const u_char *id)
{
static char buf[25];
snprintf(buf, 25, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
GET_U_1(id), GET_U_1(id + 1), GET_U_1(id + 2),
GET_U_1(id + 3), GET_U_1(id + 4), GET_U_1(id + 5),
GET_U_1(id + 6), GET_U_1(id + 7));
buf[24] = '\0';
return buf;
}
static const unsigned char v4prefix[16] =
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
static const char *
format_prefix(netdissect_options *ndo, const u_char *prefix, unsigned char plen)
{
static char buf[50];
/*
* prefix points to a buffer on the stack into which the prefix has
* been placed, so we can't use GET_IPADDR_STRING() or
* GET_IP6ADDR_STRING() on it.
*/
if(plen >= 96 && memcmp(prefix, v4prefix, 12) == 0)
snprintf(buf, 50, "%s/%u", ipaddr_string(ndo, prefix + 12), plen - 96);
else
snprintf(buf, 50, "%s/%u", ip6addr_string(ndo, prefix), plen);
buf[49] = '\0';
return buf;
}
static const char *
format_address(netdissect_options *ndo, const u_char *prefix)
{
/*
* prefix points to a buffer on the stack into which the prefix has
* been placed, so we can't use GET_IPADDR_STRING() or
* GET_IP6ADDR_STRING() on it.
*/
if(memcmp(prefix, v4prefix, 12) == 0)
return ipaddr_string(ndo, prefix + 12);
else
return ip6addr_string(ndo, prefix);
}
static const char *
format_interval(const uint16_t i)
{
static char buf[sizeof("000.00s")];
if (i == 0)
return "0.0s (bogus)";
snprintf(buf, sizeof(buf), "%u.%02us", i / 100, i % 100);
return buf;
}
static const char *
format_interval_update(const uint16_t i)
{
return i == 0xFFFF ? "infinity" : format_interval(i);
}
static const char *
format_timestamp(const uint32_t i)
{
static char buf[sizeof("0000.000000s")];
snprintf(buf, sizeof(buf), "%u.%06us", i / 1000000, i % 1000000);
return buf;
}
/* Return number of octets consumed from the input buffer (not the prefix length
* in bytes), or -1 for encoding error. */
static int
network_prefix(int ae, int plen, unsigned int omitted,
const unsigned char *p, const unsigned char *dp,
unsigned int len, unsigned char *p_r)
{
unsigned pb;
unsigned char prefix[16];
int consumed = 0;
if(plen >= 0)
pb = (plen + 7) / 8;
else if(ae == 1)
pb = 4;
else
pb = 16;
if(pb > 16)
return -1;
memset(prefix, 0, 16);
switch(ae) {
case 0: break;
case 1:
if(omitted > 4 || pb > 4 || (pb > omitted && len < pb - omitted))
return -1;
memcpy(prefix, v4prefix, 12);
if(omitted) {
if (dp == NULL) return -1;
memcpy(prefix, dp, 12 + omitted);
}
if(pb > omitted) {
memcpy(prefix + 12 + omitted, p, pb - omitted);
consumed = pb - omitted;
}
break;
case 2:
if(omitted > 16 || (pb > omitted && len < pb - omitted))
return -1;
if(omitted) {
if (dp == NULL) return -1;
memcpy(prefix, dp, omitted);
}
if(pb > omitted) {
memcpy(prefix + omitted, p, pb - omitted);
consumed = pb - omitted;
}
break;
case 3:
if(pb > 8 && len < pb - 8) return -1;
prefix[0] = 0xfe;
prefix[1] = 0x80;
if(pb > 8) {
memcpy(prefix + 8, p, pb - 8);
consumed = pb - 8;
}
break;
default:
return -1;
}
memcpy(p_r, prefix, 16);
return consumed;
}
static int
network_address(int ae, const unsigned char *a, unsigned int len,
unsigned char *a_r)
{
return network_prefix(ae, -1, 0, a, NULL, len, a_r);
}
/*
* Sub-TLVs consume the "extra data" of Babel TLVs (see Section 4.3 of RFC6126),
* their encoding is similar to the encoding of TLVs, but the type namespace is
* different:
*
* o Type 0 stands for Pad1 sub-TLV with the same encoding as the Pad1 TLV.
* o Type 1 stands for PadN sub-TLV with the same encoding as the PadN TLV.
* o Type 2 stands for Diversity sub-TLV, which propagates diversity routing
* data. Its body is a variable-length sequence of 8-bit unsigned integers,
* each representing per-hop number of interfering radio channel for the
* prefix. Channel 0 is invalid and must not be used in the sub-TLV, channel
* 255 interferes with any other channel.
* o Type 3 stands for Timestamp sub-TLV, used to compute RTT between
* neighbours. In the case of a Hello TLV, the body stores a 32-bits
* timestamp, while in the case of a IHU TLV, two 32-bits timestamps are
* stored.
*
* Sub-TLV types 0 and 1 are valid for any TLV type, whether sub-TLV type 2 is
* only valid for TLV type 8 (Update). Note that within an Update TLV a missing
* Diversity sub-TLV is not the same as a Diversity sub-TLV with an empty body.
* The former would mean a lack of any claims about the interference, and the
* latter would state that interference is definitely absent.
* A type 3 sub-TLV is valid both for Hello and IHU TLVs, though the exact
* semantic of the sub-TLV is different in each case.
*/
static void
subtlvs_print(netdissect_options *ndo,
const u_char *cp, const u_char *ep, const uint8_t tlv_type)
{
uint8_t subtype, sublen;
const char *sep;
uint32_t t1, t2;
while (cp < ep) {
subtype = GET_U_1(cp);
cp++;
if(subtype == MESSAGE_SUB_PAD1) {
ND_PRINT(" sub-pad1");
continue;
}
if ((MANDATORY_MASK & subtype) != 0)
ND_PRINT(" (M)");
if(cp == ep)
goto invalid;
sublen = GET_U_1(cp);
cp++;
if(cp + sublen > ep)
goto invalid;
switch(subtype) {
case MESSAGE_SUB_PADN:
ND_PRINT(" sub-padn");
cp += sublen;
break;
case MESSAGE_SUB_DIVERSITY:
ND_PRINT(" sub-diversity");
if (sublen == 0) {
ND_PRINT(" empty");
break;
}
sep = " ";
while (sublen) {
ND_PRINT("%s%s", sep,
tok2str(diversity_str, "%u", GET_U_1(cp)));
cp++;
sep = "-";
sublen--;
}
if(tlv_type != MESSAGE_UPDATE &&
tlv_type != MESSAGE_UPDATE_SRC_SPECIFIC)
ND_PRINT(" (bogus)");
break;
case MESSAGE_SUB_TIMESTAMP:
ND_PRINT(" sub-timestamp");
if(tlv_type == MESSAGE_HELLO) {
if(sublen < 4)
goto invalid;
t1 = GET_BE_U_4(cp);
ND_PRINT(" %s", format_timestamp(t1));
} else if(tlv_type == MESSAGE_IHU) {
if(sublen < 8)
goto invalid;
t1 = GET_BE_U_4(cp);
ND_PRINT(" %s", format_timestamp(t1));
t2 = GET_BE_U_4(cp + 4);
ND_PRINT("|%s", format_timestamp(t2));
} else
ND_PRINT(" (bogus)");
cp += sublen;
break;
default:
ND_PRINT(" sub-unknown-0x%02x", subtype);
cp += sublen;
} /* switch */
} /* while */
return;
invalid:
nd_print_invalid(ndo);
}
#define ICHECK(i, l) \
if ((i) + (l) > tlvs_length || (i) + (l) > packet_length_remaining) \
goto invalid;
static int
babel_print_v2_tlvs(netdissect_options *ndo,
const u_char *cp, u_int tlvs_length,
u_int packet_length_remaining)
{
u_int i;
u_char v4_prefix[16] =
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
u_char v6_prefix[16] = {0};
i = 0;
while(i < tlvs_length) {
const u_char *message;
uint8_t type;
u_int len;
message = cp + i;
ICHECK(i, 1);
if((type = GET_U_1(message)) == MESSAGE_PAD1) {
ND_PRINT(ndo->ndo_vflag ? "\n\tPad 1" : " pad1");
i += 1;
continue;
}
ICHECK(i, 2);
ND_TCHECK_2(message);
len = GET_U_1(message + 1);
ICHECK(i, 2 + len);
ND_TCHECK_LEN(message, 2 + len);
switch(type) {
case MESSAGE_PADN: {
if (!ndo->ndo_vflag)
ND_PRINT(" padN");
else
ND_PRINT("\n\tPad %u", len + 2);
}
break;
case MESSAGE_ACK_REQ: {
u_short nonce, interval;
if (!ndo->ndo_vflag)
ND_PRINT(" ack-req");
else {
ND_PRINT("\n\tAcknowledgment Request ");
if(len < 6) goto invalid;
nonce = GET_BE_U_2(message + 4);
interval = GET_BE_U_2(message + 6);
ND_PRINT("%04x %s", nonce, format_interval(interval));
}
}
break;
case MESSAGE_ACK: {
u_short nonce;
if (!ndo->ndo_vflag)
ND_PRINT(" ack");
else {
ND_PRINT("\n\tAcknowledgment ");
if(len < 2) goto invalid;
nonce = GET_BE_U_2(message + 2);
ND_PRINT("%04x", nonce);
}
}
break;
case MESSAGE_HELLO: {
u_short seqno, interval, unicast;
if (!ndo->ndo_vflag)
ND_PRINT(" hello");
else {
ND_PRINT("\n\tHello ");
if(len < 6) goto invalid;
unicast = (GET_BE_U_2(message + 2) & UNICAST_MASK);
seqno = GET_BE_U_2(message + 4);
interval = GET_BE_U_2(message + 6);
if(unicast)
ND_PRINT("(Unicast) ");
ND_PRINT("seqno %u ", seqno);
if(interval!=0)
ND_PRINT("interval %s", format_interval(interval));
else
ND_PRINT("unscheduled");
/* Extra data. */
if(len > 6)
subtlvs_print(ndo, message + 8, message + 2 + len, type);
}
}
break;
case MESSAGE_IHU: {
unsigned short rxcost, interval;
if (!ndo->ndo_vflag)
ND_PRINT(" ihu");
else {
u_char address[16];
u_char ae;
int rc;
ND_PRINT("\n\tIHU ");
if(len < 6) goto invalid;
rxcost = GET_BE_U_2(message + 4);
interval = GET_BE_U_2(message + 6);
ae = GET_U_1(message + 2);
rc = network_address(ae, message + 8,
len - 6, address);
if(rc < 0) { nd_print_trunc(ndo); break; }
ND_PRINT("%s rxcost %u interval %s",
ae == 0 ? "any" : format_address(ndo, address),
rxcost, format_interval(interval));
/* Extra data. */
if((u_int)rc < len - 6)
subtlvs_print(ndo, message + 8 + rc, message + 2 + len,
type);
}
}
break;
case MESSAGE_ROUTER_ID: {
if (!ndo->ndo_vflag)
ND_PRINT(" router-id");
else {
ND_PRINT("\n\tRouter Id");
if(len < 10) goto invalid;
ND_PRINT(" %s", format_id(ndo, message + 4));
}
}
break;
case MESSAGE_NH: {
if (!ndo->ndo_vflag)
ND_PRINT(" nh");
else {
int rc;
u_char ae;
u_char nh[16];
ND_PRINT("\n\tNext Hop");
if(len < 2) goto invalid;
ae = GET_U_1(message + 2);
rc = network_address(ae, message + 4,
len - 2, nh);
if(rc < 0) goto invalid;
ND_PRINT(" %s", ae == 0 ? "invalid AE 0" : format_address(ndo, nh));
}
}
break;
case MESSAGE_UPDATE: {
if (!ndo->ndo_vflag) {
ND_PRINT(" update");
if(len < 10)
goto invalid;
else
ND_PRINT("%s%s%s",
(GET_U_1(message + 3) & 0x80) ? "/prefix": "",
(GET_U_1(message + 3) & 0x40) ? "/id" : "",
(GET_U_1(message + 3) & 0x3f) ? "/unknown" : "");
} else {
u_short interval, seqno, metric;
u_char ae, plen;
int rc;
u_char prefix[16];
ND_PRINT("\n\tUpdate");
if(len < 10) goto invalid;
ae = GET_U_1(message + 2);
plen = GET_U_1(message + 4) + (GET_U_1(message + 2) == 1 ? 96 : 0);
rc = network_prefix(ae,
GET_U_1(message + 4),
GET_U_1(message + 5),
message + 12,
GET_U_1(message + 2) == 1 ? v4_prefix : v6_prefix,
len - 10, prefix);
if(rc < 0) goto invalid;
interval = GET_BE_U_2(message + 6);
seqno = GET_BE_U_2(message + 8);
metric = GET_BE_U_2(message + 10);
ND_PRINT("%s%s%s %s metric %u seqno %u interval %s",
(GET_U_1(message + 3) & 0x80) ? "/prefix": "",
(GET_U_1(message + 3) & 0x40) ? "/id" : "",
(GET_U_1(message + 3) & 0x3f) ? "/unknown" : "",
ae == 0 ? "any" : format_prefix(ndo, prefix, plen),
metric, seqno, format_interval_update(interval));
if(GET_U_1(message + 3) & 0x80) {
if(GET_U_1(message + 2) == 1)
memcpy(v4_prefix, prefix, 16);
else
memcpy(v6_prefix, prefix, 16);
}
/* extra data? */
if((u_int)rc < len - 10)
subtlvs_print(ndo, message + 12 + rc, message + 2 + len, type);
}
}
break;
case MESSAGE_ROUTE_REQUEST: {
if (!ndo->ndo_vflag)
ND_PRINT(" route-request");
else {
int rc;
u_char prefix[16], ae, plen;
ND_PRINT("\n\tRoute Request ");
if(len < 2) goto invalid;
ae = GET_U_1(message + 2);
plen = GET_U_1(message + 3) + (GET_U_1(message + 2) == 1 ? 96 : 0);
rc = network_prefix(ae,
GET_U_1(message + 3), 0,
message + 4, NULL, len - 2, prefix);
if(rc < 0) goto invalid;
ND_PRINT("for %s",
ae == 0 ? "any" : format_prefix(ndo, prefix, plen));
}
}
break;
case MESSAGE_SEQNO_REQUEST : {
if (!ndo->ndo_vflag)
ND_PRINT(" seqno-request");
else {
int rc;
u_short seqno;
u_char prefix[16], ae, plen;
ND_PRINT("\n\tSeqno Request ");
if(len < 14) goto invalid;
ae = GET_U_1(message + 2);
seqno = GET_BE_U_2(message + 4);
rc = network_prefix(ae,
GET_U_1(message + 3), 0,
message + 16, NULL, len - 14, prefix);
if(rc < 0) goto invalid;
plen = GET_U_1(message + 3) + (GET_U_1(message + 2) == 1 ? 96 : 0);
ND_PRINT("(%u hops) for %s seqno %u id %s",
GET_U_1(message + 6),
ae == 0 ? "invalid AE 0" : format_prefix(ndo, prefix, plen),
seqno, format_id(ndo, message + 8));
}
}
break;
case MESSAGE_TSPC :
if (!ndo->ndo_vflag)
ND_PRINT(" tspc");
else {
ND_PRINT("\n\tTS/PC ");
if(len < 6) goto invalid;
ND_PRINT("timestamp %u packetcounter %u",
GET_BE_U_4(message + 4),
GET_BE_U_2(message + 2));
}
break;
case MESSAGE_HMAC : {
if (!ndo->ndo_vflag)
ND_PRINT(" hmac");
else {
unsigned j;
ND_PRINT("\n\tHMAC ");
if(len < 18) goto invalid;
ND_PRINT("key-id %u digest-%u ", GET_BE_U_2(message + 2),
len - 2);
for (j = 0; j < len - 2; j++)
ND_PRINT("%02X", GET_U_1(message + j + 4));
}
}
break;
case MESSAGE_UPDATE_SRC_SPECIFIC : {
if(!ndo->ndo_vflag) {
ND_PRINT(" ss-update");
} else {
u_char prefix[16], src_prefix[16];
u_short interval, seqno, metric;
u_char ae, plen, src_plen, omitted;
int rc;
int parsed_len = 10;
ND_PRINT("\n\tSS-Update");
if(len < 10) goto invalid;
ae = GET_U_1(message + 2);
src_plen = GET_U_1(message + 3);
plen = GET_U_1(message + 4);
omitted = GET_U_1(message + 5);
interval = GET_BE_U_2(message + 6);
seqno = GET_BE_U_2(message + 8);
metric = GET_BE_U_2(message + 10);
rc = network_prefix(ae, plen, omitted, message + 2 + parsed_len,
ae == 1 ? v4_prefix : v6_prefix,
len - parsed_len, prefix);
if(rc < 0) goto invalid;
if(ae == 1)
plen += 96;
parsed_len += rc;
rc = network_prefix(ae, src_plen, 0, message + 2 + parsed_len,
NULL, len - parsed_len, src_prefix);
if(rc < 0) goto invalid;
if(ae == 1)
src_plen += 96;
parsed_len += rc;
ND_PRINT(" %s from", format_prefix(ndo, prefix, plen));
ND_PRINT(" %s metric %u seqno %u interval %s",
format_prefix(ndo, src_prefix, src_plen),
metric, seqno, format_interval_update(interval));
/* extra data? */
if((u_int)parsed_len < len)
subtlvs_print(ndo, message + 2 + parsed_len,
message + 2 + len, type);
}
}
break;
case MESSAGE_REQUEST_SRC_SPECIFIC : {
if(!ndo->ndo_vflag)
ND_PRINT(" ss-request");
else {
int rc, parsed_len = 3;
u_char ae, plen, src_plen, prefix[16], src_prefix[16];
ND_PRINT("\n\tSS-Request ");
if(len < 3) goto invalid;
ae = GET_U_1(message + 2);
plen = GET_U_1(message + 3);
src_plen = GET_U_1(message + 4);
rc = network_prefix(ae, plen, 0, message + 2 + parsed_len,
NULL, len - parsed_len, prefix);
if(rc < 0) goto invalid;
if(ae == 1)
plen += 96;
parsed_len += rc;
rc = network_prefix(ae, src_plen, 0, message + 2 + parsed_len,
NULL, len - parsed_len, src_prefix);
if(rc < 0) goto invalid;
if(ae == 1)
src_plen += 96;
parsed_len += rc;
if(ae == 0) {
ND_PRINT("for any");
} else {
ND_PRINT("for (%s, ", format_prefix(ndo, prefix, plen));
ND_PRINT("%s)", format_prefix(ndo, src_prefix, src_plen));
}
}
}
break;
case MESSAGE_MH_REQUEST_SRC_SPECIFIC : {
if(!ndo->ndo_vflag)
ND_PRINT(" ss-mh-request");
else {
int rc, parsed_len = 14;
u_short seqno;
u_char ae, plen, src_plen, prefix[16], src_prefix[16], hopc;
const u_char *router_id = NULL;
ND_PRINT("\n\tSS-MH-Request ");
if(len < 14) goto invalid;
ae = GET_U_1(message + 2);
plen = GET_U_1(message + 3);
seqno = GET_BE_U_2(message + 4);
hopc = GET_U_1(message + 6);
src_plen = GET_U_1(message + 7);
router_id = message + 8;
rc = network_prefix(ae, plen, 0, message + 2 + parsed_len,
NULL, len - parsed_len, prefix);
if(rc < 0) goto invalid;
if(ae == 1)
plen += 96;
parsed_len += rc;
rc = network_prefix(ae, src_plen, 0, message + 2 + parsed_len,
NULL, len - parsed_len, src_prefix);
if(rc < 0) goto invalid;
if(ae == 1)
src_plen += 96;
ND_PRINT("(%u hops) for (%s, ",
hopc, format_prefix(ndo, prefix, plen));
ND_PRINT("%s) seqno %u id %s",
format_prefix(ndo, src_prefix, src_plen),
seqno, format_id(ndo, router_id));
}
}
break;
case MESSAGE_MAC: {
if (!ndo->ndo_vflag)
ND_PRINT(" mac");
else {
ND_PRINT("\n\tMAC ");
ND_PRINT("len %u", len);
}
}
break;
case MESSAGE_PC: {
if (!ndo->ndo_vflag)
ND_PRINT(" pc");
else {
ND_PRINT("\n\tPC");
if(len < 4) goto invalid;
ND_PRINT(" value %u",
GET_BE_U_4(message + 2));
ND_PRINT(" index len %u", len-4);
}
}
break;
case MESSAGE_CHALLENGE_REQUEST: {
if (!ndo->ndo_vflag)
ND_PRINT(" challenge_request");
else {
ND_PRINT("\n\tChallenge Request");
if(len > 192) goto invalid;
ND_PRINT(" len %u", len);
}
}
break;
case MESSAGE_CHALLENGE_REPLY: {
if (!ndo->ndo_vflag)
ND_PRINT(" challenge_reply");
else {
ND_PRINT("\n\tChallenge Reply");
if (len > 192) goto invalid;
ND_PRINT(" len %u", len);
}
}
break;
default:
if (!ndo->ndo_vflag)
ND_PRINT(" unknown");
else
ND_PRINT("\n\tUnknown message type %u", type);
}
i += len + 2;
}
return 0; /* OK */
trunc:
return -1; /* packet truncated by capture process */
invalid:
return -2; /* packet is invalid */
}
static void
babel_print_v2(netdissect_options *ndo,
const u_char *cp, u_int length)
{
u_short bodylen;
int ret;
ND_TCHECK_4(cp);
if (length < 4)
goto invalid;
bodylen = GET_BE_U_2(cp + 2);
ND_PRINT(" (%u)", bodylen);
length -= 4;
cp += 4;
/* Process the TLVs in the body */
if (length < bodylen)
goto invalid;
ret = babel_print_v2_tlvs(ndo, cp, bodylen, length);
if (ret == -1)
goto trunc;
if (ret == -2)
goto invalid;
length -= bodylen;
cp += bodylen;
/* If there's a trailer, process the TLVs in the trailer */
if (length != 0) {
if(ndo->ndo_vflag) ND_PRINT("\n\t----");
else ND_PRINT(" |");
ret = babel_print_v2_tlvs(ndo, cp, length, length);
if (ret == -1)
goto trunc;
if (ret == -2)
goto invalid;
}
return;
trunc:
nd_print_trunc(ndo);
return;
invalid:
nd_print_invalid(ndo);
}
diff --git a/contrib/tcpdump/print-bcm-li.c b/contrib/tcpdump/print-bcm-li.c
index 12b1ebbe20cc..5ecb9ff94cad 100644
--- a/contrib/tcpdump/print-bcm-li.c
+++ b/contrib/tcpdump/print-bcm-li.c
@@ -1,130 +1,128 @@
/*
* 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.
*/
/* \summary: Broadcom LI Printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#define BCM_LI_SHIM_LEN 4
static const struct tok bcm_li_direction_values[] = {
{ 1, "unused" },
{ 2, "egress" },
{ 3, "ingress" },
{ 0, NULL}
};
#define BCM_LI_PKT_TYPE_UNDECIDED 4
#define BCM_LI_PKT_TYPE_IPV4 5
#define BCM_LI_PKT_TYPE_IPV6 6
#define BCM_LI_PKT_TYPE_ETHERNET 7
static const struct tok bcm_li_pkt_type_values[] = {
{ BCM_LI_PKT_TYPE_UNDECIDED, "undecided" },
{ BCM_LI_PKT_TYPE_IPV4, "ipv4" },
{ BCM_LI_PKT_TYPE_IPV6, "ipv6" },
{ BCM_LI_PKT_TYPE_ETHERNET, "ethernet" },
{ 0, NULL}
};
static const struct tok bcm_li_pkt_subtype_values[] = {
{ 1, "single VLAN tag" },
{ 2, "double VLAN tag" },
{ 3, "untagged" },
{ 0, NULL}
};
void
bcm_li_print(netdissect_options *ndo,
const u_char *bp, u_int length)
{
u_int shim, direction, pkt_type, pkt_subtype, li_id;
ndo->ndo_protocol = "bcm_li";
if (length < BCM_LI_SHIM_LEN) {
ND_PRINT(" (length %u < %u)", length, BCM_LI_SHIM_LEN);
goto invalid;
}
shim = GET_BE_U_4(bp);
direction = (shim >> 29) & 0x7;
pkt_type = (shim >> 25) & 0xf;
pkt_subtype = (shim >> 22) & 0x7;
li_id = shim & 0x3fffff;
length -= BCM_LI_SHIM_LEN;
bp += BCM_LI_SHIM_LEN;
ND_PRINT("%sBCM-LI-SHIM: direction %s, pkt-type %s, pkt-subtype %s, li-id %u%s",
ndo->ndo_vflag ? "\n " : "",
tok2str(bcm_li_direction_values, "unknown", direction),
tok2str(bcm_li_pkt_type_values, "unknown", pkt_type),
tok2str(bcm_li_pkt_subtype_values, "unknown", pkt_subtype),
li_id,
ndo->ndo_vflag ? "\n ": "");
if (!ndo->ndo_vflag) {
ND_TCHECK_LEN(bp, length);
return;
}
switch (pkt_type) {
case BCM_LI_PKT_TYPE_ETHERNET:
ether_print(ndo, bp, length, ND_BYTES_AVAILABLE_AFTER(bp), NULL, NULL);
break;
case BCM_LI_PKT_TYPE_IPV4:
ip_print(ndo, bp, length);
break;
case BCM_LI_PKT_TYPE_IPV6:
ip6_print(ndo, bp, length);
break;
case BCM_LI_PKT_TYPE_UNDECIDED:
/*
* Guess IP version from first nibble.
*/
if ((GET_U_1(bp) >> 4) == 4) {
ip_print(ndo, bp, length);
} else if ((GET_U_1(bp) >> 4) == 6) {
ip6_print(ndo, bp, length);
} else {
ND_PRINT("unknown payload");
}
break;
default:
goto invalid;
}
return;
invalid:
nd_print_invalid(ndo);
}
diff --git a/contrib/tcpdump/print-beep.c b/contrib/tcpdump/print-beep.c
index 76017eaf89dc..ec5b2f19e257 100644
--- a/contrib/tcpdump/print-beep.c
+++ b/contrib/tcpdump/print-beep.c
@@ -1,69 +1,67 @@
/*
* Copyright (C) 2000, Richard Sharpe
*
* This software may be distributed either under the terms of the
* BSD-style license that accompanies tcpdump or under the GNU GPL
* version 2 or later.
*
* print-beep.c
*
*/
/* \summary: Blocks Extensible Exchange Protocol (BEEP) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <string.h>
#include "netdissect.h"
/* Check for a string but not go beyond length
* Return TRUE on match, FALSE otherwise
*
* Looks at the first few chars up to tl1 ...
*/
static int
l_strnstart(netdissect_options *ndo, const char *tstr1, u_int tl1,
const char *str2, u_int l2)
{
if (!ND_TTEST_LEN(str2, tl1)) {
/*
* We don't have tl1 bytes worth of captured data
* for the string, so we can't check for this
* string.
*/
return 0;
}
if (tl1 > l2)
return 0;
return (strncmp(tstr1, str2, tl1) == 0 ? 1 : 0);
}
void
beep_print(netdissect_options *ndo, const u_char *bp, u_int length)
{
ndo->ndo_protocol = "beep";
if (l_strnstart(ndo, "MSG", 4, (const char *)bp, length)) /* A REQuest */
ND_PRINT(" BEEP MSG");
else if (l_strnstart(ndo, "RPY ", 4, (const char *)bp, length))
ND_PRINT(" BEEP RPY");
else if (l_strnstart(ndo, "ERR ", 4, (const char *)bp, length))
ND_PRINT(" BEEP ERR");
else if (l_strnstart(ndo, "ANS ", 4, (const char *)bp, length))
ND_PRINT(" BEEP ANS");
else if (l_strnstart(ndo, "NUL ", 4, (const char *)bp, length))
ND_PRINT(" BEEP NUL");
else if (l_strnstart(ndo, "SEQ ", 4, (const char *)bp, length))
ND_PRINT(" BEEP SEQ");
else if (l_strnstart(ndo, "END", 4, (const char *)bp, length))
ND_PRINT(" BEEP END");
else
ND_PRINT(" BEEP (payload or undecoded)");
}
diff --git a/contrib/tcpdump/print-bfd.c b/contrib/tcpdump/print-bfd.c
index 8c047357db3e..a7c9a5621c77 100644
--- a/contrib/tcpdump/print-bfd.c
+++ b/contrib/tcpdump/print-bfd.c
@@ -1,426 +1,422 @@
/*
* 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.
*
* Original code by Hannes Gredler (hannes@gredler.at)
*/
/* \summary: Bidirectional Forwarding Detection (BFD) printer */
/*
* specification: draft-ietf-bfd-base-01 for version 0,
* RFC 5880 for version 1, and RFC 5881
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
#include "udp.h"
/*
* Control packet, BFDv0, draft-ietf-bfd-base-01
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |Vers | Diag |H|D|P|F|C|A|Rsv| Detect Mult | Length |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | My Discriminator |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Your Discriminator |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Desired Min TX Interval |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Required Min RX Interval |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Required Min Echo RX Interval |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/*
* Control packet, BFDv1, RFC 5880
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |Vers | Diag |Sta|P|F|C|A|D|M| Detect Mult | Length |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | My Discriminator |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Your Discriminator |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Desired Min TX Interval |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Required Min RX Interval |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Required Min Echo RX Interval |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct bfd_header_t {
nd_uint8_t version_diag;
nd_uint8_t flags;
nd_uint8_t detect_time_multiplier;
nd_uint8_t length;
nd_uint32_t my_discriminator;
nd_uint32_t your_discriminator;
nd_uint32_t desired_min_tx_interval;
nd_uint32_t required_min_rx_interval;
nd_uint32_t required_min_echo_interval;
};
/*
* An optional Authentication Header may be present
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Auth Type | Auth Len | Authentication Data... |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct bfd_auth_header_t {
nd_uint8_t auth_type;
nd_uint8_t auth_len;
nd_uint8_t auth_data;
nd_uint8_t dummy; /* minimum 4 bytes */
};
enum auth_type {
AUTH_PASSWORD = 1,
AUTH_MD5 = 2,
AUTH_MET_MD5 = 3,
AUTH_SHA1 = 4,
AUTH_MET_SHA1 = 5
};
static const struct tok bfd_v1_authentication_values[] = {
{ AUTH_PASSWORD, "Simple Password" },
{ AUTH_MD5, "Keyed MD5" },
{ AUTH_MET_MD5, "Meticulous Keyed MD5" },
{ AUTH_SHA1, "Keyed SHA1" },
{ AUTH_MET_SHA1, "Meticulous Keyed SHA1" },
{ 0, NULL }
};
enum auth_length {
AUTH_PASSWORD_FIELD_MIN_LEN = 4, /* header + password min: 3 + 1 */
AUTH_PASSWORD_FIELD_MAX_LEN = 19, /* header + password max: 3 + 16 */
AUTH_MD5_FIELD_LEN = 24,
AUTH_MD5_HASH_LEN = 16,
AUTH_SHA1_FIELD_LEN = 28,
AUTH_SHA1_HASH_LEN = 20
};
#define BFD_EXTRACT_VERSION(x) (((x)&0xe0)>>5)
#define BFD_EXTRACT_DIAG(x) ((x)&0x1f)
static const struct tok bfd_diag_values[] = {
{ 0, "No Diagnostic" },
{ 1, "Control Detection Time Expired" },
{ 2, "Echo Function Failed" },
{ 3, "Neighbor Signaled Session Down" },
{ 4, "Forwarding Plane Reset" },
{ 5, "Path Down" },
{ 6, "Concatenated Path Down" },
{ 7, "Administratively Down" },
{ 8, "Reverse Concatenated Path Down" },
{ 0, NULL }
};
static const struct tok bfd_port_values[] = {
{ BFD_CONTROL_PORT, "Control" },
{ BFD_MULTIHOP_PORT, "Multihop" },
{ BFD_LAG_PORT, "Lag" },
{ 0, NULL }
};
#define BFD_FLAG_AUTH 0x04
static const struct tok bfd_v0_flag_values[] = {
{ 0x80, "I Hear You" },
{ 0x40, "Demand" },
{ 0x20, "Poll" },
{ 0x10, "Final" },
{ 0x08, "Control Plane Independent" },
{ BFD_FLAG_AUTH, "Authentication Present" },
{ 0x02, "Reserved" },
{ 0x01, "Reserved" },
{ 0, NULL }
};
static const struct tok bfd_v1_flag_values[] = {
{ 0x20, "Poll" },
{ 0x10, "Final" },
{ 0x08, "Control Plane Independent" },
{ BFD_FLAG_AUTH, "Authentication Present" },
{ 0x02, "Demand" },
{ 0x01, "Multipoint" },
{ 0, NULL }
};
static const struct tok bfd_v1_state_values[] = {
{ 0, "AdminDown" },
{ 1, "Down" },
{ 2, "Init" },
{ 3, "Up" },
{ 0, NULL }
};
static void
auth_print(netdissect_options *ndo, const u_char *pptr)
{
const struct bfd_auth_header_t *bfd_auth_header;
uint8_t auth_type, auth_len;
int i;
pptr += sizeof (struct bfd_header_t);
bfd_auth_header = (const struct bfd_auth_header_t *)pptr;
ND_TCHECK_SIZE(bfd_auth_header);
auth_type = GET_U_1(bfd_auth_header->auth_type);
auth_len = GET_U_1(bfd_auth_header->auth_len);
ND_PRINT("\n\tAuthentication: %s (%u), length: %u",
tok2str(bfd_v1_authentication_values,"Unknown",auth_type),
auth_type, auth_len);
pptr += 2;
ND_PRINT("\n\t Auth Key ID: %u", GET_U_1(pptr));
switch(auth_type) {
case AUTH_PASSWORD:
/*
* Simple Password Authentication Section Format
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Auth Type | Auth Len | Auth Key ID | Password... |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | ... |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
if (auth_len < AUTH_PASSWORD_FIELD_MIN_LEN ||
auth_len > AUTH_PASSWORD_FIELD_MAX_LEN) {
ND_PRINT("[invalid length %u]",
auth_len);
break;
}
pptr++;
ND_PRINT(", Password: ");
/* the length is equal to the password length plus three */
(void)nd_printn(ndo, pptr, auth_len - 3, NULL);
break;
case AUTH_MD5:
case AUTH_MET_MD5:
/*
* Keyed MD5 and Meticulous Keyed MD5 Authentication Section Format
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Auth Type | Auth Len | Auth Key ID | Reserved |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Sequence Number |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Auth Key/Digest... |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | ... |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
if (auth_len != AUTH_MD5_FIELD_LEN) {
ND_PRINT("[invalid length %u]",
auth_len);
break;
}
pptr += 2;
ND_PRINT(", Sequence Number: 0x%08x", GET_BE_U_4(pptr));
pptr += 4;
ND_TCHECK_LEN(pptr, AUTH_MD5_HASH_LEN);
ND_PRINT("\n\t Digest: ");
for(i = 0; i < AUTH_MD5_HASH_LEN; i++)
ND_PRINT("%02x", GET_U_1(pptr + i));
break;
case AUTH_SHA1:
case AUTH_MET_SHA1:
/*
* Keyed SHA1 and Meticulous Keyed SHA1 Authentication Section Format
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Auth Type | Auth Len | Auth Key ID | Reserved |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Sequence Number |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Auth Key/Hash... |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | ... |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
if (auth_len != AUTH_SHA1_FIELD_LEN) {
ND_PRINT("[invalid length %u]",
auth_len);
break;
}
pptr += 2;
ND_PRINT(", Sequence Number: 0x%08x", GET_BE_U_4(pptr));
pptr += 4;
ND_TCHECK_LEN(pptr, AUTH_SHA1_HASH_LEN);
ND_PRINT("\n\t Hash: ");
for(i = 0; i < AUTH_SHA1_HASH_LEN; i++)
ND_PRINT("%02x", GET_U_1(pptr + i));
break;
}
}
void
bfd_print(netdissect_options *ndo, const u_char *pptr,
u_int len, u_int port)
{
ndo->ndo_protocol = "bfd";
if (port == BFD_CONTROL_PORT ||
port == BFD_MULTIHOP_PORT ||
port == BFD_LAG_PORT) {
/*
* Control packet.
*/
const struct bfd_header_t *bfd_header;
uint8_t version_diag;
uint8_t version = 0;
uint8_t flags;
bfd_header = (const struct bfd_header_t *)pptr;
ND_TCHECK_SIZE(bfd_header);
version_diag = GET_U_1(bfd_header->version_diag);
version = BFD_EXTRACT_VERSION(version_diag);
flags = GET_U_1(bfd_header->flags);
switch (version) {
/* BFDv0 */
case 0:
- if (ndo->ndo_vflag < 1)
- {
+ if (ndo->ndo_vflag < 1) {
ND_PRINT("BFDv0, Control, Flags: [%s], length: %u",
bittok2str(bfd_v0_flag_values, "none", flags),
len);
return;
}
ND_PRINT("BFDv0, length: %u\n\tControl, Flags: [%s], Diagnostic: %s (0x%02x)",
len,
bittok2str(bfd_v0_flag_values, "none", flags),
tok2str(bfd_diag_values,"unknown",BFD_EXTRACT_DIAG(version_diag)),
BFD_EXTRACT_DIAG(version_diag));
ND_PRINT("\n\tDetection Timer Multiplier: %u (%u ms Detection time), BFD Length: %u",
GET_U_1(bfd_header->detect_time_multiplier),
GET_U_1(bfd_header->detect_time_multiplier) * GET_BE_U_4(bfd_header->desired_min_tx_interval)/1000,
GET_U_1(bfd_header->length));
ND_PRINT("\n\tMy Discriminator: 0x%08x",
GET_BE_U_4(bfd_header->my_discriminator));
ND_PRINT(", Your Discriminator: 0x%08x",
GET_BE_U_4(bfd_header->your_discriminator));
ND_PRINT("\n\t Desired min Tx Interval: %4u ms",
GET_BE_U_4(bfd_header->desired_min_tx_interval)/1000);
ND_PRINT("\n\t Required min Rx Interval: %4u ms",
GET_BE_U_4(bfd_header->required_min_rx_interval)/1000);
ND_PRINT("\n\t Required min Echo Interval: %4u ms",
GET_BE_U_4(bfd_header->required_min_echo_interval)/1000);
if (flags & BFD_FLAG_AUTH) {
auth_print(ndo, pptr);
}
break;
/* BFDv1 */
case 1:
- if (ndo->ndo_vflag < 1)
- {
+ if (ndo->ndo_vflag < 1) {
ND_PRINT("BFDv1, %s, State %s, Flags: [%s], length: %u",
tok2str(bfd_port_values, "unknown (%u)", port),
tok2str(bfd_v1_state_values, "unknown (%u)", (flags & 0xc0) >> 6),
bittok2str(bfd_v1_flag_values, "none", flags & 0x3f),
len);
return;
}
ND_PRINT("BFDv1, length: %u\n\t%s, State %s, Flags: [%s], Diagnostic: %s (0x%02x)",
len,
tok2str(bfd_port_values, "unknown (%u)", port),
tok2str(bfd_v1_state_values, "unknown (%u)", (flags & 0xc0) >> 6),
bittok2str(bfd_v1_flag_values, "none", flags & 0x3f),
tok2str(bfd_diag_values,"unknown",BFD_EXTRACT_DIAG(version_diag)),
BFD_EXTRACT_DIAG(version_diag));
ND_PRINT("\n\tDetection Timer Multiplier: %u (%u ms Detection time), BFD Length: %u",
GET_U_1(bfd_header->detect_time_multiplier),
GET_U_1(bfd_header->detect_time_multiplier) * GET_BE_U_4(bfd_header->desired_min_tx_interval)/1000,
GET_U_1(bfd_header->length));
ND_PRINT("\n\tMy Discriminator: 0x%08x",
GET_BE_U_4(bfd_header->my_discriminator));
ND_PRINT(", Your Discriminator: 0x%08x",
GET_BE_U_4(bfd_header->your_discriminator));
ND_PRINT("\n\t Desired min Tx Interval: %4u ms",
GET_BE_U_4(bfd_header->desired_min_tx_interval)/1000);
ND_PRINT("\n\t Required min Rx Interval: %4u ms",
GET_BE_U_4(bfd_header->required_min_rx_interval)/1000);
ND_PRINT("\n\t Required min Echo Interval: %4u ms",
GET_BE_U_4(bfd_header->required_min_echo_interval)/1000);
if (flags & BFD_FLAG_AUTH) {
auth_print(ndo, pptr);
}
break;
default:
ND_PRINT("BFDv%u, Control, length: %u",
version,
len);
if (ndo->ndo_vflag >= 1) {
if(!print_unknown_data(ndo, pptr,"\n\t",len))
return;
}
break;
}
} else if (port == BFD_ECHO_PORT) {
/*
* Echo packet.
*/
ND_PRINT("BFD, Echo, length: %u",
len);
if (ndo->ndo_vflag >= 1) {
if(!print_unknown_data(ndo, pptr,"\n\t",len))
return;
}
} else {
/*
* Unknown packet type.
*/
ND_PRINT("BFD, unknown (%u), length: %u",
port,
len);
if (ndo->ndo_vflag >= 1) {
if(!print_unknown_data(ndo, pptr,"\n\t",len))
return;
}
}
}
diff --git a/contrib/tcpdump/print-bgp.c b/contrib/tcpdump/print-bgp.c
index efeaea45f3b0..ed112506d4de 100644
--- a/contrib/tcpdump/print-bgp.c
+++ b/contrib/tcpdump/print-bgp.c
@@ -1,3162 +1,3165 @@
/*
* Copyright (C) 1999 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* Extensively modified by Hannes Gredler (hannes@gredler.at) for more
* complete BGP support.
*/
/* \summary: Border Gateway Protocol (BGP) printer */
/* specification: RFC 4271 */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <stdio.h>
#include <string.h>
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#include "af.h"
#include "l2vpn.h"
struct bgp {
nd_byte bgp_marker[16];
nd_uint16_t bgp_len;
nd_uint8_t bgp_type;
};
#define BGP_SIZE 19 /* unaligned */
#define BGP_OPEN 1
#define BGP_UPDATE 2
#define BGP_NOTIFICATION 3
#define BGP_KEEPALIVE 4
#define BGP_ROUTE_REFRESH 5
static const struct tok bgp_msg_values[] = {
{ BGP_OPEN, "Open"},
{ BGP_UPDATE, "Update"},
{ BGP_NOTIFICATION, "Notification"},
{ BGP_KEEPALIVE, "Keepalive"},
{ BGP_ROUTE_REFRESH, "Route Refresh"},
{ 0, NULL}
};
struct bgp_open {
nd_byte bgpo_marker[16];
nd_uint16_t bgpo_len;
nd_uint8_t bgpo_type;
nd_uint8_t bgpo_version;
nd_uint16_t bgpo_myas;
nd_uint16_t bgpo_holdtime;
nd_uint32_t bgpo_id;
nd_uint8_t bgpo_optlen;
/* options should follow */
};
#define BGP_OPEN_SIZE 29 /* unaligned */
struct bgp_opt {
nd_uint8_t bgpopt_type;
nd_uint8_t bgpopt_len;
/* variable length */
};
#define BGP_OPT_SIZE 2 /* some compilers may pad to 4 bytes */
#define BGP_CAP_HEADER_SIZE 2 /* some compilers may pad to 4 bytes */
struct bgp_notification {
nd_byte bgpn_marker[16];
nd_uint16_t bgpn_len;
nd_uint8_t bgpn_type;
nd_uint8_t bgpn_major;
nd_uint8_t bgpn_minor;
};
#define BGP_NOTIFICATION_SIZE 21 /* unaligned */
struct bgp_route_refresh {
nd_byte bgp_marker[16];
nd_uint16_t len;
nd_uint8_t type; /* No padding after this; afi is, in fact, not aligned */
nd_uint16_t afi;
nd_uint8_t res;
nd_uint8_t safi;
};
#define BGP_ROUTE_REFRESH_SIZE 23
#define bgp_attr_lenlen(flags, p) \
(((flags) & 0x10) ? 2U : 1U)
#define bgp_attr_len(flags, p) \
(((flags) & 0x10) ? GET_BE_U_2(p) : GET_U_1(p))
#define BGPTYPE_ORIGIN 1
#define BGPTYPE_AS_PATH 2
#define BGPTYPE_NEXT_HOP 3
#define BGPTYPE_MULTI_EXIT_DISC 4
#define BGPTYPE_LOCAL_PREF 5
#define BGPTYPE_ATOMIC_AGGREGATE 6
#define BGPTYPE_AGGREGATOR 7
#define BGPTYPE_COMMUNITIES 8 /* RFC1997 */
#define BGPTYPE_ORIGINATOR_ID 9 /* RFC4456 */
#define BGPTYPE_CLUSTER_LIST 10 /* RFC4456 */
#define BGPTYPE_DPA 11 /* deprecated, draft-ietf-idr-bgp-dpa */
#define BGPTYPE_ADVERTISERS 12 /* deprecated RFC1863 */
#define BGPTYPE_RCID_PATH 13 /* deprecated RFC1863 */
#define BGPTYPE_MP_REACH_NLRI 14 /* RFC4760 */
#define BGPTYPE_MP_UNREACH_NLRI 15 /* RFC4760 */
#define BGPTYPE_EXTD_COMMUNITIES 16 /* RFC4360 */
#define BGPTYPE_AS4_PATH 17 /* RFC6793 */
#define BGPTYPE_AGGREGATOR4 18 /* RFC6793 */
#define BGPTYPE_PMSI_TUNNEL 22 /* RFC6514 */
#define BGPTYPE_TUNNEL_ENCAP 23 /* RFC5512 */
#define BGPTYPE_TRAFFIC_ENG 24 /* RFC5543 */
#define BGPTYPE_IPV6_EXTD_COMMUNITIES 25 /* RFC5701 */
#define BGPTYPE_AIGP 26 /* RFC7311 */
#define BGPTYPE_PE_DISTINGUISHER_LABEL 27 /* RFC6514 */
#define BGPTYPE_ENTROPY_LABEL 28 /* RFC6790 */
#define BGPTYPE_LARGE_COMMUNITY 32 /* draft-ietf-idr-large-community-05 */
#define BGPTYPE_ATTR_SET 128 /* RFC6368 */
#define BGP_MP_NLRI_MINSIZE 3 /* End of RIB Marker detection */
static const struct tok bgp_attr_values[] = {
{ BGPTYPE_ORIGIN, "Origin"},
{ BGPTYPE_AS_PATH, "AS Path"},
{ BGPTYPE_AS4_PATH, "AS4 Path"},
{ BGPTYPE_NEXT_HOP, "Next Hop"},
{ BGPTYPE_MULTI_EXIT_DISC, "Multi Exit Discriminator"},
{ BGPTYPE_LOCAL_PREF, "Local Preference"},
{ BGPTYPE_ATOMIC_AGGREGATE, "Atomic Aggregate"},
{ BGPTYPE_AGGREGATOR, "Aggregator"},
{ BGPTYPE_AGGREGATOR4, "Aggregator4"},
{ BGPTYPE_COMMUNITIES, "Community"},
{ BGPTYPE_ORIGINATOR_ID, "Originator ID"},
{ BGPTYPE_CLUSTER_LIST, "Cluster List"},
{ BGPTYPE_DPA, "DPA"},
{ BGPTYPE_ADVERTISERS, "Advertisers"},
{ BGPTYPE_RCID_PATH, "RCID Path / Cluster ID"},
{ BGPTYPE_MP_REACH_NLRI, "Multi-Protocol Reach NLRI"},
{ BGPTYPE_MP_UNREACH_NLRI, "Multi-Protocol Unreach NLRI"},
{ BGPTYPE_EXTD_COMMUNITIES, "Extended Community"},
{ BGPTYPE_PMSI_TUNNEL, "PMSI Tunnel"},
{ BGPTYPE_TUNNEL_ENCAP, "Tunnel Encapsulation"},
{ BGPTYPE_TRAFFIC_ENG, "Traffic Engineering"},
{ BGPTYPE_IPV6_EXTD_COMMUNITIES, "IPv6 Extended Community"},
{ BGPTYPE_AIGP, "Accumulated IGP Metric"},
{ BGPTYPE_PE_DISTINGUISHER_LABEL, "PE Distinguisher Label"},
{ BGPTYPE_ENTROPY_LABEL, "Entropy Label"},
{ BGPTYPE_LARGE_COMMUNITY, "Large Community"},
{ BGPTYPE_ATTR_SET, "Attribute Set"},
{ 255, "Reserved for development"},
{ 0, NULL}
};
#define BGP_AS_SET 1
#define BGP_AS_SEQUENCE 2
#define BGP_CONFED_AS_SEQUENCE 3 /* draft-ietf-idr-rfc3065bis-01 */
#define BGP_CONFED_AS_SET 4 /* draft-ietf-idr-rfc3065bis-01 */
#define BGP_AS_SEG_TYPE_MIN BGP_AS_SET
#define BGP_AS_SEG_TYPE_MAX BGP_CONFED_AS_SET
static const struct tok bgp_as_path_segment_open_values[] = {
{ BGP_AS_SEQUENCE, ""},
{ BGP_AS_SET, "{ "},
{ BGP_CONFED_AS_SEQUENCE, "( "},
{ BGP_CONFED_AS_SET, "({ "},
{ 0, NULL}
};
static const struct tok bgp_as_path_segment_close_values[] = {
{ BGP_AS_SEQUENCE, ""},
{ BGP_AS_SET, "}"},
{ BGP_CONFED_AS_SEQUENCE, ")"},
{ BGP_CONFED_AS_SET, "})"},
{ 0, NULL}
};
#define BGP_OPT_AUTH 1
#define BGP_OPT_CAP 2
static const struct tok bgp_opt_values[] = {
{ BGP_OPT_AUTH, "Authentication Information"},
{ BGP_OPT_CAP, "Capabilities Advertisement"},
{ 0, NULL}
};
#define BGP_CAPCODE_MP 1 /* RFC2858 */
#define BGP_CAPCODE_RR 2 /* RFC2918 */
#define BGP_CAPCODE_ORF 3 /* RFC5291 */
#define BGP_CAPCODE_MR 4 /* RFC3107 */
#define BGP_CAPCODE_EXT_NH 5 /* RFC5549 */
#define BGP_CAPCODE_ML 8 /* RFC8277 */
#define BGP_CAPCODE_RESTART 64 /* RFC4724 */
#define BGP_CAPCODE_AS_NEW 65 /* RFC6793 */
#define BGP_CAPCODE_DYN_CAP 67 /* draft-ietf-idr-dynamic-cap */
#define BGP_CAPCODE_MULTISESS 68 /* draft-ietf-idr-bgp-multisession */
#define BGP_CAPCODE_ADD_PATH 69 /* RFC7911 */
#define BGP_CAPCODE_ENH_RR 70 /* draft-keyur-bgp-enhanced-route-refresh */
#define BGP_CAPCODE_LLGR 71 /* draft-uttaro-idr-bgp-persistence-05 */
#define BGP_CAPCODE_RR_CISCO 128
static const struct tok bgp_capcode_values[] = {
{ BGP_CAPCODE_MP, "Multiprotocol Extensions"},
{ BGP_CAPCODE_RR, "Route Refresh"},
{ BGP_CAPCODE_ORF, "Cooperative Route Filtering"},
{ BGP_CAPCODE_MR, "Multiple Routes to a Destination"},
{ BGP_CAPCODE_EXT_NH, "Extended Next Hop Encoding"},
{ BGP_CAPCODE_ML, "Multiple Labels"},
{ BGP_CAPCODE_RESTART, "Graceful Restart"},
{ BGP_CAPCODE_AS_NEW, "32-Bit AS Number"},
{ BGP_CAPCODE_DYN_CAP, "Dynamic Capability"},
{ BGP_CAPCODE_MULTISESS, "Multisession BGP"},
{ BGP_CAPCODE_ADD_PATH, "Multiple Paths"},
{ BGP_CAPCODE_ENH_RR, "Enhanced Route Refresh"},
{ BGP_CAPCODE_LLGR, "Long-lived Graceful Restart"},
{ BGP_CAPCODE_RR_CISCO, "Route Refresh (Cisco)"},
{ 0, NULL}
};
#define BGP_NOTIFY_MAJOR_MSG 1
#define BGP_NOTIFY_MAJOR_OPEN 2
#define BGP_NOTIFY_MAJOR_UPDATE 3
#define BGP_NOTIFY_MAJOR_HOLDTIME 4
#define BGP_NOTIFY_MAJOR_FSM 5
#define BGP_NOTIFY_MAJOR_CEASE 6
#define BGP_NOTIFY_MAJOR_CAP 7
static const struct tok bgp_notify_major_values[] = {
{ BGP_NOTIFY_MAJOR_MSG, "Message Header Error"},
{ BGP_NOTIFY_MAJOR_OPEN, "OPEN Message Error"},
{ BGP_NOTIFY_MAJOR_UPDATE, "UPDATE Message Error"},
{ BGP_NOTIFY_MAJOR_HOLDTIME,"Hold Timer Expired"},
{ BGP_NOTIFY_MAJOR_FSM, "Finite State Machine Error"},
{ BGP_NOTIFY_MAJOR_CEASE, "Cease"},
{ BGP_NOTIFY_MAJOR_CAP, "Capability Message Error"},
{ 0, NULL}
};
/* RFC 4486 */
#define BGP_NOTIFY_MINOR_CEASE_MAXPRFX 1
#define BGP_NOTIFY_MINOR_CEASE_SHUT 2
#define BGP_NOTIFY_MINOR_CEASE_RESET 4
static const struct tok bgp_notify_minor_cease_values[] = {
{ BGP_NOTIFY_MINOR_CEASE_MAXPRFX, "Maximum Number of Prefixes Reached"},
{ BGP_NOTIFY_MINOR_CEASE_SHUT, "Administrative Shutdown"},
{ 3, "Peer Unconfigured"},
{ BGP_NOTIFY_MINOR_CEASE_RESET, "Administrative Reset"},
{ 5, "Connection Rejected"},
{ 6, "Other Configuration Change"},
{ 7, "Connection Collision Resolution"},
{ 0, NULL}
};
static const struct tok bgp_notify_minor_msg_values[] = {
{ 1, "Connection Not Synchronized"},
{ 2, "Bad Message Length"},
{ 3, "Bad Message Type"},
{ 0, NULL}
};
static const struct tok bgp_notify_minor_open_values[] = {
{ 1, "Unsupported Version Number"},
{ 2, "Bad Peer AS"},
{ 3, "Bad BGP Identifier"},
{ 4, "Unsupported Optional Parameter"},
{ 5, "Authentication Failure"},
{ 6, "Unacceptable Hold Time"},
{ 7, "Capability Message Error"},
{ 0, NULL}
};
static const struct tok bgp_notify_minor_update_values[] = {
{ 1, "Malformed Attribute List"},
{ 2, "Unrecognized Well-known Attribute"},
{ 3, "Missing Well-known Attribute"},
{ 4, "Attribute Flags Error"},
{ 5, "Attribute Length Error"},
{ 6, "Invalid ORIGIN Attribute"},
{ 7, "AS Routing Loop"},
{ 8, "Invalid NEXT_HOP Attribute"},
{ 9, "Optional Attribute Error"},
{ 10, "Invalid Network Field"},
{ 11, "Malformed AS_PATH"},
{ 0, NULL}
};
static const struct tok bgp_notify_minor_fsm_values[] = {
{ 0, "Unspecified Error"},
{ 1, "In OpenSent State"},
{ 2, "In OpenConfirm State"},
{ 3, "In Established State"},
{ 0, NULL }
};
static const struct tok bgp_notify_minor_cap_values[] = {
{ 1, "Invalid Action Value" },
{ 2, "Invalid Capability Length" },
{ 3, "Malformed Capability Value" },
{ 4, "Unsupported Capability Code" },
{ 0, NULL }
};
static const struct tok bgp_origin_values[] = {
{ 0, "IGP"},
{ 1, "EGP"},
{ 2, "Incomplete"},
{ 0, NULL}
};
#define BGP_PMSI_TUNNEL_RSVP_P2MP 1
#define BGP_PMSI_TUNNEL_LDP_P2MP 2
#define BGP_PMSI_TUNNEL_PIM_SSM 3
#define BGP_PMSI_TUNNEL_PIM_SM 4
#define BGP_PMSI_TUNNEL_PIM_BIDIR 5
#define BGP_PMSI_TUNNEL_INGRESS 6
#define BGP_PMSI_TUNNEL_LDP_MP2MP 7
static const struct tok bgp_pmsi_tunnel_values[] = {
{ BGP_PMSI_TUNNEL_RSVP_P2MP, "RSVP-TE P2MP LSP"},
{ BGP_PMSI_TUNNEL_LDP_P2MP, "LDP P2MP LSP"},
{ BGP_PMSI_TUNNEL_PIM_SSM, "PIM-SSM Tree"},
{ BGP_PMSI_TUNNEL_PIM_SM, "PIM-SM Tree"},
{ BGP_PMSI_TUNNEL_PIM_BIDIR, "PIM-Bidir Tree"},
{ BGP_PMSI_TUNNEL_INGRESS, "Ingress Replication"},
{ BGP_PMSI_TUNNEL_LDP_MP2MP, "LDP MP2MP LSP"},
{ 0, NULL}
};
static const struct tok bgp_pmsi_flag_values[] = {
{ 0x01, "Leaf Information required"},
{ 0, NULL}
};
#define BGP_AIGP_TLV 1
static const struct tok bgp_aigp_values[] = {
{ BGP_AIGP_TLV, "AIGP"},
{ 0, NULL}
};
/* Subsequent address family identifier, RFC2283 section 7 */
#define SAFNUM_RES 0
#define SAFNUM_UNICAST 1
#define SAFNUM_MULTICAST 2
#define SAFNUM_UNIMULTICAST 3 /* deprecated now */
/* labeled BGP RFC3107 */
#define SAFNUM_LABUNICAST 4
/* RFC6514 */
#define SAFNUM_MULTICAST_VPN 5
/* draft-nalawade-kapoor-tunnel-safi */
#define SAFNUM_TUNNEL 64
/* RFC4761 */
#define SAFNUM_VPLS 65
/* RFC6037 */
#define SAFNUM_MDT 66
/* RFC7432 */
#define SAFNUM_EVPN 70
/* RFC4364 */
#define SAFNUM_VPNUNICAST 128
/* RFC6513 */
#define SAFNUM_VPNMULTICAST 129
#define SAFNUM_VPNUNIMULTICAST 130 /* deprecated now */
/* RFC4684 */
#define SAFNUM_RT_ROUTING_INFO 132
#define BGP_VPN_RD_LEN 8
static const struct tok bgp_safi_values[] = {
{ SAFNUM_RES, "Reserved"},
{ SAFNUM_UNICAST, "Unicast"},
{ SAFNUM_MULTICAST, "Multicast"},
{ SAFNUM_UNIMULTICAST, "Unicast+Multicast"},
{ SAFNUM_LABUNICAST, "labeled Unicast"},
{ SAFNUM_TUNNEL, "Tunnel"},
{ SAFNUM_VPLS, "VPLS"},
{ SAFNUM_MDT, "MDT"},
{ SAFNUM_EVPN, "EVPN"},
{ SAFNUM_VPNUNICAST, "labeled VPN Unicast"},
{ SAFNUM_VPNMULTICAST, "labeled VPN Multicast"},
{ SAFNUM_VPNUNIMULTICAST, "labeled VPN Unicast+Multicast"},
{ SAFNUM_RT_ROUTING_INFO, "Route Target Routing Information"},
{ SAFNUM_MULTICAST_VPN, "Multicast VPN"},
{ 0, NULL }
};
/* well-known community */
#define BGP_COMMUNITY_NO_EXPORT 0xffffff01
#define BGP_COMMUNITY_NO_ADVERT 0xffffff02
#define BGP_COMMUNITY_NO_EXPORT_SUBCONFED 0xffffff03
/* Extended community type - RFC 4360 */
#define BGP_EXT_COM_RT_0 0x0002 /* Route Target,Format AS(2bytes):AN(4bytes) */
#define BGP_EXT_COM_RT_1 0x0102 /* Route Target,Format IP address:AN(2bytes) */
#define BGP_EXT_COM_RT_2 0x0202 /* Route Target,Format AN(4bytes):local(2bytes) */
#define BGP_EXT_COM_RO_0 0x0003 /* Route Origin,Format AS(2bytes):AN(4bytes) */
#define BGP_EXT_COM_RO_1 0x0103 /* Route Origin,Format IP address:AN(2bytes) */
#define BGP_EXT_COM_RO_2 0x0203 /* Route Origin,Format AN(4bytes):local(2bytes) */
#define BGP_EXT_COM_LINKBAND 0x4004 /* Link Bandwidth,Format AS(2B):Bandwidth(4B) */
/* rfc2547 bgp-mpls-vpns */
#define BGP_EXT_COM_VPN_ORIGIN 0x0005 /* OSPF Domain ID / VPN of Origin - draft-rosen-vpns-ospf-bgp-mpls */
#define BGP_EXT_COM_VPN_ORIGIN2 0x0105 /* duplicate - keep for backwards compatibility */
#define BGP_EXT_COM_VPN_ORIGIN3 0x0205 /* duplicate - keep for backwards compatibility */
#define BGP_EXT_COM_VPN_ORIGIN4 0x8005 /* duplicate - keep for backwards compatibility */
#define BGP_EXT_COM_OSPF_RTYPE 0x0306 /* OSPF Route Type,Format Area(4B):RouteType(1B):Options(1B) */
#define BGP_EXT_COM_OSPF_RTYPE2 0x8000 /* duplicate - keep for backwards compatibility */
#define BGP_EXT_COM_ENCAP 0x030c /* rfc5512 */
#define BGP_EXT_COM_OSPF_RID 0x0107 /* OSPF Router ID,Format RouterID(4B):Unused(2B) */
#define BGP_EXT_COM_OSPF_RID2 0x8001 /* duplicate - keep for backwards compatibility */
#define BGP_EXT_COM_L2INFO 0x800a /* draft-kompella-ppvpn-l2vpn */
#define BGP_EXT_COM_SOURCE_AS 0x0009 /* RFC-ietf-l3vpn-2547bis-mcast-bgp-08.txt */
#define BGP_EXT_COM_VRF_RT_IMP 0x010b /* RFC-ietf-l3vpn-2547bis-mcast-bgp-08.txt */
#define BGP_EXT_COM_L2VPN_RT_0 0x000a /* L2VPN Identifier,Format AS(2bytes):AN(4bytes) */
#define BGP_EXT_COM_L2VPN_RT_1 0xF10a /* L2VPN Identifier,Format IP address:AN(2bytes) */
/* https://www.cisco.com/en/US/tech/tk436/tk428/technologies_tech_note09186a00801eb09a.shtml */
#define BGP_EXT_COM_EIGRP_GEN 0x8800
#define BGP_EXT_COM_EIGRP_METRIC_AS_DELAY 0x8801
#define BGP_EXT_COM_EIGRP_METRIC_REL_NH_BW 0x8802
#define BGP_EXT_COM_EIGRP_METRIC_LOAD_MTU 0x8803
#define BGP_EXT_COM_EIGRP_EXT_REMAS_REMID 0x8804
#define BGP_EXT_COM_EIGRP_EXT_REMPROTO_REMMETRIC 0x8805
static const struct tok bgp_extd_comm_flag_values[] = {
{ 0x8000, "vendor-specific"},
{ 0x4000, "non-transitive"},
{ 0, NULL},
};
static const struct tok bgp_extd_comm_subtype_values[] = {
{ BGP_EXT_COM_RT_0, "target"},
{ BGP_EXT_COM_RT_1, "target"},
{ BGP_EXT_COM_RT_2, "target"},
{ BGP_EXT_COM_RO_0, "origin"},
{ BGP_EXT_COM_RO_1, "origin"},
{ BGP_EXT_COM_RO_2, "origin"},
{ BGP_EXT_COM_LINKBAND, "link-BW"},
{ BGP_EXT_COM_VPN_ORIGIN, "ospf-domain"},
{ BGP_EXT_COM_VPN_ORIGIN2, "ospf-domain"},
{ BGP_EXT_COM_VPN_ORIGIN3, "ospf-domain"},
{ BGP_EXT_COM_VPN_ORIGIN4, "ospf-domain"},
{ BGP_EXT_COM_OSPF_RTYPE, "ospf-route-type"},
{ BGP_EXT_COM_OSPF_RTYPE2, "ospf-route-type"},
{ BGP_EXT_COM_ENCAP, "encapsulation"},
{ BGP_EXT_COM_OSPF_RID, "ospf-router-id"},
{ BGP_EXT_COM_OSPF_RID2, "ospf-router-id"},
{ BGP_EXT_COM_L2INFO, "layer2-info"},
{ BGP_EXT_COM_EIGRP_GEN, "eigrp-general-route (flag, tag)" },
{ BGP_EXT_COM_EIGRP_METRIC_AS_DELAY, "eigrp-route-metric (AS, delay)" },
{ BGP_EXT_COM_EIGRP_METRIC_REL_NH_BW, "eigrp-route-metric (reliability, nexthop, bandwidth)" },
{ BGP_EXT_COM_EIGRP_METRIC_LOAD_MTU, "eigrp-route-metric (load, MTU)" },
{ BGP_EXT_COM_EIGRP_EXT_REMAS_REMID, "eigrp-external-route (remote-AS, remote-ID)" },
{ BGP_EXT_COM_EIGRP_EXT_REMPROTO_REMMETRIC, "eigrp-external-route (remote-proto, remote-metric)" },
{ BGP_EXT_COM_SOURCE_AS, "source-AS" },
{ BGP_EXT_COM_VRF_RT_IMP, "vrf-route-import"},
{ BGP_EXT_COM_L2VPN_RT_0, "l2vpn-id"},
{ BGP_EXT_COM_L2VPN_RT_1, "l2vpn-id"},
{ 0, NULL},
};
/* RFC RFC5512 BGP Tunnel Encapsulation Attribute Tunnel Types */
#define BGP_ENCAP_TUNNEL_L2TPV3_IP 1
#define BGP_ENCAP_TUNNEL_GRE 2
#define BGP_ENCAP_TUNNEL_TRANSMIT 3
#define BGP_ENCAP_TUNNEL_IPSEC 4
#define BGP_ENCAP_TUNNEL_IP_IPSEC 5
#define BGP_ENCAP_TUNNEL_MPLS_IP 6
#define BGP_ENCAP_TUNNEL_IP_IP 7
#define BGP_ENCAP_TUNNEL_VXLAN 8
#define BGP_ENCAP_TUNNEL_NVGRE 9
#define BGP_ENCAP_TUNNEL_MPLS 10
#define BGP_ENCAP_TUNNEL_MPLS_GRE 11
#define BGP_ENCAP_TUNNEL_VXLAN_GPE 12
#define BGP_ENCAP_TUNNEL_MPLS_UDP 13
#define BGP_ENCAP_TUNNEL_IPV6 14
#define BGP_ENCAP_TUNNEL_SR_TE 15
#define BGP_ENCAP_TUNNEL_BARE 16
#define BGP_ENCAP_TUNNEL_SR 17
static const struct tok bgp_extd_comm_encap_tunnel_values[] = {
{ BGP_ENCAP_TUNNEL_L2TPV3_IP, "L2TPv3 over IP"},
{ BGP_ENCAP_TUNNEL_GRE, "GRE"},
{ BGP_ENCAP_TUNNEL_TRANSMIT, "Transmit Tunnel"},
{ BGP_ENCAP_TUNNEL_IPSEC, "IPsec"},
{ BGP_ENCAP_TUNNEL_IP_IPSEC, "IP in IP with IPsec"},
{ BGP_ENCAP_TUNNEL_MPLS_IP, "MPLS in IP with IPsec"},
{ BGP_ENCAP_TUNNEL_IP_IP, "IP in IP"},
{ BGP_ENCAP_TUNNEL_VXLAN, "VXLAN"},
{ BGP_ENCAP_TUNNEL_NVGRE, "NVGRE"},
{ BGP_ENCAP_TUNNEL_MPLS, "MPLS"},
{ BGP_ENCAP_TUNNEL_MPLS_GRE, "MPLS in GRE"},
{ BGP_ENCAP_TUNNEL_VXLAN_GPE, "VXLAN GPE"},
{ BGP_ENCAP_TUNNEL_MPLS_UDP, "MPLS in UDP"},
{ BGP_ENCAP_TUNNEL_IPV6, "IPv6"},
{ BGP_ENCAP_TUNNEL_SR_TE, "SR TE"},
{ BGP_ENCAP_TUNNEL_BARE, "Bare"},
{ BGP_ENCAP_TUNNEL_SR, "SR"},
{ 0, NULL},
};
/* OSPF codes for BGP_EXT_COM_OSPF_RTYPE draft-rosen-vpns-ospf-bgp-mpls */
#define BGP_OSPF_RTYPE_RTR 1 /* OSPF Router LSA */
#define BGP_OSPF_RTYPE_NET 2 /* OSPF Network LSA */
#define BGP_OSPF_RTYPE_SUM 3 /* OSPF Summary LSA */
#define BGP_OSPF_RTYPE_EXT 5 /* OSPF External LSA, note that ASBR doesn't apply to MPLS-VPN */
#define BGP_OSPF_RTYPE_NSSA 7 /* OSPF NSSA External*/
#define BGP_OSPF_RTYPE_SHAM 129 /* OSPF-MPLS-VPN Sham link */
#define BGP_OSPF_RTYPE_METRIC_TYPE 0x1 /* LSB of RTYPE Options Field */
static const struct tok bgp_extd_comm_ospf_rtype_values[] = {
{ BGP_OSPF_RTYPE_RTR, "Router" },
{ BGP_OSPF_RTYPE_NET, "Network" },
{ BGP_OSPF_RTYPE_SUM, "Summary" },
{ BGP_OSPF_RTYPE_EXT, "External" },
{ BGP_OSPF_RTYPE_NSSA,"NSSA External" },
{ BGP_OSPF_RTYPE_SHAM,"MPLS-VPN Sham" },
{ 0, NULL },
};
/* ADD-PATH Send/Receive field values */
static const struct tok bgp_add_path_recvsend[] = {
{ 1, "Receive" },
{ 2, "Send" },
{ 3, "Both" },
{ 0, NULL },
};
#define AS_STR_SIZE sizeof("xxxxx.xxxxx")
/*
* as_printf
*
* Convert an AS number into a string and return string pointer.
*
* Depending on bflag is set or not, AS number is converted into ASDOT notation
* or plain number notation.
*
*/
static char *
as_printf(netdissect_options *ndo,
char *str, size_t size, u_int asnum)
{
if (!ndo->ndo_bflag || asnum <= 0xFFFF) {
snprintf(str, size, "%u", asnum);
} else {
snprintf(str, size, "%u.%u", asnum >> 16, asnum & 0xFFFF);
}
return str;
}
#define ITEMCHECK(minlen) if (itemlen < minlen) goto badtlv;
int
decode_prefix4(netdissect_options *ndo,
const u_char *pptr, u_int itemlen, char *buf, size_t buflen)
{
nd_ipv4 addr;
u_int plen, plenbytes;
ITEMCHECK(1);
plen = GET_U_1(pptr);
if (32 < plen)
return -1;
itemlen -= 1;
memset(&addr, 0, sizeof(addr));
plenbytes = (plen + 7) / 8;
ITEMCHECK(plenbytes);
GET_CPY_BYTES(&addr, pptr + 1, plenbytes);
if (plen % 8) {
((u_char *)&addr)[plenbytes - 1] &= ((0xff00 >> (plen % 8)) & 0xff);
}
snprintf(buf, buflen, "%s/%u", ipaddr_string(ndo, (const u_char *)&addr), plen);
return 1 + plenbytes;
badtlv:
return -2;
}
static int
decode_labeled_prefix4(netdissect_options *ndo,
const u_char *pptr, u_int itemlen, char *buf,
size_t buflen)
{
nd_ipv4 addr;
u_int plen, plenbytes;
/* prefix length and label = 4 bytes */
ND_TCHECK_4(pptr);
ITEMCHECK(4);
plen = GET_U_1(pptr); /* get prefix length */
/* this is one of the weirdnesses of rfc3107
the label length (actually the label + COS bits)
is added to the prefix length;
we also do only read out just one label -
there is no real application for advertisement of
stacked labels in a single BGP message
*/
if (24 > plen)
return -1;
plen-=24; /* adjust prefixlen - labellength */
if (32 < plen)
return -1;
itemlen -= 4;
memset(&addr, 0, sizeof(addr));
plenbytes = (plen + 7) / 8;
ITEMCHECK(plenbytes);
GET_CPY_BYTES(&addr, pptr + 4, plenbytes);
if (plen % 8) {
((u_char *)&addr)[plenbytes - 1] &= ((0xff00 >> (plen % 8)) & 0xff);
}
/* the label may get offsetted by 4 bits so lets shift it right */
snprintf(buf, buflen, "%s/%u, label:%u %s",
ipaddr_string(ndo, (const u_char *)&addr),
plen,
GET_BE_U_3(pptr + 1)>>4,
((GET_U_1(pptr + 3) & 1) == 0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
return 4 + plenbytes;
trunc:
return -2;
badtlv:
return -3;
}
/*
* bgp_vpn_ip_print
*
* print an ipv4 or ipv6 address into a buffer dependent on address length.
*/
static char *
bgp_vpn_ip_print(netdissect_options *ndo,
const u_char *pptr, u_int addr_length)
{
/* worst case string is s fully formatted v6 address */
static char addr[sizeof("1234:5678:89ab:cdef:1234:5678:89ab:cdef")];
char *pos = addr;
switch(addr_length) {
case (sizeof(nd_ipv4) << 3): /* 32 */
snprintf(pos, sizeof(addr), "%s", GET_IPADDR_STRING(pptr));
break;
case (sizeof(nd_ipv6) << 3): /* 128 */
snprintf(pos, sizeof(addr), "%s", GET_IP6ADDR_STRING(pptr));
break;
default:
snprintf(pos, sizeof(addr), "bogus address length %u", addr_length);
break;
}
pos += strlen(pos);
*(pos) = '\0';
return (addr);
}
/*
* bgp_vpn_sg_print
*
* print an multicast s,g entry into a buffer.
* the s,g entry is encoded like this.
*
* +-----------------------------------+
* | Multicast Source Length (1 octet) |
* +-----------------------------------+
* | Multicast Source (Variable) |
* +-----------------------------------+
* | Multicast Group Length (1 octet) |
* +-----------------------------------+
* | Multicast Group (Variable) |
* +-----------------------------------+
*
* return the number of bytes read from the wire.
*/
static u_int
bgp_vpn_sg_print(netdissect_options *ndo,
const u_char *pptr, char *buf, size_t buflen)
{
uint8_t addr_length;
u_int total_length, offset;
total_length = 0;
/* Source address length, encoded in bits */
addr_length = GET_U_1(pptr);
pptr++;
/* Source address */
ND_TCHECK_LEN(pptr, (addr_length >> 3));
total_length += (addr_length >> 3) + 1;
offset = (u_int)strlen(buf);
if (addr_length) {
snprintf(buf + offset, buflen - offset, ", Source %s",
bgp_vpn_ip_print(ndo, pptr, addr_length));
pptr += (addr_length >> 3);
}
/* Group address length, encoded in bits */
addr_length = GET_U_1(pptr);
pptr++;
/* Group address */
ND_TCHECK_LEN(pptr, (addr_length >> 3));
total_length += (addr_length >> 3) + 1;
offset = (u_int)strlen(buf);
if (addr_length) {
snprintf(buf + offset, buflen - offset, ", Group %s",
bgp_vpn_ip_print(ndo, pptr, addr_length));
pptr += (addr_length >> 3);
}
trunc:
return (total_length);
}
/* Print an RFC 4364 Route Distinguisher */
const char *
bgp_vpn_rd_print(netdissect_options *ndo,
const u_char *pptr)
{
/* allocate space for the largest possible string */
static char rd[sizeof("xxxxx.xxxxx:xxxxx (xxx.xxx.xxx.xxx:xxxxx)")];
char *pos = rd;
/* allocate space for the largest possible string */
char astostr[AS_STR_SIZE];
/* ok lets load the RD format */
switch (GET_BE_U_2(pptr)) {
case 0:
/* 2-byte-AS:number fmt */
snprintf(pos, sizeof(rd) - (pos - rd), "%u:%u (= %u.%u.%u.%u)",
GET_BE_U_2(pptr + 2),
GET_BE_U_4(pptr + 4),
GET_U_1(pptr + 4), GET_U_1(pptr + 5),
GET_U_1(pptr + 6), GET_U_1(pptr + 7));
break;
case 1:
/* IP-address:AS fmt */
snprintf(pos, sizeof(rd) - (pos - rd), "%u.%u.%u.%u:%u",
GET_U_1(pptr + 2), GET_U_1(pptr + 3),
GET_U_1(pptr + 4), GET_U_1(pptr + 5),
GET_BE_U_2(pptr + 6));
break;
case 2:
/* 4-byte-AS:number fmt */
snprintf(pos, sizeof(rd) - (pos - rd), "%s:%u (%u.%u.%u.%u:%u)",
as_printf(ndo, astostr, sizeof(astostr), GET_BE_U_4(pptr + 2)),
GET_BE_U_2(pptr + 6), GET_U_1(pptr + 2),
GET_U_1(pptr + 3), GET_U_1(pptr + 4),
GET_U_1(pptr + 5), GET_BE_U_2(pptr + 6));
break;
default:
snprintf(pos, sizeof(rd) - (pos - rd), "unknown RD format");
break;
}
pos += strlen(pos);
*(pos) = '\0';
return (rd);
}
/*
* Print an RFC 4360 Extended Community.
*/
static void
bgp_extended_community_print(netdissect_options *ndo,
const u_char *pptr)
{
union { /* copy buffer for bandwidth values */
float f;
uint32_t i;
} bw;
/* allocate space for the largest possible string */
char astostr[AS_STR_SIZE];
switch (GET_BE_U_2(pptr)) {
case BGP_EXT_COM_RT_0:
case BGP_EXT_COM_RO_0:
case BGP_EXT_COM_L2VPN_RT_0:
ND_PRINT("%u:%u (= %s)",
GET_BE_U_2(pptr + 2),
GET_BE_U_4(pptr + 4),
GET_IPADDR_STRING(pptr+4));
break;
case BGP_EXT_COM_RT_1:
case BGP_EXT_COM_RO_1:
case BGP_EXT_COM_L2VPN_RT_1:
case BGP_EXT_COM_VRF_RT_IMP:
ND_PRINT("%s:%u",
GET_IPADDR_STRING(pptr+2),
GET_BE_U_2(pptr + 6));
break;
case BGP_EXT_COM_RT_2:
case BGP_EXT_COM_RO_2:
ND_PRINT("%s:%u",
as_printf(ndo, astostr, sizeof(astostr),
GET_BE_U_4(pptr + 2)), GET_BE_U_2(pptr + 6));
break;
case BGP_EXT_COM_LINKBAND:
bw.i = GET_BE_U_4(pptr + 4);
ND_PRINT("bandwidth: %.3f Mbps",
bw.f*8/1000000);
break;
case BGP_EXT_COM_VPN_ORIGIN:
case BGP_EXT_COM_VPN_ORIGIN2:
case BGP_EXT_COM_VPN_ORIGIN3:
case BGP_EXT_COM_VPN_ORIGIN4:
case BGP_EXT_COM_OSPF_RID:
case BGP_EXT_COM_OSPF_RID2:
ND_PRINT("%s", GET_IPADDR_STRING(pptr+2));
break;
case BGP_EXT_COM_OSPF_RTYPE:
case BGP_EXT_COM_OSPF_RTYPE2:
ND_PRINT("area:%s, router-type:%s, metric-type:%s%s",
GET_IPADDR_STRING(pptr+2),
tok2str(bgp_extd_comm_ospf_rtype_values,
"unknown (0x%02x)",
GET_U_1((pptr + 6))),
(GET_U_1(pptr + 7) & BGP_OSPF_RTYPE_METRIC_TYPE) ? "E2" : "",
((GET_U_1(pptr + 6) == BGP_OSPF_RTYPE_EXT) || (GET_U_1(pptr + 6) == BGP_OSPF_RTYPE_NSSA)) ? "E1" : "");
break;
case BGP_EXT_COM_L2INFO:
ND_PRINT("%s Control Flags [0x%02x]:MTU %u",
tok2str(l2vpn_encaps_values,
"unknown encaps",
GET_U_1((pptr + 2))),
GET_U_1((pptr + 3)),
GET_BE_U_2(pptr + 4));
break;
case BGP_EXT_COM_SOURCE_AS:
ND_PRINT("AS %u", GET_BE_U_2(pptr + 2));
break;
case BGP_EXT_COM_ENCAP:
ND_PRINT("Tunnel type: %s", tok2str(bgp_extd_comm_encap_tunnel_values,
"unknown encaps",
GET_BE_U_2(pptr + 6)));
break;
default:
ND_PRINT("%02x%02x%02x%02x%02x%02x",
GET_U_1(pptr + 2),
GET_U_1(pptr + 3),
GET_U_1(pptr + 4),
GET_U_1(pptr + 5),
GET_U_1(pptr + 6),
GET_U_1(pptr + 7));
break;
}
}
/*
* RFC4684 (Section 4)/RFC2858 (Section 4).
* RTC membership prefix is structured as follows
* [prefix-len] [origin-as] [route-target]
* The route-target is encoded as RT ext-comms.
* Prefix-len may be 0, 32..96
*
* Note that pptr is not packet data - it is
* a buffer owned by our caller - therefore GET_*
* macros can not be used.
*/
static char *
bgp_rt_prefix_print(netdissect_options *ndo,
const u_char *pptr,
u_int plen)
{
/* allocate space for the largest possible string */
char rtc_prefix_in_hex[sizeof("0000 0000 0000 0000")] = "";
u_int rtc_prefix_in_hex_len = 0;
static char output[61]; /* max response string */
/* allocate space for the largest possible string */
char astostr[AS_STR_SIZE];
uint16_t ec_type = 0;
u_int octet_count;
u_int i;
if (plen == 0) {
snprintf(output, sizeof(output), "route-target: 0:0/0");
return (output);
}
/* hex representation of the prefix */
octet_count = (plen+7)/8;
for (i=0; i<octet_count; i++) {
rtc_prefix_in_hex_len += snprintf(rtc_prefix_in_hex+rtc_prefix_in_hex_len,
sizeof(rtc_prefix_in_hex)-rtc_prefix_in_hex_len,
"%02x%s", *(pptr+i),
((i%2 == 1) && (i<octet_count-1)) ? " " : "");
}
if (plen < 16) {
/*
* The prefix is too short to include the full ext-comm type,
* so we have no way to parse it further.
*/
snprintf(output, sizeof(output), "route-target: partial-type: (%s/%d)",
rtc_prefix_in_hex, plen);
return (output);
}
/*
* get the ext-comm type
* Note: pptr references a static 8 octet buffer with unused bits set to 0,
* hence EXTRACT_*() macros are safe.
*/
ec_type = EXTRACT_BE_U_2(pptr);
switch (ec_type) {
case BGP_EXT_COM_RT_0:
/* 2-byte-AS:number fmt */
snprintf(output, sizeof(output), "route-target: %u:%u/%d (%s)",
EXTRACT_BE_U_2(pptr+2),
EXTRACT_BE_U_4(pptr+4),
plen, rtc_prefix_in_hex);
break;
case BGP_EXT_COM_RT_1:
/* IP-address:AS fmt */
snprintf(output, sizeof(output), "route-target: %u.%u.%u.%u:%u/%d (%s)",
*(pptr+2), *(pptr+3), *(pptr+4), *(pptr+5),
EXTRACT_BE_U_2(pptr+6), plen, rtc_prefix_in_hex);
break;
case BGP_EXT_COM_RT_2:
/* 4-byte-AS:number fmt */
snprintf(output, sizeof(output), "route-target: %s:%u/%d (%s)",
as_printf(ndo, astostr, sizeof(astostr), EXTRACT_BE_U_4(pptr+2)),
EXTRACT_BE_U_2(pptr+6), plen, rtc_prefix_in_hex);
break;
default:
snprintf(output, sizeof(output), "route target: unknown-type(%04x) (%s/%d)",
ec_type,
rtc_prefix_in_hex, plen);
break;
}
return (output);
}
/* RFC 4684 */
static int
decode_rt_routing_info(netdissect_options *ndo,
const u_char *pptr)
{
uint8_t route_target[8];
u_int plen;
/* allocate space for the largest possible string */
char astostr[AS_STR_SIZE];
u_int num_octets;
/* NLRI "prefix length" from RFC 2858 Section 4. */
plen = GET_U_1(pptr); /* get prefix length */
/* NLRI "prefix" (ibid), valid lengths are { 0, 32, 33, ..., 96 } bits.
* RFC 4684 Section 4 defines the layout of "origin AS" and "route
* target" fields inside the "prefix" depending on its length.
*/
if (0 == plen) {
/* Without "origin AS", without "route target". */
ND_PRINT("\n\t default route target");
return 1;
}
if (32 > plen) {
ND_PRINT("\n\t (illegal prefix length)");
return -1;
}
/* With at least "origin AS", possibly with "route target". */
as_printf(ndo, astostr, sizeof(astostr), GET_BE_U_4(pptr + 1));
plen -= 32; /* adjust prefix length */
if (64 < plen) {
ND_PRINT("\n\t (illegal prefix length)");
return -1;
}
/* From now on (plen + 7) / 8 evaluates to { 0, 1, 2, ..., 8 }
* and gives the number of octets in the variable-length "route
* target" field inside this NLRI "prefix". Look for it.
*/
memset(&route_target, 0, sizeof(route_target));
num_octets = (plen + 7) / 8;
GET_CPY_BYTES(&route_target, pptr + 5, num_octets);
/* If mask-len is not on octet boundary, ensure all extra bits are 0 */
if (plen % 8) {
((u_char *)&route_target)[num_octets - 1] &=
((0xff00 >> (plen % 8)) & 0xff);
}
ND_PRINT("\n\t origin AS: %s, %s",
astostr,
bgp_rt_prefix_print(ndo, (u_char *)&route_target, plen));
return 5 + num_octets;
}
static int
decode_labeled_vpn_prefix4(netdissect_options *ndo,
const u_char *pptr, char *buf, size_t buflen)
{
nd_ipv4 addr;
u_int plen;
plen = GET_U_1(pptr); /* get prefix length */
if ((24+64) > plen)
return -1;
plen -= (24+64); /* adjust prefixlen - labellength - RD len*/
if (32 < plen)
return -1;
memset(&addr, 0, sizeof(addr));
GET_CPY_BYTES(&addr, pptr + 12, (plen + 7) / 8);
if (plen % 8) {
((u_char *)&addr)[(plen + 7) / 8 - 1] &=
((0xff00 >> (plen % 8)) & 0xff);
}
/* the label may get offsetted by 4 bits so lets shift it right */
snprintf(buf, buflen, "RD: %s, %s/%u, label:%u %s",
bgp_vpn_rd_print(ndo, pptr+4),
ipaddr_string(ndo, (const u_char *)&addr),
plen,
GET_BE_U_3(pptr + 1)>>4,
((GET_U_1(pptr + 3) & 1) == 0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
return 12 + (plen + 7) / 8;
}
/*
* +-------------------------------+
* | |
* | RD:IPv4-address (12 octets) |
* | |
* +-------------------------------+
* | MDT Group-address (4 octets) |
* +-------------------------------+
*/
#define MDT_VPN_NLRI_LEN 16
static int
decode_mdt_vpn_nlri(netdissect_options *ndo,
const u_char *pptr, char *buf, size_t buflen)
{
const u_char *rd;
const u_char *vpn_ip;
/* if the NLRI is not predefined length, quit.*/
if (GET_U_1(pptr) != MDT_VPN_NLRI_LEN * 8)
return -1;
pptr++;
/* RD */
ND_TCHECK_8(pptr);
rd = pptr;
pptr += 8;
/* IPv4 address */
vpn_ip = pptr;
pptr += sizeof(nd_ipv4);
/* MDT Group Address */
snprintf(buf, buflen, "RD: %s, VPN IP Address: %s, MC Group Address: %s",
bgp_vpn_rd_print(ndo, rd), GET_IPADDR_STRING(vpn_ip), GET_IPADDR_STRING(pptr));
return MDT_VPN_NLRI_LEN + 1;
trunc:
return -2;
}
#define BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_I_PMSI 1
#define BGP_MULTICAST_VPN_ROUTE_TYPE_INTER_AS_I_PMSI 2
#define BGP_MULTICAST_VPN_ROUTE_TYPE_S_PMSI 3
#define BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_SEG_LEAF 4
#define BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_ACTIVE 5
#define BGP_MULTICAST_VPN_ROUTE_TYPE_SHARED_TREE_JOIN 6
#define BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_TREE_JOIN 7
static const struct tok bgp_multicast_vpn_route_type_values[] = {
{ BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_I_PMSI, "Intra-AS I-PMSI"},
{ BGP_MULTICAST_VPN_ROUTE_TYPE_INTER_AS_I_PMSI, "Inter-AS I-PMSI"},
{ BGP_MULTICAST_VPN_ROUTE_TYPE_S_PMSI, "S-PMSI"},
{ BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_SEG_LEAF, "Intra-AS Segment-Leaf"},
{ BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_ACTIVE, "Source-Active"},
{ BGP_MULTICAST_VPN_ROUTE_TYPE_SHARED_TREE_JOIN, "Shared Tree Join"},
{ BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_TREE_JOIN, "Source Tree Join"},
{ 0, NULL}
};
static int
decode_multicast_vpn(netdissect_options *ndo,
const u_char *pptr, char *buf, size_t buflen)
{
/* allocate space for the largest possible string */
char astostr[AS_STR_SIZE];
uint8_t route_type, route_length;
u_int addr_length, sg_length;
u_int offset;
route_type = GET_U_1(pptr);
pptr++;
route_length = GET_U_1(pptr);
pptr++;
snprintf(buf, buflen, "Route-Type: %s (%u), length: %u",
tok2str(bgp_multicast_vpn_route_type_values,
"Unknown", route_type),
route_type, route_length);
switch(route_type) {
case BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_I_PMSI:
ND_TCHECK_LEN(pptr, BGP_VPN_RD_LEN);
+ if (route_length < BGP_VPN_RD_LEN)
+ goto trunc;
offset = (u_int)strlen(buf);
snprintf(buf + offset, buflen - offset, ", RD: %s, Originator %s",
bgp_vpn_rd_print(ndo, pptr),
bgp_vpn_ip_print(ndo, pptr + BGP_VPN_RD_LEN,
(route_length - BGP_VPN_RD_LEN) << 3));
break;
case BGP_MULTICAST_VPN_ROUTE_TYPE_INTER_AS_I_PMSI:
ND_TCHECK_LEN(pptr, BGP_VPN_RD_LEN + 4);
offset = (u_int)strlen(buf);
snprintf(buf + offset, buflen - offset, ", RD: %s, Source-AS %s",
bgp_vpn_rd_print(ndo, pptr),
as_printf(ndo, astostr, sizeof(astostr),
GET_BE_U_4(pptr + BGP_VPN_RD_LEN)));
break;
case BGP_MULTICAST_VPN_ROUTE_TYPE_S_PMSI:
ND_TCHECK_LEN(pptr, BGP_VPN_RD_LEN);
offset = (u_int)strlen(buf);
snprintf(buf + offset, buflen - offset, ", RD: %s",
bgp_vpn_rd_print(ndo, pptr));
pptr += BGP_VPN_RD_LEN;
sg_length = bgp_vpn_sg_print(ndo, pptr, buf, buflen);
addr_length = route_length - sg_length;
ND_TCHECK_LEN(pptr, addr_length);
offset = (u_int)strlen(buf);
snprintf(buf + offset, buflen - offset, ", Originator %s",
bgp_vpn_ip_print(ndo, pptr, addr_length << 3));
break;
case BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_ACTIVE:
ND_TCHECK_LEN(pptr, BGP_VPN_RD_LEN);
offset = (u_int)strlen(buf);
snprintf(buf + offset, buflen - offset, ", RD: %s",
bgp_vpn_rd_print(ndo, pptr));
pptr += BGP_VPN_RD_LEN;
bgp_vpn_sg_print(ndo, pptr, buf, buflen);
break;
case BGP_MULTICAST_VPN_ROUTE_TYPE_SHARED_TREE_JOIN: /* fall through */
case BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_TREE_JOIN:
ND_TCHECK_LEN(pptr, BGP_VPN_RD_LEN + 4);
offset = (u_int)strlen(buf);
snprintf(buf + offset, buflen - offset, ", RD: %s, Source-AS %s",
bgp_vpn_rd_print(ndo, pptr),
as_printf(ndo, astostr, sizeof(astostr),
GET_BE_U_4(pptr + BGP_VPN_RD_LEN)));
pptr += BGP_VPN_RD_LEN + 4;
bgp_vpn_sg_print(ndo, pptr, buf, buflen);
break;
/*
* no per route-type printing yet.
*/
case BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_SEG_LEAF:
default:
break;
}
return route_length + 2;
trunc:
return -2;
}
/*
* As I remember, some versions of systems have an snprintf() that
* returns -1 if the buffer would have overflowed. If the return
* value is negative, set buflen to 0, to indicate that we've filled
* the buffer up.
*
* If the return value is greater than buflen, that means that
* the buffer would have overflowed; again, set buflen to 0 in
* that case.
*/
#define UPDATE_BUF_BUFLEN(buf, buflen, stringlen) \
if (stringlen<0) \
buflen=0; \
else if ((u_int)stringlen>buflen) \
buflen=0; \
else { \
buflen-=stringlen; \
buf+=stringlen; \
}
static int
decode_labeled_vpn_l2(netdissect_options *ndo,
const u_char *pptr, char *buf, size_t buflen)
{
u_int plen, tlen, tlv_type, tlv_len, ttlv_len;
int stringlen;
plen = GET_BE_U_2(pptr);
tlen = plen;
pptr += 2;
/* Old and new L2VPN NLRI share AFI/SAFI
* -> Assume a 12 Byte-length NLRI is auto-discovery-only
* and > 17 as old format. Complain for the middle case
*/
if (plen == 12) {
/* assume AD-only with RD, BGPNH */
ND_TCHECK_LEN(pptr, 12);
buf[0] = '\0';
stringlen = snprintf(buf, buflen, "RD: %s, BGPNH: %s",
bgp_vpn_rd_print(ndo, pptr),
GET_IPADDR_STRING(pptr+8));
UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
pptr += 12;
tlen -= 12;
return plen + 2;
} else if (plen > 17) {
/* assume old format */
/* RD, ID, LBLKOFF, LBLBASE */
ND_TCHECK_LEN(pptr, 15);
buf[0] = '\0';
stringlen = snprintf(buf, buflen, "RD: %s, CE-ID: %u, Label-Block Offset: %u, Label Base %u",
bgp_vpn_rd_print(ndo, pptr),
GET_BE_U_2(pptr + 8),
GET_BE_U_2(pptr + 10),
GET_BE_U_3(pptr + 12)>>4); /* the label is offsetted by 4 bits so lets shift it right */
UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
pptr += 15;
tlen -= 15;
/* ok now the variable part - lets read out TLVs*/
while (tlen != 0) {
if (tlen < 3) {
if (buflen != 0) {
stringlen=snprintf(buf,buflen, "\n\t\tran past the end");
UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
}
return plen + 2;
}
tlv_type = GET_U_1(pptr);
pptr++;
tlv_len = GET_BE_U_2(pptr); /* length, in *bits* */
ttlv_len = (tlv_len + 7)/8; /* length, in *bytes* */
pptr += 2;
switch(tlv_type) {
case 1:
if (buflen != 0) {
stringlen=snprintf(buf,buflen, "\n\t\tcircuit status vector (%u) length: %u: 0x",
tlv_type,
tlv_len);
UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
}
while (ttlv_len != 0) {
if (tlen < 1) {
if (buflen != 0) {
stringlen=snprintf(buf,buflen, " (ran past the end)");
UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
}
return plen + 2;
}
ND_TCHECK_1(pptr);
if (buflen != 0) {
stringlen=snprintf(buf,buflen, "%02x",
GET_U_1(pptr));
pptr++;
UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
}
ttlv_len--;
tlen--;
}
break;
default:
if (buflen != 0) {
stringlen=snprintf(buf,buflen, "\n\t\tunknown TLV #%u, length: %u",
tlv_type,
tlv_len);
UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
}
if (tlen < ttlv_len) {
if (buflen != 0) {
stringlen=snprintf(buf,buflen, " (ran past the end)");
UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
}
return plen + 2;
}
tlen -= ttlv_len;
break;
}
}
return plen + 2;
} else {
/* complain bitterly ? */
/* fall through */
goto trunc;
}
trunc:
return -2;
}
int
decode_prefix6(netdissect_options *ndo,
const u_char *pd, u_int itemlen, char *buf, size_t buflen)
{
nd_ipv6 addr;
u_int plen, plenbytes;
ITEMCHECK(1);
plen = GET_U_1(pd);
if (128 < plen)
return -1;
itemlen -= 1;
memset(&addr, 0, sizeof(addr));
plenbytes = (plen + 7) / 8;
ITEMCHECK(plenbytes);
GET_CPY_BYTES(&addr, pd + 1, plenbytes);
if (plen % 8) {
addr[plenbytes - 1] &=
((0xff00 >> (plen % 8)) & 0xff);
}
snprintf(buf, buflen, "%s/%u", ip6addr_string(ndo, (const u_char *)&addr), plen);
return 1 + plenbytes;
badtlv:
return -2;
}
static int
decode_labeled_prefix6(netdissect_options *ndo,
const u_char *pptr, u_int itemlen, char *buf, size_t buflen)
{
nd_ipv6 addr;
u_int plen, plenbytes;
/* prefix length and label = 4 bytes */
ND_TCHECK_4(pptr);
ITEMCHECK(4);
plen = GET_U_1(pptr); /* get prefix length */
if (24 > plen)
return -1;
plen -= 24; /* adjust prefixlen - labellength */
if (128 < plen)
return -1;
itemlen -= 4;
memset(&addr, 0, sizeof(addr));
plenbytes = (plen + 7) / 8;
GET_CPY_BYTES(&addr, pptr + 4, plenbytes);
if (plen % 8) {
addr[plenbytes - 1] &=
((0xff00 >> (plen % 8)) & 0xff);
}
/* the label may get offsetted by 4 bits so lets shift it right */
snprintf(buf, buflen, "%s/%u, label:%u %s",
ip6addr_string(ndo, (const u_char *)&addr),
plen,
GET_BE_U_3(pptr + 1)>>4,
((GET_U_1(pptr + 3) & 1) == 0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
return 4 + plenbytes;
trunc:
return -2;
badtlv:
return -3;
}
static int
decode_labeled_vpn_prefix6(netdissect_options *ndo,
const u_char *pptr, char *buf, size_t buflen)
{
nd_ipv6 addr;
u_int plen;
plen = GET_U_1(pptr); /* get prefix length */
if ((24+64) > plen)
return -1;
plen -= (24+64); /* adjust prefixlen - labellength - RD len*/
if (128 < plen)
return -1;
memset(&addr, 0, sizeof(addr));
GET_CPY_BYTES(&addr, pptr + 12, (plen + 7) / 8);
if (plen % 8) {
addr[(plen + 7) / 8 - 1] &=
((0xff00 >> (plen % 8)) & 0xff);
}
/* the label may get offsetted by 4 bits so lets shift it right */
snprintf(buf, buflen, "RD: %s, %s/%u, label:%u %s",
bgp_vpn_rd_print(ndo, pptr+4),
ip6addr_string(ndo, (const u_char *)&addr),
plen,
GET_BE_U_3(pptr + 1)>>4,
((GET_U_1(pptr + 3) & 1) == 0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
return 12 + (plen + 7) / 8;
}
static int
decode_clnp_prefix(netdissect_options *ndo,
const u_char *pptr, char *buf, size_t buflen)
{
uint8_t addr[19];
u_int plen;
plen = GET_U_1(pptr); /* get prefix length */
if (152 < plen)
return -1;
memset(&addr, 0, sizeof(addr));
GET_CPY_BYTES(&addr, pptr + 4, (plen + 7) / 8);
if (plen % 8) {
addr[(plen + 7) / 8 - 1] &=
((0xff00 >> (plen % 8)) & 0xff);
}
/* Cannot use GET_ISONSAP_STRING (not packet buffer pointer) */
snprintf(buf, buflen, "%s/%u",
isonsap_string(ndo, addr,(plen + 7) / 8),
plen);
return 1 + (plen + 7) / 8;
}
static int
decode_labeled_vpn_clnp_prefix(netdissect_options *ndo,
const u_char *pptr, char *buf, size_t buflen)
{
uint8_t addr[19];
u_int plen;
plen = GET_U_1(pptr); /* get prefix length */
if ((24+64) > plen)
return -1;
plen -= (24+64); /* adjust prefixlen - labellength - RD len*/
if (152 < plen)
return -1;
memset(&addr, 0, sizeof(addr));
GET_CPY_BYTES(&addr, pptr + 12, (plen + 7) / 8);
if (plen % 8) {
addr[(plen + 7) / 8 - 1] &= ((0xff00 >> (plen % 8)) & 0xff);
}
/* the label may get offsetted by 4 bits so lets shift it right */
/* Cannot use GET_ISONSAP_STRING (not packet buffer pointer) */
snprintf(buf, buflen, "RD: %s, %s/%u, label:%u %s",
bgp_vpn_rd_print(ndo, pptr+4),
isonsap_string(ndo, addr,(plen + 7) / 8),
plen,
GET_BE_U_3(pptr + 1)>>4,
((GET_U_1(pptr + 3) & 1) == 0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
return 12 + (plen + 7) / 8;
}
/*
* bgp_attr_get_as_size
*
* Try to find the size of the ASs encoded in an as-path. It is not obvious, as
* both Old speakers that do not support 4 byte AS, and the new speakers that do
* support, exchange AS-Path with the same path-attribute type value 0x02.
*/
static u_int
bgp_attr_get_as_size(netdissect_options *ndo,
uint8_t bgpa_type, const u_char *pptr, u_int len)
{
const u_char *tptr = pptr;
/*
* If the path attribute is the optional AS4 path type, then we already
* know, that ASs must be encoded in 4 byte format.
*/
if (bgpa_type == BGPTYPE_AS4_PATH) {
return 4;
}
/*
* Let us assume that ASs are of 2 bytes in size, and check if the AS-Path
* TLV is good. If not, ask the caller to try with AS encoded as 4 bytes
* each.
*/
while (tptr < pptr + len) {
/*
* If we do not find a valid segment type, our guess might be wrong.
*/
if (GET_U_1(tptr) < BGP_AS_SEG_TYPE_MIN || GET_U_1(tptr) > BGP_AS_SEG_TYPE_MAX) {
goto trunc;
}
tptr += 2 + GET_U_1(tptr + 1) * 2;
}
/*
* If we correctly reached end of the AS path attribute data content,
* then most likely ASs were indeed encoded as 2 bytes.
*/
if (tptr == pptr + len) {
return 2;
}
trunc:
/*
* We can come here, either we did not have enough data, or if we
* try to decode 4 byte ASs in 2 byte format. Either way, return 4,
- * so that calller can try to decode each AS as of 4 bytes. If indeed
+ * so that caller can try to decode each AS as of 4 bytes. If indeed
* there was not enough data, it will crib and end the parse anyways.
*/
return 4;
}
/*
* The only way to know that a BGP UPDATE message is using add path is
* by checking if the capability is in the OPEN message which we may have missed.
* So this function checks if it is possible that the update could contain add path
* and if so it checks that standard BGP doesn't make sense.
*/
static int
check_add_path(netdissect_options *ndo, const u_char *pptr, u_int length,
u_int max_prefix_length)
{
u_int offset, prefix_length;
if (length < 5) {
return 0;
}
/*
- * Scan through the NLRI information under the assumpetion that
+ * Scan through the NLRI information under the assumption that
* it doesn't have path IDs.
*/
for (offset = 0; offset < length;) {
offset += 4;
if (!ND_TTEST_1(pptr + offset)) {
/* We ran out of captured data; quit scanning. */
break;
}
prefix_length = GET_U_1(pptr + offset);
/*
* Add 4 to cover the path id
* and check the prefix length isn't greater than 32/128.
*/
if (prefix_length > max_prefix_length) {
return 0;
}
/* Add 1 for the prefix_length byte and prefix_length to cover the address */
offset += 1 + ((prefix_length + 7) / 8);
}
/* check we haven't gone past the end of the section */
if (offset > length) {
return 0;
}
/* check it's not standard BGP */
for (offset = 0; offset < length; ) {
if (!ND_TTEST_1(pptr + offset)) {
/* We ran out of captured data; quit scanning. */
break;
}
prefix_length = GET_U_1(pptr + offset);
/*
* If the prefix_length is zero (0.0.0.0/0)
* and since it's not the only address (length >= 5)
* then it is add-path
*/
if (prefix_length < 1 || prefix_length > max_prefix_length) {
return 1;
}
offset += 1 + ((prefix_length + 7) / 8);
}
if (offset > length) {
return 1;
}
/* assume not add-path by default */
return 0;
}
static int
bgp_mp_af_print(netdissect_options *ndo,
const u_char *tptr, u_int tlen,
uint16_t *afp, uint8_t *safip)
{
uint16_t af;
uint8_t safi;
af = GET_BE_U_2(tptr);
*afp = af;
safi = GET_U_1(tptr + 2);
*safip = safi;
ND_PRINT("\n\t AFI: %s (%u), %sSAFI: %s (%u)",
tok2str(af_values, "Unknown AFI", af),
af,
(safi>128) ? "vendor specific " : "", /* 128 is meanwhile wellknown */
tok2str(bgp_safi_values, "Unknown SAFI", safi),
safi);
switch(af<<8 | safi) {
case (AFNUM_INET<<8 | SAFNUM_UNICAST):
case (AFNUM_INET<<8 | SAFNUM_MULTICAST):
case (AFNUM_INET<<8 | SAFNUM_UNIMULTICAST):
case (AFNUM_INET<<8 | SAFNUM_LABUNICAST):
case (AFNUM_INET<<8 | SAFNUM_RT_ROUTING_INFO):
case (AFNUM_INET<<8 | SAFNUM_VPNUNICAST):
case (AFNUM_INET<<8 | SAFNUM_VPNMULTICAST):
case (AFNUM_INET<<8 | SAFNUM_VPNUNIMULTICAST):
case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN):
case (AFNUM_INET<<8 | SAFNUM_MDT):
case (AFNUM_INET6<<8 | SAFNUM_UNICAST):
case (AFNUM_INET6<<8 | SAFNUM_MULTICAST):
case (AFNUM_INET6<<8 | SAFNUM_UNIMULTICAST):
case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST):
case (AFNUM_INET6<<8 | SAFNUM_VPNUNICAST):
case (AFNUM_INET6<<8 | SAFNUM_VPNMULTICAST):
case (AFNUM_INET6<<8 | SAFNUM_VPNUNIMULTICAST):
case (AFNUM_NSAP<<8 | SAFNUM_UNICAST):
case (AFNUM_NSAP<<8 | SAFNUM_MULTICAST):
case (AFNUM_NSAP<<8 | SAFNUM_UNIMULTICAST):
case (AFNUM_NSAP<<8 | SAFNUM_VPNUNICAST):
case (AFNUM_NSAP<<8 | SAFNUM_VPNMULTICAST):
case (AFNUM_NSAP<<8 | SAFNUM_VPNUNIMULTICAST):
case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNICAST):
case (AFNUM_L2VPN<<8 | SAFNUM_VPNMULTICAST):
case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNIMULTICAST):
case (AFNUM_VPLS<<8 | SAFNUM_VPLS):
break;
default:
ND_TCHECK_LEN(tptr, tlen);
ND_PRINT("\n\t no AFI %u / SAFI %u decoder", af, safi);
if (ndo->ndo_vflag <= 1)
print_unknown_data(ndo, tptr, "\n\t ", tlen);
return -1;
}
return 0;
trunc:
return -2;
}
static int
bgp_nlri_print(netdissect_options *ndo, uint16_t af, uint8_t safi,
const u_char *tptr, u_int len,
char *buf, size_t buflen,
int add_path4, int add_path6)
{
int advance;
u_int path_id = 0;
switch (af<<8 | safi) {
case (AFNUM_INET<<8 | SAFNUM_UNICAST):
case (AFNUM_INET<<8 | SAFNUM_MULTICAST):
case (AFNUM_INET<<8 | SAFNUM_UNIMULTICAST):
if (add_path4) {
path_id = GET_BE_U_4(tptr);
tptr += 4;
}
advance = decode_prefix4(ndo, tptr, len, buf, buflen);
if (advance == -1)
ND_PRINT("\n\t (illegal prefix length)");
else if (advance == -2)
break; /* bytes left, but not enough */
else
ND_PRINT("\n\t %s", buf);
if (add_path4) {
ND_PRINT(" Path Id: %u", path_id);
advance += 4;
}
break;
case (AFNUM_INET<<8 | SAFNUM_LABUNICAST):
advance = decode_labeled_prefix4(ndo, tptr, len, buf, buflen);
if (advance == -1)
ND_PRINT("\n\t (illegal prefix length)");
else if (advance == -2)
goto trunc;
else if (advance == -3)
break; /* bytes left, but not enough */
else
ND_PRINT("\n\t %s", buf);
break;
case (AFNUM_INET<<8 | SAFNUM_VPNUNICAST):
case (AFNUM_INET<<8 | SAFNUM_VPNMULTICAST):
case (AFNUM_INET<<8 | SAFNUM_VPNUNIMULTICAST):
advance = decode_labeled_vpn_prefix4(ndo, tptr, buf, buflen);
if (advance == -1)
ND_PRINT("\n\t (illegal prefix length)");
else
ND_PRINT("\n\t %s", buf);
break;
case (AFNUM_INET<<8 | SAFNUM_RT_ROUTING_INFO):
advance = decode_rt_routing_info(ndo, tptr);
break;
case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN): /* fall through */
case (AFNUM_INET6<<8 | SAFNUM_MULTICAST_VPN):
advance = decode_multicast_vpn(ndo, tptr, buf, buflen);
if (advance == -1)
ND_PRINT("\n\t (illegal prefix length)");
else if (advance == -2)
goto trunc;
else
ND_PRINT("\n\t %s", buf);
break;
case (AFNUM_INET<<8 | SAFNUM_MDT):
advance = decode_mdt_vpn_nlri(ndo, tptr, buf, buflen);
if (advance == -1)
ND_PRINT("\n\t (illegal prefix length)");
else if (advance == -2)
goto trunc;
else
ND_PRINT("\n\t %s", buf);
break;
case (AFNUM_INET6<<8 | SAFNUM_UNICAST):
case (AFNUM_INET6<<8 | SAFNUM_MULTICAST):
case (AFNUM_INET6<<8 | SAFNUM_UNIMULTICAST):
if (add_path6) {
path_id = GET_BE_U_4(tptr);
tptr += 4;
}
advance = decode_prefix6(ndo, tptr, len, buf, buflen);
if (advance == -1)
ND_PRINT("\n\t (illegal prefix length)");
else if (advance == -2)
break; /* bytes left, but not enough */
else
ND_PRINT("\n\t %s", buf);
if (add_path6) {
ND_PRINT(" Path Id: %u", path_id);
advance += 4;
}
break;
case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST):
advance = decode_labeled_prefix6(ndo, tptr, len, buf, buflen);
if (advance == -1)
ND_PRINT("\n\t (illegal prefix length)");
else if (advance == -2)
goto trunc;
else if (advance == -3)
break; /* bytes left, but not enough */
else
ND_PRINT("\n\t %s", buf);
break;
case (AFNUM_INET6<<8 | SAFNUM_VPNUNICAST):
case (AFNUM_INET6<<8 | SAFNUM_VPNMULTICAST):
case (AFNUM_INET6<<8 | SAFNUM_VPNUNIMULTICAST):
advance = decode_labeled_vpn_prefix6(ndo, tptr, buf, buflen);
if (advance == -1)
ND_PRINT("\n\t (illegal prefix length)");
else
ND_PRINT("\n\t %s", buf);
break;
case (AFNUM_VPLS<<8 | SAFNUM_VPLS):
case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNICAST):
case (AFNUM_L2VPN<<8 | SAFNUM_VPNMULTICAST):
case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNIMULTICAST):
advance = decode_labeled_vpn_l2(ndo, tptr, buf, buflen);
if (advance == -1)
ND_PRINT("\n\t (illegal length)");
else if (advance == -2)
goto trunc;
else
ND_PRINT("\n\t %s", buf);
break;
case (AFNUM_NSAP<<8 | SAFNUM_UNICAST):
case (AFNUM_NSAP<<8 | SAFNUM_MULTICAST):
case (AFNUM_NSAP<<8 | SAFNUM_UNIMULTICAST):
advance = decode_clnp_prefix(ndo, tptr, buf, buflen);
if (advance == -1)
ND_PRINT("\n\t (illegal prefix length)");
else
ND_PRINT("\n\t %s", buf);
break;
case (AFNUM_NSAP<<8 | SAFNUM_VPNUNICAST):
case (AFNUM_NSAP<<8 | SAFNUM_VPNMULTICAST):
case (AFNUM_NSAP<<8 | SAFNUM_VPNUNIMULTICAST):
advance = decode_labeled_vpn_clnp_prefix(ndo, tptr, buf, buflen);
if (advance == -1)
ND_PRINT("\n\t (illegal prefix length)");
else
ND_PRINT("\n\t %s", buf);
break;
default:
/*
* This should not happen, we should have been protected
* by bgp_mp_af_print()'s return value.
*/
ND_PRINT("\n\t ERROR: no AFI %u / SAFI %u decoder", af, safi);
advance = -4;
break;
}
return advance;
trunc: /* we rely on the caller to recognize -2 return value */
return -2;
}
static int
bgp_attr_print(netdissect_options *ndo,
uint8_t atype, const u_char *pptr, u_int len,
const unsigned attr_set_level)
{
/* allocate space for the largest possible string */
char astostr[AS_STR_SIZE];
u_int i;
uint16_t af;
uint8_t safi, snpa, nhlen;
int advance;
u_int tlen;
const u_char *tptr;
char buf[MAXHOSTNAMELEN + 100];
u_int as_size;
int add_path4, add_path6;
int ret;
tptr = pptr;
tlen = len;
switch (atype) {
case BGPTYPE_ORIGIN:
if (len != 1)
ND_PRINT("invalid len");
else {
ND_PRINT("%s", tok2str(bgp_origin_values,
"Unknown Origin Typecode",
GET_U_1(tptr)));
}
break;
/*
* Process AS4 byte path and AS2 byte path attributes here.
*/
case BGPTYPE_AS4_PATH:
case BGPTYPE_AS_PATH:
if (len % 2) {
ND_PRINT("invalid len");
break;
}
if (!len) {
ND_PRINT("empty");
break;
}
/*
* BGP updates exchanged between New speakers that support 4
* byte AS, ASs are always encoded in 4 bytes. There is no
* definitive way to find this, just by the packet's
* contents. So, check for packet's TLV's sanity assuming
* 2 bytes first, and it does not pass, assume that ASs are
* encoded in 4 bytes format and move on.
*/
as_size = bgp_attr_get_as_size(ndo, atype, pptr, len);
while (tptr < pptr + len) {
ND_PRINT("%s", tok2str(bgp_as_path_segment_open_values,
"?", GET_U_1(tptr)));
for (i = 0; i < GET_U_1(tptr + 1) * as_size; i += as_size) {
ND_TCHECK_LEN(tptr + 2 + i, as_size);
ND_PRINT("%s ",
as_printf(ndo, astostr, sizeof(astostr),
as_size == 2 ?
GET_BE_U_2(tptr + i + 2) :
GET_BE_U_4(tptr + i + 2)));
}
ND_PRINT("%s", tok2str(bgp_as_path_segment_close_values,
"?", GET_U_1(tptr)));
tptr += 2 + GET_U_1(tptr + 1) * as_size;
}
break;
case BGPTYPE_NEXT_HOP:
if (len != 4)
ND_PRINT("invalid len");
else {
ND_PRINT("%s", GET_IPADDR_STRING(tptr));
}
break;
case BGPTYPE_MULTI_EXIT_DISC:
case BGPTYPE_LOCAL_PREF:
if (len != 4)
ND_PRINT("invalid len");
else {
ND_PRINT("%u", GET_BE_U_4(tptr));
}
break;
case BGPTYPE_ATOMIC_AGGREGATE:
if (len != 0)
ND_PRINT("invalid len");
break;
case BGPTYPE_AGGREGATOR:
/*
* Depending on the AS encoded is of 2 bytes or of 4 bytes,
* the length of this PA can be either 6 bytes or 8 bytes.
*/
if (len != 6 && len != 8) {
ND_PRINT("invalid len");
break;
}
ND_TCHECK_LEN(tptr, len);
if (len == 6) {
ND_PRINT(" AS #%s, origin %s",
as_printf(ndo, astostr, sizeof(astostr), GET_BE_U_2(tptr)),
GET_IPADDR_STRING(tptr + 2));
} else {
ND_PRINT(" AS #%s, origin %s",
as_printf(ndo, astostr, sizeof(astostr),
GET_BE_U_4(tptr)), GET_IPADDR_STRING(tptr + 4));
}
break;
case BGPTYPE_AGGREGATOR4:
if (len != 8) {
ND_PRINT("invalid len");
break;
}
ND_PRINT(" AS #%s, origin %s",
as_printf(ndo, astostr, sizeof(astostr), GET_BE_U_4(tptr)),
GET_IPADDR_STRING(tptr + 4));
break;
case BGPTYPE_COMMUNITIES:
if (len % 4) {
ND_PRINT("invalid len");
break;
}
while (tlen != 0) {
uint32_t comm;
ND_TCHECK_4(tptr);
if (tlen < 4)
goto trunc;
comm = GET_BE_U_4(tptr);
switch (comm) {
case BGP_COMMUNITY_NO_EXPORT:
ND_PRINT(" NO_EXPORT");
break;
case BGP_COMMUNITY_NO_ADVERT:
ND_PRINT(" NO_ADVERTISE");
break;
case BGP_COMMUNITY_NO_EXPORT_SUBCONFED:
ND_PRINT(" NO_EXPORT_SUBCONFED");
break;
default:
ND_PRINT("%u:%u%s",
(comm >> 16) & 0xffff,
comm & 0xffff,
(tlen>4) ? ", " : "");
break;
}
tlen -=4;
tptr +=4;
}
break;
case BGPTYPE_ORIGINATOR_ID:
if (len != 4) {
ND_PRINT("invalid len");
break;
}
ND_PRINT("%s",GET_IPADDR_STRING(tptr));
break;
case BGPTYPE_CLUSTER_LIST:
if (len % 4) {
ND_PRINT("invalid len");
break;
}
while (tlen != 0) {
if (tlen < 4)
goto trunc;
ND_PRINT("%s%s",
GET_IPADDR_STRING(tptr),
(tlen>4) ? ", " : "");
tlen -=4;
tptr +=4;
}
break;
case BGPTYPE_MP_REACH_NLRI:
ND_TCHECK_3(tptr);
if (tlen < 3)
goto trunc;
ret = bgp_mp_af_print(ndo, tptr, tlen, &af, &safi);
if (ret == -2)
goto trunc;
if (ret < 0)
break;
tptr += 3;
tlen -= 3;
ND_TCHECK_1(tptr);
if (tlen < 1)
goto trunc;
nhlen = GET_U_1(tptr);
tptr++;
tlen--;
if (nhlen) {
u_int nnh = 0;
uint8_t tnhlen = nhlen;
if (tlen < tnhlen)
goto trunc;
ND_PRINT("\n\t nexthop: ");
while (tnhlen != 0) {
if (nnh++ > 0) {
ND_PRINT(", " );
}
switch(af<<8 | safi) {
case (AFNUM_INET<<8 | SAFNUM_UNICAST):
case (AFNUM_INET<<8 | SAFNUM_MULTICAST):
case (AFNUM_INET<<8 | SAFNUM_UNIMULTICAST):
case (AFNUM_INET<<8 | SAFNUM_LABUNICAST):
case (AFNUM_INET<<8 | SAFNUM_RT_ROUTING_INFO):
case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN):
case (AFNUM_INET<<8 | SAFNUM_MDT):
if (tnhlen < sizeof(nd_ipv4)) {
ND_PRINT("invalid len");
tptr += tnhlen;
tlen -= tnhlen;
tnhlen = 0;
} else {
ND_PRINT("%s",GET_IPADDR_STRING(tptr));
tptr += sizeof(nd_ipv4);
tnhlen -= sizeof(nd_ipv4);
tlen -= sizeof(nd_ipv4);
}
break;
case (AFNUM_INET<<8 | SAFNUM_VPNUNICAST):
case (AFNUM_INET<<8 | SAFNUM_VPNMULTICAST):
case (AFNUM_INET<<8 | SAFNUM_VPNUNIMULTICAST):
if (tnhlen < sizeof(nd_ipv4)+BGP_VPN_RD_LEN) {
ND_PRINT("invalid len");
tptr += tnhlen;
tlen -= tnhlen;
tnhlen = 0;
} else {
ND_PRINT("RD: %s, %s",
bgp_vpn_rd_print(ndo, tptr),
GET_IPADDR_STRING(tptr+BGP_VPN_RD_LEN));
tptr += (sizeof(nd_ipv4)+BGP_VPN_RD_LEN);
tlen -= (sizeof(nd_ipv4)+BGP_VPN_RD_LEN);
tnhlen -= (sizeof(nd_ipv4)+BGP_VPN_RD_LEN);
}
break;
case (AFNUM_INET6<<8 | SAFNUM_UNICAST):
case (AFNUM_INET6<<8 | SAFNUM_MULTICAST):
case (AFNUM_INET6<<8 | SAFNUM_UNIMULTICAST):
case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST):
if (tnhlen < sizeof(nd_ipv6)) {
ND_PRINT("invalid len");
tptr += tnhlen;
tlen -= tnhlen;
tnhlen = 0;
} else {
ND_PRINT("%s", GET_IP6ADDR_STRING(tptr));
tptr += sizeof(nd_ipv6);
tlen -= sizeof(nd_ipv6);
tnhlen -= sizeof(nd_ipv6);
}
break;
case (AFNUM_INET6<<8 | SAFNUM_VPNUNICAST):
case (AFNUM_INET6<<8 | SAFNUM_VPNMULTICAST):
case (AFNUM_INET6<<8 | SAFNUM_VPNUNIMULTICAST):
if (tnhlen < sizeof(nd_ipv6)+BGP_VPN_RD_LEN) {
ND_PRINT("invalid len");
tptr += tnhlen;
tlen -= tnhlen;
tnhlen = 0;
} else {
ND_PRINT("RD: %s, %s",
bgp_vpn_rd_print(ndo, tptr),
GET_IP6ADDR_STRING(tptr+BGP_VPN_RD_LEN));
tptr += (sizeof(nd_ipv6)+BGP_VPN_RD_LEN);
tlen -= (sizeof(nd_ipv6)+BGP_VPN_RD_LEN);
tnhlen -= (sizeof(nd_ipv6)+BGP_VPN_RD_LEN);
}
break;
case (AFNUM_VPLS<<8 | SAFNUM_VPLS):
case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNICAST):
case (AFNUM_L2VPN<<8 | SAFNUM_VPNMULTICAST):
case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNIMULTICAST):
if (tnhlen < sizeof(nd_ipv4)) {
ND_PRINT("invalid len");
tptr += tnhlen;
tlen -= tnhlen;
tnhlen = 0;
} else {
ND_PRINT("%s", GET_IPADDR_STRING(tptr));
tptr += (sizeof(nd_ipv4));
tlen -= (sizeof(nd_ipv4));
tnhlen -= (sizeof(nd_ipv4));
}
break;
case (AFNUM_NSAP<<8 | SAFNUM_UNICAST):
case (AFNUM_NSAP<<8 | SAFNUM_MULTICAST):
case (AFNUM_NSAP<<8 | SAFNUM_UNIMULTICAST):
ND_PRINT("%s", GET_ISONSAP_STRING(tptr, tnhlen));
tptr += tnhlen;
tlen -= tnhlen;
tnhlen = 0;
break;
case (AFNUM_NSAP<<8 | SAFNUM_VPNUNICAST):
case (AFNUM_NSAP<<8 | SAFNUM_VPNMULTICAST):
case (AFNUM_NSAP<<8 | SAFNUM_VPNUNIMULTICAST):
if (tnhlen < BGP_VPN_RD_LEN+1) {
ND_PRINT("invalid len");
tptr += tnhlen;
tlen -= tnhlen;
tnhlen = 0;
} else {
ND_TCHECK_LEN(tptr, tnhlen);
ND_PRINT("RD: %s, %s",
bgp_vpn_rd_print(ndo, tptr),
GET_ISONSAP_STRING(tptr+BGP_VPN_RD_LEN,tnhlen-BGP_VPN_RD_LEN));
/* rfc986 mapped IPv4 address ? */
if (GET_BE_U_4(tptr + BGP_VPN_RD_LEN) == 0x47000601)
ND_PRINT(" = %s", GET_IPADDR_STRING(tptr+BGP_VPN_RD_LEN+4));
/* rfc1888 mapped IPv6 address ? */
else if (GET_BE_U_3(tptr + BGP_VPN_RD_LEN) == 0x350000)
ND_PRINT(" = %s", GET_IP6ADDR_STRING(tptr+BGP_VPN_RD_LEN+3));
tptr += tnhlen;
tlen -= tnhlen;
tnhlen = 0;
}
break;
default:
/*
* bgp_mp_af_print() should have saved us from
* an unsupported AFI/SAFI.
*/
ND_PRINT("ERROR: no AFI %u/SAFI %u nexthop decoder", af, safi);
tptr += tnhlen;
tlen -= tnhlen;
tnhlen = 0;
goto done;
break;
}
}
}
ND_PRINT(", nh-length: %u", nhlen);
/* As per RFC 2858; this is reserved in RFC 4760 */
if (tlen < 1)
goto trunc;
snpa = GET_U_1(tptr);
tptr++;
tlen--;
if (snpa) {
ND_PRINT("\n\t %u SNPA", snpa);
for (/*nothing*/; snpa != 0; snpa--) {
uint8_t snpalen;
if (tlen < 1)
goto trunc;
snpalen = GET_U_1(tptr);
ND_PRINT("\n\t %u bytes", snpalen);
tptr++;
tlen--;
if (tlen < snpalen)
goto trunc;
ND_TCHECK_LEN(tptr, snpalen);
tptr += snpalen;
tlen -= snpalen;
}
} else {
ND_PRINT(", no SNPA");
}
- add_path4 = check_add_path(ndo, tptr, (len-ND_BYTES_BETWEEN(tptr, pptr)), 32);
- add_path6 = check_add_path(ndo, tptr, (len-ND_BYTES_BETWEEN(tptr, pptr)), 128);
+ add_path4 = check_add_path(ndo, tptr,
+ (len-ND_BYTES_BETWEEN(pptr, tptr)), 32);
+ add_path6 = check_add_path(ndo, tptr,
+ (len-ND_BYTES_BETWEEN(pptr, tptr)), 128);
while (tptr < pptr + len) {
advance = bgp_nlri_print(ndo, af, safi, tptr, len, buf, sizeof(buf),
add_path4, add_path6);
if (advance == -2)
goto trunc;
if (advance < 0)
break;
tptr += advance;
}
break;
case BGPTYPE_MP_UNREACH_NLRI:
ND_TCHECK_LEN(tptr, BGP_MP_NLRI_MINSIZE);
ret = bgp_mp_af_print(ndo, tptr, tlen, &af, &safi);
if (ret == -2)
goto trunc;
if (ret < 0)
break;
if (len == BGP_MP_NLRI_MINSIZE)
ND_PRINT("\n\t End-of-Rib Marker (empty NLRI)");
tptr += 3;
- add_path4 = check_add_path(ndo, tptr, (len-ND_BYTES_BETWEEN(tptr, pptr)), 32);
- add_path6 = check_add_path(ndo, tptr, (len-ND_BYTES_BETWEEN(tptr, pptr)), 128);
+ add_path4 = check_add_path(ndo, tptr,
+ (len-ND_BYTES_BETWEEN(pptr, tptr)), 32);
+ add_path6 = check_add_path(ndo, tptr,
+ (len-ND_BYTES_BETWEEN(pptr, tptr)), 128);
while (tptr < pptr + len) {
advance = bgp_nlri_print(ndo, af, safi, tptr, len, buf, sizeof(buf),
add_path4, add_path6);
if (advance == -2)
goto trunc;
if (advance < 0)
break;
tptr += advance;
}
break;
case BGPTYPE_EXTD_COMMUNITIES:
if (len % 8) {
ND_PRINT("invalid len");
break;
}
while (tlen != 0) {
uint16_t extd_comm;
ND_TCHECK_2(tptr);
if (tlen < 2)
goto trunc;
extd_comm=GET_BE_U_2(tptr);
ND_PRINT("\n\t %s (0x%04x), Flags [%s]",
tok2str(bgp_extd_comm_subtype_values,
"unknown extd community typecode",
extd_comm),
extd_comm,
bittok2str(bgp_extd_comm_flag_values, "none", extd_comm));
ND_TCHECK_8(tptr);
if (tlen < 8)
goto trunc;
ND_PRINT(": ");
bgp_extended_community_print(ndo, tptr);
tlen -= 8;
tptr += 8;
}
break;
case BGPTYPE_PMSI_TUNNEL:
{
uint8_t tunnel_type, flags;
ND_TCHECK_5(tptr);
if (tlen < 5)
goto trunc;
flags = GET_U_1(tptr);
tunnel_type = GET_U_1(tptr + 1);
ND_PRINT("\n\t Tunnel-type %s (%u), Flags [%s], MPLS Label %u",
tok2str(bgp_pmsi_tunnel_values, "Unknown", tunnel_type),
tunnel_type,
bittok2str(bgp_pmsi_flag_values, "none", flags),
GET_BE_U_3(tptr + 2)>>4);
tptr +=5;
tlen -= 5;
switch (tunnel_type) {
case BGP_PMSI_TUNNEL_PIM_SM: /* fall through */
case BGP_PMSI_TUNNEL_PIM_BIDIR:
ND_PRINT("\n\t Sender %s, P-Group %s",
GET_IPADDR_STRING(tptr),
GET_IPADDR_STRING(tptr+4));
break;
case BGP_PMSI_TUNNEL_PIM_SSM:
ND_PRINT("\n\t Root-Node %s, P-Group %s",
GET_IPADDR_STRING(tptr),
GET_IPADDR_STRING(tptr+4));
break;
case BGP_PMSI_TUNNEL_INGRESS:
ND_PRINT("\n\t Tunnel-Endpoint %s",
GET_IPADDR_STRING(tptr));
break;
case BGP_PMSI_TUNNEL_LDP_P2MP: /* fall through */
case BGP_PMSI_TUNNEL_LDP_MP2MP:
ND_PRINT("\n\t Root-Node %s, LSP-ID 0x%08x",
GET_IPADDR_STRING(tptr),
GET_BE_U_4(tptr + 4));
break;
case BGP_PMSI_TUNNEL_RSVP_P2MP:
ND_PRINT("\n\t Extended-Tunnel-ID %s, P2MP-ID 0x%08x",
GET_IPADDR_STRING(tptr),
GET_BE_U_4(tptr + 4));
break;
default:
if (ndo->ndo_vflag <= 1) {
print_unknown_data(ndo, tptr, "\n\t ", tlen);
}
}
break;
}
case BGPTYPE_AIGP:
{
uint8_t type;
uint16_t length;
while (tlen >= 3) {
type = GET_U_1(tptr);
length = GET_BE_U_2(tptr + 1);
tptr += 3;
tlen -= 3;
ND_PRINT("\n\t %s TLV (%u), length %u",
tok2str(bgp_aigp_values, "Unknown", type),
type, length);
if (length < 3)
goto trunc;
length -= 3;
/*
* Check if we can read the TLV data.
*/
if (tlen < length)
goto trunc;
switch (type) {
case BGP_AIGP_TLV:
if (length < 8)
goto trunc;
ND_PRINT(", metric %" PRIu64,
GET_BE_U_8(tptr));
break;
default:
if (ndo->ndo_vflag <= 1) {
print_unknown_data(ndo, tptr,"\n\t ", length);
}
}
tptr += length;
tlen -= length;
}
break;
}
case BGPTYPE_ATTR_SET:
ND_TCHECK_4(tptr);
if (len < 4)
goto trunc;
ND_PRINT("\n\t Origin AS: %s",
as_printf(ndo, astostr, sizeof(astostr), GET_BE_U_4(tptr)));
tptr += 4;
len -= 4;
while (len) {
u_int aflags, alenlen, alen;
ND_TCHECK_2(tptr);
if (len < 2) {
ND_PRINT(" [path attr too short]");
tptr += len;
break;
}
aflags = GET_U_1(tptr);
atype = GET_U_1(tptr + 1);
tptr += 2;
len -= 2;
alenlen = bgp_attr_lenlen(aflags, tptr);
ND_TCHECK_LEN(tptr, alenlen);
if (len < alenlen) {
ND_PRINT(" [path attr too short]");
tptr += len;
break;
}
alen = bgp_attr_len(aflags, tptr);
tptr += alenlen;
len -= alenlen;
ND_PRINT("\n\t %s (%u), length: %u",
tok2str(bgp_attr_values,
"Unknown Attribute", atype),
atype,
alen);
if (aflags) {
ND_PRINT(", Flags [%s%s%s%s",
aflags & 0x80 ? "O" : "",
aflags & 0x40 ? "T" : "",
aflags & 0x20 ? "P" : "",
aflags & 0x10 ? "E" : "");
if (aflags & 0xf)
ND_PRINT("+%x", aflags & 0xf);
ND_PRINT("]");
}
ND_PRINT(": ");
if (len < alen) {
ND_PRINT(" [path attr too short]");
tptr += len;
break;
}
/*
* The protocol encoding per se allows ATTR_SET to be nested
* as many times as the message can accommodate. This printer
* used to be able to recurse into ATTR_SET contents until the
* stack exhaustion, but now there is a limit on that (if live
* protocol exchange goes that many levels deep, something is
* probably wrong anyway). Feel free to refine this value if
* you can find the spec with respective normative text.
*/
if (attr_set_level == 10)
ND_PRINT("(too many nested levels, not recursing)");
else if (!bgp_attr_print(ndo, atype, tptr, alen, attr_set_level + 1))
return 0;
tptr += alen;
len -= alen;
}
break;
case BGPTYPE_LARGE_COMMUNITY:
if (len == 0 || len % 12) {
ND_PRINT("invalid len");
break;
}
ND_PRINT("\n\t ");
while (len != 0) {
ND_PRINT("%u:%u:%u%s",
GET_BE_U_4(tptr),
GET_BE_U_4(tptr + 4),
GET_BE_U_4(tptr + 8),
(len > 12) ? ", " : "");
tptr += 12;
/*
* len will always be a multiple of 12, as per the above,
* so this will never underflow.
*/
len -= 12;
}
break;
default:
ND_TCHECK_LEN(pptr, len);
ND_PRINT("\n\t no Attribute %u decoder", atype); /* we have no decoder for the attribute */
if (ndo->ndo_vflag <= 1)
print_unknown_data(ndo, pptr, "\n\t ", len);
break;
}
done:
if (ndo->ndo_vflag > 1 && len) { /* omit zero length attributes*/
ND_TCHECK_LEN(pptr, len);
print_unknown_data(ndo, pptr, "\n\t ", len);
}
return 1;
trunc:
return 0;
}
static void
bgp_capabilities_print(netdissect_options *ndo,
const u_char *opt, u_int caps_len)
{
/* allocate space for the largest possible string */
char astostr[AS_STR_SIZE];
u_int cap_type, cap_len, tcap_len, cap_offset;
u_int i = 0;
while (i < caps_len) {
ND_TCHECK_LEN(opt + i, BGP_CAP_HEADER_SIZE);
cap_type=GET_U_1(opt + i);
cap_len=GET_U_1(opt + i + 1);
ND_PRINT("\n\t %s (%u), length: %u",
tok2str(bgp_capcode_values, "Unknown", cap_type),
cap_type,
cap_len);
ND_TCHECK_LEN(opt + 2 + i, cap_len);
switch (cap_type) {
case BGP_CAPCODE_MP:
/* AFI (16 bits), Reserved (8 bits), SAFI (8 bits) */
if (cap_len < 4) {
ND_PRINT(" (too short, < 4)");
return;
}
ND_PRINT("\n\t\tAFI %s (%u), SAFI %s (%u)",
tok2str(af_values, "Unknown", GET_BE_U_2(opt + i + 2)),
GET_BE_U_2(opt + i + 2),
tok2str(bgp_safi_values, "Unknown", GET_U_1(opt + i + 5)),
GET_U_1(opt + i + 5));
break;
case BGP_CAPCODE_ML:
cap_offset = 2;
tcap_len = cap_len;
while (tcap_len >= 4) {
ND_PRINT( "\n\t\tAFI %s (%u), SAFI %s (%u), Count: %u",
tok2str(af_values, "Unknown",
GET_BE_U_2(opt + i + cap_offset)),
GET_BE_U_2(opt + i + cap_offset),
tok2str(bgp_safi_values, "Unknown",
GET_U_1(opt + i + cap_offset + 2)),
GET_U_1(opt + i + cap_offset + 2),
GET_U_1(opt + i + cap_offset + 3));
tcap_len -= 4;
cap_offset += 4;
}
break;
case BGP_CAPCODE_RESTART:
/* Restart Flags (4 bits), Restart Time in seconds (12 bits) */
if (cap_len < 2) {
ND_PRINT(" (too short, < 2)");
return;
}
tcap_len=cap_len;
ND_PRINT("\n\t\tRestart Flags: [%s], Restart Time %us",
((GET_U_1(opt + i + 2))&0x80) ? "R" : "none",
GET_BE_U_2(opt + i + 2)&0xfff);
tcap_len-=2;
cap_offset=4;
while(tcap_len>=4) {
ND_PRINT("\n\t\t AFI %s (%u), SAFI %s (%u), Forwarding state preserved: %s",
tok2str(af_values,"Unknown",
GET_BE_U_2(opt + i + cap_offset)),
GET_BE_U_2(opt + i + cap_offset),
tok2str(bgp_safi_values,"Unknown",
GET_U_1(opt + i + cap_offset + 2)),
GET_U_1(opt + (i + cap_offset + 2)),
((GET_U_1(opt + (i + cap_offset + 3)))&0x80) ? "yes" : "no" );
tcap_len -= 4;
cap_offset += 4;
}
break;
case BGP_CAPCODE_RR:
case BGP_CAPCODE_LLGR:
case BGP_CAPCODE_RR_CISCO:
break;
case BGP_CAPCODE_AS_NEW:
/*
* Extract the 4 byte AS number encoded.
*/
if (cap_len < 4) {
ND_PRINT(" (too short, < 4)");
return;
}
ND_PRINT("\n\t\t 4 Byte AS %s",
as_printf(ndo, astostr, sizeof(astostr),
GET_BE_U_4(opt + i + 2)));
break;
case BGP_CAPCODE_ADD_PATH:
if (cap_len == 0) {
ND_PRINT(" (bogus)"); /* length */
break;
}
tcap_len=cap_len;
cap_offset=2;
while (tcap_len != 0) {
if (tcap_len < 4) {
nd_print_invalid(ndo);
break;
}
ND_PRINT("\n\t\tAFI %s (%u), SAFI %s (%u), Send/Receive: %s",
tok2str(af_values,"Unknown",GET_BE_U_2(opt + i + cap_offset)),
GET_BE_U_2(opt + i + cap_offset),
tok2str(bgp_safi_values,"Unknown",GET_U_1(opt + i + cap_offset + 2)),
GET_U_1(opt + (i + cap_offset + 2)),
tok2str(bgp_add_path_recvsend,"Bogus (0x%02x)",GET_U_1(opt + i + cap_offset + 3))
);
tcap_len -= 4;
cap_offset += 4;
}
break;
default:
ND_PRINT("\n\t\tno decoder for Capability %u",
cap_type);
if (ndo->ndo_vflag <= 1)
print_unknown_data(ndo, opt + i + 2, "\n\t\t",
cap_len);
break;
}
if (ndo->ndo_vflag > 1 && cap_len != 0) {
print_unknown_data(ndo, opt + i + 2, "\n\t\t", cap_len);
}
i += BGP_CAP_HEADER_SIZE + cap_len;
}
return;
trunc:
nd_print_trunc(ndo);
}
static void
bgp_open_print(netdissect_options *ndo,
const u_char *dat, u_int length)
{
/* allocate space for the largest possible string */
char astostr[AS_STR_SIZE];
const struct bgp_open *bgp_open_header;
u_int optslen;
const struct bgp_opt *bgpopt;
const u_char *opt;
u_int i;
ND_TCHECK_LEN(dat, BGP_OPEN_SIZE);
if (length < BGP_OPEN_SIZE)
goto trunc;
bgp_open_header = (const struct bgp_open *)dat;
ND_PRINT("\n\t Version %u, ",
GET_U_1(bgp_open_header->bgpo_version));
ND_PRINT("my AS %s, ",
as_printf(ndo, astostr, sizeof(astostr), GET_BE_U_2(bgp_open_header->bgpo_myas)));
ND_PRINT("Holdtime %us, ",
GET_BE_U_2(bgp_open_header->bgpo_holdtime));
ND_PRINT("ID %s", GET_IPADDR_STRING(bgp_open_header->bgpo_id));
optslen = GET_U_1(bgp_open_header->bgpo_optlen);
ND_PRINT("\n\t Optional parameters, length: %u", optslen);
opt = dat + BGP_OPEN_SIZE;
length -= BGP_OPEN_SIZE;
i = 0;
while (i < optslen) {
uint8_t opt_type, opt_len;
ND_TCHECK_LEN(opt + i, BGP_OPT_SIZE);
if (length < BGP_OPT_SIZE + i)
goto trunc;
bgpopt = (const struct bgp_opt *)(opt + i);
opt_type = GET_U_1(bgpopt->bgpopt_type);
opt_len = GET_U_1(bgpopt->bgpopt_len);
if (BGP_OPT_SIZE + i + opt_len > optslen) {
ND_PRINT("\n\t Option %u, length: %u, goes past the end of the options",
opt_type, opt_len);
break;
}
ND_PRINT("\n\t Option %s (%u), length: %u",
tok2str(bgp_opt_values,"Unknown",opt_type),
opt_type,
opt_len);
/* now let's decode the options we know*/
switch(opt_type) {
case BGP_OPT_CAP:
bgp_capabilities_print(ndo, opt + BGP_OPT_SIZE + i,
opt_len);
break;
case BGP_OPT_AUTH:
default:
ND_PRINT("\n\t no decoder for option %u",
opt_type);
break;
}
i += BGP_OPT_SIZE + opt_len;
}
return;
trunc:
nd_print_trunc(ndo);
}
static void
bgp_update_print(netdissect_options *ndo,
const u_char *dat, u_int length)
{
const u_char *p;
u_int withdrawn_routes_len;
char buf[MAXHOSTNAMELEN + 100];
int wpfx;
u_int len;
int i;
int add_path;
u_int path_id = 0;
ND_TCHECK_LEN(dat, BGP_SIZE);
if (length < BGP_SIZE)
goto trunc;
p = dat + BGP_SIZE;
length -= BGP_SIZE;
/* Unfeasible routes */
ND_TCHECK_2(p);
if (length < 2)
goto trunc;
withdrawn_routes_len = GET_BE_U_2(p);
p += 2;
length -= 2;
if (withdrawn_routes_len > 1) {
/*
* Without keeping state from the original NLRI message,
* it's not possible to tell if this a v4 or v6 route,
* so only try to decode it if we're not v6 enabled.
*/
ND_TCHECK_LEN(p, withdrawn_routes_len);
if (length < withdrawn_routes_len)
goto trunc;
ND_PRINT("\n\t Withdrawn routes:");
add_path = check_add_path(ndo, p, withdrawn_routes_len, 32);
while (withdrawn_routes_len != 0) {
if (add_path) {
if (withdrawn_routes_len < 4) {
p += withdrawn_routes_len;
length -= withdrawn_routes_len;
break;
}
path_id = GET_BE_U_4(p);
p += 4;
length -= 4;
withdrawn_routes_len -= 4;
}
wpfx = decode_prefix4(ndo, p, withdrawn_routes_len, buf, sizeof(buf));
if (wpfx == -1) {
ND_PRINT("\n\t (illegal prefix length)");
break;
} else if (wpfx == -2)
goto trunc; /* bytes left, but not enough */
else {
ND_PRINT("\n\t %s", buf);
if (add_path) {
ND_PRINT(" Path Id: %u", path_id);
}
p += wpfx;
length -= wpfx;
withdrawn_routes_len -= wpfx;
}
}
} else {
ND_TCHECK_LEN(p, withdrawn_routes_len);
if (length < withdrawn_routes_len)
goto trunc;
p += withdrawn_routes_len;
length -= withdrawn_routes_len;
}
ND_TCHECK_2(p);
if (length < 2)
goto trunc;
len = GET_BE_U_2(p);
p += 2;
length -= 2;
if (withdrawn_routes_len == 0 && len == 0 && length == 0) {
/* No withdrawn routes, no path attributes, no NLRI */
ND_PRINT("\n\t End-of-Rib Marker (empty NLRI)");
return;
}
if (len) {
/* Make sure the path attributes don't go past the end of the packet */
if (length < len)
goto trunc;
/* do something more useful!*/
while (len) {
uint8_t aflags, atype, alenlen;
uint16_t alen;
ND_TCHECK_2(p);
if (length < 2)
goto trunc;
if (len < 2) {
ND_PRINT("\n\t [path attrs too short]");
p += len;
length -= len;
break;
}
aflags = GET_U_1(p);
atype = GET_U_1(p + 1);
p += 2;
len -= 2;
length -= 2;
alenlen = bgp_attr_lenlen(aflags, p);
ND_TCHECK_LEN(p, alenlen);
if (length < alenlen)
goto trunc;
if (len < alenlen) {
ND_PRINT("\n\t [path attrs too short]");
p += len;
length -= len;
break;
}
alen = bgp_attr_len(aflags, p);
p += alenlen;
len -= alenlen;
length -= alenlen;
ND_PRINT("\n\t %s (%u), length: %u",
tok2str(bgp_attr_values, "Unknown Attribute", atype),
atype,
alen);
if (aflags) {
ND_PRINT(", Flags [%s%s%s%s",
aflags & 0x80 ? "O" : "",
aflags & 0x40 ? "T" : "",
aflags & 0x20 ? "P" : "",
aflags & 0x10 ? "E" : "");
if (aflags & 0xf)
ND_PRINT("+%x", aflags & 0xf);
ND_PRINT("]: ");
}
if (len < alen) {
ND_PRINT(" [path attrs too short]");
p += len;
length -= len;
break;
}
if (length < alen)
goto trunc;
if (!bgp_attr_print(ndo, atype, p, alen, 0))
goto trunc;
p += alen;
len -= alen;
length -= alen;
}
}
if (length) {
add_path = check_add_path(ndo, p, length, 32);
ND_PRINT("\n\t Updated routes:");
while (length != 0) {
if (add_path) {
ND_TCHECK_4(p);
if (length < 4)
goto trunc;
path_id = GET_BE_U_4(p);
p += 4;
length -= 4;
}
i = decode_prefix4(ndo, p, length, buf, sizeof(buf));
if (i == -1) {
ND_PRINT("\n\t (illegal prefix length)");
break;
} else if (i == -2)
goto trunc; /* bytes left, but not enough */
else {
ND_PRINT("\n\t %s", buf);
if (add_path) {
ND_PRINT(" Path Id: %u", path_id);
}
p += i;
length -= i;
}
}
}
return;
trunc:
nd_print_trunc(ndo);
}
static void
bgp_notification_print(netdissect_options *ndo,
const u_char *dat, u_int length)
{
const struct bgp_notification *bgp_notification_header;
const u_char *tptr;
uint8_t bgpn_major, bgpn_minor;
ND_TCHECK_LEN(dat, BGP_NOTIFICATION_SIZE);
if (length<BGP_NOTIFICATION_SIZE)
return;
bgp_notification_header = (const struct bgp_notification *)dat;
bgpn_major = GET_U_1(bgp_notification_header->bgpn_major);
bgpn_minor = GET_U_1(bgp_notification_header->bgpn_minor);
ND_PRINT(", %s (%u)",
tok2str(bgp_notify_major_values, "Unknown Error",
bgpn_major),
bgpn_major);
switch (bgpn_major) {
case BGP_NOTIFY_MAJOR_MSG:
ND_PRINT(", subcode %s (%u)",
tok2str(bgp_notify_minor_msg_values, "Unknown",
bgpn_minor),
bgpn_minor);
break;
case BGP_NOTIFY_MAJOR_OPEN:
ND_PRINT(", subcode %s (%u)",
tok2str(bgp_notify_minor_open_values, "Unknown",
bgpn_minor),
bgpn_minor);
break;
case BGP_NOTIFY_MAJOR_UPDATE:
ND_PRINT(", subcode %s (%u)",
tok2str(bgp_notify_minor_update_values, "Unknown",
bgpn_minor),
bgpn_minor);
break;
case BGP_NOTIFY_MAJOR_FSM:
ND_PRINT(" subcode %s (%u)",
tok2str(bgp_notify_minor_fsm_values, "Unknown",
bgpn_minor),
bgpn_minor);
break;
case BGP_NOTIFY_MAJOR_CAP:
ND_PRINT(" subcode %s (%u)",
tok2str(bgp_notify_minor_cap_values, "Unknown",
bgpn_minor),
bgpn_minor);
break;
case BGP_NOTIFY_MAJOR_CEASE:
ND_PRINT(", subcode %s (%u)",
tok2str(bgp_notify_minor_cease_values, "Unknown",
bgpn_minor),
bgpn_minor);
/* RFC 4486 mentions optionally 7 bytes
* for the maxprefix subtype, which may contain AFI, SAFI and MAXPREFIXES
*/
if(bgpn_minor == BGP_NOTIFY_MINOR_CEASE_MAXPRFX && length >= BGP_NOTIFICATION_SIZE + 7) {
tptr = dat + BGP_NOTIFICATION_SIZE;
ND_PRINT(", AFI %s (%u), SAFI %s (%u), Max Prefixes: %u",
tok2str(af_values, "Unknown", GET_BE_U_2(tptr)),
GET_BE_U_2(tptr),
tok2str(bgp_safi_values, "Unknown", GET_U_1((tptr + 2))),
GET_U_1((tptr + 2)),
GET_BE_U_4(tptr + 3));
}
/*
* RFC 9003 describes a method to send a communication
* intended for human consumption regarding the Administrative Shutdown
*/
if ((bgpn_minor == BGP_NOTIFY_MINOR_CEASE_SHUT ||
bgpn_minor == BGP_NOTIFY_MINOR_CEASE_RESET) &&
length >= BGP_NOTIFICATION_SIZE + 1) {
tptr = dat + BGP_NOTIFICATION_SIZE;
uint8_t shutdown_comm_length = GET_U_1(tptr);
uint8_t remainder_offset = 0;
/* garbage, hexdump it all */
if (shutdown_comm_length > length - (BGP_NOTIFICATION_SIZE + 1)) {
ND_PRINT(", invalid Shutdown Communication length");
- }
- else if (shutdown_comm_length == 0) {
+ } else if (shutdown_comm_length == 0) {
ND_PRINT(", empty Shutdown Communication");
remainder_offset += 1;
}
/* a proper shutdown communication */
else {
ND_PRINT(", Shutdown Communication (length: %u): \"", shutdown_comm_length);
(void)nd_printn(ndo, tptr+1, shutdown_comm_length, NULL);
ND_PRINT("\"");
remainder_offset += shutdown_comm_length + 1;
}
/* if there is trailing data, hexdump it */
if(length - (remainder_offset + BGP_NOTIFICATION_SIZE) > 0) {
ND_PRINT(", Data: (length: %u)", length - (remainder_offset + BGP_NOTIFICATION_SIZE));
hex_print(ndo, "\n\t\t", tptr + remainder_offset, length - (remainder_offset + BGP_NOTIFICATION_SIZE));
}
}
break;
default:
break;
}
return;
trunc:
nd_print_trunc(ndo);
}
static void
bgp_route_refresh_print(netdissect_options *ndo,
const u_char *pptr, u_int len)
{
const struct bgp_route_refresh *bgp_route_refresh_header;
ND_TCHECK_LEN(pptr, BGP_ROUTE_REFRESH_SIZE);
/* some little sanity checking */
if (len<BGP_ROUTE_REFRESH_SIZE)
return;
bgp_route_refresh_header = (const struct bgp_route_refresh *)pptr;
ND_PRINT("\n\t AFI %s (%u), SAFI %s (%u)",
tok2str(af_values,"Unknown",
GET_BE_U_2(bgp_route_refresh_header->afi)),
GET_BE_U_2(bgp_route_refresh_header->afi),
tok2str(bgp_safi_values,"Unknown",
GET_U_1(bgp_route_refresh_header->safi)),
GET_U_1(bgp_route_refresh_header->safi));
if (ndo->ndo_vflag > 1) {
ND_TCHECK_LEN(pptr, len);
print_unknown_data(ndo, pptr, "\n\t ", len);
}
return;
trunc:
nd_print_trunc(ndo);
}
static int
bgp_pdu_print(netdissect_options *ndo,
const u_char *dat, u_int length)
{
const struct bgp *bgp_header;
uint8_t bgp_type;
ND_TCHECK_LEN(dat, BGP_SIZE);
bgp_header = (const struct bgp *)dat;
bgp_type = GET_U_1(bgp_header->bgp_type);
ND_PRINT("\n\t%s Message (%u), length: %u",
tok2str(bgp_msg_values, "Unknown", bgp_type),
bgp_type,
length);
switch (bgp_type) {
case BGP_OPEN:
bgp_open_print(ndo, dat, length);
break;
case BGP_UPDATE:
bgp_update_print(ndo, dat, length);
break;
case BGP_NOTIFICATION:
bgp_notification_print(ndo, dat, length);
break;
case BGP_KEEPALIVE:
break;
case BGP_ROUTE_REFRESH:
bgp_route_refresh_print(ndo, dat, length);
break;
default:
/* we have no decoder for the BGP message */
ND_TCHECK_LEN(dat, length);
ND_PRINT("\n\t no Message %u decoder", bgp_type);
print_unknown_data(ndo, dat, "\n\t ", length);
break;
}
return 1;
trunc:
nd_print_trunc(ndo);
return 0;
}
void
bgp_print(netdissect_options *ndo,
const u_char *dat, u_int length _U_)
{
const u_char *p;
const u_char *ep = ndo->ndo_snapend;
const u_char *start;
const u_char marker[] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
};
const struct bgp *bgp_header;
uint16_t hlen;
ndo->ndo_protocol = "bgp";
ND_PRINT(": BGP");
if (ndo->ndo_vflag < 1) /* lets be less chatty */
return;
p = dat;
start = p;
while (p < ep) {
if (!ND_TTEST_1(p))
break;
if (GET_U_1(p) != 0xff) {
p++;
continue;
}
if (!ND_TTEST_LEN(p, sizeof(marker)))
break;
if (memcmp(p, marker, sizeof(marker)) != 0) {
p++;
continue;
}
/* found BGP header */
ND_TCHECK_LEN(p, BGP_SIZE);
bgp_header = (const struct bgp *)p;
if (start != p)
nd_print_trunc(ndo);
hlen = GET_BE_U_2(bgp_header->bgp_len);
if (hlen < BGP_SIZE) {
ND_PRINT("\nmessage length %u < %u", hlen, BGP_SIZE);
nd_print_invalid(ndo);
break;
}
if (ND_TTEST_LEN(p, hlen)) {
if (!bgp_pdu_print(ndo, p, hlen))
return;
p += hlen;
start = p;
} else {
ND_PRINT("\n[|BGP %s]",
tok2str(bgp_msg_values,
"Unknown Message Type",
GET_U_1(bgp_header->bgp_type)));
break;
}
}
return;
trunc:
nd_print_trunc(ndo);
}
diff --git a/contrib/tcpdump/print-bootp.c b/contrib/tcpdump/print-bootp.c
index d230a24cbf83..b20dabc64052 100644
--- a/contrib/tcpdump/print-bootp.c
+++ b/contrib/tcpdump/print-bootp.c
@@ -1,1074 +1,1109 @@
/*
* 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.
*/
/* \summary: BOOTP and IPv4 DHCP printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <string.h>
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
/*
* Bootstrap Protocol (BOOTP). RFC951 and RFC1048.
*
* This file specifies the "implementation-independent" BOOTP protocol
* information which is common to both client and server.
*
* Copyright 1988 by Carnegie Mellon.
*
* Permission to use, copy, modify, and distribute this program for any
* purpose and without fee is hereby granted, provided that this copyright
* and permission notice appear on all copies and supporting documentation,
* the name of Carnegie Mellon not be used in advertising or publicity
* pertaining to distribution of the program without specific prior
* permission, and notice be given in supporting documentation that copying
* and distribution is by permission of Carnegie Mellon and Stanford
* University. Carnegie Mellon makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*/
struct bootp {
nd_uint8_t bp_op; /* packet opcode type */
nd_uint8_t bp_htype; /* hardware addr type */
nd_uint8_t bp_hlen; /* hardware addr length */
nd_uint8_t bp_hops; /* gateway hops */
nd_uint32_t bp_xid; /* transaction ID */
nd_uint16_t bp_secs; /* seconds since boot began */
nd_uint16_t bp_flags; /* flags - see bootp_flag_values[]
in print-bootp.c */
nd_ipv4 bp_ciaddr; /* client IP address */
nd_ipv4 bp_yiaddr; /* 'your' IP address */
nd_ipv4 bp_siaddr; /* server IP address */
nd_ipv4 bp_giaddr; /* gateway IP address */
nd_byte bp_chaddr[16]; /* client hardware address */
nd_byte bp_sname[64]; /* server host name */
nd_byte bp_file[128]; /* boot file name */
nd_byte bp_vend[64]; /* vendor-specific area */
};
#define BOOTPREPLY 2
#define BOOTPREQUEST 1
/*
* Vendor magic cookie (v_magic) for CMU
*/
#define VM_CMU "CMU"
/*
* Vendor magic cookie (v_magic) for RFC1048
*/
#define VM_RFC1048 { 99, 130, 83, 99 }
/*
* RFC1048 tag values used to specify what information is being supplied in
* the vendor field of the packet.
*/
#define TAG_PAD ((uint8_t) 0)
#define TAG_SUBNET_MASK ((uint8_t) 1)
#define TAG_TIME_OFFSET ((uint8_t) 2)
#define TAG_GATEWAY ((uint8_t) 3)
#define TAG_TIME_SERVER ((uint8_t) 4)
#define TAG_NAME_SERVER ((uint8_t) 5)
#define TAG_DOMAIN_SERVER ((uint8_t) 6)
#define TAG_LOG_SERVER ((uint8_t) 7)
#define TAG_COOKIE_SERVER ((uint8_t) 8)
#define TAG_LPR_SERVER ((uint8_t) 9)
#define TAG_IMPRESS_SERVER ((uint8_t) 10)
#define TAG_RLP_SERVER ((uint8_t) 11)
#define TAG_HOSTNAME ((uint8_t) 12)
#define TAG_BOOTSIZE ((uint8_t) 13)
#define TAG_END ((uint8_t) 255)
/* RFC1497 tags */
#define TAG_DUMPPATH ((uint8_t) 14)
#define TAG_DOMAINNAME ((uint8_t) 15)
#define TAG_SWAP_SERVER ((uint8_t) 16)
#define TAG_ROOTPATH ((uint8_t) 17)
#define TAG_EXTPATH ((uint8_t) 18)
/* RFC2132 */
#define TAG_IP_FORWARD ((uint8_t) 19)
#define TAG_NL_SRCRT ((uint8_t) 20)
#define TAG_PFILTERS ((uint8_t) 21)
#define TAG_REASS_SIZE ((uint8_t) 22)
#define TAG_DEF_TTL ((uint8_t) 23)
#define TAG_MTU_TIMEOUT ((uint8_t) 24)
#define TAG_MTU_TABLE ((uint8_t) 25)
#define TAG_INT_MTU ((uint8_t) 26)
#define TAG_LOCAL_SUBNETS ((uint8_t) 27)
#define TAG_BROAD_ADDR ((uint8_t) 28)
#define TAG_DO_MASK_DISC ((uint8_t) 29)
#define TAG_SUPPLY_MASK ((uint8_t) 30)
#define TAG_DO_RDISC ((uint8_t) 31)
#define TAG_RTR_SOL_ADDR ((uint8_t) 32)
#define TAG_STATIC_ROUTE ((uint8_t) 33)
#define TAG_USE_TRAILERS ((uint8_t) 34)
#define TAG_ARP_TIMEOUT ((uint8_t) 35)
#define TAG_ETH_ENCAP ((uint8_t) 36)
#define TAG_TCP_TTL ((uint8_t) 37)
#define TAG_TCP_KEEPALIVE ((uint8_t) 38)
#define TAG_KEEPALIVE_GO ((uint8_t) 39)
#define TAG_NIS_DOMAIN ((uint8_t) 40)
#define TAG_NIS_SERVERS ((uint8_t) 41)
#define TAG_NTP_SERVERS ((uint8_t) 42)
#define TAG_VENDOR_OPTS ((uint8_t) 43)
#define TAG_NETBIOS_NS ((uint8_t) 44)
#define TAG_NETBIOS_DDS ((uint8_t) 45)
#define TAG_NETBIOS_NODE ((uint8_t) 46)
#define TAG_NETBIOS_SCOPE ((uint8_t) 47)
#define TAG_XWIN_FS ((uint8_t) 48)
#define TAG_XWIN_DM ((uint8_t) 49)
#define TAG_NIS_P_DOMAIN ((uint8_t) 64)
#define TAG_NIS_P_SERVERS ((uint8_t) 65)
#define TAG_MOBILE_HOME ((uint8_t) 68)
-#define TAG_SMPT_SERVER ((uint8_t) 69)
+#define TAG_SMTP_SERVER ((uint8_t) 69)
#define TAG_POP3_SERVER ((uint8_t) 70)
#define TAG_NNTP_SERVER ((uint8_t) 71)
#define TAG_WWW_SERVER ((uint8_t) 72)
#define TAG_FINGER_SERVER ((uint8_t) 73)
#define TAG_IRC_SERVER ((uint8_t) 74)
#define TAG_STREETTALK_SRVR ((uint8_t) 75)
#define TAG_STREETTALK_STDA ((uint8_t) 76)
/* DHCP options */
#define TAG_REQUESTED_IP ((uint8_t) 50)
#define TAG_IP_LEASE ((uint8_t) 51)
#define TAG_OPT_OVERLOAD ((uint8_t) 52)
#define TAG_TFTP_SERVER ((uint8_t) 66)
#define TAG_BOOTFILENAME ((uint8_t) 67)
#define TAG_DHCP_MESSAGE ((uint8_t) 53)
#define TAG_SERVER_ID ((uint8_t) 54)
#define TAG_PARM_REQUEST ((uint8_t) 55)
#define TAG_MESSAGE ((uint8_t) 56)
#define TAG_MAX_MSG_SIZE ((uint8_t) 57)
#define TAG_RENEWAL_TIME ((uint8_t) 58)
#define TAG_REBIND_TIME ((uint8_t) 59)
#define TAG_VENDOR_CLASS ((uint8_t) 60)
#define TAG_CLIENT_ID ((uint8_t) 61)
/* RFC 2241 */
#define TAG_NDS_SERVERS ((uint8_t) 85)
#define TAG_NDS_TREE_NAME ((uint8_t) 86)
#define TAG_NDS_CONTEXT ((uint8_t) 87)
/* RFC 2242 */
#define TAG_NDS_IPDOMAIN ((uint8_t) 62)
#define TAG_NDS_IPINFO ((uint8_t) 63)
/* RFC 2485 */
#define TAG_OPEN_GROUP_UAP ((uint8_t) 98)
/* RFC 2563 */
#define TAG_DISABLE_AUTOCONF ((uint8_t) 116)
/* RFC 2610 */
#define TAG_SLP_DA ((uint8_t) 78)
#define TAG_SLP_SCOPE ((uint8_t) 79)
/* RFC 2937 */
#define TAG_NS_SEARCH ((uint8_t) 117)
/* RFC 3004 - The User Class Option for DHCP */
#define TAG_USER_CLASS ((uint8_t) 77)
/* RFC 3011 */
#define TAG_IP4_SUBNET_SELECT ((uint8_t) 118)
/* RFC 3442 */
#define TAG_CLASSLESS_STATIC_RT ((uint8_t) 121)
#define TAG_CLASSLESS_STA_RT_MS ((uint8_t) 249)
+/* RFC8572 */
+#define TAG_SZTP_REDIRECT ((uint8_t) 143)
/* RFC 5859 - TFTP Server Address Option for DHCPv4 */
#define TAG_TFTP_SERVER_ADDRESS ((uint8_t) 150)
/* https://www.iana.org/assignments/bootp-dhcp-parameters/bootp-dhcp-parameters.xhtml */
#define TAG_SLP_NAMING_AUTH ((uint8_t) 80)
#define TAG_CLIENT_FQDN ((uint8_t) 81)
#define TAG_AGENT_CIRCUIT ((uint8_t) 82)
#define TAG_AGENT_REMOTE ((uint8_t) 83)
#define TAG_TZ_STRING ((uint8_t) 88)
#define TAG_FQDN_OPTION ((uint8_t) 89)
#define TAG_AUTH ((uint8_t) 90)
#define TAG_CLIENT_LAST_TRANSACTION_TIME ((uint8_t) 91)
#define TAG_ASSOCIATED_IP ((uint8_t) 92)
#define TAG_CLIENT_ARCH ((uint8_t) 93)
#define TAG_CLIENT_NDI ((uint8_t) 94)
#define TAG_CLIENT_GUID ((uint8_t) 97)
#define TAG_LDAP_URL ((uint8_t) 95)
/* RFC 4833, TZ codes */
#define TAG_TZ_PCODE ((uint8_t) 100)
#define TAG_TZ_TCODE ((uint8_t) 101)
#define TAG_NETINFO_PARENT ((uint8_t) 112)
#define TAG_NETINFO_PARENT_TAG ((uint8_t) 113)
#define TAG_URL ((uint8_t) 114)
#define TAG_MUDURL ((uint8_t) 161)
/* DHCP Message types (values for TAG_DHCP_MESSAGE option) */
#define DHCPDISCOVER 1
#define DHCPOFFER 2
#define DHCPREQUEST 3
#define DHCPDECLINE 4
#define DHCPACK 5
#define DHCPNAK 6
#define DHCPRELEASE 7
#define DHCPINFORM 8
/* Defined in RFC4388 */
#define DHCPLEASEQUERY 10
#define DHCPLEASEUNASSIGNED 11
#define DHCPLEASEUNKNOWN 12
#define DHCPLEASEACTIVE 13
/*
* "vendor" data permitted for CMU bootp clients.
*/
struct cmu_vend {
nd_byte v_magic[4]; /* magic number */
nd_uint32_t v_flags; /* flags/opcodes, etc. */
nd_ipv4 v_smask; /* Subnet mask */
nd_ipv4 v_dgate; /* Default gateway */
nd_ipv4 v_dns1, v_dns2; /* Domain name servers */
nd_ipv4 v_ins1, v_ins2; /* IEN-116 name servers */
nd_ipv4 v_ts1, v_ts2; /* Time servers */
nd_byte v_unused[24]; /* currently unused */
};
/* v_flags values */
#define VF_SMASK 1 /* Subnet mask field contains valid data */
/* RFC 4702 DHCP Client FQDN Option */
#define CLIENT_FQDN_FLAGS_S 0x01
#define CLIENT_FQDN_FLAGS_O 0x02
#define CLIENT_FQDN_FLAGS_E 0x04
#define CLIENT_FQDN_FLAGS_N 0x08
/* end of original bootp.h */
static void rfc1048_print(netdissect_options *, const u_char *);
static void cmu_print(netdissect_options *, const u_char *);
static char *client_fqdn_flags(u_int flags);
static const struct tok bootp_flag_values[] = {
{ 0x8000, "Broadcast" },
{ 0, NULL}
};
static const struct tok bootp_op_values[] = {
{ BOOTPREQUEST, "Request" },
{ BOOTPREPLY, "Reply" },
{ 0, NULL}
};
/*
* Print bootp requests
*/
void
bootp_print(netdissect_options *ndo,
const u_char *cp, u_int length)
{
const struct bootp *bp;
static const u_char vm_cmu[4] = VM_CMU;
static const u_char vm_rfc1048[4] = VM_RFC1048;
uint8_t bp_op, bp_htype, bp_hlen;
ndo->ndo_protocol = "bootp";
bp = (const struct bootp *)cp;
bp_op = GET_U_1(bp->bp_op);
ND_PRINT("BOOTP/DHCP, %s",
tok2str(bootp_op_values, "unknown (0x%02x)", bp_op));
bp_htype = GET_U_1(bp->bp_htype);
bp_hlen = GET_U_1(bp->bp_hlen);
if (bp_htype == 1 && bp_hlen == MAC_ADDR_LEN && bp_op == BOOTPREQUEST) {
ND_PRINT(" from %s", GET_ETHERADDR_STRING(bp->bp_chaddr));
}
ND_PRINT(", length %u", length);
if (!ndo->ndo_vflag)
return;
ND_TCHECK_2(bp->bp_secs);
/* The usual hardware address type is 1 (10Mb Ethernet) */
if (bp_htype != 1)
ND_PRINT(", htype %u", bp_htype);
/* The usual length for 10Mb Ethernet address is 6 bytes */
if (bp_htype != 1 || bp_hlen != MAC_ADDR_LEN)
ND_PRINT(", hlen %u", bp_hlen);
/* Only print interesting fields */
if (GET_U_1(bp->bp_hops))
ND_PRINT(", hops %u", GET_U_1(bp->bp_hops));
if (GET_BE_U_4(bp->bp_xid))
ND_PRINT(", xid 0x%x", GET_BE_U_4(bp->bp_xid));
if (GET_BE_U_2(bp->bp_secs))
ND_PRINT(", secs %u", GET_BE_U_2(bp->bp_secs));
ND_PRINT(", Flags [%s]",
bittok2str(bootp_flag_values, "none", GET_BE_U_2(bp->bp_flags)));
if (ndo->ndo_vflag > 1)
ND_PRINT(" (0x%04x)", GET_BE_U_2(bp->bp_flags));
/* Client's ip address */
if (GET_IPV4_TO_NETWORK_ORDER(bp->bp_ciaddr))
ND_PRINT("\n\t Client-IP %s", GET_IPADDR_STRING(bp->bp_ciaddr));
/* 'your' ip address (bootp client) */
if (GET_IPV4_TO_NETWORK_ORDER(bp->bp_yiaddr))
ND_PRINT("\n\t Your-IP %s", GET_IPADDR_STRING(bp->bp_yiaddr));
/* Server's ip address */
if (GET_IPV4_TO_NETWORK_ORDER(bp->bp_siaddr))
ND_PRINT("\n\t Server-IP %s", GET_IPADDR_STRING(bp->bp_siaddr));
/* Gateway's ip address */
if (GET_IPV4_TO_NETWORK_ORDER(bp->bp_giaddr))
ND_PRINT("\n\t Gateway-IP %s", GET_IPADDR_STRING(bp->bp_giaddr));
/* Client's Ethernet address */
if (bp_htype == 1 && bp_hlen == MAC_ADDR_LEN) {
ND_PRINT("\n\t Client-Ethernet-Address %s", GET_ETHERADDR_STRING(bp->bp_chaddr));
}
if (GET_U_1(bp->bp_sname)) { /* get first char only */
ND_PRINT("\n\t sname \"");
if (nd_printztn(ndo, bp->bp_sname, (u_int)sizeof(bp->bp_sname),
ndo->ndo_snapend) == 0) {
ND_PRINT("\"");
nd_print_trunc(ndo);
return;
}
ND_PRINT("\"");
}
if (GET_U_1(bp->bp_file)) { /* get first char only */
ND_PRINT("\n\t file \"");
if (nd_printztn(ndo, bp->bp_file, (u_int)sizeof(bp->bp_file),
ndo->ndo_snapend) == 0) {
ND_PRINT("\"");
nd_print_trunc(ndo);
return;
}
ND_PRINT("\"");
}
/* Decode the vendor buffer */
ND_TCHECK_4(bp->bp_vend);
if (memcmp((const char *)bp->bp_vend, vm_rfc1048,
sizeof(uint32_t)) == 0)
rfc1048_print(ndo, bp->bp_vend);
else if (memcmp((const char *)bp->bp_vend, vm_cmu,
sizeof(uint32_t)) == 0)
cmu_print(ndo, bp->bp_vend);
else {
uint32_t ul;
ul = GET_BE_U_4(bp->bp_vend);
if (ul != 0)
ND_PRINT("\n\t Vendor-#0x%x", ul);
}
return;
trunc:
nd_print_trunc(ndo);
}
/*
* The first character specifies the format to print:
* i - ip address (32 bits)
* p - ip address pairs (32 bits + 32 bits)
* l - long (32 bits)
* L - unsigned long (32 bits)
* s - short (16 bits)
* b - period-separated decimal bytes (variable length)
* x - colon-separated hex bytes (variable length)
* a - ASCII string (variable length)
* B - on/off (8 bits)
* $ - special (explicit code to handle)
*/
static const struct tok tag2str[] = {
/* RFC1048 tags */
{ TAG_PAD, " PAD" },
{ TAG_SUBNET_MASK, "iSubnet-Mask" }, /* subnet mask (RFC950) */
{ TAG_TIME_OFFSET, "LTime-Zone" }, /* seconds from UTC */
{ TAG_GATEWAY, "iDefault-Gateway" }, /* default gateway */
{ TAG_TIME_SERVER, "iTime-Server" }, /* time servers (RFC868) */
{ TAG_NAME_SERVER, "iIEN-Name-Server" }, /* IEN name servers (IEN116) */
{ TAG_DOMAIN_SERVER, "iDomain-Name-Server" }, /* domain name (RFC1035) */
{ TAG_LOG_SERVER, "iLOG" }, /* MIT log servers */
{ TAG_COOKIE_SERVER, "iCS" }, /* cookie servers (RFC865) */
{ TAG_LPR_SERVER, "iLPR-Server" }, /* lpr server (RFC1179) */
{ TAG_IMPRESS_SERVER, "iIM" }, /* impress servers (Imagen) */
{ TAG_RLP_SERVER, "iRL" }, /* resource location (RFC887) */
{ TAG_HOSTNAME, "aHostname" }, /* ASCII hostname */
{ TAG_BOOTSIZE, "sBS" }, /* 512 byte blocks */
{ TAG_END, " END" },
/* RFC1497 tags */
{ TAG_DUMPPATH, "aDP" },
{ TAG_DOMAINNAME, "aDomain-Name" },
{ TAG_SWAP_SERVER, "iSS" },
{ TAG_ROOTPATH, "aRP" },
{ TAG_EXTPATH, "aEP" },
/* RFC2132 tags */
{ TAG_IP_FORWARD, "BIPF" },
{ TAG_NL_SRCRT, "BSRT" },
{ TAG_PFILTERS, "pPF" },
{ TAG_REASS_SIZE, "sRSZ" },
{ TAG_DEF_TTL, "bTTL" },
{ TAG_MTU_TIMEOUT, "lMTU-Timeout" },
{ TAG_MTU_TABLE, "sMTU-Table" },
{ TAG_INT_MTU, "sMTU" },
{ TAG_LOCAL_SUBNETS, "BLSN" },
{ TAG_BROAD_ADDR, "iBR" },
{ TAG_DO_MASK_DISC, "BMD" },
{ TAG_SUPPLY_MASK, "BMS" },
{ TAG_DO_RDISC, "BRouter-Discovery" },
{ TAG_RTR_SOL_ADDR, "iRSA" },
{ TAG_STATIC_ROUTE, "pStatic-Route" },
{ TAG_USE_TRAILERS, "BUT" },
{ TAG_ARP_TIMEOUT, "lAT" },
{ TAG_ETH_ENCAP, "BIE" },
{ TAG_TCP_TTL, "bTT" },
{ TAG_TCP_KEEPALIVE, "lKI" },
{ TAG_KEEPALIVE_GO, "BKG" },
{ TAG_NIS_DOMAIN, "aYD" },
{ TAG_NIS_SERVERS, "iYS" },
{ TAG_NTP_SERVERS, "iNTP" },
{ TAG_VENDOR_OPTS, "bVendor-Option" },
{ TAG_NETBIOS_NS, "iNetbios-Name-Server" },
{ TAG_NETBIOS_DDS, "iWDD" },
{ TAG_NETBIOS_NODE, "$Netbios-Node" },
{ TAG_NETBIOS_SCOPE, "aNetbios-Scope" },
{ TAG_XWIN_FS, "iXFS" },
{ TAG_XWIN_DM, "iXDM" },
{ TAG_NIS_P_DOMAIN, "sN+D" },
{ TAG_NIS_P_SERVERS, "iN+S" },
{ TAG_MOBILE_HOME, "iMH" },
- { TAG_SMPT_SERVER, "iSMTP" },
+ { TAG_SMTP_SERVER, "iSMTP" },
{ TAG_POP3_SERVER, "iPOP3" },
{ TAG_NNTP_SERVER, "iNNTP" },
{ TAG_WWW_SERVER, "iWWW" },
{ TAG_FINGER_SERVER, "iFG" },
{ TAG_IRC_SERVER, "iIRC" },
{ TAG_STREETTALK_SRVR, "iSTS" },
{ TAG_STREETTALK_STDA, "iSTDA" },
{ TAG_REQUESTED_IP, "iRequested-IP" },
{ TAG_IP_LEASE, "lLease-Time" },
{ TAG_OPT_OVERLOAD, "$OO" },
{ TAG_TFTP_SERVER, "aTFTP" },
{ TAG_BOOTFILENAME, "aBF" },
{ TAG_DHCP_MESSAGE, " DHCP-Message" },
{ TAG_SERVER_ID, "iServer-ID" },
{ TAG_PARM_REQUEST, "bParameter-Request" },
{ TAG_MESSAGE, "aMSG" },
{ TAG_MAX_MSG_SIZE, "sMSZ" },
{ TAG_RENEWAL_TIME, "lRN" },
{ TAG_REBIND_TIME, "lRB" },
{ TAG_VENDOR_CLASS, "aVendor-Class" },
{ TAG_CLIENT_ID, "$Client-ID" },
/* RFC 2485 */
{ TAG_OPEN_GROUP_UAP, "aUAP" },
/* RFC 2563 */
{ TAG_DISABLE_AUTOCONF, "BNOAUTO" },
/* RFC 2610 */
{ TAG_SLP_DA, "bSLP-DA" }, /*"b" is a little wrong */
{ TAG_SLP_SCOPE, "bSLP-SCOPE" }, /*"b" is a little wrong */
/* RFC 2937 */
{ TAG_NS_SEARCH, "sNSSEARCH" }, /* XXX 's' */
/* RFC 3004 - The User Class Option for DHCP */
{ TAG_USER_CLASS, "$User-Class" },
/* RFC 3011 */
{ TAG_IP4_SUBNET_SELECT, "iSUBNET" },
/* RFC 3442 */
{ TAG_CLASSLESS_STATIC_RT, "$Classless-Static-Route" },
{ TAG_CLASSLESS_STA_RT_MS, "$Classless-Static-Route-Microsoft" },
+/* RFC 8572 */
+ { TAG_SZTP_REDIRECT, "$SZTP-Redirect" },
/* RFC 5859 - TFTP Server Address Option for DHCPv4 */
{ TAG_TFTP_SERVER_ADDRESS, "iTFTP-Server-Address" },
/* https://www.iana.org/assignments/bootp-dhcp-parameters/bootp-dhcp-parameters.xhtml#options */
{ TAG_SLP_NAMING_AUTH, "aSLP-NA" },
{ TAG_CLIENT_FQDN, "$FQDN" },
{ TAG_AGENT_CIRCUIT, "$Agent-Information" },
{ TAG_AGENT_REMOTE, "bARMT" },
{ TAG_TZ_STRING, "aTZSTR" },
{ TAG_FQDN_OPTION, "bFQDNS" }, /* XXX 'b' */
{ TAG_AUTH, "bAUTH" }, /* XXX 'b' */
{ TAG_CLIENT_LAST_TRANSACTION_TIME, "LLast-Transaction-Time" },
{ TAG_ASSOCIATED_IP, "iAssociated-IP" },
{ TAG_CLIENT_ARCH, "sARCH" },
{ TAG_CLIENT_NDI, "bNDI" }, /* XXX 'b' */
{ TAG_CLIENT_GUID, "bGUID" }, /* XXX 'b' */
{ TAG_LDAP_URL, "aLDAP" },
{ TAG_TZ_PCODE, "aPOSIX-TZ" },
{ TAG_TZ_TCODE, "aTZ-Name" },
{ TAG_NETINFO_PARENT, "iNI" },
{ TAG_NETINFO_PARENT_TAG, "aNITAG" },
{ TAG_URL, "aURL" },
{ TAG_MUDURL, "aMUD-URL" },
{ 0, NULL }
};
/* DHCP "options overload" types */
static const struct tok oo2str[] = {
{ 1, "file" },
{ 2, "sname" },
{ 3, "file+sname" },
{ 0, NULL }
};
/* NETBIOS over TCP/IP node type options */
static const struct tok nbo2str[] = {
{ 0x1, "b-node" },
{ 0x2, "p-node" },
{ 0x4, "m-node" },
{ 0x8, "h-node" },
{ 0, NULL }
};
/* ARP Hardware types, for Client-ID option */
static const struct tok arp2str[] = {
{ 0x1, "ether" },
{ 0x6, "ieee802" },
{ 0x7, "arcnet" },
{ 0xf, "frelay" },
{ 0x17, "strip" },
{ 0x18, "ieee1394" },
{ 0, NULL }
};
static const struct tok dhcp_msg_values[] = {
{ DHCPDISCOVER, "Discover" },
{ DHCPOFFER, "Offer" },
{ DHCPREQUEST, "Request" },
{ DHCPDECLINE, "Decline" },
{ DHCPACK, "ACK" },
{ DHCPNAK, "NACK" },
{ DHCPRELEASE, "Release" },
{ DHCPINFORM, "Inform" },
{ DHCPLEASEQUERY, "LeaseQuery" },
{ DHCPLEASEUNASSIGNED, "LeaseUnassigned" },
{ DHCPLEASEUNKNOWN, "LeaseUnknown" },
{ DHCPLEASEACTIVE, "LeaseActive" },
{ 0, NULL }
};
#define AGENT_SUBOPTION_CIRCUIT_ID 1 /* RFC 3046 */
#define AGENT_SUBOPTION_REMOTE_ID 2 /* RFC 3046 */
#define AGENT_SUBOPTION_SUBSCRIBER_ID 6 /* RFC 3993 */
static const struct tok agent_suboption_values[] = {
{ AGENT_SUBOPTION_CIRCUIT_ID, "Circuit-ID" },
{ AGENT_SUBOPTION_REMOTE_ID, "Remote-ID" },
{ AGENT_SUBOPTION_SUBSCRIBER_ID, "Subscriber-ID" },
{ 0, NULL }
};
static void
rfc1048_print(netdissect_options *ndo,
const u_char *bp)
{
uint16_t tag;
u_int len;
const char *cp;
char c;
int first, idx;
uint8_t subopt, suboptlen;
ND_PRINT("\n\t Vendor-rfc1048 Extensions");
/* Step over magic cookie */
ND_PRINT("\n\t Magic Cookie 0x%08x", GET_BE_U_4(bp));
bp += sizeof(int32_t);
/* Loop while we there is a tag left in the buffer */
while (ND_TTEST_1(bp)) {
tag = GET_U_1(bp);
bp++;
if (tag == TAG_PAD && ndo->ndo_vflag < 3)
continue;
if (tag == TAG_END && ndo->ndo_vflag < 3)
return;
cp = tok2str(tag2str, "?Unknown", tag);
c = *cp++;
if (tag == TAG_PAD || tag == TAG_END)
len = 0;
else {
/* Get the length; check for truncation */
len = GET_U_1(bp);
bp++;
}
ND_PRINT("\n\t %s (%u), length %u%s", cp, tag, len,
len > 0 ? ": " : "");
if (tag == TAG_PAD && ndo->ndo_vflag > 2) {
u_int ntag = 1;
while (ND_TTEST_1(bp) &&
GET_U_1(bp) == TAG_PAD) {
bp++;
ntag++;
}
if (ntag > 1)
ND_PRINT(", occurs %u", ntag);
}
ND_TCHECK_LEN(bp, len);
if (tag == TAG_DHCP_MESSAGE && len == 1) {
ND_PRINT("%s",
tok2str(dhcp_msg_values, "Unknown (%u)", GET_U_1(bp)));
bp++;
continue;
}
if (tag == TAG_PARM_REQUEST) {
idx = 0;
while (len > 0) {
uint8_t innertag = GET_U_1(bp);
bp++;
len--;
cp = tok2str(tag2str, "?Unknown", innertag);
if (idx % 4 == 0)
ND_PRINT("\n\t ");
else
ND_PRINT(", ");
ND_PRINT("%s (%u)", cp + 1, innertag);
idx++;
}
continue;
}
/* Print data */
if (c == '?') {
/* Base default formats for unknown tags on data size */
if (len & 1)
c = 'b';
else if (len & 2)
c = 's';
else
c = 'l';
}
first = 1;
switch (c) {
case 'a':
/* ASCII strings */
ND_PRINT("\"");
if (nd_printn(ndo, bp, len, ndo->ndo_snapend)) {
ND_PRINT("\"");
goto trunc;
}
ND_PRINT("\"");
bp += len;
len = 0;
break;
case 'i':
case 'l':
case 'L':
/* ip addresses/32-bit words */
while (len >= 4) {
if (!first)
ND_PRINT(",");
if (c == 'i')
ND_PRINT("%s", GET_IPADDR_STRING(bp));
else if (c == 'L')
ND_PRINT("%d", GET_BE_S_4(bp));
else
ND_PRINT("%u", GET_BE_U_4(bp));
bp += 4;
len -= 4;
first = 0;
}
break;
case 'p':
/* IP address pairs */
while (len >= 2*4) {
if (!first)
ND_PRINT(",");
ND_PRINT("(%s:", GET_IPADDR_STRING(bp));
bp += 4;
len -= 4;
ND_PRINT("%s)", GET_IPADDR_STRING(bp));
bp += 4;
len -= 4;
first = 0;
}
break;
case 's':
/* shorts */
while (len >= 2) {
if (!first)
ND_PRINT(",");
ND_PRINT("%u", GET_BE_U_2(bp));
bp += 2;
len -= 2;
first = 0;
}
break;
case 'B':
/* boolean */
while (len > 0) {
uint8_t bool_value;
if (!first)
ND_PRINT(",");
bool_value = GET_U_1(bp);
switch (bool_value) {
case 0:
ND_PRINT("N");
break;
case 1:
ND_PRINT("Y");
break;
default:
ND_PRINT("%u?", bool_value);
break;
}
++bp;
--len;
first = 0;
}
break;
case 'b':
case 'x':
default:
/* Bytes */
while (len > 0) {
uint8_t byte_value;
if (!first)
ND_PRINT(c == 'x' ? ":" : ".");
byte_value = GET_U_1(bp);
if (c == 'x')
ND_PRINT("%02x", byte_value);
else
ND_PRINT("%u", byte_value);
++bp;
--len;
first = 0;
}
break;
case '$':
/* Guys we can't handle with one of the usual cases */
switch (tag) {
case TAG_NETBIOS_NODE:
/* this option should be at least 1 byte long */
if (len < 1) {
ND_PRINT("[ERROR: length < 1 bytes]");
break;
}
tag = GET_U_1(bp);
++bp;
--len;
ND_PRINT("%s", tok2str(nbo2str, NULL, tag));
break;
case TAG_OPT_OVERLOAD:
/* this option should be at least 1 byte long */
if (len < 1) {
ND_PRINT("[ERROR: length < 1 bytes]");
break;
}
tag = GET_U_1(bp);
++bp;
--len;
ND_PRINT("%s", tok2str(oo2str, NULL, tag));
break;
case TAG_CLIENT_FQDN:
/* this option should be at least 3 bytes long */
if (len < 3) {
ND_PRINT("[ERROR: length < 3 bytes]");
bp += len;
len = 0;
break;
}
if (GET_U_1(bp) & 0xf0) {
ND_PRINT("[ERROR: MBZ nibble 0x%x != 0] ",
(GET_U_1(bp) & 0xf0) >> 4);
}
if (GET_U_1(bp) & 0x0f)
ND_PRINT("[%s] ",
client_fqdn_flags(GET_U_1(bp)));
bp++;
if (GET_U_1(bp) || GET_U_1(bp + 1))
ND_PRINT("%u/%u ", GET_U_1(bp),
GET_U_1(bp + 1));
bp += 2;
ND_PRINT("\"");
if (nd_printn(ndo, bp, len - 3, ndo->ndo_snapend)) {
ND_PRINT("\"");
goto trunc;
}
ND_PRINT("\"");
bp += len - 3;
len = 0;
break;
case TAG_CLIENT_ID:
{
int type;
/* this option should be at least 1 byte long */
if (len < 1) {
ND_PRINT("[ERROR: length < 1 bytes]");
break;
}
type = GET_U_1(bp);
bp++;
len--;
if (type == 0) {
ND_PRINT("\"");
if (nd_printn(ndo, bp, len, ndo->ndo_snapend)) {
ND_PRINT("\"");
goto trunc;
}
ND_PRINT("\"");
bp += len;
len = 0;
break;
} else {
ND_PRINT("%s ", tok2str(arp2str, "hardware-type %u,", type));
while (len > 0) {
if (!first)
ND_PRINT(":");
ND_PRINT("%02x", GET_U_1(bp));
++bp;
--len;
first = 0;
}
}
break;
}
case TAG_AGENT_CIRCUIT:
while (len >= 2) {
subopt = GET_U_1(bp);
suboptlen = GET_U_1(bp + 1);
bp += 2;
len -= 2;
if (suboptlen > len) {
ND_PRINT("\n\t %s SubOption %u, length %u: length goes past end of option",
tok2str(agent_suboption_values, "Unknown", subopt),
subopt,
suboptlen);
bp += len;
len = 0;
break;
}
ND_PRINT("\n\t %s SubOption %u, length %u: ",
tok2str(agent_suboption_values, "Unknown", subopt),
subopt,
suboptlen);
switch (subopt) {
case AGENT_SUBOPTION_CIRCUIT_ID: /* fall through */
case AGENT_SUBOPTION_REMOTE_ID:
case AGENT_SUBOPTION_SUBSCRIBER_ID:
if (nd_printn(ndo, bp, suboptlen, ndo->ndo_snapend))
goto trunc;
break;
default:
print_unknown_data(ndo, bp, "\n\t\t", suboptlen);
}
len -= suboptlen;
bp += suboptlen;
}
break;
case TAG_CLASSLESS_STATIC_RT:
case TAG_CLASSLESS_STA_RT_MS:
{
u_int mask_width, significant_octets, i;
/* this option should be at least 5 bytes long */
if (len < 5) {
ND_PRINT("[ERROR: length < 5 bytes]");
bp += len;
len = 0;
break;
}
while (len > 0) {
if (!first)
ND_PRINT(",");
mask_width = GET_U_1(bp);
bp++;
len--;
/* mask_width <= 32 */
if (mask_width > 32) {
ND_PRINT("[ERROR: Mask width (%u) > 32]", mask_width);
bp += len;
len = 0;
break;
}
significant_octets = (mask_width + 7) / 8;
/* significant octets + router(4) */
if (len < significant_octets + 4) {
ND_PRINT("[ERROR: Remaining length (%u) < %u bytes]", len, significant_octets + 4);
bp += len;
len = 0;
break;
}
ND_PRINT("(");
if (mask_width == 0)
ND_PRINT("default");
else {
for (i = 0; i < significant_octets ; i++) {
if (i > 0)
ND_PRINT(".");
ND_PRINT("%u",
GET_U_1(bp));
bp++;
}
for (i = significant_octets ; i < 4 ; i++)
ND_PRINT(".0");
ND_PRINT("/%u", mask_width);
}
ND_PRINT(":%s)", GET_IPADDR_STRING(bp));
bp += 4;
len -= (significant_octets + 4);
first = 0;
}
break;
}
case TAG_USER_CLASS:
{
u_int suboptnumber = 1;
first = 1;
if (len < 2) {
ND_PRINT("[ERROR: length < 2 bytes]");
bp += len;
len = 0;
break;
}
while (len > 0) {
suboptlen = GET_U_1(bp);
bp++;
len--;
ND_PRINT("\n\t ");
ND_PRINT("instance#%u: ", suboptnumber);
if (suboptlen == 0) {
ND_PRINT("[ERROR: suboption length must be non-zero]");
bp += len;
len = 0;
break;
}
if (len < suboptlen) {
ND_PRINT("[ERROR: invalid option]");
bp += len;
len = 0;
break;
}
ND_PRINT("\"");
if (nd_printn(ndo, bp, suboptlen, ndo->ndo_snapend)) {
ND_PRINT("\"");
goto trunc;
}
ND_PRINT("\"");
ND_PRINT(", length %u", suboptlen);
suboptnumber++;
len -= suboptlen;
bp += suboptlen;
}
break;
}
+
+ case TAG_SZTP_REDIRECT:
+ /* as per https://datatracker.ietf.org/doc/html/rfc8572#section-8.3
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-...-+-+-+-+-+-+-+
+ | uri-length | URI |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-...-+-+-+-+-+-+-+
+
+ * uri-length: 2 octets long; specifies the length of the URI data.
+ * URI: URI of the SZTP bootstrap server.
+ */
+ while (len >= 2) {
+ suboptlen = GET_BE_U_2(bp);
+ bp += 2;
+ len -= 2;
+ ND_PRINT("\n\t ");
+ ND_PRINT("length %u: ", suboptlen);
+ if (len < suboptlen) {
+ ND_PRINT("length goes past end of option");
+ bp += len;
+ len = 0;
+ break;
+ }
+ ND_PRINT("\"");
+ nd_printjn(ndo, bp, suboptlen);
+ ND_PRINT("\"");
+ len -= suboptlen;
+ bp += suboptlen;
+ }
+ if (len != 0) {
+ ND_PRINT("[ERROR: length < 2 bytes]");
+ }
+ break;
+
default:
ND_PRINT("[unknown special tag %u, size %u]",
tag, len);
bp += len;
len = 0;
break;
}
break;
}
/* Data left over? */
if (len) {
ND_PRINT("\n\t trailing data length %u", len);
bp += len;
}
}
return;
trunc:
nd_print_trunc(ndo);
}
#define PRINTCMUADDR(m, s) { ND_TCHECK_4(cmu->m); \
if (GET_IPV4_TO_NETWORK_ORDER(cmu->m) != 0) \
ND_PRINT(" %s:%s", s, GET_IPADDR_STRING(cmu->m)); }
static void
cmu_print(netdissect_options *ndo,
const u_char *bp)
{
const struct cmu_vend *cmu;
uint8_t v_flags;
ND_PRINT(" vend-cmu");
cmu = (const struct cmu_vend *)bp;
/* Only print if there are unknown bits */
ND_TCHECK_4(cmu->v_flags);
v_flags = GET_U_1(cmu->v_flags);
if ((v_flags & ~(VF_SMASK)) != 0)
ND_PRINT(" F:0x%x", v_flags);
PRINTCMUADDR(v_dgate, "DG");
PRINTCMUADDR(v_smask, v_flags & VF_SMASK ? "SM" : "SM*");
PRINTCMUADDR(v_dns1, "NS1");
PRINTCMUADDR(v_dns2, "NS2");
PRINTCMUADDR(v_ins1, "IEN1");
PRINTCMUADDR(v_ins2, "IEN2");
PRINTCMUADDR(v_ts1, "TS1");
PRINTCMUADDR(v_ts2, "TS2");
return;
trunc:
nd_print_trunc(ndo);
}
#undef PRINTCMUADDR
static char *
client_fqdn_flags(u_int flags)
{
static char buf[8+1];
int i = 0;
if (flags & CLIENT_FQDN_FLAGS_S)
buf[i++] = 'S';
if (flags & CLIENT_FQDN_FLAGS_O)
buf[i++] = 'O';
if (flags & CLIENT_FQDN_FLAGS_E)
buf[i++] = 'E';
if (flags & CLIENT_FQDN_FLAGS_N)
buf[i++] = 'N';
buf[i] = '\0';
return buf;
}
diff --git a/contrib/tcpdump/print-brcmtag.c b/contrib/tcpdump/print-brcmtag.c
index efc6a1eefa46..a3d15e28fd72 100644
--- a/contrib/tcpdump/print-brcmtag.c
+++ b/contrib/tcpdump/print-brcmtag.c
@@ -1,151 +1,148 @@
/*
* Copyright (c) 1988, 1989, 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.
*/
/* \summary: Broadcom Ethernet switches tag (4 bytes) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
-#include "ethertype.h"
#include "addrtoname.h"
#include "extract.h"
#define ETHER_TYPE_LEN 2
#define BRCM_TAG_LEN 4
#define BRCM_OPCODE_SHIFT 5
#define BRCM_OPCODE_MASK 0x7
/* Ingress fields */
#define BRCM_IG_TC_SHIFT 2
#define BRCM_IG_TC_MASK 0x7
#define BRCM_IG_TE_MASK 0x3
#define BRCM_IG_TS_SHIFT 7
#define BRCM_IG_DSTMAP_MASK 0x1ff
/* Egress fields */
#define BRCM_EG_CID_MASK 0xff
#define BRCM_EG_RC_MASK 0xff
#define BRCM_EG_RC_RSVD (3 << 6)
#define BRCM_EG_RC_EXCEPTION (1 << 5)
#define BRCM_EG_RC_PROT_SNOOP (1 << 4)
#define BRCM_EG_RC_PROT_TERM (1 << 3)
#define BRCM_EG_RC_SWITCH (1 << 2)
#define BRCM_EG_RC_MAC_LEARN (1 << 1)
#define BRCM_EG_RC_MIRROR (1 << 0)
#define BRCM_EG_TC_SHIFT 5
#define BRCM_EG_TC_MASK 0x7
#define BRCM_EG_PID_MASK 0x1f
static const struct tok brcm_tag_te_values[] = {
{ 0, "None" },
{ 1, "Untag" },
{ 2, "Header"},
{ 3, "Reserved" },
{ 0, NULL }
};
static const struct tok brcm_tag_rc_values[] = {
{ 1, "mirror" },
{ 2, "MAC learning" },
{ 4, "switching" },
{ 8, "prot term" },
{ 16, "prot snoop" },
{ 32, "exception" },
{ 0, NULL }
};
static void
brcm_tag_print(netdissect_options *ndo, const u_char *bp)
{
uint8_t tag[BRCM_TAG_LEN];
uint16_t dst_map;
unsigned int i;
for (i = 0; i < BRCM_TAG_LEN; i++)
tag[i] = GET_U_1(bp + i);
ND_PRINT("BRCM tag OP: %s", tag[0] ? "IG" : "EG");
if (tag[0] & (1 << BRCM_OPCODE_SHIFT)) {
/* Ingress Broadcom tag */
ND_PRINT(", TC: %d", (tag[1] >> BRCM_IG_TC_SHIFT) &
BRCM_IG_TC_MASK);
ND_PRINT(", TE: %s",
tok2str(brcm_tag_te_values, "unknown",
(tag[1] & BRCM_IG_TE_MASK)));
ND_PRINT(", TS: %d", tag[1] >> BRCM_IG_TS_SHIFT);
dst_map = (uint16_t)tag[2] << 8 | tag[3];
ND_PRINT(", DST map: 0x%04x", dst_map & BRCM_IG_DSTMAP_MASK);
} else {
/* Egress Broadcom tag */
ND_PRINT(", CID: %d", tag[1]);
ND_PRINT(", RC: %s", tok2str(brcm_tag_rc_values,
"reserved", tag[2]));
ND_PRINT(", TC: %d", (tag[3] >> BRCM_EG_TC_SHIFT) &
BRCM_EG_TC_MASK);
ND_PRINT(", port: %d", tag[3] & BRCM_EG_PID_MASK);
}
ND_PRINT(", ");
}
void
brcm_tag_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h,
const u_char *p)
{
u_int caplen = h->caplen;
u_int length = h->len;
ndo->ndo_protocol = "brcm-tag";
ndo->ndo_ll_hdr_len +=
ether_switch_tag_print(ndo, p, length, caplen,
brcm_tag_print, BRCM_TAG_LEN);
}
void
brcm_tag_prepend_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h,
const u_char *p)
{
u_int caplen = h->caplen;
u_int length = h->len;
ndo->ndo_protocol = "brcm-tag-prepend";
ND_TCHECK_LEN(p, BRCM_TAG_LEN);
ndo->ndo_ll_hdr_len += BRCM_TAG_LEN;
if (ndo->ndo_eflag) {
/* Print the prepended Broadcom tag. */
brcm_tag_print(ndo, p);
}
p += BRCM_TAG_LEN;
length -= BRCM_TAG_LEN;
caplen -= BRCM_TAG_LEN;
/*
* Now print the Ethernet frame following it.
*/
ndo->ndo_ll_hdr_len +=
ether_print(ndo, p, length, caplen, NULL, NULL);
}
diff --git a/contrib/tcpdump/print-bt.c b/contrib/tcpdump/print-bt.c
index 46aa2782aeb5..290434b99cc0 100644
--- a/contrib/tcpdump/print-bt.c
+++ b/contrib/tcpdump/print-bt.c
@@ -1,71 +1,69 @@
/*
* Copyright (c) 2007
* paolo.abeni@email.it 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 Paolo Abeni.''
* The name of author may not 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.
*/
/* \summary: Bluetooth printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
#ifdef DLT_BLUETOOTH_HCI_H4_WITH_PHDR
/*
* Header prepended by libpcap to each bluetooth h4 frame;
* the direction field is in network byte order.
*/
typedef struct _bluetooth_h4_header {
nd_uint32_t direction; /* if first bit is set direction is incoming */
} bluetooth_h4_header;
#define BT_HDRLEN sizeof(bluetooth_h4_header)
/*
* This is the top level routine of the printer. 'p' points
* to the bluetooth header of the packet, 'h->ts' is the timestamp,
* 'h->len' is the length of the packet off the wire, and 'h->caplen'
* is the number of bytes actually captured.
*/
void
bt_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
{
u_int length = h->len;
u_int caplen = h->caplen;
const bluetooth_h4_header *hdr = (const bluetooth_h4_header *)p;
ndo->ndo_protocol = "bluetooth";
nd_print_protocol(ndo);
ND_TCHECK_LEN(p, BT_HDRLEN);
ndo->ndo_ll_hdr_len += BT_HDRLEN;
caplen -= BT_HDRLEN;
length -= BT_HDRLEN;
p += BT_HDRLEN;
if (ndo->ndo_eflag)
ND_PRINT(", hci length %u, direction %s", length,
(GET_BE_U_4(hdr->direction)&0x1) ? "in" : "out");
if (!ndo->ndo_suppress_default_print)
ND_DEFAULTPRINT(p, caplen);
}
#endif
diff --git a/contrib/tcpdump/print-calm-fast.c b/contrib/tcpdump/print-calm-fast.c
index 1220d867ec60..5b79337a62f2 100644
--- a/contrib/tcpdump/print-calm-fast.c
+++ b/contrib/tcpdump/print-calm-fast.c
@@ -1,71 +1,69 @@
/*
* Copyright (c) 2013 The TCPDUMP project
*
* 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.
*
* Original code by Ola Martin Lykkja (ola.lykkja@q-free.com)
*/
/* \summary: Communication access for land mobiles (CALM) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
#include "addrtoname.h"
/*
ISO 29281:2009
Intelligent Transport Systems . Communications access for land mobiles (CALM)
CALM non-IP networking
*/
/*
* This is the top level routine of the printer. 'bp' points
* to the calm header of the packet.
*/
void
calm_fast_print(netdissect_options *ndo, const u_char *bp, u_int length, const struct lladdr_info *src)
{
ndo->ndo_protocol = "calm_fast";
ND_PRINT("CALM FAST");
if (src != NULL)
ND_PRINT(" src:%s", (src->addr_string)(ndo, src->addr));
ND_PRINT("; ");
if (length < 2) {
ND_PRINT(" (length %u < 2)", length);
goto invalid;
}
ND_PRINT("SrcNwref:%u; ", GET_U_1(bp));
length -= 1;
bp += 1;
ND_PRINT("DstNwref:%u; ", GET_U_1(bp));
length -= 1;
bp += 1;
if (ndo->ndo_vflag)
ND_DEFAULTPRINT(bp, length);
return;
invalid:
nd_print_invalid(ndo);
ND_TCHECK_LEN(bp, length);
}
diff --git a/contrib/tcpdump/print-carp.c b/contrib/tcpdump/print-carp.c
index 75f506685f56..a073908d7600 100644
--- a/contrib/tcpdump/print-carp.c
+++ b/contrib/tcpdump/print-carp.c
@@ -1,78 +1,77 @@
/* $OpenBSD: print-carp.c,v 1.6 2009/10/27 23:59:55 deraadt Exp $ */
/*
* Copyright (c) 2000 William C. Fenner.
* All rights reserved.
*
* Kevin Steves <ks@hp.se> July 2000
* Modified to:
* - print version, type string and packet length
* - print IP address count if > 1 (-v)
* - verify checksum (-v)
* - print authentication string (-v)
*
* Copyright (c) 2011 Advanced Computing Technologies
* George V. Neille-Neil
*
* Modified to:
* - work correctly with CARP
* - compile into the latest tcpdump
* - print out the counter
*
* 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.
* The name of William C. Fenner may not 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.
*
*/
/* \summary: Common Address Redundancy Protocol (CARP) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h" /* for checksum structure and functions */
#include "extract.h"
void
carp_print(netdissect_options *ndo, const u_char *bp, u_int len, u_int ttl)
{
u_int version, type;
const char *type_s;
ndo->ndo_protocol = "carp";
+ nd_print_protocol_caps(ndo);
version = (GET_U_1(bp) & 0xf0) >> 4;
type = GET_U_1(bp) & 0x0f;
if (type == 1)
type_s = "advertise";
else
type_s = "unknown";
- ND_PRINT("CARPv%u-%s %u: ", version, type_s, len);
+ ND_PRINT("v%u-%s %u: ", version, type_s, len);
if (ttl != 255)
ND_PRINT("[ttl=%u!] ", ttl);
if (version != 2 || type != 1)
return;
ND_PRINT("vhid=%u advbase=%u advskew=%u authlen=%u ",
GET_U_1(bp + 1), GET_U_1(bp + 5), GET_U_1(bp + 2),
GET_U_1(bp + 3));
if (ndo->ndo_vflag) {
struct cksum_vec vec[1];
vec[0].ptr = (const uint8_t *)bp;
vec[0].len = len;
if (ND_TTEST_LEN(bp, len) && in_cksum(vec, 1))
ND_PRINT(" (bad carp cksum %x!)",
GET_BE_U_2(bp + 6));
}
ND_PRINT("counter=%" PRIu64, GET_BE_U_8(bp + 8));
}
diff --git a/contrib/tcpdump/print-cdp.c b/contrib/tcpdump/print-cdp.c
index 9f5c24bca6bd..c4adf180c84b 100644
--- a/contrib/tcpdump/print-cdp.c
+++ b/contrib/tcpdump/print-cdp.c
@@ -1,472 +1,468 @@
/*
* Copyright (c) 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.
*
* Code by Gert Doering, SpaceNet GmbH, gert@space.net
*
* Reference documentation:
* https://web.archive.org/web/20000914194913/http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/frames.pdf
*/
/* \summary: Cisco Discovery Protocol (CDP) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <string.h>
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#include "nlpid.h"
#define CDP_HEADER_LEN 4
#define CDP_HEADER_VERSION_OFFSET 0
#define CDP_HEADER_TTL_OFFSET 1
#define CDP_HEADER_CHECKSUM_OFFSET 2
#define CDP_TLV_HEADER_LEN 4
#define CDP_TLV_TYPE_OFFSET 0
#define CDP_TLV_LEN_OFFSET 2
static const struct tok cdp_capability_values[] = {
{ 0x01, "Router" },
{ 0x02, "Transparent Bridge" },
{ 0x04, "Source Route Bridge" },
{ 0x08, "L2 Switch" },
{ 0x10, "L3 capable" },
{ 0x20, "IGMP snooping" },
{ 0x40, "L1 capable" },
{ 0, NULL }
};
static void cdp_print_addr(netdissect_options *, const u_char *, u_int);
static void cdp_print_prefixes(netdissect_options *, const u_char *, u_int);
static void
cdp_print_string(netdissect_options *ndo,
const u_char *cp, const u_int len)
{
ND_PRINT("'");
(void)nd_printn(ndo, cp, len, NULL);
ND_PRINT("'");
}
static void
cdp_print_power(netdissect_options *ndo,
const u_char *cp, const u_int len)
{
u_int val = 0;
switch (len) {
case 1:
val = GET_U_1(cp);
break;
case 2:
val = GET_BE_U_2(cp);
break;
case 3:
val = GET_BE_U_3(cp);
break;
}
ND_PRINT("%1.2fW", val / 1000.0);
}
static void
cdp_print_capability(netdissect_options *ndo,
const u_char *cp, const u_int len _U_)
{
uint32_t val = GET_BE_U_4(cp);
ND_PRINT("(0x%08x): %s", val,
bittok2str(cdp_capability_values, "none", val));
}
/* Rework the version string to get a nice indentation. */
static void
cdp_print_version(netdissect_options *ndo,
const u_char *cp, const u_int len)
{
unsigned i;
ND_PRINT("\n\t ");
for (i = 0; i < len; i++) {
u_char c = GET_U_1(cp + i);
if (c == '\n')
ND_PRINT("\n\t ");
else
fn_print_char(ndo, c);
}
}
static void
cdp_print_uint16(netdissect_options *ndo,
const u_char *cp, const u_int len _U_)
{
ND_PRINT("%u", GET_BE_U_2(cp));
}
static void
cdp_print_duplex(netdissect_options *ndo,
const u_char *cp, const u_int len _U_)
{
ND_PRINT("%s", GET_U_1(cp) ? "full": "half");
}
/* https://www.cisco.com/c/en/us/td/docs/voice_ip_comm/cata/186/2_12_m/english/release/notes/186rn21m.html
* plus more details from other sources
*
* There are apparently versions of the request with both
* 2 bytes and 3 bytes of value. The 3 bytes of value
* appear to be a 1-byte application type followed by a
* 2-byte VLAN ID; the 2 bytes of value are unknown
* (they're 0x20 0x00 in some captures I've seen; that
* is not a valid VLAN ID, as VLAN IDs are 12 bits).
*
* The replies all appear to be 3 bytes long.
*/
static void
cdp_print_ata186(netdissect_options *ndo,
const u_char *cp, const u_int len)
{
if (len == 2)
ND_PRINT("unknown 0x%04x", GET_BE_U_2(cp));
else
ND_PRINT("app %u, vlan %u", GET_U_1(cp), GET_BE_U_2(cp + 1));
}
static void
cdp_print_mtu(netdissect_options *ndo,
const u_char *cp, const u_int len _U_)
{
ND_PRINT("%u bytes", GET_BE_U_4(cp));
}
static void
cdp_print_uint8x(netdissect_options *ndo,
const u_char *cp, const u_int len _U_)
{
ND_PRINT("0x%02x", GET_U_1(cp));
}
static void
cdp_print_phys_loc(netdissect_options *ndo,
const u_char *cp, const u_int len)
{
ND_PRINT("0x%02x", GET_U_1(cp));
if (len > 1) {
ND_PRINT("/");
(void)nd_printn(ndo, cp + 1, len - 1, NULL);
}
}
struct cdp_tlvinfo {
const char *name;
void (*printer)(netdissect_options *ndo, const u_char *, u_int);
int min_len, max_len;
};
#define T_DEV_ID 0x01
#define T_MAX 0x17
static const struct cdp_tlvinfo cdptlvs[T_MAX + 1] = {
/* 0x00 */
[ T_DEV_ID ] = { "Device-ID", cdp_print_string, -1, -1 },
[ 0x02 ] = { "Address", cdp_print_addr, -1, -1 },
[ 0x03 ] = { "Port-ID", cdp_print_string, -1, -1 },
[ 0x04 ] = { "Capability", cdp_print_capability, 4, 4 },
[ 0x05 ] = { "Version String", cdp_print_version, -1, -1 },
[ 0x06 ] = { "Platform", cdp_print_string, -1, -1 },
[ 0x07 ] = { "Prefixes", cdp_print_prefixes, -1, -1 },
/* not documented */
[ 0x08 ] = { "Protocol-Hello option", NULL, -1, -1 },
/* CDPv2 */
[ 0x09 ] = { "VTP Management Domain", cdp_print_string, -1, -1 },
/* CDPv2 */
[ 0x0a ] = { "Native VLAN ID", cdp_print_uint16, 2, 2 },
/* CDPv2 */
[ 0x0b ] = { "Duplex", cdp_print_duplex, 1, 1 },
/* 0x0c */
/* 0x0d */
/* incomplete doc. */
[ 0x0e ] = { "ATA-186 VoIP VLAN assignment", cdp_print_ata186, 3, 3 },
/* incomplete doc. */
[ 0x0f ] = { "ATA-186 VoIP VLAN request", cdp_print_ata186, 2, 3 },
/* not documented */
[ 0x10 ] = { "power consumption", cdp_print_power, 1, 3 },
/* not documented */
[ 0x11 ] = { "MTU", cdp_print_mtu, 4, 4 },
/* not documented */
[ 0x12 ] = { "AVVID trust bitmap", cdp_print_uint8x, 1, 1 },
/* not documented */
[ 0x13 ] = { "AVVID untrusted ports CoS", cdp_print_uint8x, 1, 1 },
/* not documented */
[ 0x14 ] = { "System Name", cdp_print_string, -1, -1 },
/* not documented */
[ 0x15 ] = { "System Object ID (not decoded)", NULL, -1, -1 },
[ 0x16 ] = { "Management Addresses", cdp_print_addr, 4, -1 },
/* not documented */
[ 0x17 ] = { "Physical Location", cdp_print_phys_loc, 1, -1 },
};
void
cdp_print(netdissect_options *ndo,
const u_char *tptr, u_int length)
{
u_int orig_length = length;
uint16_t checksum;
ndo->ndo_protocol = "cdp";
if (length < CDP_HEADER_LEN) {
ND_PRINT(" (packet length %u < %u)", length, CDP_HEADER_LEN);
goto invalid;
}
ND_PRINT("CDPv%u, ttl: %us",
GET_U_1(tptr + CDP_HEADER_VERSION_OFFSET),
GET_U_1(tptr + CDP_HEADER_TTL_OFFSET));
checksum = GET_BE_U_2(tptr + CDP_HEADER_CHECKSUM_OFFSET);
if (ndo->ndo_vflag)
ND_PRINT(", checksum: 0x%04x (unverified), length %u",
checksum, orig_length);
tptr += CDP_HEADER_LEN;
length -= CDP_HEADER_LEN;
while (length) {
u_int type, len;
const struct cdp_tlvinfo *info;
const char *name;
u_char covered = 0;
if (length < CDP_TLV_HEADER_LEN) {
ND_PRINT(" (remaining packet length %u < %u)",
length, CDP_TLV_HEADER_LEN);
goto invalid;
}
type = GET_BE_U_2(tptr + CDP_TLV_TYPE_OFFSET);
len = GET_BE_U_2(tptr + CDP_TLV_LEN_OFFSET); /* object length includes the 4 bytes header length */
info = type <= T_MAX ? &cdptlvs[type] : NULL;
name = (info && info->name) ? info->name : "unknown field type";
if (len < CDP_TLV_HEADER_LEN) {
if (ndo->ndo_vflag)
ND_PRINT("\n\t%s (0x%02x), TLV length: %u byte%s (too short)",
name, type, len, PLURAL_SUFFIX(len));
else
ND_PRINT(", %s TLV length %u too short",
name, len);
goto invalid;
}
if (len > length) {
ND_PRINT(" (TLV length %u > %u)", len, length);
goto invalid;
}
tptr += CDP_TLV_HEADER_LEN;
length -= CDP_TLV_HEADER_LEN;
len -= CDP_TLV_HEADER_LEN;
/* In non-verbose mode just print Device-ID. */
if (!ndo->ndo_vflag && type == T_DEV_ID)
ND_PRINT(", Device-ID ");
else if (ndo->ndo_vflag)
ND_PRINT("\n\t%s (0x%02x), value length: %u byte%s: ",
name, type, len, PLURAL_SUFFIX(len));
if (info) {
if ((info->min_len > 0 && len < (unsigned)info->min_len) ||
(info->max_len > 0 && len > (unsigned)info->max_len))
ND_PRINT(" (malformed TLV)");
else if (ndo->ndo_vflag || type == T_DEV_ID) {
if (info->printer)
info->printer(ndo, tptr, len);
else
ND_TCHECK_LEN(tptr, len);
/*
* When the type is defined without a printer,
* do not print the hex dump.
*/
covered = 1;
}
}
- if (!covered) {
+ if (ndo->ndo_vflag && !covered) {
ND_TCHECK_LEN(tptr, len);
print_unknown_data(ndo, tptr, "\n\t ", len);
}
tptr += len;
length -= len;
}
if (ndo->ndo_vflag < 1)
ND_PRINT(", length %u", orig_length);
return;
invalid:
nd_print_invalid(ndo);
ND_TCHECK_LEN(tptr, length);
}
/*
* Protocol type values.
*
* PT_NLPID means that the protocol type field contains an OSI NLPID.
*
* PT_IEEE_802_2 means that the protocol type field contains an IEEE 802.2
* LLC header that specifies that the payload is for that protocol.
*/
#define PT_NLPID 1 /* OSI NLPID */
#define PT_IEEE_802_2 2 /* IEEE 802.2 LLC header */
static void
cdp_print_addr(netdissect_options *ndo,
const u_char * p, u_int l)
{
u_int num;
static const u_char prot_ipv6[] = {
0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x86, 0xdd
};
if (l < 4) {
ND_PRINT(" (not enough space for num)");
goto invalid;
}
num = GET_BE_U_4(p);
p += 4;
l -= 4;
while (num) {
u_int pt, pl, al;
if (l < 2) {
ND_PRINT(" (not enough space for PT+PL)");
goto invalid;
}
pt = GET_U_1(p); /* type of "protocol" field */
pl = GET_U_1(p + 1); /* length of "protocol" field */
p += 2;
l -= 2;
if (l < pl + 2) {
ND_PRINT(" (not enough space for P+AL)");
goto invalid;
}
/* Skip the protocol for now. */
al = GET_BE_U_2(p + pl); /* address length */
if (pt == PT_NLPID && pl == 1 && GET_U_1(p) == NLPID_IP &&
al == 4) {
/*
* IPv4: protocol type = NLPID, protocol length = 1
* (1-byte NLPID), protocol = 0xcc (NLPID for IPv4),
* address length = 4
*/
p += pl + 2;
l -= pl + 2;
/* p is just beyond al now. */
if (l < al) {
ND_PRINT(" (not enough space for A)");
goto invalid;
}
ND_PRINT("IPv4 (%u) %s", num, GET_IPADDR_STRING(p));
p += al;
l -= al;
- }
- else if (pt == PT_IEEE_802_2 && pl == 8 &&
+ } else if (pt == PT_IEEE_802_2 && pl == 8 &&
memcmp(p, prot_ipv6, 8) == 0 && al == 16) {
/*
* IPv6: protocol type = IEEE 802.2 header,
* protocol length = 8 (size of LLC+SNAP header),
* protocol = LLC+SNAP header with the IPv6
* Ethertype, address length = 16
*/
p += pl + 2;
l -= pl + 2;
/* p is just beyond al now. */
if (l < al) {
ND_PRINT(" (not enough space for A)");
goto invalid;
}
ND_PRINT("IPv6 (%u) %s", num, GET_IP6ADDR_STRING(p));
p += al;
l -= al;
- }
- else {
+ } else {
/*
* Generic case: just print raw data
*/
ND_PRINT("pt=0x%02x, pl=%u, pb=", pt, pl);
while (pl != 0) {
ND_PRINT(" %02x", GET_U_1(p));
p++;
l--;
pl--;
}
ND_PRINT(", al=%u, a=", al);
p += 2;
l -= 2;
/* p is just beyond al now. */
if (l < al) {
ND_PRINT(" (not enough space for A)");
goto invalid;
}
while (al != 0) {
ND_PRINT(" %02x", GET_U_1(p));
p++;
l--;
al--;
}
}
num--;
if (num)
ND_PRINT(" ");
}
if (l)
ND_PRINT(" (%u bytes of stray data)", l);
return;
invalid:
ND_TCHECK_LEN(p, l);
}
static void
cdp_print_prefixes(netdissect_options *ndo,
const u_char * p, u_int l)
{
if (l % 5) {
ND_PRINT(" [length %u is not a multiple of 5]", l);
goto invalid;
}
ND_PRINT(" IPv4 Prefixes (%u):", l / 5);
while (l > 0) {
ND_PRINT(" %u.%u.%u.%u/%u",
GET_U_1(p), GET_U_1(p + 1), GET_U_1(p + 2),
GET_U_1(p + 3), GET_U_1(p + 4));
l -= 5;
p += 5;
}
return;
invalid:
ND_TCHECK_LEN(p, l);
}
diff --git a/contrib/tcpdump/print-cfm.c b/contrib/tcpdump/print-cfm.c
index e950719e691d..e78be378b128 100644
--- a/contrib/tcpdump/print-cfm.c
+++ b/contrib/tcpdump/print-cfm.c
@@ -1,766 +1,764 @@
/*
* Copyright (c) 1998-2006 The TCPDUMP project
*
* 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.
*
* Original code by Hannes Gredler (hannes@gredler.at)
*/
/* \summary: IEEE 802.1ag Connectivity Fault Management (CFM) protocols printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "extract.h"
#include "addrtoname.h"
#include "oui.h"
#include "af.h"
struct cfm_common_header_t {
nd_uint8_t mdlevel_version;
nd_uint8_t opcode;
nd_uint8_t flags;
nd_uint8_t first_tlv_offset;
};
#define CFM_VERSION 0
#define CFM_EXTRACT_VERSION(x) ((x)&0x1f)
#define CFM_EXTRACT_MD_LEVEL(x) (((x)&0xe0)>>5)
#define CFM_OPCODE_CCM 1
#define CFM_OPCODE_LBR 2
#define CFM_OPCODE_LBM 3
#define CFM_OPCODE_LTR 4
#define CFM_OPCODE_LTM 5
static const struct tok cfm_opcode_values[] = {
{ CFM_OPCODE_CCM, "Continuity Check Message"},
{ CFM_OPCODE_LBR, "Loopback Reply"},
{ CFM_OPCODE_LBM, "Loopback Message"},
{ CFM_OPCODE_LTR, "Linktrace Reply"},
{ CFM_OPCODE_LTM, "Linktrace Message"},
{ 0, NULL}
};
/*
* Message Formats.
*/
struct cfm_ccm_t {
nd_uint32_t sequence;
nd_uint16_t ma_epi;
nd_byte names[48];
nd_byte itu_t_y_1731[16];
};
/*
* Timer Bases for the CCM Interval field.
* Expressed in units of seconds.
*/
static const float ccm_interval_base[8] = {0.0f, 0.003333f, 0.01f, 0.1f, 1.0f, 10.0f, 60.0f, 600.0f};
#define CCM_INTERVAL_MIN_MULTIPLIER 3.25
#define CCM_INTERVAL_MAX_MULTIPLIER 3.5
#define CFM_CCM_RDI_FLAG 0x80
#define CFM_EXTRACT_CCM_INTERVAL(x) ((x)&0x07)
#define CFM_CCM_MD_FORMAT_8021 0
#define CFM_CCM_MD_FORMAT_NONE 1
#define CFM_CCM_MD_FORMAT_DNS 2
#define CFM_CCM_MD_FORMAT_MAC 3
#define CFM_CCM_MD_FORMAT_CHAR 4
static const struct tok cfm_md_nameformat_values[] = {
{ CFM_CCM_MD_FORMAT_8021, "IEEE 802.1"},
{ CFM_CCM_MD_FORMAT_NONE, "No MD Name present"},
{ CFM_CCM_MD_FORMAT_DNS, "DNS string"},
{ CFM_CCM_MD_FORMAT_MAC, "MAC + 16Bit Integer"},
{ CFM_CCM_MD_FORMAT_CHAR, "Character string"},
{ 0, NULL}
};
#define CFM_CCM_MA_FORMAT_8021 0
#define CFM_CCM_MA_FORMAT_VID 1
#define CFM_CCM_MA_FORMAT_CHAR 2
#define CFM_CCM_MA_FORMAT_INT 3
#define CFM_CCM_MA_FORMAT_VPN 4
static const struct tok cfm_ma_nameformat_values[] = {
{ CFM_CCM_MA_FORMAT_8021, "IEEE 802.1"},
{ CFM_CCM_MA_FORMAT_VID, "Primary VID"},
{ CFM_CCM_MA_FORMAT_CHAR, "Character string"},
{ CFM_CCM_MA_FORMAT_INT, "16Bit Integer"},
{ CFM_CCM_MA_FORMAT_VPN, "RFC2685 VPN-ID"},
{ 0, NULL}
};
struct cfm_lbm_t {
nd_uint32_t transaction_id;
};
struct cfm_ltm_t {
nd_uint32_t transaction_id;
nd_uint8_t ttl;
nd_mac_addr original_mac;
nd_mac_addr target_mac;
};
static const struct tok cfm_ltm_flag_values[] = {
{ 0x80, "Use Forwarding-DB only"},
{ 0, NULL}
};
struct cfm_ltr_t {
nd_uint32_t transaction_id;
nd_uint8_t ttl;
nd_uint8_t replay_action;
};
static const struct tok cfm_ltr_flag_values[] = {
{ 0x80, "UseFDB Only"},
{ 0x40, "FwdYes"},
{ 0x20, "Terminal MEP"},
{ 0, NULL}
};
static const struct tok cfm_ltr_replay_action_values[] = {
{ 1, "Exact Match"},
{ 2, "Filtering DB"},
{ 3, "MIP CCM DB"},
{ 0, NULL}
};
#define CFM_TLV_END 0
#define CFM_TLV_SENDER_ID 1
#define CFM_TLV_PORT_STATUS 2
#define CFM_TLV_INTERFACE_STATUS 3
#define CFM_TLV_DATA 4
#define CFM_TLV_REPLY_INGRESS 5
#define CFM_TLV_REPLY_EGRESS 6
#define CFM_TLV_PRIVATE 31
static const struct tok cfm_tlv_values[] = {
{ CFM_TLV_END, "End"},
{ CFM_TLV_SENDER_ID, "Sender ID"},
{ CFM_TLV_PORT_STATUS, "Port status"},
{ CFM_TLV_INTERFACE_STATUS, "Interface status"},
{ CFM_TLV_DATA, "Data"},
{ CFM_TLV_REPLY_INGRESS, "Reply Ingress"},
{ CFM_TLV_REPLY_EGRESS, "Reply Egress"},
{ CFM_TLV_PRIVATE, "Organization Specific"},
{ 0, NULL}
};
/*
* TLVs
*/
struct cfm_tlv_header_t {
nd_uint8_t type;
nd_uint16_t length;
};
/* FIXME define TLV formats */
static const struct tok cfm_tlv_port_status_values[] = {
{ 1, "Blocked"},
{ 2, "Up"},
{ 0, NULL}
};
static const struct tok cfm_tlv_interface_status_values[] = {
{ 1, "Up"},
{ 2, "Down"},
{ 3, "Testing"},
{ 5, "Dormant"},
{ 6, "not present"},
{ 7, "lower Layer down"},
{ 0, NULL}
};
#define CFM_CHASSIS_ID_CHASSIS_COMPONENT 1
#define CFM_CHASSIS_ID_INTERFACE_ALIAS 2
#define CFM_CHASSIS_ID_PORT_COMPONENT 3
#define CFM_CHASSIS_ID_MAC_ADDRESS 4
#define CFM_CHASSIS_ID_NETWORK_ADDRESS 5
#define CFM_CHASSIS_ID_INTERFACE_NAME 6
#define CFM_CHASSIS_ID_LOCAL 7
static const struct tok cfm_tlv_senderid_chassisid_values[] = {
{ 0, "Reserved"},
{ CFM_CHASSIS_ID_CHASSIS_COMPONENT, "Chassis component"},
{ CFM_CHASSIS_ID_INTERFACE_ALIAS, "Interface alias"},
{ CFM_CHASSIS_ID_PORT_COMPONENT, "Port component"},
{ CFM_CHASSIS_ID_MAC_ADDRESS, "MAC address"},
{ CFM_CHASSIS_ID_NETWORK_ADDRESS, "Network address"},
{ CFM_CHASSIS_ID_INTERFACE_NAME, "Interface name"},
{ CFM_CHASSIS_ID_LOCAL, "Locally assigned"},
{ 0, NULL}
};
static int
cfm_network_addr_print(netdissect_options *ndo,
const u_char *tptr, const u_int length)
{
u_int network_addr_type;
u_int hexdump = FALSE;
/*
* Although AFIs are typically 2 octets wide,
* 802.1ab specifies that this field width
* is only one octet.
*/
if (length < 1) {
ND_PRINT("\n\t Network Address Type (invalid, no data");
return hexdump;
}
/* The calling function must make any due ND_TCHECK calls. */
network_addr_type = GET_U_1(tptr);
ND_PRINT("\n\t Network Address Type %s (%u)",
tok2str(af_values, "Unknown", network_addr_type),
network_addr_type);
/*
* Resolve the passed in Address.
*/
switch(network_addr_type) {
case AFNUM_INET:
if (length != 1 + 4) {
ND_PRINT("(invalid IPv4 address length %u)", length - 1);
hexdump = TRUE;
break;
}
ND_PRINT(", %s", GET_IPADDR_STRING(tptr + 1));
break;
case AFNUM_INET6:
if (length != 1 + 16) {
ND_PRINT("(invalid IPv6 address length %u)", length - 1);
hexdump = TRUE;
break;
}
ND_PRINT(", %s", GET_IP6ADDR_STRING(tptr + 1));
break;
default:
hexdump = TRUE;
break;
}
return hexdump;
}
void
cfm_print(netdissect_options *ndo,
const u_char *pptr, u_int length)
{
const struct cfm_common_header_t *cfm_common_header;
uint8_t mdlevel_version, opcode, flags, first_tlv_offset;
const struct cfm_tlv_header_t *cfm_tlv_header;
const uint8_t *tptr, *tlv_ptr;
const uint8_t *namesp;
u_int names_data_remaining;
uint8_t md_nameformat, md_namelength;
const uint8_t *md_name;
uint8_t ma_nameformat, ma_namelength;
const uint8_t *ma_name;
u_int hexdump, tlen, cfm_tlv_len, cfm_tlv_type, ccm_interval;
union {
const struct cfm_ccm_t *cfm_ccm;
const struct cfm_lbm_t *cfm_lbm;
const struct cfm_ltm_t *cfm_ltm;
const struct cfm_ltr_t *cfm_ltr;
} msg_ptr;
ndo->ndo_protocol = "cfm";
tptr=pptr;
cfm_common_header = (const struct cfm_common_header_t *)pptr;
if (length < sizeof(*cfm_common_header))
goto tooshort;
ND_TCHECK_SIZE(cfm_common_header);
/*
* Sanity checking of the header.
*/
mdlevel_version = GET_U_1(cfm_common_header->mdlevel_version);
if (CFM_EXTRACT_VERSION(mdlevel_version) != CFM_VERSION) {
ND_PRINT("CFMv%u not supported, length %u",
CFM_EXTRACT_VERSION(mdlevel_version), length);
return;
}
opcode = GET_U_1(cfm_common_header->opcode);
ND_PRINT("CFMv%u %s, MD Level %u, length %u",
CFM_EXTRACT_VERSION(mdlevel_version),
tok2str(cfm_opcode_values, "unknown (%u)", opcode),
CFM_EXTRACT_MD_LEVEL(mdlevel_version),
length);
/*
* In non-verbose mode just print the opcode and md-level.
*/
if (ndo->ndo_vflag < 1) {
return;
}
flags = GET_U_1(cfm_common_header->flags);
first_tlv_offset = GET_U_1(cfm_common_header->first_tlv_offset);
ND_PRINT("\n\tFirst TLV offset %u", first_tlv_offset);
tptr += sizeof(struct cfm_common_header_t);
tlen = length - sizeof(struct cfm_common_header_t);
/*
* Sanity check the first TLV offset.
*/
if (first_tlv_offset > tlen) {
ND_PRINT(" (too large, must be <= %u)", tlen);
return;
}
switch (opcode) {
case CFM_OPCODE_CCM:
msg_ptr.cfm_ccm = (const struct cfm_ccm_t *)tptr;
if (first_tlv_offset < sizeof(*msg_ptr.cfm_ccm)) {
ND_PRINT(" (too small 1, must be >= %zu)",
sizeof(*msg_ptr.cfm_ccm));
return;
}
if (tlen < sizeof(*msg_ptr.cfm_ccm))
goto tooshort;
ND_TCHECK_SIZE(msg_ptr.cfm_ccm);
ccm_interval = CFM_EXTRACT_CCM_INTERVAL(flags);
ND_PRINT(", Flags [CCM Interval %u%s]",
ccm_interval,
flags & CFM_CCM_RDI_FLAG ?
", RDI" : "");
/*
* Resolve the CCM interval field.
*/
if (ccm_interval) {
ND_PRINT("\n\t CCM Interval %.3fs"
", min CCM Lifetime %.3fs, max CCM Lifetime %.3fs",
ccm_interval_base[ccm_interval],
ccm_interval_base[ccm_interval] * CCM_INTERVAL_MIN_MULTIPLIER,
ccm_interval_base[ccm_interval] * CCM_INTERVAL_MAX_MULTIPLIER);
}
ND_PRINT("\n\t Sequence Number 0x%08x, MA-End-Point-ID 0x%04x",
GET_BE_U_4(msg_ptr.cfm_ccm->sequence),
GET_BE_U_2(msg_ptr.cfm_ccm->ma_epi));
namesp = msg_ptr.cfm_ccm->names;
names_data_remaining = sizeof(msg_ptr.cfm_ccm->names);
/*
* Resolve the MD fields.
*/
md_nameformat = GET_U_1(namesp);
namesp++;
names_data_remaining--; /* We know this is != 0 */
if (md_nameformat != CFM_CCM_MD_FORMAT_NONE) {
md_namelength = GET_U_1(namesp);
namesp++;
names_data_remaining--; /* We know this is !=0 */
ND_PRINT("\n\t MD Name Format %s (%u), MD Name length %u",
tok2str(cfm_md_nameformat_values, "Unknown",
md_nameformat),
md_nameformat,
md_namelength);
/*
* -3 for the MA short name format and length and one byte
* of MA short name.
*/
if (md_namelength > names_data_remaining - 3) {
ND_PRINT(" (too large, must be <= %u)", names_data_remaining - 2);
return;
}
md_name = namesp;
ND_PRINT("\n\t MD Name: ");
switch (md_nameformat) {
case CFM_CCM_MD_FORMAT_DNS:
case CFM_CCM_MD_FORMAT_CHAR:
nd_printjnp(ndo, md_name, md_namelength);
break;
case CFM_CCM_MD_FORMAT_MAC:
if (md_namelength == MAC_ADDR_LEN) {
ND_PRINT("\n\t MAC %s", GET_ETHERADDR_STRING(md_name));
} else {
ND_PRINT("\n\t MAC (length invalid)");
}
break;
/* FIXME add printers for those MD formats - hexdump for now */
case CFM_CCM_MA_FORMAT_8021:
default:
print_unknown_data(ndo, md_name, "\n\t ",
md_namelength);
}
namesp += md_namelength;
names_data_remaining -= md_namelength;
} else {
ND_PRINT("\n\t MD Name Format %s (%u)",
tok2str(cfm_md_nameformat_values, "Unknown",
md_nameformat),
md_nameformat);
}
/*
* Resolve the MA fields.
*/
ma_nameformat = GET_U_1(namesp);
namesp++;
names_data_remaining--; /* We know this is != 0 */
ma_namelength = GET_U_1(namesp);
namesp++;
names_data_remaining--; /* We know this is != 0 */
ND_PRINT("\n\t MA Name-Format %s (%u), MA name length %u",
tok2str(cfm_ma_nameformat_values, "Unknown",
ma_nameformat),
ma_nameformat,
ma_namelength);
if (ma_namelength > names_data_remaining) {
ND_PRINT(" (too large, must be <= %u)", names_data_remaining);
return;
}
ma_name = namesp;
ND_PRINT("\n\t MA Name: ");
switch (ma_nameformat) {
case CFM_CCM_MA_FORMAT_CHAR:
nd_printjnp(ndo, ma_name, ma_namelength);
break;
/* FIXME add printers for those MA formats - hexdump for now */
case CFM_CCM_MA_FORMAT_8021:
case CFM_CCM_MA_FORMAT_VID:
case CFM_CCM_MA_FORMAT_INT:
case CFM_CCM_MA_FORMAT_VPN:
default:
print_unknown_data(ndo, ma_name, "\n\t ", ma_namelength);
}
break;
case CFM_OPCODE_LTM:
msg_ptr.cfm_ltm = (const struct cfm_ltm_t *)tptr;
if (first_tlv_offset < sizeof(*msg_ptr.cfm_ltm)) {
ND_PRINT(" (too small 4, must be >= %zu)",
sizeof(*msg_ptr.cfm_ltm));
return;
}
if (tlen < sizeof(*msg_ptr.cfm_ltm))
goto tooshort;
ND_TCHECK_SIZE(msg_ptr.cfm_ltm);
ND_PRINT(", Flags [%s]",
bittok2str(cfm_ltm_flag_values, "none", flags));
ND_PRINT("\n\t Transaction-ID 0x%08x, ttl %u",
GET_BE_U_4(msg_ptr.cfm_ltm->transaction_id),
GET_U_1(msg_ptr.cfm_ltm->ttl));
ND_PRINT("\n\t Original-MAC %s, Target-MAC %s",
GET_ETHERADDR_STRING(msg_ptr.cfm_ltm->original_mac),
GET_ETHERADDR_STRING(msg_ptr.cfm_ltm->target_mac));
break;
case CFM_OPCODE_LTR:
msg_ptr.cfm_ltr = (const struct cfm_ltr_t *)tptr;
if (first_tlv_offset < sizeof(*msg_ptr.cfm_ltr)) {
ND_PRINT(" (too small 5, must be >= %zu)",
sizeof(*msg_ptr.cfm_ltr));
return;
}
if (tlen < sizeof(*msg_ptr.cfm_ltr))
goto tooshort;
ND_TCHECK_SIZE(msg_ptr.cfm_ltr);
ND_PRINT(", Flags [%s]",
bittok2str(cfm_ltr_flag_values, "none", flags));
ND_PRINT("\n\t Transaction-ID 0x%08x, ttl %u",
GET_BE_U_4(msg_ptr.cfm_ltr->transaction_id),
GET_U_1(msg_ptr.cfm_ltr->ttl));
ND_PRINT("\n\t Replay-Action %s (%u)",
tok2str(cfm_ltr_replay_action_values,
"Unknown",
GET_U_1(msg_ptr.cfm_ltr->replay_action)),
GET_U_1(msg_ptr.cfm_ltr->replay_action));
break;
/*
* No message decoder yet.
* Hexdump everything up until the start of the TLVs
*/
case CFM_OPCODE_LBR:
case CFM_OPCODE_LBM:
default:
print_unknown_data(ndo, tptr, "\n\t ",
tlen - first_tlv_offset);
break;
}
tptr += first_tlv_offset;
tlen -= first_tlv_offset;
while (tlen > 0) {
cfm_tlv_header = (const struct cfm_tlv_header_t *)tptr;
/* Enough to read the tlv type ? */
cfm_tlv_type = GET_U_1(cfm_tlv_header->type);
ND_PRINT("\n\t%s TLV (0x%02x)",
tok2str(cfm_tlv_values, "Unknown", cfm_tlv_type),
cfm_tlv_type);
if (cfm_tlv_type == CFM_TLV_END) {
/* Length is "Not present if the Type field is 0." */
return;
}
/* do we have the full tlv header ? */
if (tlen < sizeof(struct cfm_tlv_header_t))
goto tooshort;
ND_TCHECK_LEN(tptr, sizeof(struct cfm_tlv_header_t));
cfm_tlv_len=GET_BE_U_2(cfm_tlv_header->length);
ND_PRINT(", length %u", cfm_tlv_len);
tptr += sizeof(struct cfm_tlv_header_t);
tlen -= sizeof(struct cfm_tlv_header_t);
tlv_ptr = tptr;
/* do we have the full tlv ? */
if (tlen < cfm_tlv_len)
goto tooshort;
ND_TCHECK_LEN(tptr, cfm_tlv_len);
hexdump = FALSE;
switch(cfm_tlv_type) {
case CFM_TLV_PORT_STATUS:
if (cfm_tlv_len < 1) {
ND_PRINT(" (too short, must be >= 1)");
return;
}
ND_PRINT(", Status: %s (%u)",
tok2str(cfm_tlv_port_status_values, "Unknown", GET_U_1(tptr)),
GET_U_1(tptr));
break;
case CFM_TLV_INTERFACE_STATUS:
if (cfm_tlv_len < 1) {
ND_PRINT(" (too short, must be >= 1)");
return;
}
ND_PRINT(", Status: %s (%u)",
tok2str(cfm_tlv_interface_status_values, "Unknown", GET_U_1(tptr)),
GET_U_1(tptr));
break;
case CFM_TLV_PRIVATE:
if (cfm_tlv_len < 4) {
ND_PRINT(" (too short, must be >= 4)");
return;
}
ND_PRINT(", Vendor: %s (%u), Sub-Type %u",
tok2str(oui_values,"Unknown", GET_BE_U_3(tptr)),
GET_BE_U_3(tptr),
GET_U_1(tptr + 3));
hexdump = TRUE;
break;
case CFM_TLV_SENDER_ID:
{
u_int chassis_id_type, chassis_id_length;
u_int mgmt_addr_length;
if (cfm_tlv_len < 1) {
ND_PRINT(" (too short, must be >= 1)");
goto next_tlv;
}
/*
* Get the Chassis ID length and check it.
* IEEE 802.1Q-2014 Section 21.5.3.1
*/
chassis_id_length = GET_U_1(tptr);
tptr++;
tlen--;
cfm_tlv_len--;
if (chassis_id_length) {
/*
* IEEE 802.1Q-2014 Section 21.5.3.2: Chassis ID Subtype, references
* IEEE 802.1AB-2005 Section 9.5.2.2, subsequently
* IEEE 802.1AB-2016 Section 8.5.2.2: chassis ID subtype
*/
if (cfm_tlv_len < 1) {
ND_PRINT("\n\t (TLV too short)");
goto next_tlv;
}
chassis_id_type = GET_U_1(tptr);
cfm_tlv_len--;
ND_PRINT("\n\t Chassis-ID Type %s (%u), Chassis-ID length %u",
tok2str(cfm_tlv_senderid_chassisid_values,
"Unknown",
chassis_id_type),
chassis_id_type,
chassis_id_length);
if (cfm_tlv_len < chassis_id_length) {
ND_PRINT("\n\t (TLV too short)");
goto next_tlv;
}
/* IEEE 802.1Q-2014 Section 21.5.3.3: Chassis ID */
switch (chassis_id_type) {
case CFM_CHASSIS_ID_MAC_ADDRESS:
if (chassis_id_length != MAC_ADDR_LEN) {
ND_PRINT(" (invalid MAC address length)");
hexdump = TRUE;
break;
}
ND_PRINT("\n\t MAC %s", GET_ETHERADDR_STRING(tptr + 1));
break;
case CFM_CHASSIS_ID_NETWORK_ADDRESS:
hexdump |= cfm_network_addr_print(ndo, tptr + 1, chassis_id_length);
break;
case CFM_CHASSIS_ID_INTERFACE_NAME: /* fall through */
case CFM_CHASSIS_ID_INTERFACE_ALIAS:
case CFM_CHASSIS_ID_LOCAL:
case CFM_CHASSIS_ID_CHASSIS_COMPONENT:
case CFM_CHASSIS_ID_PORT_COMPONENT:
nd_printjnp(ndo, tptr + 1, chassis_id_length);
break;
default:
hexdump = TRUE;
break;
}
cfm_tlv_len -= chassis_id_length;
tptr += 1 + chassis_id_length;
tlen -= 1 + chassis_id_length;
}
/*
* Check if there is a Management Address.
* IEEE 802.1Q-2014 Section 21.5.3.4: Management Address Domain Length
* This and all subsequent fields are not present if the TLV length
* allows only the above fields.
*/
if (cfm_tlv_len == 0) {
/* No, there isn't; we're done. */
break;
}
/* Here mgmt_addr_length stands for the management domain length. */
mgmt_addr_length = GET_U_1(tptr);
tptr++;
tlen--;
cfm_tlv_len--;
ND_PRINT("\n\t Management Address Domain Length %u", mgmt_addr_length);
if (mgmt_addr_length) {
/* IEEE 802.1Q-2014 Section 21.5.3.5: Management Address Domain */
if (cfm_tlv_len < mgmt_addr_length) {
ND_PRINT("\n\t (TLV too short)");
goto next_tlv;
}
cfm_tlv_len -= mgmt_addr_length;
/*
* XXX - this is an OID; print it as such.
*/
hex_print(ndo, "\n\t Management Address Domain: ", tptr, mgmt_addr_length);
tptr += mgmt_addr_length;
tlen -= mgmt_addr_length;
/*
* IEEE 802.1Q-2014 Section 21.5.3.6: Management Address Length
* This field is present if Management Address Domain Length is not 0.
*/
if (cfm_tlv_len < 1) {
ND_PRINT(" (Management Address Length is missing)");
hexdump = TRUE;
break;
}
/* Here mgmt_addr_length stands for the management address length. */
mgmt_addr_length = GET_U_1(tptr);
tptr++;
tlen--;
cfm_tlv_len--;
ND_PRINT("\n\t Management Address Length %u", mgmt_addr_length);
if (mgmt_addr_length) {
/* IEEE 802.1Q-2014 Section 21.5.3.7: Management Address */
if (cfm_tlv_len < mgmt_addr_length) {
ND_PRINT("\n\t (TLV too short)");
return;
}
cfm_tlv_len -= mgmt_addr_length;
/*
* XXX - this is a TransportDomain; print it as such.
*/
hex_print(ndo, "\n\t Management Address: ", tptr, mgmt_addr_length);
tptr += mgmt_addr_length;
tlen -= mgmt_addr_length;
}
}
break;
}
/*
* FIXME those are the defined TLVs that lack a decoder
* you are welcome to contribute code ;-)
*/
case CFM_TLV_DATA:
case CFM_TLV_REPLY_INGRESS:
case CFM_TLV_REPLY_EGRESS:
default:
hexdump = TRUE;
break;
}
/* do we want to see an additional hexdump ? */
if (hexdump || ndo->ndo_vflag > 1)
print_unknown_data(ndo, tlv_ptr, "\n\t ", cfm_tlv_len);
next_tlv:
tptr+=cfm_tlv_len;
tlen-=cfm_tlv_len;
}
return;
tooshort:
ND_PRINT("\n\t\t packet is too short");
return;
trunc:
nd_print_trunc(ndo);
}
diff --git a/contrib/tcpdump/print-chdlc.c b/contrib/tcpdump/print-chdlc.c
index 235675da42b1..135d742ce2b9 100644
--- a/contrib/tcpdump/print-chdlc.c
+++ b/contrib/tcpdump/print-chdlc.c
@@ -1,198 +1,196 @@
/*
* 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.
*/
/* \summary: Cisco HDLC printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "addrtoname.h"
#include "ethertype.h"
#include "extract.h"
#include "chdlc.h"
#include "nlpid.h"
static void chdlc_slarp_print(netdissect_options *, const u_char *, u_int);
static const struct tok chdlc_cast_values[] = {
{ CHDLC_UNICAST, "unicast" },
{ CHDLC_BCAST, "bcast" },
{ 0, NULL}
};
/* Standard CHDLC printer */
void
chdlc_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
{
ndo->ndo_protocol = "chdlc";
ndo->ndo_ll_hdr_len += chdlc_print(ndo, p, h->len);
}
u_int
chdlc_print(netdissect_options *ndo, const u_char *p, u_int length)
{
u_int proto;
const u_char *bp = p;
ndo->ndo_protocol = "chdlc";
if (length < CHDLC_HDRLEN)
goto trunc;
proto = GET_BE_U_2(p + 2);
if (ndo->ndo_eflag) {
ND_PRINT("%s, ethertype %s (0x%04x), length %u: ",
tok2str(chdlc_cast_values, "0x%02x", GET_U_1(p)),
tok2str(ethertype_values, "Unknown", proto),
proto,
length);
}
length -= CHDLC_HDRLEN;
p += CHDLC_HDRLEN;
switch (proto) {
case ETHERTYPE_IP:
ip_print(ndo, p, length);
break;
case ETHERTYPE_IPV6:
ip6_print(ndo, p, length);
break;
case CHDLC_TYPE_SLARP:
chdlc_slarp_print(ndo, p, length);
break;
case ETHERTYPE_MPLS:
case ETHERTYPE_MPLS_MULTI:
mpls_print(ndo, p, length);
break;
case ETHERTYPE_ISO:
/* is the fudge byte set ? lets verify by spotting ISO headers */
if (length < 2)
goto trunc;
if (GET_U_1(p + 1) == NLPID_CLNP ||
GET_U_1(p + 1) == NLPID_ESIS ||
GET_U_1(p + 1) == NLPID_ISIS)
isoclns_print(ndo, p + 1, length - 1);
else
isoclns_print(ndo, p, length);
break;
default:
if (!ndo->ndo_eflag)
ND_PRINT("unknown CHDLC protocol (0x%04x)", proto);
break;
}
return (CHDLC_HDRLEN);
trunc:
nd_print_trunc(ndo);
return (ND_BYTES_AVAILABLE_AFTER(bp));
}
/*
* The fixed-length portion of a SLARP packet.
*/
struct cisco_slarp {
nd_uint32_t code;
#define SLARP_REQUEST 0
#define SLARP_REPLY 1
#define SLARP_KEEPALIVE 2
union {
struct {
uint8_t addr[4];
uint8_t mask[4];
} addr;
struct {
nd_uint32_t myseq;
nd_uint32_t yourseq;
nd_uint16_t rel;
} keep;
} un;
};
#define SLARP_MIN_LEN 14
#define SLARP_MAX_LEN 18
static void
chdlc_slarp_print(netdissect_options *ndo, const u_char *cp, u_int length)
{
const struct cisco_slarp *slarp;
u_int sec,min,hrs,days;
ndo->ndo_protocol = "chdlc_slarp";
ND_PRINT("SLARP (length: %u), ",length);
if (length < SLARP_MIN_LEN)
goto trunc;
slarp = (const struct cisco_slarp *)cp;
ND_TCHECK_LEN(slarp, SLARP_MIN_LEN);
switch (GET_BE_U_4(slarp->code)) {
case SLARP_REQUEST:
ND_PRINT("request");
/*
* At least according to William "Chops" Westfield's
* message in
*
* https://web.archive.org/web/20190725151313/www.nethelp.no/net/cisco-hdlc.txt
*
* the address and mask aren't used in requests -
* they're just zero.
*/
break;
case SLARP_REPLY:
ND_PRINT("reply %s/%s",
GET_IPADDR_STRING(slarp->un.addr.addr),
GET_IPADDR_STRING(slarp->un.addr.mask));
break;
case SLARP_KEEPALIVE:
ND_PRINT("keepalive: mineseen=0x%08x, yourseen=0x%08x, reliability=0x%04x",
GET_BE_U_4(slarp->un.keep.myseq),
GET_BE_U_4(slarp->un.keep.yourseq),
GET_BE_U_2(slarp->un.keep.rel));
if (length >= SLARP_MAX_LEN) { /* uptime-stamp is optional */
cp += SLARP_MIN_LEN;
sec = GET_BE_U_4(cp) / 1000;
min = sec / 60; sec -= min * 60;
hrs = min / 60; min -= hrs * 60;
days = hrs / 24; hrs -= days * 24;
ND_PRINT(", link uptime=%ud%uh%um%us",days,hrs,min,sec);
}
break;
default:
ND_PRINT("0x%02x unknown", GET_BE_U_4(slarp->code));
if (ndo->ndo_vflag <= 1)
print_unknown_data(ndo,cp+4,"\n\t",length-4);
break;
}
if (SLARP_MAX_LEN < length && ndo->ndo_vflag)
ND_PRINT(", (trailing junk: %u bytes)", length - SLARP_MAX_LEN);
if (ndo->ndo_vflag > 1)
print_unknown_data(ndo,cp+4,"\n\t",length-4);
return;
trunc:
nd_print_trunc(ndo);
}
diff --git a/contrib/tcpdump/print-cip.c b/contrib/tcpdump/print-cip.c
index b8ef77fd2fb3..96587fe0ffc7 100644
--- a/contrib/tcpdump/print-cip.c
+++ b/contrib/tcpdump/print-cip.c
@@ -1,87 +1,85 @@
/*
* Marko Kiiskila carnil@cs.tut.fi
*
* Tampere University of Technology - Telecommunications Laboratory
*
* Permission to use, copy, modify and distribute this
* software and its documentation is hereby granted,
* provided that both the copyright notice and this
* permission notice appear in all copies of the software,
* derivative works or modified versions, and any portions
* thereof, that both notices appear in supporting
* documentation, and that the use of this software is
* acknowledged in any publications resulting from using
* the software.
*
* TUT ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION AND DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS
* SOFTWARE.
*
*/
/* \summary: Linux Classical IP over ATM printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include <string.h>
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "addrtoname.h"
static const unsigned char rfcllc[] = {
0xaa, /* DSAP: non-ISO */
0xaa, /* SSAP: non-ISO */
0x03, /* Ctrl: Unnumbered Information Command PDU */
0x00, /* OUI: EtherType */
0x00,
0x00 };
/*
* This is the top level routine of the printer. 'p' points
* to the LLC/SNAP or raw header of the packet, 'h->ts' is the timestamp,
* 'h->len' is the length of the packet off the wire, and 'h->caplen'
* is the number of bytes actually captured.
*/
void
cip_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
{
u_int caplen = h->caplen;
u_int length = h->len;
int llc_hdrlen;
ndo->ndo_protocol = "cip";
if (ndo->ndo_eflag)
/*
* There is no MAC-layer header, so just print the length.
*/
ND_PRINT("%u: ", length);
ND_TCHECK_LEN(p, sizeof(rfcllc));
if (memcmp(rfcllc, p, sizeof(rfcllc)) == 0) {
/*
* LLC header is present. Try to print it & higher layers.
*/
llc_hdrlen = llc_print(ndo, p, length, caplen, NULL, NULL);
if (llc_hdrlen < 0) {
/* packet type not known, print raw packet */
if (!ndo->ndo_suppress_default_print)
ND_DEFAULTPRINT(p, caplen);
llc_hdrlen = -llc_hdrlen;
}
} else {
/*
* LLC header is absent; treat it as just IP.
*/
llc_hdrlen = 0;
ip_print(ndo, p, length);
}
ndo->ndo_ll_hdr_len += llc_hdrlen;
}
diff --git a/contrib/tcpdump/print-cnfp.c b/contrib/tcpdump/print-cnfp.c
index 101148fa86c0..553b051d483b 100644
--- a/contrib/tcpdump/print-cnfp.c
+++ b/contrib/tcpdump/print-cnfp.c
@@ -1,486 +1,484 @@
/* $OpenBSD: print-cnfp.c,v 1.2 1998/06/25 20:26:59 mickey Exp $ */
/*
* Copyright (c) 1998 Michael Shalayeff
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Michael Shalayeff.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* \summary: Cisco NetFlow protocol printer */
/*
* Cisco NetFlow protocol
*
* See
*
* https://www.cisco.com/c/en/us/td/docs/net_mgmt/netflow_collection_engine/3-6/user/guide/format.html#wp1005892
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <stdio.h>
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#include "tcp.h"
#include "ipproto.h"
struct nfhdr_v1 {
nd_uint16_t version; /* version number */
nd_uint16_t count; /* # of records */
nd_uint32_t msys_uptime;
nd_uint32_t utc_sec;
nd_uint32_t utc_nsec;
};
struct nfrec_v1 {
nd_ipv4 src_ina;
nd_ipv4 dst_ina;
nd_ipv4 nhop_ina;
nd_uint16_t input; /* SNMP index of input interface */
nd_uint16_t output; /* SNMP index of output interface */
nd_uint32_t packets; /* packets in the flow */
nd_uint32_t octets; /* layer 3 octets in the packets of the flow */
nd_uint32_t start_time; /* sys_uptime value at start of flow */
nd_uint32_t last_time; /* sys_uptime value when last packet of flow was received */
nd_uint16_t srcport; /* TCP/UDP source port or equivalent */
nd_uint16_t dstport; /* TCP/UDP source port or equivalent */
nd_byte pad1[2]; /* pad */
nd_uint8_t proto; /* IP protocol type */
nd_uint8_t tos; /* IP type of service */
nd_uint8_t tcp_flags; /* cumulative OR of TCP flags */
nd_byte pad[3]; /* padding */
nd_uint32_t reserved; /* unused */
};
struct nfhdr_v5 {
nd_uint16_t version; /* version number */
nd_uint16_t count; /* # of records */
nd_uint32_t msys_uptime;
nd_uint32_t utc_sec;
nd_uint32_t utc_nsec;
nd_uint32_t sequence; /* flow sequence number */
nd_uint8_t engine_type; /* type of flow-switching engine */
nd_uint8_t engine_id; /* slot number of the flow-switching engine */
nd_uint16_t sampling_interval; /* sampling mode and interval */
};
struct nfrec_v5 {
nd_ipv4 src_ina;
nd_ipv4 dst_ina;
nd_ipv4 nhop_ina;
nd_uint16_t input; /* SNMP index of input interface */
nd_uint16_t output; /* SNMP index of output interface */
nd_uint32_t packets; /* packets in the flow */
nd_uint32_t octets; /* layer 3 octets in the packets of the flow */
nd_uint32_t start_time; /* sys_uptime value at start of flow */
nd_uint32_t last_time; /* sys_uptime value when last packet of flow was received */
nd_uint16_t srcport; /* TCP/UDP source port or equivalent */
nd_uint16_t dstport; /* TCP/UDP source port or equivalent */
nd_byte pad1; /* pad */
nd_uint8_t tcp_flags; /* cumulative OR of TCP flags */
nd_uint8_t proto; /* IP protocol type */
nd_uint8_t tos; /* IP type of service */
nd_uint16_t src_as; /* AS number of the source */
nd_uint16_t dst_as; /* AS number of the destination */
nd_uint8_t src_mask; /* source address mask bits */
nd_uint8_t dst_mask; /* destination address prefix mask bits */
nd_byte pad2[2];
nd_ipv4 peer_nexthop; /* v6: IP address of the nexthop within the peer (FIB)*/
};
struct nfhdr_v6 {
nd_uint16_t version; /* version number */
nd_uint16_t count; /* # of records */
nd_uint32_t msys_uptime;
nd_uint32_t utc_sec;
nd_uint32_t utc_nsec;
nd_uint32_t sequence; /* v5 flow sequence number */
nd_uint32_t reserved; /* v5 only */
};
struct nfrec_v6 {
nd_ipv4 src_ina;
nd_ipv4 dst_ina;
nd_ipv4 nhop_ina;
nd_uint16_t input; /* SNMP index of input interface */
nd_uint16_t output; /* SNMP index of output interface */
nd_uint32_t packets; /* packets in the flow */
nd_uint32_t octets; /* layer 3 octets in the packets of the flow */
nd_uint32_t start_time; /* sys_uptime value at start of flow */
nd_uint32_t last_time; /* sys_uptime value when last packet of flow was received */
nd_uint16_t srcport; /* TCP/UDP source port or equivalent */
nd_uint16_t dstport; /* TCP/UDP source port or equivalent */
nd_byte pad1; /* pad */
nd_uint8_t tcp_flags; /* cumulative OR of TCP flags */
nd_uint8_t proto; /* IP protocol type */
nd_uint8_t tos; /* IP type of service */
nd_uint16_t src_as; /* AS number of the source */
nd_uint16_t dst_as; /* AS number of the destination */
nd_uint8_t src_mask; /* source address mask bits */
nd_uint8_t dst_mask; /* destination address prefix mask bits */
nd_uint16_t flags;
nd_ipv4 peer_nexthop; /* v6: IP address of the nexthop within the peer (FIB)*/
};
static void
cnfp_v1_print(netdissect_options *ndo, const u_char *cp)
{
const struct nfhdr_v1 *nh;
const struct nfrec_v1 *nr;
const char *p_name;
uint8_t proto;
u_int nrecs, ver;
#if 0
time_t t;
#endif
nh = (const struct nfhdr_v1 *)cp;
ND_TCHECK_SIZE(nh);
ver = GET_BE_U_2(nh->version);
nrecs = GET_BE_U_4(nh->count);
#if 0
/*
* This is seconds since the UN*X epoch, and is followed by
* nanoseconds. XXX - format it, rather than just dumping the
* raw seconds-since-the-Epoch.
*/
t = GET_BE_U_4(nh->utc_sec);
#endif
ND_PRINT("NetFlow v%x, %u.%03u uptime, %u.%09u, ", ver,
GET_BE_U_4(nh->msys_uptime)/1000,
GET_BE_U_4(nh->msys_uptime)%1000,
GET_BE_U_4(nh->utc_sec), GET_BE_U_4(nh->utc_nsec));
nr = (const struct nfrec_v1 *)&nh[1];
ND_PRINT("%2u recs", nrecs);
for (; nrecs != 0; nr++, nrecs--) {
char buf[20];
char asbuf[20];
/*
* Make sure we have the entire record.
*/
ND_TCHECK_SIZE(nr);
ND_PRINT("\n started %u.%03u, last %u.%03u",
GET_BE_U_4(nr->start_time)/1000,
GET_BE_U_4(nr->start_time)%1000,
GET_BE_U_4(nr->last_time)/1000,
GET_BE_U_4(nr->last_time)%1000);
asbuf[0] = buf[0] = '\0';
ND_PRINT("\n %s%s%s:%u ",
intoa(GET_IPV4_TO_NETWORK_ORDER(nr->src_ina)),
buf, asbuf,
GET_BE_U_2(nr->srcport));
ND_PRINT("> %s%s%s:%u ",
intoa(GET_IPV4_TO_NETWORK_ORDER(nr->dst_ina)),
buf, asbuf,
GET_BE_U_2(nr->dstport));
ND_PRINT(">> %s\n ",
intoa(GET_IPV4_TO_NETWORK_ORDER(nr->nhop_ina)));
proto = GET_U_1(nr->proto);
if (!ndo->ndo_nflag && (p_name = netdb_protoname(proto)) != NULL)
ND_PRINT("%s ", p_name);
else
ND_PRINT("%u ", proto);
/* tcp flags for tcp only */
if (proto == IPPROTO_TCP) {
u_int flags;
flags = GET_U_1(nr->tcp_flags);
ND_PRINT("%s%s%s%s%s%s%s",
flags & TH_FIN ? "F" : "",
flags & TH_SYN ? "S" : "",
flags & TH_RST ? "R" : "",
flags & TH_PUSH ? "P" : "",
flags & TH_ACK ? "A" : "",
flags & TH_URG ? "U" : "",
flags ? " " : "");
}
buf[0]='\0';
ND_PRINT("tos %u, %u (%u octets) %s",
GET_U_1(nr->tos),
GET_BE_U_4(nr->packets),
GET_BE_U_4(nr->octets), buf);
}
return;
trunc:
nd_print_trunc(ndo);
}
static void
cnfp_v5_print(netdissect_options *ndo, const u_char *cp)
{
const struct nfhdr_v5 *nh;
const struct nfrec_v5 *nr;
const char *p_name;
uint8_t proto;
u_int nrecs, ver;
#if 0
time_t t;
#endif
nh = (const struct nfhdr_v5 *)cp;
ND_TCHECK_SIZE(nh);
ver = GET_BE_U_2(nh->version);
nrecs = GET_BE_U_4(nh->count);
#if 0
/*
* This is seconds since the UN*X epoch, and is followed by
* nanoseconds. XXX - format it, rather than just dumping the
* raw seconds-since-the-Epoch.
*/
t = GET_BE_U_4(nh->utc_sec);
#endif
ND_PRINT("NetFlow v%x, %u.%03u uptime, %u.%09u, ", ver,
GET_BE_U_4(nh->msys_uptime)/1000,
GET_BE_U_4(nh->msys_uptime)%1000,
GET_BE_U_4(nh->utc_sec), GET_BE_U_4(nh->utc_nsec));
ND_PRINT("#%u, ", GET_BE_U_4(nh->sequence));
nr = (const struct nfrec_v5 *)&nh[1];
ND_PRINT("%2u recs", nrecs);
for (; nrecs != 0; nr++, nrecs--) {
char buf[20];
char asbuf[20];
/*
* Make sure we have the entire record.
*/
ND_TCHECK_SIZE(nr);
ND_PRINT("\n started %u.%03u, last %u.%03u",
GET_BE_U_4(nr->start_time)/1000,
GET_BE_U_4(nr->start_time)%1000,
GET_BE_U_4(nr->last_time)/1000,
GET_BE_U_4(nr->last_time)%1000);
asbuf[0] = buf[0] = '\0';
snprintf(buf, sizeof(buf), "/%u", GET_U_1(nr->src_mask));
snprintf(asbuf, sizeof(asbuf), ":%u",
GET_BE_U_2(nr->src_as));
ND_PRINT("\n %s%s%s:%u ",
intoa(GET_IPV4_TO_NETWORK_ORDER(nr->src_ina)),
buf, asbuf,
GET_BE_U_2(nr->srcport));
snprintf(buf, sizeof(buf), "/%u", GET_U_1(nr->dst_mask));
snprintf(asbuf, sizeof(asbuf), ":%u",
GET_BE_U_2(nr->dst_as));
ND_PRINT("> %s%s%s:%u ",
intoa(GET_IPV4_TO_NETWORK_ORDER(nr->dst_ina)),
buf, asbuf,
GET_BE_U_2(nr->dstport));
ND_PRINT(">> %s\n ",
intoa(GET_IPV4_TO_NETWORK_ORDER(nr->nhop_ina)));
proto = GET_U_1(nr->proto);
if (!ndo->ndo_nflag && (p_name = netdb_protoname(proto)) != NULL)
ND_PRINT("%s ", p_name);
else
ND_PRINT("%u ", proto);
/* tcp flags for tcp only */
if (proto == IPPROTO_TCP) {
u_int flags;
flags = GET_U_1(nr->tcp_flags);
ND_PRINT("%s%s%s%s%s%s%s",
flags & TH_FIN ? "F" : "",
flags & TH_SYN ? "S" : "",
flags & TH_RST ? "R" : "",
flags & TH_PUSH ? "P" : "",
flags & TH_ACK ? "A" : "",
flags & TH_URG ? "U" : "",
flags ? " " : "");
}
buf[0]='\0';
ND_PRINT("tos %u, %u (%u octets) %s",
GET_U_1(nr->tos),
GET_BE_U_4(nr->packets),
GET_BE_U_4(nr->octets), buf);
}
return;
trunc:
nd_print_trunc(ndo);
}
static void
cnfp_v6_print(netdissect_options *ndo, const u_char *cp)
{
const struct nfhdr_v6 *nh;
const struct nfrec_v6 *nr;
const char *p_name;
uint8_t proto;
u_int nrecs, ver;
#if 0
time_t t;
#endif
nh = (const struct nfhdr_v6 *)cp;
ND_TCHECK_SIZE(nh);
ver = GET_BE_U_2(nh->version);
nrecs = GET_BE_U_4(nh->count);
#if 0
/*
* This is seconds since the UN*X epoch, and is followed by
* nanoseconds. XXX - format it, rather than just dumping the
* raw seconds-since-the-Epoch.
*/
t = GET_BE_U_4(nh->utc_sec);
#endif
ND_PRINT("NetFlow v%x, %u.%03u uptime, %u.%09u, ", ver,
GET_BE_U_4(nh->msys_uptime)/1000,
GET_BE_U_4(nh->msys_uptime)%1000,
GET_BE_U_4(nh->utc_sec), GET_BE_U_4(nh->utc_nsec));
ND_PRINT("#%u, ", GET_BE_U_4(nh->sequence));
nr = (const struct nfrec_v6 *)&nh[1];
ND_PRINT("%2u recs", nrecs);
for (; nrecs != 0; nr++, nrecs--) {
char buf[20];
char asbuf[20];
/*
* Make sure we have the entire record.
*/
ND_TCHECK_SIZE(nr);
ND_PRINT("\n started %u.%03u, last %u.%03u",
GET_BE_U_4(nr->start_time)/1000,
GET_BE_U_4(nr->start_time)%1000,
GET_BE_U_4(nr->last_time)/1000,
GET_BE_U_4(nr->last_time)%1000);
asbuf[0] = buf[0] = '\0';
snprintf(buf, sizeof(buf), "/%u", GET_U_1(nr->src_mask));
snprintf(asbuf, sizeof(asbuf), ":%u",
GET_BE_U_2(nr->src_as));
ND_PRINT("\n %s%s%s:%u ",
intoa(GET_IPV4_TO_NETWORK_ORDER(nr->src_ina)),
buf, asbuf,
GET_BE_U_2(nr->srcport));
snprintf(buf, sizeof(buf), "/%u", GET_U_1(nr->dst_mask));
snprintf(asbuf, sizeof(asbuf), ":%u",
GET_BE_U_2(nr->dst_as));
ND_PRINT("> %s%s%s:%u ",
intoa(GET_IPV4_TO_NETWORK_ORDER(nr->dst_ina)),
buf, asbuf,
GET_BE_U_2(nr->dstport));
ND_PRINT(">> %s\n ",
intoa(GET_IPV4_TO_NETWORK_ORDER(nr->nhop_ina)));
proto = GET_U_1(nr->proto);
if (!ndo->ndo_nflag && (p_name = netdb_protoname(proto)) != NULL)
ND_PRINT("%s ", p_name);
else
ND_PRINT("%u ", proto);
/* tcp flags for tcp only */
if (proto == IPPROTO_TCP) {
u_int flags;
flags = GET_U_1(nr->tcp_flags);
ND_PRINT("%s%s%s%s%s%s%s",
flags & TH_FIN ? "F" : "",
flags & TH_SYN ? "S" : "",
flags & TH_RST ? "R" : "",
flags & TH_PUSH ? "P" : "",
flags & TH_ACK ? "A" : "",
flags & TH_URG ? "U" : "",
flags ? " " : "");
}
buf[0]='\0';
snprintf(buf, sizeof(buf), "(%u<>%u encaps)",
(GET_BE_U_2(nr->flags) >> 8) & 0xff,
(GET_BE_U_2(nr->flags)) & 0xff);
ND_PRINT("tos %u, %u (%u octets) %s",
GET_U_1(nr->tos),
GET_BE_U_4(nr->packets),
GET_BE_U_4(nr->octets), buf);
}
return;
trunc:
nd_print_trunc(ndo);
}
void
cnfp_print(netdissect_options *ndo, const u_char *cp)
{
int ver;
/*
* First 2 bytes are the version number.
*/
ndo->ndo_protocol = "cnfp";
ver = GET_BE_U_2(cp);
switch (ver) {
case 1:
cnfp_v1_print(ndo, cp);
break;
case 5:
cnfp_v5_print(ndo, cp);
break;
case 6:
cnfp_v6_print(ndo, cp);
break;
default:
ND_PRINT("NetFlow v%x", ver);
break;
}
}
diff --git a/contrib/tcpdump/print-dccp.c b/contrib/tcpdump/print-dccp.c
index 392345753798..62d8988b7e1d 100644
--- a/contrib/tcpdump/print-dccp.c
+++ b/contrib/tcpdump/print-dccp.c
@@ -1,705 +1,703 @@
/*
* Copyright (C) Arnaldo Carvalho de Melo 2004
* Copyright (C) Ian McDonald 2005
* Copyright (C) Yoshifumi Nishida 2005
*
* This software may be distributed either under the terms of the
* BSD-style license that accompanies tcpdump or the GNU GPL version 2
*/
/* \summary: Datagram Congestion Control Protocol (DCCP) printer */
/* specification: RFC 4340 */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#include "ip.h"
#include "ip6.h"
#include "ipproto.h"
/* RFC4340: Datagram Congestion Control Protocol (DCCP) */
/**
* struct dccp_hdr - generic part of DCCP packet header, with a 24-bit
* sequence number
*
* @dccph_sport - Relevant port on the endpoint that sent this packet
* @dccph_dport - Relevant port on the other endpoint
* @dccph_doff - Data Offset from the start of the DCCP header, in 32-bit words
* @dccph_ccval - Used by the HC-Sender CCID
* @dccph_cscov - Parts of the packet that are covered by the Checksum field
* @dccph_checksum - Internet checksum, depends on dccph_cscov
* @dccph_x - 0 = 24 bit sequence number, 1 = 48
* @dccph_type - packet type, see DCCP_PKT_ prefixed macros
* @dccph_seq - 24-bit sequence number
*/
struct dccp_hdr {
nd_uint16_t dccph_sport,
dccph_dport;
nd_uint8_t dccph_doff;
nd_uint8_t dccph_ccval_cscov;
nd_uint16_t dccph_checksum;
nd_uint8_t dccph_xtr;
nd_uint24_t dccph_seq;
};
/**
* struct dccp_hdr_ext - generic part of DCCP packet header, with a 48-bit
* sequence number
*
* @dccph_sport - Relevant port on the endpoint that sent this packet
* @dccph_dport - Relevant port on the other endpoint
* @dccph_doff - Data Offset from the start of the DCCP header, in 32-bit words
* @dccph_ccval - Used by the HC-Sender CCID
* @dccph_cscov - Parts of the packet that are covered by the Checksum field
* @dccph_checksum - Internet checksum, depends on dccph_cscov
* @dccph_x - 0 = 24 bit sequence number, 1 = 48
* @dccph_type - packet type, see DCCP_PKT_ prefixed macros
* @dccph_seq - 48-bit sequence number
*/
struct dccp_hdr_ext {
nd_uint16_t dccph_sport,
dccph_dport;
nd_uint8_t dccph_doff;
nd_uint8_t dccph_ccval_cscov;
nd_uint16_t dccph_checksum;
nd_uint8_t dccph_xtr;
nd_uint8_t reserved;
nd_uint48_t dccph_seq;
};
#define DCCPH_CCVAL(dh) ((GET_U_1((dh)->dccph_ccval_cscov) >> 4) & 0xF)
#define DCCPH_CSCOV(dh) (GET_U_1((dh)->dccph_ccval_cscov) & 0xF)
#define DCCPH_X(dh) (GET_U_1((dh)->dccph_xtr) & 1)
#define DCCPH_TYPE(dh) ((GET_U_1((dh)->dccph_xtr) >> 1) & 0xF)
/**
* struct dccp_hdr_request - Connection initiation request header
*
* @dccph_req_service - Service to which the client app wants to connect
*/
struct dccp_hdr_request {
nd_uint32_t dccph_req_service;
};
/**
* struct dccp_hdr_response - Connection initiation response header
*
* @dccph_resp_ack - 48 bit ack number, contains GSR
* @dccph_resp_service - Echoes the Service Code on a received DCCP-Request
*/
struct dccp_hdr_response {
nd_uint64_t dccph_resp_ack; /* always 8 bytes, first 2 reserved */
nd_uint32_t dccph_resp_service;
};
/**
* struct dccp_hdr_reset - Unconditionally shut down a connection
*
* @dccph_resp_ack - 48 bit ack number
* @dccph_reset_service - Echoes the Service Code on a received DCCP-Request
*/
struct dccp_hdr_reset {
nd_uint64_t dccph_reset_ack; /* always 8 bytes, first 2 reserved */
nd_uint8_t dccph_reset_code;
nd_uint8_t dccph_reset_data1;
nd_uint8_t dccph_reset_data2;
nd_uint8_t dccph_reset_data3;
};
enum dccp_pkt_type {
DCCP_PKT_REQUEST = 0,
DCCP_PKT_RESPONSE,
DCCP_PKT_DATA,
DCCP_PKT_ACK,
DCCP_PKT_DATAACK,
DCCP_PKT_CLOSEREQ,
DCCP_PKT_CLOSE,
DCCP_PKT_RESET,
DCCP_PKT_SYNC,
DCCP_PKT_SYNCACK
};
static const struct tok dccp_pkt_type_str[] = {
{ DCCP_PKT_REQUEST, "DCCP-Request" },
{ DCCP_PKT_RESPONSE, "DCCP-Response" },
{ DCCP_PKT_DATA, "DCCP-Data" },
{ DCCP_PKT_ACK, "DCCP-Ack" },
{ DCCP_PKT_DATAACK, "DCCP-DataAck" },
{ DCCP_PKT_CLOSEREQ, "DCCP-CloseReq" },
{ DCCP_PKT_CLOSE, "DCCP-Close" },
{ DCCP_PKT_RESET, "DCCP-Reset" },
{ DCCP_PKT_SYNC, "DCCP-Sync" },
{ DCCP_PKT_SYNCACK, "DCCP-SyncAck" },
{ 0, NULL}
};
enum dccp_reset_codes {
DCCP_RESET_CODE_UNSPECIFIED = 0,
DCCP_RESET_CODE_CLOSED,
DCCP_RESET_CODE_ABORTED,
DCCP_RESET_CODE_NO_CONNECTION,
DCCP_RESET_CODE_PACKET_ERROR,
DCCP_RESET_CODE_OPTION_ERROR,
DCCP_RESET_CODE_MANDATORY_ERROR,
DCCP_RESET_CODE_CONNECTION_REFUSED,
DCCP_RESET_CODE_BAD_SERVICE_CODE,
DCCP_RESET_CODE_TOO_BUSY,
DCCP_RESET_CODE_BAD_INIT_COOKIE,
DCCP_RESET_CODE_AGGRESSION_PENALTY,
__DCCP_RESET_CODE_LAST
};
static const char *dccp_reset_codes[] = {
"unspecified",
"closed",
"aborted",
"no_connection",
"packet_error",
"option_error",
"mandatory_error",
"connection_refused",
"bad_service_code",
"too_busy",
"bad_init_cookie",
"aggression_penalty",
};
static const char *dccp_feature_nums[] = {
"reserved",
"ccid",
"allow_short_seqno",
"sequence_window",
"ecn_incapable",
"ack_ratio",
"send_ack_vector",
"send_ndp_count",
"minimum checksum coverage",
"check data checksum",
};
static u_int
dccp_csum_coverage(netdissect_options *ndo,
const struct dccp_hdr *dh, u_int len)
{
u_int cov;
if (DCCPH_CSCOV(dh) == 0)
return len;
cov = (GET_U_1(dh->dccph_doff) + DCCPH_CSCOV(dh) - 1) * sizeof(uint32_t);
return (cov > len)? len : cov;
}
static uint16_t dccp_cksum(netdissect_options *ndo, const struct ip *ip,
const struct dccp_hdr *dh, u_int len)
{
return nextproto4_cksum(ndo, ip, (const uint8_t *)(const void *)dh, len,
dccp_csum_coverage(ndo, dh, len), IPPROTO_DCCP);
}
static uint16_t dccp6_cksum(netdissect_options *ndo, const struct ip6_hdr *ip6,
const struct dccp_hdr *dh, u_int len)
{
return nextproto6_cksum(ndo, ip6, (const uint8_t *)(const void *)dh, len,
dccp_csum_coverage(ndo, dh, len), IPPROTO_DCCP);
}
static const char *dccp_reset_code(uint8_t code)
{
if (code >= __DCCP_RESET_CODE_LAST)
return "invalid";
return dccp_reset_codes[code];
}
static uint64_t
dccp_seqno(netdissect_options *ndo, const u_char *bp)
{
const struct dccp_hdr *dh = (const struct dccp_hdr *)bp;
uint64_t seqno;
if (DCCPH_X(dh) != 0) {
const struct dccp_hdr_ext *dhx = (const struct dccp_hdr_ext *)bp;
seqno = GET_BE_U_6(dhx->dccph_seq);
} else {
seqno = GET_BE_U_3(dh->dccph_seq);
}
return seqno;
}
static unsigned int
dccp_basic_hdr_len(netdissect_options *ndo, const struct dccp_hdr *dh)
{
return DCCPH_X(dh) ? sizeof(struct dccp_hdr_ext) : sizeof(struct dccp_hdr);
}
static void dccp_print_ack_no(netdissect_options *ndo, const u_char *bp)
{
const struct dccp_hdr *dh = (const struct dccp_hdr *)bp;
const u_char *ackp = bp + dccp_basic_hdr_len(ndo, dh);
uint64_t ackno;
if (DCCPH_X(dh) != 0) {
ackno = GET_BE_U_6(ackp + 2);
} else {
ackno = GET_BE_U_3(ackp + 1);
}
ND_PRINT("(ack=%" PRIu64 ") ", ackno);
}
static u_int dccp_print_option(netdissect_options *, const u_char *, u_int);
/**
* dccp_print - show dccp packet
* @bp - beginning of dccp packet
* @data2 - beginning of enclosing
* @len - length of ip packet
*/
void
dccp_print(netdissect_options *ndo, const u_char *bp, const u_char *data2,
u_int len)
{
const struct dccp_hdr *dh;
const struct ip *ip;
const struct ip6_hdr *ip6;
const u_char *cp;
u_short sport, dport;
u_int hlen;
u_int fixed_hdrlen;
uint8_t dccph_type;
ndo->ndo_protocol = "dccp";
dh = (const struct dccp_hdr *)bp;
ip = (const struct ip *)data2;
if (IP_V(ip) == 6)
ip6 = (const struct ip6_hdr *)data2;
else
ip6 = NULL;
/* make sure we have enough data to look at the X bit */
cp = (const u_char *)(dh + 1);
if (cp > ndo->ndo_snapend)
goto trunc;
if (len < sizeof(struct dccp_hdr)) {
ND_PRINT("truncated-dccp - %zu bytes missing!",
sizeof(struct dccp_hdr) - len);
return;
}
/* get the length of the generic header */
fixed_hdrlen = dccp_basic_hdr_len(ndo, dh);
if (len < fixed_hdrlen) {
ND_PRINT("truncated-dccp - %u bytes missing!",
fixed_hdrlen - len);
return;
}
ND_TCHECK_LEN(dh, fixed_hdrlen);
sport = GET_BE_U_2(dh->dccph_sport);
dport = GET_BE_U_2(dh->dccph_dport);
hlen = GET_U_1(dh->dccph_doff) * 4;
if (ip6) {
ND_PRINT("%s.%u > %s.%u: ",
GET_IP6ADDR_STRING(ip6->ip6_src), sport,
GET_IP6ADDR_STRING(ip6->ip6_dst), dport);
} else {
ND_PRINT("%s.%u > %s.%u: ",
GET_IPADDR_STRING(ip->ip_src), sport,
GET_IPADDR_STRING(ip->ip_dst), dport);
}
nd_print_protocol_caps(ndo);
if (ndo->ndo_qflag) {
ND_PRINT(" %u", len - hlen);
if (hlen > len) {
ND_PRINT(" [bad hdr length %u - too long, > %u]",
hlen, len);
}
return;
}
/* other variables in generic header */
if (ndo->ndo_vflag) {
ND_PRINT(" (CCVal %u, CsCov %u", DCCPH_CCVAL(dh), DCCPH_CSCOV(dh));
}
/* checksum calculation */
if (ndo->ndo_vflag && ND_TTEST_LEN(bp, len)) {
uint16_t sum = 0, dccp_sum;
dccp_sum = GET_BE_U_2(dh->dccph_checksum);
ND_PRINT(", cksum 0x%04x ", dccp_sum);
if (IP_V(ip) == 4)
sum = dccp_cksum(ndo, ip, dh, len);
else if (IP_V(ip) == 6)
sum = dccp6_cksum(ndo, ip6, dh, len);
if (sum != 0)
ND_PRINT("(incorrect -> 0x%04x)",in_cksum_shouldbe(dccp_sum, sum));
else
ND_PRINT("(correct)");
}
if (ndo->ndo_vflag)
ND_PRINT(")");
ND_PRINT(" ");
dccph_type = DCCPH_TYPE(dh);
switch (dccph_type) {
case DCCP_PKT_REQUEST: {
const struct dccp_hdr_request *dhr =
(const struct dccp_hdr_request *)(bp + fixed_hdrlen);
fixed_hdrlen += 4;
if (len < fixed_hdrlen) {
ND_PRINT("truncated-%s - %u bytes missing!",
tok2str(dccp_pkt_type_str, "", dccph_type),
fixed_hdrlen - len);
return;
}
ND_TCHECK_SIZE(dhr);
ND_PRINT("%s (service=%u) ",
tok2str(dccp_pkt_type_str, "", dccph_type),
GET_BE_U_4(dhr->dccph_req_service));
break;
}
case DCCP_PKT_RESPONSE: {
const struct dccp_hdr_response *dhr =
(const struct dccp_hdr_response *)(bp + fixed_hdrlen);
fixed_hdrlen += 12;
if (len < fixed_hdrlen) {
ND_PRINT("truncated-%s - %u bytes missing!",
tok2str(dccp_pkt_type_str, "", dccph_type),
fixed_hdrlen - len);
return;
}
ND_TCHECK_SIZE(dhr);
ND_PRINT("%s (service=%u) ",
tok2str(dccp_pkt_type_str, "", dccph_type),
GET_BE_U_4(dhr->dccph_resp_service));
break;
}
case DCCP_PKT_DATA:
ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type));
break;
case DCCP_PKT_ACK: {
fixed_hdrlen += 8;
if (len < fixed_hdrlen) {
ND_PRINT("truncated-%s - %u bytes missing!",
tok2str(dccp_pkt_type_str, "", dccph_type),
fixed_hdrlen - len);
return;
}
ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type));
break;
}
case DCCP_PKT_DATAACK: {
fixed_hdrlen += 8;
if (len < fixed_hdrlen) {
ND_PRINT("truncated-%s - %u bytes missing!",
tok2str(dccp_pkt_type_str, "", dccph_type),
fixed_hdrlen - len);
return;
}
ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type));
break;
}
case DCCP_PKT_CLOSEREQ:
fixed_hdrlen += 8;
if (len < fixed_hdrlen) {
ND_PRINT("truncated-%s - %u bytes missing!",
tok2str(dccp_pkt_type_str, "", dccph_type),
fixed_hdrlen - len);
return;
}
ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type));
break;
case DCCP_PKT_CLOSE:
fixed_hdrlen += 8;
if (len < fixed_hdrlen) {
ND_PRINT("truncated-%s - %u bytes missing!",
tok2str(dccp_pkt_type_str, "", dccph_type),
fixed_hdrlen - len);
return;
}
ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type));
break;
case DCCP_PKT_RESET: {
const struct dccp_hdr_reset *dhr =
(const struct dccp_hdr_reset *)(bp + fixed_hdrlen);
fixed_hdrlen += 12;
if (len < fixed_hdrlen) {
ND_PRINT("truncated-%s - %u bytes missing!",
tok2str(dccp_pkt_type_str, "", dccph_type),
fixed_hdrlen - len);
return;
}
ND_TCHECK_SIZE(dhr);
ND_PRINT("%s (code=%s) ",
tok2str(dccp_pkt_type_str, "", dccph_type),
dccp_reset_code(GET_U_1(dhr->dccph_reset_code)));
break;
}
case DCCP_PKT_SYNC:
fixed_hdrlen += 8;
if (len < fixed_hdrlen) {
ND_PRINT("truncated-%s - %u bytes missing!",
tok2str(dccp_pkt_type_str, "", dccph_type),
fixed_hdrlen - len);
return;
}
ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type));
break;
case DCCP_PKT_SYNCACK:
fixed_hdrlen += 8;
if (len < fixed_hdrlen) {
ND_PRINT("truncated-%s - %u bytes missing!",
tok2str(dccp_pkt_type_str, "", dccph_type),
fixed_hdrlen - len);
return;
}
ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type));
break;
default:
ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "unknown-type-%u", dccph_type));
break;
}
if ((DCCPH_TYPE(dh) != DCCP_PKT_DATA) &&
(DCCPH_TYPE(dh) != DCCP_PKT_REQUEST))
dccp_print_ack_no(ndo, bp);
if (ndo->ndo_vflag < 2)
return;
ND_PRINT("seq %" PRIu64, dccp_seqno(ndo, bp));
/* process options */
if (hlen > fixed_hdrlen){
u_int optlen;
cp = bp + fixed_hdrlen;
ND_PRINT(" <");
hlen -= fixed_hdrlen;
while(1){
optlen = dccp_print_option(ndo, cp, hlen);
if (!optlen)
break;
if (hlen <= optlen)
break;
hlen -= optlen;
cp += optlen;
ND_PRINT(", ");
}
ND_PRINT(">");
}
return;
trunc:
nd_print_trunc(ndo);
}
static const struct tok dccp_option_values[] = {
{ 0, "nop" },
{ 1, "mandatory" },
{ 2, "slowreceiver" },
{ 32, "change_l" },
{ 33, "confirm_l" },
{ 34, "change_r" },
{ 35, "confirm_r" },
{ 36, "initcookie" },
{ 37, "ndp_count" },
{ 38, "ack_vector0" },
{ 39, "ack_vector1" },
{ 40, "data_dropped" },
{ 41, "timestamp" },
{ 42, "timestamp_echo" },
{ 43, "elapsed_time" },
{ 44, "data_checksum" },
{ 0, NULL }
};
static u_int
dccp_print_option(netdissect_options *ndo, const u_char *option, u_int hlen)
{
uint8_t optlen, i;
if (GET_U_1(option) >= 32) {
optlen = GET_U_1(option + 1);
if (optlen < 2) {
if (GET_U_1(option) >= 128)
ND_PRINT("CCID option %u optlen too short",
GET_U_1(option));
else
ND_PRINT("%s optlen too short",
tok2str(dccp_option_values, "Option %u", GET_U_1(option)));
return 0;
}
} else
optlen = 1;
if (hlen < optlen) {
if (GET_U_1(option) >= 128)
ND_PRINT("CCID option %u optlen goes past header length",
GET_U_1(option));
else
ND_PRINT("%s optlen goes past header length",
tok2str(dccp_option_values, "Option %u", GET_U_1(option)));
return 0;
}
ND_TCHECK_LEN(option, optlen);
if (GET_U_1(option) >= 128) {
ND_PRINT("CCID option %u", GET_U_1(option));
switch (optlen) {
case 4:
ND_PRINT(" %u", GET_BE_U_2(option + 2));
break;
case 6:
ND_PRINT(" %u", GET_BE_U_4(option + 2));
break;
default:
break;
}
} else {
ND_PRINT("%s",
tok2str(dccp_option_values, "Option %u", GET_U_1(option)));
switch (GET_U_1(option)) {
case 32:
case 33:
case 34:
case 35:
if (optlen < 3) {
ND_PRINT(" optlen too short");
return optlen;
}
if (GET_U_1(option + 2) < 10){
ND_PRINT(" %s",
dccp_feature_nums[GET_U_1(option + 2)]);
for (i = 0; i < optlen - 3; i++)
ND_PRINT(" %u",
GET_U_1(option + 3 + i));
}
break;
case 36:
if (optlen > 2) {
ND_PRINT(" 0x");
for (i = 0; i < optlen - 2; i++)
ND_PRINT("%02x",
GET_U_1(option + 2 + i));
}
break;
case 37:
for (i = 0; i < optlen - 2; i++)
ND_PRINT(" %u", GET_U_1(option + 2 + i));
break;
case 38:
if (optlen > 2) {
ND_PRINT(" 0x");
for (i = 0; i < optlen - 2; i++)
ND_PRINT("%02x",
GET_U_1(option + 2 + i));
}
break;
case 39:
if (optlen > 2) {
ND_PRINT(" 0x");
for (i = 0; i < optlen - 2; i++)
ND_PRINT("%02x",
GET_U_1(option + 2 + i));
}
break;
case 40:
if (optlen > 2) {
ND_PRINT(" 0x");
for (i = 0; i < optlen - 2; i++)
ND_PRINT("%02x",
GET_U_1(option + 2 + i));
}
break;
case 41:
/*
* 13.1. Timestamp Option
*
* +--------+--------+--------+--------+--------+--------+
* |00101001|00000110| Timestamp Value |
* +--------+--------+--------+--------+--------+--------+
* Type=41 Length=6
*/
if (optlen == 6)
ND_PRINT(" %u", GET_BE_U_4(option + 2));
else
ND_PRINT(" [optlen != 6]");
break;
case 42:
/*
* 13.3. Timestamp Echo Option
*
* +--------+--------+--------+--------+--------+--------+
* |00101010|00000110| Timestamp Echo |
* +--------+--------+--------+--------+--------+--------+
* Type=42 Len=6
*
* +--------+--------+------- ... -------+--------+--------+
* |00101010|00001000| Timestamp Echo | Elapsed Time |
* +--------+--------+------- ... -------+--------+--------+
* Type=42 Len=8 (4 bytes)
*
* +--------+--------+------- ... -------+------- ... -------+
* |00101010|00001010| Timestamp Echo | Elapsed Time |
* +--------+--------+------- ... -------+------- ... -------+
* Type=42 Len=10 (4 bytes) (4 bytes)
*/
switch (optlen) {
case 6:
ND_PRINT(" %u", GET_BE_U_4(option + 2));
break;
case 8:
ND_PRINT(" %u", GET_BE_U_4(option + 2));
ND_PRINT(" (elapsed time %u)",
GET_BE_U_2(option + 6));
break;
case 10:
ND_PRINT(" %u", GET_BE_U_4(option + 2));
ND_PRINT(" (elapsed time %u)",
GET_BE_U_4(option + 6));
break;
default:
ND_PRINT(" [optlen != 6 or 8 or 10]");
break;
}
break;
case 43:
if (optlen == 6)
ND_PRINT(" %u", GET_BE_U_4(option + 2));
else if (optlen == 4)
ND_PRINT(" %u", GET_BE_U_2(option + 2));
else
ND_PRINT(" [optlen != 4 or 6]");
break;
case 44:
if (optlen > 2) {
ND_PRINT(" ");
for (i = 0; i < optlen - 2; i++)
ND_PRINT("%02x",
GET_U_1(option + 2 + i));
}
break;
}
}
return optlen;
trunc:
nd_print_trunc(ndo);
return 0;
}
diff --git a/contrib/tcpdump/print-decnet.c b/contrib/tcpdump/print-decnet.c
index 6a6dd25982f9..a114e2d3bccd 100644
--- a/contrib/tcpdump/print-decnet.c
+++ b/contrib/tcpdump/print-decnet.c
@@ -1,1182 +1,1180 @@
/*
* Copyright (c) 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.
*/
/* \summary: DECnet printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <stdio.h>
#include <stdlib.h>
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
#include "addrtoname.h"
#ifndef _WIN32
typedef nd_uint8_t byte; /* single byte field */
#else
/*
* the keyword 'byte' generates conflicts in Windows
*/
typedef nd_uint8_t Byte; /* single byte field */
#define byte Byte
#endif /* _WIN32 */
typedef nd_uint16_t word; /* 2 byte field */
typedef nd_uint32_t longword; /* 4 bytes field */
/*
* Definitions for DECNET Phase IV protocol headers
*/
typedef union {
nd_mac_addr dne_addr; /* full Ethernet address */
struct {
nd_byte dne_hiord[4]; /* DECnet HIORD prefix */
nd_byte dne_nodeaddr[2]; /* DECnet node address */
} dne_remote;
} etheraddr; /* Ethernet address */
#define HIORD 0x000400aa /* high 32-bits of address (swapped) */
#define AREAMASK 0176000 /* mask for area field */
#define AREASHIFT 10 /* bit-offset for area field */
#define NODEMASK 01777 /* mask for node address field */
/*
* Define long and short header formats.
*/
struct shorthdr
{
byte sh_flags; /* route flags */
word sh_dst; /* destination node address */
word sh_src; /* source node address */
byte sh_visits; /* visit count */
};
struct longhdr
{
byte lg_flags; /* route flags */
byte lg_darea; /* destination area (reserved) */
byte lg_dsarea; /* destination subarea (reserved) */
etheraddr lg_dst; /* destination id */
byte lg_sarea; /* source area (reserved) */
byte lg_ssarea; /* source subarea (reserved) */
etheraddr lg_src; /* source id */
byte lg_nextl2; /* next level 2 router (reserved) */
byte lg_visits; /* visit count */
byte lg_service; /* service class (reserved) */
byte lg_pt; /* protocol type (reserved) */
};
union routehdr
{
struct shorthdr rh_short; /* short route header */
struct longhdr rh_long; /* long route header */
};
/*
* Define the values of various fields in the protocol messages.
*
* 1. Data packet formats.
*/
#define RMF_MASK 7 /* mask for message type */
#define RMF_SHORT 2 /* short message format */
#define RMF_LONG 6 /* long message format */
#ifndef RMF_RQR
#define RMF_RQR 010 /* request return to sender */
#define RMF_RTS 020 /* returning to sender */
#define RMF_IE 040 /* intra-ethernet packet */
#endif /* RMR_RQR */
#define RMF_FVER 0100 /* future version flag */
#define RMF_PAD 0200 /* pad field */
#define RMF_PADMASK 0177 /* pad field mask */
#define VIS_MASK 077 /* visit field mask */
/*
* 2. Control packet formats.
*/
#define RMF_CTLMASK 017 /* mask for message type */
#define RMF_CTLMSG 01 /* control message indicator */
#define RMF_INIT 01 /* initialization message */
#define RMF_VER 03 /* verification message */
#define RMF_TEST 05 /* hello and test message */
#define RMF_L1ROUT 07 /* level 1 routing message */
#define RMF_L2ROUT 011 /* level 2 routing message */
#define RMF_RHELLO 013 /* router hello message */
#define RMF_EHELLO 015 /* endnode hello message */
#define TI_L2ROUT 01 /* level 2 router */
#define TI_L1ROUT 02 /* level 1 router */
#define TI_ENDNODE 03 /* endnode */
#define TI_VERIF 04 /* verification required */
#define TI_BLOCK 010 /* blocking requested */
#define VE_VERS 2 /* version number (2) */
#define VE_ECO 0 /* ECO number */
#define VE_UECO 0 /* user ECO number (0) */
#define P3_VERS 1 /* phase III version number (1) */
#define P3_ECO 3 /* ECO number (3) */
#define P3_UECO 0 /* user ECO number (0) */
#define II_L2ROUT 01 /* level 2 router */
#define II_L1ROUT 02 /* level 1 router */
#define II_ENDNODE 03 /* endnode */
#define II_VERIF 04 /* verification required */
#define II_NOMCAST 040 /* no multicast traffic accepted */
#define II_BLOCK 0100 /* blocking requested */
#define II_TYPEMASK 03 /* mask for node type */
#define TESTDATA 0252 /* test data bytes */
#define TESTLEN 1 /* length of transmitted test data */
/*
* Define control message formats.
*/
struct initmsg /* initialization message */
{
byte in_flags; /* route flags */
word in_src; /* source node address */
byte in_info; /* routing layer information */
word in_blksize; /* maximum data link block size */
byte in_vers; /* version number */
byte in_eco; /* ECO number */
byte in_ueco; /* user ECO number */
word in_hello; /* hello timer */
byte in_rsvd; /* reserved image field */
};
struct verifmsg /* verification message */
{
byte ve_flags; /* route flags */
word ve_src; /* source node address */
byte ve_fcnval; /* function value image field */
};
struct testmsg /* hello and test message */
{
byte te_flags; /* route flags */
word te_src; /* source node address */
byte te_data; /* test data image field */
};
struct l1rout /* level 1 routing message */
{
byte r1_flags; /* route flags */
word r1_src; /* source node address */
byte r1_rsvd; /* reserved field */
};
struct l2rout /* level 2 routing message */
{
byte r2_flags; /* route flags */
word r2_src; /* source node address */
byte r2_rsvd; /* reserved field */
};
struct rhellomsg /* router hello message */
{
byte rh_flags; /* route flags */
byte rh_vers; /* version number */
byte rh_eco; /* ECO number */
byte rh_ueco; /* user ECO number */
etheraddr rh_src; /* source id */
byte rh_info; /* routing layer information */
word rh_blksize; /* maximum data link block size */
byte rh_priority; /* router's priority */
byte rh_area; /* reserved */
word rh_hello; /* hello timer */
byte rh_mpd; /* reserved */
};
struct ehellomsg /* endnode hello message */
{
byte eh_flags; /* route flags */
byte eh_vers; /* version number */
byte eh_eco; /* ECO number */
byte eh_ueco; /* user ECO number */
etheraddr eh_src; /* source id */
byte eh_info; /* routing layer information */
word eh_blksize; /* maximum data link block size */
byte eh_area; /* area (reserved) */
byte eh_seed[8]; /* verification seed */
etheraddr eh_router; /* designated router */
word eh_hello; /* hello timer */
byte eh_mpd; /* (reserved) */
byte eh_data; /* test data image field */
};
union controlmsg
{
struct initmsg cm_init; /* initialization message */
struct verifmsg cm_ver; /* verification message */
struct testmsg cm_test; /* hello and test message */
struct l1rout cm_l1rou; /* level 1 routing message */
struct l2rout cm_l2rout; /* level 2 routing message */
struct rhellomsg cm_rhello; /* router hello message */
struct ehellomsg cm_ehello; /* endnode hello message */
};
/* Macros for decoding routing-info fields */
#define RI_COST(x) ((x)&0777)
#define RI_HOPS(x) (((x)>>10)&037)
/*
* NSP protocol fields and values.
*/
#define NSP_TYPEMASK 014 /* mask to isolate type code */
#define NSP_SUBMASK 0160 /* mask to isolate subtype code */
#define NSP_SUBSHFT 4 /* shift to move subtype code */
#define MFT_DATA 0 /* data message */
#define MFT_ACK 04 /* acknowledgement message */
#define MFT_CTL 010 /* control message */
#define MFS_ILS 020 /* data or I/LS indicator */
#define MFS_BOM 040 /* beginning of message (data) */
#define MFS_MOM 0 /* middle of message (data) */
#define MFS_EOM 0100 /* end of message (data) */
#define MFS_INT 040 /* interrupt message */
#define MFS_DACK 0 /* data acknowledgement */
#define MFS_IACK 020 /* I/LS acknowledgement */
#define MFS_CACK 040 /* connect acknowledgement */
#define MFS_NOP 0 /* no operation */
#define MFS_CI 020 /* connect initiate */
#define MFS_CC 040 /* connect confirm */
#define MFS_DI 060 /* disconnect initiate */
#define MFS_DC 0100 /* disconnect confirm */
#define MFS_RCI 0140 /* retransmitted connect initiate */
#define SGQ_ACK 0100000 /* ack */
#define SGQ_NAK 0110000 /* negative ack */
#define SGQ_OACK 0120000 /* other channel ack */
#define SGQ_ONAK 0130000 /* other channel negative ack */
#define SGQ_MASK 07777 /* mask to isolate seq # */
#define SGQ_OTHER 020000 /* other channel qualifier */
#define SGQ_DELAY 010000 /* ack delay flag */
#define SGQ_EOM 0100000 /* pseudo flag for end-of-message */
#define LSM_MASK 03 /* mask for modifier field */
#define LSM_NOCHANGE 0 /* no change */
#define LSM_DONOTSEND 1 /* do not send data */
#define LSM_SEND 2 /* send data */
#define LSI_MASK 014 /* mask for interpretation field */
#define LSI_DATA 0 /* data segment or message count */
#define LSI_INTR 4 /* interrupt request count */
#define LSI_INTM 0377 /* funny marker for int. message */
#define COS_MASK 014 /* mask for flow control field */
#define COS_NONE 0 /* no flow control */
#define COS_SEGMENT 04 /* segment flow control */
#define COS_MESSAGE 010 /* message flow control */
#define COS_DEFAULT 1 /* default value for field */
#define COI_MASK 3 /* mask for version field */
#define COI_32 0 /* version 3.2 */
#define COI_31 1 /* version 3.1 */
#define COI_40 2 /* version 4.0 */
#define COI_41 3 /* version 4.1 */
#define MNU_MASK 140 /* mask for session control version */
#define MNU_10 000 /* session V1.0 */
#define MNU_20 040 /* session V2.0 */
#define MNU_ACCESS 1 /* access control present */
#define MNU_USRDATA 2 /* user data field present */
#define MNU_INVKPROXY 4 /* invoke proxy field present */
#define MNU_UICPROXY 8 /* use uic-based proxy */
#define DC_NORESOURCES 1 /* no resource reason code */
#define DC_NOLINK 41 /* no link terminate reason code */
#define DC_COMPLETE 42 /* disconnect complete reason code */
#define DI_NOERROR 0 /* user disconnect */
#define DI_SHUT 3 /* node is shutting down */
#define DI_NOUSER 4 /* destination end user does not exist */
#define DI_INVDEST 5 /* invalid end user destination */
#define DI_REMRESRC 6 /* insufficient remote resources */
#define DI_TPA 8 /* third party abort */
#define DI_PROTOCOL 7 /* protocol error discovered */
#define DI_ABORT 9 /* user abort */
#define DI_LOCALRESRC 32 /* insufficient local resources */
#define DI_REMUSERRESRC 33 /* insufficient remote user resources */
#define DI_BADACCESS 34 /* bad access control information */
#define DI_BADACCNT 36 /* bad ACCOUNT information */
#define DI_CONNECTABORT 38 /* connect request cancelled */
#define DI_TIMEDOUT 38 /* remote node or user crashed */
#define DI_UNREACHABLE 39 /* local timers expired due to ... */
#define DI_BADIMAGE 43 /* bad image data in connect */
#define DI_SERVMISMATCH 54 /* cryptographic service mismatch */
#define UC_OBJREJECT 0 /* object rejected connect */
#define UC_USERDISCONNECT 0 /* user disconnect */
#define UC_RESOURCES 1 /* insufficient resources (local or remote) */
#define UC_NOSUCHNODE 2 /* unrecognized node name */
#define UC_REMOTESHUT 3 /* remote node shutting down */
#define UC_NOSUCHOBJ 4 /* unrecognized object */
#define UC_INVOBJFORMAT 5 /* invalid object name format */
#define UC_OBJTOOBUSY 6 /* object too busy */
#define UC_NETWORKABORT 8 /* network abort */
#define UC_USERABORT 9 /* user abort */
#define UC_INVNODEFORMAT 10 /* invalid node name format */
#define UC_LOCALSHUT 11 /* local node shutting down */
#define UC_ACCESSREJECT 34 /* invalid access control information */
#define UC_NORESPONSE 38 /* no response from object */
#define UC_UNREACHABLE 39 /* node unreachable */
/*
* NSP message formats.
*/
struct nsphdr /* general nsp header */
{
byte nh_flags; /* message flags */
word nh_dst; /* destination link address */
word nh_src; /* source link address */
};
struct seghdr /* data segment header */
{
byte sh_flags; /* message flags */
word sh_dst; /* destination link address */
word sh_src; /* source link address */
word sh_seq[3]; /* sequence numbers */
};
struct minseghdr /* minimum data segment header */
{
byte ms_flags; /* message flags */
word ms_dst; /* destination link address */
word ms_src; /* source link address */
word ms_seq; /* sequence number */
};
struct lsmsg /* link service message (after hdr) */
{
byte ls_lsflags; /* link service flags */
byte ls_fcval; /* flow control value */
};
struct ackmsg /* acknowledgement message */
{
byte ak_flags; /* message flags */
word ak_dst; /* destination link address */
word ak_src; /* source link address */
word ak_acknum[2]; /* acknowledgement numbers */
};
struct minackmsg /* minimum acknowledgement message */
{
byte mk_flags; /* message flags */
word mk_dst; /* destination link address */
word mk_src; /* source link address */
word mk_acknum; /* acknowledgement number */
};
struct ciackmsg /* connect acknowledgement message */
{
byte ck_flags; /* message flags */
word ck_dst; /* destination link address */
};
struct cimsg /* connect initiate message */
{
byte ci_flags; /* message flags */
word ci_dst; /* destination link address (0) */
word ci_src; /* source link address */
byte ci_services; /* requested services */
byte ci_info; /* information */
word ci_segsize; /* maximum segment size */
};
struct ccmsg /* connect confirm message */
{
byte cc_flags; /* message flags */
word cc_dst; /* destination link address */
word cc_src; /* source link address */
byte cc_services; /* requested services */
byte cc_info; /* information */
word cc_segsize; /* maximum segment size */
byte cc_optlen; /* optional data length */
};
struct cnmsg /* generic connect message */
{
byte cn_flags; /* message flags */
word cn_dst; /* destination link address */
word cn_src; /* source link address */
byte cn_services; /* requested services */
byte cn_info; /* information */
word cn_segsize; /* maximum segment size */
};
struct dimsg /* disconnect initiate message */
{
byte di_flags; /* message flags */
word di_dst; /* destination link address */
word di_src; /* source link address */
word di_reason; /* reason code */
byte di_optlen; /* optional data length */
};
struct dcmsg /* disconnect confirm message */
{
byte dc_flags; /* message flags */
word dc_dst; /* destination link address */
word dc_src; /* source link address */
word dc_reason; /* reason code */
};
/* Forwards */
static int print_decnet_ctlmsg(netdissect_options *, const union routehdr *, u_int, u_int);
static void print_t_info(netdissect_options *, u_int);
static void print_l1_routes(netdissect_options *, const u_char *, u_int);
static void print_l2_routes(netdissect_options *, const u_char *, u_int);
static void print_i_info(netdissect_options *, u_int);
static void print_elist(const u_char *, u_int);
static int print_nsp(netdissect_options *, const u_char *, u_int);
static void print_reason(netdissect_options *, u_int);
void
decnet_print(netdissect_options *ndo,
const u_char *ap, u_int length,
u_int caplen)
{
const union routehdr *rhp;
u_int mflags;
uint16_t dst, src;
u_int hops;
u_int nsplen, pktlen;
const u_char *nspp;
ndo->ndo_protocol = "decnet";
if (length < sizeof(struct shorthdr)) {
ND_PRINT(" (length %u < %zu)", length, sizeof(struct shorthdr));
goto invalid;
}
pktlen = GET_LE_U_2(ap);
if (pktlen < sizeof(struct shorthdr)) {
ND_PRINT(" (pktlen %u < %zu)", pktlen, sizeof(struct shorthdr));
goto invalid;
}
if (pktlen > length) {
ND_PRINT(" (pktlen %u > %u)", pktlen, length);
goto invalid;
}
length = pktlen;
rhp = (const union routehdr *)(ap + sizeof(short));
mflags = GET_U_1(rhp->rh_short.sh_flags);
if (mflags & RMF_PAD) {
/* pad bytes of some sort in front of message */
u_int padlen = mflags & RMF_PADMASK;
if (ndo->ndo_vflag)
ND_PRINT("[pad:%u] ", padlen);
if (length < padlen + 2) {
ND_PRINT(" (length %u < %u)", length, padlen + 2);
goto invalid;
}
ND_TCHECK_LEN(ap + sizeof(short), padlen);
ap += padlen;
length -= padlen;
caplen -= padlen;
rhp = (const union routehdr *)(ap + sizeof(short));
mflags = GET_U_1(rhp->rh_short.sh_flags);
}
if (mflags & RMF_FVER) {
ND_PRINT("future-version-decnet");
ND_DEFAULTPRINT(ap, ND_MIN(length, caplen));
return;
}
/* is it a control message? */
if (mflags & RMF_CTLMSG) {
if (!print_decnet_ctlmsg(ndo, rhp, length, caplen))
goto invalid;
return;
}
switch (mflags & RMF_MASK) {
case RMF_LONG:
if (length < sizeof(struct longhdr)) {
ND_PRINT(" (length %u < %zu)", length, sizeof(struct longhdr));
goto invalid;
}
ND_TCHECK_SIZE(&rhp->rh_long);
dst =
GET_LE_U_2(rhp->rh_long.lg_dst.dne_remote.dne_nodeaddr);
src =
GET_LE_U_2(rhp->rh_long.lg_src.dne_remote.dne_nodeaddr);
hops = GET_U_1(rhp->rh_long.lg_visits);
nspp = ap + sizeof(short) + sizeof(struct longhdr);
nsplen = length - sizeof(struct longhdr);
break;
case RMF_SHORT:
dst = GET_LE_U_2(rhp->rh_short.sh_dst);
src = GET_LE_U_2(rhp->rh_short.sh_src);
hops = (GET_U_1(rhp->rh_short.sh_visits) & VIS_MASK)+1;
nspp = ap + sizeof(short) + sizeof(struct shorthdr);
nsplen = length - sizeof(struct shorthdr);
break;
default:
ND_PRINT("unknown message flags under mask");
ND_DEFAULTPRINT((const u_char *)ap, ND_MIN(length, caplen));
return;
}
ND_PRINT("%s > %s %u ",
dnaddr_string(ndo, src), dnaddr_string(ndo, dst), pktlen);
if (ndo->ndo_vflag) {
if (mflags & RMF_RQR)
ND_PRINT("RQR ");
if (mflags & RMF_RTS)
ND_PRINT("RTS ");
if (mflags & RMF_IE)
ND_PRINT("IE ");
ND_PRINT("%u hops ", hops);
}
if (!print_nsp(ndo, nspp, nsplen))
goto invalid;
return;
invalid:
nd_print_invalid(ndo);
}
static int
print_decnet_ctlmsg(netdissect_options *ndo,
const union routehdr *rhp, u_int length,
u_int caplen)
{
/* Our caller has already checked for mflags */
u_int mflags = GET_U_1(rhp->rh_short.sh_flags);
const union controlmsg *cmp = (const union controlmsg *)rhp;
uint16_t src, dst;
u_int info, blksize, eco, ueco, hello, other, vers;
u_int priority;
const u_char *rhpx = (const u_char *)rhp;
switch (mflags & RMF_CTLMASK) {
case RMF_INIT:
ND_PRINT("init ");
if (length < sizeof(struct initmsg))
goto invalid;
ND_TCHECK_SIZE(&cmp->cm_init);
src = GET_LE_U_2(cmp->cm_init.in_src);
info = GET_U_1(cmp->cm_init.in_info);
blksize = GET_LE_U_2(cmp->cm_init.in_blksize);
vers = GET_U_1(cmp->cm_init.in_vers);
eco = GET_U_1(cmp->cm_init.in_eco);
ueco = GET_U_1(cmp->cm_init.in_ueco);
hello = GET_LE_U_2(cmp->cm_init.in_hello);
print_t_info(ndo, info);
ND_PRINT("src %sblksize %u vers %u eco %u ueco %u hello %u",
dnaddr_string(ndo, src), blksize, vers, eco, ueco,
hello);
break;
case RMF_VER:
ND_PRINT("verification ");
if (length < sizeof(struct verifmsg))
goto invalid;
src = GET_LE_U_2(cmp->cm_ver.ve_src);
other = GET_U_1(cmp->cm_ver.ve_fcnval);
ND_PRINT("src %s fcnval %o", dnaddr_string(ndo, src), other);
break;
case RMF_TEST:
ND_PRINT("test ");
if (length < sizeof(struct testmsg))
goto invalid;
src = GET_LE_U_2(cmp->cm_test.te_src);
other = GET_U_1(cmp->cm_test.te_data);
ND_PRINT("src %s data %o", dnaddr_string(ndo, src), other);
break;
case RMF_L1ROUT:
ND_PRINT("lev-1-routing ");
if (length < sizeof(struct l1rout))
goto invalid;
ND_TCHECK_SIZE(&cmp->cm_l1rou);
src = GET_LE_U_2(cmp->cm_l1rou.r1_src);
ND_PRINT("src %s ", dnaddr_string(ndo, src));
print_l1_routes(ndo, &(rhpx[sizeof(struct l1rout)]),
length - sizeof(struct l1rout));
break;
case RMF_L2ROUT:
ND_PRINT("lev-2-routing ");
if (length < sizeof(struct l2rout))
goto invalid;
ND_TCHECK_SIZE(&cmp->cm_l2rout);
src = GET_LE_U_2(cmp->cm_l2rout.r2_src);
ND_PRINT("src %s ", dnaddr_string(ndo, src));
print_l2_routes(ndo, &(rhpx[sizeof(struct l2rout)]),
length - sizeof(struct l2rout));
break;
case RMF_RHELLO:
ND_PRINT("router-hello ");
if (length < sizeof(struct rhellomsg))
goto invalid;
ND_TCHECK_SIZE(&cmp->cm_rhello);
vers = GET_U_1(cmp->cm_rhello.rh_vers);
eco = GET_U_1(cmp->cm_rhello.rh_eco);
ueco = GET_U_1(cmp->cm_rhello.rh_ueco);
src =
GET_LE_U_2(cmp->cm_rhello.rh_src.dne_remote.dne_nodeaddr);
info = GET_U_1(cmp->cm_rhello.rh_info);
blksize = GET_LE_U_2(cmp->cm_rhello.rh_blksize);
priority = GET_U_1(cmp->cm_rhello.rh_priority);
hello = GET_LE_U_2(cmp->cm_rhello.rh_hello);
print_i_info(ndo, info);
ND_PRINT("vers %u eco %u ueco %u src %s blksize %u pri %u hello %u",
vers, eco, ueco, dnaddr_string(ndo, src),
blksize, priority, hello);
print_elist(&(rhpx[sizeof(struct rhellomsg)]),
length - sizeof(struct rhellomsg));
break;
case RMF_EHELLO:
ND_PRINT("endnode-hello ");
if (length < sizeof(struct ehellomsg))
goto invalid;
vers = GET_U_1(cmp->cm_ehello.eh_vers);
eco = GET_U_1(cmp->cm_ehello.eh_eco);
ueco = GET_U_1(cmp->cm_ehello.eh_ueco);
src =
GET_LE_U_2(cmp->cm_ehello.eh_src.dne_remote.dne_nodeaddr);
info = GET_U_1(cmp->cm_ehello.eh_info);
blksize = GET_LE_U_2(cmp->cm_ehello.eh_blksize);
/*seed*/
dst =
GET_LE_U_2(cmp->cm_ehello.eh_router.dne_remote.dne_nodeaddr);
hello = GET_LE_U_2(cmp->cm_ehello.eh_hello);
other = GET_U_1(cmp->cm_ehello.eh_data);
print_i_info(ndo, info);
ND_PRINT("vers %u eco %u ueco %u src %s blksize %u rtr %s hello %u data %o",
vers, eco, ueco, dnaddr_string(ndo, src),
blksize, dnaddr_string(ndo, dst), hello, other);
break;
default:
ND_PRINT("unknown control message");
ND_DEFAULTPRINT((const u_char *)rhp, ND_MIN(length, caplen));
break;
}
return (1);
invalid:
return (0);
}
static void
print_t_info(netdissect_options *ndo,
u_int info)
{
u_int ntype = info & 3;
switch (ntype) {
case 0: ND_PRINT("reserved-ntype? "); break;
case TI_L2ROUT: ND_PRINT("l2rout "); break;
case TI_L1ROUT: ND_PRINT("l1rout "); break;
case TI_ENDNODE: ND_PRINT("endnode "); break;
}
if (info & TI_VERIF)
ND_PRINT("verif ");
if (info & TI_BLOCK)
ND_PRINT("blo ");
}
static void
print_l1_routes(netdissect_options *ndo,
const u_char *rp, u_int len)
{
u_int count;
u_int id;
u_int info;
/* The last short is a checksum */
while (len > (3 * sizeof(short))) {
ND_TCHECK_LEN(rp, 3 * sizeof(short));
count = GET_LE_U_2(rp);
if (count > 1024)
return; /* seems to be bogus from here on */
rp += sizeof(short);
len -= sizeof(short);
id = GET_LE_U_2(rp);
rp += sizeof(short);
len -= sizeof(short);
info = GET_LE_U_2(rp);
rp += sizeof(short);
len -= sizeof(short);
ND_PRINT("{ids %u-%u cost %u hops %u} ", id, id + count,
RI_COST(info), RI_HOPS(info));
}
}
static void
print_l2_routes(netdissect_options *ndo,
const u_char *rp, u_int len)
{
u_int count;
u_int area;
u_int info;
/* The last short is a checksum */
while (len > (3 * sizeof(short))) {
ND_TCHECK_LEN(rp, 3 * sizeof(short));
count = GET_LE_U_2(rp);
if (count > 1024)
return; /* seems to be bogus from here on */
rp += sizeof(short);
len -= sizeof(short);
area = GET_LE_U_2(rp);
rp += sizeof(short);
len -= sizeof(short);
info = GET_LE_U_2(rp);
rp += sizeof(short);
len -= sizeof(short);
ND_PRINT("{areas %u-%u cost %u hops %u} ", area, area + count,
RI_COST(info), RI_HOPS(info));
}
}
static void
print_i_info(netdissect_options *ndo,
u_int info)
{
u_int ntype = info & II_TYPEMASK;
switch (ntype) {
case 0: ND_PRINT("reserved-ntype? "); break;
case II_L2ROUT: ND_PRINT("l2rout "); break;
case II_L1ROUT: ND_PRINT("l1rout "); break;
case II_ENDNODE: ND_PRINT("endnode "); break;
}
if (info & II_VERIF)
ND_PRINT("verif ");
if (info & II_NOMCAST)
ND_PRINT("nomcast ");
if (info & II_BLOCK)
ND_PRINT("blo ");
}
static void
print_elist(const u_char *elp _U_, u_int len _U_)
{
/* Not enough examples available for me to debug this */
}
static int
print_nsp(netdissect_options *ndo,
const u_char *nspp, u_int nsplen)
{
const struct nsphdr *nsphp = (const struct nsphdr *)nspp;
u_int dst, src, flags;
if (nsplen < sizeof(struct nsphdr)) {
ND_PRINT(" (nsplen %u < %zu)", nsplen, sizeof(struct nsphdr));
goto invalid;
}
flags = GET_U_1(nsphp->nh_flags);
dst = GET_LE_U_2(nsphp->nh_dst);
src = GET_LE_U_2(nsphp->nh_src);
switch (flags & NSP_TYPEMASK) {
case MFT_DATA:
switch (flags & NSP_SUBMASK) {
case MFS_BOM:
case MFS_MOM:
case MFS_EOM:
case MFS_BOM+MFS_EOM:
ND_PRINT("data %u>%u ", src, dst);
{
const struct seghdr *shp = (const struct seghdr *)nspp;
u_int ack;
u_int data_off = sizeof(struct minseghdr);
if (nsplen < data_off)
goto invalid;
ack = GET_LE_U_2(shp->sh_seq[0]);
if (ack & SGQ_ACK) { /* acknum field */
if ((ack & SGQ_NAK) == SGQ_NAK)
ND_PRINT("nak %u ", ack & SGQ_MASK);
else
ND_PRINT("ack %u ", ack & SGQ_MASK);
data_off += sizeof(short);
if (nsplen < data_off)
goto invalid;
ack = GET_LE_U_2(shp->sh_seq[1]);
if (ack & SGQ_OACK) { /* ackoth field */
if ((ack & SGQ_ONAK) == SGQ_ONAK)
ND_PRINT("onak %u ", ack & SGQ_MASK);
else
ND_PRINT("oack %u ", ack & SGQ_MASK);
data_off += sizeof(short);
if (nsplen < data_off)
goto invalid;
ack = GET_LE_U_2(shp->sh_seq[2]);
}
}
ND_PRINT("seg %u ", ack & SGQ_MASK);
}
break;
case MFS_ILS+MFS_INT:
ND_PRINT("intr ");
{
const struct seghdr *shp = (const struct seghdr *)nspp;
u_int ack;
u_int data_off = sizeof(struct minseghdr);
if (nsplen < data_off)
goto invalid;
ack = GET_LE_U_2(shp->sh_seq[0]);
if (ack & SGQ_ACK) { /* acknum field */
if ((ack & SGQ_NAK) == SGQ_NAK)
ND_PRINT("nak %u ", ack & SGQ_MASK);
else
ND_PRINT("ack %u ", ack & SGQ_MASK);
data_off += sizeof(short);
if (nsplen < data_off)
goto invalid;
ack = GET_LE_U_2(shp->sh_seq[1]);
if (ack & SGQ_OACK) { /* ackdat field */
if ((ack & SGQ_ONAK) == SGQ_ONAK)
ND_PRINT("nakdat %u ", ack & SGQ_MASK);
else
ND_PRINT("ackdat %u ", ack & SGQ_MASK);
data_off += sizeof(short);
if (nsplen < data_off)
goto invalid;
ack = GET_LE_U_2(shp->sh_seq[2]);
}
}
ND_PRINT("seg %u ", ack & SGQ_MASK);
}
break;
case MFS_ILS:
ND_PRINT("link-service %u>%u ", src, dst);
{
const struct seghdr *shp = (const struct seghdr *)nspp;
const struct lsmsg *lsmp =
(const struct lsmsg *)(nspp + sizeof(struct seghdr));
u_int ack;
u_int lsflags, fcval;
if (nsplen < sizeof(struct seghdr) + sizeof(struct lsmsg))
goto invalid;
ack = GET_LE_U_2(shp->sh_seq[0]);
if (ack & SGQ_ACK) { /* acknum field */
if ((ack & SGQ_NAK) == SGQ_NAK)
ND_PRINT("nak %u ", ack & SGQ_MASK);
else
ND_PRINT("ack %u ", ack & SGQ_MASK);
ack = GET_LE_U_2(shp->sh_seq[1]);
if (ack & SGQ_OACK) { /* ackdat field */
if ((ack & SGQ_ONAK) == SGQ_ONAK)
ND_PRINT("nakdat %u ", ack & SGQ_MASK);
else
ND_PRINT("ackdat %u ", ack & SGQ_MASK);
ack = GET_LE_U_2(shp->sh_seq[2]);
}
}
ND_PRINT("seg %u ", ack & SGQ_MASK);
lsflags = GET_U_1(lsmp->ls_lsflags);
fcval = GET_U_1(lsmp->ls_fcval);
switch (lsflags & LSI_MASK) {
case LSI_DATA:
ND_PRINT("dat seg count %u ", fcval);
switch (lsflags & LSM_MASK) {
case LSM_NOCHANGE:
break;
case LSM_DONOTSEND:
ND_PRINT("donotsend-data ");
break;
case LSM_SEND:
ND_PRINT("send-data ");
break;
default:
ND_PRINT("reserved-fcmod? %x", lsflags);
break;
}
break;
case LSI_INTR:
ND_PRINT("intr req count %u ", fcval);
break;
default:
ND_PRINT("reserved-fcval-int? %x", lsflags);
break;
}
}
break;
default:
ND_PRINT("reserved-subtype? %x %u > %u", flags, src, dst);
break;
}
break;
case MFT_ACK:
switch (flags & NSP_SUBMASK) {
case MFS_DACK:
ND_PRINT("data-ack %u>%u ", src, dst);
{
const struct ackmsg *amp = (const struct ackmsg *)nspp;
u_int ack;
if (nsplen < sizeof(struct ackmsg))
goto invalid;
ND_TCHECK_SIZE(amp);
ack = GET_LE_U_2(amp->ak_acknum[0]);
if (ack & SGQ_ACK) { /* acknum field */
if ((ack & SGQ_NAK) == SGQ_NAK)
ND_PRINT("nak %u ", ack & SGQ_MASK);
else
ND_PRINT("ack %u ", ack & SGQ_MASK);
ack = GET_LE_U_2(amp->ak_acknum[1]);
if (ack & SGQ_OACK) { /* ackoth field */
if ((ack & SGQ_ONAK) == SGQ_ONAK)
ND_PRINT("onak %u ", ack & SGQ_MASK);
else
ND_PRINT("oack %u ", ack & SGQ_MASK);
}
}
}
break;
case MFS_IACK:
ND_PRINT("ils-ack %u>%u ", src, dst);
{
const struct ackmsg *amp = (const struct ackmsg *)nspp;
u_int ack;
if (nsplen < sizeof(struct ackmsg))
goto invalid;
ND_TCHECK_SIZE(amp);
ack = GET_LE_U_2(amp->ak_acknum[0]);
if (ack & SGQ_ACK) { /* acknum field */
if ((ack & SGQ_NAK) == SGQ_NAK)
ND_PRINT("nak %u ", ack & SGQ_MASK);
else
ND_PRINT("ack %u ", ack & SGQ_MASK);
ack = GET_LE_U_2(amp->ak_acknum[1]);
if (ack & SGQ_OACK) { /* ackdat field */
if ((ack & SGQ_ONAK) == SGQ_ONAK)
ND_PRINT("nakdat %u ", ack & SGQ_MASK);
else
ND_PRINT("ackdat %u ", ack & SGQ_MASK);
}
}
}
break;
case MFS_CACK:
ND_PRINT("conn-ack %u", dst);
break;
default:
ND_PRINT("reserved-acktype? %x %u > %u", flags, src, dst);
break;
}
break;
case MFT_CTL:
switch (flags & NSP_SUBMASK) {
case MFS_CI:
case MFS_RCI:
if ((flags & NSP_SUBMASK) == MFS_CI)
ND_PRINT("conn-initiate ");
else
ND_PRINT("retrans-conn-initiate ");
ND_PRINT("%u>%u ", src, dst);
{
const struct cimsg *cimp = (const struct cimsg *)nspp;
u_int services, info, segsize;
if (nsplen < sizeof(struct cimsg))
goto invalid;
services = GET_U_1(cimp->ci_services);
info = GET_U_1(cimp->ci_info);
segsize = GET_LE_U_2(cimp->ci_segsize);
switch (services & COS_MASK) {
case COS_NONE:
break;
case COS_SEGMENT:
ND_PRINT("seg ");
break;
case COS_MESSAGE:
ND_PRINT("msg ");
break;
}
switch (info & COI_MASK) {
case COI_32:
ND_PRINT("ver 3.2 ");
break;
case COI_31:
ND_PRINT("ver 3.1 ");
break;
case COI_40:
ND_PRINT("ver 4.0 ");
break;
case COI_41:
ND_PRINT("ver 4.1 ");
break;
}
ND_PRINT("segsize %u ", segsize);
}
break;
case MFS_CC:
ND_PRINT("conn-confirm %u>%u ", src, dst);
{
const struct ccmsg *ccmp = (const struct ccmsg *)nspp;
u_int services, info;
u_int segsize, optlen;
if (nsplen < sizeof(struct ccmsg))
goto invalid;
services = GET_U_1(ccmp->cc_services);
info = GET_U_1(ccmp->cc_info);
segsize = GET_LE_U_2(ccmp->cc_segsize);
optlen = GET_U_1(ccmp->cc_optlen);
switch (services & COS_MASK) {
case COS_NONE:
break;
case COS_SEGMENT:
ND_PRINT("seg ");
break;
case COS_MESSAGE:
ND_PRINT("msg ");
break;
}
switch (info & COI_MASK) {
case COI_32:
ND_PRINT("ver 3.2 ");
break;
case COI_31:
ND_PRINT("ver 3.1 ");
break;
case COI_40:
ND_PRINT("ver 4.0 ");
break;
case COI_41:
ND_PRINT("ver 4.1 ");
break;
}
ND_PRINT("segsize %u ", segsize);
if (optlen) {
ND_PRINT("optlen %u ", optlen);
}
}
break;
case MFS_DI:
ND_PRINT("disconn-initiate %u>%u ", src, dst);
{
const struct dimsg *dimp = (const struct dimsg *)nspp;
u_int reason;
u_int optlen;
if (nsplen < sizeof(struct dimsg))
goto invalid;
reason = GET_LE_U_2(dimp->di_reason);
optlen = GET_U_1(dimp->di_optlen);
print_reason(ndo, reason);
if (optlen) {
ND_PRINT("optlen %u ", optlen);
}
}
break;
case MFS_DC:
ND_PRINT("disconn-confirm %u>%u ", src, dst);
{
const struct dcmsg *dcmp = (const struct dcmsg *)nspp;
u_int reason;
reason = GET_LE_U_2(dcmp->dc_reason);
print_reason(ndo, reason);
}
break;
default:
ND_PRINT("reserved-ctltype? %x %u > %u", flags, src, dst);
break;
}
break;
default:
ND_PRINT("reserved-type? %x %u > %u", flags, src, dst);
break;
}
return (1);
invalid:
return (0);
}
static const struct tok reason2str[] = {
{ UC_OBJREJECT, "object rejected connect" },
{ UC_RESOURCES, "insufficient resources" },
{ UC_NOSUCHNODE, "unrecognized node name" },
{ DI_SHUT, "node is shutting down" },
{ UC_NOSUCHOBJ, "unrecognized object" },
{ UC_INVOBJFORMAT, "invalid object name format" },
{ UC_OBJTOOBUSY, "object too busy" },
{ DI_PROTOCOL, "protocol error discovered" },
{ DI_TPA, "third party abort" },
{ UC_USERABORT, "user abort" },
{ UC_INVNODEFORMAT, "invalid node name format" },
{ UC_LOCALSHUT, "local node shutting down" },
{ DI_LOCALRESRC, "insufficient local resources" },
{ DI_REMUSERRESRC, "insufficient remote user resources" },
{ UC_ACCESSREJECT, "invalid access control information" },
{ DI_BADACCNT, "bad ACCOUNT information" },
{ UC_NORESPONSE, "no response from object" },
{ UC_UNREACHABLE, "node unreachable" },
{ DC_NOLINK, "no link terminate" },
{ DC_COMPLETE, "disconnect complete" },
{ DI_BADIMAGE, "bad image data in connect" },
{ DI_SERVMISMATCH, "cryptographic service mismatch" },
{ 0, NULL }
};
static void
print_reason(netdissect_options *ndo,
u_int reason)
{
ND_PRINT("%s ", tok2str(reason2str, "reason-%u", reason));
}
const char *
dnnum_string(netdissect_options *ndo, u_short dnaddr)
{
char *str;
size_t siz;
u_int area = (u_short)(dnaddr & AREAMASK) >> AREASHIFT;
u_int node = dnaddr & NODEMASK;
/* malloc() return used by the 'dnaddrtable' hash table: do not free() */
str = (char *)malloc(siz = sizeof("00.0000"));
if (str == NULL)
(*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC, "%s: malloc", __func__);
snprintf(str, siz, "%u.%u", area, node);
return(str);
}
diff --git a/contrib/tcpdump/print-dhcp6.c b/contrib/tcpdump/print-dhcp6.c
index 6b0dc21335d3..c196ad7497f3 100644
--- a/contrib/tcpdump/print-dhcp6.c
+++ b/contrib/tcpdump/print-dhcp6.c
@@ -1,853 +1,907 @@
/*
* Copyright (C) 1998 and 1999 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* \summary: IPv6 DHCP printer */
/*
* RFC3315: DHCPv6
* supported DHCPv6 options:
* RFC3319: Session Initiation Protocol (SIP) Servers options,
* RFC3633: IPv6 Prefix options,
* RFC3646: DNS Configuration options,
* RFC3898: Network Information Service (NIS) Configuration options,
* RFC4075: Simple Network Time Protocol (SNTP) Configuration option,
* RFC4242: Information Refresh Time option,
* RFC4280: Broadcast and Multicast Control Servers options,
* RFC5908: Network Time Protocol (NTP) Server Option for DHCPv6
* RFC6334: Dual-Stack Lite option,
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
/* lease duration */
#define DHCP6_DURATION_INFINITE 0xffffffff
/* Error Values */
#define DH6ERR_FAILURE 16
#define DH6ERR_AUTHFAIL 17
#define DH6ERR_POORLYFORMED 18
#define DH6ERR_UNAVAIL 19
#define DH6ERR_OPTUNAVAIL 20
/* Message type */
#define DH6_SOLICIT 1
#define DH6_ADVERTISE 2
#define DH6_REQUEST 3
#define DH6_CONFIRM 4
#define DH6_RENEW 5
#define DH6_REBIND 6
#define DH6_REPLY 7
#define DH6_RELEASE 8
#define DH6_DECLINE 9
#define DH6_RECONFIGURE 10
#define DH6_INFORM_REQ 11
#define DH6_RELAY_FORW 12
#define DH6_RELAY_REPLY 13
#define DH6_LEASEQUERY 14
#define DH6_LQ_REPLY 15
static const struct tok dh6_msgtype_str[] = {
{ DH6_SOLICIT, "solicit" },
{ DH6_ADVERTISE, "advertise" },
{ DH6_REQUEST, "request" },
{ DH6_CONFIRM, "confirm" },
{ DH6_RENEW, "renew" },
{ DH6_REBIND, "rebind" },
{ DH6_REPLY, "reply" },
{ DH6_RELEASE, "release" },
{ DH6_DECLINE, "decline" },
{ DH6_RECONFIGURE, "reconfigure" },
{ DH6_INFORM_REQ, "inf-req" },
{ DH6_RELAY_FORW, "relay-fwd" },
{ DH6_RELAY_REPLY, "relay-reply" },
{ DH6_LEASEQUERY, "leasequery" },
{ DH6_LQ_REPLY, "leasequery-reply" },
{ 0, NULL }
};
/* DHCP6 base packet format */
struct dhcp6 {
union {
nd_uint8_t msgtype;
nd_uint32_t xid;
} dh6_msgtypexid;
/* options follow */
};
#define DH6_XIDMASK 0x00ffffff
/* DHCPv6 relay messages */
struct dhcp6_relay {
nd_uint8_t dh6relay_msgtype;
nd_uint8_t dh6relay_hcnt;
nd_ipv6 dh6relay_linkaddr; /* XXX: badly aligned */
nd_ipv6 dh6relay_peeraddr;
/* options follow */
};
/* options */
#define DH6OPT_CLIENTID 1
#define DH6OPT_SERVERID 2
+# define DUID_LLT 1 /* RFC8415 */
+# define DUID_EN 2 /* RFC8415 */
+# define DUID_LL 3 /* RFC8415 */
+# define DUID_UUID 4 /* RFC6355 */
#define DH6OPT_IA_NA 3
#define DH6OPT_IA_TA 4
#define DH6OPT_IA_ADDR 5
#define DH6OPT_ORO 6
#define DH6OPT_PREFERENCE 7
# define DH6OPT_PREF_MAX 255
#define DH6OPT_ELAPSED_TIME 8
#define DH6OPT_RELAY_MSG 9
/*#define DH6OPT_SERVER_MSG 10 deprecated */
#define DH6OPT_AUTH 11
# define DH6OPT_AUTHPROTO_DELAYED 2
# define DH6OPT_AUTHPROTO_RECONFIG 3
# define DH6OPT_AUTHALG_HMACMD5 1
# define DH6OPT_AUTHRDM_MONOCOUNTER 0
# define DH6OPT_AUTHRECONFIG_KEY 1
# define DH6OPT_AUTHRECONFIG_HMACMD5 2
#define DH6OPT_UNICAST 12
#define DH6OPT_STATUS_CODE 13
# define DH6OPT_STCODE_SUCCESS 0
# define DH6OPT_STCODE_UNSPECFAIL 1
# define DH6OPT_STCODE_NOADDRAVAIL 2
# define DH6OPT_STCODE_NOBINDING 3
# define DH6OPT_STCODE_NOTONLINK 4
# define DH6OPT_STCODE_USEMULTICAST 5
# define DH6OPT_STCODE_NOPREFIXAVAIL 6
# define DH6OPT_STCODE_UNKNOWNQUERYTYPE 7
# define DH6OPT_STCODE_MALFORMEDQUERY 8
# define DH6OPT_STCODE_NOTCONFIGURED 9
# define DH6OPT_STCODE_NOTALLOWED 10
#define DH6OPT_RAPID_COMMIT 14
#define DH6OPT_USER_CLASS 15
#define DH6OPT_VENDOR_CLASS 16
#define DH6OPT_VENDOR_OPTS 17
#define DH6OPT_INTERFACE_ID 18
#define DH6OPT_RECONF_MSG 19
#define DH6OPT_RECONF_ACCEPT 20
#define DH6OPT_SIP_SERVER_D 21
#define DH6OPT_SIP_SERVER_A 22
#define DH6OPT_DNS_SERVERS 23
#define DH6OPT_DOMAIN_LIST 24
#define DH6OPT_IA_PD 25
#define DH6OPT_IA_PD_PREFIX 26
#define DH6OPT_NIS_SERVERS 27
#define DH6OPT_NISP_SERVERS 28
#define DH6OPT_NIS_NAME 29
#define DH6OPT_NISP_NAME 30
#define DH6OPT_SNTP_SERVERS 31
#define DH6OPT_LIFETIME 32
#define DH6OPT_BCMCS_SERVER_D 33
#define DH6OPT_BCMCS_SERVER_A 34
#define DH6OPT_GEOCONF_CIVIC 36
#define DH6OPT_REMOTE_ID 37
#define DH6OPT_SUBSCRIBER_ID 38
#define DH6OPT_CLIENT_FQDN 39
#define DH6OPT_PANA_AGENT 40
#define DH6OPT_NEW_POSIX_TIMEZONE 41
#define DH6OPT_NEW_TZDB_TIMEZONE 42
#define DH6OPT_ERO 43
#define DH6OPT_LQ_QUERY 44
#define DH6OPT_CLIENT_DATA 45
#define DH6OPT_CLT_TIME 46
#define DH6OPT_LQ_RELAY_DATA 47
#define DH6OPT_LQ_CLIENT_LINK 48
#define DH6OPT_NTP_SERVER 56
# define DH6OPT_NTP_SUBOPTION_SRV_ADDR 1
# define DH6OPT_NTP_SUBOPTION_MC_ADDR 2
# define DH6OPT_NTP_SUBOPTION_SRV_FQDN 3
+#define DH6OPT_BOOTFILE_URL 59 /* RFC5970 */
#define DH6OPT_AFTR_NAME 64
#define DH6OPT_MUDURL 112
+#define DH6OPT_SZTP_REDIRECT 136 /* RFC8572 */
static const struct tok dh6opt_str[] = {
{ DH6OPT_CLIENTID, "client-ID" },
{ DH6OPT_SERVERID, "server-ID" },
{ DH6OPT_IA_NA, "IA_NA" },
{ DH6OPT_IA_TA, "IA_TA" },
{ DH6OPT_IA_ADDR, "IA_ADDR" },
{ DH6OPT_ORO, "option-request" },
{ DH6OPT_PREFERENCE, "preference" },
{ DH6OPT_ELAPSED_TIME, "elapsed-time" },
{ DH6OPT_RELAY_MSG, "relay-message" },
{ DH6OPT_AUTH, "authentication" },
{ DH6OPT_UNICAST, "server-unicast" },
{ DH6OPT_STATUS_CODE, "status-code" },
{ DH6OPT_RAPID_COMMIT, "rapid-commit" },
{ DH6OPT_USER_CLASS, "user-class" },
{ DH6OPT_VENDOR_CLASS, "vendor-class" },
{ DH6OPT_VENDOR_OPTS, "vendor-specific-info" },
{ DH6OPT_INTERFACE_ID, "interface-ID" },
{ DH6OPT_RECONF_MSG, "reconfigure-message" },
{ DH6OPT_RECONF_ACCEPT, "reconfigure-accept" },
{ DH6OPT_SIP_SERVER_D, "SIP-servers-domain" },
{ DH6OPT_SIP_SERVER_A, "SIP-servers-address" },
{ DH6OPT_DNS_SERVERS, "DNS-server" },
{ DH6OPT_DOMAIN_LIST, "DNS-search-list" },
{ DH6OPT_IA_PD, "IA_PD" },
{ DH6OPT_IA_PD_PREFIX, "IA_PD-prefix" },
{ DH6OPT_SNTP_SERVERS, "SNTP-servers" },
{ DH6OPT_LIFETIME, "lifetime" },
{ DH6OPT_NIS_SERVERS, "NIS-server" },
{ DH6OPT_NISP_SERVERS, "NIS+-server" },
{ DH6OPT_NIS_NAME, "NIS-domain-name" },
{ DH6OPT_NISP_NAME, "NIS+-domain-name" },
{ DH6OPT_BCMCS_SERVER_D, "BCMCS-domain-name" },
{ DH6OPT_BCMCS_SERVER_A, "BCMCS-server" },
{ DH6OPT_GEOCONF_CIVIC, "Geoconf-Civic" },
{ DH6OPT_REMOTE_ID, "Remote-ID" },
{ DH6OPT_SUBSCRIBER_ID, "Subscriber-ID" },
{ DH6OPT_CLIENT_FQDN, "Client-FQDN" },
{ DH6OPT_PANA_AGENT, "PANA-agent" },
{ DH6OPT_NEW_POSIX_TIMEZONE, "POSIX-timezone" },
{ DH6OPT_NEW_TZDB_TIMEZONE, "POSIX-tz-database" },
{ DH6OPT_ERO, "Echo-request-option" },
{ DH6OPT_LQ_QUERY, "Lease-query" },
{ DH6OPT_CLIENT_DATA, "LQ-client-data" },
{ DH6OPT_CLT_TIME, "Clt-time" },
{ DH6OPT_LQ_RELAY_DATA, "LQ-relay-data" },
{ DH6OPT_LQ_CLIENT_LINK, "LQ-client-link" },
{ DH6OPT_NTP_SERVER, "NTP-server" },
+ { DH6OPT_BOOTFILE_URL, "Bootfile-URL" },
{ DH6OPT_AFTR_NAME, "AFTR-Name" },
{ DH6OPT_MUDURL, "MUD-URL" },
+ { DH6OPT_SZTP_REDIRECT, "SZTP-redirect" },
{ 0, NULL }
};
static const struct tok dh6opt_stcode_str[] = {
{ DH6OPT_STCODE_SUCCESS, "Success" }, /* RFC3315 */
{ DH6OPT_STCODE_UNSPECFAIL, "UnspecFail" }, /* RFC3315 */
{ DH6OPT_STCODE_NOADDRAVAIL, "NoAddrsAvail" }, /* RFC3315 */
{ DH6OPT_STCODE_NOBINDING, "NoBinding" }, /* RFC3315 */
{ DH6OPT_STCODE_NOTONLINK, "NotOnLink" }, /* RFC3315 */
{ DH6OPT_STCODE_USEMULTICAST, "UseMulticast" }, /* RFC3315 */
{ DH6OPT_STCODE_NOPREFIXAVAIL, "NoPrefixAvail" }, /* RFC3633 */
{ DH6OPT_STCODE_UNKNOWNQUERYTYPE, "UnknownQueryType" }, /* RFC5007 */
{ DH6OPT_STCODE_MALFORMEDQUERY, "MalformedQuery" }, /* RFC5007 */
{ DH6OPT_STCODE_NOTCONFIGURED, "NotConfigured" }, /* RFC5007 */
{ DH6OPT_STCODE_NOTALLOWED, "NotAllowed" }, /* RFC5007 */
{ 0, NULL }
};
struct dhcp6opt {
nd_uint16_t dh6opt_type;
nd_uint16_t dh6opt_len;
/* type-dependent data follows */
};
static const char *
dhcp6stcode(const uint16_t code)
{
return code > 255 ? "INVALID code" : tok2str(dh6opt_stcode_str, "code%u", code);
}
static void
dhcp6opt_print(netdissect_options *ndo,
const u_char *cp, const u_char *ep)
{
const struct dhcp6opt *dh6o;
const u_char *tp;
u_int i;
uint16_t opttype;
uint16_t optlen;
uint8_t auth_proto;
uint8_t auth_alg;
uint8_t auth_rdm;
u_int authinfolen, authrealmlen;
u_int remain_len; /* Length of remaining options */
u_int label_len; /* Label length */
uint16_t subopt_code;
uint16_t subopt_len;
uint8_t dh6_reconf_type;
uint8_t dh6_lq_query_type;
+ u_int first_list_value;
+ uint16_t remainder_len;
if (cp == ep)
return;
while (cp < ep) {
if (ep < cp + sizeof(*dh6o))
goto trunc;
dh6o = (const struct dhcp6opt *)cp;
ND_TCHECK_SIZE(dh6o);
optlen = GET_BE_U_2(dh6o->dh6opt_len);
if (ep < cp + sizeof(*dh6o) + optlen)
goto trunc;
opttype = GET_BE_U_2(dh6o->dh6opt_type);
ND_PRINT(" (%s", tok2str(dh6opt_str, "opt_%u", opttype));
ND_TCHECK_LEN(cp + sizeof(*dh6o), optlen);
switch (opttype) {
case DH6OPT_CLIENTID:
case DH6OPT_SERVERID:
if (optlen < 2) {
/*(*/
ND_PRINT(" ?)");
break;
}
tp = (const u_char *)(dh6o + 1);
switch (GET_BE_U_2(tp)) {
- case 1:
+ case DUID_LLT:
if (optlen >= 2 + 6) {
ND_PRINT(" hwaddr/time type %u time %u ",
GET_BE_U_2(tp + 2),
GET_BE_U_4(tp + 4));
for (i = 8; i < optlen; i++)
ND_PRINT("%02x",
GET_U_1(tp + i));
/*(*/
ND_PRINT(")");
} else {
/*(*/
ND_PRINT(" ?)");
}
break;
- case 2:
- if (optlen >= 2 + 8) {
- ND_PRINT(" vid ");
- for (i = 2; i < 2 + 8; i++)
+ case DUID_EN:
+ if (optlen >= 2 + 4) {
+ ND_PRINT(" enterprise %u ", GET_BE_U_4(tp + 2));
+ for (i = 2 + 4; i < optlen; i++)
ND_PRINT("%02x",
GET_U_1(tp + i));
/*(*/
ND_PRINT(")");
} else {
/*(*/
ND_PRINT(" ?)");
}
break;
- case 3:
+ case DUID_LL:
if (optlen >= 2 + 2) {
ND_PRINT(" hwaddr type %u ",
GET_BE_U_2(tp + 2));
for (i = 4; i < optlen; i++)
ND_PRINT("%02x",
GET_U_1(tp + i));
/*(*/
ND_PRINT(")");
} else {
/*(*/
ND_PRINT(" ?)");
}
break;
+ case DUID_UUID:
+ ND_PRINT(" uuid ");
+ if (optlen == 2 + 16) {
+ for (i = 2; i < optlen; i++)
+ ND_PRINT("%02x",
+ GET_U_1(tp + i));
+ /*(*/
+ ND_PRINT(")");
+ } else {
+ /*(*/
+ ND_PRINT(" ?)");
+ }
+ break;
default:
ND_PRINT(" type %u)", GET_BE_U_2(tp));
break;
}
break;
case DH6OPT_IA_ADDR:
if (optlen < 24) {
/*(*/
ND_PRINT(" ?)");
break;
}
tp = (const u_char *)(dh6o + 1);
ND_PRINT(" %s", GET_IP6ADDR_STRING(tp));
ND_PRINT(" pltime:%u vltime:%u",
GET_BE_U_4(tp + 16),
GET_BE_U_4(tp + 20));
if (optlen > 24) {
/* there are sub-options */
dhcp6opt_print(ndo, tp + 24, tp + optlen);
}
ND_PRINT(")");
break;
case DH6OPT_ORO:
case DH6OPT_ERO:
if (optlen % 2) {
ND_PRINT(" ?)");
break;
}
tp = (const u_char *)(dh6o + 1);
for (i = 0; i < optlen; i += 2) {
ND_PRINT(" %s",
tok2str(dh6opt_str, "opt_%u", GET_BE_U_2(tp + i)));
}
ND_PRINT(")");
break;
case DH6OPT_PREFERENCE:
if (optlen != 1) {
ND_PRINT(" ?)");
break;
}
tp = (const u_char *)(dh6o + 1);
ND_PRINT(" %u)", GET_U_1(tp));
break;
case DH6OPT_ELAPSED_TIME:
if (optlen != 2) {
ND_PRINT(" ?)");
break;
}
tp = (const u_char *)(dh6o + 1);
ND_PRINT(" %u)", GET_BE_U_2(tp));
break;
case DH6OPT_RELAY_MSG:
{
const u_char *snapend_save;
ND_PRINT(" (");
tp = (const u_char *)(dh6o + 1);
/*
* Update the snapend to the end of the option before
* calling recursively dhcp6_print() for the nested
* packet. Other options may be present after the
* nested DHCPv6 packet. This prevents that, in
* dhcp6_print(), for the nested DHCPv6 packet, the
* remaining length < remaining caplen.
*/
snapend_save = ndo->ndo_snapend;
ndo->ndo_snapend = ND_MIN(tp + optlen, ndo->ndo_snapend);
dhcp6_print(ndo, tp, optlen);
ndo->ndo_snapend = snapend_save;
ND_PRINT(")");
break;
}
case DH6OPT_AUTH:
if (optlen < 11) {
ND_PRINT(" ?)");
break;
}
tp = (const u_char *)(dh6o + 1);
auth_proto = GET_U_1(tp);
switch (auth_proto) {
case DH6OPT_AUTHPROTO_DELAYED:
ND_PRINT(" proto: delayed");
break;
case DH6OPT_AUTHPROTO_RECONFIG:
ND_PRINT(" proto: reconfigure");
break;
default:
ND_PRINT(" proto: %u", auth_proto);
break;
}
tp++;
auth_alg = GET_U_1(tp);
switch (auth_alg) {
case DH6OPT_AUTHALG_HMACMD5:
/* XXX: may depend on the protocol */
ND_PRINT(", alg: HMAC-MD5");
break;
default:
ND_PRINT(", alg: %u", auth_alg);
break;
}
tp++;
auth_rdm = GET_U_1(tp);
switch (auth_rdm) {
case DH6OPT_AUTHRDM_MONOCOUNTER:
ND_PRINT(", RDM: mono");
break;
default:
ND_PRINT(", RDM: %u", auth_rdm);
break;
}
tp++;
ND_PRINT(", RD:");
for (i = 0; i < 4; i++, tp += 2)
ND_PRINT(" %04x", GET_BE_U_2(tp));
/* protocol dependent part */
authinfolen = optlen - 11;
switch (auth_proto) {
case DH6OPT_AUTHPROTO_DELAYED:
if (authinfolen == 0)
break;
if (authinfolen < 20) {
ND_PRINT(" ??");
break;
}
authrealmlen = authinfolen - 20;
if (authrealmlen > 0) {
ND_PRINT(", realm: ");
}
for (i = 0; i < authrealmlen; i++, tp++)
ND_PRINT("%02x", GET_U_1(tp));
ND_PRINT(", key ID: %08x", GET_BE_U_4(tp));
tp += 4;
ND_PRINT(", HMAC-MD5:");
for (i = 0; i < 4; i++, tp+= 4)
ND_PRINT(" %08x", GET_BE_U_4(tp));
break;
case DH6OPT_AUTHPROTO_RECONFIG:
if (authinfolen != 17) {
ND_PRINT(" ??");
break;
}
switch (GET_U_1(tp)) {
case DH6OPT_AUTHRECONFIG_KEY:
ND_PRINT(" reconfig-key");
break;
case DH6OPT_AUTHRECONFIG_HMACMD5:
ND_PRINT(" type: HMAC-MD5");
break;
default:
ND_PRINT(" type: ??");
break;
}
tp++;
ND_PRINT(" value:");
for (i = 0; i < 4; i++, tp+= 4)
ND_PRINT(" %08x", GET_BE_U_4(tp));
break;
default:
ND_PRINT(" ??");
break;
}
ND_PRINT(")");
break;
case DH6OPT_RAPID_COMMIT: /* nothing todo */
ND_PRINT(")");
break;
case DH6OPT_INTERFACE_ID:
case DH6OPT_SUBSCRIBER_ID:
/*
* Since we cannot predict the encoding, print hex dump
* at most 10 characters.
*/
tp = (const u_char *)(dh6o + 1);
ND_PRINT(" ");
for (i = 0; i < optlen && i < 10; i++)
ND_PRINT("%02x", GET_U_1(tp + i));
ND_PRINT("...)");
break;
case DH6OPT_RECONF_MSG:
if (optlen != 1) {
ND_PRINT(" ?)");
break;
}
tp = (const u_char *)(dh6o + 1);
dh6_reconf_type = GET_U_1(tp);
switch (dh6_reconf_type) {
case DH6_RENEW:
ND_PRINT(" for renew)");
break;
case DH6_INFORM_REQ:
ND_PRINT(" for inf-req)");
break;
default:
ND_PRINT(" for ?\?\?(%02x))", dh6_reconf_type);
break;
}
break;
case DH6OPT_RECONF_ACCEPT: /* nothing todo */
ND_PRINT(")");
break;
case DH6OPT_SIP_SERVER_A:
case DH6OPT_DNS_SERVERS:
case DH6OPT_SNTP_SERVERS:
case DH6OPT_NIS_SERVERS:
case DH6OPT_NISP_SERVERS:
case DH6OPT_BCMCS_SERVER_A:
case DH6OPT_PANA_AGENT:
case DH6OPT_LQ_CLIENT_LINK:
if (optlen % 16) {
ND_PRINT(" ?)");
break;
}
tp = (const u_char *)(dh6o + 1);
for (i = 0; i < optlen; i += 16)
ND_PRINT(" %s", GET_IP6ADDR_STRING(tp + i));
ND_PRINT(")");
break;
case DH6OPT_SIP_SERVER_D:
case DH6OPT_DOMAIN_LIST:
tp = (const u_char *)(dh6o + 1);
while (tp < cp + sizeof(*dh6o) + optlen) {
ND_PRINT(" ");
if ((tp = fqdn_print(ndo, tp, cp + sizeof(*dh6o) + optlen)) == NULL)
goto trunc;
}
ND_PRINT(")");
break;
case DH6OPT_STATUS_CODE:
if (optlen < 2) {
ND_PRINT(" ?)");
break;
}
tp = (const u_char *)(dh6o + 1);
ND_PRINT(" %s)", dhcp6stcode(GET_BE_U_2(tp)));
break;
case DH6OPT_IA_NA:
case DH6OPT_IA_PD:
if (optlen < 12) {
ND_PRINT(" ?)");
break;
}
tp = (const u_char *)(dh6o + 1);
ND_PRINT(" IAID:%u T1:%u T2:%u",
GET_BE_U_4(tp),
GET_BE_U_4(tp + 4),
GET_BE_U_4(tp + 8));
if (optlen > 12) {
/* there are sub-options */
dhcp6opt_print(ndo, tp + 12, tp + optlen);
}
ND_PRINT(")");
break;
case DH6OPT_IA_TA:
if (optlen < 4) {
ND_PRINT(" ?)");
break;
}
tp = (const u_char *)(dh6o + 1);
ND_PRINT(" IAID:%u", GET_BE_U_4(tp));
if (optlen > 4) {
/* there are sub-options */
dhcp6opt_print(ndo, tp + 4, tp + optlen);
}
ND_PRINT(")");
break;
case DH6OPT_IA_PD_PREFIX:
if (optlen < 25) {
ND_PRINT(" ?)");
break;
}
tp = (const u_char *)(dh6o + 1);
ND_PRINT(" %s/%u", GET_IP6ADDR_STRING(tp + 9),
GET_U_1(tp + 8));
ND_PRINT(" pltime:%u vltime:%u",
GET_BE_U_4(tp),
GET_BE_U_4(tp + 4));
if (optlen > 25) {
/* there are sub-options */
dhcp6opt_print(ndo, tp + 25, tp + optlen);
}
ND_PRINT(")");
break;
case DH6OPT_LIFETIME:
case DH6OPT_CLT_TIME:
if (optlen != 4) {
ND_PRINT(" ?)");
break;
}
tp = (const u_char *)(dh6o + 1);
ND_PRINT(" %u)", GET_BE_U_4(tp));
break;
case DH6OPT_REMOTE_ID:
if (optlen < 4) {
ND_PRINT(" ?)");
break;
}
tp = (const u_char *)(dh6o + 1);
ND_PRINT(" %u ", GET_BE_U_4(tp));
/*
* Print hex dump first 10 characters.
*/
for (i = 4; i < optlen && i < 14; i++)
ND_PRINT("%02x", GET_U_1(tp + i));
ND_PRINT("...)");
break;
case DH6OPT_LQ_QUERY:
if (optlen < 17) {
ND_PRINT(" ?)");
break;
}
tp = (const u_char *)(dh6o + 1);
dh6_lq_query_type = GET_U_1(tp);
switch (dh6_lq_query_type) {
case 1:
ND_PRINT(" by-address");
break;
case 2:
ND_PRINT(" by-clientID");
break;
default:
ND_PRINT(" type_%u", dh6_lq_query_type);
break;
}
ND_PRINT(" %s", GET_IP6ADDR_STRING(tp + 1));
if (optlen > 17) {
/* there are query-options */
dhcp6opt_print(ndo, tp + 17, tp + optlen);
}
ND_PRINT(")");
break;
case DH6OPT_CLIENT_DATA:
tp = (const u_char *)(dh6o + 1);
if (optlen > 0) {
/* there are encapsulated options */
dhcp6opt_print(ndo, tp, tp + optlen);
}
ND_PRINT(")");
break;
case DH6OPT_LQ_RELAY_DATA:
if (optlen < 16) {
ND_PRINT(" ?)");
break;
}
tp = (const u_char *)(dh6o + 1);
ND_PRINT(" %s ", GET_IP6ADDR_STRING(tp));
/*
* Print hex dump first 10 characters.
*/
for (i = 16; i < optlen && i < 26; i++)
ND_PRINT("%02x", GET_U_1(tp + i));
ND_PRINT("...)");
break;
case DH6OPT_NTP_SERVER:
if (optlen < 4) {
ND_PRINT(" ?)");
break;
}
tp = (const u_char *)(dh6o + 1);
while (tp < cp + sizeof(*dh6o) + optlen - 4) {
subopt_code = GET_BE_U_2(tp);
tp += 2;
subopt_len = GET_BE_U_2(tp);
tp += 2;
if (tp + subopt_len > cp + sizeof(*dh6o) + optlen)
goto trunc;
ND_PRINT(" subopt:%u", subopt_code);
switch (subopt_code) {
case DH6OPT_NTP_SUBOPTION_SRV_ADDR:
case DH6OPT_NTP_SUBOPTION_MC_ADDR:
if (subopt_len != 16) {
ND_PRINT(" ?");
break;
}
ND_PRINT(" %s", GET_IP6ADDR_STRING(tp));
break;
case DH6OPT_NTP_SUBOPTION_SRV_FQDN:
ND_PRINT(" ");
if (fqdn_print(ndo, tp, tp + subopt_len) == NULL)
goto trunc;
break;
default:
ND_PRINT(" ?");
break;
}
tp += subopt_len;
}
ND_PRINT(")");
break;
case DH6OPT_AFTR_NAME:
if (optlen < 3) {
ND_PRINT(" ?)");
break;
}
tp = (const u_char *)(dh6o + 1);
remain_len = optlen;
ND_PRINT(" ");
/* Encoding is described in section 3.1 of RFC 1035 */
while (remain_len && GET_U_1(tp)) {
label_len = GET_U_1(tp);
tp++;
if (label_len < remain_len - 1) {
nd_printjnp(ndo, tp, label_len);
tp += label_len;
remain_len -= (label_len + 1);
if(GET_U_1(tp)) ND_PRINT(".");
} else {
ND_PRINT(" ?");
break;
}
}
ND_PRINT(")");
break;
case DH6OPT_NEW_POSIX_TIMEZONE: /* all three of these options */
case DH6OPT_NEW_TZDB_TIMEZONE: /* are encoded similarly */
case DH6OPT_MUDURL: /* although GMT might not work */
if (optlen < 5) {
ND_PRINT(" ?)");
break;
}
tp = (const u_char *)(dh6o + 1);
ND_PRINT(" ");
nd_printjnp(ndo, tp, optlen);
ND_PRINT(")");
break;
+ case DH6OPT_BOOTFILE_URL:
+ tp = (const u_char *)(dh6o + 1);
+ ND_PRINT(" ");
+ nd_printjn(ndo, tp, optlen);
+ ND_PRINT(")");
+ break;
+
+ case DH6OPT_SZTP_REDIRECT:
+ case DH6OPT_USER_CLASS:
+ ND_PRINT(" ");
+ tp = (const u_char *)(dh6o + 1);
+ first_list_value = TRUE;
+ remainder_len = optlen;
+ while (remainder_len >= 2) {
+ if (first_list_value == FALSE) {
+ ND_PRINT(",");
+ }
+ first_list_value = FALSE;
+ subopt_len = GET_BE_U_2(tp);
+ if (subopt_len > remainder_len-2) {
+ break;
+ }
+ tp += 2;
+ nd_printjn(ndo, tp, subopt_len);
+ tp += subopt_len;
+ remainder_len -= (subopt_len+2);
+ }
+ if (remainder_len != 0 ) {
+ ND_PRINT(" ?");
+ }
+ ND_PRINT(")");
+ break;
+
default:
ND_PRINT(")");
break;
}
cp += sizeof(*dh6o) + optlen;
}
return;
trunc:
nd_print_trunc(ndo);
}
/*
* Print dhcp6 packets
*/
void
dhcp6_print(netdissect_options *ndo,
const u_char *cp, u_int length)
{
const struct dhcp6 *dh6;
const struct dhcp6_relay *dh6relay;
uint8_t msgtype;
const u_char *ep;
const u_char *extp;
const char *name;
ndo->ndo_protocol = "dhcp6";
ND_PRINT("dhcp6");
ep = ndo->ndo_snapend;
if (cp + length < ep)
ep = cp + length;
dh6 = (const struct dhcp6 *)cp;
dh6relay = (const struct dhcp6_relay *)cp;
ND_TCHECK_4(dh6->dh6_msgtypexid.xid);
msgtype = GET_U_1(dh6->dh6_msgtypexid.msgtype);
name = tok2str(dh6_msgtype_str, "msgtype-%u", msgtype);
if (!ndo->ndo_vflag) {
ND_PRINT(" %s", name);
return;
}
/* XXX relay agent messages have to be handled differently */
ND_PRINT(" %s (", name); /*)*/
if (msgtype != DH6_RELAY_FORW && msgtype != DH6_RELAY_REPLY) {
ND_PRINT("xid=%x",
GET_BE_U_4(dh6->dh6_msgtypexid.xid) & DH6_XIDMASK);
extp = (const u_char *)(dh6 + 1);
dhcp6opt_print(ndo, extp, ep);
} else { /* relay messages */
ND_PRINT("linkaddr=%s", GET_IP6ADDR_STRING(dh6relay->dh6relay_linkaddr));
ND_PRINT(" peeraddr=%s", GET_IP6ADDR_STRING(dh6relay->dh6relay_peeraddr));
dhcp6opt_print(ndo, (const u_char *)(dh6relay + 1), ep);
}
/*(*/
ND_PRINT(")");
return;
trunc:
nd_print_trunc(ndo);
}
diff --git a/contrib/tcpdump/print-domain.c b/contrib/tcpdump/print-domain.c
index d2275a5e2a30..7ac891f04716 100644
--- a/contrib/tcpdump/print-domain.c
+++ b/contrib/tcpdump/print-domain.c
@@ -1,1171 +1,1171 @@
/*
* Copyright (c) 1988, 1989, 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.
*/
/* \summary: Domain Name System (DNS) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <string.h>
#include "netdissect.h"
#include "addrtoname.h"
#include "addrtostr.h"
#include "extract.h"
#include "nameser.h"
static const char *ns_ops[] = {
"", " inv_q", " stat", " op3", " notify", " update", " op6", " op7",
" op8", " updateA", " updateD", " updateDA",
" updateM", " updateMA", " zoneInit", " zoneRef",
};
static const char *ns_resp[] = {
"", " FormErr", " ServFail", " NXDomain",
" NotImp", " Refused", " YXDomain", " YXRRSet",
" NXRRSet", " NotAuth", " NotZone", " Resp11",
" Resp12", " Resp13", " Resp14", " NoChange",
" BadVers", "Resp17", " Resp18", " Resp19",
" Resp20", "Resp21", " Resp22", " BadCookie",
};
static const char *
ns_rcode(u_int rcode) {
static char buf[sizeof(" Resp4095")];
if (rcode < sizeof(ns_resp)/sizeof(ns_resp[0])) {
return (ns_resp[rcode]);
}
snprintf(buf, sizeof(buf), " Resp%u", rcode & 0xfff);
return (buf);
}
/* skip over a domain name */
static const u_char *
ns_nskip(netdissect_options *ndo,
const u_char *cp)
{
u_char i;
if (!ND_TTEST_1(cp))
return (NULL);
i = GET_U_1(cp);
cp++;
while (i) {
switch (i & TYPE_MASK) {
case TYPE_INDIR:
return (cp + 1);
case TYPE_EDNS0: {
int bitlen, bytelen;
if ((i & ~TYPE_MASK) != EDNS0_ELT_BITLABEL)
return(NULL); /* unknown ELT */
if (!ND_TTEST_1(cp))
return (NULL);
if ((bitlen = GET_U_1(cp)) == 0)
bitlen = 256;
cp++;
bytelen = (bitlen + 7) / 8;
cp += bytelen;
}
break;
case TYPE_RESERVED:
return (NULL);
case TYPE_LABEL:
cp += i;
break;
}
if (!ND_TTEST_1(cp))
return (NULL);
i = GET_U_1(cp);
cp++;
}
return (cp);
}
static const u_char *
blabel_print(netdissect_options *ndo,
const u_char *cp)
{
u_int bitlen, slen, b;
const u_char *bitp, *lim;
uint8_t tc;
if (!ND_TTEST_1(cp))
return(NULL);
if ((bitlen = GET_U_1(cp)) == 0)
bitlen = 256;
slen = (bitlen + 3) / 4;
lim = cp + 1 + slen;
/* print the bit string as a hex string */
ND_PRINT("\\[x");
for (bitp = cp + 1, b = bitlen; bitp < lim && b > 7; b -= 8, bitp++) {
ND_PRINT("%02x", GET_U_1(bitp));
}
if (b > 4) {
tc = GET_U_1(bitp);
bitp++;
ND_PRINT("%02x", tc & (0xff << (8 - b)));
} else if (b > 0) {
tc = GET_U_1(bitp);
bitp++;
ND_PRINT("%1x", ((tc >> 4) & 0x0f) & (0x0f << (4 - b)));
}
ND_PRINT("/%u]", bitlen);
return lim;
}
static int
labellen(netdissect_options *ndo,
const u_char *cp)
{
u_int i;
if (!ND_TTEST_1(cp))
return(-1);
i = GET_U_1(cp);
switch (i & TYPE_MASK) {
case TYPE_EDNS0: {
u_int bitlen, elt;
if ((elt = (i & ~TYPE_MASK)) != EDNS0_ELT_BITLABEL) {
ND_PRINT("<ELT %d>", elt);
return(-1);
}
if (!ND_TTEST_1(cp + 1))
return(-1);
if ((bitlen = GET_U_1(cp + 1)) == 0)
bitlen = 256;
return(((bitlen + 7) / 8) + 1);
}
case TYPE_INDIR:
case TYPE_LABEL:
return(i);
default:
/*
* TYPE_RESERVED, but we use default to suppress compiler
* warnings about falling out of the switch statement.
*/
ND_PRINT("<BAD LABEL TYPE>");
return(-1);
}
}
/* print a <domain-name> */
const u_char *
fqdn_print(netdissect_options *ndo,
const u_char *cp, const u_char *bp)
{
u_int i, l;
const u_char *rp = NULL;
int compress = 0;
u_int elt;
u_int offset, max_offset;
u_int name_chars = 0;
if ((l = labellen(ndo, cp)) == (u_int)-1)
return(NULL);
if (!ND_TTEST_1(cp))
return(NULL);
max_offset = (u_int)(cp - bp);
i = GET_U_1(cp);
cp++;
if ((i & TYPE_MASK) != TYPE_INDIR) {
compress = 0;
rp = cp + l;
}
if (i != 0) {
while (i && cp < ndo->ndo_snapend) {
switch (i & TYPE_MASK) {
case TYPE_INDIR:
if (!compress) {
rp = cp + 1;
compress = 1;
}
if (!ND_TTEST_1(cp))
return(NULL);
offset = (((i << 8) | GET_U_1(cp)) & 0x3fff);
/*
* This must move backwards in the packet.
* No RFC explicitly says that, but BIND's
* name decompression code requires it,
* as a way of preventing infinite loops
* and other bad behavior, and it's probably
* what was intended (compress by pointing
* to domain name suffixes already seen in
* the packet).
*/
if (offset >= max_offset) {
ND_PRINT("<BAD PTR>");
return(NULL);
}
max_offset = offset;
cp = bp + offset;
if (!ND_TTEST_1(cp))
return(NULL);
i = GET_U_1(cp);
if ((l = labellen(ndo, cp)) == (u_int)-1)
return(NULL);
cp++;
continue;
case TYPE_EDNS0:
elt = (i & ~TYPE_MASK);
switch(elt) {
case EDNS0_ELT_BITLABEL:
if (blabel_print(ndo, cp) == NULL)
return (NULL);
break;
default:
/* unknown ELT */
ND_PRINT("<ELT %u>", elt);
return(NULL);
}
break;
case TYPE_RESERVED:
ND_PRINT("<BAD LABEL TYPE>");
return(NULL);
case TYPE_LABEL:
if (name_chars + l <= MAXCDNAME) {
if (nd_printn(ndo, cp, l, ndo->ndo_snapend))
return(NULL);
} else if (name_chars < MAXCDNAME) {
if (nd_printn(ndo, cp,
MAXCDNAME - name_chars, ndo->ndo_snapend))
return(NULL);
}
name_chars += l;
break;
}
cp += l;
if (name_chars <= MAXCDNAME)
ND_PRINT(".");
name_chars++;
if (!ND_TTEST_1(cp))
return(NULL);
i = GET_U_1(cp);
if ((l = labellen(ndo, cp)) == (u_int)-1)
return(NULL);
cp++;
if (!compress)
rp += l + 1;
}
if (name_chars > MAXCDNAME)
ND_PRINT("<DOMAIN NAME TOO LONG>");
} else
ND_PRINT(".");
return (rp);
}
/* print a <character-string> */
static const u_char *
ns_cprint(netdissect_options *ndo,
const u_char *cp)
{
u_int i;
if (!ND_TTEST_1(cp))
return (NULL);
i = GET_U_1(cp);
cp++;
if (nd_printn(ndo, cp, i, ndo->ndo_snapend))
return (NULL);
return (cp + i);
}
static void
print_eopt_ecs(netdissect_options *ndo, const u_char *cp,
u_int data_len)
{
u_int family, addr_bits, src_len, scope_len;
u_char padded[32];
char addr[INET6_ADDRSTRLEN];
/* ecs option must at least contain family, src len, and scope len */
if (data_len < 4) {
nd_print_invalid(ndo);
return;
}
family = GET_BE_U_2(cp);
cp += 2;
src_len = GET_U_1(cp);
cp += 1;
scope_len = GET_U_1(cp);
cp += 1;
if (family == 1)
addr_bits = 32;
else if (family == 2)
addr_bits = 128;
else {
nd_print_invalid(ndo);
return;
}
if (data_len - 4 > (addr_bits / 8)) {
nd_print_invalid(ndo);
return;
}
/* checks for invalid ecs scope or source length */
if (src_len > addr_bits || scope_len > addr_bits || ((src_len + 7) / 8) != (data_len - 4)) {
nd_print_invalid(ndo);
return;
}
/* pad the truncated address from ecs with zeros */
memset(padded, 0, sizeof(padded));
memcpy(padded, cp, data_len - 4);
if (family == 1)
ND_PRINT("%s/%d/%d", addrtostr(padded, addr, INET_ADDRSTRLEN),
src_len, scope_len);
else
ND_PRINT("%s/%d/%d", addrtostr6(padded, addr, INET6_ADDRSTRLEN),
src_len, scope_len);
}
extern const struct tok edns_opt2str[];
extern const struct tok dau_alg2str[];
extern const struct tok dhu_alg2str[];
extern const struct tok n3u_alg2str[];
/* print an <EDNS-option> */
static const u_char *
eopt_print(netdissect_options *ndo,
const u_char *cp)
{
u_int opt, data_len, i;
if (!ND_TTEST_2(cp))
return (NULL);
opt = GET_BE_U_2(cp);
cp += 2;
ND_PRINT("%s", tok2str(edns_opt2str, "Opt%u", opt));
if (!ND_TTEST_2(cp))
return (NULL);
data_len = GET_BE_U_2(cp);
cp += 2;
ND_TCHECK_LEN(cp, data_len);
if (data_len > 0) {
ND_PRINT(" ");
switch (opt) {
case E_ECS:
print_eopt_ecs(ndo, cp, data_len);
break;
case E_COOKIE:
if (data_len < 8 || (data_len > 8 && data_len < 16) || data_len > 40)
nd_print_invalid(ndo);
else {
for (i = 0; i < data_len; ++i) {
/* split client and server cookie */
if (i == 8)
ND_PRINT(" ");
ND_PRINT("%02x", GET_U_1(cp + i));
}
}
break;
case E_KEEPALIVE:
if (data_len != 2)
nd_print_invalid(ndo);
else
/* keepalive is in increments of 100ms. Convert to seconds */
ND_PRINT("%0.1f sec", (GET_BE_U_2(cp) / 10.0));
break;
case E_EXPIRE:
if (data_len != 4)
nd_print_invalid(ndo);
else
ND_PRINT("%u sec", GET_BE_U_4(cp));
break;
case E_PADDING:
/* ignore contents and just print length */
ND_PRINT("(%u)", data_len);
break;
case E_KEYTAG:
if (data_len % 2 != 0)
nd_print_invalid(ndo);
else
for (i = 0; i < data_len; i += 2) {
if (i > 0)
ND_PRINT(" ");
ND_PRINT("%u", GET_BE_U_2(cp + i));
}
break;
case E_DAU:
for (i = 0; i < data_len; ++i) {
if (i > 0)
ND_PRINT(" ");
ND_PRINT("%s", tok2str(dau_alg2str, "Alg_%u", GET_U_1(cp + i)));
}
break;
case E_DHU:
for (i = 0; i < data_len; ++i) {
if (i > 0)
ND_PRINT(" ");
ND_PRINT("%s", tok2str(dhu_alg2str, "Alg_%u", GET_U_1(cp + i)));
}
break;
case E_N3U:
for (i = 0; i < data_len; ++i) {
if (i > 0)
ND_PRINT(" ");
ND_PRINT("%s", tok2str(n3u_alg2str, "Alg_%u", GET_U_1(cp + i)));
}
break;
case E_CHAIN:
fqdn_print(ndo, cp, cp + data_len);
break;
case E_NSID:
/* intentional fall-through. NSID is an undefined byte string */
default:
for (i = 0; i < data_len; ++i)
ND_PRINT("%02x", GET_U_1(cp + i));
break;
}
}
return (cp + data_len);
trunc:
return (NULL);
}
extern const struct tok ns_type2str[];
/* https://www.iana.org/assignments/dns-parameters */
const struct tok ns_type2str[] = {
{ T_A, "A" }, /* RFC 1035 */
{ T_NS, "NS" }, /* RFC 1035 */
{ T_MD, "MD" }, /* RFC 1035 */
{ T_MF, "MF" }, /* RFC 1035 */
{ T_CNAME, "CNAME" }, /* RFC 1035 */
{ T_SOA, "SOA" }, /* RFC 1035 */
{ T_MB, "MB" }, /* RFC 1035 */
{ T_MG, "MG" }, /* RFC 1035 */
{ T_MR, "MR" }, /* RFC 1035 */
{ T_NULL, "NULL" }, /* RFC 1035 */
{ T_WKS, "WKS" }, /* RFC 1035 */
{ T_PTR, "PTR" }, /* RFC 1035 */
{ T_HINFO, "HINFO" }, /* RFC 1035 */
{ T_MINFO, "MINFO" }, /* RFC 1035 */
{ T_MX, "MX" }, /* RFC 1035 */
{ T_TXT, "TXT" }, /* RFC 1035 */
{ T_RP, "RP" }, /* RFC 1183 */
{ T_AFSDB, "AFSDB" }, /* RFC 5864 */
{ T_X25, "X25" }, /* RFC 1183 */
{ T_ISDN, "ISDN" }, /* RFC 1183 */
{ T_RT, "RT" }, /* RFC 1183 */
{ T_NSAP, "NSAP" }, /* RFC 1706 */
{ T_NSAP_PTR, "NSAP_PTR" }, /* RFC 1706 */
{ T_SIG, "SIG" }, /* RFC 3008 */
{ T_KEY, "KEY" }, /* RFC 3110 */
{ T_PX, "PX" }, /* RFC 2163 */
{ T_GPOS, "GPOS" }, /* RFC 1712 */
{ T_AAAA, "AAAA" }, /* RFC 3596 */
{ T_LOC, "LOC" }, /* RFC 1876 */
{ T_NXT, "NXT" }, /* RFC 3755 */
{ T_EID, "EID" }, /* Nimrod */
{ T_NIMLOC, "NIMLOC" }, /* Nimrod */
{ T_SRV, "SRV" }, /* RFC 2782 */
{ T_ATMA, "ATMA" }, /* ATM Forum */
{ T_NAPTR, "NAPTR" }, /* RFC 3403 */
{ T_KX, "KX" }, /* RFC 2230 */
{ T_CERT, "CERT" }, /* RFC 4398 */
{ T_A6, "A6" }, /* RFC 6563 */
{ T_DNAME, "DNAME" }, /* RFC 6672 */
{ T_SINK, "SINK" },
{ T_OPT, "OPT" }, /* RFC 6891 */
{ T_APL, "APL" }, /* RFC 3123 */
{ T_DS, "DS" }, /* RFC 4034 */
{ T_SSHFP, "SSHFP" }, /* RFC 4255 */
{ T_IPSECKEY, "IPSECKEY" }, /* RFC 4025 */
{ T_RRSIG, "RRSIG" }, /* RFC 4034 */
{ T_NSEC, "NSEC" }, /* RFC 4034 */
{ T_DNSKEY, "DNSKEY" }, /* RFC 4034 */
{ T_DHCID, "DHCID" }, /* RFC 4071 */
{ T_NSEC3, "NSEC3" }, /* RFC 5155 */
{ T_NSEC3PARAM, "NSEC3PARAM" }, /* RFC 5155 */
{ T_TLSA, "TLSA" }, /* RFC 6698 */
{ T_SMIMEA, "SMIMEA" }, /* RFC 8162 */
{ T_HIP, "HIP" }, /* RFC 8005 */
{ T_NINFO, "NINFO" },
{ T_RKEY, "RKEY" },
{ T_TALINK, "TALINK" },
{ T_CDS, "CDS" }, /* RFC 7344 */
{ T_CDNSKEY, "CDNSKEY" }, /* RFC 7344 */
{ T_OPENPGPKEY, "OPENPGPKEY" }, /* RFC 7929 */
{ T_CSYNC, "CSYNC" }, /* RFC 7477 */
{ T_ZONEMD, "ZONEMD" }, /* RFC 8976 */
{ T_SVCB, "SVCB" },
{ T_HTTPS, "HTTPS" },
{ T_SPF, "SPF" }, /* RFC 7208 */
{ T_UINFO, "UINFO" },
{ T_UID, "UID" },
{ T_GID, "GID" },
{ T_UNSPEC, "UNSPEC" },
{ T_NID, "NID" }, /* RFC 6742 */
{ T_L32, "L32" }, /* RFC 6742 */
{ T_L64, "L64" }, /* RFC 6742 */
{ T_LP, "LP" }, /* RFC 6742 */
{ T_EUI48, "EUI48" }, /* RFC 7043 */
{ T_EUI64, "EUI64" }, /* RFC 7043 */
{ T_TKEY, "TKEY" }, /* RFC 2930 */
{ T_TSIG, "TSIG" }, /* RFC 8945 */
{ T_IXFR, "IXFR" }, /* RFC 1995 */
{ T_AXFR, "AXFR" }, /* RFC 5936 */
{ T_MAILB, "MAILB" }, /* RFC 1035 */
{ T_MAILA, "MAILA" }, /* RFC 1035 */
{ T_ANY, "ANY" }, /* RFC 8482 */
{ T_URI, "URI" }, /* RFC 7553 */
{ T_CAA, "CAA" }, /* RFC 8659 */
{ T_AVC, "AVC" },
{ T_DOA, "DOA" },
{ T_AMTRELAY, "AMTRELAY" }, /* RFC 8777 */
{ T_TA, "TA" },
{ T_DLV, "DLV" }, /* RFC 8749 */
{ 0, NULL }
};
extern const struct tok ns_class2str[];
const struct tok ns_class2str[] = {
{ C_IN, "IN" }, /* Not used */
{ C_CHAOS, "CHAOS" },
{ C_HS, "HS" },
{ C_ANY, "ANY" },
{ 0, NULL }
};
const struct tok edns_opt2str[] = {
{ E_LLQ, "LLQ" },
{ E_UL, "UL" },
{ E_NSID, "NSID" },
{ E_DAU, "DAU" },
{ E_DHU, "DHU" },
{ E_N3U, "N3U" },
{ E_ECS, "ECS" },
{ E_EXPIRE, "EXPIRE" },
{ E_COOKIE, "COOKIE" },
{ E_KEEPALIVE, "KEEPALIVE" },
{ E_PADDING, "PADDING" },
{ E_CHAIN, "CHAIN" },
{ E_KEYTAG, "KEY-TAG" },
{ E_CLIENTTAG, "CLIENT-TAG" },
{ E_SERVERTAG, "SERVER-TAG" },
{ 0, NULL }
};
const struct tok dau_alg2str[] = {
{ A_DELETE, "DELETE" },
{ A_RSAMD5, "RSAMD5" },
{ A_DH, "DH" },
{ A_DSA, "DS" },
{ A_RSASHA1, "RSASHA1" },
{ A_DSA_NSEC3_SHA1, "DSA-NSEC3-SHA1" },
{ A_RSASHA1_NSEC3_SHA1, "RSASHA1-NSEC3-SHA1" },
{ A_RSASHA256, "RSASHA256" },
{ A_RSASHA512, "RSASHA512" },
{ A_ECC_GOST, "ECC-GOST" },
{ A_ECDSAP256SHA256, "ECDSAP256SHA256" },
{ A_ECDSAP384SHA384, "ECDSAP384SHA384" },
{ A_ED25519, "ED25519" },
{ A_ED448, "ED448" },
{ A_INDIRECT, "INDIRECT" },
{ A_PRIVATEDNS, "PRIVATEDNS" },
{ A_PRIVATEOID, "PRIVATEOID" },
{ 0, NULL }
};
const struct tok dhu_alg2str[] = {
{ DS_SHA1, "SHA-1" },
{ DS_SHA256,"SHA-256" },
{ DS_GOST, "GOST_R_34.11-94" },
{ DS_SHA384,"SHA-384" },
{ 0, NULL }
};
const struct tok n3u_alg2str[] = {
{ NSEC_SHA1,"SHA-1" },
{ 0, NULL }
};
/* print a query */
static const u_char *
ns_qprint(netdissect_options *ndo,
const u_char *cp, const u_char *bp, int is_mdns)
{
const u_char *np = cp;
u_int i, class;
cp = ns_nskip(ndo, cp);
if (cp == NULL || !ND_TTEST_4(cp))
return(NULL);
/* print the qtype */
i = GET_BE_U_2(cp);
cp += 2;
ND_PRINT(" %s", tok2str(ns_type2str, "Type%u", i));
/* print the qclass (if it's not IN) */
i = GET_BE_U_2(cp);
cp += 2;
if (is_mdns)
class = (i & ~C_QU);
else
class = i;
if (class != C_IN)
ND_PRINT(" %s", tok2str(ns_class2str, "(Class %u)", class));
if (is_mdns) {
ND_PRINT(i & C_QU ? " (QU)" : " (QM)");
}
ND_PRINT("? ");
cp = fqdn_print(ndo, np, bp);
return(cp ? cp + 4 : NULL);
}
/* print a reply */
static const u_char *
ns_rprint(netdissect_options *ndo,
const u_char *cp, const u_char *bp, int is_mdns)
{
u_int i, class, opt_flags = 0;
u_short typ, len;
const u_char *rp;
if (ndo->ndo_vflag) {
ND_PRINT(" ");
if ((cp = fqdn_print(ndo, cp, bp)) == NULL)
return NULL;
} else
cp = ns_nskip(ndo, cp);
if (cp == NULL || !ND_TTEST_LEN(cp, 10))
return (ndo->ndo_snapend);
/* print the type/qtype */
typ = GET_BE_U_2(cp);
cp += 2;
/* print the class (if it's not IN and the type isn't OPT) */
i = GET_BE_U_2(cp);
cp += 2;
if (is_mdns)
class = (i & ~C_CACHE_FLUSH);
else
class = i;
if (class != C_IN && typ != T_OPT)
ND_PRINT(" %s", tok2str(ns_class2str, "(Class %u)", class));
if (is_mdns) {
if (i & C_CACHE_FLUSH)
ND_PRINT(" (Cache flush)");
}
if (typ == T_OPT) {
/* get opt flags */
cp += 2;
opt_flags = GET_BE_U_2(cp);
/* ignore rest of ttl field */
cp += 2;
} else if (ndo->ndo_vflag > 2) {
/* print ttl */
ND_PRINT(" [");
unsigned_relts_print(ndo, GET_BE_U_4(cp));
ND_PRINT("]");
cp += 4;
} else {
/* ignore ttl */
cp += 4;
}
len = GET_BE_U_2(cp);
cp += 2;
rp = cp + len;
ND_PRINT(" %s", tok2str(ns_type2str, "Type%u", typ));
if (rp > ndo->ndo_snapend)
return(NULL);
switch (typ) {
case T_A:
if (!ND_TTEST_LEN(cp, sizeof(nd_ipv4)))
return(NULL);
ND_PRINT(" %s", intoa(GET_IPV4_TO_NETWORK_ORDER(cp)));
break;
case T_NS:
case T_CNAME:
case T_PTR:
case T_DNAME:
ND_PRINT(" ");
if (fqdn_print(ndo, cp, bp) == NULL)
return(NULL);
break;
case T_SOA:
if (!ndo->ndo_vflag)
break;
ND_PRINT(" ");
if ((cp = fqdn_print(ndo, cp, bp)) == NULL)
return(NULL);
ND_PRINT(" ");
if ((cp = fqdn_print(ndo, cp, bp)) == NULL)
return(NULL);
if (!ND_TTEST_LEN(cp, 5 * 4))
return(NULL);
ND_PRINT(" %u", GET_BE_U_4(cp));
cp += 4;
ND_PRINT(" %u", GET_BE_U_4(cp));
cp += 4;
ND_PRINT(" %u", GET_BE_U_4(cp));
cp += 4;
ND_PRINT(" %u", GET_BE_U_4(cp));
cp += 4;
ND_PRINT(" %u", GET_BE_U_4(cp));
cp += 4;
break;
case T_MX:
ND_PRINT(" ");
if (!ND_TTEST_2(cp))
return(NULL);
if (fqdn_print(ndo, cp + 2, bp) == NULL)
return(NULL);
ND_PRINT(" %u", GET_BE_U_2(cp));
break;
case T_TXT:
while (cp < rp) {
ND_PRINT(" \"");
cp = ns_cprint(ndo, cp);
if (cp == NULL)
return(NULL);
ND_PRINT("\"");
}
break;
case T_SRV:
ND_PRINT(" ");
if (!ND_TTEST_6(cp))
return(NULL);
if (fqdn_print(ndo, cp + 6, bp) == NULL)
return(NULL);
ND_PRINT(":%u %u %u", GET_BE_U_2(cp + 4),
GET_BE_U_2(cp), GET_BE_U_2(cp + 2));
break;
case T_AAAA:
{
char ntop_buf[INET6_ADDRSTRLEN];
if (!ND_TTEST_LEN(cp, sizeof(nd_ipv6)))
return(NULL);
ND_PRINT(" %s",
addrtostr6(cp, ntop_buf, sizeof(ntop_buf)));
break;
}
case T_A6:
{
nd_ipv6 a;
int pbit, pbyte;
char ntop_buf[INET6_ADDRSTRLEN];
if (!ND_TTEST_1(cp))
return(NULL);
pbit = GET_U_1(cp);
pbyte = (pbit & ~7) / 8;
if (pbit > 128) {
ND_PRINT(" %u(bad plen)", pbit);
break;
} else if (pbit < 128) {
memset(a, 0, sizeof(a));
GET_CPY_BYTES(a + pbyte, cp + 1, sizeof(a) - pbyte);
ND_PRINT(" %u %s", pbit,
addrtostr6(&a, ntop_buf, sizeof(ntop_buf)));
}
if (pbit > 0) {
ND_PRINT(" ");
if (fqdn_print(ndo, cp + 1 + sizeof(a) - pbyte, bp) == NULL)
return(NULL);
}
break;
}
case T_URI:
if (!ND_TTEST_LEN(cp, len))
return(NULL);
+ if (len < 4) {
+ ND_PRINT(" len %u is too short (< 4)", len);
+ break;
+ }
ND_PRINT(" %u %u ", GET_BE_U_2(cp), GET_BE_U_2(cp + 2));
if (nd_printn(ndo, cp + 4, len - 4, ndo->ndo_snapend))
return(NULL);
break;
case T_OPT:
ND_PRINT(" UDPsize=%u", class);
if (opt_flags & 0x8000)
ND_PRINT(" DO");
if (cp < rp) {
ND_PRINT(" [");
while (cp < rp) {
cp = eopt_print(ndo, cp);
if (cp == NULL)
return(NULL);
if (cp < rp)
ND_PRINT(",");
}
ND_PRINT("]");
}
break;
case T_TSIG:
{
if (cp + len > ndo->ndo_snapend)
return(NULL);
if (!ndo->ndo_vflag)
break;
ND_PRINT(" ");
if ((cp = fqdn_print(ndo, cp, bp)) == NULL)
return(NULL);
cp += 6;
if (!ND_TTEST_2(cp))
return(NULL);
ND_PRINT(" fudge=%u", GET_BE_U_2(cp));
cp += 2;
if (!ND_TTEST_2(cp))
return(NULL);
ND_PRINT(" maclen=%u", GET_BE_U_2(cp));
cp += 2 + GET_BE_U_2(cp);
if (!ND_TTEST_2(cp))
return(NULL);
ND_PRINT(" origid=%u", GET_BE_U_2(cp));
cp += 2;
if (!ND_TTEST_2(cp))
return(NULL);
ND_PRINT(" error=%u", GET_BE_U_2(cp));
cp += 2;
if (!ND_TTEST_2(cp))
return(NULL);
ND_PRINT(" otherlen=%u", GET_BE_U_2(cp));
cp += 2;
}
}
return (rp); /* XXX This isn't always right */
}
void
domain_print(netdissect_options *ndo,
const u_char *bp, u_int length, int over_tcp, int is_mdns)
{
const dns_header_t *np;
uint16_t flags, rcode, rdlen, type;
u_int qdcount, ancount, nscount, arcount;
u_int i;
const u_char *cp;
uint16_t b2;
ndo->ndo_protocol = "domain";
if (over_tcp) {
/*
* The message is prefixed with a two byte length field
* which gives the message length, excluding the two byte
* length field. (RFC 1035 - 4.2.2. TCP usage)
*/
if (length < 2) {
ND_PRINT(" [DNS over TCP: length %u < 2]", length);
nd_print_invalid(ndo);
return;
} else {
length -= 2; /* excluding the two byte length field */
if (GET_BE_U_2(bp) != length) {
ND_PRINT(" [prefix length(%u) != length(%u)]",
GET_BE_U_2(bp), length);
nd_print_invalid(ndo);
return;
} else {
bp += 2;
/* in over TCP case, we need to prepend a space
* (not needed in over UDP case)
*/
ND_PRINT(" ");
}
}
}
np = (const dns_header_t *)bp;
if(length < sizeof(*np)) {
nd_print_protocol(ndo);
ND_PRINT(" [length %u < %zu]", length, sizeof(*np));
nd_print_invalid(ndo);
return;
}
ND_TCHECK_SIZE(np);
flags = GET_BE_U_2(np->flags);
/* get the byte-order right */
qdcount = GET_BE_U_2(np->qdcount);
ancount = GET_BE_U_2(np->ancount);
nscount = GET_BE_U_2(np->nscount);
arcount = GET_BE_U_2(np->arcount);
/* find the opt record to extract extended rcode */
cp = (const u_char *)(np + 1);
rcode = DNS_RCODE(flags);
for (i = 0; i < qdcount; i++) {
if ((cp = ns_nskip(ndo, cp)) == NULL)
goto print;
cp += 4; /* skip QTYPE and QCLASS */
if (cp >= ndo->ndo_snapend)
goto print;
}
for (i = 0; i < ancount + nscount; i++) {
if ((cp = ns_nskip(ndo, cp)) == NULL)
goto print;
cp += 8; /* skip TYPE, CLASS and TTL */
if (cp + 2 > ndo->ndo_snapend)
goto print;
rdlen = GET_BE_U_2(cp);
cp += 2 + rdlen;
if (cp >= ndo->ndo_snapend)
goto print;
}
for (i = 0; i < arcount; i++) {
if ((cp = ns_nskip(ndo, cp)) == NULL)
goto print;
if (cp + 2 > ndo->ndo_snapend)
goto print;
type = GET_BE_U_2(cp);
cp += 4; /* skip TYPE and CLASS */
if (cp + 1 > ndo->ndo_snapend)
goto print;
if (type == T_OPT) {
rcode |= (GET_U_1(cp) << 4);
goto print;
}
cp += 4;
if (cp + 2 > ndo->ndo_snapend)
goto print;
rdlen = GET_BE_U_2(cp);
cp += 2 + rdlen;
if (cp >= ndo->ndo_snapend)
goto print;
}
print:
if (DNS_QR(flags)) {
/* this is a response */
ND_PRINT("%u%s%s%s%s%s%s",
GET_BE_U_2(np->id),
ns_ops[DNS_OPCODE(flags)],
ns_rcode(rcode),
DNS_AA(flags)? "*" : "",
DNS_RA(flags)? "" : "-",
DNS_TC(flags)? "|" : "",
DNS_AD(flags)? "$" : "");
if (qdcount != 1)
ND_PRINT(" [%uq]", qdcount);
/* Print QUESTION section on -vv */
cp = (const u_char *)(np + 1);
for (i = 0; i < qdcount; i++) {
if (i != 0)
ND_PRINT(",");
if (ndo->ndo_vflag > 1) {
ND_PRINT(" q:");
if ((cp = ns_qprint(ndo, cp, bp, is_mdns)) == NULL)
goto trunc;
} else {
if ((cp = ns_nskip(ndo, cp)) == NULL)
goto trunc;
cp += 4; /* skip QTYPE and QCLASS */
}
}
ND_PRINT(" %u/%u/%u", ancount, nscount, arcount);
if (ancount) {
if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL)
goto trunc;
ancount--;
while (cp < ndo->ndo_snapend && ancount) {
ND_PRINT(",");
if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL)
goto trunc;
ancount--;
}
}
if (ancount)
goto trunc;
/* Print NS and AR sections on -vv */
if (ndo->ndo_vflag > 1) {
if (cp < ndo->ndo_snapend && nscount) {
ND_PRINT(" ns:");
if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL)
goto trunc;
nscount--;
while (cp < ndo->ndo_snapend && nscount) {
ND_PRINT(",");
if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL)
goto trunc;
nscount--;
}
}
if (nscount)
goto trunc;
if (cp < ndo->ndo_snapend && arcount) {
ND_PRINT(" ar:");
if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL)
goto trunc;
arcount--;
while (cp < ndo->ndo_snapend && arcount) {
ND_PRINT(",");
if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL)
goto trunc;
arcount--;
}
}
if (arcount)
goto trunc;
}
- }
- else {
+ } else {
/* this is a request */
ND_PRINT("%u%s%s%s", GET_BE_U_2(np->id),
ns_ops[DNS_OPCODE(flags)],
DNS_RD(flags) ? "+" : "",
DNS_CD(flags) ? "%" : "");
/* any weirdness? */
b2 = GET_BE_U_2(((const u_short *)np) + 1);
if (b2 & 0x6cf)
ND_PRINT(" [b2&3=0x%x]", b2);
if (DNS_OPCODE(flags) == IQUERY) {
if (qdcount)
ND_PRINT(" [%uq]", qdcount);
if (ancount != 1)
ND_PRINT(" [%ua]", ancount);
- }
- else {
+ } else {
if (ancount)
ND_PRINT(" [%ua]", ancount);
if (qdcount != 1)
ND_PRINT(" [%uq]", qdcount);
}
if (nscount)
ND_PRINT(" [%un]", nscount);
if (arcount)
ND_PRINT(" [%uau]", arcount);
cp = (const u_char *)(np + 1);
if (qdcount) {
cp = ns_qprint(ndo, cp, (const u_char *)np, is_mdns);
if (!cp)
goto trunc;
qdcount--;
while (cp < ndo->ndo_snapend && qdcount) {
cp = ns_qprint(ndo, (const u_char *)cp,
(const u_char *)np,
is_mdns);
if (!cp)
goto trunc;
qdcount--;
}
}
if (qdcount)
goto trunc;
/* Print remaining sections on -vv */
if (ndo->ndo_vflag > 1) {
if (ancount) {
if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL)
goto trunc;
ancount--;
while (cp < ndo->ndo_snapend && ancount) {
ND_PRINT(",");
if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL)
goto trunc;
ancount--;
}
}
if (ancount)
goto trunc;
if (cp < ndo->ndo_snapend && nscount) {
ND_PRINT(" ns:");
if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL)
goto trunc;
nscount--;
while (cp < ndo->ndo_snapend && nscount) {
ND_PRINT(",");
if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL)
goto trunc;
nscount--;
}
}
if (nscount > 0)
goto trunc;
if (cp < ndo->ndo_snapend && arcount) {
ND_PRINT(" ar:");
if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL)
goto trunc;
arcount--;
while (cp < ndo->ndo_snapend && arcount) {
ND_PRINT(",");
if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL)
goto trunc;
arcount--;
}
}
if (arcount)
goto trunc;
}
}
ND_PRINT(" (%u)", length);
return;
trunc:
nd_print_trunc(ndo);
}
diff --git a/contrib/tcpdump/print-dsa.c b/contrib/tcpdump/print-dsa.c
index 1ed9acf672f5..42d59461fd48 100644
--- a/contrib/tcpdump/print-dsa.c
+++ b/contrib/tcpdump/print-dsa.c
@@ -1,219 +1,217 @@
/*
* Copyright (c) 1988, 1989, 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.
*/
/* \summary: Marvell (Ethertype) Distributed Switch Architecture printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "ethertype.h"
#include "addrtoname.h"
#include "extract.h"
/*
* Format of (Ethertyped or not) DSA tagged frames:
*
* 7 6 5 4 3 2 1 0
* . . . . . . . . .
* 0 +---+---+---+---+---+---+---+---+
* | Ether Destination Address |
* +6 +---+---+---+---+---+---+---+---+
* | Ether Source Address |
* +6 +---+---+---+---+---+---+---+---+ +-
* | Prog. DSA Ether Type [15:8] | | (8-byte) EDSA Tag
* +1 +---+---+---+---+---+---+---+---+ | Contains a programmable Ether type,
* | Prog. DSA Ether Type [7:0] | | two reserved bytes (always 0),
* +1 +---+---+---+---+---+---+---+---+ | and a standard DSA tag.
* | Reserved (0x00 0x00) | |
* +2 +---+---+---+---+---+---+---+---+ | +-
* | Mode |b29| Src/Trg Dev | | | (4-byte) DSA Tag
* +1 +---+---+---+---+---+---+---+---+ | | Contains a DSA tag mode,
* |Src/Trg Port/Trunk |b18|b17|b16| | | source or target switch device,
* +1 +---+---+---+---+---+---+---+---+ | | source or target port or trunk,
* | PRI [2:0] |b12| VID [11:8] | | | and misc (IEEE and FPri) bits.
* +1 +---+---+---+---+---+---+---+---+ | |
* | VID [7:0] | | |
* +1 +---+---+---+---+---+---+---+---+ +- +-
* | Ether Length/Type |
* +2 +---+---+---+---+---+---+---+---+
* . . . . . . . . .
*
* Mode: Forward, To_CPU, From_CPU, To_Sniffer
* b29: (Source or Target) IEEE Tag Mode
* b18: Forward's Src_Is_Trunk, To_CPU's Code[2], To_Sniffer's Rx_Sniff
* b17: To_CPU's Code[1]
* b16: Original frame's CFI
* b12: To_CPU's Code[0]
*/
#define TOK(tag, byte, mask, shift) ((GET_U_1(&(((const u_char *) tag)[byte])) & (mask)) >> (shift))
#define DSA_LEN 4
#define DSA_MODE(tag) TOK(tag, 0, 0xc0, 6)
#define DSA_MODE_TO_CPU 0x0
#define DSA_MODE_FROM_CPU 0x1
#define DSA_MODE_TO_SNIFFER 0x2
#define DSA_MODE_FORWARD 0x3
#define DSA_TAGGED(tag) TOK(tag, 0, 0x20, 5)
#define DSA_DEV(tag) TOK(tag, 0, 0x1f, 0)
#define DSA_PORT(tag) TOK(tag, 1, 0xf8, 3)
#define DSA_TRUNK(tag) TOK(tag, 1, 0x04, 2)
#define DSA_RX_SNIFF(tag) TOK(tag, 1, 0x04, 2)
#define DSA_CFI(tag) TOK(tag, 1, 0x01, 0)
#define DSA_PRI(tag) TOK(tag, 2, 0xe0, 5)
#define DSA_VID(tag) ((u_short)((TOK(tag, 2, 0x0f, 0) << 8) | (TOK(tag, 3, 0xff, 0))))
#define DSA_CODE(tag) ((TOK(tag, 1, 0x06, 1) << 1) | TOK(tag, 2, 0x10, 4))
#define EDSA_LEN 8
static const struct tok dsa_mode_values[] = {
{ DSA_MODE_TO_CPU, "To CPU" },
{ DSA_MODE_FROM_CPU, "From CPU" },
{ DSA_MODE_TO_SNIFFER, "To Sniffer"},
{ DSA_MODE_FORWARD, "Forward" },
{ 0, NULL }
};
static const struct tok dsa_code_values[] = {
{ 0x0, "BPDU (MGMT) Trap" },
{ 0x1, "Frame2Reg" },
{ 0x2, "IGMP/MLD Trap" },
{ 0x3, "Policy Trap" },
{ 0x4, "ARP Mirror" },
{ 0x5, "Policy Mirror" },
{ 0, NULL }
};
static void
tag_common_print(netdissect_options *ndo, const u_char *p)
{
if (ndo->ndo_eflag) {
ND_PRINT("mode %s, ", tok2str(dsa_mode_values, "unknown", DSA_MODE(p)));
switch (DSA_MODE(p)) {
case DSA_MODE_FORWARD:
ND_PRINT("dev %u, %s %u, ", DSA_DEV(p),
DSA_TRUNK(p) ? "trunk" : "port", DSA_PORT(p));
break;
case DSA_MODE_FROM_CPU:
ND_PRINT("target dev %u, port %u, ",
DSA_DEV(p), DSA_PORT(p));
break;
case DSA_MODE_TO_CPU:
ND_PRINT("source dev %u, port %u, ",
DSA_DEV(p), DSA_PORT(p));
ND_PRINT("code %s, ",
tok2str(dsa_code_values, "reserved", DSA_CODE(p)));
break;
case DSA_MODE_TO_SNIFFER:
ND_PRINT("source dev %u, port %u, ",
DSA_DEV(p), DSA_PORT(p));
ND_PRINT("%s sniff, ",
DSA_RX_SNIFF(p) ? "ingress" : "egress");
break;
default:
break;
}
ND_PRINT("%s, ", DSA_TAGGED(p) ? "tagged" : "untagged");
ND_PRINT("%s", DSA_CFI(p) ? "CFI, " : "");
ND_PRINT("VID %u, ", DSA_VID(p));
ND_PRINT("FPri %u, ", DSA_PRI(p));
} else {
switch (DSA_MODE(p)) {
case DSA_MODE_FORWARD:
ND_PRINT("Forward %s %u.%u, ",
DSA_TRUNK(p) ? "trunk" : "port",
DSA_DEV(p), DSA_PORT(p));
break;
case DSA_MODE_FROM_CPU:
ND_PRINT("CPU > port %u.%u, ",
DSA_DEV(p), DSA_PORT(p));
break;
case DSA_MODE_TO_CPU:
ND_PRINT("port %u.%u > CPU, ",
DSA_DEV(p), DSA_PORT(p));
break;
case DSA_MODE_TO_SNIFFER:
ND_PRINT("port %u.%u > %s Sniffer, ",
DSA_DEV(p), DSA_PORT(p),
DSA_RX_SNIFF(p) ? "Rx" : "Tx");
break;
default:
break;
}
ND_PRINT("VLAN %u%c, ", DSA_VID(p), DSA_TAGGED(p) ? 't' : 'u');
}
}
static void
dsa_tag_print(netdissect_options *ndo, const u_char *bp)
{
if (ndo->ndo_eflag)
ND_PRINT("Marvell DSA ");
else
ND_PRINT("DSA ");
tag_common_print(ndo, bp);
}
static void
edsa_tag_print(netdissect_options *ndo, const u_char *bp)
{
const u_char *p = bp;
uint16_t edsa_etype;
edsa_etype = GET_BE_U_2(p);
if (ndo->ndo_eflag) {
ND_PRINT("Marvell EDSA ethertype 0x%04x (%s), ", edsa_etype,
tok2str(ethertype_values, "Unknown", edsa_etype));
ND_PRINT("rsvd %u %u, ", GET_U_1(p + 2), GET_U_1(p + 3));
} else
ND_PRINT("EDSA 0x%04x, ", edsa_etype);
p += 4;
tag_common_print(ndo, p);
}
void
dsa_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
{
u_int caplen = h->caplen;
u_int length = h->len;
ndo->ndo_protocol = "dsa";
ndo->ndo_ll_hdr_len +=
ether_switch_tag_print(ndo, p, length, caplen, dsa_tag_print, DSA_LEN);
}
void
edsa_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
{
u_int caplen = h->caplen;
u_int length = h->len;
ndo->ndo_protocol = "edsa";
ndo->ndo_ll_hdr_len +=
ether_switch_tag_print(ndo, p, length, caplen, edsa_tag_print, EDSA_LEN);
}
diff --git a/contrib/tcpdump/print-dtp.c b/contrib/tcpdump/print-dtp.c
index a1ae4ba4d5aa..4bc6f5ca4841 100644
--- a/contrib/tcpdump/print-dtp.c
+++ b/contrib/tcpdump/print-dtp.c
@@ -1,122 +1,120 @@
/*
* Copyright (c) 1998-2007 The TCPDUMP project
*
* 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.
*
* Original code by Carles Kishimoto <carles.kishimoto@gmail.com>
*/
/* \summary: Dynamic Trunking Protocol (DTP) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#define DTP_HEADER_LEN 1
#define DTP_DOMAIN_TLV 0x0001
#define DTP_STATUS_TLV 0x0002
#define DTP_DTP_TYPE_TLV 0x0003
#define DTP_NEIGHBOR_TLV 0x0004
static const struct tok dtp_tlv_values[] = {
{ DTP_DOMAIN_TLV, "Domain" },
{ DTP_STATUS_TLV, "Status" },
{ DTP_DTP_TYPE_TLV, "DTP type" },
{ DTP_NEIGHBOR_TLV, "Neighbor" },
{ 0, NULL}
};
void
dtp_print(netdissect_options *ndo, const u_char *tptr, u_int length)
{
ndo->ndo_protocol = "dtp";
if (length < DTP_HEADER_LEN) {
ND_PRINT("[zero packet length]");
goto invalid;
}
ND_PRINT("DTPv%u, length %u",
GET_U_1(tptr),
length);
/*
* In non-verbose mode, just print version.
*/
if (ndo->ndo_vflag < 1) {
return;
}
tptr += DTP_HEADER_LEN;
length -= DTP_HEADER_LEN;
while (length) {
uint16_t type, len;
if (length < 4) {
ND_PRINT("[%u bytes remaining]", length);
goto invalid;
}
type = GET_BE_U_2(tptr);
len = GET_BE_U_2(tptr + 2);
/* XXX: should not be but sometimes it is, see the test captures */
if (type == 0)
return;
ND_PRINT("\n\t%s (0x%04x) TLV, length %u",
tok2str(dtp_tlv_values, "Unknown", type),
type, len);
/* infinite loop check */
if (len < 4 || len > length) {
- ND_PRINT("[invalid TLV length %u]", len);
+ ND_PRINT("[TLV length %u]", len);
goto invalid;
}
switch (type) {
case DTP_DOMAIN_TLV:
ND_PRINT(", ");
nd_printjnp(ndo, tptr+4, len-4);
break;
case DTP_STATUS_TLV:
case DTP_DTP_TYPE_TLV:
if (len != 5)
goto invalid;
ND_PRINT(", 0x%x", GET_U_1(tptr + 4));
break;
case DTP_NEIGHBOR_TLV:
if (len != 10)
goto invalid;
ND_PRINT(", %s", GET_ETHERADDR_STRING(tptr+4));
break;
default:
ND_TCHECK_LEN(tptr, len);
break;
}
tptr += len;
length -= len;
}
return;
invalid:
nd_print_invalid(ndo);
ND_TCHECK_LEN(tptr, length);
}
diff --git a/contrib/tcpdump/print-dvmrp.c b/contrib/tcpdump/print-dvmrp.c
index 7d7ca07555ac..e57580b535d8 100644
--- a/contrib/tcpdump/print-dvmrp.c
+++ b/contrib/tcpdump/print-dvmrp.c
@@ -1,332 +1,330 @@
/*
* Copyright (c) 1995, 1996
* 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.
*/
/* \summary: Distance Vector Multicast Routing Protocol printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "extract.h"
#include "addrtoname.h"
/*
* See: RFC 1075 and draft-ietf-idmr-dvmrp-v3
*
* DVMRP message types and flag values shamelessly stolen from
* mrouted/dvmrp.h.
*/
#define DVMRP_PROBE 1 /* for finding neighbors */
#define DVMRP_REPORT 2 /* for reporting some or all routes */
#define DVMRP_ASK_NEIGHBORS 3 /* sent by mapper, asking for a list */
/* of this router's neighbors */
#define DVMRP_NEIGHBORS 4 /* response to such a request */
#define DVMRP_ASK_NEIGHBORS2 5 /* as above, want new format reply */
#define DVMRP_NEIGHBORS2 6
#define DVMRP_PRUNE 7 /* prune message */
#define DVMRP_GRAFT 8 /* graft message */
#define DVMRP_GRAFT_ACK 9 /* graft acknowledgement */
static const struct tok dvmrp_msgtype_str[] = {
{ DVMRP_PROBE, "Probe" },
{ DVMRP_REPORT, "Report" },
{ DVMRP_ASK_NEIGHBORS, "Ask-neighbors(old)" },
{ DVMRP_NEIGHBORS, "Neighbors(old)" },
{ DVMRP_ASK_NEIGHBORS2, "Ask-neighbors2" },
{ DVMRP_NEIGHBORS2, "Neighbors2" },
{ DVMRP_PRUNE, "Prune" },
{ DVMRP_GRAFT, "Graft" },
{ DVMRP_GRAFT_ACK, "Graft-ACK" },
{ 0, NULL }
};
/*
* 'flags' byte values in DVMRP_NEIGHBORS2 reply.
*/
#define DVMRP_NF_TUNNEL 0x01 /* neighbors reached via tunnel */
#define DVMRP_NF_SRCRT 0x02 /* tunnel uses IP source routing */
#define DVMRP_NF_DOWN 0x10 /* kernel state of interface */
#define DVMRP_NF_DISABLED 0x20 /* administratively disabled */
#define DVMRP_NF_QUERIER 0x40 /* I am the subnet's querier */
static void print_probe(netdissect_options *, const u_char *, u_int);
static void print_report(netdissect_options *, const u_char *, u_int);
static void print_neighbors(netdissect_options *, const u_char *, u_int);
static void print_neighbors2(netdissect_options *, const u_char *, u_int, uint8_t, uint8_t);
void
dvmrp_print(netdissect_options *ndo,
const u_char *bp, u_int len)
{
u_char type;
uint8_t major_version, minor_version;
ndo->ndo_protocol = "dvmrp";
if (len < 8) {
ND_PRINT(" [length %u < 8]", len);
goto invalid;
}
type = GET_U_1(bp + 1);
/* Skip IGMP header */
bp += 8;
len -= 8;
ND_PRINT(" %s", tok2str(dvmrp_msgtype_str, "[type %u]", type));
switch (type) {
case DVMRP_PROBE:
if (ndo->ndo_vflag) {
print_probe(ndo, bp, len);
}
break;
case DVMRP_REPORT:
if (ndo->ndo_vflag > 1) {
print_report(ndo, bp, len);
}
break;
case DVMRP_NEIGHBORS:
print_neighbors(ndo, bp, len);
break;
case DVMRP_NEIGHBORS2:
/*
* extract version from IGMP group address field
*/
bp -= 4;
major_version = GET_U_1(bp + 3);
minor_version = GET_U_1(bp + 2);
bp += 4;
print_neighbors2(ndo, bp, len, major_version, minor_version);
break;
case DVMRP_PRUNE:
ND_PRINT(" src %s grp %s", GET_IPADDR_STRING(bp), GET_IPADDR_STRING(bp + 4));
ND_PRINT(" timer ");
unsigned_relts_print(ndo, GET_BE_U_4(bp + 8));
break;
case DVMRP_GRAFT:
ND_PRINT(" src %s grp %s", GET_IPADDR_STRING(bp), GET_IPADDR_STRING(bp + 4));
break;
case DVMRP_GRAFT_ACK:
ND_PRINT(" src %s grp %s", GET_IPADDR_STRING(bp), GET_IPADDR_STRING(bp + 4));
break;
}
return;
invalid:
nd_print_invalid(ndo);
}
static void
print_report(netdissect_options *ndo,
const u_char *bp,
u_int len)
{
uint32_t mask, origin;
u_int metric, done;
u_int i, width;
while (len > 0) {
if (len < 3) {
ND_PRINT(" [length %u < 3]", len);
goto invalid;
}
mask = (uint32_t)0xff << 24 | GET_U_1(bp) << 16 |
GET_U_1(bp + 1) << 8 | GET_U_1(bp + 2);
width = 1;
if (GET_U_1(bp))
width = 2;
if (GET_U_1(bp + 1))
width = 3;
if (GET_U_1(bp + 2))
width = 4;
ND_PRINT("\n\tMask %s", intoa(htonl(mask)));
bp += 3;
len -= 3;
do {
if (len < width + 1) {
ND_PRINT("\n\t [Truncated Report]");
goto invalid;
}
origin = 0;
for (i = 0; i < width; ++i) {
origin = origin << 8 | GET_U_1(bp);
bp++;
}
for ( ; i < 4; ++i)
origin <<= 8;
metric = GET_U_1(bp);
bp++;
done = metric & 0x80;
metric &= 0x7f;
ND_PRINT("\n\t %s metric %u", intoa(htonl(origin)),
metric);
len -= width + 1;
} while (!done);
}
return;
invalid:
nd_print_invalid(ndo);
}
static void
print_probe(netdissect_options *ndo,
const u_char *bp,
u_int len)
{
if (len < 4) {
ND_PRINT(" [full length %u < 4]", len);
goto invalid;
}
ND_PRINT(ndo->ndo_vflag > 1 ? "\n\t" : " ");
ND_PRINT("genid %u", GET_BE_U_4(bp));
if (ndo->ndo_vflag < 2)
return;
bp += 4;
len -= 4;
while (len > 0) {
if (len < 4) {
ND_PRINT("[remaining length %u < 4]", len);
goto invalid;
}
ND_PRINT("\n\tneighbor %s", GET_IPADDR_STRING(bp));
bp += 4; len -= 4;
}
return;
invalid:
nd_print_invalid(ndo);
}
static void
print_neighbors(netdissect_options *ndo,
const u_char *bp,
u_int len)
{
const u_char *laddr;
u_char metric;
u_char thresh;
int ncount;
while (len > 0) {
if (len < 7) {
ND_PRINT(" [length %u < 7]", len);
goto invalid;
}
laddr = bp;
bp += 4;
metric = GET_U_1(bp);
bp++;
thresh = GET_U_1(bp);
bp++;
ncount = GET_U_1(bp);
bp++;
len -= 7;
while (--ncount >= 0) {
if (len < 4) {
ND_PRINT(" [length %u < 4]", len);
goto invalid;
}
ND_PRINT(" [%s ->", GET_IPADDR_STRING(laddr));
ND_PRINT(" %s, (%u/%u)]",
GET_IPADDR_STRING(bp), metric, thresh);
bp += 4;
len -= 4;
}
}
return;
invalid:
nd_print_invalid(ndo);
}
static void
print_neighbors2(netdissect_options *ndo,
const u_char *bp,
u_int len, uint8_t major_version,
uint8_t minor_version)
{
const u_char *laddr;
u_char metric, thresh, flags;
int ncount;
ND_PRINT(" (v %u.%u):", major_version, minor_version);
while (len > 0) {
if (len < 8) {
ND_PRINT(" [length %u < 8]", len);
goto invalid;
}
laddr = bp;
bp += 4;
metric = GET_U_1(bp);
bp++;
thresh = GET_U_1(bp);
bp++;
flags = GET_U_1(bp);
bp++;
ncount = GET_U_1(bp);
bp++;
len -= 8;
while (--ncount >= 0 && len > 0) {
if (len < 4) {
ND_PRINT(" [length %u < 4]", len);
goto invalid;
}
ND_PRINT(" [%s -> ", GET_IPADDR_STRING(laddr));
ND_PRINT("%s (%u/%u", GET_IPADDR_STRING(bp),
metric, thresh);
if (flags & DVMRP_NF_TUNNEL)
ND_PRINT("/tunnel");
if (flags & DVMRP_NF_SRCRT)
ND_PRINT("/srcrt");
if (flags & DVMRP_NF_QUERIER)
ND_PRINT("/querier");
if (flags & DVMRP_NF_DISABLED)
ND_PRINT("/disabled");
if (flags & DVMRP_NF_DOWN)
ND_PRINT("/down");
ND_PRINT(")]");
bp += 4;
len -= 4;
}
if (ncount != -1) {
- ND_PRINT(" [invalid ncount]");
+ ND_PRINT(" [ncount %d]", ncount);
goto invalid;
}
}
return;
invalid:
nd_print_invalid(ndo);
}
diff --git a/contrib/tcpdump/print-eap.c b/contrib/tcpdump/print-eap.c
index 78439b71c003..1b1b9762a4ad 100644
--- a/contrib/tcpdump/print-eap.c
+++ b/contrib/tcpdump/print-eap.c
@@ -1,341 +1,340 @@
/*
* Copyright (c) 2004 - Michael Richardson <mcr@xelerance.com>
*
* 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.
*/
/* \summary: Extensible Authentication Protocol (EAP) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "extract.h"
#define EAP_FRAME_TYPE_PACKET 0
#define EAP_FRAME_TYPE_START 1
#define EAP_FRAME_TYPE_LOGOFF 2
#define EAP_FRAME_TYPE_KEY 3
#define EAP_FRAME_TYPE_ENCAP_ASF_ALERT 4
struct eap_frame_t {
nd_uint8_t version;
nd_uint8_t type;
nd_uint16_t length;
};
static const struct tok eap_frame_type_values[] = {
{ EAP_FRAME_TYPE_PACKET, "EAP packet" },
{ EAP_FRAME_TYPE_START, "EAPOL start" },
{ EAP_FRAME_TYPE_LOGOFF, "EAPOL logoff" },
{ EAP_FRAME_TYPE_KEY, "EAPOL key" },
{ EAP_FRAME_TYPE_ENCAP_ASF_ALERT, "Encapsulated ASF alert" },
{ 0, NULL}
};
/* RFC 3748 */
struct eap_packet_t {
nd_uint8_t code;
nd_uint8_t id;
nd_uint16_t length;
};
#define EAP_REQUEST 1
#define EAP_RESPONSE 2
#define EAP_SUCCESS 3
#define EAP_FAILURE 4
static const struct tok eap_code_values[] = {
{ EAP_REQUEST, "Request" },
{ EAP_RESPONSE, "Response" },
{ EAP_SUCCESS, "Success" },
{ EAP_FAILURE, "Failure" },
{ 0, NULL}
};
#define EAP_TYPE_NO_PROPOSED 0
#define EAP_TYPE_IDENTITY 1
#define EAP_TYPE_NOTIFICATION 2
#define EAP_TYPE_NAK 3
#define EAP_TYPE_MD5_CHALLENGE 4
#define EAP_TYPE_OTP 5
#define EAP_TYPE_GTC 6
#define EAP_TYPE_TLS 13 /* RFC 5216 */
#define EAP_TYPE_SIM 18 /* RFC 4186 */
#define EAP_TYPE_TTLS 21 /* RFC 5281, draft-funk-eap-ttls-v0-01.txt */
#define EAP_TYPE_AKA 23 /* RFC 4187 */
#define EAP_TYPE_FAST 43 /* RFC 4851 */
#define EAP_TYPE_EXPANDED_TYPES 254
#define EAP_TYPE_EXPERIMENTAL 255
static const struct tok eap_type_values[] = {
{ EAP_TYPE_NO_PROPOSED, "No proposed" },
{ EAP_TYPE_IDENTITY, "Identity" },
{ EAP_TYPE_NOTIFICATION, "Notification" },
{ EAP_TYPE_NAK, "Nak" },
{ EAP_TYPE_MD5_CHALLENGE, "MD5-challenge" },
{ EAP_TYPE_OTP, "OTP" },
{ EAP_TYPE_GTC, "GTC" },
{ EAP_TYPE_TLS, "TLS" },
{ EAP_TYPE_SIM, "SIM" },
{ EAP_TYPE_TTLS, "TTLS" },
{ EAP_TYPE_AKA, "AKA" },
{ EAP_TYPE_FAST, "FAST" },
{ EAP_TYPE_EXPANDED_TYPES, "Expanded types" },
{ EAP_TYPE_EXPERIMENTAL, "Experimental" },
{ 0, NULL}
};
#define EAP_TLS_EXTRACT_BIT_L(x) (((x)&0x80)>>7)
/* RFC 5216 - EAP TLS bits */
#define EAP_TLS_FLAGS_LEN_INCLUDED (1 << 7)
#define EAP_TLS_FLAGS_MORE_FRAGMENTS (1 << 6)
#define EAP_TLS_FLAGS_START (1 << 5)
static const struct tok eap_tls_flags_values[] = {
{ EAP_TLS_FLAGS_LEN_INCLUDED, "L bit" },
{ EAP_TLS_FLAGS_MORE_FRAGMENTS, "More fragments bit"},
{ EAP_TLS_FLAGS_START, "Start bit"},
{ 0, NULL}
};
#define EAP_TTLS_VERSION(x) ((x)&0x07)
/* EAP-AKA and EAP-SIM - RFC 4187 */
#define EAP_AKA_CHALLENGE 1
#define EAP_AKA_AUTH_REJECT 2
#define EAP_AKA_SYNC_FAILURE 4
#define EAP_AKA_IDENTITY 5
#define EAP_SIM_START 10
#define EAP_SIM_CHALLENGE 11
#define EAP_AKA_NOTIFICATION 12
#define EAP_AKA_REAUTH 13
#define EAP_AKA_CLIENT_ERROR 14
static const struct tok eap_aka_subtype_values[] = {
{ EAP_AKA_CHALLENGE, "Challenge" },
{ EAP_AKA_AUTH_REJECT, "Auth reject" },
{ EAP_AKA_SYNC_FAILURE, "Sync failure" },
{ EAP_AKA_IDENTITY, "Identity" },
{ EAP_SIM_START, "Start" },
{ EAP_SIM_CHALLENGE, "Challenge" },
{ EAP_AKA_NOTIFICATION, "Notification" },
{ EAP_AKA_REAUTH, "Reauth" },
{ EAP_AKA_CLIENT_ERROR, "Client error" },
{ 0, NULL}
};
/*
* Print EAP requests / responses
*/
void
eap_print(netdissect_options *ndo,
const u_char *cp,
u_int length)
{
u_int type, subtype, len;
u_int count;
const char *sep;
+ ndo->ndo_protocol = "eap";
type = GET_U_1(cp);
len = GET_BE_U_2(cp + 2);
if (len != length) {
/*
* Probably a fragment; in some cases the fragmentation might
* not put an EAP header on every packet, if reassembly can
* be done without that (e.g., fragmentation to make a message
* fit in multiple TLVs in a RADIUS packet).
*/
ND_PRINT("EAP fragment?");
return;
}
ND_PRINT("%s (%u), id %u, len %u",
tok2str(eap_code_values, "unknown", type),
type,
GET_U_1((cp + 1)),
len);
if (len < 4) {
ND_PRINT(" (too short for EAP header)");
return;
}
ND_TCHECK_LEN(cp, len);
if (type == EAP_REQUEST || type == EAP_RESPONSE) {
/* RFC 3748 Section 4.1 */
if (len < 5) {
ND_PRINT(" (too short for EAP request/response)");
return;
}
subtype = GET_U_1(cp + 4);
ND_PRINT("\n\t\t Type %s (%u)",
tok2str(eap_type_values, "unknown", subtype),
subtype);
switch (subtype) {
case EAP_TYPE_IDENTITY:
/* According to RFC 3748, the message is optional */
if (len > 5) {
ND_PRINT(", Identity: ");
nd_printjnp(ndo, cp + 5, len - 5);
}
break;
case EAP_TYPE_NOTIFICATION:
/* According to RFC 3748, there must be at least one octet of message */
if (len < 6) {
ND_PRINT(" (too short for EAP Notification request/response)");
return;
}
ND_PRINT(", Notification: ");
nd_printjnp(ndo, cp + 5, len - 5);
break;
case EAP_TYPE_NAK:
/*
* one or more octets indicating
* the desired authentication
* type one octet per type
*/
if (len < 6) {
ND_PRINT(" (too short for EAP Legacy NAK request/response)");
return;
}
sep = "";
for (count = 5; count < len; count++) {
ND_PRINT("%s %s (%u)", sep,
tok2str(eap_type_values, "unknown", GET_U_1((cp + count))),
GET_U_1(cp + count));
sep = ",";
}
break;
case EAP_TYPE_TTLS:
case EAP_TYPE_TLS:
if (len < 6) {
ND_PRINT(" (too short for EAP TLS/TTLS request/response)");
return;
}
if (subtype == EAP_TYPE_TTLS)
ND_PRINT(" TTLSv%u",
EAP_TTLS_VERSION(GET_U_1((cp + 5))));
ND_PRINT(" flags [%s] 0x%02x",
bittok2str(eap_tls_flags_values, "none", GET_U_1((cp + 5))),
GET_U_1(cp + 5));
if (EAP_TLS_EXTRACT_BIT_L(GET_U_1(cp + 5))) {
if (len < 10) {
ND_PRINT(" (too short for EAP TLS/TTLS request/response with length)");
return;
}
ND_PRINT(", len %u", GET_BE_U_4(cp + 6));
}
break;
case EAP_TYPE_FAST:
if (len < 6) {
ND_PRINT(" (too short for EAP FAST request/response)");
return;
}
ND_PRINT(" FASTv%u",
EAP_TTLS_VERSION(GET_U_1((cp + 5))));
ND_PRINT(" flags [%s] 0x%02x",
bittok2str(eap_tls_flags_values, "none", GET_U_1((cp + 5))),
GET_U_1(cp + 5));
if (EAP_TLS_EXTRACT_BIT_L(GET_U_1(cp + 5))) {
if (len < 10) {
ND_PRINT(" (too short for EAP FAST request/response with length)");
return;
}
ND_PRINT(", len %u", GET_BE_U_4(cp + 6));
}
/* FIXME - TLV attributes follow */
break;
case EAP_TYPE_AKA:
case EAP_TYPE_SIM:
if (len < 6) {
ND_PRINT(" (too short for EAP SIM/AKA request/response)");
return;
}
ND_PRINT(" subtype [%s] 0x%02x",
tok2str(eap_aka_subtype_values, "unknown", GET_U_1((cp + 5))),
GET_U_1(cp + 5));
/* FIXME - TLV attributes follow */
break;
case EAP_TYPE_MD5_CHALLENGE:
case EAP_TYPE_OTP:
case EAP_TYPE_GTC:
case EAP_TYPE_EXPANDED_TYPES:
case EAP_TYPE_EXPERIMENTAL:
default:
break;
}
}
return;
trunc:
nd_print_trunc(ndo);
}
void
eapol_print(netdissect_options *ndo,
const u_char *cp)
{
const struct eap_frame_t *eap;
u_int eap_type, eap_len;
ndo->ndo_protocol = "eap";
eap = (const struct eap_frame_t *)cp;
ND_TCHECK_SIZE(eap);
eap_type = GET_U_1(eap->type);
ND_PRINT("%s (%u) v%u, len %u",
tok2str(eap_frame_type_values, "unknown", eap_type),
eap_type,
GET_U_1(eap->version),
GET_BE_U_2(eap->length));
if (ndo->ndo_vflag < 1)
return;
cp += sizeof(struct eap_frame_t);
eap_len = GET_BE_U_2(eap->length);
switch (eap_type) {
case EAP_FRAME_TYPE_PACKET:
if (eap_len == 0)
goto trunc;
ND_PRINT(", ");
eap_print(ndo, cp, eap_len);
return;
case EAP_FRAME_TYPE_LOGOFF:
case EAP_FRAME_TYPE_ENCAP_ASF_ALERT:
default:
break;
}
return;
trunc:
nd_print_trunc(ndo);
}
diff --git a/contrib/tcpdump/print-egp.c b/contrib/tcpdump/print-egp.c
index cc9f44e3c09e..60a3fb4f59d9 100644
--- a/contrib/tcpdump/print-egp.c
+++ b/contrib/tcpdump/print-egp.c
@@ -1,392 +1,390 @@
/*
* Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Lawrence Berkeley Laboratory,
* Berkeley, CA. The name of the University may not 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.
*
* Initial contribution from Jeff Honig (jch@MITCHELL.CIT.CORNELL.EDU).
*/
/* \summary: Exterior Gateway Protocol (EGP) printer */
/* specification: RFC 827 */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
struct egp_packet {
nd_uint8_t egp_version;
#define EGP_VERSION 2
nd_uint8_t egp_type;
#define EGPT_ACQUIRE 3
#define EGPT_REACH 5
#define EGPT_POLL 2
#define EGPT_UPDATE 1
#define EGPT_ERROR 8
nd_uint8_t egp_code;
#define EGPC_REQUEST 0
#define EGPC_CONFIRM 1
#define EGPC_REFUSE 2
#define EGPC_CEASE 3
#define EGPC_CEASEACK 4
#define EGPC_HELLO 0
#define EGPC_HEARDU 1
nd_uint8_t egp_status;
#define EGPS_UNSPEC 0
#define EGPS_ACTIVE 1
#define EGPS_PASSIVE 2
#define EGPS_NORES 3
#define EGPS_ADMIN 4
#define EGPS_GODOWN 5
#define EGPS_PARAM 6
#define EGPS_PROTO 7
#define EGPS_INDET 0
#define EGPS_UP 1
#define EGPS_DOWN 2
#define EGPS_UNSOL 0x80
nd_uint16_t egp_checksum;
nd_uint16_t egp_as;
nd_uint16_t egp_sequence;
union {
nd_uint16_t egpu_hello;
nd_uint8_t egpu_gws[2];
nd_uint16_t egpu_reason;
#define EGPR_UNSPEC 0
#define EGPR_BADHEAD 1
#define EGPR_BADDATA 2
#define EGPR_NOREACH 3
#define EGPR_XSPOLL 4
#define EGPR_NORESP 5
#define EGPR_UVERSION 6
} egp_handg;
#define egp_hello egp_handg.egpu_hello
#define egp_intgw egp_handg.egpu_gws[0]
#define egp_extgw egp_handg.egpu_gws[1]
#define egp_reason egp_handg.egpu_reason
union {
nd_uint16_t egpu_poll;
nd_ipv4 egpu_sourcenet;
} egp_pands;
#define egp_poll egp_pands.egpu_poll
#define egp_sourcenet egp_pands.egpu_sourcenet
};
static const char *egp_acquire_codes[] = {
"request",
"confirm",
"refuse",
"cease",
"cease_ack"
};
static const char *egp_acquire_status[] = {
"unspecified",
"active_mode",
"passive_mode",
"insufficient_resources",
"administratively_prohibited",
"going_down",
"parameter_violation",
"protocol_violation"
};
static const char *egp_reach_codes[] = {
"hello",
"i-h-u"
};
static const char *egp_status_updown[] = {
"indeterminate",
"up",
"down"
};
static const char *egp_reasons[] = {
"unspecified",
"bad_EGP_header_format",
"bad_EGP_data_field_format",
"reachability_info_unavailable",
"excessive_polling_rate",
"no_response",
"unsupported_version"
};
static void
egpnr_print(netdissect_options *ndo,
const struct egp_packet *egp, u_int length)
{
const uint8_t *cp;
uint32_t addr;
uint32_t net;
u_int netlen;
u_int gateways, distances, networks;
u_int intgw, extgw, t_gateways;
const char *comma;
addr = GET_IPV4_TO_NETWORK_ORDER(egp->egp_sourcenet);
if (IN_CLASSA(addr)) {
net = addr & IN_CLASSA_NET;
netlen = 1;
} else if (IN_CLASSB(addr)) {
net = addr & IN_CLASSB_NET;
netlen = 2;
} else if (IN_CLASSC(addr)) {
net = addr & IN_CLASSC_NET;
netlen = 3;
} else {
net = 0;
netlen = 0;
}
cp = (const uint8_t *)(egp + 1);
length -= sizeof(*egp);
intgw = GET_U_1(egp->egp_intgw);
extgw = GET_U_1(egp->egp_extgw);
t_gateways = intgw + extgw;
for (gateways = 0; gateways < t_gateways; ++gateways) {
/* Pickup host part of gateway address */
addr = 0;
if (length < 4 - netlen)
goto trunc;
ND_TCHECK_LEN(cp, 4 - netlen);
switch (netlen) {
case 1:
addr = GET_U_1(cp);
cp++;
/* fall through */
case 2:
addr = (addr << 8) | GET_U_1(cp);
cp++;
/* fall through */
case 3:
addr = (addr << 8) | GET_U_1(cp);
cp++;
break;
}
addr |= net;
length -= 4 - netlen;
if (length < 1)
goto trunc;
distances = GET_U_1(cp);
cp++;
length--;
ND_PRINT(" %s %s ",
gateways < intgw ? "int" : "ext",
ipaddr_string(ndo, (const u_char *)&addr)); /* local buffer, not packet data; don't use GET_IPADDR_STRING() */
comma = "";
ND_PRINT("(");
while (distances != 0) {
if (length < 2)
goto trunc;
ND_PRINT("%sd%u:", comma, GET_U_1(cp));
cp++;
comma = ", ";
networks = GET_U_1(cp);
cp++;
length -= 2;
while (networks != 0) {
/* Pickup network number */
if (length < 1)
goto trunc;
addr = ((uint32_t) GET_U_1(cp)) << 24;
cp++;
length--;
if (IN_CLASSB(addr)) {
if (length < 1)
goto trunc;
addr |= ((uint32_t) GET_U_1(cp)) << 16;
cp++;
length--;
} else if (!IN_CLASSA(addr)) {
if (length < 2)
goto trunc;
addr |= ((uint32_t) GET_U_1(cp)) << 16;
cp++;
addr |= ((uint32_t) GET_U_1(cp)) << 8;
cp++;
length -= 2;
}
ND_PRINT(" %s", ipaddr_string(ndo, (const u_char *)&addr)); /* local buffer, not packet data; don't use GET_IPADDR_STRING() */
networks--;
}
distances--;
}
ND_PRINT(")");
}
return;
trunc:
nd_print_trunc(ndo);
}
void
egp_print(netdissect_options *ndo,
const uint8_t *bp, u_int length)
{
const struct egp_packet *egp;
u_int version;
u_int type;
u_int code;
u_int status;
ndo->ndo_protocol = "egp";
egp = (const struct egp_packet *)bp;
if (length < sizeof(*egp) || !ND_TTEST_SIZE(egp)) {
nd_print_trunc(ndo);
return;
}
version = GET_U_1(egp->egp_version);
if (!ndo->ndo_vflag) {
ND_PRINT("EGPv%u, AS %u, seq %u, length %u",
version,
GET_BE_U_2(egp->egp_as),
GET_BE_U_2(egp->egp_sequence),
length);
return;
} else
ND_PRINT("EGPv%u, length %u",
version,
length);
if (version != EGP_VERSION) {
ND_PRINT("[version %u]", version);
return;
}
type = GET_U_1(egp->egp_type);
code = GET_U_1(egp->egp_code);
status = GET_U_1(egp->egp_status);
switch (type) {
case EGPT_ACQUIRE:
ND_PRINT(" acquire");
switch (code) {
case EGPC_REQUEST:
case EGPC_CONFIRM:
ND_PRINT(" %s", egp_acquire_codes[code]);
switch (status) {
case EGPS_UNSPEC:
case EGPS_ACTIVE:
case EGPS_PASSIVE:
ND_PRINT(" %s", egp_acquire_status[status]);
break;
default:
ND_PRINT(" [status %u]", status);
break;
}
ND_PRINT(" hello:%u poll:%u",
GET_BE_U_2(egp->egp_hello),
GET_BE_U_2(egp->egp_poll));
break;
case EGPC_REFUSE:
case EGPC_CEASE:
case EGPC_CEASEACK:
ND_PRINT(" %s", egp_acquire_codes[code]);
switch (status ) {
case EGPS_UNSPEC:
case EGPS_NORES:
case EGPS_ADMIN:
case EGPS_GODOWN:
case EGPS_PARAM:
case EGPS_PROTO:
ND_PRINT(" %s", egp_acquire_status[status]);
break;
default:
ND_PRINT("[status %u]", status);
break;
}
break;
default:
ND_PRINT("[code %u]", code);
break;
}
break;
case EGPT_REACH:
switch (code) {
case EGPC_HELLO:
case EGPC_HEARDU:
ND_PRINT(" %s", egp_reach_codes[code]);
if (status <= EGPS_DOWN)
ND_PRINT(" state:%s", egp_status_updown[status]);
else
ND_PRINT(" [status %u]", status);
break;
default:
ND_PRINT("[reach code %u]", code);
break;
}
break;
case EGPT_POLL:
ND_PRINT(" poll");
if (status <= EGPS_DOWN)
ND_PRINT(" state:%s", egp_status_updown[status]);
else
ND_PRINT(" [status %u]", status);
ND_PRINT(" net:%s", GET_IPADDR_STRING(egp->egp_sourcenet));
break;
case EGPT_UPDATE:
ND_PRINT(" update");
if (status & EGPS_UNSOL) {
status &= ~EGPS_UNSOL;
ND_PRINT(" unsolicited");
}
if (status <= EGPS_DOWN)
ND_PRINT(" state:%s", egp_status_updown[status]);
else
ND_PRINT(" [status %u]", status);
ND_PRINT(" %s int %u ext %u",
GET_IPADDR_STRING(egp->egp_sourcenet),
GET_U_1(egp->egp_intgw),
GET_U_1(egp->egp_extgw));
if (ndo->ndo_vflag)
egpnr_print(ndo, egp, length);
break;
case EGPT_ERROR:
ND_PRINT(" error");
if (status <= EGPS_DOWN)
ND_PRINT(" state:%s", egp_status_updown[status]);
else
ND_PRINT(" [status %u]", status);
if (GET_BE_U_2(egp->egp_reason) <= EGPR_UVERSION)
ND_PRINT(" %s",
egp_reasons[GET_BE_U_2(egp->egp_reason)]);
else
ND_PRINT(" [reason %u]", GET_BE_U_2(egp->egp_reason));
break;
default:
ND_PRINT("[type %u]", type);
break;
}
}
diff --git a/contrib/tcpdump/print-eigrp.c b/contrib/tcpdump/print-eigrp.c
index 2702beb2972a..9116cf685b9a 100644
--- a/contrib/tcpdump/print-eigrp.c
+++ b/contrib/tcpdump/print-eigrp.c
@@ -1,532 +1,530 @@
/*
* Copyright (c) 1998-2004 Hannes Gredler <hannes@gredler.at>
* The TCPDUMP project
*
* 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.
*/
/* \summary: Enhanced Interior Gateway Routing Protocol (EIGRP) printer */
/*
* specification:
*
* https://web.archive.org/web/20190722221712/https://www.rhyshaden.com/eigrp.htm
* RFC 7868
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <string.h>
#include "netdissect.h"
#include "extract.h"
#include "addrtoname.h"
struct eigrp_common_header {
nd_uint8_t version;
nd_uint8_t opcode;
nd_uint16_t checksum;
nd_uint32_t flags;
nd_uint32_t seq;
nd_uint32_t ack;
nd_uint16_t vrid;
nd_uint16_t asn;
};
#define EIGRP_VERSION 2
#define EIGRP_OPCODE_UPDATE 1
#define EIGRP_OPCODE_QUERY 3
#define EIGRP_OPCODE_REPLY 4
#define EIGRP_OPCODE_HELLO 5
#define EIGRP_OPCODE_IPXSAP 6
#define EIGRP_OPCODE_PROBE 7
static const struct tok eigrp_opcode_values[] = {
{ EIGRP_OPCODE_UPDATE, "Update" },
{ EIGRP_OPCODE_QUERY, "Query" },
{ EIGRP_OPCODE_REPLY, "Reply" },
{ EIGRP_OPCODE_HELLO, "Hello" },
{ EIGRP_OPCODE_IPXSAP, "IPX SAP" },
{ EIGRP_OPCODE_PROBE, "Probe" },
{ 0, NULL}
};
static const struct tok eigrp_common_header_flag_values[] = {
{ 0x01, "Init" },
{ 0x02, "Conditionally Received" },
{ 0x04, "Restart" },
{ 0x08, "End-of-Table" },
{ 0, NULL}
};
struct eigrp_tlv_header {
nd_uint16_t type;
nd_uint16_t length;
};
#define EIGRP_TLV_GENERAL_PARM 0x0001
#define EIGRP_TLV_AUTH 0x0002
#define EIGRP_TLV_SEQ 0x0003
#define EIGRP_TLV_SW_VERSION 0x0004
#define EIGRP_TLV_MCAST_SEQ 0x0005
#define EIGRP_TLV_IP_INT 0x0102
#define EIGRP_TLV_IP_EXT 0x0103
#define EIGRP_TLV_AT_INT 0x0202
#define EIGRP_TLV_AT_EXT 0x0203
#define EIGRP_TLV_AT_CABLE_SETUP 0x0204
#define EIGRP_TLV_IPX_INT 0x0302
#define EIGRP_TLV_IPX_EXT 0x0303
static const struct tok eigrp_tlv_values[] = {
{ EIGRP_TLV_GENERAL_PARM, "General Parameters"},
{ EIGRP_TLV_AUTH, "Authentication"},
{ EIGRP_TLV_SEQ, "Sequence"},
{ EIGRP_TLV_SW_VERSION, "Software Version"},
{ EIGRP_TLV_MCAST_SEQ, "Next Multicast Sequence"},
{ EIGRP_TLV_IP_INT, "IP Internal routes"},
{ EIGRP_TLV_IP_EXT, "IP External routes"},
{ EIGRP_TLV_AT_INT, "AppleTalk Internal routes"},
{ EIGRP_TLV_AT_EXT, "AppleTalk External routes"},
{ EIGRP_TLV_AT_CABLE_SETUP, "AppleTalk Cable setup"},
{ EIGRP_TLV_IPX_INT, "IPX Internal routes"},
{ EIGRP_TLV_IPX_EXT, "IPX External routes"},
{ 0, NULL}
};
struct eigrp_tlv_general_parm_t {
nd_uint8_t k1;
nd_uint8_t k2;
nd_uint8_t k3;
nd_uint8_t k4;
nd_uint8_t k5;
nd_uint8_t res;
nd_uint16_t holdtime;
};
struct eigrp_tlv_sw_version_t {
nd_uint8_t ios_major;
nd_uint8_t ios_minor;
nd_uint8_t eigrp_major;
nd_uint8_t eigrp_minor;
};
struct eigrp_tlv_ip_int_t {
nd_ipv4 nexthop;
nd_uint32_t delay;
nd_uint32_t bandwidth;
nd_uint24_t mtu;
nd_uint8_t hopcount;
nd_uint8_t reliability;
nd_uint8_t load;
nd_byte reserved[2];
nd_uint8_t plen;
nd_uint8_t destination; /* variable length [1-4] bytes encoding */
};
struct eigrp_tlv_ip_ext_t {
nd_ipv4 nexthop;
nd_ipv4 origin_router;
nd_uint32_t origin_as;
nd_uint32_t tag;
nd_uint32_t metric;
nd_byte reserved[2];
nd_uint8_t proto_id;
nd_uint8_t flags;
nd_uint32_t delay;
nd_uint32_t bandwidth;
nd_uint24_t mtu;
nd_uint8_t hopcount;
nd_uint8_t reliability;
nd_uint8_t load;
nd_byte reserved2[2];
nd_uint8_t plen;
nd_uint8_t destination; /* variable length [1-4] bytes encoding */
};
struct eigrp_tlv_at_cable_setup_t {
nd_uint16_t cable_start;
nd_uint16_t cable_end;
nd_uint32_t router_id;
};
struct eigrp_tlv_at_int_t {
nd_byte nexthop[4];
nd_uint32_t delay;
nd_uint32_t bandwidth;
nd_uint24_t mtu;
nd_uint8_t hopcount;
nd_uint8_t reliability;
nd_uint8_t load;
nd_byte reserved[2];
nd_uint16_t cable_start;
nd_uint16_t cable_end;
};
struct eigrp_tlv_at_ext_t {
nd_byte nexthop[4];
nd_uint32_t origin_router;
nd_uint32_t origin_as;
nd_uint32_t tag;
nd_uint8_t proto_id;
nd_uint8_t flags;
nd_uint16_t metric;
nd_uint32_t delay;
nd_uint32_t bandwidth;
nd_uint24_t mtu;
nd_uint8_t hopcount;
nd_uint8_t reliability;
nd_uint8_t load;
nd_byte reserved2[2];
nd_uint16_t cable_start;
nd_uint16_t cable_end;
};
static const struct tok eigrp_ext_proto_id_values[] = {
{ 0x01, "IGRP" },
{ 0x02, "EIGRP" },
{ 0x03, "Static" },
{ 0x04, "RIP" },
{ 0x05, "Hello" },
{ 0x06, "OSPF" },
{ 0x07, "IS-IS" },
{ 0x08, "EGP" },
{ 0x09, "BGP" },
{ 0x0a, "IDRP" },
{ 0x0b, "Connected" },
{ 0, NULL}
};
void
eigrp_print(netdissect_options *ndo, const u_char *pptr, u_int len)
{
const struct eigrp_common_header *eigrp_com_header;
const struct eigrp_tlv_header *eigrp_tlv_header;
const u_char *tptr,*tlv_tptr;
u_int tlen,eigrp_tlv_len,eigrp_tlv_type,tlv_tlen, byte_length, bit_length;
uint8_t prefix[4];
union {
const struct eigrp_tlv_general_parm_t *eigrp_tlv_general_parm;
const struct eigrp_tlv_sw_version_t *eigrp_tlv_sw_version;
const struct eigrp_tlv_ip_int_t *eigrp_tlv_ip_int;
const struct eigrp_tlv_ip_ext_t *eigrp_tlv_ip_ext;
const struct eigrp_tlv_at_cable_setup_t *eigrp_tlv_at_cable_setup;
const struct eigrp_tlv_at_int_t *eigrp_tlv_at_int;
const struct eigrp_tlv_at_ext_t *eigrp_tlv_at_ext;
} tlv_ptr;
ndo->ndo_protocol = "eigrp";
tptr=pptr;
eigrp_com_header = (const struct eigrp_common_header *)pptr;
ND_TCHECK_SIZE(eigrp_com_header);
/*
* Sanity checking of the header.
*/
if (GET_U_1(eigrp_com_header->version) != EIGRP_VERSION) {
ND_PRINT("EIGRP version %u packet not supported",
GET_U_1(eigrp_com_header->version));
return;
}
/* in non-verbose mode just lets print the basic Message Type*/
if (ndo->ndo_vflag < 1) {
ND_PRINT("EIGRP %s, length: %u",
tok2str(eigrp_opcode_values, "unknown (%u)",GET_U_1(eigrp_com_header->opcode)),
len);
return;
}
/* ok they seem to want to know everything - lets fully decode it */
if (len < sizeof(struct eigrp_common_header)) {
ND_PRINT("EIGRP %s, length: %u (too short, < %zu)",
tok2str(eigrp_opcode_values, "unknown (%u)",GET_U_1(eigrp_com_header->opcode)),
len, sizeof(struct eigrp_common_header));
return;
}
tlen=len-sizeof(struct eigrp_common_header);
ND_PRINT("\n\tEIGRP v%u, opcode: %s (%u), chksum: 0x%04x, Flags: [%s]"
"\n\tseq: 0x%08x, ack: 0x%08x, VRID: %u, AS: %u, length: %u",
GET_U_1(eigrp_com_header->version),
tok2str(eigrp_opcode_values, "unknown, type: %u",GET_U_1(eigrp_com_header->opcode)),
GET_U_1(eigrp_com_header->opcode),
GET_BE_U_2(eigrp_com_header->checksum),
bittok2str(eigrp_common_header_flag_values,
"none",
GET_BE_U_4(eigrp_com_header->flags)),
GET_BE_U_4(eigrp_com_header->seq),
GET_BE_U_4(eigrp_com_header->ack),
GET_BE_U_2(eigrp_com_header->vrid),
GET_BE_U_2(eigrp_com_header->asn),
tlen);
tptr+=sizeof(struct eigrp_common_header);
while(tlen>0) {
/* did we capture enough for fully decoding the object header ? */
ND_TCHECK_LEN(tptr, sizeof(struct eigrp_tlv_header));
eigrp_tlv_header = (const struct eigrp_tlv_header *)tptr;
eigrp_tlv_len=GET_BE_U_2(eigrp_tlv_header->length);
eigrp_tlv_type=GET_BE_U_2(eigrp_tlv_header->type);
if (eigrp_tlv_len < sizeof(struct eigrp_tlv_header) ||
eigrp_tlv_len > tlen) {
print_unknown_data(ndo,tptr+sizeof(struct eigrp_tlv_header),"\n\t ",tlen);
return;
}
ND_PRINT("\n\t %s TLV (0x%04x), length: %u",
tok2str(eigrp_tlv_values,
"Unknown",
eigrp_tlv_type),
eigrp_tlv_type,
eigrp_tlv_len);
if (eigrp_tlv_len < sizeof(struct eigrp_tlv_header)) {
ND_PRINT(" (too short, < %zu)",
sizeof(struct eigrp_tlv_header));
break;
}
tlv_tptr=tptr+sizeof(struct eigrp_tlv_header);
tlv_tlen=eigrp_tlv_len-sizeof(struct eigrp_tlv_header);
/* did we capture enough for fully decoding the object ? */
ND_TCHECK_LEN(tptr, eigrp_tlv_len);
switch(eigrp_tlv_type) {
case EIGRP_TLV_GENERAL_PARM:
tlv_ptr.eigrp_tlv_general_parm = (const struct eigrp_tlv_general_parm_t *)tlv_tptr;
if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_general_parm)) {
ND_PRINT(" (too short, < %zu)",
sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_general_parm));
break;
}
ND_PRINT("\n\t holdtime: %us, k1 %u, k2 %u, k3 %u, k4 %u, k5 %u",
GET_BE_U_2(tlv_ptr.eigrp_tlv_general_parm->holdtime),
GET_U_1(tlv_ptr.eigrp_tlv_general_parm->k1),
GET_U_1(tlv_ptr.eigrp_tlv_general_parm->k2),
GET_U_1(tlv_ptr.eigrp_tlv_general_parm->k3),
GET_U_1(tlv_ptr.eigrp_tlv_general_parm->k4),
GET_U_1(tlv_ptr.eigrp_tlv_general_parm->k5));
break;
case EIGRP_TLV_SW_VERSION:
tlv_ptr.eigrp_tlv_sw_version = (const struct eigrp_tlv_sw_version_t *)tlv_tptr;
if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_sw_version)) {
ND_PRINT(" (too short, < %zu)",
sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_sw_version));
break;
}
ND_PRINT("\n\t IOS version: %u.%u, EIGRP version %u.%u",
GET_U_1(tlv_ptr.eigrp_tlv_sw_version->ios_major),
GET_U_1(tlv_ptr.eigrp_tlv_sw_version->ios_minor),
GET_U_1(tlv_ptr.eigrp_tlv_sw_version->eigrp_major),
GET_U_1(tlv_ptr.eigrp_tlv_sw_version->eigrp_minor));
break;
case EIGRP_TLV_IP_INT:
tlv_ptr.eigrp_tlv_ip_int = (const struct eigrp_tlv_ip_int_t *)tlv_tptr;
if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_ip_int)) {
ND_PRINT(" (too short, < %zu)",
sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_ip_int));
break;
}
bit_length = GET_U_1(tlv_ptr.eigrp_tlv_ip_int->plen);
if (bit_length > 32) {
ND_PRINT("\n\t illegal prefix length %u",bit_length);
break;
}
byte_length = (bit_length + 7) / 8; /* variable length encoding */
memset(prefix, 0, 4);
GET_CPY_BYTES(prefix, tlv_ptr.eigrp_tlv_ip_int->destination, byte_length);
ND_PRINT("\n\t IPv4 prefix: %15s/%u, nexthop: ",
ipaddr_string(ndo, prefix), /* local buffer, not packet data; don't use GET_IPADDR_STRING() */
bit_length);
if (GET_BE_U_4(tlv_ptr.eigrp_tlv_ip_int->nexthop) == 0)
ND_PRINT("self");
else
ND_PRINT("%s",
GET_IPADDR_STRING(tlv_ptr.eigrp_tlv_ip_int->nexthop));
ND_PRINT("\n\t delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u",
(GET_BE_U_4(tlv_ptr.eigrp_tlv_ip_int->delay)/100),
GET_BE_U_4(tlv_ptr.eigrp_tlv_ip_int->bandwidth),
GET_BE_U_3(tlv_ptr.eigrp_tlv_ip_int->mtu),
GET_U_1(tlv_ptr.eigrp_tlv_ip_int->hopcount),
GET_U_1(tlv_ptr.eigrp_tlv_ip_int->reliability),
GET_U_1(tlv_ptr.eigrp_tlv_ip_int->load));
break;
case EIGRP_TLV_IP_EXT:
tlv_ptr.eigrp_tlv_ip_ext = (const struct eigrp_tlv_ip_ext_t *)tlv_tptr;
if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_ip_ext)) {
ND_PRINT(" (too short, < %zu)",
sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_ip_ext));
break;
}
bit_length = GET_U_1(tlv_ptr.eigrp_tlv_ip_ext->plen);
if (bit_length > 32) {
ND_PRINT("\n\t illegal prefix length %u",bit_length);
break;
}
byte_length = (bit_length + 7) / 8; /* variable length encoding */
memset(prefix, 0, 4);
GET_CPY_BYTES(prefix, tlv_ptr.eigrp_tlv_ip_ext->destination, byte_length);
ND_PRINT("\n\t IPv4 prefix: %15s/%u, nexthop: ",
ipaddr_string(ndo, prefix), /* local buffer, not packet data; don't use GET_IPADDR_STRING() */
bit_length);
if (GET_BE_U_4(tlv_ptr.eigrp_tlv_ip_ext->nexthop) == 0)
ND_PRINT("self");
else
ND_PRINT("%s",
GET_IPADDR_STRING(tlv_ptr.eigrp_tlv_ip_ext->nexthop));
ND_PRINT("\n\t origin-router %s, origin-as %u, origin-proto %s, flags [0x%02x], tag 0x%08x, metric %u",
GET_IPADDR_STRING(tlv_ptr.eigrp_tlv_ip_ext->origin_router),
GET_BE_U_4(tlv_ptr.eigrp_tlv_ip_ext->origin_as),
tok2str(eigrp_ext_proto_id_values,"unknown",GET_U_1(tlv_ptr.eigrp_tlv_ip_ext->proto_id)),
GET_U_1(tlv_ptr.eigrp_tlv_ip_ext->flags),
GET_BE_U_4(tlv_ptr.eigrp_tlv_ip_ext->tag),
GET_BE_U_4(tlv_ptr.eigrp_tlv_ip_ext->metric));
ND_PRINT("\n\t delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u",
(GET_BE_U_4(tlv_ptr.eigrp_tlv_ip_ext->delay)/100),
GET_BE_U_4(tlv_ptr.eigrp_tlv_ip_ext->bandwidth),
GET_BE_U_3(tlv_ptr.eigrp_tlv_ip_ext->mtu),
GET_U_1(tlv_ptr.eigrp_tlv_ip_ext->hopcount),
GET_U_1(tlv_ptr.eigrp_tlv_ip_ext->reliability),
GET_U_1(tlv_ptr.eigrp_tlv_ip_ext->load));
break;
case EIGRP_TLV_AT_CABLE_SETUP:
tlv_ptr.eigrp_tlv_at_cable_setup = (const struct eigrp_tlv_at_cable_setup_t *)tlv_tptr;
if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_at_cable_setup)) {
ND_PRINT(" (too short, < %zu)",
sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_at_cable_setup));
break;
}
ND_PRINT("\n\t Cable-range: %u-%u, Router-ID %u",
GET_BE_U_2(tlv_ptr.eigrp_tlv_at_cable_setup->cable_start),
GET_BE_U_2(tlv_ptr.eigrp_tlv_at_cable_setup->cable_end),
GET_BE_U_4(tlv_ptr.eigrp_tlv_at_cable_setup->router_id));
break;
case EIGRP_TLV_AT_INT:
tlv_ptr.eigrp_tlv_at_int = (const struct eigrp_tlv_at_int_t *)tlv_tptr;
if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_at_int)) {
ND_PRINT(" (too short, < %zu)",
sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_at_int));
break;
}
ND_PRINT("\n\t Cable-Range: %u-%u, nexthop: ",
GET_BE_U_2(tlv_ptr.eigrp_tlv_at_int->cable_start),
GET_BE_U_2(tlv_ptr.eigrp_tlv_at_int->cable_end));
if (GET_BE_U_4(tlv_ptr.eigrp_tlv_at_int->nexthop) == 0)
ND_PRINT("self");
else
ND_PRINT("%u.%u",
GET_BE_U_2(&tlv_ptr.eigrp_tlv_at_int->nexthop[0]),
GET_BE_U_2(&tlv_ptr.eigrp_tlv_at_int->nexthop[2]));
ND_PRINT("\n\t delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u",
(GET_BE_U_4(tlv_ptr.eigrp_tlv_at_int->delay)/100),
GET_BE_U_4(tlv_ptr.eigrp_tlv_at_int->bandwidth),
GET_BE_U_3(tlv_ptr.eigrp_tlv_at_int->mtu),
GET_U_1(tlv_ptr.eigrp_tlv_at_int->hopcount),
GET_U_1(tlv_ptr.eigrp_tlv_at_int->reliability),
GET_U_1(tlv_ptr.eigrp_tlv_at_int->load));
break;
case EIGRP_TLV_AT_EXT:
tlv_ptr.eigrp_tlv_at_ext = (const struct eigrp_tlv_at_ext_t *)tlv_tptr;
if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_at_ext)) {
ND_PRINT(" (too short, < %zu)",
sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_at_ext));
break;
}
ND_PRINT("\n\t Cable-Range: %u-%u, nexthop: ",
GET_BE_U_2(tlv_ptr.eigrp_tlv_at_ext->cable_start),
GET_BE_U_2(tlv_ptr.eigrp_tlv_at_ext->cable_end));
if (GET_BE_U_4(tlv_ptr.eigrp_tlv_at_ext->nexthop) == 0)
ND_PRINT("self");
else
ND_PRINT("%u.%u",
GET_BE_U_2(&tlv_ptr.eigrp_tlv_at_ext->nexthop[0]),
GET_BE_U_2(&tlv_ptr.eigrp_tlv_at_ext->nexthop[2]));
ND_PRINT("\n\t origin-router %u, origin-as %u, origin-proto %s, flags [0x%02x], tag 0x%08x, metric %u",
GET_BE_U_4(tlv_ptr.eigrp_tlv_at_ext->origin_router),
GET_BE_U_4(tlv_ptr.eigrp_tlv_at_ext->origin_as),
tok2str(eigrp_ext_proto_id_values,"unknown",GET_U_1(tlv_ptr.eigrp_tlv_at_ext->proto_id)),
GET_U_1(tlv_ptr.eigrp_tlv_at_ext->flags),
GET_BE_U_4(tlv_ptr.eigrp_tlv_at_ext->tag),
GET_BE_U_2(tlv_ptr.eigrp_tlv_at_ext->metric));
ND_PRINT("\n\t delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u",
(GET_BE_U_4(tlv_ptr.eigrp_tlv_at_ext->delay)/100),
GET_BE_U_4(tlv_ptr.eigrp_tlv_at_ext->bandwidth),
GET_BE_U_3(tlv_ptr.eigrp_tlv_at_ext->mtu),
GET_U_1(tlv_ptr.eigrp_tlv_at_ext->hopcount),
GET_U_1(tlv_ptr.eigrp_tlv_at_ext->reliability),
GET_U_1(tlv_ptr.eigrp_tlv_at_ext->load));
break;
/*
* FIXME those are the defined TLVs that lack a decoder
* you are welcome to contribute code ;-)
*/
case EIGRP_TLV_AUTH:
case EIGRP_TLV_SEQ:
case EIGRP_TLV_MCAST_SEQ:
case EIGRP_TLV_IPX_INT:
case EIGRP_TLV_IPX_EXT:
default:
if (ndo->ndo_vflag <= 1)
print_unknown_data(ndo,tlv_tptr,"\n\t ",tlv_tlen);
break;
}
/* do we want to see an additionally hexdump ? */
if (ndo->ndo_vflag > 1)
print_unknown_data(ndo,tptr+sizeof(struct eigrp_tlv_header),"\n\t ",
eigrp_tlv_len-sizeof(struct eigrp_tlv_header));
tptr+=eigrp_tlv_len;
tlen-=eigrp_tlv_len;
}
return;
trunc:
nd_print_trunc(ndo);
}
diff --git a/contrib/tcpdump/print-enc.c b/contrib/tcpdump/print-enc.c
index 928b02c8870e..f439500fe533 100644
--- a/contrib/tcpdump/print-enc.c
+++ b/contrib/tcpdump/print-enc.c
@@ -1,158 +1,156 @@
/* $OpenBSD: print-enc.c,v 1.7 2002/02/19 19:39:40 millert Exp $ */
/*
* Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996
* 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.
*/
/* \summary: OpenBSD IPsec encapsulation BPF layer printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
#include "af.h"
/* From $OpenBSD: if_enc.h,v 1.8 2001/06/25 05:14:00 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr) and
* Niels Provos (provos@physnet.uni-hamburg.de).
*
* This code was written by John Ioannidis for BSD/OS in Athens, Greece,
* in November 1995.
*
* Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
* by Angelos D. Keromytis.
*
* Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
* and Niels Provos.
*
* Copyright (C) 1995, 1996, 1997, 1998 by John Ioannidis, Angelos D. Keromytis
* and Niels Provos.
* Copyright (c) 2001, Angelos D. Keromytis.
*
* Permission to use, copy, and modify this software with or without fee
* is hereby granted, provided that this entire notice is included in
* all copies of any software which is or includes a copy or
* modification of this software.
* You may use this code under the GNU public license if you so wish. Please
* contribute changes back to the authors under this freer than GPL license
* so that we may further the use of strong encryption without limitations to
* all.
*
* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
* MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
* PURPOSE.
*/
#define ENC_HDRLEN 12
/* From $OpenBSD: mbuf.h,v 1.56 2002/01/25 15:50:23 art Exp $ */
#define M_CONF 0x0400 /* packet was encrypted (ESP-transport) */
#define M_AUTH 0x0800 /* packet was authenticated (AH) */
struct enchdr {
nd_uint32_t af;
nd_uint32_t spi;
nd_uint32_t flags;
};
#define ENC_PRINT_TYPE(wh, xf, name) \
if ((wh) & (xf)) { \
ND_PRINT("%s%s", name, (wh) == (xf) ? "): " : ","); \
(wh) &= ~(xf); \
}
/*
* Byte-swap a 32-bit number.
* ("htonl()" or "ntohl()" won't work - we want to byte-swap even on
* big-endian platforms.)
*/
#define SWAPLONG(y) \
((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff))
void
enc_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h, const u_char *p)
{
u_int length = h->len;
u_int af, flags;
const struct enchdr *hdr;
ndo->ndo_protocol = "enc";
ND_TCHECK_LEN(p, ENC_HDRLEN);
ndo->ndo_ll_hdr_len += ENC_HDRLEN;
hdr = (const struct enchdr *)p;
/*
* The address family and flags fields are in the byte order
* of the host that originally captured the traffic.
*
* To determine that, look at the address family. It's 32-bit,
* it is not likely ever to be > 65535 (I doubt there will
* ever be > 65535 address families and, so far, AF_ values have
* not been allocated very sparsely) so it should not have the
* upper 16 bits set, and it is not likely ever to be AF_UNSPEC,
* i.e. it's not likely ever to be 0, so if it's byte-swapped,
* it should have at least one of the upper 16 bits set.
*
* So if any of the upper 16 bits are set, we assume it, and
* the flags field, are byte-swapped.
*
* The SPI field is always in network byte order, i.e. big-
* endian.
*/
UNALIGNED_MEMCPY(&af, &hdr->af, sizeof (af));
UNALIGNED_MEMCPY(&flags, &hdr->flags, sizeof (flags));
if ((af & 0xFFFF0000) != 0) {
af = SWAPLONG(af);
flags = SWAPLONG(flags);
}
if (flags == 0)
ND_PRINT("(unprotected): ");
else
ND_PRINT("(");
ENC_PRINT_TYPE(flags, M_AUTH, "authentic");
ENC_PRINT_TYPE(flags, M_CONF, "confidential");
/* ENC_PRINT_TYPE(flags, M_TUNNEL, "tunnel"); */
ND_PRINT("SPI 0x%08x: ", GET_BE_U_4(hdr->spi));
length -= ENC_HDRLEN;
p += ENC_HDRLEN;
switch (af) {
case BSD_AFNUM_INET:
ip_print(ndo, p, length);
break;
case BSD_AFNUM_INET6_BSD:
case BSD_AFNUM_INET6_FREEBSD:
case BSD_AFNUM_INET6_DARWIN:
ip6_print(ndo, p, length);
break;
}
}
diff --git a/contrib/tcpdump/print-esp.c b/contrib/tcpdump/print-esp.c
index 2cee08893a12..53ee6c8f6afb 100644
--- a/contrib/tcpdump/print-esp.c
+++ b/contrib/tcpdump/print-esp.c
@@ -1,928 +1,931 @@
/* $NetBSD: print-ah.c,v 1.4 1996/05/20 00:41:16 fvdl Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994
* 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.
*/
/* \summary: IPSEC Encapsulating Security Payload (ESP) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <string.h>
#include <stdlib.h>
-/* Any code in this file that depends on HAVE_LIBCRYPTO depends on
- * HAVE_OPENSSL_EVP_H too. Undefining the former when the latter isn't defined
- * is the simplest way of handling the dependency.
- */
#ifdef HAVE_LIBCRYPTO
-#ifdef HAVE_OPENSSL_EVP_H
#include <openssl/evp.h>
-#else
-#undef HAVE_LIBCRYPTO
-#endif
#endif
#include "netdissect.h"
#include "extract.h"
#include "diag-control.h"
#ifdef HAVE_LIBCRYPTO
#include "strtoaddr.h"
#include "ascii_strcasecmp.h"
#endif
#include "ip.h"
#include "ip6.h"
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* RFC1827/2406 Encapsulated Security Payload.
*/
struct newesp {
nd_uint32_t esp_spi; /* ESP */
nd_uint32_t esp_seq; /* Sequence number */
/*variable size*/ /* (IV and) Payload data */
/*variable size*/ /* padding */
/*8bit*/ /* pad size */
/*8bit*/ /* next header */
/*8bit*/ /* next header */
/*variable size, 32bit bound*/ /* Authentication data */
};
#ifdef HAVE_LIBCRYPTO
union inaddr_u {
nd_ipv4 in4;
nd_ipv6 in6;
};
struct sa_list {
struct sa_list *next;
u_int daddr_version;
union inaddr_u daddr;
uint32_t spi; /* if == 0, then IKEv2 */
int initiator;
u_char spii[8]; /* for IKEv2 */
u_char spir[8];
const EVP_CIPHER *evp;
u_int ivlen;
int authlen;
u_char authsecret[256];
int authsecret_len;
u_char secret[256]; /* is that big enough for all secrets? */
int secretlen;
};
#ifndef HAVE_EVP_CIPHER_CTX_NEW
/*
* Allocate an EVP_CIPHER_CTX.
* Used if we have an older version of OpenSSL that doesn't provide
* routines to allocate and free them.
*/
static EVP_CIPHER_CTX *
EVP_CIPHER_CTX_new(void)
{
EVP_CIPHER_CTX *ctx;
ctx = malloc(sizeof(*ctx));
if (ctx == NULL)
return (NULL);
memset(ctx, 0, sizeof(*ctx));
return (ctx);
}
static void
EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx)
{
EVP_CIPHER_CTX_cleanup(ctx);
free(ctx);
}
#endif
#ifdef HAVE_EVP_DECRYPTINIT_EX
/*
* Initialize the cipher by calling EVP_DecryptInit_ex(), because
* calling EVP_DecryptInit() will reset the cipher context, clearing
* the cipher, so calling it twice, with the second call having a
* null cipher, will clear the already-set cipher. EVP_DecryptInit_ex(),
* however, won't reset the cipher context, so you can use it to specify
* the IV in a second call after a first call to EVP_DecryptInit_ex()
* to set the cipher and the key.
*
* XXX - is there some reason why we need to make two calls?
*/
static int
set_cipher_parameters(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
const unsigned char *key,
const unsigned char *iv)
{
return EVP_DecryptInit_ex(ctx, cipher, NULL, key, iv);
}
#else
/*
* Initialize the cipher by calling EVP_DecryptInit(), because we don't
* have EVP_DecryptInit_ex(); we rely on it not trashing the context.
*/
static int
set_cipher_parameters(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
const unsigned char *key,
const unsigned char *iv)
{
return EVP_DecryptInit(ctx, cipher, key, iv);
}
#endif
static u_char *
do_decrypt(netdissect_options *ndo, const char *caller, struct sa_list *sa,
const u_char *iv, const u_char *ct, unsigned int ctlen)
{
EVP_CIPHER_CTX *ctx;
unsigned int block_size;
unsigned int ptlen;
u_char *pt;
int len;
ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL) {
/*
* Failed to initialize the cipher context.
* From a look at the OpenSSL code, this appears to
* mean "couldn't allocate memory for the cipher context";
* note that we're not passing any parameters, so there's
* not much else it can mean.
*/
(*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC,
"%s: can't allocate memory for cipher context", caller);
return NULL;
}
if (set_cipher_parameters(ctx, sa->evp, sa->secret, NULL) < 0) {
EVP_CIPHER_CTX_free(ctx);
(*ndo->ndo_warning)(ndo, "%s: espkey init failed", caller);
return NULL;
}
if (set_cipher_parameters(ctx, NULL, NULL, iv) < 0) {
EVP_CIPHER_CTX_free(ctx);
(*ndo->ndo_warning)(ndo, "%s: IV init failed", caller);
return NULL;
}
/*
* At least as I read RFC 5996 section 3.14 and RFC 4303 section 2.4,
* if the cipher has a block size of which the ciphertext's size must
* be a multiple, the payload must be padded to make that happen, so
* the ciphertext length must be a multiple of the block size. Fail
* if that's not the case.
*/
block_size = (unsigned int)EVP_CIPHER_CTX_block_size(ctx);
if ((ctlen % block_size) != 0) {
EVP_CIPHER_CTX_free(ctx);
(*ndo->ndo_warning)(ndo,
"%s: ciphertext size %u is not a multiple of the cipher block size %u",
caller, ctlen, block_size);
return NULL;
}
/*
* Attempt to allocate a buffer for the decrypted data, because
* we can't decrypt on top of the input buffer.
*/
ptlen = ctlen;
pt = (u_char *)calloc(1, ptlen);
if (pt == NULL) {
EVP_CIPHER_CTX_free(ctx);
(*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC,
"%s: can't allocate memory for decryption buffer", caller);
return NULL;
}
/*
* The size of the ciphertext handed to us is a multiple of the
* cipher block size, so we don't need to worry about padding.
*/
if (!EVP_CIPHER_CTX_set_padding(ctx, 0)) {
free(pt);
EVP_CIPHER_CTX_free(ctx);
(*ndo->ndo_warning)(ndo,
"%s: EVP_CIPHER_CTX_set_padding failed", caller);
return NULL;
}
if (!EVP_DecryptUpdate(ctx, pt, &len, ct, ctlen)) {
free(pt);
EVP_CIPHER_CTX_free(ctx);
(*ndo->ndo_warning)(ndo, "%s: EVP_DecryptUpdate failed",
caller);
return NULL;
}
EVP_CIPHER_CTX_free(ctx);
return pt;
}
/*
* This will allocate a new buffer containing the decrypted data.
* It returns 1 on success and 0 on failure.
*
* It will push the new buffer and the values of ndo->ndo_packetp and
* ndo->ndo_snapend onto the buffer stack, and change ndo->ndo_packetp
* and ndo->ndo_snapend to refer to the new buffer.
*
* Our caller must pop the buffer off the stack when it's finished
* dissecting anything in it and before it does any dissection of
* anything in the old buffer. That will free the new buffer.
*/
DIAG_OFF_DEPRECATION
int esp_decrypt_buffer_by_ikev2_print(netdissect_options *ndo,
int initiator,
const u_char spii[8],
const u_char spir[8],
const u_char *buf, const u_char *end)
{
struct sa_list *sa;
const u_char *iv;
const u_char *ct;
unsigned int ctlen;
u_char *pt;
/* initiator arg is any non-zero value */
if(initiator) initiator=1;
/* see if we can find the SA, and if so, decode it */
for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) {
if (sa->spi == 0
&& initiator == sa->initiator
&& memcmp(spii, sa->spii, 8) == 0
&& memcmp(spir, sa->spir, 8) == 0)
break;
}
if(sa == NULL) return 0;
if(sa->evp == NULL) return 0;
/*
* remove authenticator, and see if we still have something to
* work with
*/
end = end - sa->authlen;
iv = buf;
ct = iv + sa->ivlen;
ctlen = end-ct;
if(end <= ct) return 0;
pt = do_decrypt(ndo, __func__, sa, iv,
ct, ctlen);
if (pt == NULL)
return 0;
/*
* Switch to the output buffer for dissection, and save it
* on the buffer stack so it can be freed; our caller must
* pop it when done.
*/
if (!nd_push_buffer(ndo, pt, pt, ctlen)) {
free(pt);
(*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC,
"%s: can't push buffer on buffer stack", __func__);
}
return 1;
}
DIAG_ON_DEPRECATION
static void esp_print_addsa(netdissect_options *ndo,
const struct sa_list *sa, int sa_def)
{
/* copy the "sa" */
struct sa_list *nsa;
/* malloc() return used in a 'struct sa_list': do not free() */
nsa = (struct sa_list *)malloc(sizeof(struct sa_list));
if (nsa == NULL)
(*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC,
"%s: malloc", __func__);
*nsa = *sa;
if (sa_def)
ndo->ndo_sa_default = nsa;
nsa->next = ndo->ndo_sa_list_head;
ndo->ndo_sa_list_head = nsa;
}
static u_int hexdigit(netdissect_options *ndo, char hex)
{
if (hex >= '0' && hex <= '9')
return (hex - '0');
else if (hex >= 'A' && hex <= 'F')
return (hex - 'A' + 10);
else if (hex >= 'a' && hex <= 'f')
return (hex - 'a' + 10);
else {
(*ndo->ndo_error)(ndo, S_ERR_ND_ESP_SECRET,
"invalid hex digit %c in espsecret\n", hex);
}
}
static u_int hex2byte(netdissect_options *ndo, char *hexstring)
{
u_int byte;
byte = (hexdigit(ndo, hexstring[0]) << 4) + hexdigit(ndo, hexstring[1]);
return byte;
}
/*
* returns size of binary, 0 on failure.
*/
static int
espprint_decode_hex(netdissect_options *ndo,
u_char *binbuf, unsigned int binbuf_len, char *hex)
{
unsigned int len;
int i;
len = strlen(hex) / 2;
if (len > binbuf_len) {
(*ndo->ndo_warning)(ndo, "secret is too big: %u\n", len);
return 0;
}
i = 0;
while (hex[0] != '\0' && hex[1]!='\0') {
binbuf[i] = hex2byte(ndo, hex);
hex += 2;
i++;
}
return i;
}
/*
* decode the form: SPINUM@IP <tab> ALGONAME:0xsecret
*/
DIAG_OFF_DEPRECATION
static int
espprint_decode_encalgo(netdissect_options *ndo,
char *decode, struct sa_list *sa)
{
size_t i;
const EVP_CIPHER *evp;
int authlen = 0;
char *colon, *p;
+ const char *real_decode;
colon = strchr(decode, ':');
if (colon == NULL) {
(*ndo->ndo_warning)(ndo, "failed to decode espsecret: %s\n", decode);
return 0;
}
*colon = '\0';
if (strlen(decode) > strlen("-hmac96") &&
!strcmp(decode + strlen(decode) - strlen("-hmac96"),
"-hmac96")) {
p = strstr(decode, "-hmac96");
*p = '\0';
authlen = 12;
}
if (strlen(decode) > strlen("-cbc") &&
!strcmp(decode + strlen(decode) - strlen("-cbc"), "-cbc")) {
p = strstr(decode, "-cbc");
*p = '\0';
}
- evp = EVP_get_cipherbyname(decode);
+ /*
+ * Not all versions of libcrypto support calls to add aliases
+ * to ciphers - newer versions of libressl don't - so, instead
+ * of making "3des" an alias for "des_ede3_cbc", if attempting
+ * to get the cipher fails and the name is "3des", we try
+ * "des_ede3_cbc".
+ */
+ real_decode = decode;
+ if (strcmp(real_decode, "3des") == 0)
+ real_decode = "des-ede3-cbc";
+ evp = EVP_get_cipherbyname(real_decode);
if (!evp) {
- (*ndo->ndo_warning)(ndo, "failed to find cipher algo %s\n", decode);
+ if (decode != real_decode)
+ (*ndo->ndo_warning)(ndo, "failed to find cipher algo %s (%s)\n", real_decode, decode);
+ else
+ (*ndo->ndo_warning)(ndo, "failed to find cipher algo %s\n", decode);
sa->evp = NULL;
sa->authlen = 0;
sa->ivlen = 0;
return 0;
}
sa->evp = evp;
sa->authlen = authlen;
/* This returns an int, but it should never be negative */
sa->ivlen = EVP_CIPHER_iv_length(evp);
colon++;
if (colon[0] == '0' && colon[1] == 'x') {
/* decode some hex! */
colon += 2;
sa->secretlen = espprint_decode_hex(ndo, sa->secret, sizeof(sa->secret), colon);
if(sa->secretlen == 0) return 0;
} else {
i = strlen(colon);
if (i < sizeof(sa->secret)) {
memcpy(sa->secret, colon, i);
sa->secretlen = i;
} else {
memcpy(sa->secret, colon, sizeof(sa->secret));
sa->secretlen = sizeof(sa->secret);
}
}
return 1;
}
DIAG_ON_DEPRECATION
/*
* for the moment, ignore the auth algorithm, just hard code the authenticator
* length. Need to research how openssl looks up HMAC stuff.
*/
static int
espprint_decode_authalgo(netdissect_options *ndo,
char *decode, struct sa_list *sa)
{
char *colon;
colon = strchr(decode, ':');
if (colon == NULL) {
(*ndo->ndo_warning)(ndo, "failed to decode espsecret: %s\n", decode);
return 0;
}
*colon = '\0';
if(ascii_strcasecmp(decode,"sha1") == 0 ||
ascii_strcasecmp(decode,"md5") == 0) {
sa->authlen = 12;
}
return 1;
}
static void esp_print_decode_ikeline(netdissect_options *ndo, char *line,
const char *file, int lineno)
{
/* it's an IKEv2 secret, store it instead */
struct sa_list sa1;
char *init;
char *icookie, *rcookie;
int ilen, rlen;
char *authkey;
char *enckey;
init = strsep(&line, " \t");
icookie = strsep(&line, " \t");
rcookie = strsep(&line, " \t");
authkey = strsep(&line, " \t");
enckey = strsep(&line, " \t");
/* if any fields are missing */
if(!init || !icookie || !rcookie || !authkey || !enckey) {
(*ndo->ndo_warning)(ndo, "print_esp: failed to find all fields for ikev2 at %s:%u",
file, lineno);
return;
}
ilen = strlen(icookie);
rlen = strlen(rcookie);
if((init[0]!='I' && init[0]!='R')
|| icookie[0]!='0' || icookie[1]!='x'
|| rcookie[0]!='0' || rcookie[1]!='x'
|| ilen!=18
|| rlen!=18) {
(*ndo->ndo_warning)(ndo, "print_esp: line %s:%u improperly formatted.",
file, lineno);
(*ndo->ndo_warning)(ndo, "init=%s icookie=%s(%u) rcookie=%s(%u)",
init, icookie, ilen, rcookie, rlen);
return;
}
sa1.spi = 0;
sa1.initiator = (init[0] == 'I');
if(espprint_decode_hex(ndo, sa1.spii, sizeof(sa1.spii), icookie+2)!=8)
return;
if(espprint_decode_hex(ndo, sa1.spir, sizeof(sa1.spir), rcookie+2)!=8)
return;
if(!espprint_decode_encalgo(ndo, enckey, &sa1)) return;
if(!espprint_decode_authalgo(ndo, authkey, &sa1)) return;
esp_print_addsa(ndo, &sa1, FALSE);
}
/*
*
* special form: file /name
* causes us to go read from this file instead.
*
*/
static void esp_print_decode_onesecret(netdissect_options *ndo, char *line,
const char *file, int lineno)
{
struct sa_list sa1;
int sa_def;
char *spikey;
char *decode;
spikey = strsep(&line, " \t");
sa_def = 0;
memset(&sa1, 0, sizeof(struct sa_list));
/* if there is only one token, then it is an algo:key token */
if (line == NULL) {
decode = spikey;
spikey = NULL;
/* sa1.daddr.version = 0; */
/* memset(&sa1.daddr, 0, sizeof(sa1.daddr)); */
/* sa1.spi = 0; */
sa_def = 1;
} else
decode = line;
if (spikey && ascii_strcasecmp(spikey, "file") == 0) {
/* open file and read it */
FILE *secretfile;
char fileline[1024];
int subfile_lineno=0;
char *nl;
char *filename = line;
secretfile = fopen(filename, FOPEN_READ_TXT);
if (secretfile == NULL) {
(*ndo->ndo_error)(ndo, S_ERR_ND_OPEN_FILE,
"%s: can't open %s: %s\n",
__func__, filename, strerror(errno));
}
while (fgets(fileline, sizeof(fileline)-1, secretfile) != NULL) {
subfile_lineno++;
/* remove newline from the line */
nl = strchr(fileline, '\n');
if (nl)
*nl = '\0';
if (fileline[0] == '#') continue;
if (fileline[0] == '\0') continue;
esp_print_decode_onesecret(ndo, fileline, filename, subfile_lineno);
}
fclose(secretfile);
return;
}
if (spikey && ascii_strcasecmp(spikey, "ikev2") == 0) {
esp_print_decode_ikeline(ndo, line, file, lineno);
return;
}
if (spikey) {
char *spistr, *foo;
uint32_t spino;
spistr = strsep(&spikey, "@");
if (spistr == NULL) {
(*ndo->ndo_warning)(ndo, "print_esp: failed to find the @ token");
return;
}
spino = strtoul(spistr, &foo, 0);
if (spistr == foo || !spikey) {
(*ndo->ndo_warning)(ndo, "print_esp: failed to decode spi# %s\n", foo);
return;
}
sa1.spi = spino;
if (strtoaddr6(spikey, &sa1.daddr.in6) == 1) {
sa1.daddr_version = 6;
} else if (strtoaddr(spikey, &sa1.daddr.in4) == 1) {
sa1.daddr_version = 4;
} else {
(*ndo->ndo_warning)(ndo, "print_esp: can not decode IP# %s\n", spikey);
return;
}
}
if (decode) {
/* skip any blank spaces */
while (*decode == ' ' || *decode == '\t' || *decode == '\r' || *decode == '\n')
decode++;
if(!espprint_decode_encalgo(ndo, decode, &sa1)) {
return;
}
}
esp_print_addsa(ndo, &sa1, sa_def);
}
DIAG_OFF_DEPRECATION
static void esp_init(netdissect_options *ndo _U_)
{
/*
* 0.9.6 doesn't appear to define OPENSSL_API_COMPAT, so
* we check whether it's undefined or it's less than the
* value for 1.1.0.
*/
#if !defined(OPENSSL_API_COMPAT) || OPENSSL_API_COMPAT < 0x10100000L
OpenSSL_add_all_algorithms();
#endif
- EVP_add_cipher_alias(SN_des_ede3_cbc, "3des");
}
DIAG_ON_DEPRECATION
void esp_decodesecret_print(netdissect_options *ndo)
{
char *line;
char *p;
static int initialized = 0;
if (!initialized) {
esp_init(ndo);
initialized = 1;
}
p = ndo->ndo_espsecret;
while (p && p[0] != '\0') {
/* pick out the first line or first thing until a comma */
if ((line = strsep(&p, "\n,")) == NULL) {
line = p;
p = NULL;
}
esp_print_decode_onesecret(ndo, line, "cmdline", 0);
}
ndo->ndo_espsecret = NULL;
}
#endif
#ifdef HAVE_LIBCRYPTO
#define USED_IF_LIBCRYPTO
#else
#define USED_IF_LIBCRYPTO _U_
#endif
#ifdef HAVE_LIBCRYPTO
DIAG_OFF_DEPRECATION
#endif
void
esp_print(netdissect_options *ndo,
const u_char *bp, u_int length,
const u_char *bp2 USED_IF_LIBCRYPTO,
u_int ver USED_IF_LIBCRYPTO,
int fragmented USED_IF_LIBCRYPTO,
u_int ttl_hl USED_IF_LIBCRYPTO)
{
const struct newesp *esp;
const u_char *ep;
#ifdef HAVE_LIBCRYPTO
const struct ip *ip;
struct sa_list *sa = NULL;
const struct ip6_hdr *ip6 = NULL;
const u_char *iv;
u_int ivlen;
u_int payloadlen;
const u_char *ct;
u_char *pt;
u_int padlen;
u_int nh;
#endif
ndo->ndo_protocol = "esp";
esp = (const struct newesp *)bp;
/* 'ep' points to the end of available data. */
ep = ndo->ndo_snapend;
if ((const u_char *)(esp + 1) >= ep) {
nd_print_trunc(ndo);
return;
}
ND_PRINT("ESP(spi=0x%08x", GET_BE_U_4(esp->esp_spi));
ND_PRINT(",seq=0x%x)", GET_BE_U_4(esp->esp_seq));
ND_PRINT(", length %u", length);
#ifdef HAVE_LIBCRYPTO
/* initialize SAs */
if (ndo->ndo_sa_list_head == NULL) {
if (!ndo->ndo_espsecret)
return;
esp_decodesecret_print(ndo);
}
if (ndo->ndo_sa_list_head == NULL)
return;
ip = (const struct ip *)bp2;
switch (ver) {
case 6:
ip6 = (const struct ip6_hdr *)bp2;
/* we do not attempt to decrypt jumbograms */
if (!GET_BE_U_2(ip6->ip6_plen))
return;
/* XXX - check whether it's fragmented? */
/* if we can't get nexthdr, we do not need to decrypt it */
/* see if we can find the SA, and if so, decode it */
for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) {
if (sa->spi == GET_BE_U_4(esp->esp_spi) &&
sa->daddr_version == 6 &&
UNALIGNED_MEMCMP(&sa->daddr.in6, &ip6->ip6_dst,
sizeof(nd_ipv6)) == 0) {
break;
}
}
break;
case 4:
/* nexthdr & padding are in the last fragment */
if (fragmented)
return;
/* see if we can find the SA, and if so, decode it */
for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) {
if (sa->spi == GET_BE_U_4(esp->esp_spi) &&
sa->daddr_version == 4 &&
UNALIGNED_MEMCMP(&sa->daddr.in4, &ip->ip_dst,
sizeof(nd_ipv4)) == 0) {
break;
}
}
break;
default:
return;
}
/* if we didn't find the specific one, then look for
* an unspecified one.
*/
if (sa == NULL)
sa = ndo->ndo_sa_default;
/* if not found fail */
if (sa == NULL)
return;
/* pointer to the IV, if there is one */
iv = (const u_char *)(esp + 1) + 0;
/* length of the IV, if there is one; 0, if there isn't */
ivlen = sa->ivlen;
/*
* Get a pointer to the ciphertext.
*
* p points to the beginning of the payload, i.e. to the
* initialization vector, so if we skip past the initialization
* vector, it points to the beginning of the ciphertext.
*/
ct = iv + ivlen;
/*
* Make sure the authentication data/integrity check value length
* isn't bigger than the total amount of data available after
* the ESP header and initialization vector is removed and,
* if not, slice the authentication data/ICV off.
*/
if (ep - ct < sa->authlen) {
nd_print_trunc(ndo);
return;
}
ep = ep - sa->authlen;
/*
* Calculate the length of the ciphertext. ep points to
* the beginning of the authentication data/integrity check
* value, i.e. right past the end of the ciphertext;
*/
payloadlen = ep - ct;
if (sa->evp == NULL)
return;
/*
* If the next header value is past the end of the available
* data, we won't be able to fetch it once we've decrypted
* the ciphertext, so there's no point in decrypting the data.
*
* Report it as truncation.
*/
if (!ND_TTEST_1(ep - 1)) {
nd_print_trunc(ndo);
return;
}
pt = do_decrypt(ndo, __func__, sa, iv, ct, payloadlen);
if (pt == NULL)
return;
/*
* Switch to the output buffer for dissection, and
* save it on the buffer stack so it can be freed.
*/
if (!nd_push_buffer(ndo, pt, pt, payloadlen)) {
free(pt);
(*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC,
"%s: can't push buffer on buffer stack", __func__);
}
/*
* Sanity check for pad length; if it, plus 2 for the pad
* length and next header fields, is bigger than the ciphertext
* length (which is also the plaintext length), it's too big.
*
* XXX - the check can fail if the packet is corrupt *or* if
* it was not decrypted with the correct key, so that the
* "plaintext" is not what was being sent.
*/
padlen = GET_U_1(pt + payloadlen - 2);
if (padlen + 2 > payloadlen) {
nd_print_trunc(ndo);
return;
}
/* Get the next header */
nh = GET_U_1(pt + payloadlen - 1);
ND_PRINT(": ");
/*
* Don't put padding + padding length(1 byte) + next header(1 byte)
* in the buffer because they are not part of the plaintext to decode.
*/
if (!nd_push_snaplen(ndo, pt, payloadlen - (padlen + 2))) {
(*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC,
"%s: can't push snaplen on buffer stack", __func__);
}
/* Now dissect the plaintext. */
ip_demux_print(ndo, pt, payloadlen - (padlen + 2), ver, fragmented,
ttl_hl, nh, bp2);
/* Pop the buffer, freeing it. */
nd_pop_packet_info(ndo);
/* Pop the nd_push_snaplen */
nd_pop_packet_info(ndo);
#endif
}
#ifdef HAVE_LIBCRYPTO
DIAG_ON_DEPRECATION
#endif
diff --git a/contrib/tcpdump/print-ether.c b/contrib/tcpdump/print-ether.c
index cd623f902568..6768499adf77 100644
--- a/contrib/tcpdump/print-ether.c
+++ b/contrib/tcpdump/print-ether.c
@@ -1,665 +1,663 @@
/*
* 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.
*/
/* \summary: Ethernet printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
#include "addrtoname.h"
#include "ethertype.h"
/*
* Structure of an Ethernet header.
*/
struct ether_header {
nd_mac_addr ether_dhost;
nd_mac_addr ether_shost;
nd_uint16_t ether_length_type;
};
/*
* Length of an Ethernet header; note that some compilers may pad
* "struct ether_header" to a multiple of 4 bytes, for example, so
* "sizeof (struct ether_header)" may not give the right answer.
*/
#define ETHER_HDRLEN 14
const struct tok ethertype_values[] = {
{ ETHERTYPE_IP, "IPv4" },
{ ETHERTYPE_MPLS, "MPLS unicast" },
{ ETHERTYPE_MPLS_MULTI, "MPLS multicast" },
{ ETHERTYPE_IPV6, "IPv6" },
{ ETHERTYPE_8021Q, "802.1Q" },
{ ETHERTYPE_8021Q9100, "802.1Q-9100" },
{ ETHERTYPE_8021QinQ, "802.1Q-QinQ" },
{ ETHERTYPE_8021Q9200, "802.1Q-9200" },
{ ETHERTYPE_MACSEC, "802.1AE MACsec" },
{ ETHERTYPE_VMAN, "VMAN" },
{ ETHERTYPE_PUP, "PUP" },
{ ETHERTYPE_ARP, "ARP"},
{ ETHERTYPE_REVARP, "Reverse ARP"},
{ ETHERTYPE_NS, "NS" },
{ ETHERTYPE_SPRITE, "Sprite" },
{ ETHERTYPE_TRAIL, "Trail" },
{ ETHERTYPE_MOPDL, "MOP DL" },
{ ETHERTYPE_MOPRC, "MOP RC" },
{ ETHERTYPE_DN, "DN" },
{ ETHERTYPE_LAT, "LAT" },
{ ETHERTYPE_SCA, "SCA" },
{ ETHERTYPE_TEB, "TEB" },
{ ETHERTYPE_LANBRIDGE, "Lanbridge" },
{ ETHERTYPE_DECDNS, "DEC DNS" },
{ ETHERTYPE_DECDTS, "DEC DTS" },
{ ETHERTYPE_VEXP, "VEXP" },
{ ETHERTYPE_VPROD, "VPROD" },
{ ETHERTYPE_ATALK, "Appletalk" },
{ ETHERTYPE_AARP, "Appletalk ARP" },
{ ETHERTYPE_IPX, "IPX" },
{ ETHERTYPE_PPP, "PPP" },
{ ETHERTYPE_MPCP, "MPCP" },
{ ETHERTYPE_SLOW, "Slow Protocols" },
{ ETHERTYPE_PPPOED, "PPPoE D" },
{ ETHERTYPE_PPPOES, "PPPoE S" },
{ ETHERTYPE_EAPOL, "EAPOL" },
{ ETHERTYPE_REALTEK, "Realtek protocols" },
{ ETHERTYPE_MS_NLB_HB, "MS NLB heartbeat" },
{ ETHERTYPE_JUMBO, "Jumbo" },
{ ETHERTYPE_NSH, "NSH" },
{ ETHERTYPE_LOOPBACK, "Loopback" },
{ ETHERTYPE_ISO, "OSI" },
{ ETHERTYPE_GRE_ISO, "GRE-OSI" },
{ ETHERTYPE_CFM_OLD, "CFM (old)" },
{ ETHERTYPE_CFM, "CFM" },
{ ETHERTYPE_IEEE1905_1, "IEEE1905.1" },
{ ETHERTYPE_LLDP, "LLDP" },
{ ETHERTYPE_TIPC, "TIPC"},
{ ETHERTYPE_GEONET_OLD, "GeoNet (old)"},
{ ETHERTYPE_GEONET, "GeoNet"},
{ ETHERTYPE_CALM_FAST, "CALM FAST"},
{ ETHERTYPE_AOE, "AoE" },
{ ETHERTYPE_PTP, "PTP" },
{ ETHERTYPE_ARISTA, "Arista Vendor Specific Protocol" },
{ 0, NULL}
};
static void
ether_addresses_print(netdissect_options *ndo, const u_char *src,
const u_char *dst)
{
ND_PRINT("%s > %s, ",
GET_ETHERADDR_STRING(src), GET_ETHERADDR_STRING(dst));
}
static void
ether_type_print(netdissect_options *ndo, uint16_t type)
{
if (!ndo->ndo_qflag)
ND_PRINT("ethertype %s (0x%04x)",
tok2str(ethertype_values, "Unknown", type), type);
else
ND_PRINT("%s",
tok2str(ethertype_values, "Unknown Ethertype (0x%04x)", type));
}
/*
* Common code for printing Ethernet frames.
*
* It can handle Ethernet headers with extra tag information inserted
* after the destination and source addresses, as is inserted by some
* switch chips, and extra encapsulation header information before
* printing Ethernet header information (such as a LANE ID for ATM LANE).
*/
static u_int
ether_common_print(netdissect_options *ndo, const u_char *p, u_int length,
u_int caplen,
void (*print_switch_tag)(netdissect_options *ndo, const u_char *),
u_int switch_tag_len,
void (*print_encap_header)(netdissect_options *ndo, const u_char *),
const u_char *encap_header_arg)
{
const struct ether_header *ehp;
u_int orig_length;
u_int hdrlen;
u_short length_type;
int printed_length;
int llc_hdrlen;
struct lladdr_info src, dst;
if (length < caplen) {
ND_PRINT("[length %u < caplen %u]", length, caplen);
nd_print_invalid(ndo);
return length;
}
if (caplen < ETHER_HDRLEN + switch_tag_len) {
nd_print_trunc(ndo);
return caplen;
}
if (print_encap_header != NULL)
(*print_encap_header)(ndo, encap_header_arg);
orig_length = length;
/*
* Get the source and destination addresses, skip past them,
* and print them if we're printing the link-layer header.
*/
ehp = (const struct ether_header *)p;
src.addr = ehp->ether_shost;
src.addr_string = etheraddr_string;
dst.addr = ehp->ether_dhost;
dst.addr_string = etheraddr_string;
length -= 2*MAC_ADDR_LEN;
caplen -= 2*MAC_ADDR_LEN;
p += 2*MAC_ADDR_LEN;
hdrlen = 2*MAC_ADDR_LEN;
if (ndo->ndo_eflag)
ether_addresses_print(ndo, src.addr, dst.addr);
/*
* Print the switch tag, if we have one, and skip past it.
*/
if (print_switch_tag != NULL)
(*print_switch_tag)(ndo, p);
length -= switch_tag_len;
caplen -= switch_tag_len;
p += switch_tag_len;
hdrlen += switch_tag_len;
/*
* Get the length/type field, skip past it, and print it
* if we're printing the link-layer header.
*/
recurse:
length_type = GET_BE_U_2(p);
length -= 2;
caplen -= 2;
p += 2;
hdrlen += 2;
/*
* Process 802.1AE MACsec headers.
*/
printed_length = 0;
if (length_type == ETHERTYPE_MACSEC) {
/*
* MACsec, aka IEEE 802.1AE-2006
* Print the header, and try to print the payload if it's not encrypted
*/
if (ndo->ndo_eflag) {
ether_type_print(ndo, length_type);
ND_PRINT(", length %u: ", orig_length);
printed_length = 1;
}
int ret = macsec_print(ndo, &p, &length, &caplen, &hdrlen,
&src, &dst);
if (ret == 0) {
/* Payload is encrypted; print it as raw data. */
if (!ndo->ndo_suppress_default_print)
ND_DEFAULTPRINT(p, caplen);
return hdrlen;
} else if (ret > 0) {
/* Problem printing the header; just quit. */
return ret;
} else {
/*
* Keep processing type/length fields.
*/
length_type = GET_BE_U_2(p);
- ND_LCHECK_U(caplen, 2);
+ ND_ICHECK_U(caplen, <, 2);
length -= 2;
caplen -= 2;
p += 2;
hdrlen += 2;
}
}
/*
* Process VLAN tag types.
*/
while (length_type == ETHERTYPE_8021Q ||
length_type == ETHERTYPE_8021Q9100 ||
length_type == ETHERTYPE_8021Q9200 ||
length_type == ETHERTYPE_8021QinQ) {
/*
* It has a VLAN tag.
* Print VLAN information, and then go back and process
* the enclosed type field.
*/
if (caplen < 4) {
ndo->ndo_protocol = "vlan";
nd_print_trunc(ndo);
return hdrlen + caplen;
}
if (length < 4) {
ndo->ndo_protocol = "vlan";
nd_print_trunc(ndo);
return hdrlen + length;
}
if (ndo->ndo_eflag) {
uint16_t tag = GET_BE_U_2(p);
ether_type_print(ndo, length_type);
if (!printed_length) {
ND_PRINT(", length %u: ", orig_length);
printed_length = 1;
} else
ND_PRINT(", ");
ND_PRINT("%s, ", ieee8021q_tci_string(tag));
}
length_type = GET_BE_U_2(p + 2);
p += 4;
length -= 4;
caplen -= 4;
hdrlen += 4;
}
/*
* We now have the final length/type field.
*/
if (length_type <= MAX_ETHERNET_LENGTH_VAL) {
/*
* It's a length field, containing the length of the
* remaining payload; use it as such, as long as
* it's not too large (bigger than the actual payload).
*/
if (length_type < length) {
length = length_type;
if (caplen > length)
caplen = length;
}
/*
* Cut off the snapshot length to the end of the
* payload.
*/
if (!nd_push_snaplen(ndo, p, length)) {
(*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC,
"%s: can't push snaplen on buffer stack", __func__);
}
if (ndo->ndo_eflag) {
ND_PRINT("802.3");
if (!printed_length)
ND_PRINT(", length %u: ", length);
}
/*
* An LLC header follows the length. Print that and
* higher layers.
*/
llc_hdrlen = llc_print(ndo, p, length, caplen, &src, &dst);
if (llc_hdrlen < 0) {
/* packet type not known, print raw packet */
if (!ndo->ndo_suppress_default_print)
ND_DEFAULTPRINT(p, caplen);
llc_hdrlen = -llc_hdrlen;
}
hdrlen += llc_hdrlen;
nd_pop_packet_info(ndo);
} else if (length_type == ETHERTYPE_JUMBO) {
/*
* It's a type field, with the type for Alteon jumbo frames.
* See
*
* https://tools.ietf.org/html/draft-ietf-isis-ext-eth-01
*
* which indicates that, following the type field,
* there's an LLC header and payload.
*/
/* Try to print the LLC-layer header & higher layers */
llc_hdrlen = llc_print(ndo, p, length, caplen, &src, &dst);
if (llc_hdrlen < 0) {
/* packet type not known, print raw packet */
if (!ndo->ndo_suppress_default_print)
ND_DEFAULTPRINT(p, caplen);
llc_hdrlen = -llc_hdrlen;
}
hdrlen += llc_hdrlen;
} else if (length_type == ETHERTYPE_ARISTA) {
if (caplen < 2) {
ND_PRINT("[|arista]");
return hdrlen + caplen;
}
if (length < 2) {
ND_PRINT("[|arista]");
return hdrlen + length;
}
ether_type_print(ndo, length_type);
ND_PRINT(", length %u: ", orig_length);
int bytesConsumed = arista_ethertype_print(ndo, p, length);
if (bytesConsumed > 0) {
p += bytesConsumed;
length -= bytesConsumed;
caplen -= bytesConsumed;
hdrlen += bytesConsumed;
goto recurse;
} else {
/* subtype/version not known, print raw packet */
if (!ndo->ndo_eflag && length_type > MAX_ETHERNET_LENGTH_VAL) {
ether_addresses_print(ndo, src.addr, dst.addr);
ether_type_print(ndo, length_type);
ND_PRINT(", length %u: ", orig_length);
}
if (!ndo->ndo_suppress_default_print)
ND_DEFAULTPRINT(p, caplen);
}
} else {
/*
* It's a type field with some other value.
*/
if (ndo->ndo_eflag) {
ether_type_print(ndo, length_type);
if (!printed_length)
ND_PRINT(", length %u: ", orig_length);
else
ND_PRINT(", ");
}
if (ethertype_print(ndo, length_type, p, length, caplen, &src, &dst) == 0) {
/* type not known, print raw packet */
if (!ndo->ndo_eflag) {
/*
* We didn't print the full link-layer
* header, as -e wasn't specified, so
* print only the source and destination
* MAC addresses and the final Ethernet
* type.
*/
ether_addresses_print(ndo, src.addr, dst.addr);
ether_type_print(ndo, length_type);
ND_PRINT(", length %u: ", orig_length);
}
if (!ndo->ndo_suppress_default_print)
ND_DEFAULTPRINT(p, caplen);
}
}
invalid:
return hdrlen;
}
/*
- * Print an Ethernet frame while specyfing a non-standard Ethernet header
+ * Print an Ethernet frame while specifying a non-standard Ethernet header
* length.
* This might be encapsulated within another frame; we might be passed
* a pointer to a function that can print header information for that
* frame's protocol, and an argument to pass to that function.
*
* FIXME: caplen can and should be derived from ndo->ndo_snapend and p.
*/
u_int
ether_switch_tag_print(netdissect_options *ndo, const u_char *p, u_int length,
u_int caplen,
void (*print_switch_tag)(netdissect_options *, const u_char *),
u_int switch_tag_len)
{
return ether_common_print(ndo, p, length, caplen, print_switch_tag,
switch_tag_len, NULL, NULL);
}
/*
* Print an Ethernet frame.
* This might be encapsulated within another frame; we might be passed
* a pointer to a function that can print header information for that
* frame's protocol, and an argument to pass to that function.
*
* FIXME: caplen can and should be derived from ndo->ndo_snapend and p.
*/
u_int
ether_print(netdissect_options *ndo,
const u_char *p, u_int length, u_int caplen,
void (*print_encap_header)(netdissect_options *ndo, const u_char *),
const u_char *encap_header_arg)
{
ndo->ndo_protocol = "ether";
return ether_common_print(ndo, p, length, caplen, NULL, 0,
print_encap_header, encap_header_arg);
}
/*
* This is the top level routine of the printer. 'p' points
* to the ether header of the packet, 'h->len' is the length
* of the packet off the wire, and 'h->caplen' is the number
* of bytes actually captured.
*/
void
ether_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h,
const u_char *p)
{
ndo->ndo_protocol = "ether";
ndo->ndo_ll_hdr_len +=
ether_print(ndo, p, h->len, h->caplen, NULL, NULL);
}
/*
* This is the top level routine of the printer. 'p' points
* to the ether header of the packet, 'h->len' is the length
* of the packet off the wire, and 'h->caplen' is the number
* of bytes actually captured.
*
* This is for DLT_NETANALYZER, which has a 4-byte pseudo-header
* before the Ethernet header.
*/
void
netanalyzer_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h,
const u_char *p)
{
/*
* Fail if we don't have enough data for the Hilscher pseudo-header.
*/
ndo->ndo_protocol = "netanalyzer";
ND_TCHECK_LEN(p, 4);
/* Skip the pseudo-header. */
ndo->ndo_ll_hdr_len += 4;
ndo->ndo_ll_hdr_len +=
ether_print(ndo, p + 4, h->len - 4, h->caplen - 4, NULL, NULL);
}
/*
* This is the top level routine of the printer. 'p' points
* to the ether header of the packet, 'h->len' is the length
* of the packet off the wire, and 'h->caplen' is the number
* of bytes actually captured.
*
* This is for DLT_NETANALYZER_TRANSPARENT, which has a 4-byte
* pseudo-header, a 7-byte Ethernet preamble, and a 1-byte Ethernet SOF
* before the Ethernet header.
*/
void
netanalyzer_transparent_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h,
const u_char *p)
{
/*
* Fail if we don't have enough data for the Hilscher pseudo-header,
* preamble, and SOF.
*/
ndo->ndo_protocol = "netanalyzer_transparent";
ND_TCHECK_LEN(p, 12);
/* Skip the pseudo-header, preamble, and SOF. */
ndo->ndo_ll_hdr_len += 12;
ndo->ndo_ll_hdr_len +=
ether_print(ndo, p + 12, h->len - 12, h->caplen - 12, NULL, NULL);
}
/*
* Prints the packet payload, given an Ethernet type code for the payload's
* protocol.
*
* Returns non-zero if it can do so, zero if the ethertype is unknown.
*/
int
ethertype_print(netdissect_options *ndo,
u_short ether_type, const u_char *p,
u_int length, u_int caplen,
const struct lladdr_info *src, const struct lladdr_info *dst)
{
switch (ether_type) {
case ETHERTYPE_IP:
ip_print(ndo, p, length);
return (1);
case ETHERTYPE_IPV6:
ip6_print(ndo, p, length);
return (1);
case ETHERTYPE_ARP:
case ETHERTYPE_REVARP:
arp_print(ndo, p, length, caplen);
return (1);
case ETHERTYPE_DN:
decnet_print(ndo, p, length, caplen);
return (1);
case ETHERTYPE_ATALK:
if (ndo->ndo_vflag)
ND_PRINT("et1 ");
atalk_print(ndo, p, length);
return (1);
case ETHERTYPE_AARP:
aarp_print(ndo, p, length);
return (1);
case ETHERTYPE_IPX:
ND_PRINT("(NOV-ETHII) ");
ipx_print(ndo, p, length);
return (1);
case ETHERTYPE_ISO:
if (length == 0 || caplen == 0) {
ndo->ndo_protocol = "isoclns";
nd_print_trunc(ndo);
return (1);
}
/* At least one byte is required */
/* FIXME: Reference for this byte? */
ND_TCHECK_LEN(p, 1);
isoclns_print(ndo, p + 1, length - 1);
return(1);
case ETHERTYPE_PPPOED:
case ETHERTYPE_PPPOES:
case ETHERTYPE_PPPOED2:
case ETHERTYPE_PPPOES2:
pppoe_print(ndo, p, length);
return (1);
case ETHERTYPE_EAPOL:
eapol_print(ndo, p);
return (1);
case ETHERTYPE_REALTEK:
rtl_print(ndo, p, length, src, dst);
return (1);
case ETHERTYPE_PPP:
if (length) {
ND_PRINT(": ");
ppp_print(ndo, p, length);
}
return (1);
case ETHERTYPE_MPCP:
mpcp_print(ndo, p, length);
return (1);
case ETHERTYPE_SLOW:
slow_print(ndo, p, length);
return (1);
case ETHERTYPE_CFM:
case ETHERTYPE_CFM_OLD:
cfm_print(ndo, p, length);
return (1);
case ETHERTYPE_LLDP:
lldp_print(ndo, p, length);
return (1);
case ETHERTYPE_NSH:
nsh_print(ndo, p, length);
return (1);
case ETHERTYPE_LOOPBACK:
loopback_print(ndo, p, length);
return (1);
case ETHERTYPE_MPLS:
case ETHERTYPE_MPLS_MULTI:
mpls_print(ndo, p, length);
return (1);
case ETHERTYPE_TIPC:
tipc_print(ndo, p, length, caplen);
return (1);
case ETHERTYPE_MS_NLB_HB:
msnlb_print(ndo, p);
return (1);
case ETHERTYPE_GEONET_OLD:
case ETHERTYPE_GEONET:
geonet_print(ndo, p, length, src);
return (1);
case ETHERTYPE_CALM_FAST:
calm_fast_print(ndo, p, length, src);
return (1);
case ETHERTYPE_AOE:
aoe_print(ndo, p, length);
return (1);
case ETHERTYPE_PTP:
ptp_print(ndo, p, length);
return (1);
case ETHERTYPE_LAT:
case ETHERTYPE_SCA:
case ETHERTYPE_MOPRC:
case ETHERTYPE_MOPDL:
case ETHERTYPE_IEEE1905_1:
/* default_print for now */
default:
return (0);
}
}
diff --git a/contrib/tcpdump/print-fddi.c b/contrib/tcpdump/print-fddi.c
index fb8d3ed57ca1..db29841914b8 100644
--- a/contrib/tcpdump/print-fddi.c
+++ b/contrib/tcpdump/print-fddi.c
@@ -1,350 +1,347 @@
/*
* Copyright (c) 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.
*/
/* \summary: Fiber Distributed Data Interface (FDDI) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <string.h>
#include "netdissect.h"
#include "extract.h"
#include "addrtoname.h"
/*
* Based on Ultrix if_fddi.h
*/
struct fddi_header {
nd_uint8_t fddi_fc; /* frame control */
nd_mac_addr fddi_dhost;
nd_mac_addr fddi_shost;
};
/*
* Length of an FDDI header; note that some compilers may pad
* "struct fddi_header" to a multiple of 4 bytes, for example, so
* "sizeof (struct fddi_header)" may not give the right
* answer.
*/
#define FDDI_HDRLEN 13
/* Useful values for fddi_fc (frame control) field */
/*
* FDDI Frame Control bits
*/
#define FDDIFC_C 0x80 /* Class bit */
#define FDDIFC_L 0x40 /* Address length bit */
#define FDDIFC_F 0x30 /* Frame format bits */
#define FDDIFC_Z 0x0f /* Control bits */
/*
* FDDI Frame Control values. (48-bit addressing only).
*/
#define FDDIFC_VOID 0x40 /* Void frame */
#define FDDIFC_NRT 0x80 /* Nonrestricted token */
#define FDDIFC_RT 0xc0 /* Restricted token */
#define FDDIFC_SMT_INFO 0x41 /* SMT Info */
#define FDDIFC_SMT_NSA 0x4F /* SMT Next station adrs */
#define FDDIFC_MAC_BEACON 0xc2 /* MAC Beacon frame */
#define FDDIFC_MAC_CLAIM 0xc3 /* MAC Claim frame */
#define FDDIFC_LLC_ASYNC 0x50 /* Async. LLC frame */
#define FDDIFC_LLC_SYNC 0xd0 /* Sync. LLC frame */
#define FDDIFC_IMP_ASYNC 0x60 /* Implementor Async. */
#define FDDIFC_IMP_SYNC 0xe0 /* Implementor Synch. */
#define FDDIFC_SMT 0x40 /* SMT frame */
#define FDDIFC_MAC 0xc0 /* MAC frame */
#define FDDIFC_CLFF 0xF0 /* Class/Length/Format bits */
#define FDDIFC_ZZZZ 0x0F /* Control bits */
/*
* Some FDDI interfaces use bit-swapped addresses.
*/
#if defined(ultrix) || defined(__alpha) || defined(__bsdi) || defined(__NetBSD__) || defined(__linux__)
static int fddi_bitswap = 0;
#else
static int fddi_bitswap = 1;
#endif
/*
* FDDI support for tcpdump, by Jeffrey Mogul [DECWRL], June 1992
*
* Based in part on code by Van Jacobson, which bears this note:
*
* NOTE: This is a very preliminary hack for FDDI support.
* There are all sorts of wired in constants & nothing (yet)
* to print SMT packets as anything other than hex dumps.
* Most of the necessary changes are waiting on my redoing
* the "header" that a kernel fddi driver supplies to bpf: I
* want it to look like one byte of 'direction' (0 or 1
* depending on whether the packet was inbound or outbound),
* two bytes of system/driver dependent data (anything an
* implementor thinks would be useful to filter on and/or
* save per-packet, then the real 21-byte FDDI header.
* Steve McCanne & I have also talked about adding the
* 'direction' byte to all bpf headers (e.g., in the two
* bytes of padding on an ethernet header). It's not clear
* we could do this in a backwards compatible way & we hate
* the idea of an incompatible bpf change. Discussions are
* proceeding.
*
* Also, to really support FDDI (and better support 802.2
* over ethernet) we really need to re-think the rather simple
* minded assumptions about fixed length & fixed format link
* level headers made in gencode.c. One day...
*
* - vj
*/
static const u_char fddi_bit_swap[] = {
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
};
/*
* Print FDDI frame-control bits
*/
static void
print_fddi_fc(netdissect_options *ndo, u_char fc)
{
switch (fc) {
case FDDIFC_VOID: /* Void frame */
ND_PRINT("void ");
break;
case FDDIFC_NRT: /* Nonrestricted token */
ND_PRINT("nrt ");
break;
case FDDIFC_RT: /* Restricted token */
ND_PRINT("rt ");
break;
case FDDIFC_SMT_INFO: /* SMT Info */
ND_PRINT("info ");
break;
case FDDIFC_SMT_NSA: /* SMT Next station adrs */
ND_PRINT("nsa ");
break;
case FDDIFC_MAC_BEACON: /* MAC Beacon frame */
ND_PRINT("beacon ");
break;
case FDDIFC_MAC_CLAIM: /* MAC Claim frame */
ND_PRINT("claim ");
break;
default:
switch (fc & FDDIFC_CLFF) {
case FDDIFC_MAC:
ND_PRINT("mac%1x ", fc & FDDIFC_ZZZZ);
break;
case FDDIFC_SMT:
ND_PRINT("smt%1x ", fc & FDDIFC_ZZZZ);
break;
case FDDIFC_LLC_ASYNC:
ND_PRINT("async%1x ", fc & FDDIFC_ZZZZ);
break;
case FDDIFC_LLC_SYNC:
ND_PRINT("sync%1x ", fc & FDDIFC_ZZZZ);
break;
case FDDIFC_IMP_ASYNC:
ND_PRINT("imp_async%1x ", fc & FDDIFC_ZZZZ);
break;
case FDDIFC_IMP_SYNC:
ND_PRINT("imp_sync%1x ", fc & FDDIFC_ZZZZ);
break;
default:
ND_PRINT("%02x ", fc);
break;
}
}
}
/* Extract src, dst addresses */
static void
extract_fddi_addrs(const struct fddi_header *fddip, char *fsrc, char *fdst)
{
int i;
if (fddi_bitswap) {
/*
* bit-swap the fddi addresses (isn't the IEEE standards
* process wonderful!) then convert them to names.
*/
for (i = 0; i < 6; ++i)
fdst[i] = fddi_bit_swap[fddip->fddi_dhost[i]];
for (i = 0; i < 6; ++i)
fsrc[i] = fddi_bit_swap[fddip->fddi_shost[i]];
- }
- else {
+ } else {
memcpy(fdst, (const char *)fddip->fddi_dhost, 6);
memcpy(fsrc, (const char *)fddip->fddi_shost, 6);
}
}
/*
* Print the FDDI MAC header
*/
static void
fddi_hdr_print(netdissect_options *ndo,
const struct fddi_header *fddip, u_int length,
const u_char *fsrc, const u_char *fdst)
{
const char *srcname, *dstname;
srcname = etheraddr_string(ndo, fsrc);
dstname = etheraddr_string(ndo, fdst);
if (!ndo->ndo_qflag)
print_fddi_fc(ndo, GET_U_1(fddip->fddi_fc));
ND_PRINT("%s > %s, length %u: ",
srcname, dstname,
length);
}
static void
fddi_smt_print(netdissect_options *ndo, const u_char *p _U_, u_int length _U_)
{
ND_PRINT("<SMT printer not yet implemented>");
}
u_int
fddi_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen)
{
const struct fddi_header *fddip = (const struct fddi_header *)p;
uint8_t fc;
nd_mac_addr srcmac, dstmac;
struct lladdr_info src, dst;
int llc_hdrlen;
ndo->ndo_protocol = "fddi";
if (caplen < FDDI_HDRLEN) {
nd_print_trunc(ndo);
return (caplen);
}
fc = GET_U_1(fddip->fddi_fc);
/*
* Get the FDDI addresses into a canonical form
*/
extract_fddi_addrs(fddip, (char *)srcmac, (char *)dstmac);
if (ndo->ndo_eflag)
fddi_hdr_print(ndo, fddip, length, srcmac, dstmac);
src.addr = srcmac;
src.addr_string = etheraddr_string;
dst.addr = dstmac;
dst.addr_string = etheraddr_string;
/* Skip over FDDI MAC header */
length -= FDDI_HDRLEN;
p += FDDI_HDRLEN;
caplen -= FDDI_HDRLEN;
/* Frame Control field determines interpretation of packet */
if ((fc & FDDIFC_CLFF) == FDDIFC_LLC_ASYNC) {
/* Try to print the LLC-layer header & higher layers */
llc_hdrlen = llc_print(ndo, p, length, caplen, &src, &dst);
if (llc_hdrlen < 0) {
/*
* Some kinds of LLC packet we cannot
* handle intelligently
*/
if (!ndo->ndo_suppress_default_print)
ND_DEFAULTPRINT(p, caplen);
llc_hdrlen = -llc_hdrlen;
}
} else if ((fc & FDDIFC_CLFF) == FDDIFC_SMT) {
fddi_smt_print(ndo, p, caplen);
llc_hdrlen = 0;
} else {
/* Some kinds of FDDI packet we cannot handle intelligently */
if (!ndo->ndo_eflag)
fddi_hdr_print(ndo, fddip, length + FDDI_HDRLEN, srcmac,
dstmac);
if (!ndo->ndo_suppress_default_print)
ND_DEFAULTPRINT(p, caplen);
llc_hdrlen = 0;
}
return (FDDI_HDRLEN + llc_hdrlen);
}
/*
* This is the top level routine of the printer. 'p' points
* to the FDDI header of the packet, 'h->ts' is the timestamp,
* 'h->len' is the length of the packet off the wire, and 'h->caplen'
* is the number of bytes actually captured.
*/
void
fddi_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
{
ndo->ndo_protocol = "fddi";
ndo->ndo_ll_hdr_len += fddi_print(ndo, p, h->len, h->caplen);
}
diff --git a/contrib/tcpdump/print-forces.c b/contrib/tcpdump/print-forces.c
index 1c7beb6a7692..958902503b1e 100644
--- a/contrib/tcpdump/print-forces.c
+++ b/contrib/tcpdump/print-forces.c
@@ -1,1715 +1,1713 @@
/*
* 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.
*
* Copyright (c) 2009 Mojatatu Networks, Inc
*
*/
/* \summary: Forwarding and Control Element Separation (ForCES) Protocol printer */
/* specification: RFC 5810 */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "extract.h"
#define ForCES_VERS 1
#define ForCES_HDRL 24
#define ForCES_ALNL 4U
#define TLV_HDRL 4
#define ILV_HDRL 8
#define TOM_RSVD 0x0
#define TOM_ASSNSETUP 0x1
#define TOM_ASSNTEARD 0x2
#define TOM_CONFIG 0x3
#define TOM_QUERY 0x4
#define TOM_EVENTNOT 0x5
#define TOM_PKTREDIR 0x6
#define TOM_HEARTBT 0x0F
#define TOM_ASSNSETREP 0x11
#define TOM_CONFIGREP 0x13
#define TOM_QUERYREP 0x14
/*
* tom_h Flags: resv1(8b):maxtlvs(4b):resv2(2b):mintlv(2b)
*/
#define ZERO_TTLV 0x01
#define ZERO_MORE_TTLV 0x02
#define ONE_MORE_TTLV 0x04
#define ZERO_TLV 0x00
#define ONE_TLV 0x10
#define TWO_TLV 0x20
#define MAX_TLV 0xF0
#define TTLV_T1 (ONE_MORE_TTLV|ONE_TLV)
#define TTLV_T2 (ONE_MORE_TTLV|MAX_TLV)
struct tom_h {
uint32_t v;
uint16_t flags;
uint16_t op_msk;
const char *s;
int (*print) (netdissect_options *ndo, const u_char * pptr, u_int len,
uint16_t op_msk, int indent);
};
enum {
TOM_RSV_I,
TOM_ASS_I,
TOM_AST_I,
TOM_CFG_I,
TOM_QRY_I,
TOM_EVN_I,
TOM_RED_I,
TOM_HBT_I,
TOM_ASR_I,
TOM_CNR_I,
TOM_QRR_I,
_TOM_RSV_MAX
};
#define TOM_MAX_IND (_TOM_RSV_MAX - 1)
static int
tom_valid(uint8_t tom)
{
if (tom > 0) {
if (tom >= 0x7 && tom <= 0xe)
return 0;
if (tom == 0x10)
return 0;
if (tom > 0x14)
return 0;
return 1;
} else
return 0;
}
static const char *
ForCES_node(uint32_t node)
{
if (node <= 0x3FFFFFFF)
return "FE";
if (node >= 0x40000000 && node <= 0x7FFFFFFF)
return "CE";
if (node >= 0xC0000000 && node <= 0xFFFFFFEF)
return "AllMulticast";
if (node == 0xFFFFFFFD)
return "AllCEsBroadcast";
if (node == 0xFFFFFFFE)
return "AllFEsBroadcast";
if (node == 0xFFFFFFFF)
return "AllBroadcast";
return "ForCESreserved";
}
static const struct tok ForCES_ACKs[] = {
{0x0, "NoACK"},
{0x1, "SuccessACK"},
{0x2, "FailureACK"},
{0x3, "AlwaysACK"},
{0, NULL}
};
static const struct tok ForCES_EMs[] = {
{0x0, "EMReserved"},
{0x1, "execute-all-or-none"},
{0x2, "execute-until-failure"},
{0x3, "continue-execute-on-failure"},
{0, NULL}
};
static const struct tok ForCES_ATs[] = {
{0x0, "Standalone"},
{0x1, "2PCtransaction"},
{0, NULL}
};
static const struct tok ForCES_TPs[] = {
{0x0, "StartofTransaction"},
{0x1, "MiddleofTransaction"},
{0x2, "EndofTransaction"},
{0x3, "abort"},
{0, NULL}
};
/*
* Structure of forces header, naked of TLVs.
*/
struct forcesh {
nd_uint8_t fm_vrsvd; /* version and reserved */
#define ForCES_V(forcesh) (GET_U_1((forcesh)->fm_vrsvd) >> 4)
nd_uint8_t fm_tom; /* type of message */
nd_uint16_t fm_len; /* total length * 4 bytes */
#define ForCES_BLN(forcesh) ((uint32_t)(GET_BE_U_2((forcesh)->fm_len) << 2))
nd_uint32_t fm_sid; /* Source ID */
#define ForCES_SID(forcesh) GET_BE_U_4((forcesh)->fm_sid)
nd_uint32_t fm_did; /* Destination ID */
#define ForCES_DID(forcesh) GET_BE_U_4((forcesh)->fm_did)
nd_uint8_t fm_cor[8]; /* correlator */
nd_uint32_t fm_flags; /* flags */
#define ForCES_ACK(forcesh) ((GET_BE_U_4((forcesh)->fm_flags)&0xC0000000) >> 30)
#define ForCES_PRI(forcesh) ((GET_BE_U_4((forcesh)->fm_flags)&0x38000000) >> 27)
#define ForCES_RS1(forcesh) ((GET_BE_U_4((forcesh)->fm_flags)&0x07000000) >> 24)
#define ForCES_EM(forcesh) ((GET_BE_U_4((forcesh)->fm_flags)&0x00C00000) >> 22)
#define ForCES_AT(forcesh) ((GET_BE_U_4((forcesh)->fm_flags)&0x00200000) >> 21)
#define ForCES_TP(forcesh) ((GET_BE_U_4((forcesh)->fm_flags)&0x00180000) >> 19)
#define ForCES_RS2(forcesh) ((GET_BE_U_4((forcesh)->fm_flags)&0x0007FFFF) >> 0)
};
#define ForCES_HLN_VALID(fhl,tlen) ((tlen) >= ForCES_HDRL && \
(fhl) >= ForCES_HDRL && \
(fhl) == (tlen))
#define F_LFB_RSVD 0x0
#define F_LFB_FEO 0x1
#define F_LFB_FEPO 0x2
static const struct tok ForCES_LFBs[] = {
{F_LFB_RSVD, "Invalid TLV"},
{F_LFB_FEO, "FEObj LFB"},
{F_LFB_FEPO, "FEProtoObj LFB"},
{0, NULL}
};
/* this is defined in RFC5810 section A.2 */
/* https://www.iana.org/assignments/forces/forces.xhtml#oper-tlv-types */
enum {
F_OP_RSV = 0,
F_OP_SET = 1,
F_OP_SETPROP = 2,
F_OP_SETRESP = 3,
F_OP_SETPRESP = 4,
F_OP_DEL = 5,
F_OP_DELRESP = 6,
F_OP_GET = 7,
F_OP_GETPROP = 8,
F_OP_GETRESP = 9,
F_OP_GETPRESP = 10,
F_OP_REPORT = 11,
F_OP_COMMIT = 12,
F_OP_RCOMMIT = 13,
F_OP_RTRCOMP = 14,
_F_OP_MAX
};
#define F_OP_MAX (_F_OP_MAX - 1)
enum {
B_OP_SET = 1 << (F_OP_SET - 1),
B_OP_SETPROP = 1 << (F_OP_SETPROP - 1),
B_OP_SETRESP = 1 << (F_OP_SETRESP - 1),
B_OP_SETPRESP = 1 << (F_OP_SETPRESP - 1),
B_OP_DEL = 1 << (F_OP_DEL - 1),
B_OP_DELRESP = 1 << (F_OP_DELRESP - 1),
B_OP_GET = 1 << (F_OP_GET - 1),
B_OP_GETPROP = 1 << (F_OP_GETPROP - 1),
B_OP_GETRESP = 1 << (F_OP_GETRESP - 1),
B_OP_GETPRESP = 1 << (F_OP_GETPRESP - 1),
B_OP_REPORT = 1 << (F_OP_REPORT - 1),
B_OP_COMMIT = 1 << (F_OP_COMMIT - 1),
B_OP_RCOMMIT = 1 << (F_OP_RCOMMIT - 1),
B_OP_RTRCOMP = 1 << (F_OP_RTRCOMP - 1)
};
struct optlv_h {
uint16_t flags;
uint16_t op_msk;
const char *s;
int (*print) (netdissect_options *ndo, const u_char * pptr, u_int len,
uint16_t op_msk, int indent);
};
static int genoptlv_print(netdissect_options *, const u_char * pptr, u_int len,
uint16_t op_msk, int indent);
static int recpdoptlv_print(netdissect_options *, const u_char * pptr, u_int len,
uint16_t op_msk, int indent);
static int invoptlv_print(netdissect_options *, const u_char * pptr, u_int len,
uint16_t op_msk, int indent);
#define OP_MIN_SIZ 8
struct pathdata_h {
nd_uint16_t pflags;
nd_uint16_t pIDcnt;
};
#define B_FULLD 0x1
#define B_SPARD 0x2
#define B_RESTV 0x4
#define B_KEYIN 0x8
#define B_APPND 0x10
#define B_TRNG 0x20
static const struct optlv_h OPTLV_msg[F_OP_MAX + 1] = {
/* F_OP_RSV */ {ZERO_TTLV, 0, "Invalid OPTLV", invoptlv_print},
/* F_OP_SET */ {TTLV_T2, B_FULLD | B_SPARD, " Set", recpdoptlv_print},
/* F_OP_SETPROP */
{TTLV_T2, B_FULLD | B_SPARD, " SetProp", recpdoptlv_print},
/* F_OP_SETRESP */ {TTLV_T2, B_RESTV, " SetResp", recpdoptlv_print},
/* F_OP_SETPRESP */ {TTLV_T2, B_RESTV, " SetPropResp", recpdoptlv_print},
/* F_OP_DEL */ {ZERO_TTLV, 0, " Del", recpdoptlv_print},
/* F_OP_DELRESP */ {TTLV_T2, B_RESTV, " DelResp", recpdoptlv_print},
/* F_OP_GET */ {ZERO_TTLV, 0, " Get", recpdoptlv_print},
/* F_OP_GETPROP */ {ZERO_TTLV, 0, " GetProp", recpdoptlv_print},
/* F_OP_GETRESP */
{TTLV_T2, B_FULLD | B_SPARD | B_RESTV, " GetResp", recpdoptlv_print},
/* F_OP_GETPRESP */
{TTLV_T2, B_FULLD | B_RESTV, " GetPropResp", recpdoptlv_print},
/* F_OP_REPORT */
{TTLV_T2, B_FULLD | B_SPARD, " Report", recpdoptlv_print},
/* F_OP_COMMIT */ {ZERO_TTLV, 0, " Commit", NULL},
/* F_OP_RCOMMIT */ {TTLV_T1, B_RESTV, " RCommit", genoptlv_print},
/* F_OP_RTRCOMP */ {ZERO_TTLV, 0, " RTRCOMP", NULL},
};
static const struct optlv_h *
get_forces_optlv_h(uint16_t opt)
{
if (opt > F_OP_MAX || opt == F_OP_RSV)
return &OPTLV_msg[F_OP_RSV];
return &OPTLV_msg[opt];
}
#define IND_SIZE 256
#define IND_CHR ' '
#define IND_PREF '\n'
#define IND_SUF 0x0
static char ind_buf[IND_SIZE];
static char *
indent_pr(int indent, int nlpref)
{
int i = 0;
char *r = ind_buf;
if (indent > (IND_SIZE - 1))
indent = IND_SIZE - 1;
if (nlpref) {
r[i] = IND_PREF;
i++;
indent--;
}
while (--indent >= 0)
r[i++] = IND_CHR;
r[i] = IND_SUF;
return r;
}
static int
op_valid(uint16_t op, uint16_t mask)
{
if (op == 0)
return 0;
if (op <= F_OP_MAX)
return (1 << (op - 1)) & mask; /* works only for 0x0001 through 0x0010 */
/* I guess we should allow vendor operations? */
if (op >= 0x8000)
return 1;
return 0;
}
#define F_TLV_RSVD 0x0000
#define F_TLV_REDR 0x0001
#define F_TLV_ASRS 0x0010
#define F_TLV_ASRT 0x0011
#define F_TLV_LFBS 0x1000
#define F_TLV_PDAT 0x0110
#define F_TLV_KEYI 0x0111
#define F_TLV_FULD 0x0112
#define F_TLV_SPAD 0x0113
#define F_TLV_REST 0x0114
#define F_TLV_METD 0x0115
#define F_TLV_REDD 0x0116
#define F_TLV_TRNG 0x0117
#define F_TLV_VNST 0x8000
static const struct tok ForCES_TLV[] = {
{F_TLV_RSVD, "Invalid TLV"},
{F_TLV_REDR, "REDIRECT TLV"},
{F_TLV_ASRS, "ASResult TLV"},
{F_TLV_ASRT, "ASTreason TLV"},
{F_TLV_LFBS, "LFBselect TLV"},
{F_TLV_PDAT, "PATH-DATA TLV"},
{F_TLV_KEYI, "KEYINFO TLV"},
{F_TLV_FULD, "FULLDATA TLV"},
{F_TLV_SPAD, "SPARSEDATA TLV"},
{F_TLV_REST, "RESULT TLV"},
{F_TLV_METD, "METADATA TLV"},
{F_TLV_REDD, "REDIRECTDATA TLV"},
{0, NULL}
};
#define TLV_HLN 4
static int
ttlv_valid(uint16_t ttlv)
{
if (ttlv > 0) {
if (ttlv == 1 || ttlv == 0x1000)
return 1;
if (ttlv >= 0x10 && ttlv <= 0x11)
return 1;
if (ttlv >= 0x110 && ttlv <= 0x116)
return 1;
if (ttlv >= 0x8000)
return 0; /* XXX: */
}
return 0;
}
struct forces_ilv {
nd_uint32_t type;
nd_uint32_t length;
};
struct forces_tlv {
nd_uint16_t type;
nd_uint16_t length;
};
#define F_ALN_LEN(len) roundup2(len, ForCES_ALNL)
#define GET_TOP_TLV(fhdr) ((const struct forces_tlv *)((fhdr) + sizeof (struct forcesh)))
#define TLV_SET_LEN(len) (F_ALN_LEN(TLV_HDRL) + (len))
#define TLV_DATA(tlvp) ((const void*)(((const char*)(tlvp)) + TLV_SET_LEN(0)))
#define GO_NXT_TLV(tlv,rlen) ((rlen) -= F_ALN_LEN(GET_BE_U_2((tlv)->length)), \
(const struct forces_tlv*)(((const char*)(tlv)) \
+ F_ALN_LEN(GET_BE_U_2((tlv)->length))))
#define ILV_SET_LEN(len) (F_ALN_LEN(ILV_HDRL) + (len))
#define ILV_DATA(ilvp) ((const void*)(((const char*)(ilvp)) + ILV_SET_LEN(0)))
#define GO_NXT_ILV(ilv,rlen) ((rlen) -= F_ALN_LEN(GET_BE_U_4((ilv)->length)), \
(const struct forces_ilv *)(((const char*)(ilv)) \
+ F_ALN_LEN(GET_BE_U_4((ilv)->length))))
#define INVALID_RLEN 1
#define INVALID_STLN 2
#define INVALID_LTLN 3
#define INVALID_ALEN 4
static const struct tok ForCES_TLV_err[] = {
{INVALID_RLEN, "Invalid total length"},
{INVALID_STLN, "xLV too short"},
{INVALID_LTLN, "xLV too long"},
{INVALID_ALEN, "data padding missing"},
{0, NULL}
};
static u_int
tlv_valid(u_int tlvl, u_int rlen)
{
if (rlen < TLV_HDRL)
return INVALID_RLEN;
if (tlvl < TLV_HDRL)
return INVALID_STLN;
if (tlvl > rlen)
return INVALID_LTLN;
if (rlen < F_ALN_LEN(tlvl))
return INVALID_ALEN;
return 0;
}
static int
ilv_valid(netdissect_options *ndo, const struct forces_ilv *ilv, u_int rlen)
{
if (rlen < ILV_HDRL)
return INVALID_RLEN;
if (GET_BE_U_4(ilv->length) < ILV_HDRL)
return INVALID_STLN;
if (GET_BE_U_4(ilv->length) > rlen)
return INVALID_LTLN;
if (rlen < F_ALN_LEN(GET_BE_U_4(ilv->length)))
return INVALID_ALEN;
return 0;
}
static int lfbselect_print(netdissect_options *, const u_char * pptr, u_int len,
uint16_t op_msk, int indent);
static int redirect_print(netdissect_options *, const u_char * pptr, u_int len,
uint16_t op_msk, int indent);
static int asrtlv_print(netdissect_options *, const u_char * pptr, u_int len,
uint16_t op_msk, int indent);
static int asttlv_print(netdissect_options *, const u_char * pptr, u_int len,
uint16_t op_msk, int indent);
struct forces_lfbsh {
nd_uint32_t class;
nd_uint32_t instance;
};
#define ASSNS_OPS (B_OP_REPORT)
#define CFG_OPS (B_OP_SET|B_OP_SETPROP|B_OP_DEL|B_OP_COMMIT|B_OP_RTRCOMP)
#define CFG_ROPS (B_OP_SETRESP|B_OP_SETPRESP|B_OP_DELRESP|B_OP_RCOMMIT)
#define CFG_QY (B_OP_GET|B_OP_GETPROP)
#define CFG_QYR (B_OP_GETRESP|B_OP_GETPRESP)
#define CFG_EVN (B_OP_REPORT)
static const struct tom_h ForCES_msg[TOM_MAX_IND + 1] = {
/* TOM_RSV_I */ {TOM_RSVD, ZERO_TTLV, 0, "Invalid message", NULL},
/* TOM_ASS_I */ {TOM_ASSNSETUP, ZERO_MORE_TTLV | TWO_TLV, ASSNS_OPS,
"Association Setup", lfbselect_print},
/* TOM_AST_I */
{TOM_ASSNTEARD, TTLV_T1, 0, "Association TearDown", asttlv_print},
/* TOM_CFG_I */ {TOM_CONFIG, TTLV_T2, CFG_OPS, "Config", lfbselect_print},
/* TOM_QRY_I */ {TOM_QUERY, TTLV_T2, CFG_QY, "Query", lfbselect_print},
/* TOM_EVN_I */ {TOM_EVENTNOT, TTLV_T1, CFG_EVN, "Event Notification",
lfbselect_print},
/* TOM_RED_I */
{TOM_PKTREDIR, TTLV_T2, 0, "Packet Redirect", redirect_print},
/* TOM_HBT_I */ {TOM_HEARTBT, ZERO_TTLV, 0, "HeartBeat", NULL},
/* TOM_ASR_I */
{TOM_ASSNSETREP, TTLV_T1, 0, "Association Response", asrtlv_print},
/* TOM_CNR_I */ {TOM_CONFIGREP, TTLV_T2, CFG_ROPS, "Config Response",
lfbselect_print},
/* TOM_QRR_I */
{TOM_QUERYREP, TTLV_T2, CFG_QYR, "Query Response", lfbselect_print},
};
static const struct tom_h *
get_forces_tom(uint8_t tom)
{
int i;
for (i = TOM_RSV_I; i <= TOM_MAX_IND; i++) {
const struct tom_h *th = &ForCES_msg[i];
if (th->v == tom)
return th;
}
return &ForCES_msg[TOM_RSV_I];
}
struct pdata_ops {
uint32_t v;
uint16_t flags;
uint16_t op_msk;
const char *s;
int (*print) (netdissect_options *, const u_char * pptr, u_int len,
uint16_t op_msk, int indent);
};
enum {
PD_RSV_I,
PD_SEL_I,
PD_FDT_I,
PD_SDT_I,
PD_RES_I,
PD_PDT_I,
_PD_RSV_MAX
};
#define PD_MAX_IND (_TOM_RSV_MAX - 1)
static int
pd_valid(uint16_t pd)
{
if (pd >= F_TLV_PDAT && pd <= F_TLV_REST)
return 1;
return 0;
}
static void
chk_op_type(netdissect_options *ndo,
uint16_t type, uint16_t msk, uint16_t omsk)
{
if (type != F_TLV_PDAT) {
if (msk & B_KEYIN) {
if (type != F_TLV_KEYI) {
ND_PRINT("Based on flags expected KEYINFO TLV!\n");
}
} else {
if (!(msk & omsk)) {
ND_PRINT("Illegal DATA encoding for type 0x%x programmed %x got %x\n",
type, omsk, msk);
}
}
}
}
#define F_SELKEY 1
#define F_SELTABRANGE 2
#define F_TABAPPEND 4
struct res_val {
nd_uint8_t result;
nd_uint8_t resv1;
nd_uint16_t resv2;
};
static int prestlv_print(netdissect_options *, const u_char * pptr, u_int len,
uint16_t op_msk, int indent);
static int pkeyitlv_print(netdissect_options *, const u_char * pptr, u_int len,
uint16_t op_msk, int indent);
static int fdatatlv_print(netdissect_options *, const u_char * pptr, u_int len,
uint16_t op_msk, int indent);
static int sdatatlv_print(netdissect_options *, const u_char * pptr, u_int len,
uint16_t op_msk, int indent);
static const struct pdata_ops ForCES_pdata[PD_MAX_IND + 1] = {
/* PD_RSV_I */ {0, 0, 0, "Invalid message", NULL},
/* PD_SEL_I */ {F_TLV_KEYI, 0, 0, "KEYINFO TLV", pkeyitlv_print},
/* PD_FDT_I */ {F_TLV_FULD, 0, B_FULLD, "FULLDATA TLV", fdatatlv_print},
/* PD_SDT_I */ {F_TLV_SPAD, 0, B_SPARD, "SPARSEDATA TLV", sdatatlv_print},
/* PD_RES_I */ {F_TLV_REST, 0, B_RESTV, "RESULT TLV", prestlv_print},
/* PD_PDT_I */
{F_TLV_PDAT, 0, 0, "Inner PATH-DATA TLV", recpdoptlv_print},
};
static const struct pdata_ops *
get_forces_pd(uint16_t pd)
{
int i;
for (i = PD_RSV_I + 1; i <= PD_MAX_IND; i++) {
const struct pdata_ops *pdo = &ForCES_pdata[i];
if (pdo->v == pd)
return pdo;
}
return &ForCES_pdata[TOM_RSV_I];
}
enum {
E_SUCCESS,
E_INVALID_HEADER,
E_LENGTH_MISMATCH,
E_VERSION_MISMATCH,
E_INVALID_DESTINATION_PID,
E_LFB_UNKNOWN,
E_LFB_NOT_FOUND,
E_LFB_INSTANCE_ID_NOT_FOUND,
E_INVALID_PATH,
E_COMPONENT_DOES_NOT_EXIST,
E_EXISTS,
E_NOT_FOUND,
E_READ_ONLY,
E_INVALID_ARRAY_CREATION,
E_VALUE_OUT_OF_RANGE,
E_CONTENTS_TOO_LONG,
E_INVALID_PARAMETERS,
E_INVALID_MESSAGE_TYPE,
E_INVALID_FLAGS,
E_INVALID_TLV,
E_EVENT_ERROR,
E_NOT_SUPPORTED,
E_MEMORY_ERROR,
E_INTERNAL_ERROR,
/* 0x18-0xFE are reserved .. */
E_UNSPECIFIED_ERROR = 0XFF
};
static const struct tok ForCES_errs[] = {
{E_SUCCESS, "SUCCESS"},
{E_INVALID_HEADER, "INVALID HEADER"},
{E_LENGTH_MISMATCH, "LENGTH MISMATCH"},
{E_VERSION_MISMATCH, "VERSION MISMATCH"},
{E_INVALID_DESTINATION_PID, "INVALID DESTINATION PID"},
{E_LFB_UNKNOWN, "LFB UNKNOWN"},
{E_LFB_NOT_FOUND, "LFB NOT FOUND"},
{E_LFB_INSTANCE_ID_NOT_FOUND, "LFB INSTANCE ID NOT FOUND"},
{E_INVALID_PATH, "INVALID PATH"},
{E_COMPONENT_DOES_NOT_EXIST, "COMPONENT DOES NOT EXIST"},
{E_EXISTS, "EXISTS ALREADY"},
{E_NOT_FOUND, "NOT FOUND"},
{E_READ_ONLY, "READ ONLY"},
{E_INVALID_ARRAY_CREATION, "INVALID ARRAY CREATION"},
{E_VALUE_OUT_OF_RANGE, "VALUE OUT OF RANGE"},
{E_CONTENTS_TOO_LONG, "CONTENTS TOO LONG"},
{E_INVALID_PARAMETERS, "INVALID PARAMETERS"},
{E_INVALID_MESSAGE_TYPE, "INVALID MESSAGE TYPE"},
{E_INVALID_FLAGS, "INVALID FLAGS"},
{E_INVALID_TLV, "INVALID TLV"},
{E_EVENT_ERROR, "EVENT ERROR"},
{E_NOT_SUPPORTED, "NOT SUPPORTED"},
{E_MEMORY_ERROR, "MEMORY ERROR"},
{E_INTERNAL_ERROR, "INTERNAL ERROR"},
{E_UNSPECIFIED_ERROR, "UNSPECIFIED ERROR"},
{0, NULL}
};
#define RESLEN 4
static int
prestlv_print(netdissect_options *ndo,
const u_char * pptr, u_int len,
uint16_t op_msk _U_, int indent)
{
const struct forces_tlv *tlv = (const struct forces_tlv *)pptr;
const u_char *tdp = (const u_char *) TLV_DATA(tlv);
const struct res_val *r = (const struct res_val *)tdp;
u_int dlen;
uint8_t result;
/*
* pdatacnt_print() has ensured that len (the TLV length)
* >= TLV_HDRL.
*/
dlen = len - TLV_HDRL;
if (dlen != RESLEN) {
ND_PRINT("illegal RESULT-TLV: %u bytes!\n", dlen);
return -1;
}
ND_TCHECK_SIZE(r);
result = GET_U_1(r->result);
if (result >= 0x18 && result <= 0xFE) {
ND_PRINT("illegal reserved result code: 0x%x!\n", result);
return -1;
}
if (ndo->ndo_vflag >= 3) {
char *ib = indent_pr(indent, 0);
ND_PRINT("%s Result: %s (code 0x%x)\n", ib,
tok2str(ForCES_errs, NULL, result), result);
}
return 0;
trunc:
nd_print_trunc(ndo);
return -1;
}
static int
fdatatlv_print(netdissect_options *ndo,
const u_char * pptr, u_int len,
uint16_t op_msk _U_, int indent)
{
const struct forces_tlv *tlv = (const struct forces_tlv *)pptr;
u_int rlen;
const u_char *tdp = (const u_char *) TLV_DATA(tlv);
uint16_t type;
/*
* pdatacnt_print() or pkeyitlv_print() has ensured that len
* (the TLV length) >= TLV_HDRL.
*/
rlen = len - TLV_HDRL;
ND_TCHECK_SIZE(tlv);
type = GET_BE_U_2(tlv->type);
if (type != F_TLV_FULD) {
ND_PRINT("Error: expecting FULLDATA!\n");
return -1;
}
if (ndo->ndo_vflag >= 3) {
char *ib = indent_pr(indent + 2, 1);
ND_PRINT("%s[", ib + 1);
hex_print(ndo, ib, tdp, rlen);
ND_PRINT("\n%s]", ib + 1);
}
return 0;
trunc:
nd_print_trunc(ndo);
return -1;
}
static int
sdatailv_print(netdissect_options *ndo,
const u_char * pptr, u_int len,
uint16_t op_msk _U_, int indent)
{
u_int rlen;
const struct forces_ilv *ilv = (const struct forces_ilv *)pptr;
int invilv;
if (len < ILV_HDRL) {
ND_PRINT("Error: BAD SPARSEDATA-TLV!\n");
return -1;
}
rlen = len;
indent += 1;
while (rlen != 0) {
#if 0
ND_PRINT("Jamal - outstanding length <%u>\n", rlen);
#endif
char *ib = indent_pr(indent, 1);
const u_char *tdp = (const u_char *) ILV_DATA(ilv);
invilv = ilv_valid(ndo, ilv, rlen);
if (invilv) {
ND_PRINT("Error: %s, rlen %u\n",
tok2str(ForCES_TLV_err, NULL, invilv), rlen);
return -1;
}
if (ndo->ndo_vflag >= 3) {
u_int ilvl = GET_BE_U_4(ilv->length);
ND_PRINT("\n%s ILV: type %x length %u\n", ib + 1,
GET_BE_U_4(ilv->type), ilvl);
hex_print(ndo, "\t\t[", tdp, ilvl-ILV_HDRL);
}
ilv = GO_NXT_ILV(ilv, rlen);
}
return 0;
}
static int
sdatatlv_print(netdissect_options *ndo,
const u_char * pptr, u_int len,
uint16_t op_msk, int indent)
{
const struct forces_tlv *tlv = (const struct forces_tlv *)pptr;
u_int rlen;
const u_char *tdp = (const u_char *) TLV_DATA(tlv);
uint16_t type;
/*
* pdatacnt_print() has ensured that len (the TLV length)
* >= TLV_HDRL.
*/
rlen = len - TLV_HDRL;
ND_TCHECK_SIZE(tlv);
type = GET_BE_U_2(tlv->type);
if (type != F_TLV_SPAD) {
ND_PRINT("Error: expecting SPARSEDATA!\n");
return -1;
}
return sdatailv_print(ndo, tdp, rlen, op_msk, indent);
trunc:
nd_print_trunc(ndo);
return -1;
}
static int
pkeyitlv_print(netdissect_options *ndo,
const u_char * pptr, u_int len,
uint16_t op_msk, int indent)
{
const struct forces_tlv *tlv = (const struct forces_tlv *)pptr;
const u_char *tdp = (const u_char *) TLV_DATA(tlv);
const u_char *dp = tdp + 4;
const struct forces_tlv *kdtlv = (const struct forces_tlv *)dp;
uint32_t id;
char *ib = indent_pr(indent, 0);
uint16_t type, tll;
u_int invtlv;
id = GET_BE_U_4(tdp);
ND_PRINT("%sKeyinfo: Key 0x%x\n", ib, id);
type = GET_BE_U_2(kdtlv->type);
tll = GET_BE_U_2(kdtlv->length);
invtlv = tlv_valid(tll, len);
if (invtlv) {
ND_PRINT("%s TLV type 0x%x len %u\n",
tok2str(ForCES_TLV_err, NULL, invtlv), type,
tll);
return -1;
}
/*
* At this point, tlv_valid() has ensured that the TLV
* length is large enough but not too large (it doesn't
* go past the end of the containing TLV).
*/
tll = GET_BE_U_2(kdtlv->length);
dp = (const u_char *) TLV_DATA(kdtlv);
return fdatatlv_print(ndo, dp, tll, op_msk, indent);
}
#define PTH_DESC_SIZE 12
static int
pdatacnt_print(netdissect_options *ndo,
const u_char * pptr, u_int len,
uint16_t IDcnt, uint16_t op_msk, int indent)
{
u_int i;
uint32_t id;
char *ib = indent_pr(indent, 0);
if ((op_msk & B_APPND) && ndo->ndo_vflag >= 3) {
ND_PRINT("%sTABLE APPEND\n", ib);
}
for (i = 0; i < IDcnt; i++) {
ND_TCHECK_4(pptr);
if (len < 4)
goto trunc;
id = GET_BE_U_4(pptr);
if (ndo->ndo_vflag >= 3)
ND_PRINT("%sID#%02u: %u\n", ib, i + 1, id);
len -= 4;
pptr += 4;
}
if ((op_msk & B_TRNG) || (op_msk & B_KEYIN)) {
if (op_msk & B_TRNG) {
uint32_t starti, endi;
if (len < PTH_DESC_SIZE) {
ND_PRINT("pathlength %u with key/range too short %u\n",
len, PTH_DESC_SIZE);
return -1;
}
pptr += sizeof(struct forces_tlv);
len -= sizeof(struct forces_tlv);
starti = GET_BE_U_4(pptr);
pptr += 4;
len -= 4;
endi = GET_BE_U_4(pptr);
pptr += 4;
len -= 4;
if (ndo->ndo_vflag >= 3)
ND_PRINT("%sTable range: [%u,%u]\n", ib, starti, endi);
}
if (op_msk & B_KEYIN) {
const struct forces_tlv *keytlv;
uint16_t tll;
if (len < PTH_DESC_SIZE) {
ND_PRINT("pathlength %u with key/range too short %u\n",
len, PTH_DESC_SIZE);
return -1;
}
/* skip keyid */
pptr += 4;
len -= 4;
keytlv = (const struct forces_tlv *)pptr;
/* skip header */
pptr += sizeof(struct forces_tlv);
len -= sizeof(struct forces_tlv);
/* skip key content */
tll = GET_BE_U_2(keytlv->length);
if (tll < TLV_HDRL) {
ND_PRINT("key content length %u < %u\n",
tll, TLV_HDRL);
return -1;
}
tll -= TLV_HDRL;
if (len < tll) {
ND_PRINT("key content too short\n");
return -1;
}
pptr += tll;
len -= tll;
}
}
if (len) {
const struct forces_tlv *pdtlv = (const struct forces_tlv *)pptr;
uint16_t type;
uint16_t tlvl, tll;
u_int pad = 0;
u_int aln;
u_int invtlv;
type = GET_BE_U_2(pdtlv->type);
tlvl = GET_BE_U_2(pdtlv->length);
invtlv = tlv_valid(tlvl, len);
if (invtlv) {
ND_PRINT("%s Outstanding bytes %u for TLV type 0x%x TLV len %u\n",
tok2str(ForCES_TLV_err, NULL, invtlv), len, type,
tlvl);
goto pd_err;
}
/*
* At this point, tlv_valid() has ensured that the TLV
* length is large enough but not too large (it doesn't
* go past the end of the containing TLV).
*/
tll = tlvl - TLV_HDRL;
aln = F_ALN_LEN(tlvl);
if (aln > tlvl) {
if (aln > len) {
ND_PRINT("Invalid padded pathdata TLV type 0x%x len %u missing %u pad bytes\n",
type, tlvl, aln - len);
} else {
pad = aln - tlvl;
}
}
if (pd_valid(type)) {
const struct pdata_ops *ops = get_forces_pd(type);
if (ndo->ndo_vflag >= 3 && ops->v != F_TLV_PDAT) {
if (pad)
ND_PRINT("%s %s (Length %u DataLen %u pad %u Bytes)\n",
ib, ops->s, tlvl, tll, pad);
else
ND_PRINT("%s %s (Length %u DataLen %u Bytes)\n",
ib, ops->s, tlvl, tll);
}
chk_op_type(ndo, type, op_msk, ops->op_msk);
if (ops->print(ndo, (const u_char *)pdtlv,
tll + pad + TLV_HDRL, op_msk,
indent + 2) == -1)
return -1;
len -= (TLV_HDRL + pad + tll);
} else {
ND_PRINT("Invalid path data content type 0x%x len %u\n",
type, tlvl);
pd_err:
if (tlvl) {
hex_print(ndo, "Bad Data val\n\t [",
pptr, len);
ND_PRINT("]\n");
return -1;
}
}
}
return len;
trunc:
nd_print_trunc(ndo);
return -1;
}
static int
pdata_print(netdissect_options *ndo,
const u_char * pptr, u_int len,
uint16_t op_msk, int indent)
{
const struct pathdata_h *pdh = (const struct pathdata_h *)pptr;
char *ib = indent_pr(indent, 0);
u_int minsize = 0;
int more_pd = 0;
uint16_t idcnt = 0;
ND_TCHECK_SIZE(pdh);
if (len < sizeof(struct pathdata_h))
goto trunc;
if (ndo->ndo_vflag >= 3) {
ND_PRINT("\n%sPathdata: Flags 0x%x ID count %u\n",
ib, GET_BE_U_2(pdh->pflags),
GET_BE_U_2(pdh->pIDcnt));
}
if (GET_BE_U_2(pdh->pflags) & F_SELKEY) {
op_msk |= B_KEYIN;
}
/* Table GET Range operation */
if (GET_BE_U_2(pdh->pflags) & F_SELTABRANGE) {
op_msk |= B_TRNG;
}
/* Table SET append operation */
if (GET_BE_U_2(pdh->pflags) & F_TABAPPEND) {
op_msk |= B_APPND;
}
pptr += sizeof(struct pathdata_h);
len -= sizeof(struct pathdata_h);
idcnt = GET_BE_U_2(pdh->pIDcnt);
minsize = idcnt * 4;
if (len < minsize) {
ND_PRINT("\t\t\ttruncated IDs expected %uB got %uB\n", minsize,
len);
hex_print(ndo, "\t\t\tID Data[", pptr, len);
ND_PRINT("]\n");
return -1;
}
if ((op_msk & B_TRNG) && (op_msk & B_KEYIN)) {
ND_PRINT("\t\t\tIllegal to have both Table ranges and keys\n");
return -1;
}
more_pd = pdatacnt_print(ndo, pptr, len, idcnt, op_msk, indent);
if (more_pd > 0) {
int consumed = len - more_pd;
pptr += consumed;
len = more_pd;
/* XXX: Argh, recurse some more */
return recpdoptlv_print(ndo, pptr, len, op_msk, indent+1);
} else
return 0;
trunc:
nd_print_trunc(ndo);
return -1;
}
static int
genoptlv_print(netdissect_options *ndo,
const u_char * pptr, u_int len,
uint16_t op_msk, int indent)
{
const struct forces_tlv *pdtlv = (const struct forces_tlv *)pptr;
uint16_t type;
u_int tlvl;
u_int invtlv;
char *ib = indent_pr(indent, 0);
type = GET_BE_U_2(pdtlv->type);
tlvl = GET_BE_U_2(pdtlv->length);
invtlv = tlv_valid(tlvl, len);
ND_PRINT("genoptlvprint - %s TLV type 0x%x len %u\n",
tok2str(ForCES_TLV, NULL, type), type, tlvl);
if (!invtlv) {
/*
* At this point, tlv_valid() has ensured that the TLV
* length is large enough but not too large (it doesn't
* go past the end of the containing TLV).
*/
const u_char *dp = (const u_char *) TLV_DATA(pdtlv);
if (!ttlv_valid(type)) {
ND_PRINT("%s TLV type 0x%x len %u\n",
tok2str(ForCES_TLV_err, NULL, invtlv), type,
tlvl);
return -1;
}
if (ndo->ndo_vflag >= 3)
ND_PRINT("%s%s, length %u (data length %u Bytes)",
ib, tok2str(ForCES_TLV, NULL, type),
tlvl, tlvl - TLV_HDRL);
return pdata_print(ndo, dp, tlvl - TLV_HDRL, op_msk, indent + 1);
} else {
ND_PRINT("\t\t\tInvalid ForCES TLV type=%x", type);
return -1;
}
}
static int
recpdoptlv_print(netdissect_options *ndo,
const u_char * pptr, u_int len,
uint16_t op_msk, int indent)
{
const struct forces_tlv *pdtlv = (const struct forces_tlv *)pptr;
while (len != 0) {
uint16_t type, tlvl;
u_int invtlv;
char *ib;
const u_char *dp;
tlvl = GET_BE_U_2(pdtlv->length);
invtlv = tlv_valid(tlvl, len);
if (invtlv) {
break;
}
/*
* At this point, tlv_valid() has ensured that the TLV
* length is large enough but not too large (it doesn't
* go past the end of the containing TLV).
*/
ib = indent_pr(indent, 0);
type = GET_BE_U_2(pdtlv->type);
dp = (const u_char *) TLV_DATA(pdtlv);
if (ndo->ndo_vflag >= 3)
ND_PRINT("%s%s, length %u (data encapsulated %u Bytes)",
ib, tok2str(ForCES_TLV, NULL, type),
tlvl,
tlvl - TLV_HDRL);
if (pdata_print(ndo, dp, tlvl - TLV_HDRL, op_msk, indent + 1) == -1)
return -1;
pdtlv = GO_NXT_TLV(pdtlv, len);
}
if (len) {
ND_PRINT("\n\t\tMessy PATHDATA TLV header, type (0x%x)\n\t\texcess of %u Bytes ",
GET_BE_U_2(pdtlv->type),
len - GET_BE_U_2(pdtlv->length));
return -1;
}
return 0;
}
static int
invoptlv_print(netdissect_options *ndo,
const u_char * pptr, u_int len,
uint16_t op_msk _U_, int indent)
{
char *ib = indent_pr(indent, 1);
if (ndo->ndo_vflag >= 3) {
ND_PRINT("%sData[", ib + 1);
hex_print(ndo, ib, pptr, len);
ND_PRINT("%s]\n", ib);
}
return -1;
}
static int
otlv_print(netdissect_options *ndo,
const struct forces_tlv *otlv, uint16_t op_msk _U_, int indent)
{
int rc = 0;
const u_char *dp = (const u_char *) TLV_DATA(otlv);
uint16_t type;
u_int tll;
char *ib = indent_pr(indent, 0);
const struct optlv_h *ops;
/*
* lfbselect_print() has ensured that GET_BE_U_2(otlv->length)
* >= TLV_HDRL.
*/
type = GET_BE_U_2(otlv->type);
tll = GET_BE_U_2(otlv->length) - TLV_HDRL;
ops = get_forces_optlv_h(type);
if (ndo->ndo_vflag >= 3) {
ND_PRINT("%sOper TLV %s(0x%x) length %u\n", ib, ops->s, type,
GET_BE_U_2(otlv->length));
}
/* rest of ops must at least have 12B {pathinfo} */
if (tll < OP_MIN_SIZ) {
ND_PRINT("\t\tOper TLV %s(0x%x) length %u\n", ops->s, type,
GET_BE_U_2(otlv->length));
ND_PRINT("\t\tTruncated data size %u minimum required %u\n", tll,
OP_MIN_SIZ);
return invoptlv_print(ndo, dp, tll, ops->op_msk, indent);
}
/* XXX - do anything with ops->flags? */
if(ops->print) {
rc = ops->print(ndo, dp, tll, ops->op_msk, indent + 1);
}
return rc;
}
#define ASTDLN 4
#define ASTMCD 255
static int
asttlv_print(netdissect_options *ndo,
const u_char * pptr, u_int len,
uint16_t op_msk _U_, int indent)
{
uint32_t rescode;
u_int dlen;
char *ib = indent_pr(indent, 0);
/*
* forces_type_print() has ensured that len (the TLV length)
* >= TLV_HDRL.
*/
dlen = len - TLV_HDRL;
if (dlen != ASTDLN) {
ND_PRINT("illegal ASTresult-TLV: %u bytes!\n", dlen);
return -1;
}
rescode = GET_BE_U_4(pptr);
if (rescode > ASTMCD) {
ND_PRINT("illegal ASTresult result code: %u!\n", rescode);
return -1;
}
if (ndo->ndo_vflag >= 3) {
ND_PRINT("Teardown reason:\n%s", ib);
switch (rescode) {
case 0:
ND_PRINT("Normal Teardown");
break;
case 1:
ND_PRINT("Loss of Heartbeats");
break;
case 2:
ND_PRINT("Out of bandwidth");
break;
case 3:
ND_PRINT("Out of Memory");
break;
case 4:
ND_PRINT("Application Crash");
break;
default:
ND_PRINT("Unknown Teardown reason");
break;
}
ND_PRINT("(%x)\n%s", rescode, ib);
}
return 0;
}
#define ASRDLN 4
#define ASRMCD 3
static int
asrtlv_print(netdissect_options *ndo,
const u_char * pptr, u_int len,
uint16_t op_msk _U_, int indent)
{
uint32_t rescode;
u_int dlen;
char *ib = indent_pr(indent, 0);
/*
* forces_type_print() has ensured that len (the TLV length)
* >= TLV_HDRL.
*/
dlen = len - TLV_HDRL;
if (dlen != ASRDLN) { /* id, instance, oper tlv */
ND_PRINT("illegal ASRresult-TLV: %u bytes!\n", dlen);
return -1;
}
rescode = GET_BE_U_4(pptr);
if (rescode > ASRMCD) {
ND_PRINT("illegal ASRresult result code: %u!\n", rescode);
return -1;
}
if (ndo->ndo_vflag >= 3) {
ND_PRINT("\n%s", ib);
switch (rescode) {
case 0:
ND_PRINT("Success ");
break;
case 1:
ND_PRINT("FE ID invalid ");
break;
case 2:
ND_PRINT("permission denied ");
break;
default:
ND_PRINT("Unknown ");
break;
}
ND_PRINT("(%x)\n%s", rescode, ib);
}
return 0;
}
#if 0
/*
* XXX - not used.
*/
static int
gentltlv_print(netdissect_options *ndo,
const u_char * pptr _U_, u_int len,
uint16_t op_msk _U_, int indent _U_)
{
u_int dlen = len - TLV_HDRL;
if (dlen < 4) { /* at least 32 bits must exist */
ND_PRINT("truncated TLV: %u bytes missing! ", 4 - dlen);
return -1;
}
return 0;
}
#endif
#define RD_MIN 8
static int
print_metailv(netdissect_options *ndo,
const u_char * pptr, uint16_t op_msk _U_, int indent)
{
u_int rlen;
char *ib = indent_pr(indent, 0);
/* XXX: check header length */
const struct forces_ilv *ilv = (const struct forces_ilv *)pptr;
/*
* print_metatlv() has ensured that len (what remains in the
* ILV) >= ILV_HDRL.
*/
rlen = GET_BE_U_4(ilv->length) - ILV_HDRL;
ND_PRINT("%sMetaID 0x%x length %u\n", ib, GET_BE_U_4(ilv->type),
GET_BE_U_4(ilv->length));
if (ndo->ndo_vflag >= 3) {
hex_print(ndo, "\t\t[", ILV_DATA(ilv), rlen);
ND_PRINT(" ]\n");
}
return 0;
}
static int
print_metatlv(netdissect_options *ndo,
const u_char * pptr, u_int len,
uint16_t op_msk _U_, int indent)
{
u_int dlen;
char *ib = indent_pr(indent, 0);
u_int rlen;
const struct forces_ilv *ilv = (const struct forces_ilv *)pptr;
int invilv;
/*
* redirect_print() has ensured that len (what remains in the
* TLV) >= TLV_HDRL.
*/
dlen = len - TLV_HDRL;
rlen = dlen;
ND_PRINT("\n%s METADATA length %u\n", ib, rlen);
while (rlen != 0) {
invilv = ilv_valid(ndo, ilv, rlen);
if (invilv) {
break;
}
/*
* At this point, ilv_valid() has ensured that the ILV
* length is large enough but not too large (it doesn't
* go past the end of the containing TLV).
*/
print_metailv(ndo, (const u_char *) ilv, 0, indent + 1);
ilv = GO_NXT_ILV(ilv, rlen);
}
return 0;
}
static int
print_reddata(netdissect_options *ndo,
const u_char * pptr, u_int len,
uint16_t op_msk _U_, int indent)
{
u_int dlen;
char *ib = indent_pr(indent, 0);
u_int rlen;
dlen = len - TLV_HDRL;
rlen = dlen;
ND_PRINT("\n%s Redirect Data length %u\n", ib, rlen);
if (ndo->ndo_vflag >= 3) {
ND_PRINT("\t\t[");
hex_print(ndo, "\n\t\t", pptr, rlen);
ND_PRINT("\n\t\t]");
}
return 0;
}
static int
redirect_print(netdissect_options *ndo,
const u_char * pptr, u_int len,
uint16_t op_msk _U_, int indent)
{
const struct forces_tlv *tlv = (const struct forces_tlv *)pptr;
u_int dlen;
u_int rlen;
u_int invtlv;
/*
* forces_type_print() has ensured that len (the TLV length)
* >= TLV_HDRL.
*/
dlen = len - TLV_HDRL;
if (dlen <= RD_MIN) {
ND_PRINT("\n\t\ttruncated Redirect TLV: %u bytes missing! ",
RD_MIN - dlen);
return -1;
}
rlen = dlen;
indent += 1;
while (rlen != 0) {
uint16_t type, tlvl;
type = GET_BE_U_2(tlv->type);
tlvl = GET_BE_U_2(tlv->length);
invtlv = tlv_valid(tlvl, rlen);
if (invtlv) {
ND_PRINT("Bad Redirect data\n");
break;
}
/*
* At this point, tlv_valid() has ensured that the TLV
* length is large enough but not too large (it doesn't
* go past the end of the containing TLV).
*/
if (type == F_TLV_METD) {
print_metatlv(ndo, (const u_char *) TLV_DATA(tlv),
tlvl, 0,
indent);
} else if (type == F_TLV_REDD) {
print_reddata(ndo, (const u_char *) TLV_DATA(tlv),
tlvl, 0,
indent);
} else {
ND_PRINT("Unknown REDIRECT TLV 0x%x len %u\n",
type,
tlvl);
}
tlv = GO_NXT_TLV(tlv, rlen);
}
if (rlen) {
ND_PRINT("\n\t\tMessy Redirect TLV header, type (0x%x)\n\t\texcess of %u Bytes ",
GET_BE_U_2(tlv->type),
rlen - GET_BE_U_2(tlv->length));
return -1;
}
return 0;
}
#define OP_OFF 8
#define OP_MIN 12
static int
lfbselect_print(netdissect_options *ndo,
const u_char * pptr, u_int len,
uint16_t op_msk, int indent)
{
const struct forces_lfbsh *lfbs;
const struct forces_tlv *otlv;
char *ib = indent_pr(indent, 0);
u_int dlen;
u_int rlen;
u_int invtlv;
/*
* forces_type_print() has ensured that len (the TLV length)
* >= TLV_HDRL.
*/
dlen = len - TLV_HDRL;
if (dlen <= OP_MIN) { /* id, instance, oper tlv header .. */
ND_PRINT("\n\t\ttruncated lfb selector: %u bytes missing! ",
OP_MIN - dlen);
return -1;
}
/*
* At this point, we know that dlen > OP_MIN; OP_OFF < OP_MIN, so
* we also know that it's > OP_OFF.
*/
rlen = dlen - OP_OFF;
lfbs = (const struct forces_lfbsh *)pptr;
ND_TCHECK_SIZE(lfbs);
if (ndo->ndo_vflag >= 3) {
ND_PRINT("\n%s%s(Classid %x) instance %x\n",
ib,
tok2str(ForCES_LFBs, NULL, GET_BE_U_4(lfbs->class)),
GET_BE_U_4(lfbs->class),
GET_BE_U_4(lfbs->instance));
}
otlv = (const struct forces_tlv *)(lfbs + 1);
indent += 1;
while (rlen != 0) {
uint16_t type, tlvl;
type = GET_BE_U_2(otlv->type);
tlvl = GET_BE_U_2(otlv->length);
invtlv = tlv_valid(tlvl, rlen);
if (invtlv)
break;
/*
* At this point, tlv_valid() has ensured that the TLV
* length is large enough but not too large (it doesn't
* go past the end of the containing TLV).
*/
if (op_valid(type, op_msk)) {
otlv_print(ndo, otlv, 0, indent);
} else {
if (ndo->ndo_vflag < 3)
ND_PRINT("\n");
ND_PRINT("\t\tINValid oper-TLV type 0x%x length %u for this ForCES message\n",
type, tlvl);
invoptlv_print(ndo, (const u_char *)otlv, rlen, 0, indent);
}
otlv = GO_NXT_TLV(otlv, rlen);
}
if (rlen) {
ND_PRINT("\n\t\tMessy oper TLV header, type (0x%x)\n\t\texcess of %u Bytes ",
GET_BE_U_2(otlv->type),
rlen - GET_BE_U_2(otlv->length));
return -1;
}
return 0;
trunc:
nd_print_trunc(ndo);
return -1;
}
static int
forces_type_print(netdissect_options *ndo,
const u_char * pptr, const struct forcesh *fhdr _U_,
u_int mlen, const struct tom_h *tops)
{
const struct forces_tlv *tltlv;
u_int rlen;
u_int invtlv;
int rc = 0;
u_int ttlv = 0;
/*
* forces_print() has already checked that mlen >= ForCES_HDRL
* by calling ForCES_HLN_VALID().
*/
rlen = mlen - ForCES_HDRL;
if (rlen > TLV_HLN) {
if (tops->flags & ZERO_TTLV) {
ND_PRINT("<0x%x>Illegal Top level TLV!\n", tops->flags);
return -1;
}
} else {
if (tops->flags & ZERO_MORE_TTLV)
return 0;
if (tops->flags & ONE_MORE_TTLV) {
ND_PRINT("\tTop level TLV Data missing!\n");
return -1;
}
}
if (tops->flags & ZERO_TTLV) {
return 0;
}
ttlv = tops->flags >> 4;
tltlv = GET_TOP_TLV(pptr);
/*XXX: 15 top level tlvs will probably be fine
You are nuts if you send more ;-> */
while (rlen != 0) {
uint16_t type, tlvl;
type = GET_BE_U_2(tltlv->type);
tlvl = GET_BE_U_2(tltlv->length);
invtlv = tlv_valid(tlvl, rlen);
if (invtlv)
break;
/*
* At this point, tlv_valid() has ensured that the TLV
* length is large enough but not too large (it doesn't
* go past the end of the packet).
*/
if (!ttlv_valid(type)) {
ND_PRINT("\n\tInvalid ForCES Top TLV type=0x%x",
type);
return -1;
}
if (ndo->ndo_vflag >= 3)
ND_PRINT("\t%s, length %u (data length %u Bytes)",
tok2str(ForCES_TLV, NULL, type),
tlvl,
tlvl - TLV_HDRL);
rc = tops->print(ndo, (const u_char *) TLV_DATA(tltlv),
tlvl,
tops->op_msk, 9);
if (rc < 0) {
return -1;
}
tltlv = GO_NXT_TLV(tltlv, rlen);
ttlv--;
if (ttlv <= 0)
break;
}
/*
* XXX - if ttlv != 0, does that mean that the packet was too
* short, and didn't have *enough* TLVs in it?
*/
if (rlen) {
ND_PRINT("\tMess TopTLV header: min %u, total %u advertised %u ",
TLV_HDRL, rlen, GET_BE_U_2(tltlv->length));
return -1;
}
return 0;
}
void
forces_print(netdissect_options *ndo,
const u_char * pptr, u_int len)
{
const struct forcesh *fhdr;
u_int mlen;
uint32_t flg_raw;
uint8_t tom;
const struct tom_h *tops;
int rc = 0;
ndo->ndo_protocol = "forces";
fhdr = (const struct forcesh *)pptr;
ND_TCHECK_SIZE(fhdr);
tom = GET_U_1(fhdr->fm_tom);
if (!tom_valid(tom)) {
ND_PRINT("Invalid ForCES message type %u\n", tom);
goto error;
}
mlen = ForCES_BLN(fhdr);
tops = get_forces_tom(tom);
if (tops->v == TOM_RSVD) {
ND_PRINT("\n\tUnknown ForCES message type=0x%x", tom);
goto error;
}
ND_PRINT("\n\tForCES %s ", tops->s);
if (!ForCES_HLN_VALID(mlen, len)) {
ND_PRINT("Illegal ForCES pkt len - min %u, total recvd %u, advertised %u ",
ForCES_HDRL, len, ForCES_BLN(fhdr));
goto error;
}
flg_raw = GET_BE_U_4(pptr + 20);
if (ndo->ndo_vflag >= 1) {
ND_PRINT("\n\tForCES Version %u len %uB flags 0x%08x ",
ForCES_V(fhdr), mlen, flg_raw);
ND_PRINT("\n\tSrcID 0x%x(%s) DstID 0x%x(%s) Correlator 0x%" PRIx64,
ForCES_SID(fhdr), ForCES_node(ForCES_SID(fhdr)),
ForCES_DID(fhdr), ForCES_node(ForCES_DID(fhdr)),
GET_BE_U_8(fhdr->fm_cor));
}
if (ndo->ndo_vflag >= 2) {
ND_PRINT("\n\tForCES flags:\n\t %s(0x%x), prio=%u, %s(0x%x),\n\t %s(0x%x), %s(0x%x)\n",
tok2str(ForCES_ACKs, "ACKUnknown", ForCES_ACK(fhdr)),
ForCES_ACK(fhdr),
ForCES_PRI(fhdr),
tok2str(ForCES_EMs, "EMUnknown", ForCES_EM(fhdr)),
ForCES_EM(fhdr),
tok2str(ForCES_ATs, "ATUnknown", ForCES_AT(fhdr)),
ForCES_AT(fhdr),
tok2str(ForCES_TPs, "TPUnknown", ForCES_TP(fhdr)),
ForCES_TP(fhdr));
ND_PRINT("\t Extra flags: rsv(b5-7) 0x%x rsv(b13-31) 0x%x\n",
ForCES_RS1(fhdr), ForCES_RS2(fhdr));
}
rc = forces_type_print(ndo, pptr, fhdr, mlen, tops);
if (rc < 0) {
error:
hex_print(ndo, "\n\t[", pptr, len);
ND_PRINT("\n\t]");
return;
}
if (ndo->ndo_vflag >= 4) {
ND_PRINT("\n\t Raw ForCES message\n\t [");
hex_print(ndo, "\n\t ", pptr, len);
ND_PRINT("\n\t ]");
}
return;
trunc:
nd_print_trunc(ndo);
}
diff --git a/contrib/tcpdump/print-fr.c b/contrib/tcpdump/print-fr.c
index f0d7fbeb12b3..79e32ceb07a7 100644
--- a/contrib/tcpdump/print-fr.c
+++ b/contrib/tcpdump/print-fr.c
@@ -1,1157 +1,1161 @@
/*
* Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996
* 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.
*/
/* \summary: Frame Relay printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <stdio.h>
#include <string.h>
#include "netdissect.h"
#include "addrtoname.h"
#include "ethertype.h"
#include "llc.h"
#include "nlpid.h"
#include "extract.h"
static void frf15_print(netdissect_options *ndo, const u_char *, u_int);
/*
* the frame relay header has a variable length
*
* the EA bit determines if there is another byte
* in the header
*
* minimum header length is 2 bytes
* maximum header length is 4 bytes
*
* 7 6 5 4 3 2 1 0
* +----+----+----+----+----+----+----+----+
* | DLCI (6 bits) | CR | EA |
* +----+----+----+----+----+----+----+----+
* | DLCI (4 bits) |FECN|BECN| DE | EA |
* +----+----+----+----+----+----+----+----+
* | DLCI (7 bits) | EA |
* +----+----+----+----+----+----+----+----+
* | DLCI (6 bits) |SDLC| EA |
* +----+----+----+----+----+----+----+----+
*/
#define FR_EA_BIT 0x01
#define FR_CR_BIT 0x02000000
#define FR_DE_BIT 0x00020000
#define FR_BECN_BIT 0x00040000
#define FR_FECN_BIT 0x00080000
#define FR_SDLC_BIT 0x00000002
static const struct tok fr_header_flag_values[] = {
{ FR_CR_BIT, "C!" },
{ FR_DE_BIT, "DE" },
{ FR_BECN_BIT, "BECN" },
{ FR_FECN_BIT, "FECN" },
{ FR_SDLC_BIT, "sdlcore" },
{ 0, NULL }
};
/* FRF.15 / FRF.16 */
#define MFR_B_BIT 0x80
#define MFR_E_BIT 0x40
#define MFR_C_BIT 0x20
#define MFR_BEC_MASK (MFR_B_BIT | MFR_E_BIT | MFR_C_BIT)
#define MFR_CTRL_FRAME (MFR_B_BIT | MFR_E_BIT | MFR_C_BIT)
#define MFR_FRAG_FRAME (MFR_B_BIT | MFR_E_BIT )
static const struct tok frf_flag_values[] = {
{ MFR_B_BIT, "Begin" },
{ MFR_E_BIT, "End" },
{ MFR_C_BIT, "Control" },
{ 0, NULL }
};
/* Finds out Q.922 address length, DLCI and flags. Returns 1 on success,
* 0 on invalid address, -1 on truncated packet
* save the flags dep. on address length
*/
static int parse_q922_header(netdissect_options *ndo,
const u_char *p, u_int *dlci,
u_int *addr_len, uint32_t *flags, u_int length)
{
if (!ND_TTEST_1(p) || length < 1)
return -1;
if ((GET_U_1(p) & FR_EA_BIT))
return 0;
if (!ND_TTEST_1(p + 1) || length < 2)
return -1;
*addr_len = 2;
*dlci = ((GET_U_1(p) & 0xFC) << 2) | ((GET_U_1(p + 1) & 0xF0) >> 4);
*flags = ((GET_U_1(p) & 0x02) << 24) | /* CR flag */
((GET_U_1(p + 1) & 0x0e) << 16); /* FECN,BECN,DE flags */
if (GET_U_1(p + 1) & FR_EA_BIT)
return 1; /* 2-byte Q.922 address */
p += 2;
length -= 2;
if (!ND_TTEST_1(p) || length < 1)
return -1;
(*addr_len)++; /* 3- or 4-byte Q.922 address */
if ((GET_U_1(p) & FR_EA_BIT) == 0) {
*dlci = (*dlci << 7) | (GET_U_1(p) >> 1);
(*addr_len)++; /* 4-byte Q.922 address */
p++;
length--;
}
if (!ND_TTEST_1(p) || length < 1)
return -1;
if ((GET_U_1(p) & FR_EA_BIT) == 0)
return 0; /* more than 4 bytes of Q.922 address? */
*flags = *flags | (GET_U_1(p) & 0x02); /* SDLC flag */
*dlci = (*dlci << 6) | (GET_U_1(p) >> 2);
return 1;
}
const char *
q922_string(netdissect_options *ndo, const u_char *p, u_int length)
{
static u_int dlci, addr_len;
static uint32_t flags;
static char buffer[sizeof("parse_q922_header() returned XXXXXXXXXXX")];
int ret;
memset(buffer, 0, sizeof(buffer));
ret = parse_q922_header(ndo, p, &dlci, &addr_len, &flags, length);
if (ret == 1) {
snprintf(buffer, sizeof(buffer), "DLCI %u", dlci);
return buffer;
} else if (ret == 0) {
return "<Invalid DLCI>";
} else if (ret == -1) {
return "<Truncated>";
} else {
snprintf(buffer, sizeof(buffer), "parse_q922_header() returned %d", ret);
return buffer;
}
}
/* Frame Relay packet structure, with flags and CRC removed
+---------------------------+
| Q.922 Address* |
+-- --+
| |
+---------------------------+
| Control (UI = 0x03) |
+---------------------------+
| Optional Pad (0x00) |
+---------------------------+
| NLPID |
+---------------------------+
| . |
| . |
| . |
| Data |
| . |
| . |
+---------------------------+
* Q.922 addresses, as presently defined, are two octets and
contain a 10-bit DLCI. In some networks Q.922 addresses
may optionally be increased to three or four octets.
*/
static void
fr_hdr_print(netdissect_options *ndo, int length, u_int addr_len,
u_int dlci, uint32_t flags, uint16_t nlpid)
{
if (ndo->ndo_qflag) {
ND_PRINT("Q.922, DLCI %u, length %u: ",
dlci,
length);
} else {
if (nlpid <= 0xff) /* if its smaller than 256 then its a NLPID */
ND_PRINT("Q.922, hdr-len %u, DLCI %u, Flags [%s], NLPID %s (0x%02x), length %u: ",
addr_len,
dlci,
bittok2str(fr_header_flag_values, "none", flags),
tok2str(nlpid_values,"unknown", nlpid),
nlpid,
length);
else /* must be an ethertype */
ND_PRINT("Q.922, hdr-len %u, DLCI %u, Flags [%s], cisco-ethertype %s (0x%04x), length %u: ",
addr_len,
dlci,
bittok2str(fr_header_flag_values, "none", flags),
tok2str(ethertype_values, "unknown", nlpid),
nlpid,
length);
}
}
/* Frame Relay */
void
fr_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h, const u_char *p)
{
u_int length = h->len;
u_int caplen = h->caplen;
ndo->ndo_protocol = "fr";
if (caplen < 4) { /* minimum frame header length */
nd_print_trunc(ndo);
ndo->ndo_ll_hdr_len += caplen;
return;
}
ndo->ndo_ll_hdr_len += fr_print(ndo, p, length);
}
u_int
fr_print(netdissect_options *ndo,
const u_char *p, u_int length)
{
int ret;
uint16_t extracted_ethertype;
u_int dlci;
u_int addr_len;
uint16_t nlpid;
u_int hdr_len;
uint32_t flags;
ndo->ndo_protocol = "fr";
ret = parse_q922_header(ndo, p, &dlci, &addr_len, &flags, length);
if (ret == -1)
goto trunc;
if (ret == 0) {
ND_PRINT("Q.922, invalid address");
return 0;
}
ND_TCHECK_1(p + addr_len);
if (length < addr_len + 1)
goto trunc;
if (GET_U_1(p + addr_len) != LLC_UI && dlci != 0) {
/*
* Let's figure out if we have Cisco-style encapsulation,
* with an Ethernet type (Cisco HDLC type?) following the
* address.
*/
if (!ND_TTEST_2(p + addr_len) || length < addr_len + 2) {
/* no Ethertype */
ND_PRINT("UI %02x! ", GET_U_1(p + addr_len));
} else {
extracted_ethertype = GET_BE_U_2(p + addr_len);
if (ndo->ndo_eflag)
fr_hdr_print(ndo, length, addr_len, dlci,
flags, extracted_ethertype);
if (ethertype_print(ndo, extracted_ethertype,
p+addr_len+ETHERTYPE_LEN,
length-addr_len-ETHERTYPE_LEN,
ND_BYTES_AVAILABLE_AFTER(p)-addr_len-ETHERTYPE_LEN,
NULL, NULL) == 0)
/* ether_type not known, probably it wasn't one */
ND_PRINT("UI %02x! ", GET_U_1(p + addr_len));
else
return addr_len + 2;
}
}
ND_TCHECK_1(p + addr_len + 1);
if (length < addr_len + 2)
goto trunc;
if (GET_U_1(p + addr_len + 1) == 0) {
/*
* Assume a pad byte after the control (UI) byte.
* A pad byte should only be used with 3-byte Q.922.
*/
if (addr_len != 3)
ND_PRINT("Pad! ");
hdr_len = addr_len + 1 /* UI */ + 1 /* pad */ + 1 /* NLPID */;
} else {
/*
* Not a pad byte.
* A pad byte should be used with 3-byte Q.922.
*/
if (addr_len == 3)
ND_PRINT("No pad! ");
hdr_len = addr_len + 1 /* UI */ + 1 /* NLPID */;
}
ND_TCHECK_1(p + hdr_len - 1);
if (length < hdr_len)
goto trunc;
nlpid = GET_U_1(p + hdr_len - 1);
if (ndo->ndo_eflag)
fr_hdr_print(ndo, length, addr_len, dlci, flags, nlpid);
p += hdr_len;
length -= hdr_len;
switch (nlpid) {
case NLPID_IP:
ip_print(ndo, p, length);
break;
case NLPID_IP6:
ip6_print(ndo, p, length);
break;
case NLPID_CLNP:
case NLPID_ESIS:
case NLPID_ISIS:
isoclns_print(ndo, p - 1, length + 1); /* OSI printers need the NLPID field */
break;
case NLPID_SNAP:
if (snap_print(ndo, p, length, ND_BYTES_AVAILABLE_AFTER(p), NULL, NULL, 0) == 0) {
/* ether_type not known, print raw packet */
if (!ndo->ndo_eflag)
fr_hdr_print(ndo, length + hdr_len, hdr_len,
dlci, flags, nlpid);
if (!ndo->ndo_suppress_default_print)
ND_DEFAULTPRINT(p - hdr_len, length + hdr_len);
}
break;
case NLPID_Q933:
q933_print(ndo, p, length);
break;
case NLPID_MFR:
frf15_print(ndo, p, length);
break;
case NLPID_PPP:
ppp_print(ndo, p, length);
break;
default:
if (!ndo->ndo_eflag)
fr_hdr_print(ndo, length + hdr_len, addr_len,
dlci, flags, nlpid);
if (!ndo->ndo_xflag)
ND_DEFAULTPRINT(p, length);
}
return hdr_len;
trunc:
nd_print_trunc(ndo);
return 0;
}
/* Multi Link Frame Relay (FRF.16) */
void
mfr_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h, const u_char *p)
{
u_int length = h->len;
u_int caplen = h->caplen;
ndo->ndo_protocol = "mfr";
if (caplen < 2) { /* minimum frame header length */
nd_print_trunc(ndo);
ndo->ndo_ll_hdr_len += caplen;
return;
}
ndo->ndo_ll_hdr_len += mfr_print(ndo, p, length);
}
#define MFR_CTRL_MSG_ADD_LINK 1
#define MFR_CTRL_MSG_ADD_LINK_ACK 2
#define MFR_CTRL_MSG_ADD_LINK_REJ 3
#define MFR_CTRL_MSG_HELLO 4
#define MFR_CTRL_MSG_HELLO_ACK 5
#define MFR_CTRL_MSG_REMOVE_LINK 6
#define MFR_CTRL_MSG_REMOVE_LINK_ACK 7
static const struct tok mfr_ctrl_msg_values[] = {
{ MFR_CTRL_MSG_ADD_LINK, "Add Link" },
{ MFR_CTRL_MSG_ADD_LINK_ACK, "Add Link ACK" },
{ MFR_CTRL_MSG_ADD_LINK_REJ, "Add Link Reject" },
{ MFR_CTRL_MSG_HELLO, "Hello" },
{ MFR_CTRL_MSG_HELLO_ACK, "Hello ACK" },
{ MFR_CTRL_MSG_REMOVE_LINK, "Remove Link" },
{ MFR_CTRL_MSG_REMOVE_LINK_ACK, "Remove Link ACK" },
{ 0, NULL }
};
#define MFR_CTRL_IE_BUNDLE_ID 1
#define MFR_CTRL_IE_LINK_ID 2
#define MFR_CTRL_IE_MAGIC_NUM 3
#define MFR_CTRL_IE_TIMESTAMP 5
#define MFR_CTRL_IE_VENDOR_EXT 6
#define MFR_CTRL_IE_CAUSE 7
static const struct tok mfr_ctrl_ie_values[] = {
{ MFR_CTRL_IE_BUNDLE_ID, "Bundle ID"},
{ MFR_CTRL_IE_LINK_ID, "Link ID"},
{ MFR_CTRL_IE_MAGIC_NUM, "Magic Number"},
{ MFR_CTRL_IE_TIMESTAMP, "Timestamp"},
{ MFR_CTRL_IE_VENDOR_EXT, "Vendor Extension"},
{ MFR_CTRL_IE_CAUSE, "Cause"},
{ 0, NULL }
};
#define MFR_ID_STRING_MAXLEN 50
struct ie_tlv_header_t {
uint8_t ie_type;
uint8_t ie_len;
};
u_int
mfr_print(netdissect_options *ndo,
const u_char *p, u_int length)
{
u_int tlen,idx,hdr_len = 0;
uint16_t sequence_num;
uint8_t ie_type,ie_len;
const uint8_t *tptr;
/*
* FRF.16 Link Integrity Control Frame
*
* 7 6 5 4 3 2 1 0
* +----+----+----+----+----+----+----+----+
* | B | E | C=1| 0 0 0 0 | EA |
* +----+----+----+----+----+----+----+----+
* | 0 0 0 0 0 0 0 0 |
* +----+----+----+----+----+----+----+----+
* | message type |
* +----+----+----+----+----+----+----+----+
*/
ndo->ndo_protocol = "mfr";
if (length < 4) { /* minimum frame header length */
ND_PRINT("[length %u < 4]", length);
nd_print_invalid(ndo);
return length;
}
ND_TCHECK_4(p);
if ((GET_U_1(p) & MFR_BEC_MASK) == MFR_CTRL_FRAME && GET_U_1(p + 1) == 0) {
ND_PRINT("FRF.16 Control, Flags [%s], %s, length %u",
bittok2str(frf_flag_values,"none",(GET_U_1(p) & MFR_BEC_MASK)),
tok2str(mfr_ctrl_msg_values,"Unknown Message (0x%02x)",GET_U_1(p + 2)),
length);
tptr = p + 3;
tlen = length -3;
hdr_len = 3;
if (!ndo->ndo_vflag)
return hdr_len;
while (tlen>sizeof(struct ie_tlv_header_t)) {
ND_TCHECK_LEN(tptr, sizeof(struct ie_tlv_header_t));
ie_type=GET_U_1(tptr);
ie_len=GET_U_1(tptr + 1);
ND_PRINT("\n\tIE %s (%u), length %u: ",
tok2str(mfr_ctrl_ie_values,"Unknown",ie_type),
ie_type,
ie_len);
/* infinite loop check */
if (ie_type == 0 || ie_len <= sizeof(struct ie_tlv_header_t))
return hdr_len;
ND_TCHECK_LEN(tptr, ie_len);
tptr+=sizeof(struct ie_tlv_header_t);
/* tlv len includes header */
ie_len-=sizeof(struct ie_tlv_header_t);
tlen-=sizeof(struct ie_tlv_header_t);
switch (ie_type) {
case MFR_CTRL_IE_MAGIC_NUM:
/* FRF.16.1 Section 3.4.3 Magic Number Information Element */
if (ie_len != 4) {
ND_PRINT("[IE data length %d != 4]", ie_len);
nd_print_invalid(ndo);
break;
}
ND_PRINT("0x%08x", GET_BE_U_4(tptr));
break;
case MFR_CTRL_IE_BUNDLE_ID: /* same message format */
case MFR_CTRL_IE_LINK_ID:
for (idx = 0; idx < ie_len && idx < MFR_ID_STRING_MAXLEN; idx++) {
if (GET_U_1(tptr + idx) != 0) /* don't print null termination */
fn_print_char(ndo, GET_U_1(tptr + idx));
else
break;
}
break;
case MFR_CTRL_IE_TIMESTAMP:
- if (ie_len == sizeof(struct timeval)) {
- ts_print(ndo, (const struct timeval *)tptr);
+ /*
+ * FRF.16.1 Section 3.4.4 Timestamp Information Element
+ *
+ * The maximum length is 14 octets. Format is implementation
+ * specific.
+ */
+ if (ie_len > 14) {
+ ND_PRINT("[Timestamp IE length %d > 14]", ie_len);
+ nd_print_invalid(ndo);
break;
}
- /* fall through and hexdump if no unix timestamp */
+ /* fall through and hexdump */
ND_FALL_THROUGH;
/*
* FIXME those are the defined IEs that lack a decoder
* you are welcome to contribute code ;-)
*/
case MFR_CTRL_IE_VENDOR_EXT:
case MFR_CTRL_IE_CAUSE:
default:
if (ndo->ndo_vflag <= 1)
print_unknown_data(ndo, tptr, "\n\t ", ie_len);
break;
}
/* do we want to see a hexdump of the IE ? */
if (ndo->ndo_vflag > 1 )
print_unknown_data(ndo, tptr, "\n\t ", ie_len);
tlen-=ie_len;
tptr+=ie_len;
}
return hdr_len;
}
/*
* FRF.16 Fragmentation Frame
*
* 7 6 5 4 3 2 1 0
* +----+----+----+----+----+----+----+----+
* | B | E | C=0|seq. (high 4 bits) | EA |
* +----+----+----+----+----+----+----+----+
* | sequence (low 8 bits) |
* +----+----+----+----+----+----+----+----+
* | DLCI (6 bits) | CR | EA |
* +----+----+----+----+----+----+----+----+
* | DLCI (4 bits) |FECN|BECN| DE | EA |
* +----+----+----+----+----+----+----+----+
*/
sequence_num = (GET_U_1(p)&0x1e)<<7 | GET_U_1(p + 1);
/* whole packet or first fragment ? */
if ((GET_U_1(p) & MFR_BEC_MASK) == MFR_FRAG_FRAME ||
(GET_U_1(p) & MFR_BEC_MASK) == MFR_B_BIT) {
ND_PRINT("FRF.16 Frag, seq %u, Flags [%s], ",
sequence_num,
bittok2str(frf_flag_values,"none",(GET_U_1(p) & MFR_BEC_MASK)));
hdr_len = 2;
fr_print(ndo, p+hdr_len,length-hdr_len);
return hdr_len;
}
/* must be a middle or the last fragment */
ND_PRINT("FRF.16 Frag, seq %u, Flags [%s]",
sequence_num,
bittok2str(frf_flag_values,"none",(GET_U_1(p) & MFR_BEC_MASK)));
print_unknown_data(ndo, p, "\n\t", length);
return hdr_len;
trunc:
nd_print_trunc(ndo);
return length;
}
/* an NLPID of 0xb1 indicates a 2-byte
* FRF.15 header
*
* 7 6 5 4 3 2 1 0
* +----+----+----+----+----+----+----+----+
* ~ Q.922 header ~
* +----+----+----+----+----+----+----+----+
* | NLPID (8 bits) | NLPID=0xb1
* +----+----+----+----+----+----+----+----+
* | B | E | C |seq. (high 4 bits) | R |
* +----+----+----+----+----+----+----+----+
* | sequence (low 8 bits) |
* +----+----+----+----+----+----+----+----+
*/
#define FR_FRF15_FRAGTYPE 0x01
static void
frf15_print(netdissect_options *ndo,
const u_char *p, u_int length)
{
uint16_t sequence_num, flags;
if (length < 2)
goto trunc;
flags = GET_U_1(p)&MFR_BEC_MASK;
sequence_num = (GET_U_1(p)&0x1e)<<7 | GET_U_1(p + 1);
ND_PRINT("FRF.15, seq 0x%03x, Flags [%s],%s Fragmentation, length %u",
sequence_num,
bittok2str(frf_flag_values,"none",flags),
GET_U_1(p)&FR_FRF15_FRAGTYPE ? "Interface" : "End-to-End",
length);
/* TODO:
* depending on all permutations of the B, E and C bit
* dig as deep as we can - e.g. on the first (B) fragment
* there is enough payload to print the IP header
* on non (B) fragments it depends if the fragmentation
* model is end-to-end or interface based whether we want to print
* another Q.922 header
*/
return;
trunc:
nd_print_trunc(ndo);
}
/*
* Q.933 decoding portion for framerelay specific.
*/
/* Q.933 packet format
Format of Other Protocols
using Q.933 NLPID
+-------------------------------+
| Q.922 Address |
+---------------+---------------+
|Control 0x03 | NLPID 0x08 |
+---------------+---------------+
| L2 Protocol ID |
| octet 1 | octet 2 |
+-------------------------------+
| L3 Protocol ID |
| octet 2 | octet 2 |
+-------------------------------+
| Protocol Data |
+-------------------------------+
| FCS |
+-------------------------------+
*/
/* L2 (Octet 1)- Call Reference Usually is 0x0 */
/*
* L2 (Octet 2)- Message Types definition 1 byte long.
*/
/* Call Establish */
#define MSG_TYPE_ESC_TO_NATIONAL 0x00
#define MSG_TYPE_ALERT 0x01
#define MSG_TYPE_CALL_PROCEEDING 0x02
#define MSG_TYPE_CONNECT 0x07
#define MSG_TYPE_CONNECT_ACK 0x0F
#define MSG_TYPE_PROGRESS 0x03
#define MSG_TYPE_SETUP 0x05
/* Call Clear */
#define MSG_TYPE_DISCONNECT 0x45
#define MSG_TYPE_RELEASE 0x4D
#define MSG_TYPE_RELEASE_COMPLETE 0x5A
#define MSG_TYPE_RESTART 0x46
#define MSG_TYPE_RESTART_ACK 0x4E
/* Status */
#define MSG_TYPE_STATUS 0x7D
#define MSG_TYPE_STATUS_ENQ 0x75
static const struct tok fr_q933_msg_values[] = {
{ MSG_TYPE_ESC_TO_NATIONAL, "ESC to National" },
{ MSG_TYPE_ALERT, "Alert" },
{ MSG_TYPE_CALL_PROCEEDING, "Call proceeding" },
{ MSG_TYPE_CONNECT, "Connect" },
{ MSG_TYPE_CONNECT_ACK, "Connect ACK" },
{ MSG_TYPE_PROGRESS, "Progress" },
{ MSG_TYPE_SETUP, "Setup" },
{ MSG_TYPE_DISCONNECT, "Disconnect" },
{ MSG_TYPE_RELEASE, "Release" },
{ MSG_TYPE_RELEASE_COMPLETE, "Release Complete" },
{ MSG_TYPE_RESTART, "Restart" },
{ MSG_TYPE_RESTART_ACK, "Restart ACK" },
{ MSG_TYPE_STATUS, "Status Reply" },
{ MSG_TYPE_STATUS_ENQ, "Status Enquiry" },
{ 0, NULL }
};
#define IE_IS_SINGLE_OCTET(iecode) ((iecode) & 0x80)
#define IE_IS_SHIFT(iecode) (((iecode) & 0xF0) == 0x90)
#define IE_SHIFT_IS_NON_LOCKING(iecode) ((iecode) & 0x08)
#define IE_SHIFT_IS_LOCKING(iecode) (!(IE_SHIFT_IS_NON_LOCKING(iecode)))
#define IE_SHIFT_CODESET(iecode) ((iecode) & 0x07)
#define FR_LMI_ANSI_REPORT_TYPE_IE 0x01
#define FR_LMI_ANSI_LINK_VERIFY_IE_91 0x19 /* details? */
#define FR_LMI_ANSI_LINK_VERIFY_IE 0x03
#define FR_LMI_ANSI_PVC_STATUS_IE 0x07
#define FR_LMI_CCITT_REPORT_TYPE_IE 0x51
#define FR_LMI_CCITT_LINK_VERIFY_IE 0x53
#define FR_LMI_CCITT_PVC_STATUS_IE 0x57
static const struct tok fr_q933_ie_values_codeset_0_5[] = {
{ FR_LMI_ANSI_REPORT_TYPE_IE, "ANSI Report Type" },
{ FR_LMI_ANSI_LINK_VERIFY_IE_91, "ANSI Link Verify" },
{ FR_LMI_ANSI_LINK_VERIFY_IE, "ANSI Link Verify" },
{ FR_LMI_ANSI_PVC_STATUS_IE, "ANSI PVC Status" },
{ FR_LMI_CCITT_REPORT_TYPE_IE, "CCITT Report Type" },
{ FR_LMI_CCITT_LINK_VERIFY_IE, "CCITT Link Verify" },
{ FR_LMI_CCITT_PVC_STATUS_IE, "CCITT PVC Status" },
{ 0, NULL }
};
#define FR_LMI_REPORT_TYPE_IE_FULL_STATUS 0
#define FR_LMI_REPORT_TYPE_IE_LINK_VERIFY 1
#define FR_LMI_REPORT_TYPE_IE_ASYNC_PVC 2
static const struct tok fr_lmi_report_type_ie_values[] = {
{ FR_LMI_REPORT_TYPE_IE_FULL_STATUS, "Full Status" },
{ FR_LMI_REPORT_TYPE_IE_LINK_VERIFY, "Link verify" },
{ FR_LMI_REPORT_TYPE_IE_ASYNC_PVC, "Async PVC Status" },
{ 0, NULL }
};
/* array of 16 codesets - currently we only support codepage 0 and 5 */
static const struct tok *fr_q933_ie_codesets[] = {
fr_q933_ie_values_codeset_0_5,
NULL,
NULL,
NULL,
NULL,
fr_q933_ie_values_codeset_0_5,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
};
static int fr_q933_print_ie_codeset_0_5(netdissect_options *ndo, u_int iecode,
u_int ielength, const u_char *p);
typedef int (*codeset_pr_func_t)(netdissect_options *, u_int iecode,
u_int ielength, const u_char *p);
/* array of 16 codesets - currently we only support codepage 0 and 5 */
static const codeset_pr_func_t fr_q933_print_ie_codeset[] = {
fr_q933_print_ie_codeset_0_5,
NULL,
NULL,
NULL,
NULL,
fr_q933_print_ie_codeset_0_5,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
};
/*
* ITU-T Q.933.
*
* p points to octet 2, the octet containing the length of the
* call reference value, so p[n] is octet n+2 ("octet X" is as
* used in Q.931/Q.933).
*
* XXX - actually used both for Q.931 and Q.933.
*/
void
q933_print(netdissect_options *ndo,
const u_char *p, u_int length)
{
u_int olen;
u_int call_ref_length, i;
uint8_t call_ref[15]; /* maximum length - length field is 4 bits */
u_int msgtype;
u_int iecode;
u_int ielength;
u_int codeset = 0;
u_int is_ansi = 0;
u_int ie_is_known;
u_int non_locking_shift;
u_int unshift_codeset;
ndo->ndo_protocol = "q.933";
ND_PRINT("%s", ndo->ndo_eflag ? "" : "Q.933");
if (length == 0 || !ND_TTEST_1(p)) {
if (!ndo->ndo_eflag)
ND_PRINT(", ");
ND_PRINT("length %u", length);
goto trunc;
}
/*
* Get the length of the call reference value.
*/
olen = length; /* preserve the original length for display */
call_ref_length = GET_U_1(p) & 0x0f;
p++;
length--;
/*
* Get the call reference value.
*/
for (i = 0; i < call_ref_length; i++) {
if (length == 0 || !ND_TTEST_1(p)) {
if (!ndo->ndo_eflag)
ND_PRINT(", ");
ND_PRINT("length %u", olen);
goto trunc;
}
call_ref[i] = GET_U_1(p);
p++;
length--;
}
/*
* Get the message type.
*/
if (length == 0 || !ND_TTEST_1(p)) {
if (!ndo->ndo_eflag)
ND_PRINT(", ");
ND_PRINT("length %u", olen);
goto trunc;
}
msgtype = GET_U_1(p);
p++;
length--;
/*
* Peek ahead to see if we start with a shift.
*/
non_locking_shift = 0;
unshift_codeset = codeset;
if (length != 0) {
if (!ND_TTEST_1(p)) {
if (!ndo->ndo_eflag)
ND_PRINT(", ");
ND_PRINT("length %u", olen);
goto trunc;
}
iecode = GET_U_1(p);
if (IE_IS_SHIFT(iecode)) {
/*
* It's a shift. Skip over it.
*/
p++;
length--;
/*
* Get the codeset.
*/
codeset = IE_SHIFT_CODESET(iecode);
/*
* If it's a locking shift to codeset 5,
* mark this as ANSI. (XXX - 5 is actually
* for national variants in general, not
* the US variant in particular, but maybe
* this is more American exceptionalism. :-))
*/
if (IE_SHIFT_IS_LOCKING(iecode)) {
/*
* It's a locking shift.
*/
if (codeset == 5) {
/*
* It's a locking shift to
* codeset 5, so this is
* T1.617 Annex D.
*/
is_ansi = 1;
}
} else {
/*
* It's a non-locking shift.
* Remember the current codeset, so we
* can revert to it after the next IE.
*/
non_locking_shift = 1;
unshift_codeset = 0;
}
}
}
/* printing out header part */
if (!ndo->ndo_eflag)
ND_PRINT(", ");
ND_PRINT("%s, codeset %u", is_ansi ? "ANSI" : "CCITT", codeset);
if (call_ref_length != 0) {
if (call_ref_length > 1 || GET_U_1(p) != 0) {
/*
* Not a dummy call reference.
*/
ND_PRINT(", Call Ref: 0x");
for (i = 0; i < call_ref_length; i++)
ND_PRINT("%02x", call_ref[i]);
}
}
if (ndo->ndo_vflag) {
ND_PRINT(", %s (0x%02x), length %u",
tok2str(fr_q933_msg_values,
"unknown message", msgtype),
msgtype,
olen);
} else {
ND_PRINT(", %s",
tok2str(fr_q933_msg_values,
"unknown message 0x%02x", msgtype));
}
/* Loop through the rest of the IEs */
while (length != 0) {
/*
* What's the state of any non-locking shifts?
*/
if (non_locking_shift == 1) {
/*
* There's a non-locking shift in effect for
* this IE. Count it, so we reset the codeset
* before the next IE.
*/
non_locking_shift = 2;
} else if (non_locking_shift == 2) {
/*
* Unshift.
*/
codeset = unshift_codeset;
non_locking_shift = 0;
}
/*
* Get the first octet of the IE.
*/
if (!ND_TTEST_1(p)) {
if (!ndo->ndo_vflag) {
ND_PRINT(", length %u", olen);
}
goto trunc;
}
iecode = GET_U_1(p);
p++;
length--;
/* Single-octet IE? */
if (IE_IS_SINGLE_OCTET(iecode)) {
/*
* Yes. Is it a shift?
*/
if (IE_IS_SHIFT(iecode)) {
/*
* Yes. Is it locking?
*/
if (IE_SHIFT_IS_LOCKING(iecode)) {
/*
* Yes.
*/
non_locking_shift = 0;
} else {
/*
* No. Remember the current
* codeset, so we can revert
* to it after the next IE.
*/
non_locking_shift = 1;
unshift_codeset = codeset;
}
/*
* Get the codeset.
*/
codeset = IE_SHIFT_CODESET(iecode);
}
} else {
/*
* No. Get the IE length.
*/
if (length == 0 || !ND_TTEST_1(p)) {
if (!ndo->ndo_vflag) {
ND_PRINT(", length %u", olen);
}
goto trunc;
}
ielength = GET_U_1(p);
p++;
length--;
/* lets do the full IE parsing only in verbose mode
* however some IEs (DLCI Status, Link Verify)
* are also interesting in non-verbose mode */
if (ndo->ndo_vflag) {
ND_PRINT("\n\t%s IE (0x%02x), length %u: ",
tok2str(fr_q933_ie_codesets[codeset],
"unknown", iecode),
iecode,
ielength);
}
/* sanity checks */
if (iecode == 0 || ielength == 0) {
return;
}
if (length < ielength || !ND_TTEST_LEN(p, ielength)) {
if (!ndo->ndo_vflag) {
ND_PRINT(", length %u", olen);
}
goto trunc;
}
ie_is_known = 0;
if (fr_q933_print_ie_codeset[codeset] != NULL) {
ie_is_known = fr_q933_print_ie_codeset[codeset](ndo, iecode, ielength, p);
}
if (ie_is_known) {
/*
* Known IE; do we want to see a hexdump
* of it?
*/
if (ndo->ndo_vflag > 1) {
/* Yes. */
print_unknown_data(ndo, p, "\n\t ", ielength);
}
} else {
/*
* Unknown IE; if we're printing verbosely,
* print its content in hex.
*/
if (ndo->ndo_vflag >= 1) {
print_unknown_data(ndo, p, "\n\t", ielength);
}
}
length -= ielength;
p += ielength;
}
}
if (!ndo->ndo_vflag) {
ND_PRINT(", length %u", olen);
}
return;
trunc:
nd_print_trunc(ndo);
}
static int
fr_q933_print_ie_codeset_0_5(netdissect_options *ndo, u_int iecode,
u_int ielength, const u_char *p)
{
u_int dlci;
switch (iecode) {
case FR_LMI_ANSI_REPORT_TYPE_IE: /* fall through */
case FR_LMI_CCITT_REPORT_TYPE_IE:
if (ielength < 1) {
if (!ndo->ndo_vflag) {
ND_PRINT(", ");
}
ND_PRINT("Invalid REPORT TYPE IE");
return 1;
}
if (ndo->ndo_vflag) {
ND_PRINT("%s (%u)",
tok2str(fr_lmi_report_type_ie_values,"unknown",GET_U_1(p)),
GET_U_1(p));
}
return 1;
case FR_LMI_ANSI_LINK_VERIFY_IE: /* fall through */
case FR_LMI_CCITT_LINK_VERIFY_IE:
case FR_LMI_ANSI_LINK_VERIFY_IE_91:
if (!ndo->ndo_vflag) {
ND_PRINT(", ");
}
if (ielength < 2) {
ND_PRINT("Invalid LINK VERIFY IE");
return 1;
}
ND_PRINT("TX Seq: %3d, RX Seq: %3d", GET_U_1(p), GET_U_1(p + 1));
return 1;
case FR_LMI_ANSI_PVC_STATUS_IE: /* fall through */
case FR_LMI_CCITT_PVC_STATUS_IE:
if (!ndo->ndo_vflag) {
ND_PRINT(", ");
}
/* now parse the DLCI information element. */
if ((ielength < 3) ||
(GET_U_1(p) & 0x80) ||
((ielength == 3) && !(GET_U_1(p + 1) & 0x80)) ||
((ielength == 4) &&
((GET_U_1(p + 1) & 0x80) || !(GET_U_1(p + 2) & 0x80))) ||
((ielength == 5) &&
((GET_U_1(p + 1) & 0x80) || (GET_U_1(p + 2) & 0x80) ||
!(GET_U_1(p + 3) & 0x80))) ||
(ielength > 5) ||
!(GET_U_1(p + ielength - 1) & 0x80)) {
ND_PRINT("Invalid DLCI in PVC STATUS IE");
return 1;
}
dlci = ((GET_U_1(p) & 0x3F) << 4) | ((GET_U_1(p + 1) & 0x78) >> 3);
if (ielength == 4) {
dlci = (dlci << 6) | ((GET_U_1(p + 2) & 0x7E) >> 1);
- }
- else if (ielength == 5) {
+ } else if (ielength == 5) {
dlci = (dlci << 13) | (GET_U_1(p + 2) & 0x7F) | ((GET_U_1(p + 3) & 0x7E) >> 1);
}
ND_PRINT("DLCI %u: status %s%s", dlci,
GET_U_1(p + ielength - 1) & 0x8 ? "New, " : "",
GET_U_1(p + ielength - 1) & 0x2 ? "Active" : "Inactive");
return 1;
}
return 0;
}
diff --git a/contrib/tcpdump/print-frag6.c b/contrib/tcpdump/print-frag6.c
index 16e8a4b21926..a4b3be0d43ff 100644
--- a/contrib/tcpdump/print-frag6.c
+++ b/contrib/tcpdump/print-frag6.c
@@ -1,66 +1,62 @@
/*
* Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994
* 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.
*/
/* \summary: IPv6 fragmentation header printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "extract.h"
#include "ip6.h"
int
frag6_print(netdissect_options *ndo, const u_char *bp, const u_char *bp2)
{
const struct ip6_frag *dp;
const struct ip6_hdr *ip6;
ndo->ndo_protocol = "frag6";
dp = (const struct ip6_frag *)bp;
ip6 = (const struct ip6_hdr *)bp2;
- if (ndo->ndo_vflag) {
- ND_PRINT("frag (0x%08x:%u|%zu)",
- GET_BE_U_4(dp->ip6f_ident),
- GET_BE_U_2(dp->ip6f_offlg) & IP6F_OFF_MASK,
+ ND_PRINT("frag (");
+ if (ndo->ndo_vflag)
+ ND_PRINT("0x%08x:", GET_BE_U_4(dp->ip6f_ident));
+ ND_PRINT("%u|", GET_BE_U_2(dp->ip6f_offlg) & IP6F_OFF_MASK);
+ if ((bp - bp2) + sizeof(struct ip6_frag) >
+ sizeof(struct ip6_hdr) + GET_BE_U_2(ip6->ip6_plen))
+ ND_PRINT("[length < 0] (invalid))");
+ else
+ ND_PRINT("%zu)",
sizeof(struct ip6_hdr) + GET_BE_U_2(ip6->ip6_plen) -
- (bp - bp2) - sizeof(struct ip6_frag));
- } else {
- ND_PRINT("frag (%u|%zu)",
- GET_BE_U_2(dp->ip6f_offlg) & IP6F_OFF_MASK,
- sizeof(struct ip6_hdr) + GET_BE_U_2(ip6->ip6_plen) -
- (bp - bp2) - sizeof(struct ip6_frag));
- }
+ (bp - bp2) - sizeof(struct ip6_frag));
/* it is meaningless to decode non-first fragment */
if ((GET_BE_U_2(dp->ip6f_offlg) & IP6F_OFF_MASK) != 0)
return -1;
- else
- {
+ else {
ND_PRINT(" ");
return sizeof(struct ip6_frag);
}
}
diff --git a/contrib/tcpdump/print-ftp.c b/contrib/tcpdump/print-ftp.c
index b55937bba1bd..927618f577f2 100644
--- a/contrib/tcpdump/print-ftp.c
+++ b/contrib/tcpdump/print-ftp.c
@@ -1,29 +1,27 @@
/*
* 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.
*/
/* \summary: File Transfer Protocol (FTP) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
void
ftp_print(netdissect_options *ndo, const u_char *pptr, u_int len)
{
ndo->ndo_protocol = "ftp";
txtproto_print(ndo, pptr, len, NULL, 0);
}
diff --git a/contrib/tcpdump/print-geneve.c b/contrib/tcpdump/print-geneve.c
index 0b7ff6e51472..4358803b19a8 100644
--- a/contrib/tcpdump/print-geneve.c
+++ b/contrib/tcpdump/print-geneve.c
@@ -1,244 +1,242 @@
/*
* Copyright (c) 2014 VMware, Inc. All Rights Reserved.
*
* Jesse Gross <jesse@nicira.com>
*
* 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.
*/
/* \summary: Generic Network Virtualization Encapsulation (Geneve) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "extract.h"
#include "ethertype.h"
/*
* Geneve header, draft-ietf-nvo3-geneve
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |Ver| Opt Len |O|C| Rsvd. | Protocol Type |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Virtual Network Identifier (VNI) | Reserved |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Variable Length Options |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* Options:
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Option Class | Type |R|R|R| Length |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Variable Option Data |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
#define VER_SHIFT 6
#define HDR_OPTS_LEN_MASK 0x3F
#define FLAG_OAM (1 << 7)
#define FLAG_CRITICAL (1 << 6)
#define FLAG_R1 (1 << 5)
#define FLAG_R2 (1 << 4)
#define FLAG_R3 (1 << 3)
#define FLAG_R4 (1 << 2)
#define FLAG_R5 (1 << 1)
#define FLAG_R6 (1 << 0)
#define OPT_TYPE_CRITICAL (1 << 7)
#define OPT_LEN_MASK 0x1F
static const struct tok geneve_flag_values[] = {
{ FLAG_OAM, "O" },
{ FLAG_CRITICAL, "C" },
{ FLAG_R1, "R1" },
{ FLAG_R2, "R2" },
{ FLAG_R3, "R3" },
{ FLAG_R4, "R4" },
{ FLAG_R5, "R5" },
{ FLAG_R6, "R6" },
{ 0, NULL }
};
static const char *
format_opt_class(uint16_t opt_class)
{
switch (opt_class) {
case 0x0100:
return "Linux";
case 0x0101:
return "Open vSwitch";
case 0x0102:
return "Open Virtual Networking (OVN)";
case 0x0103:
return "In-band Network Telemetry (INT)";
case 0x0104:
return "VMware";
default:
if (opt_class <= 0x00ff)
return "Standard";
else if (opt_class >= 0xfff0)
return "Experimental";
}
return "Unknown";
}
static void
geneve_opts_print(netdissect_options *ndo, const u_char *bp, u_int len)
{
const char *sep = "";
while (len > 0) {
uint16_t opt_class;
uint8_t opt_type;
uint8_t opt_len;
ND_PRINT("%s", sep);
sep = ", ";
opt_class = GET_BE_U_2(bp);
opt_type = GET_U_1(bp + 2);
opt_len = 4 + ((GET_U_1(bp + 3) & OPT_LEN_MASK) * 4);
ND_PRINT("class %s (0x%x) type 0x%x%s len %u",
format_opt_class(opt_class), opt_class, opt_type,
opt_type & OPT_TYPE_CRITICAL ? "(C)" : "", opt_len);
if (opt_len > len) {
ND_PRINT(" [bad length]");
return;
}
if (ndo->ndo_vflag > 1 && opt_len > 4) {
const uint32_t *data = (const uint32_t *)(bp + 4);
int i;
ND_PRINT(" data");
for (i = 4; i < opt_len; i += 4) {
ND_PRINT(" %08x", GET_BE_U_4(data));
data++;
}
}
bp += opt_len;
len -= opt_len;
}
}
void
geneve_print(netdissect_options *ndo, const u_char *bp, u_int len)
{
uint8_t ver_opt;
u_int version;
uint8_t flags;
uint16_t prot;
uint32_t vni;
uint8_t reserved;
u_int opts_len;
ndo->ndo_protocol = "geneve";
ND_PRINT("Geneve");
if (len < 8) {
ND_PRINT(" [length %u < 8]", len);
nd_print_invalid(ndo);
return;
}
ND_TCHECK_8(bp);
ver_opt = GET_U_1(bp);
bp += 1;
len -= 1;
version = ver_opt >> VER_SHIFT;
if (version != 0) {
ND_PRINT(" ERROR: unknown-version %u", version);
return;
}
flags = GET_U_1(bp);
bp += 1;
len -= 1;
prot = GET_BE_U_2(bp);
bp += 2;
len -= 2;
vni = GET_BE_U_3(bp);
bp += 3;
len -= 3;
reserved = GET_U_1(bp);
bp += 1;
len -= 1;
ND_PRINT(", Flags [%s]",
bittok2str_nosep(geneve_flag_values, "none", flags));
ND_PRINT(", vni 0x%x", vni);
if (reserved)
ND_PRINT(", rsvd 0x%x", reserved);
if (ndo->ndo_eflag)
ND_PRINT(", proto %s (0x%04x)",
tok2str(ethertype_values, "unknown", prot), prot);
opts_len = (ver_opt & HDR_OPTS_LEN_MASK) * 4;
if (len < opts_len) {
ND_PRINT(" truncated-geneve - %u bytes missing",
opts_len - len);
return;
}
ND_TCHECK_LEN(bp, opts_len);
if (opts_len > 0) {
ND_PRINT(", options [");
if (ndo->ndo_vflag)
geneve_opts_print(ndo, bp, opts_len);
else
ND_PRINT("%u bytes", opts_len);
ND_PRINT("]");
}
bp += opts_len;
len -= opts_len;
if (ndo->ndo_vflag < 1)
ND_PRINT(": ");
else
ND_PRINT("\n\t");
if (ethertype_print(ndo, prot, bp, len, ND_BYTES_AVAILABLE_AFTER(bp), NULL, NULL) == 0) {
if (prot == ETHERTYPE_TEB)
ether_print(ndo, bp, len, ND_BYTES_AVAILABLE_AFTER(bp), NULL, NULL);
else
ND_PRINT("geneve-proto-0x%x", prot);
}
return;
trunc:
nd_print_trunc(ndo);
}
diff --git a/contrib/tcpdump/print-geonet.c b/contrib/tcpdump/print-geonet.c
index 2f8046e6b965..3f8ee07572d1 100644
--- a/contrib/tcpdump/print-geonet.c
+++ b/contrib/tcpdump/print-geonet.c
@@ -1,267 +1,265 @@
/*
* Copyright (c) 2013 The TCPDUMP project
*
* 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.
*
* Original code by Ola Martin Lykkja (ola.lykkja@q-free.com)
*/
/* \summary: ISO CALM FAST and ETSI GeoNetworking printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
#include "addrtoname.h"
/*
ETSI TS 102 636-5-1 V1.1.1 (2011-02)
Intelligent Transport Systems (ITS); Vehicular Communications; GeoNetworking;
Part 5: Transport Protocols; Sub-part 1: Basic Transport Protocol
ETSI TS 102 636-4-1 V1.1.1 (2011-06)
Intelligent Transport Systems (ITS); Vehicular communications; GeoNetworking;
Part 4: Geographical addressing and forwarding for point-to-point and point-to-multipoint communications;
Sub-part 1: Media-Independent Functionality
*/
#define GEONET_ADDR_LEN 8
static const struct tok msg_type_values[] = {
{ 0, "CAM" },
{ 1, "DENM" },
{ 101, "TPEGM" },
{ 102, "TSPDM" },
{ 103, "VPM" },
{ 104, "SRM" },
{ 105, "SLAM" },
{ 106, "ecoCAM" },
{ 107, "ITM" },
{ 150, "SA" },
{ 0, NULL }
};
static void
print_btp_body(netdissect_options *ndo,
const u_char *bp)
{
u_int msg_type;
/* Assuming ItsPduHeader */
ND_PRINT("; ItsPduHeader v:%u", GET_U_1(bp));
msg_type = GET_U_1(bp + 1);
ND_PRINT(" t:%u-%s", msg_type,
tok2str(msg_type_values, "unknown (%u)", msg_type));
}
/* EN 302 636-5-1 V2.2.1 Section 7.2: BTP-A header */
static void
print_btp(netdissect_options *ndo,
const u_char *bp)
{
ND_PRINT("; BTP Dst:%u", GET_BE_U_2(bp + 0));
ND_PRINT(" Src:%u", GET_BE_U_2(bp + 2));
}
static void
print_long_pos_vector(netdissect_options *ndo,
const u_char *bp)
{
ND_PRINT("GN_ADDR:%s ", GET_LINKADDR_STRING(bp, LINKADDR_OTHER, GEONET_ADDR_LEN));
ND_PRINT("lat:%u ", GET_BE_U_4(bp + 12));
ND_PRINT("lon:%u", GET_BE_U_4(bp + 16));
}
/*
* This is the top level routine of the printer. 'p' points
* to the geonet header of the packet.
*/
void
geonet_print(netdissect_options *ndo, const u_char *bp, u_int length,
const struct lladdr_info *src)
{
u_int version;
u_int next_hdr;
u_int hdr_type;
u_int hdr_subtype;
uint16_t payload_length;
u_int hop_limit;
const char *next_hdr_txt = "Unknown";
const char *hdr_type_txt = "Unknown";
int hdr_size = -1;
ndo->ndo_protocol = "geonet";
ND_PRINT("GeoNet ");
if (src != NULL)
ND_PRINT("src:%s", (src->addr_string)(ndo, src->addr));
ND_PRINT("; ");
/* Process Common Header */
if (length < 36) {
ND_PRINT(" (common header length %u < 36)", length);
goto invalid;
}
version = GET_U_1(bp) >> 4;
next_hdr = GET_U_1(bp) & 0x0f;
hdr_type = GET_U_1(bp + 1) >> 4;
hdr_subtype = GET_U_1(bp + 1) & 0x0f;
payload_length = GET_BE_U_2(bp + 4);
hop_limit = GET_U_1(bp + 7);
switch (next_hdr) {
case 0: next_hdr_txt = "Any"; break;
case 1: next_hdr_txt = "BTP-A"; break;
case 2: next_hdr_txt = "BTP-B"; break;
case 3: next_hdr_txt = "IPv6"; break;
}
switch (hdr_type) {
case 0: hdr_type_txt = "Any"; break;
case 1: hdr_type_txt = "Beacon"; break;
case 2: hdr_type_txt = "GeoUnicast"; break;
case 3: switch (hdr_subtype) {
case 0: hdr_type_txt = "GeoAnycastCircle"; break;
case 1: hdr_type_txt = "GeoAnycastRect"; break;
case 2: hdr_type_txt = "GeoAnycastElipse"; break;
}
break;
case 4: switch (hdr_subtype) {
case 0: hdr_type_txt = "GeoBroadcastCircle"; break;
case 1: hdr_type_txt = "GeoBroadcastRect"; break;
case 2: hdr_type_txt = "GeoBroadcastElipse"; break;
}
break;
case 5: switch (hdr_subtype) {
case 0: hdr_type_txt = "TopoScopeBcast-SH"; break;
case 1: hdr_type_txt = "TopoScopeBcast-MH"; break;
}
break;
case 6: switch (hdr_subtype) {
case 0: hdr_type_txt = "LocService-Request"; break;
case 1: hdr_type_txt = "LocService-Reply"; break;
}
break;
}
ND_PRINT("v:%u ", version);
ND_PRINT("NH:%u-%s ", next_hdr, next_hdr_txt);
ND_PRINT("HT:%u-%u-%s ", hdr_type, hdr_subtype, hdr_type_txt);
ND_PRINT("HopLim:%u ", hop_limit);
ND_PRINT("Payload:%u ", payload_length);
print_long_pos_vector(ndo, bp + 8);
/* Skip Common Header */
ND_TCHECK_LEN(bp, 36);
length -= 36;
bp += 36;
/* Process Extended Headers */
switch (hdr_type) {
case 0: /* Any */
hdr_size = 0;
break;
case 1: /* Beacon */
hdr_size = 0;
break;
case 2: /* GeoUnicast */
break;
case 3: switch (hdr_subtype) {
case 0: /* GeoAnycastCircle */
break;
case 1: /* GeoAnycastRect */
break;
case 2: /* GeoAnycastElipse */
break;
}
break;
case 4: switch (hdr_subtype) {
case 0: /* GeoBroadcastCircle */
break;
case 1: /* GeoBroadcastRect */
break;
case 2: /* GeoBroadcastElipse */
break;
}
break;
case 5: switch (hdr_subtype) {
case 0: /* TopoScopeBcast-SH */
hdr_size = 0;
break;
case 1: /* TopoScopeBcast-MH */
hdr_size = 68 - 36;
break;
}
break;
case 6: switch (hdr_subtype) {
case 0: /* LocService-Request */
break;
case 1: /* LocService-Reply */
break;
}
break;
}
/* Skip Extended headers */
if (hdr_size >= 0) {
if (length < (u_int)hdr_size) {
ND_PRINT(" (header size %d > %u)", hdr_size, length);
goto invalid;
}
ND_TCHECK_LEN(bp, hdr_size);
length -= hdr_size;
bp += hdr_size;
switch (next_hdr) {
case 0: /* Any */
break;
case 1:
case 2: /* BTP A/B */
if (length < 4) {
ND_PRINT(" (BTP length %u < 4)", length);
goto invalid;
}
print_btp(ndo, bp);
length -= 4;
bp += 4;
if (length >= 2) {
/*
* XXX - did print_btp_body()
* return if length < 2
* because this is optional,
* or was that just not
* reporting genuine errors?
*/
print_btp_body(ndo, bp);
}
break;
case 3: /* IPv6 */
break;
}
}
/* Print user data part */
if (ndo->ndo_vflag)
ND_DEFAULTPRINT(bp, length);
return;
invalid:
nd_print_invalid(ndo);
/* XXX - print the remaining data as hex? */
}
diff --git a/contrib/tcpdump/print-gre.c b/contrib/tcpdump/print-gre.c
index b1a814298b55..7832343a6d07 100644
--- a/contrib/tcpdump/print-gre.c
+++ b/contrib/tcpdump/print-gre.c
@@ -1,414 +1,412 @@
/* $OpenBSD: print-gre.c,v 1.6 2002/10/30 03:04:04 fgsch Exp $ */
/*
* Copyright (c) 2002 Jason L. Wright (jason@thought.net)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* \summary: Generic Routing Encapsulation (GRE) printer */
/*
* netdissect printer for GRE - Generic Routing Encapsulation
* RFC1701 (GRE), RFC1702 (GRE IPv4), and RFC2637 (Enhanced GRE)
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "addrtostr.h"
#include "extract.h"
#include "ethertype.h"
#define GRE_CP 0x8000 /* checksum present */
#define GRE_RP 0x4000 /* routing present */
#define GRE_KP 0x2000 /* key present */
#define GRE_SP 0x1000 /* sequence# present */
#define GRE_sP 0x0800 /* source routing */
#define GRE_AP 0x0080 /* acknowledgment# present */
static const struct tok gre_flag_values[] = {
{ GRE_CP, "checksum present"},
{ GRE_RP, "routing present"},
{ GRE_KP, "key present"},
{ GRE_SP, "sequence# present"},
{ GRE_sP, "source routing present"},
{ GRE_AP, "ack present"},
{ 0, NULL }
};
#define GRE_RECRS_MASK 0x0700 /* recursion count */
#define GRE_VERS_MASK 0x0007 /* protocol version */
/* source route entry types */
#define GRESRE_IP 0x0800 /* IP */
#define GRESRE_ASN 0xfffe /* ASN */
static void gre_print_0(netdissect_options *, const u_char *, u_int);
static void gre_print_1(netdissect_options *, const u_char *, u_int);
static int gre_sre_print(netdissect_options *, uint16_t, uint8_t, uint8_t, const u_char *, u_int);
static int gre_sre_ip_print(netdissect_options *, uint8_t, uint8_t, const u_char *, u_int);
static int gre_sre_asn_print(netdissect_options *, uint8_t, uint8_t, const u_char *, u_int);
void
gre_print(netdissect_options *ndo, const u_char *bp, u_int length)
{
u_int len = length, vers;
ndo->ndo_protocol = "gre";
ND_TCHECK_2(bp);
if (len < 2)
goto trunc;
vers = GET_BE_U_2(bp) & GRE_VERS_MASK;
ND_PRINT("GREv%u",vers);
switch(vers) {
case 0:
gre_print_0(ndo, bp, len);
break;
case 1:
gre_print_1(ndo, bp, len);
break;
default:
ND_PRINT(" ERROR: unknown-version");
break;
}
return;
trunc:
nd_print_trunc(ndo);
}
static void
gre_print_0(netdissect_options *ndo, const u_char *bp, u_int length)
{
u_int len = length;
uint16_t flags, prot;
/* 16 bits ND_TCHECKed in gre_print() */
flags = GET_BE_U_2(bp);
if (ndo->ndo_vflag)
ND_PRINT(", Flags [%s]",
bittok2str(gre_flag_values,"none",flags));
len -= 2;
bp += 2;
ND_TCHECK_2(bp);
if (len < 2)
goto trunc;
prot = GET_BE_U_2(bp);
len -= 2;
bp += 2;
if ((flags & GRE_CP) | (flags & GRE_RP)) {
ND_TCHECK_2(bp);
if (len < 2)
goto trunc;
if (ndo->ndo_vflag)
ND_PRINT(", sum 0x%x", GET_BE_U_2(bp));
bp += 2;
len -= 2;
ND_TCHECK_2(bp);
if (len < 2)
goto trunc;
ND_PRINT(", off 0x%x", GET_BE_U_2(bp));
bp += 2;
len -= 2;
}
if (flags & GRE_KP) {
ND_TCHECK_4(bp);
if (len < 4)
goto trunc;
ND_PRINT(", key=0x%x", GET_BE_U_4(bp));
bp += 4;
len -= 4;
}
if (flags & GRE_SP) {
ND_TCHECK_4(bp);
if (len < 4)
goto trunc;
ND_PRINT(", seq %u", GET_BE_U_4(bp));
bp += 4;
len -= 4;
}
if (flags & GRE_RP) {
for (;;) {
uint16_t af;
uint8_t sreoff;
uint8_t srelen;
ND_TCHECK_4(bp);
if (len < 4)
goto trunc;
af = GET_BE_U_2(bp);
sreoff = GET_U_1(bp + 2);
srelen = GET_U_1(bp + 3);
bp += 4;
len -= 4;
if (af == 0 && srelen == 0)
break;
if (!gre_sre_print(ndo, af, sreoff, srelen, bp, len))
goto trunc;
if (len < srelen)
goto trunc;
bp += srelen;
len -= srelen;
}
}
if (ndo->ndo_eflag)
ND_PRINT(", proto %s (0x%04x)",
tok2str(ethertype_values,"unknown",prot), prot);
ND_PRINT(", length %u",length);
if (ndo->ndo_vflag < 1)
ND_PRINT(": "); /* put in a colon as protocol demarc */
else
ND_PRINT("\n\t"); /* if verbose go multiline */
switch (prot) {
case ETHERTYPE_IP:
ip_print(ndo, bp, len);
break;
case ETHERTYPE_IPV6:
ip6_print(ndo, bp, len);
break;
case ETHERTYPE_MPLS:
mpls_print(ndo, bp, len);
break;
case ETHERTYPE_IPX:
ipx_print(ndo, bp, len);
break;
case ETHERTYPE_ATALK:
atalk_print(ndo, bp, len);
break;
case ETHERTYPE_GRE_ISO:
isoclns_print(ndo, bp, len);
break;
case ETHERTYPE_TEB:
ether_print(ndo, bp, len, ND_BYTES_AVAILABLE_AFTER(bp), NULL, NULL);
break;
default:
ND_PRINT("gre-proto-0x%x", prot);
}
return;
trunc:
nd_print_trunc(ndo);
}
static void
gre_print_1(netdissect_options *ndo, const u_char *bp, u_int length)
{
u_int len = length;
uint16_t flags, prot;
/* 16 bits ND_TCHECKed in gre_print() */
flags = GET_BE_U_2(bp);
len -= 2;
bp += 2;
if (ndo->ndo_vflag)
ND_PRINT(", Flags [%s]",
bittok2str(gre_flag_values,"none",flags));
ND_TCHECK_2(bp);
if (len < 2)
goto trunc;
prot = GET_BE_U_2(bp);
len -= 2;
bp += 2;
if (flags & GRE_KP) {
uint32_t k;
ND_TCHECK_4(bp);
if (len < 4)
goto trunc;
k = GET_BE_U_4(bp);
ND_PRINT(", call %u", k & 0xffff);
len -= 4;
bp += 4;
}
if (flags & GRE_SP) {
ND_TCHECK_4(bp);
if (len < 4)
goto trunc;
ND_PRINT(", seq %u", GET_BE_U_4(bp));
bp += 4;
len -= 4;
}
if (flags & GRE_AP) {
ND_TCHECK_4(bp);
if (len < 4)
goto trunc;
ND_PRINT(", ack %u", GET_BE_U_4(bp));
bp += 4;
len -= 4;
}
if ((flags & GRE_SP) == 0)
ND_PRINT(", no-payload");
if (ndo->ndo_eflag)
ND_PRINT(", proto %s (0x%04x)",
tok2str(ethertype_values,"unknown",prot), prot);
ND_PRINT(", length %u",length);
if ((flags & GRE_SP) == 0)
return;
if (ndo->ndo_vflag < 1)
ND_PRINT(": "); /* put in a colon as protocol demarc */
else
ND_PRINT("\n\t"); /* if verbose go multiline */
switch (prot) {
case ETHERTYPE_PPP:
ppp_print(ndo, bp, len);
break;
default:
ND_PRINT("gre-proto-0x%x", prot);
break;
}
return;
trunc:
nd_print_trunc(ndo);
}
static int
gre_sre_print(netdissect_options *ndo, uint16_t af, uint8_t sreoff,
uint8_t srelen, const u_char *bp, u_int len)
{
int ret;
switch (af) {
case GRESRE_IP:
ND_PRINT(", (rtaf=ip");
ret = gre_sre_ip_print(ndo, sreoff, srelen, bp, len);
ND_PRINT(")");
break;
case GRESRE_ASN:
ND_PRINT(", (rtaf=asn");
ret = gre_sre_asn_print(ndo, sreoff, srelen, bp, len);
ND_PRINT(")");
break;
default:
ND_PRINT(", (rtaf=0x%x)", af);
ret = 1;
}
return (ret);
}
static int
gre_sre_ip_print(netdissect_options *ndo, uint8_t sreoff, uint8_t srelen,
const u_char *bp, u_int len)
{
const u_char *up = bp;
char buf[INET_ADDRSTRLEN];
if (sreoff & 3) {
ND_PRINT(", badoffset=%u", sreoff);
return (1);
}
if (srelen & 3) {
ND_PRINT(", badlength=%u", srelen);
return (1);
}
if (sreoff >= srelen) {
ND_PRINT(", badoff/len=%u/%u", sreoff, srelen);
return (1);
}
while (srelen != 0) {
ND_TCHECK_4(bp);
if (len < 4)
return (0);
addrtostr(bp, buf, sizeof(buf));
ND_PRINT(" %s%s",
((bp - up) == sreoff) ? "*" : "", buf);
bp += 4;
len -= 4;
srelen -= 4;
}
return (1);
trunc:
return 0;
}
static int
gre_sre_asn_print(netdissect_options *ndo, uint8_t sreoff, uint8_t srelen,
const u_char *bp, u_int len)
{
const u_char *up = bp;
if (sreoff & 1) {
ND_PRINT(", badoffset=%u", sreoff);
return (1);
}
if (srelen & 1) {
ND_PRINT(", badlength=%u", srelen);
return (1);
}
if (sreoff >= srelen) {
ND_PRINT(", badoff/len=%u/%u", sreoff, srelen);
return (1);
}
while (srelen != 0) {
ND_TCHECK_2(bp);
if (len < 2)
return (0);
ND_PRINT(" %s%x",
((bp - up) == sreoff) ? "*" : "", GET_BE_U_2(bp));
bp += 2;
len -= 2;
srelen -= 2;
}
return (1);
trunc:
return 0;
}
diff --git a/contrib/tcpdump/print-hncp.c b/contrib/tcpdump/print-hncp.c
index 37c13ec3469c..2dc3147ac4a4 100644
--- a/contrib/tcpdump/print-hncp.c
+++ b/contrib/tcpdump/print-hncp.c
@@ -1,866 +1,864 @@
/*
* Copyright (c) 2016 Antonin Décimo, Jean-Raphaël Gaglione
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* \summary: Home Networking Control Protocol (HNCP) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <string.h>
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
static void
hncp_print_rec(netdissect_options *ndo,
const u_char *cp, u_int length, int indent);
void
hncp_print(netdissect_options *ndo,
const u_char *cp, u_int length)
{
ndo->ndo_protocol = "hncp";
ND_PRINT("hncp (%u)", length);
hncp_print_rec(ndo, cp, length, 1);
}
/* RFC7787 */
#define DNCP_REQUEST_NETWORK_STATE 1
#define DNCP_REQUEST_NODE_STATE 2
#define DNCP_NODE_ENDPOINT 3
#define DNCP_NETWORK_STATE 4
#define DNCP_NODE_STATE 5
#define DNCP_PEER 8
#define DNCP_KEEP_ALIVE_INTERVAL 9
#define DNCP_TRUST_VERDICT 10
/* RFC7788 */
#define HNCP_HNCP_VERSION 32
#define HNCP_EXTERNAL_CONNECTION 33
#define HNCP_DELEGATED_PREFIX 34
#define HNCP_PREFIX_POLICY 43
#define HNCP_DHCPV4_DATA 37 /* This is correct, see RFC 7788 Errata ID 5113. */
#define HNCP_DHCPV6_DATA 38 /* idem */
#define HNCP_ASSIGNED_PREFIX 35
#define HNCP_NODE_ADDRESS 36
#define HNCP_DNS_DELEGATED_ZONE 39
#define HNCP_DOMAIN_NAME 40
#define HNCP_NODE_NAME 41
#define HNCP_MANAGED_PSK 42
/* See type_mask in hncp_print_rec below */
#define RANGE_DNCP_RESERVED 0x10000
#define RANGE_HNCP_UNASSIGNED 0x10001
#define RANGE_DNCP_PRIVATE_USE 0x10002
#define RANGE_DNCP_FUTURE_USE 0x10003
static const struct tok type_values[] = {
{ DNCP_REQUEST_NETWORK_STATE, "Request network state" },
{ DNCP_REQUEST_NODE_STATE, "Request node state" },
{ DNCP_NODE_ENDPOINT, "Node endpoint" },
{ DNCP_NETWORK_STATE, "Network state" },
{ DNCP_NODE_STATE, "Node state" },
{ DNCP_PEER, "Peer" },
{ DNCP_KEEP_ALIVE_INTERVAL, "Keep-alive interval" },
{ DNCP_TRUST_VERDICT, "Trust-Verdict" },
{ HNCP_HNCP_VERSION, "HNCP-Version" },
{ HNCP_EXTERNAL_CONNECTION, "External-Connection" },
{ HNCP_DELEGATED_PREFIX, "Delegated-Prefix" },
{ HNCP_PREFIX_POLICY, "Prefix-Policy" },
{ HNCP_DHCPV4_DATA, "DHCPv4-Data" },
{ HNCP_DHCPV6_DATA, "DHCPv6-Data" },
{ HNCP_ASSIGNED_PREFIX, "Assigned-Prefix" },
{ HNCP_NODE_ADDRESS, "Node-Address" },
{ HNCP_DNS_DELEGATED_ZONE, "DNS-Delegated-Zone" },
{ HNCP_DOMAIN_NAME, "Domain-Name" },
{ HNCP_NODE_NAME, "Node-Name" },
{ HNCP_MANAGED_PSK, "Managed-PSK" },
{ RANGE_DNCP_RESERVED, "Reserved" },
{ RANGE_HNCP_UNASSIGNED, "Unassigned" },
{ RANGE_DNCP_PRIVATE_USE, "Private use" },
{ RANGE_DNCP_FUTURE_USE, "Future use" },
{ 0, NULL}
};
#define DH4OPT_DNS_SERVERS 6 /* RFC2132 */
#define DH4OPT_NTP_SERVERS 42 /* RFC2132 */
#define DH4OPT_DOMAIN_SEARCH 119 /* RFC3397 */
static const struct tok dh4opt_str[] = {
{ DH4OPT_DNS_SERVERS, "DNS-server" },
{ DH4OPT_NTP_SERVERS, "NTP-server"},
{ DH4OPT_DOMAIN_SEARCH, "DNS-search" },
{ 0, NULL }
};
#define DH6OPT_DNS_SERVERS 23 /* RFC3646 */
#define DH6OPT_DOMAIN_LIST 24 /* RFC3646 */
#define DH6OPT_SNTP_SERVERS 31 /* RFC4075 */
static const struct tok dh6opt_str[] = {
{ DH6OPT_DNS_SERVERS, "DNS-server" },
{ DH6OPT_DOMAIN_LIST, "DNS-search-list" },
{ DH6OPT_SNTP_SERVERS, "SNTP-servers" },
{ 0, NULL }
};
/*
* For IPv4-mapped IPv6 addresses, length of the prefix that precedes
* the 4 bytes of IPv4 address at the end of the IPv6 address.
*/
#define IPV4_MAPPED_HEADING_LEN 12
/*
* Is an IPv6 address an IPv4-mapped address?
*/
static int
is_ipv4_mapped_address(const u_char *addr)
{
/* The value of the prefix */
static const u_char ipv4_mapped_heading[IPV4_MAPPED_HEADING_LEN] =
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF };
return memcmp(addr, ipv4_mapped_heading, IPV4_MAPPED_HEADING_LEN) == 0;
}
static const char *
format_nid(netdissect_options *ndo, const u_char *data)
{
static char buf[4][sizeof("01:01:01:01")];
static int i = 0;
i = (i + 1) % 4;
snprintf(buf[i], sizeof(buf[i]), "%02x:%02x:%02x:%02x",
GET_U_1(data), GET_U_1(data + 1), GET_U_1(data + 2),
GET_U_1(data + 3));
return buf[i];
}
static const char *
format_256(netdissect_options *ndo, const u_char *data)
{
static char buf[4][sizeof("0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef")];
static int i = 0;
i = (i + 1) % 4;
snprintf(buf[i], sizeof(buf[i]), "%016" PRIx64 "%016" PRIx64 "%016" PRIx64 "%016" PRIx64,
GET_BE_U_8(data),
GET_BE_U_8(data + 8),
GET_BE_U_8(data + 16),
GET_BE_U_8(data + 24)
);
return buf[i];
}
static const char *
format_interval(const uint32_t n)
{
static char buf[4][sizeof("0000000.000s")];
static int i = 0;
i = (i + 1) % 4;
snprintf(buf[i], sizeof(buf[i]), "%u.%03us", n / 1000, n % 1000);
return buf[i];
}
static const char *
format_ip6addr(netdissect_options *ndo, const u_char *cp)
{
if (is_ipv4_mapped_address(cp))
return GET_IPADDR_STRING(cp + IPV4_MAPPED_HEADING_LEN);
else
return GET_IP6ADDR_STRING(cp);
}
static int
print_prefix(netdissect_options *ndo, const u_char *prefix, u_int max_length)
{
int plenbytes;
char buf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx::/128")];
if (GET_U_1(prefix) >= 96 && max_length >= IPV4_MAPPED_HEADING_LEN + 1 &&
is_ipv4_mapped_address(prefix + 1)) {
nd_ipv4 addr;
u_int plen;
plen = GET_U_1(prefix) - 96;
if (32 < plen)
return -1;
max_length -= 1;
memset(&addr, 0, sizeof(addr));
plenbytes = (plen + 7) / 8;
if (max_length < (u_int)plenbytes + IPV4_MAPPED_HEADING_LEN)
return -3;
memcpy(&addr, prefix + IPV4_MAPPED_HEADING_LEN + 1, plenbytes);
if (plen % 8) {
((u_char *)&addr)[plenbytes - 1] &=
((0xff00 >> (plen % 8)) & 0xff);
}
snprintf(buf, sizeof(buf), "%s/%u", ipaddr_string(ndo, (const u_char *)&addr), plen); /* local buffer, not packet data; don't use GET_IPADDR_STRING() */
plenbytes += 1 + IPV4_MAPPED_HEADING_LEN;
} else {
plenbytes = decode_prefix6(ndo, prefix, max_length, buf, sizeof(buf));
if (plenbytes < 0)
return plenbytes;
}
ND_PRINT("%s", buf);
return plenbytes;
}
static int
print_dns_label(netdissect_options *ndo,
const u_char *cp, u_int max_length, int print)
{
u_int length = 0;
while (length < max_length) {
u_int lab_length = GET_U_1(cp + length);
length++;
if (lab_length == 0)
return (int)length;
if (length > 1 && print)
ND_PRINT(".");
if (length+lab_length > max_length) {
if (print)
nd_printjnp(ndo, cp+length, max_length-length);
break;
}
if (print)
nd_printjnp(ndo, cp+length, lab_length);
length += lab_length;
}
if (print)
ND_PRINT("[|DNS]");
return -1;
}
static int
dhcpv4_print(netdissect_options *ndo,
const u_char *cp, u_int length, int indent)
{
u_int i, t;
const uint8_t *tlv, *value;
uint8_t type, optlen;
i = 0;
while (i < length) {
if (i + 2 > length)
return -1;
tlv = cp + i;
type = GET_U_1(tlv);
optlen = GET_U_1(tlv + 1);
value = tlv + 2;
ND_PRINT("\n");
for (t = indent; t > 0; t--)
ND_PRINT("\t");
ND_PRINT("%s", tok2str(dh4opt_str, "Unknown", type));
ND_PRINT(" (%u)", optlen + 2 );
if (i + 2 + optlen > length)
return -1;
switch (type) {
case DH4OPT_DNS_SERVERS:
case DH4OPT_NTP_SERVERS: {
if (optlen < 4 || optlen % 4 != 0) {
return -1;
}
for (t = 0; t < optlen; t += 4)
ND_PRINT(" %s", GET_IPADDR_STRING(value + t));
}
break;
case DH4OPT_DOMAIN_SEARCH: {
const u_char *tp = value;
while (tp < value + optlen) {
ND_PRINT(" ");
if ((tp = fqdn_print(ndo, tp, value + optlen)) == NULL)
return -1;
}
}
break;
}
i += 2 + optlen;
}
return 0;
}
static int
dhcpv6_print(netdissect_options *ndo,
const u_char *cp, u_int length, int indent)
{
u_int i, t;
const u_char *tlv, *value;
uint16_t type, optlen;
i = 0;
while (i < length) {
if (i + 4 > length)
return -1;
tlv = cp + i;
type = GET_BE_U_2(tlv);
optlen = GET_BE_U_2(tlv + 2);
value = tlv + 4;
ND_PRINT("\n");
for (t = indent; t > 0; t--)
ND_PRINT("\t");
ND_PRINT("%s", tok2str(dh6opt_str, "Unknown", type));
ND_PRINT(" (%u)", optlen + 4 );
if (i + 4 + optlen > length)
return -1;
switch (type) {
case DH6OPT_DNS_SERVERS:
case DH6OPT_SNTP_SERVERS: {
if (optlen % 16 != 0) {
nd_print_invalid(ndo);
return -1;
}
for (t = 0; t < optlen; t += 16)
ND_PRINT(" %s", GET_IP6ADDR_STRING(value + t));
}
break;
case DH6OPT_DOMAIN_LIST: {
const u_char *tp = value;
while (tp < value + optlen) {
ND_PRINT(" ");
if ((tp = fqdn_print(ndo, tp, value + optlen)) == NULL)
return -1;
}
}
break;
}
i += 4 + optlen;
}
return 0;
}
/* Determine in-line mode */
static int
is_in_line(netdissect_options *ndo, int indent)
{
return indent - 1 >= ndo->ndo_vflag && ndo->ndo_vflag < 3;
}
static void
print_type_in_line(netdissect_options *ndo,
uint32_t type, int count, int indent, int *first_one)
{
if (count > 0) {
if (*first_one) {
*first_one = 0;
if (indent > 1) {
u_int t;
ND_PRINT("\n");
for (t = indent; t > 0; t--)
ND_PRINT("\t");
} else {
ND_PRINT(" ");
}
} else {
ND_PRINT(", ");
}
ND_PRINT("%s", tok2str(type_values, "Easter Egg", type));
if (count > 1)
ND_PRINT(" (x%d)", count);
}
}
static void
hncp_print_rec(netdissect_options *ndo,
const u_char *cp, u_int length, int indent)
{
const int in_line = is_in_line(ndo, indent);
int first_one = 1;
u_int i, t;
uint32_t last_type_mask = 0xffffffffU;
int last_type_count = -1;
const uint8_t *tlv, *value;
uint16_t type, bodylen;
uint32_t type_mask;
i = 0;
while (i < length) {
tlv = cp + i;
if (!in_line) {
ND_PRINT("\n");
for (t = indent; t > 0; t--)
ND_PRINT("\t");
}
ND_TCHECK_4(tlv);
if (i + 4 > length)
goto invalid;
type = GET_BE_U_2(tlv);
bodylen = GET_BE_U_2(tlv + 2);
value = tlv + 4;
ND_TCHECK_LEN(value, bodylen);
if (i + bodylen + 4 > length)
goto invalid;
type_mask =
(type == 0) ? RANGE_DNCP_RESERVED:
(44 <= type && type <= 511) ? RANGE_HNCP_UNASSIGNED:
(768 <= type && type <= 1023) ? RANGE_DNCP_PRIVATE_USE:
RANGE_DNCP_FUTURE_USE;
if (type == 6 || type == 7)
type_mask = RANGE_DNCP_FUTURE_USE;
/* defined types */
{
t = 0;
while (1) {
u_int key = type_values[t++].v;
if (key > 0xffff)
break;
if (key == type) {
type_mask = type;
break;
}
}
}
if (in_line) {
if (last_type_mask == type_mask) {
last_type_count++;
} else {
print_type_in_line(ndo, last_type_mask, last_type_count, indent, &first_one);
last_type_mask = type_mask;
last_type_count = 1;
}
goto skip_multiline;
}
ND_PRINT("%s", tok2str(type_values, "Easter Egg (42)", type_mask) );
if (type_mask > 0xffff)
ND_PRINT(": type=%u", type );
ND_PRINT(" (%u)", bodylen + 4 );
switch (type_mask) {
case DNCP_REQUEST_NETWORK_STATE: {
if (bodylen != 0)
nd_print_invalid(ndo);
}
break;
case DNCP_REQUEST_NODE_STATE: {
const char *node_identifier;
if (bodylen != 4) {
nd_print_invalid(ndo);
break;
}
node_identifier = format_nid(ndo, value);
ND_PRINT(" NID: %s", node_identifier);
}
break;
case DNCP_NODE_ENDPOINT: {
const char *node_identifier;
uint32_t endpoint_identifier;
if (bodylen != 8) {
nd_print_invalid(ndo);
break;
}
node_identifier = format_nid(ndo, value);
endpoint_identifier = GET_BE_U_4(value + 4);
ND_PRINT(" NID: %s EPID: %08x",
node_identifier,
endpoint_identifier
);
}
break;
case DNCP_NETWORK_STATE: {
uint64_t hash;
if (bodylen != 8) {
nd_print_invalid(ndo);
break;
}
hash = GET_BE_U_8(value);
ND_PRINT(" hash: %016" PRIx64, hash);
}
break;
case DNCP_NODE_STATE: {
const char *node_identifier, *interval;
uint32_t sequence_number;
uint64_t hash;
if (bodylen < 20) {
nd_print_invalid(ndo);
break;
}
node_identifier = format_nid(ndo, value);
sequence_number = GET_BE_U_4(value + 4);
interval = format_interval(GET_BE_U_4(value + 8));
hash = GET_BE_U_8(value + 12);
ND_PRINT(" NID: %s seqno: %u %s hash: %016" PRIx64,
node_identifier,
sequence_number,
interval,
hash
);
hncp_print_rec(ndo, value+20, bodylen-20, indent+1);
}
break;
case DNCP_PEER: {
const char *peer_node_identifier;
uint32_t peer_endpoint_identifier, endpoint_identifier;
if (bodylen != 12) {
nd_print_invalid(ndo);
break;
}
peer_node_identifier = format_nid(ndo, value);
peer_endpoint_identifier = GET_BE_U_4(value + 4);
endpoint_identifier = GET_BE_U_4(value + 8);
ND_PRINT(" Peer-NID: %s Peer-EPID: %08x Local-EPID: %08x",
peer_node_identifier,
peer_endpoint_identifier,
endpoint_identifier
);
}
break;
case DNCP_KEEP_ALIVE_INTERVAL: {
uint32_t endpoint_identifier;
const char *interval;
if (bodylen < 8) {
nd_print_invalid(ndo);
break;
}
endpoint_identifier = GET_BE_U_4(value);
interval = format_interval(GET_BE_U_4(value + 4));
ND_PRINT(" EPID: %08x Interval: %s",
endpoint_identifier,
interval
);
}
break;
case DNCP_TRUST_VERDICT: {
if (bodylen <= 36) {
nd_print_invalid(ndo);
break;
}
ND_PRINT(" Verdict: %u Fingerprint: %s Common Name: ",
GET_U_1(value),
format_256(ndo, value + 4));
nd_printjnp(ndo, value + 36, bodylen - 36);
}
break;
case HNCP_HNCP_VERSION: {
uint16_t capabilities;
uint8_t M, P, H, L;
if (bodylen < 5) {
nd_print_invalid(ndo);
break;
}
capabilities = GET_BE_U_2(value + 2);
M = (uint8_t)((capabilities >> 12) & 0xf);
P = (uint8_t)((capabilities >> 8) & 0xf);
H = (uint8_t)((capabilities >> 4) & 0xf);
L = (uint8_t)(capabilities & 0xf);
ND_PRINT(" M: %u P: %u H: %u L: %u User-agent: ",
M, P, H, L
);
nd_printjnp(ndo, value + 4, bodylen - 4);
}
break;
case HNCP_EXTERNAL_CONNECTION: {
/* Container TLV */
hncp_print_rec(ndo, value, bodylen, indent+1);
}
break;
case HNCP_DELEGATED_PREFIX: {
int l;
if (bodylen < 9 || bodylen < 9 + (GET_U_1(value + 8) + 7) / 8) {
nd_print_invalid(ndo);
break;
}
ND_PRINT(" VLSO: %s PLSO: %s Prefix: ",
format_interval(GET_BE_U_4(value)),
format_interval(GET_BE_U_4(value + 4))
);
l = print_prefix(ndo, value + 8, bodylen - 8);
if (l == -1) {
ND_PRINT("(length is invalid)");
break;
}
if (l < 0) {
/*
* We've already checked that we've captured the
* entire TLV, based on its length, so this will
* either be -1, meaning "the prefix length is
* greater than the longest possible address of
* that type" (i.e., > 32 for IPv4 or > 128 for
* IPv6", or -3, meaning "the prefix runs past
* the end of the TLV".
*/
nd_print_invalid(ndo);
break;
}
l += 8 + (-l & 3);
if (bodylen >= l)
hncp_print_rec(ndo, value + l, bodylen - l, indent+1);
}
break;
case HNCP_PREFIX_POLICY: {
uint8_t policy;
int l;
if (bodylen < 1) {
nd_print_invalid(ndo);
break;
}
policy = GET_U_1(value);
ND_PRINT(" type: ");
if (policy == 0) {
if (bodylen != 1) {
nd_print_invalid(ndo);
break;
}
ND_PRINT("Internet connectivity");
} else if (policy >= 1 && policy <= 128) {
ND_PRINT("Dest-Prefix: ");
l = print_prefix(ndo, value, bodylen);
if (l == -1) {
ND_PRINT("(length is invalid)");
break;
}
if (l < 0) {
/*
* We've already checked that we've captured the
* entire TLV, based on its length, so this will
* either be -1, meaning "the prefix length is
* greater than the longest possible address of
* that type" (i.e., > 32 for IPv4 or > 128 for
* IPv6", or -3, meaning "the prefix runs past
* the end of the TLV".
*/
nd_print_invalid(ndo);
break;
}
} else if (policy == 129) {
ND_PRINT("DNS domain: ");
print_dns_label(ndo, value+1, bodylen-1, 1);
} else if (policy == 130) {
ND_PRINT("Opaque UTF-8: ");
nd_printjnp(ndo, value + 1, bodylen - 1);
} else if (policy == 131) {
if (bodylen != 1) {
nd_print_invalid(ndo);
break;
}
ND_PRINT("Restrictive assignment");
} else if (policy >= 132) {
ND_PRINT("Unknown (%u)", policy); /* Reserved for future additions */
}
}
break;
case HNCP_DHCPV4_DATA: {
if (bodylen == 0) {
nd_print_invalid(ndo);
break;
}
if (dhcpv4_print(ndo, value, bodylen, indent+1) != 0)
goto invalid;
}
break;
case HNCP_DHCPV6_DATA: {
if (bodylen == 0) {
nd_print_invalid(ndo);
break;
}
if (dhcpv6_print(ndo, value, bodylen, indent+1) != 0) {
nd_print_invalid(ndo);
break;
}
}
break;
case HNCP_ASSIGNED_PREFIX: {
uint8_t prty;
int l;
if (bodylen < 6 || bodylen < 6 + (GET_U_1(value + 5) + 7) / 8) {
nd_print_invalid(ndo);
break;
}
prty = GET_U_1(value + 4) & 0xf;
ND_PRINT(" EPID: %08x Prty: %u",
GET_BE_U_4(value),
prty
);
ND_PRINT(" Prefix: ");
if ((l = print_prefix(ndo, value + 5, bodylen - 5)) < 0) {
nd_print_invalid(ndo);
break;
}
l += 5;
l += -l & 3;
if (bodylen >= l)
hncp_print_rec(ndo, value + l, bodylen - l, indent+1);
}
break;
case HNCP_NODE_ADDRESS: {
uint32_t endpoint_identifier;
const char *ip_address;
if (bodylen < 20) {
nd_print_invalid(ndo);
break;
}
endpoint_identifier = GET_BE_U_4(value);
ip_address = format_ip6addr(ndo, value + 4);
ND_PRINT(" EPID: %08x IP Address: %s",
endpoint_identifier,
ip_address
);
hncp_print_rec(ndo, value + 20, bodylen - 20, indent+1);
}
break;
case HNCP_DNS_DELEGATED_ZONE: {
const char *ip_address;
int len;
if (bodylen < 17) {
nd_print_invalid(ndo);
break;
}
ip_address = format_ip6addr(ndo, value);
ND_PRINT(" IP-Address: %s %c%c%c ",
ip_address,
(GET_U_1(value + 16) & 4) ? 'l' : '-',
(GET_U_1(value + 16) & 2) ? 'b' : '-',
(GET_U_1(value + 16) & 1) ? 's' : '-'
);
len = print_dns_label(ndo, value+17, bodylen-17, 1);
if (len < 0) {
nd_print_invalid(ndo);
break;
}
len += 17;
len += -len & 3;
if (bodylen >= len)
hncp_print_rec(ndo, value+len, bodylen-len, indent+1);
}
break;
case HNCP_DOMAIN_NAME: {
if (bodylen == 0) {
nd_print_invalid(ndo);
break;
}
ND_PRINT(" Domain: ");
print_dns_label(ndo, value, bodylen, 1);
}
break;
case HNCP_NODE_NAME: {
u_int l;
if (bodylen < 17) {
nd_print_invalid(ndo);
break;
}
l = GET_U_1(value + 16);
if (bodylen < 17 + l) {
nd_print_invalid(ndo);
break;
}
ND_PRINT(" IP-Address: %s Name: ",
format_ip6addr(ndo, value)
);
if (l < 64) {
ND_PRINT("\"");
nd_printjnp(ndo, value + 17, l);
ND_PRINT("\"");
} else {
nd_print_invalid(ndo);
}
l += 17;
l = roundup2(l, 4);
if (bodylen >= l)
hncp_print_rec(ndo, value + l, bodylen - l, indent+1);
}
break;
case HNCP_MANAGED_PSK: {
if (bodylen < 32) {
nd_print_invalid(ndo);
break;
}
ND_PRINT(" PSK: %s", format_256(ndo, value));
hncp_print_rec(ndo, value + 32, bodylen - 32, indent+1);
}
break;
case RANGE_DNCP_RESERVED:
case RANGE_HNCP_UNASSIGNED:
case RANGE_DNCP_PRIVATE_USE:
case RANGE_DNCP_FUTURE_USE:
break;
}
skip_multiline:
i += 4 + roundup2(bodylen, 4);
}
print_type_in_line(ndo, last_type_mask, last_type_count, indent, &first_one);
return;
trunc:
nd_print_trunc(ndo);
return;
invalid:
nd_print_invalid(ndo);
}
diff --git a/contrib/tcpdump/print-hsrp.c b/contrib/tcpdump/print-hsrp.c
index 3027826847a9..f09f00a1c43b 100644
--- a/contrib/tcpdump/print-hsrp.c
+++ b/contrib/tcpdump/print-hsrp.c
@@ -1,133 +1,131 @@
/*
* Copyright (C) 2001 Julian Cowley
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* \summary: Cisco Hot Standby Router Protocol (HSRP) printer */
/* specification: RFC 2281 for version 1 */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
/* HSRP op code types. */
static const char *op_code_str[] = {
"hello",
"coup",
"resign"
};
/* HSRP states and associated names. */
static const struct tok states[] = {
{ 0, "initial" },
{ 1, "learn" },
{ 2, "listen" },
{ 4, "speak" },
{ 8, "standby" },
{ 16, "active" },
{ 0, NULL }
};
/*
* RFC 2281:
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Version | Op Code | State | Hellotime |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Holdtime | Priority | Group | Reserved |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Authentication Data |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Authentication Data |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Virtual IP Address |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
#define HSRP_AUTH_SIZE 8
/* HSRP protocol header. */
struct hsrp {
nd_uint8_t hsrp_version;
nd_uint8_t hsrp_op_code;
nd_uint8_t hsrp_state;
nd_uint8_t hsrp_hellotime;
nd_uint8_t hsrp_holdtime;
nd_uint8_t hsrp_priority;
nd_uint8_t hsrp_group;
nd_uint8_t hsrp_reserved;
nd_byte hsrp_authdata[HSRP_AUTH_SIZE];
nd_ipv4 hsrp_virtaddr;
};
void
hsrp_print(netdissect_options *ndo, const u_char *bp, u_int len)
{
const struct hsrp *hp = (const struct hsrp *) bp;
uint8_t version;
ndo->ndo_protocol = "hsrp";
version = GET_U_1(hp->hsrp_version);
ND_PRINT("HSRPv%u", version);
if (version != 0)
return;
ND_PRINT("-");
ND_PRINT("%s ",
tok2strary(op_code_str, "unknown (%u)", GET_U_1(hp->hsrp_op_code)));
ND_PRINT("%u: ", len);
ND_PRINT("state=%s ",
tok2str(states, "Unknown (%u)", GET_U_1(hp->hsrp_state)));
ND_PRINT("group=%u ", GET_U_1(hp->hsrp_group));
if (GET_U_1(hp->hsrp_reserved) != 0) {
ND_PRINT("[reserved=%u!] ", GET_U_1(hp->hsrp_reserved));
}
ND_PRINT("addr=%s", GET_IPADDR_STRING(hp->hsrp_virtaddr));
if (ndo->ndo_vflag) {
ND_PRINT(" hellotime=");
unsigned_relts_print(ndo, GET_U_1(hp->hsrp_hellotime));
ND_PRINT(" holdtime=");
unsigned_relts_print(ndo, GET_U_1(hp->hsrp_holdtime));
ND_PRINT(" priority=%u", GET_U_1(hp->hsrp_priority));
ND_PRINT(" auth=\"");
/*
* RFC 2281 Section 5.1 does not specify the encoding of
* Authentication Data explicitly, but zero padding can be
* inferred from the "recommended default value".
*/
nd_printjnp(ndo, hp->hsrp_authdata, HSRP_AUTH_SIZE);
ND_PRINT("\"");
}
}
diff --git a/contrib/tcpdump/print-http.c b/contrib/tcpdump/print-http.c
index 6845d0d31528..cdb1fd71a21e 100644
--- a/contrib/tcpdump/print-http.c
+++ b/contrib/tcpdump/print-http.c
@@ -1,74 +1,72 @@
/*
* 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.
*/
/* \summary: Hypertext Transfer Protocol (HTTP) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
/*
* Includes WebDAV requests.
*/
static const char *httpcmds[] = {
"GET",
"PUT",
"COPY",
"HEAD",
"LOCK",
"MOVE",
"POLL",
"POST",
"BCOPY",
"BMOVE",
"MKCOL",
"TRACE",
"LABEL",
"MERGE",
"DELETE",
"SEARCH",
"UNLOCK",
"REPORT",
"UPDATE",
"NOTIFY",
"BDELETE",
"CONNECT",
"OPTIONS",
"CHECKIN",
"PROPFIND",
"CHECKOUT",
"CCM_POST",
"SUBSCRIBE",
"PROPPATCH",
"BPROPFIND",
"BPROPPATCH",
"UNCHECKOUT",
"MKACTIVITY",
"MKWORKSPACE",
"UNSUBSCRIBE",
"RPC_CONNECT",
"VERSION-CONTROL",
"BASELINE-CONTROL",
NULL
};
void
http_print(netdissect_options *ndo, const u_char *pptr, u_int len)
{
ndo->ndo_protocol = "http";
txtproto_print(ndo, pptr, len, httpcmds, RESP_CODE_SECOND_TOKEN);
}
diff --git a/contrib/tcpdump/print-icmp.c b/contrib/tcpdump/print-icmp.c
index 54d215e1d7fe..9b53a48a28b9 100644
--- a/contrib/tcpdump/print-icmp.c
+++ b/contrib/tcpdump/print-icmp.c
@@ -1,797 +1,795 @@
/*
* Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994, 1995, 1996
* 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.
*/
/* \summary: Internet Control Message Protocol (ICMP) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <stdio.h>
#include <string.h>
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#include "ip.h"
#include "udp.h"
#include "ipproto.h"
#include "mpls.h"
/*
* Interface Control Message Protocol Definitions.
* Per RFC 792, September 1981.
*/
/*
* Structure of an icmp header.
*/
struct icmp {
nd_uint8_t icmp_type; /* type of message, see below */
nd_uint8_t icmp_code; /* type sub code */
nd_uint16_t icmp_cksum; /* ones complement cksum of struct */
union {
nd_uint8_t ih_pptr; /* ICMP_PARAMPROB */
nd_ipv4 ih_gwaddr; /* ICMP_REDIRECT */
struct ih_idseq {
nd_uint16_t icd_id;
nd_uint16_t icd_seq;
} ih_idseq;
nd_uint32_t ih_void;
} icmp_hun;
#define icmp_pptr icmp_hun.ih_pptr
#define icmp_gwaddr icmp_hun.ih_gwaddr
#define icmp_id icmp_hun.ih_idseq.icd_id
#define icmp_seq icmp_hun.ih_idseq.icd_seq
#define icmp_void icmp_hun.ih_void
union {
struct id_ts {
nd_uint32_t its_otime;
nd_uint32_t its_rtime;
nd_uint32_t its_ttime;
} id_ts;
struct id_ip {
struct ip idi_ip;
/* options and then 64 bits of data */
} id_ip;
nd_uint32_t id_mask;
nd_byte id_data[1];
} icmp_dun;
#define icmp_otime icmp_dun.id_ts.its_otime
#define icmp_rtime icmp_dun.id_ts.its_rtime
#define icmp_ttime icmp_dun.id_ts.its_ttime
#define icmp_ip icmp_dun.id_ip.idi_ip
#define icmp_mask icmp_dun.id_mask
#define icmp_data icmp_dun.id_data
};
/*
* Lower bounds on packet lengths for various types.
* For the error advice packets must first insure that the
* packet is large enough to contain the returned ip header.
* Only then can we do the check to see if 64 bits of packet
* data have been returned, since we need to check the returned
* ip header length.
*/
#define ICMP_MINLEN 8 /* abs minimum */
#define ICMP_EXTD_MINLEN (156 - sizeof (struct ip)) /* draft-bonica-internet-icmp-08 */
#define ICMP_TSLEN (8 + 3 * sizeof (uint32_t)) /* timestamp */
#define ICMP_MASKLEN 12 /* address mask */
#define ICMP_ADVLENMIN (8 + sizeof (struct ip) + 8) /* min */
#define ICMP_ADVLEN(p) (8 + (IP_HL(&(p)->icmp_ip) << 2) + 8)
/* N.B.: must separately check that ip_hl >= 5 */
/*
* Definition of type and code field values.
*/
#define ICMP_ECHOREPLY 0 /* echo reply */
#define ICMP_UNREACH 3 /* dest unreachable, codes: */
#define ICMP_UNREACH_NET 0 /* bad net */
#define ICMP_UNREACH_HOST 1 /* bad host */
#define ICMP_UNREACH_PROTOCOL 2 /* bad protocol */
#define ICMP_UNREACH_PORT 3 /* bad port */
#define ICMP_UNREACH_NEEDFRAG 4 /* IP_DF caused drop */
#define ICMP_UNREACH_SRCFAIL 5 /* src route failed */
#define ICMP_UNREACH_NET_UNKNOWN 6 /* unknown net */
#define ICMP_UNREACH_HOST_UNKNOWN 7 /* unknown host */
#define ICMP_UNREACH_ISOLATED 8 /* src host isolated */
#define ICMP_UNREACH_NET_PROHIB 9 /* prohibited access */
#define ICMP_UNREACH_HOST_PROHIB 10 /* ditto */
#define ICMP_UNREACH_TOSNET 11 /* bad tos for net */
#define ICMP_UNREACH_TOSHOST 12 /* bad tos for host */
#define ICMP_SOURCEQUENCH 4 /* packet lost, slow down */
#define ICMP_REDIRECT 5 /* shorter route, codes: */
#define ICMP_REDIRECT_NET 0 /* for network */
#define ICMP_REDIRECT_HOST 1 /* for host */
#define ICMP_REDIRECT_TOSNET 2 /* for tos and net */
#define ICMP_REDIRECT_TOSHOST 3 /* for tos and host */
#define ICMP_ECHO 8 /* echo service */
#define ICMP_ROUTERADVERT 9 /* router advertisement */
#define ICMP_ROUTERSOLICIT 10 /* router solicitation */
#define ICMP_TIMXCEED 11 /* time exceeded, code: */
#define ICMP_TIMXCEED_INTRANS 0 /* ttl==0 in transit */
#define ICMP_TIMXCEED_REASS 1 /* ttl==0 in reass */
#define ICMP_PARAMPROB 12 /* ip header bad */
#define ICMP_PARAMPROB_OPTABSENT 1 /* req. opt. absent */
#define ICMP_TSTAMP 13 /* timestamp request */
#define ICMP_TSTAMPREPLY 14 /* timestamp reply */
#define ICMP_IREQ 15 /* information request */
#define ICMP_IREQREPLY 16 /* information reply */
#define ICMP_MASKREQ 17 /* address mask request */
#define ICMP_MASKREPLY 18 /* address mask reply */
#define ICMP_MAXTYPE 18
#define ICMP_ERRTYPE(type) \
((type) == ICMP_UNREACH || (type) == ICMP_SOURCEQUENCH || \
(type) == ICMP_REDIRECT || (type) == ICMP_TIMXCEED || \
(type) == ICMP_PARAMPROB)
#define ICMP_MULTIPART_EXT_TYPE(type) \
((type) == ICMP_UNREACH || \
(type) == ICMP_TIMXCEED || \
(type) == ICMP_PARAMPROB)
/* rfc1700 */
#ifndef ICMP_UNREACH_NET_UNKNOWN
#define ICMP_UNREACH_NET_UNKNOWN 6 /* destination net unknown */
#endif
#ifndef ICMP_UNREACH_HOST_UNKNOWN
#define ICMP_UNREACH_HOST_UNKNOWN 7 /* destination host unknown */
#endif
#ifndef ICMP_UNREACH_ISOLATED
#define ICMP_UNREACH_ISOLATED 8 /* source host isolated */
#endif
#ifndef ICMP_UNREACH_NET_PROHIB
#define ICMP_UNREACH_NET_PROHIB 9 /* admin prohibited net */
#endif
#ifndef ICMP_UNREACH_HOST_PROHIB
#define ICMP_UNREACH_HOST_PROHIB 10 /* admin prohibited host */
#endif
#ifndef ICMP_UNREACH_TOSNET
#define ICMP_UNREACH_TOSNET 11 /* tos prohibited net */
#endif
#ifndef ICMP_UNREACH_TOSHOST
#define ICMP_UNREACH_TOSHOST 12 /* tos prohibited host */
#endif
/* rfc1716 */
#ifndef ICMP_UNREACH_FILTER_PROHIB
#define ICMP_UNREACH_FILTER_PROHIB 13 /* admin prohibited filter */
#endif
#ifndef ICMP_UNREACH_HOST_PRECEDENCE
#define ICMP_UNREACH_HOST_PRECEDENCE 14 /* host precedence violation */
#endif
#ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF
#define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 /* precedence cutoff */
#endif
/* Most of the icmp types */
static const struct tok icmp2str[] = {
{ ICMP_ECHOREPLY, "echo reply" },
{ ICMP_SOURCEQUENCH, "source quench" },
{ ICMP_ECHO, "echo request" },
{ ICMP_ROUTERSOLICIT, "router solicitation" },
{ ICMP_TSTAMP, "time stamp request" },
{ ICMP_TSTAMPREPLY, "time stamp reply" },
{ ICMP_IREQ, "information request" },
{ ICMP_IREQREPLY, "information reply" },
{ ICMP_MASKREQ, "address mask request" },
{ 0, NULL }
};
/* rfc1191 */
struct mtu_discovery {
nd_uint16_t unused;
nd_uint16_t nexthopmtu;
};
/* rfc1256 */
struct ih_rdiscovery {
nd_uint8_t ird_addrnum;
nd_uint8_t ird_addrsiz;
nd_uint16_t ird_lifetime;
};
struct id_rdiscovery {
nd_uint32_t ird_addr;
nd_uint32_t ird_pref;
};
/*
* RFC 4884 - Extended ICMP to Support Multi-Part Messages
*
* This is a general extension mechanism, based on the mechanism
* in draft-bonica-icmp-mpls-02 ICMP Extensions for MultiProtocol
* Label Switching.
*
* The Destination Unreachable, Time Exceeded
* and Parameter Problem messages are slightly changed as per
* the above RFC. A new Length field gets added to give
* the caller an idea about the length of the piggybacked
* IP packet before the extension header starts.
*
* The Length field represents length of the padded "original datagram"
* field measured in 32-bit words.
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Type | Code | Checksum |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | unused | Length | unused |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Internet Header + leading octets of original datagram |
* | |
* | // |
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct icmp_ext_t {
nd_uint8_t icmp_type;
nd_uint8_t icmp_code;
nd_uint16_t icmp_checksum;
nd_byte icmp_reserved;
nd_uint8_t icmp_length;
nd_byte icmp_reserved2[2];
nd_byte icmp_ext_legacy_header[128]; /* extension header starts 128 bytes after ICMP header */
nd_byte icmp_ext_version_res[2];
nd_uint16_t icmp_ext_checksum;
nd_byte icmp_ext_data[1];
};
/*
* Extract version from the first octet of icmp_ext_version_res.
*/
#define ICMP_EXT_EXTRACT_VERSION(x) (((x)&0xf0)>>4)
/*
* Current version.
*/
#define ICMP_EXT_VERSION 2
/*
* Extension object class numbers.
*
* Class 1 dates back to draft-bonica-icmp-mpls-02.
*/
/* rfc4950 */
#define MPLS_STACK_ENTRY_OBJECT_CLASS 1
struct icmp_multipart_ext_object_header_t {
nd_uint16_t length;
nd_uint8_t class_num;
nd_uint8_t ctype;
};
static const struct tok icmp_multipart_ext_obj_values[] = {
{ 1, "MPLS Stack Entry" },
{ 2, "Interface Identification" },
{ 0, NULL}
};
/* prototypes */
const char *icmp_tstamp_print(u_int);
/* print the milliseconds since midnight UTC */
const char *
icmp_tstamp_print(u_int tstamp)
{
u_int msec,sec,min,hrs;
static char buf[64];
msec = tstamp % 1000;
sec = tstamp / 1000;
min = sec / 60; sec -= min * 60;
hrs = min / 60; min -= hrs * 60;
snprintf(buf, sizeof(buf), "%02u:%02u:%02u.%03u",hrs,min,sec,msec);
return buf;
}
void
icmp_print(netdissect_options *ndo, const u_char *bp, u_int plen, const u_char *bp2,
int fragmented)
{
char *cp;
const struct icmp *dp;
uint8_t icmp_type, icmp_code;
const struct icmp_ext_t *ext_dp;
const struct ip *ip;
const char *str;
const struct ip *oip;
uint8_t ip_proto;
const struct udphdr *ouh;
const uint8_t *obj_tptr;
uint32_t raw_label;
const struct icmp_multipart_ext_object_header_t *icmp_multipart_ext_object_header;
u_int hlen, mtu, obj_tlen, obj_class_num, obj_ctype;
uint16_t dport;
char buf[MAXHOSTNAMELEN + 100];
struct cksum_vec vec[1];
ndo->ndo_protocol = "icmp";
dp = (const struct icmp *)bp;
ext_dp = (const struct icmp_ext_t *)bp;
ip = (const struct ip *)bp2;
str = buf;
icmp_type = GET_U_1(dp->icmp_type);
icmp_code = GET_U_1(dp->icmp_code);
switch (icmp_type) {
case ICMP_ECHO:
case ICMP_ECHOREPLY:
(void)snprintf(buf, sizeof(buf), "echo %s, id %u, seq %u",
icmp_type == ICMP_ECHO ?
"request" : "reply",
GET_BE_U_2(dp->icmp_id),
GET_BE_U_2(dp->icmp_seq));
break;
case ICMP_UNREACH:
switch (icmp_code) {
case ICMP_UNREACH_NET:
(void)snprintf(buf, sizeof(buf),
"net %s unreachable",
GET_IPADDR_STRING(dp->icmp_ip.ip_dst));
break;
case ICMP_UNREACH_HOST:
(void)snprintf(buf, sizeof(buf),
"host %s unreachable",
GET_IPADDR_STRING(dp->icmp_ip.ip_dst));
break;
case ICMP_UNREACH_PROTOCOL:
(void)snprintf(buf, sizeof(buf),
"%s protocol %u unreachable",
GET_IPADDR_STRING(dp->icmp_ip.ip_dst),
GET_U_1(dp->icmp_ip.ip_p));
break;
case ICMP_UNREACH_PORT:
ND_TCHECK_1(dp->icmp_ip.ip_p);
oip = &dp->icmp_ip;
hlen = IP_HL(oip) * 4;
ouh = (const struct udphdr *)(((const u_char *)oip) + hlen);
dport = GET_BE_U_2(ouh->uh_dport);
ip_proto = GET_U_1(oip->ip_p);
switch (ip_proto) {
case IPPROTO_TCP:
(void)snprintf(buf, sizeof(buf),
"%s tcp port %s unreachable",
GET_IPADDR_STRING(oip->ip_dst),
tcpport_string(ndo, dport));
break;
case IPPROTO_UDP:
(void)snprintf(buf, sizeof(buf),
"%s udp port %s unreachable",
GET_IPADDR_STRING(oip->ip_dst),
udpport_string(ndo, dport));
break;
default:
(void)snprintf(buf, sizeof(buf),
"%s protocol %u port %u unreachable",
GET_IPADDR_STRING(oip->ip_dst),
ip_proto, dport);
break;
}
break;
case ICMP_UNREACH_NEEDFRAG:
{
const struct mtu_discovery *mp;
mp = (const struct mtu_discovery *)(const u_char *)&dp->icmp_void;
mtu = GET_BE_U_2(mp->nexthopmtu);
if (mtu) {
(void)snprintf(buf, sizeof(buf),
"%s unreachable - need to frag (mtu %u)",
GET_IPADDR_STRING(dp->icmp_ip.ip_dst), mtu);
} else {
(void)snprintf(buf, sizeof(buf),
"%s unreachable - need to frag",
GET_IPADDR_STRING(dp->icmp_ip.ip_dst));
}
}
break;
case ICMP_UNREACH_SRCFAIL:
(void)snprintf(buf, sizeof(buf),
"%s unreachable - source route failed",
GET_IPADDR_STRING(dp->icmp_ip.ip_dst));
break;
case ICMP_UNREACH_NET_UNKNOWN:
(void)snprintf(buf, sizeof(buf),
"net %s unreachable - unknown",
GET_IPADDR_STRING(dp->icmp_ip.ip_dst));
break;
case ICMP_UNREACH_HOST_UNKNOWN:
(void)snprintf(buf, sizeof(buf),
"host %s unreachable - unknown",
GET_IPADDR_STRING(dp->icmp_ip.ip_dst));
break;
case ICMP_UNREACH_ISOLATED:
(void)snprintf(buf, sizeof(buf),
"%s unreachable - source host isolated",
GET_IPADDR_STRING(dp->icmp_ip.ip_dst));
break;
case ICMP_UNREACH_NET_PROHIB:
(void)snprintf(buf, sizeof(buf),
"net %s unreachable - admin prohibited",
GET_IPADDR_STRING(dp->icmp_ip.ip_dst));
break;
case ICMP_UNREACH_HOST_PROHIB:
(void)snprintf(buf, sizeof(buf),
"host %s unreachable - admin prohibited",
GET_IPADDR_STRING(dp->icmp_ip.ip_dst));
break;
case ICMP_UNREACH_TOSNET:
(void)snprintf(buf, sizeof(buf),
"net %s unreachable - tos prohibited",
GET_IPADDR_STRING(dp->icmp_ip.ip_dst));
break;
case ICMP_UNREACH_TOSHOST:
(void)snprintf(buf, sizeof(buf),
"host %s unreachable - tos prohibited",
GET_IPADDR_STRING(dp->icmp_ip.ip_dst));
break;
case ICMP_UNREACH_FILTER_PROHIB:
(void)snprintf(buf, sizeof(buf),
"host %s unreachable - admin prohibited filter",
GET_IPADDR_STRING(dp->icmp_ip.ip_dst));
break;
case ICMP_UNREACH_HOST_PRECEDENCE:
(void)snprintf(buf, sizeof(buf),
"host %s unreachable - host precedence violation",
GET_IPADDR_STRING(dp->icmp_ip.ip_dst));
break;
case ICMP_UNREACH_PRECEDENCE_CUTOFF:
(void)snprintf(buf, sizeof(buf),
"host %s unreachable - precedence cutoff",
GET_IPADDR_STRING(dp->icmp_ip.ip_dst));
break;
default:
(void)snprintf(buf, sizeof(buf),
"%s unreachable - #%u",
GET_IPADDR_STRING(dp->icmp_ip.ip_dst),
icmp_code);
break;
}
break;
case ICMP_REDIRECT:
switch (icmp_code) {
case ICMP_REDIRECT_NET:
(void)snprintf(buf, sizeof(buf),
"redirect %s to net %s",
GET_IPADDR_STRING(dp->icmp_ip.ip_dst),
GET_IPADDR_STRING(dp->icmp_gwaddr));
break;
case ICMP_REDIRECT_HOST:
(void)snprintf(buf, sizeof(buf),
"redirect %s to host %s",
GET_IPADDR_STRING(dp->icmp_ip.ip_dst),
GET_IPADDR_STRING(dp->icmp_gwaddr));
break;
case ICMP_REDIRECT_TOSNET:
(void)snprintf(buf, sizeof(buf),
"redirect-tos %s to net %s",
GET_IPADDR_STRING(dp->icmp_ip.ip_dst),
GET_IPADDR_STRING(dp->icmp_gwaddr));
break;
case ICMP_REDIRECT_TOSHOST:
(void)snprintf(buf, sizeof(buf),
"redirect-tos %s to host %s",
GET_IPADDR_STRING(dp->icmp_ip.ip_dst),
GET_IPADDR_STRING(dp->icmp_gwaddr));
break;
default:
(void)snprintf(buf, sizeof(buf),
"redirect-#%u %s to %s", icmp_code,
GET_IPADDR_STRING(dp->icmp_ip.ip_dst),
GET_IPADDR_STRING(dp->icmp_gwaddr));
break;
}
break;
case ICMP_ROUTERADVERT:
{
const struct ih_rdiscovery *ihp;
const struct id_rdiscovery *idp;
u_int lifetime, num, size;
(void)snprintf(buf, sizeof(buf), "router advertisement");
cp = buf + strlen(buf);
ihp = (const struct ih_rdiscovery *)&dp->icmp_void;
ND_TCHECK_SIZE(ihp);
(void)strncpy(cp, " lifetime ", sizeof(buf) - (cp - buf));
cp = buf + strlen(buf);
lifetime = GET_BE_U_2(ihp->ird_lifetime);
if (lifetime < 60) {
(void)snprintf(cp, sizeof(buf) - (cp - buf), "%u",
lifetime);
} else if (lifetime < 60 * 60) {
(void)snprintf(cp, sizeof(buf) - (cp - buf), "%u:%02u",
lifetime / 60, lifetime % 60);
} else {
(void)snprintf(cp, sizeof(buf) - (cp - buf),
"%u:%02u:%02u",
lifetime / 3600,
(lifetime % 3600) / 60,
lifetime % 60);
}
cp = buf + strlen(buf);
num = GET_U_1(ihp->ird_addrnum);
(void)snprintf(cp, sizeof(buf) - (cp - buf), " %u:", num);
cp = buf + strlen(buf);
size = GET_U_1(ihp->ird_addrsiz);
if (size != 2) {
(void)snprintf(cp, sizeof(buf) - (cp - buf),
" [size %u]", size);
break;
}
idp = (const struct id_rdiscovery *)&dp->icmp_data;
while (num > 0) {
ND_TCHECK_SIZE(idp);
(void)snprintf(cp, sizeof(buf) - (cp - buf), " {%s %u}",
GET_IPADDR_STRING(idp->ird_addr),
GET_BE_U_4(idp->ird_pref));
cp = buf + strlen(buf);
++idp;
num--;
}
}
break;
case ICMP_TIMXCEED:
ND_TCHECK_4(dp->icmp_ip.ip_dst);
switch (icmp_code) {
case ICMP_TIMXCEED_INTRANS:
str = "time exceeded in-transit";
break;
case ICMP_TIMXCEED_REASS:
str = "ip reassembly time exceeded";
break;
default:
(void)snprintf(buf, sizeof(buf), "time exceeded-#%u",
icmp_code);
break;
}
break;
case ICMP_PARAMPROB:
if (icmp_code)
(void)snprintf(buf, sizeof(buf),
"parameter problem - code %u", icmp_code);
else {
(void)snprintf(buf, sizeof(buf),
"parameter problem - octet %u",
GET_U_1(dp->icmp_pptr));
}
break;
case ICMP_MASKREPLY:
(void)snprintf(buf, sizeof(buf), "address mask is 0x%08x",
GET_BE_U_4(dp->icmp_mask));
break;
case ICMP_TSTAMP:
(void)snprintf(buf, sizeof(buf),
"time stamp query id %u seq %u",
GET_BE_U_2(dp->icmp_id),
GET_BE_U_2(dp->icmp_seq));
break;
case ICMP_TSTAMPREPLY:
ND_TCHECK_4(dp->icmp_ttime);
(void)snprintf(buf, sizeof(buf),
"time stamp reply id %u seq %u: org %s",
GET_BE_U_2(dp->icmp_id),
GET_BE_U_2(dp->icmp_seq),
icmp_tstamp_print(GET_BE_U_4(dp->icmp_otime)));
(void)snprintf(buf+strlen(buf),sizeof(buf)-strlen(buf),", recv %s",
icmp_tstamp_print(GET_BE_U_4(dp->icmp_rtime)));
(void)snprintf(buf+strlen(buf),sizeof(buf)-strlen(buf),", xmit %s",
icmp_tstamp_print(GET_BE_U_4(dp->icmp_ttime)));
break;
default:
str = tok2str(icmp2str, "type-#%u", icmp_type);
break;
}
ND_PRINT("ICMP %s, length %u", str, plen);
if (ndo->ndo_vflag && !fragmented) { /* don't attempt checksumming if this is a frag */
if (ND_TTEST_LEN(bp, plen)) {
uint16_t sum;
vec[0].ptr = (const uint8_t *)(const void *)dp;
vec[0].len = plen;
sum = in_cksum(vec, 1);
if (sum != 0) {
uint16_t icmp_sum = GET_BE_U_2(dp->icmp_cksum);
ND_PRINT(" (wrong icmp cksum %x (->%x)!)",
icmp_sum,
in_cksum_shouldbe(icmp_sum, sum));
}
}
}
/*
* print the remnants of the IP packet.
* save the snaplength as this may get overridden in the IP printer.
*/
if (ndo->ndo_vflag >= 1 && ICMP_ERRTYPE(icmp_type)) {
const u_char *snapend_save;
bp += 8;
ND_PRINT("\n\t");
ip = (const struct ip *)bp;
snapend_save = ndo->ndo_snapend;
/*
* Update the snapend because extensions (MPLS, ...) may be
* present after the IP packet. In this case the current
* (outer) packet's snapend is not what ip_print() needs to
* decode an IP packet nested in the middle of an ICMP payload.
*
* This prevents that, in ip_print(), for the nested IP packet,
* the remaining length < remaining caplen.
*/
ndo->ndo_snapend = ND_MIN(bp + GET_BE_U_2(ip->ip_len),
ndo->ndo_snapend);
ip_print(ndo, bp, GET_BE_U_2(ip->ip_len));
ndo->ndo_snapend = snapend_save;
}
/* ndo_protocol reassignment after ip_print() call */
ndo->ndo_protocol = "icmp";
/*
* Attempt to decode multi-part message extensions (rfc4884) only for some ICMP types.
*/
if (ndo->ndo_vflag >= 1 && plen > ICMP_EXTD_MINLEN && ICMP_MULTIPART_EXT_TYPE(icmp_type)) {
ND_TCHECK_SIZE(ext_dp);
/*
* Check first if the multi-part extension header shows a non-zero length.
* If the length field is not set then silently verify the checksum
* to check if an extension header is present. This is expedient,
* however not all implementations set the length field proper.
*/
if (GET_U_1(ext_dp->icmp_length) == 0 &&
ND_TTEST_LEN(ext_dp->icmp_ext_version_res, plen - ICMP_EXTD_MINLEN)) {
vec[0].ptr = (const uint8_t *)(const void *)&ext_dp->icmp_ext_version_res;
vec[0].len = plen - ICMP_EXTD_MINLEN;
if (in_cksum(vec, 1)) {
return;
}
}
ND_PRINT("\n\tICMP Multi-Part extension v%u",
ICMP_EXT_EXTRACT_VERSION(*(ext_dp->icmp_ext_version_res)));
/*
* Sanity checking of the header.
*/
if (ICMP_EXT_EXTRACT_VERSION(*(ext_dp->icmp_ext_version_res)) !=
ICMP_EXT_VERSION) {
ND_PRINT(" packet not supported");
return;
}
hlen = plen - ICMP_EXTD_MINLEN;
if (ND_TTEST_LEN(ext_dp->icmp_ext_version_res, hlen)) {
vec[0].ptr = (const uint8_t *)(const void *)&ext_dp->icmp_ext_version_res;
vec[0].len = hlen;
ND_PRINT(", checksum 0x%04x (%scorrect), length %u",
GET_BE_U_2(ext_dp->icmp_ext_checksum),
in_cksum(vec, 1) ? "in" : "",
hlen);
}
hlen -= 4; /* subtract common header size */
obj_tptr = (const uint8_t *)ext_dp->icmp_ext_data;
while (hlen > sizeof(struct icmp_multipart_ext_object_header_t)) {
icmp_multipart_ext_object_header = (const struct icmp_multipart_ext_object_header_t *)obj_tptr;
ND_TCHECK_SIZE(icmp_multipart_ext_object_header);
obj_tlen = GET_BE_U_2(icmp_multipart_ext_object_header->length);
obj_class_num = GET_U_1(icmp_multipart_ext_object_header->class_num);
obj_ctype = GET_U_1(icmp_multipart_ext_object_header->ctype);
obj_tptr += sizeof(struct icmp_multipart_ext_object_header_t);
ND_PRINT("\n\t %s Object (%u), Class-Type: %u, length %u",
tok2str(icmp_multipart_ext_obj_values,"unknown",obj_class_num),
obj_class_num,
obj_ctype,
obj_tlen);
hlen-=sizeof(struct icmp_multipart_ext_object_header_t); /* length field includes tlv header */
/* infinite loop protection */
if ((obj_class_num == 0) ||
(obj_tlen < sizeof(struct icmp_multipart_ext_object_header_t))) {
return;
}
obj_tlen-=sizeof(struct icmp_multipart_ext_object_header_t);
switch (obj_class_num) {
case MPLS_STACK_ENTRY_OBJECT_CLASS:
switch(obj_ctype) {
case 1:
raw_label = GET_BE_U_4(obj_tptr);
ND_PRINT("\n\t label %u, tc %u", MPLS_LABEL(raw_label), MPLS_TC(raw_label));
if (MPLS_STACK(raw_label))
ND_PRINT(", [S]");
ND_PRINT(", ttl %u", MPLS_TTL(raw_label));
break;
default:
print_unknown_data(ndo, obj_tptr, "\n\t ", obj_tlen);
}
break;
default:
print_unknown_data(ndo, obj_tptr, "\n\t ", obj_tlen);
break;
}
if (hlen < obj_tlen)
break;
hlen -= obj_tlen;
obj_tptr += obj_tlen;
}
}
return;
trunc:
nd_print_trunc(ndo);
}
diff --git a/contrib/tcpdump/print-icmp6.c b/contrib/tcpdump/print-icmp6.c
index 4738e77a9e75..e67b19b40bdc 100644
--- a/contrib/tcpdump/print-icmp6.c
+++ b/contrib/tcpdump/print-icmp6.c
@@ -1,2082 +1,2079 @@
/*
* Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994
* 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.
*/
/* \summary: IPv6 Internet Control Message Protocol (ICMPv6) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <stdio.h>
#include <string.h>
#include "netdissect.h"
#include "addrtoname.h"
#include "addrtostr.h"
#include "extract.h"
#include "ip6.h"
#include "ipproto.h"
#include "udp.h"
#include "ah.h"
/* NetBSD: icmp6.h,v 1.13 2000/08/03 16:30:37 itojun Exp */
/* $KAME: icmp6.h,v 1.22 2000/08/03 15:25:16 jinmei Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
struct icmp6_hdr {
nd_uint8_t icmp6_type; /* type field */
nd_uint8_t icmp6_code; /* code field */
nd_uint16_t icmp6_cksum; /* checksum field */
union {
nd_uint32_t icmp6_un_data32[1]; /* type-specific field */
nd_uint16_t icmp6_un_data16[2]; /* type-specific field */
nd_uint8_t icmp6_un_data8[4]; /* type-specific field */
nd_byte icmp6_un_data[1]; /* type-specific field */
} icmp6_dataun;
};
#define icmp6_data32 icmp6_dataun.icmp6_un_data32
#define icmp6_data16 icmp6_dataun.icmp6_un_data16
#define icmp6_data8 icmp6_dataun.icmp6_un_data8
#define icmp6_data icmp6_dataun.icmp6_un_data
#define icmp6_pptr icmp6_data32[0] /* parameter prob */
#define icmp6_mtu icmp6_data32[0] /* packet too big */
#define icmp6_id icmp6_data16[0] /* echo request/reply */
#define icmp6_seq icmp6_data16[1] /* echo request/reply */
#define icmp6_maxdelay icmp6_data16[0] /* mcast group membership */
#define ICMP6_DST_UNREACH 1 /* dest unreachable, codes: */
#define ICMP6_PACKET_TOO_BIG 2 /* packet too big */
#define ICMP6_TIME_EXCEEDED 3 /* time exceeded, code: */
#define ICMP6_PARAM_PROB 4 /* ip6 header bad */
#define ICMP6_ECHO_REQUEST 128 /* echo service */
#define ICMP6_ECHO_REPLY 129 /* echo reply */
#define ICMP6_MEMBERSHIP_QUERY 130 /* group membership query */
#define MLD6_LISTENER_QUERY 130 /* multicast listener query */
#define ICMP6_MEMBERSHIP_REPORT 131 /* group membership report */
#define MLD6_LISTENER_REPORT 131 /* multicast listener report */
#define ICMP6_MEMBERSHIP_REDUCTION 132 /* group membership termination */
#define MLD6_LISTENER_DONE 132 /* multicast listener done */
#define ND_ROUTER_SOLICIT 133 /* router solicitation */
#define ND_ROUTER_ADVERT 134 /* router advertisement */
#define ND_NEIGHBOR_SOLICIT 135 /* neighbor solicitation */
#define ND_NEIGHBOR_ADVERT 136 /* neighbor advertisement */
#define ND_REDIRECT 137 /* redirect */
#define ICMP6_ROUTER_RENUMBERING 138 /* router renumbering */
#define ICMP6_WRUREQUEST 139 /* who are you request */
#define ICMP6_WRUREPLY 140 /* who are you reply */
#define ICMP6_FQDN_QUERY 139 /* FQDN query */
#define ICMP6_FQDN_REPLY 140 /* FQDN reply */
#define ICMP6_NI_QUERY 139 /* node information request - RFC 4620 */
#define ICMP6_NI_REPLY 140 /* node information reply - RFC 4620 */
#define IND_SOLICIT 141 /* inverse neighbor solicitation */
#define IND_ADVERT 142 /* inverse neighbor advertisement */
#define ICMP6_V2_MEMBERSHIP_REPORT 143 /* v2 membership report */
#define MLDV2_LISTENER_REPORT 143 /* v2 multicast listener report */
#define ICMP6_HADISCOV_REQUEST 144
#define ICMP6_HADISCOV_REPLY 145
#define ICMP6_MOBILEPREFIX_SOLICIT 146
#define ICMP6_MOBILEPREFIX_ADVERT 147
#define MLD6_MTRACE_RESP 200 /* mtrace response(to sender) */
#define MLD6_MTRACE 201 /* mtrace messages */
#define ICMP6_MAXTYPE 201
#define ICMP6_DST_UNREACH_NOROUTE 0 /* no route to destination */
#define ICMP6_DST_UNREACH_ADMIN 1 /* administratively prohibited */
#define ICMP6_DST_UNREACH_NOTNEIGHBOR 2 /* not a neighbor(obsolete) */
#define ICMP6_DST_UNREACH_BEYONDSCOPE 2 /* beyond scope of source address */
#define ICMP6_DST_UNREACH_ADDR 3 /* address unreachable */
#define ICMP6_DST_UNREACH_NOPORT 4 /* port unreachable */
#define ICMP6_TIME_EXCEED_TRANSIT 0 /* ttl==0 in transit */
#define ICMP6_TIME_EXCEED_REASSEMBLY 1 /* ttl==0 in reass */
#define ICMP6_PARAMPROB_HEADER 0 /* erroneous header field */
#define ICMP6_PARAMPROB_NEXTHEADER 1 /* unrecognized next header */
#define ICMP6_PARAMPROB_OPTION 2 /* unrecognized option */
#define ICMP6_PARAMPROB_FRAGHDRCHAIN 3 /* incomplete header chain */
#define ICMP6_INFOMSG_MASK 0x80 /* all informational messages */
#define ICMP6_NI_SUBJ_IPV6 0 /* Query Subject is an IPv6 address */
#define ICMP6_NI_SUBJ_FQDN 1 /* Query Subject is a Domain name */
#define ICMP6_NI_SUBJ_IPV4 2 /* Query Subject is an IPv4 address */
#define ICMP6_NI_SUCCESS 0 /* node information successful reply */
#define ICMP6_NI_REFUSED 1 /* node information request is refused */
#define ICMP6_NI_UNKNOWN 2 /* unknown Qtype */
#define ICMP6_ROUTER_RENUMBERING_COMMAND 0 /* rr command */
#define ICMP6_ROUTER_RENUMBERING_RESULT 1 /* rr result */
#define ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET 255 /* rr seq num reset */
/* Used in kernel only */
#define ND_REDIRECT_ONLINK 0 /* redirect to an on-link node */
#define ND_REDIRECT_ROUTER 1 /* redirect to a better router */
/*
* Multicast Listener Discovery
*/
struct mld6_hdr {
struct icmp6_hdr mld6_hdr;
nd_ipv6 mld6_addr; /* multicast address */
};
#define mld6_type mld6_hdr.icmp6_type
#define mld6_code mld6_hdr.icmp6_code
#define mld6_cksum mld6_hdr.icmp6_cksum
#define mld6_maxdelay mld6_hdr.icmp6_data16[0]
#define mld6_reserved mld6_hdr.icmp6_data16[1]
#define MLD_MINLEN 24
#define MLDV2_MINLEN 28
/*
* Neighbor Discovery
*/
struct nd_router_solicit { /* router solicitation */
struct icmp6_hdr nd_rs_hdr;
/* could be followed by options */
};
#define nd_rs_type nd_rs_hdr.icmp6_type
#define nd_rs_code nd_rs_hdr.icmp6_code
#define nd_rs_cksum nd_rs_hdr.icmp6_cksum
#define nd_rs_reserved nd_rs_hdr.icmp6_data32[0]
struct nd_router_advert { /* router advertisement */
struct icmp6_hdr nd_ra_hdr;
nd_uint32_t nd_ra_reachable; /* reachable time */
nd_uint32_t nd_ra_retransmit; /* retransmit timer */
/* could be followed by options */
};
#define nd_ra_type nd_ra_hdr.icmp6_type
#define nd_ra_code nd_ra_hdr.icmp6_code
#define nd_ra_cksum nd_ra_hdr.icmp6_cksum
#define nd_ra_curhoplimit nd_ra_hdr.icmp6_data8[0]
#define nd_ra_flags_reserved nd_ra_hdr.icmp6_data8[1]
#define ND_RA_FLAG_MANAGED 0x80
#define ND_RA_FLAG_OTHER 0x40
#define ND_RA_FLAG_HOME_AGENT 0x20
#define ND_RA_FLAG_IPV6ONLY 0x02
/*
* Router preference values based on draft-draves-ipngwg-router-selection-01.
* These are non-standard definitions.
*/
#define ND_RA_FLAG_RTPREF_MASK 0x18 /* 00011000 */
#define ND_RA_FLAG_RTPREF_HIGH 0x08 /* 00001000 */
#define ND_RA_FLAG_RTPREF_MEDIUM 0x00 /* 00000000 */
#define ND_RA_FLAG_RTPREF_LOW 0x18 /* 00011000 */
#define ND_RA_FLAG_RTPREF_RSV 0x10 /* 00010000 */
#define nd_ra_router_lifetime nd_ra_hdr.icmp6_data16[1]
struct nd_neighbor_solicit { /* neighbor solicitation */
struct icmp6_hdr nd_ns_hdr;
nd_ipv6 nd_ns_target; /*target address */
/* could be followed by options */
};
#define nd_ns_type nd_ns_hdr.icmp6_type
#define nd_ns_code nd_ns_hdr.icmp6_code
#define nd_ns_cksum nd_ns_hdr.icmp6_cksum
#define nd_ns_reserved nd_ns_hdr.icmp6_data32[0]
struct nd_neighbor_advert { /* neighbor advertisement */
struct icmp6_hdr nd_na_hdr;
nd_ipv6 nd_na_target; /* target address */
/* could be followed by options */
};
#define nd_na_type nd_na_hdr.icmp6_type
#define nd_na_code nd_na_hdr.icmp6_code
#define nd_na_cksum nd_na_hdr.icmp6_cksum
#define nd_na_flags_reserved nd_na_hdr.icmp6_data32[0]
#define ND_NA_FLAG_ROUTER 0x80000000
#define ND_NA_FLAG_SOLICITED 0x40000000
#define ND_NA_FLAG_OVERRIDE 0x20000000
struct nd_redirect { /* redirect */
struct icmp6_hdr nd_rd_hdr;
nd_ipv6 nd_rd_target; /* target address */
nd_ipv6 nd_rd_dst; /* destination address */
/* could be followed by options */
};
#define nd_rd_type nd_rd_hdr.icmp6_type
#define nd_rd_code nd_rd_hdr.icmp6_code
#define nd_rd_cksum nd_rd_hdr.icmp6_cksum
#define nd_rd_reserved nd_rd_hdr.icmp6_data32[0]
struct nd_opt_hdr { /* Neighbor discovery option header */
nd_uint8_t nd_opt_type;
nd_uint8_t nd_opt_len;
/* followed by option specific data*/
};
#define ND_OPT_SOURCE_LINKADDR 1
#define ND_OPT_TARGET_LINKADDR 2
#define ND_OPT_PREFIX_INFORMATION 3
#define ND_OPT_REDIRECTED_HEADER 4
#define ND_OPT_MTU 5
#define ND_OPT_ADVINTERVAL 7
#define ND_OPT_HOMEAGENT_INFO 8
#define ND_OPT_ROUTE_INFO 24 /* RFC4191 */
#define ND_OPT_RDNSS 25
#define ND_OPT_DNSSL 31
struct nd_opt_prefix_info { /* prefix information */
nd_uint8_t nd_opt_pi_type;
nd_uint8_t nd_opt_pi_len;
nd_uint8_t nd_opt_pi_prefix_len;
nd_uint8_t nd_opt_pi_flags_reserved;
nd_uint32_t nd_opt_pi_valid_time;
nd_uint32_t nd_opt_pi_preferred_time;
nd_uint32_t nd_opt_pi_reserved2;
nd_ipv6 nd_opt_pi_prefix;
};
#define ND_OPT_PI_FLAG_ONLINK 0x80
#define ND_OPT_PI_FLAG_AUTO 0x40
#define ND_OPT_PI_FLAG_ROUTER 0x20 /*2292bis*/
struct nd_opt_rd_hdr { /* redirected header */
nd_uint8_t nd_opt_rh_type;
nd_uint8_t nd_opt_rh_len;
nd_uint16_t nd_opt_rh_reserved1;
nd_uint32_t nd_opt_rh_reserved2;
/* followed by IP header and data */
};
struct nd_opt_mtu { /* MTU option */
nd_uint8_t nd_opt_mtu_type;
nd_uint8_t nd_opt_mtu_len;
nd_uint16_t nd_opt_mtu_reserved;
nd_uint32_t nd_opt_mtu_mtu;
};
struct nd_opt_rdnss { /* RDNSS RFC 6106 5.1 */
nd_uint8_t nd_opt_rdnss_type;
nd_uint8_t nd_opt_rdnss_len;
nd_uint16_t nd_opt_rdnss_reserved;
nd_uint32_t nd_opt_rdnss_lifetime;
nd_ipv6 nd_opt_rdnss_addr[1]; /* variable-length */
};
struct nd_opt_dnssl { /* DNSSL RFC 6106 5.2 */
nd_uint8_t nd_opt_dnssl_type;
nd_uint8_t nd_opt_dnssl_len;
nd_uint16_t nd_opt_dnssl_reserved;
nd_uint32_t nd_opt_dnssl_lifetime;
/* followed by list of DNS search domains, variable-length */
};
struct nd_opt_advinterval { /* Advertisement interval option */
nd_uint8_t nd_opt_adv_type;
nd_uint8_t nd_opt_adv_len;
nd_uint16_t nd_opt_adv_reserved;
nd_uint32_t nd_opt_adv_interval;
};
struct nd_opt_homeagent_info { /* Home Agent info */
nd_uint8_t nd_opt_hai_type;
nd_uint8_t nd_opt_hai_len;
nd_uint16_t nd_opt_hai_reserved;
nd_uint16_t nd_opt_hai_preference;
nd_uint16_t nd_opt_hai_lifetime;
};
struct nd_opt_route_info { /* route info */
nd_uint8_t nd_opt_rti_type;
nd_uint8_t nd_opt_rti_len;
nd_uint8_t nd_opt_rti_prefixlen;
nd_uint8_t nd_opt_rti_flags;
nd_uint32_t nd_opt_rti_lifetime;
/* prefix follows */
};
/*
* icmp6 namelookup
*/
struct icmp6_namelookup {
struct icmp6_hdr icmp6_nl_hdr;
nd_byte icmp6_nl_nonce[8];
nd_int32_t icmp6_nl_ttl;
#if 0
nd_uint8_t icmp6_nl_len;
nd_byte icmp6_nl_name[3];
#endif
/* could be followed by options */
};
/*
* icmp6 node information
*/
struct icmp6_nodeinfo {
struct icmp6_hdr icmp6_ni_hdr;
nd_byte icmp6_ni_nonce[8];
/* could be followed by reply data */
};
#define ni_type icmp6_ni_hdr.icmp6_type
#define ni_code icmp6_ni_hdr.icmp6_code
#define ni_cksum icmp6_ni_hdr.icmp6_cksum
#define ni_qtype icmp6_ni_hdr.icmp6_data16[0]
#define ni_flags icmp6_ni_hdr.icmp6_data16[1]
#define NI_QTYPE_NOOP 0 /* NOOP */
#define NI_QTYPE_SUPTYPES 1 /* Supported Qtypes (drafts up to 09) */
#define NI_QTYPE_FQDN 2 /* FQDN (draft 04) */
#define NI_QTYPE_DNSNAME 2 /* DNS Name */
#define NI_QTYPE_NODEADDR 3 /* Node Addresses */
#define NI_QTYPE_IPV4ADDR 4 /* IPv4 Addresses */
#define NI_NODEADDR_FLAG_TRUNCATE 0x0001
#define NI_NODEADDR_FLAG_ALL 0x0002
#define NI_NODEADDR_FLAG_COMPAT 0x0004
#define NI_NODEADDR_FLAG_LINKLOCAL 0x0008
#define NI_NODEADDR_FLAG_SITELOCAL 0x0010
#define NI_NODEADDR_FLAG_GLOBAL 0x0020
#define NI_NODEADDR_FLAG_ANYCAST 0x0040 /* just experimental. not in spec */
struct ni_reply_fqdn {
nd_uint32_t ni_fqdn_ttl; /* TTL */
nd_uint8_t ni_fqdn_namelen; /* length in octets of the FQDN */
nd_byte ni_fqdn_name[3]; /* XXX: alignment */
};
/*
* Router Renumbering. as router-renum-08.txt
*/
struct icmp6_router_renum { /* router renumbering header */
struct icmp6_hdr rr_hdr;
nd_uint8_t rr_segnum;
nd_uint8_t rr_flags;
nd_uint16_t rr_maxdelay;
nd_uint32_t rr_reserved;
};
#define ICMP6_RR_FLAGS_TEST 0x80
#define ICMP6_RR_FLAGS_REQRESULT 0x40
#define ICMP6_RR_FLAGS_FORCEAPPLY 0x20
#define ICMP6_RR_FLAGS_SPECSITE 0x10
#define ICMP6_RR_FLAGS_PREVDONE 0x08
#define rr_type rr_hdr.icmp6_type
#define rr_code rr_hdr.icmp6_code
#define rr_cksum rr_hdr.icmp6_cksum
#define rr_seqnum rr_hdr.icmp6_data32[0]
struct rr_pco_match { /* match prefix part */
nd_uint8_t rpm_code;
nd_uint8_t rpm_len;
nd_uint8_t rpm_ordinal;
nd_uint8_t rpm_matchlen;
nd_uint8_t rpm_minlen;
nd_uint8_t rpm_maxlen;
nd_uint16_t rpm_reserved;
nd_ipv6 rpm_prefix;
};
#define RPM_PCO_ADD 1
#define RPM_PCO_CHANGE 2
#define RPM_PCO_SETGLOBAL 3
#define RPM_PCO_MAX 4
struct rr_pco_use { /* use prefix part */
nd_uint8_t rpu_uselen;
nd_uint8_t rpu_keeplen;
nd_uint8_t rpu_ramask;
nd_uint8_t rpu_raflags;
nd_uint32_t rpu_vltime;
nd_uint32_t rpu_pltime;
nd_uint32_t rpu_flags;
nd_ipv6 rpu_prefix;
};
#define ICMP6_RR_PCOUSE_RAFLAGS_ONLINK 0x80
#define ICMP6_RR_PCOUSE_RAFLAGS_AUTO 0x40
/* network endian */
#define ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME ((uint32_t)htonl(0x80000000))
#define ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME ((uint32_t)htonl(0x40000000))
struct rr_result { /* router renumbering result message */
nd_uint16_t rrr_flags;
nd_uint8_t rrr_ordinal;
nd_uint8_t rrr_matchedlen;
nd_uint32_t rrr_ifid;
nd_ipv6 rrr_prefix;
};
/* network endian */
#define ICMP6_RR_RESULT_FLAGS_OOB ((uint16_t)htons(0x0002))
#define ICMP6_RR_RESULT_FLAGS_FORBIDDEN ((uint16_t)htons(0x0001))
static const char *get_rtpref(u_int);
static const char *get_lifetime(uint32_t);
static void print_lladdr(netdissect_options *ndo, const u_char *, size_t);
static int icmp6_opt_print(netdissect_options *ndo, const u_char *, int);
static void mld6_print(netdissect_options *ndo, const u_char *);
static void mldv2_report_print(netdissect_options *ndo, const u_char *, u_int);
static void mldv2_query_print(netdissect_options *ndo, const u_char *, u_int);
static const struct udphdr *get_upperlayer(netdissect_options *ndo, const u_char *, u_int *);
static void dnsname_print(netdissect_options *ndo, const u_char *, const u_char *);
static void icmp6_nodeinfo_print(netdissect_options *ndo, u_int, const u_char *, const u_char *);
static void icmp6_rrenum_print(netdissect_options *ndo, const u_char *, const u_char *);
/*
* DIO: Updated to RFC6550, as published in 2012: section 6. (page 30)
*/
#define ND_RPL_MESSAGE 155 /* 0x9B */
enum ND_RPL_CODE {
ND_RPL_DAG_IS=0x00,
ND_RPL_DAG_IO=0x01,
ND_RPL_DAO =0x02,
ND_RPL_DAO_ACK=0x03,
ND_RPL_SEC_DAG_IS = 0x80,
ND_RPL_SEC_DAG_IO = 0x81,
ND_RPL_SEC_DAG = 0x82,
ND_RPL_SEC_DAG_ACK= 0x83,
ND_RPL_SEC_CONSIST= 0x8A
};
enum ND_RPL_DIO_FLAGS {
ND_RPL_DIO_GROUNDED = 0x80,
ND_RPL_DIO_DATRIG = 0x40,
ND_RPL_DIO_DASUPPORT= 0x20,
ND_RPL_DIO_RES4 = 0x10,
ND_RPL_DIO_RES3 = 0x08,
ND_RPL_DIO_PRF_MASK = 0x07 /* 3-bit preference */
};
#define DAGID_LEN 16
/* section 6 of draft-ietf-roll-rpl-19 */
struct nd_rpl_security {
nd_uint8_t rpl_sec_t_reserved; /* bit 7 is T-bit */
nd_uint8_t rpl_sec_algo;
nd_uint16_t rpl_sec_kim_lvl_flags; /* bit 15/14, KIM */
/* bit 10-8, LVL, bit 7-0 flags */
nd_uint32_t rpl_sec_counter;
#if 0
nd_byte rpl_sec_ki[0]; /* depends upon kim */
#endif
};
-/* section 6.2.1, DODAG Information Solication (DIS_IS) */
+/* section 6.2.1, DODAG Information Solicitation (DIS_IS) */
struct nd_rpl_dis_is {
nd_uint8_t rpl_dis_flags;
nd_uint8_t rpl_dis_reserved;
#if 0
nd_byte rpl_dis_options[0];
#endif
};
/* section 6.3.1, DODAG Information Object (DIO) */
struct nd_rpl_dio {
nd_uint8_t rpl_instanceid;
nd_uint8_t rpl_version;
nd_uint16_t rpl_dagrank;
nd_uint8_t rpl_mopprf; /* bit 7=G, 5-3=MOP, 2-0=PRF */
nd_uint8_t rpl_dtsn; /* Dest. Advertisement Trigger Sequence Number */
nd_uint8_t rpl_flags; /* no flags defined yet */
nd_uint8_t rpl_resv1;
nd_byte rpl_dagid[DAGID_LEN];
};
#define RPL_DIO_GROUND_FLAG 0x80
#define RPL_DIO_MOP_SHIFT 3
#define RPL_DIO_MOP_MASK (7 << RPL_DIO_MOP_SHIFT)
#define RPL_DIO_PRF_SHIFT 0
#define RPL_DIO_PRF_MASK (7 << RPL_DIO_PRF_SHIFT)
#define RPL_DIO_GROUNDED(X) ((X)&RPL_DIO_GROUND_FLAG)
#define RPL_DIO_MOP(X) (enum RPL_DIO_MOP)(((X)&RPL_DIO_MOP_MASK) >> RPL_DIO_MOP_SHIFT)
#define RPL_DIO_PRF(X) (((X)&RPL_DIO_PRF_MASK) >> RPL_DIO_PRF_SHIFT)
enum RPL_DIO_MOP {
RPL_DIO_NONSTORING= 0x0,
RPL_DIO_STORING = 0x1,
RPL_DIO_NONSTORING_MULTICAST = 0x2,
RPL_DIO_STORING_MULTICAST = 0x3
};
enum RPL_SUBOPT {
RPL_OPT_PAD1 = 0,
RPL_OPT_PADN = 1,
RPL_DIO_METRICS = 2,
RPL_DIO_ROUTINGINFO = 3,
RPL_DIO_CONFIG = 4,
RPL_DAO_RPLTARGET = 5,
RPL_DAO_TRANSITINFO = 6,
RPL_DIO_DESTPREFIX = 8,
RPL_DAO_RPLTARGET_DESC=9
};
struct rpl_genoption {
nd_uint8_t rpl_dio_type;
nd_uint8_t rpl_dio_len; /* suboption length, not including type/len */
};
#define RPL_GENOPTION_LEN 2
#define RPL_DIO_LIFETIME_INFINITE 0xffffffff
#define RPL_DIO_LIFETIME_DISCONNECT 0
struct rpl_dio_destprefix {
nd_uint8_t rpl_dio_type;
nd_uint8_t rpl_dio_len;
nd_uint8_t rpl_dio_prefixlen; /* in bits */
nd_uint8_t rpl_dio_prf; /* flags, including Route Preference */
nd_uint32_t rpl_dio_prefixlifetime; /* in seconds */
#if 0
nd_byte rpl_dio_prefix[0]; /* variable number of bytes */
#endif
};
/* section 6.4.1, DODAG Information Object (DIO) */
struct nd_rpl_dao {
nd_uint8_t rpl_instanceid;
nd_uint8_t rpl_flags; /* bit 7=K, 6=D */
nd_uint8_t rpl_resv;
nd_uint8_t rpl_daoseq;
nd_byte rpl_dagid[DAGID_LEN]; /* present when D set. */
};
#define ND_RPL_DAO_MIN_LEN 4 /* length without DAGID */
/* indicates if this DAO is to be acK'ed */
#define RPL_DAO_K_SHIFT 7
#define RPL_DAO_K_MASK (1 << RPL_DAO_K_SHIFT)
#define RPL_DAO_K(X) (((X)&RPL_DAO_K_MASK) >> RPL_DAO_K_SHIFT)
/* indicates if the DAGID is present */
#define RPL_DAO_D_SHIFT 6
#define RPL_DAO_D_MASK (1 << RPL_DAO_D_SHIFT)
#define RPL_DAO_D(X) (((X)&RPL_DAO_D_MASK) >> RPL_DAO_D_SHIFT)
struct rpl_dao_target {
nd_uint8_t rpl_dao_type;
nd_uint8_t rpl_dao_len;
nd_uint8_t rpl_dao_flags; /* unused */
nd_uint8_t rpl_dao_prefixlen; /* in bits */
#if 0
nd_byte rpl_dao_prefix[0]; /* variable number of bytes */
#endif
};
/* section 6.5.1, Destination Advertisement Object Acknowledgement (DAO-ACK) */
struct nd_rpl_daoack {
nd_uint8_t rpl_instanceid;
nd_uint8_t rpl_flags; /* bit 7=D */
nd_uint8_t rpl_daoseq;
nd_uint8_t rpl_status;
nd_byte rpl_dagid[DAGID_LEN]; /* present when D set. */
};
#define ND_RPL_DAOACK_MIN_LEN 4 /* length without DAGID */
/* indicates if the DAGID is present */
#define RPL_DAOACK_D_SHIFT 7
#define RPL_DAOACK_D_MASK (1 << RPL_DAOACK_D_SHIFT)
#define RPL_DAOACK_D(X) (((X)&RPL_DAOACK_D_MASK) >> RPL_DAOACK_D_SHIFT)
static const struct tok icmp6_type_values[] = {
{ ICMP6_DST_UNREACH, "destination unreachable"},
{ ICMP6_PACKET_TOO_BIG, "packet too big"},
{ ICMP6_TIME_EXCEEDED, "time exceeded in-transit"},
{ ICMP6_PARAM_PROB, "parameter problem"},
{ ICMP6_ECHO_REQUEST, "echo request"},
{ ICMP6_ECHO_REPLY, "echo reply"},
{ MLD6_LISTENER_QUERY, "multicast listener query"},
{ MLD6_LISTENER_REPORT, "multicast listener report"},
{ MLD6_LISTENER_DONE, "multicast listener done"},
{ ND_ROUTER_SOLICIT, "router solicitation"},
{ ND_ROUTER_ADVERT, "router advertisement"},
{ ND_NEIGHBOR_SOLICIT, "neighbor solicitation"},
{ ND_NEIGHBOR_ADVERT, "neighbor advertisement"},
{ ND_REDIRECT, "redirect"},
{ ICMP6_ROUTER_RENUMBERING, "router renumbering"},
{ IND_SOLICIT, "inverse neighbor solicitation"},
{ IND_ADVERT, "inverse neighbor advertisement"},
{ MLDV2_LISTENER_REPORT, "multicast listener report v2"},
{ ICMP6_HADISCOV_REQUEST, "ha discovery request"},
{ ICMP6_HADISCOV_REPLY, "ha discovery reply"},
{ ICMP6_MOBILEPREFIX_SOLICIT, "mobile router solicitation"},
{ ICMP6_MOBILEPREFIX_ADVERT, "mobile router advertisement"},
{ ICMP6_WRUREQUEST, "who-are-you request"},
{ ICMP6_WRUREPLY, "who-are-you reply"},
{ ICMP6_NI_QUERY, "node information query"},
{ ICMP6_NI_REPLY, "node information reply"},
{ MLD6_MTRACE, "mtrace message"},
{ MLD6_MTRACE_RESP, "mtrace response"},
{ ND_RPL_MESSAGE, "RPL"},
{ 0, NULL }
};
static const struct tok icmp6_dst_unreach_code_values[] = {
{ ICMP6_DST_UNREACH_NOROUTE, "unreachable route" },
{ ICMP6_DST_UNREACH_ADMIN, " unreachable prohibited"},
{ ICMP6_DST_UNREACH_BEYONDSCOPE, "beyond scope"},
{ ICMP6_DST_UNREACH_ADDR, "unreachable address"},
{ ICMP6_DST_UNREACH_NOPORT, "unreachable port"},
{ 0, NULL }
};
static const struct tok icmp6_opt_pi_flag_values[] = {
{ ND_OPT_PI_FLAG_ONLINK, "onlink" },
{ ND_OPT_PI_FLAG_AUTO, "auto" },
{ ND_OPT_PI_FLAG_ROUTER, "router" },
{ 0, NULL }
};
static const struct tok icmp6_opt_ra_flag_values[] = {
{ ND_RA_FLAG_MANAGED, "managed" },
{ ND_RA_FLAG_OTHER, "other stateful"},
{ ND_RA_FLAG_HOME_AGENT, "home agent"},
{ ND_RA_FLAG_IPV6ONLY, "ipv6 only"},
{ 0, NULL }
};
static const struct tok icmp6_nd_na_flag_values[] = {
{ ND_NA_FLAG_ROUTER, "router" },
{ ND_NA_FLAG_SOLICITED, "solicited" },
{ ND_NA_FLAG_OVERRIDE, "override" },
{ 0, NULL }
};
static const struct tok icmp6_opt_values[] = {
{ ND_OPT_SOURCE_LINKADDR, "source link-address"},
{ ND_OPT_TARGET_LINKADDR, "destination link-address"},
{ ND_OPT_PREFIX_INFORMATION, "prefix info"},
{ ND_OPT_REDIRECTED_HEADER, "redirected header"},
{ ND_OPT_MTU, "mtu"},
{ ND_OPT_RDNSS, "rdnss"},
{ ND_OPT_DNSSL, "dnssl"},
{ ND_OPT_ADVINTERVAL, "advertisement interval"},
{ ND_OPT_HOMEAGENT_INFO, "homeagent information"},
{ ND_OPT_ROUTE_INFO, "route info"},
{ 0, NULL }
};
/* mldv2 report types */
static const struct tok mldv2report2str[] = {
{ 1, "is_in" },
{ 2, "is_ex" },
{ 3, "to_in" },
{ 4, "to_ex" },
{ 5, "allow" },
{ 6, "block" },
{ 0, NULL }
};
static const char *
get_rtpref(u_int v)
{
static const char *rtpref_str[] = {
"medium", /* 00 */
"high", /* 01 */
"rsv", /* 10 */
"low" /* 11 */
};
return rtpref_str[((v & ND_RA_FLAG_RTPREF_MASK) >> 3) & 0xff];
}
static const char *
get_lifetime(uint32_t v)
{
static char buf[20];
if (v == (uint32_t)~0UL)
return "infinity";
else {
snprintf(buf, sizeof(buf), "%us", v);
return buf;
}
}
static void
print_lladdr(netdissect_options *ndo, const uint8_t *p, size_t l)
{
const uint8_t *ep, *q;
q = p;
ep = p + l;
while (l > 0 && q < ep) {
if (q > p)
ND_PRINT(":");
ND_PRINT("%02x", GET_U_1(q));
q++;
l--;
}
}
static uint16_t icmp6_cksum(netdissect_options *ndo, const struct ip6_hdr *ip6,
const struct icmp6_hdr *icp, u_int len)
{
return nextproto6_cksum(ndo, ip6, (const uint8_t *)(const void *)icp, len, len,
IPPROTO_ICMPV6);
}
static const struct tok rpl_mop_values[] = {
{ RPL_DIO_NONSTORING, "nonstoring"},
{ RPL_DIO_STORING, "storing"},
{ RPL_DIO_NONSTORING_MULTICAST, "nonstoring-multicast"},
{ RPL_DIO_STORING_MULTICAST, "storing-multicast"},
{ 0, NULL},
};
static const struct tok rpl_subopt_values[] = {
{ RPL_OPT_PAD1, "pad1"},
{ RPL_OPT_PADN, "padN"},
{ RPL_DIO_METRICS, "metrics"},
{ RPL_DIO_ROUTINGINFO, "routinginfo"},
{ RPL_DIO_CONFIG, "config"},
{ RPL_DAO_RPLTARGET, "rpltarget"},
{ RPL_DAO_TRANSITINFO, "transitinfo"},
{ RPL_DIO_DESTPREFIX, "destprefix"},
{ RPL_DAO_RPLTARGET_DESC, "rpltargetdesc"},
{ 0, NULL},
};
static void
rpl_printopts(netdissect_options *ndo, const uint8_t *opts, u_int length)
{
const struct rpl_genoption *opt;
uint8_t dio_type;
u_int optlen;
while (length != 0) {
opt = (const struct rpl_genoption *)opts;
dio_type = GET_U_1(opt->rpl_dio_type);
if (dio_type == RPL_OPT_PAD1) {
optlen = 1;
ND_PRINT(" opt:pad1");
} else {
if (length < RPL_GENOPTION_LEN)
goto trunc;
optlen = GET_U_1(opt->rpl_dio_len)+RPL_GENOPTION_LEN;
ND_PRINT(" opt:%s len:%u ",
tok2str(rpl_subopt_values, "subopt:%u", dio_type),
optlen);
ND_TCHECK_LEN(opt, optlen);
if (length < optlen)
goto trunc;
if (ndo->ndo_vflag > 2) {
hex_print(ndo,
" ",
opts + RPL_GENOPTION_LEN, /* content of DIO option */
optlen - RPL_GENOPTION_LEN);
}
}
opts += optlen;
length -= optlen;
}
return;
trunc:
nd_print_trunc(ndo);
}
static void
rpl_dio_print(netdissect_options *ndo,
const u_char *bp, u_int length)
{
const struct nd_rpl_dio *dio = (const struct nd_rpl_dio *)bp;
- ND_LCHECK_ZU(length, sizeof(struct nd_rpl_dio));
+ ND_ICHECK_ZU(length, <, sizeof(struct nd_rpl_dio));
ND_PRINT(" [dagid:%s,seq:%u,instance:%u,rank:%u,%smop:%s,prf:%u]",
GET_IP6ADDR_STRING(dio->rpl_dagid),
GET_U_1(dio->rpl_dtsn),
GET_U_1(dio->rpl_instanceid),
GET_BE_U_2(dio->rpl_dagrank),
RPL_DIO_GROUNDED(GET_U_1(dio->rpl_mopprf)) ? "grounded,":"",
tok2str(rpl_mop_values, "mop%u",
RPL_DIO_MOP(GET_U_1(dio->rpl_mopprf))),
RPL_DIO_PRF(GET_U_1(dio->rpl_mopprf)));
if(ndo->ndo_vflag > 1) {
rpl_printopts(ndo, bp + sizeof(struct nd_rpl_dio),
length - sizeof(struct nd_rpl_dio));
}
return;
invalid:
nd_print_invalid(ndo);
}
static void
rpl_dao_print(netdissect_options *ndo,
const u_char *bp, u_int length)
{
const struct nd_rpl_dao *dao = (const struct nd_rpl_dao *)bp;
const char *dagid_str = "<elided>";
uint8_t rpl_flags;
ND_TCHECK_SIZE(dao);
if (length < ND_RPL_DAO_MIN_LEN)
goto tooshort;
bp += ND_RPL_DAO_MIN_LEN;
length -= ND_RPL_DAO_MIN_LEN;
rpl_flags = GET_U_1(dao->rpl_flags);
if(RPL_DAO_D(rpl_flags)) {
ND_TCHECK_LEN(dao->rpl_dagid, DAGID_LEN);
if (length < DAGID_LEN)
goto tooshort;
dagid_str = ip6addr_string (ndo, dao->rpl_dagid);
bp += DAGID_LEN;
length -= DAGID_LEN;
}
ND_PRINT(" [dagid:%s,seq:%u,instance:%u%s%s,flags:%02x]",
dagid_str,
GET_U_1(dao->rpl_daoseq),
GET_U_1(dao->rpl_instanceid),
RPL_DAO_K(rpl_flags) ? ",acK":"",
RPL_DAO_D(rpl_flags) ? ",Dagid":"",
rpl_flags);
if(ndo->ndo_vflag > 1) {
rpl_printopts(ndo, bp, length);
}
return;
trunc:
nd_print_trunc(ndo);
return;
tooshort:
ND_PRINT(" [|length too short]");
}
static void
rpl_daoack_print(netdissect_options *ndo,
const u_char *bp, u_int length)
{
const struct nd_rpl_daoack *daoack = (const struct nd_rpl_daoack *)bp;
const char *dagid_str = "<elided>";
ND_TCHECK_LEN(daoack, ND_RPL_DAOACK_MIN_LEN);
if (length < ND_RPL_DAOACK_MIN_LEN)
goto tooshort;
bp += ND_RPL_DAOACK_MIN_LEN;
length -= ND_RPL_DAOACK_MIN_LEN;
if(RPL_DAOACK_D(GET_U_1(daoack->rpl_flags))) {
ND_TCHECK_LEN(daoack->rpl_dagid, DAGID_LEN);
if (length < DAGID_LEN)
goto tooshort;
dagid_str = ip6addr_string (ndo, daoack->rpl_dagid);
bp += DAGID_LEN;
length -= DAGID_LEN;
}
ND_PRINT(" [dagid:%s,seq:%u,instance:%u,status:%u]",
dagid_str,
GET_U_1(daoack->rpl_daoseq),
GET_U_1(daoack->rpl_instanceid),
GET_U_1(daoack->rpl_status));
/* no officially defined options for DAOACK, but print any we find */
if(ndo->ndo_vflag > 1) {
rpl_printopts(ndo, bp, length);
}
return;
trunc:
nd_print_trunc(ndo);
return;
tooshort:
ND_PRINT(" [|dao-length too short]");
}
static void
rpl_print(netdissect_options *ndo,
uint8_t icmp6_code,
const u_char *bp, u_int length)
{
int secured = icmp6_code & 0x80;
int basecode= icmp6_code & 0x7f;
if(secured) {
ND_PRINT(", (SEC) [worktodo]");
/* XXX
* the next header pointer needs to move forward to
* skip the secure part.
*/
return;
} else {
ND_PRINT(", (CLR)");
}
switch(basecode) {
case ND_RPL_DAG_IS:
ND_PRINT("DODAG Information Solicitation");
if(ndo->ndo_vflag) {
}
break;
case ND_RPL_DAG_IO:
ND_PRINT("DODAG Information Object");
if(ndo->ndo_vflag) {
rpl_dio_print(ndo, bp, length);
}
break;
case ND_RPL_DAO:
ND_PRINT("Destination Advertisement Object");
if(ndo->ndo_vflag) {
rpl_dao_print(ndo, bp, length);
}
break;
case ND_RPL_DAO_ACK:
ND_PRINT("Destination Advertisement Object Ack");
if(ndo->ndo_vflag) {
rpl_daoack_print(ndo, bp, length);
}
break;
default:
ND_PRINT("RPL message, unknown code %u",icmp6_code);
break;
}
return;
#if 0
trunc:
nd_print_trunc(ndo);
return;
#endif
}
void
icmp6_print(netdissect_options *ndo,
const u_char *bp, u_int length, const u_char *bp2, int fragmented)
{
const struct icmp6_hdr *dp;
uint8_t icmp6_type, icmp6_code;
const struct ip6_hdr *ip;
const struct ip6_hdr *oip;
const struct udphdr *ouh;
uint16_t dport;
const u_char *ep;
u_int prot;
ndo->ndo_protocol = "icmp6";
dp = (const struct icmp6_hdr *)bp;
ip = (const struct ip6_hdr *)bp2;
oip = (const struct ip6_hdr *)(dp + 1);
/* 'ep' points to the end of available data. */
ep = ndo->ndo_snapend;
if (length == 0) {
ND_PRINT("ICMP6, length 0");
nd_print_invalid(ndo);
return;
}
if (ndo->ndo_vflag && !fragmented) {
uint16_t sum, udp_sum;
if (ND_TTEST_LEN(bp, length)) {
udp_sum = GET_BE_U_2(dp->icmp6_cksum);
sum = icmp6_cksum(ndo, ip, dp, length);
if (sum != 0)
ND_PRINT("[bad icmp6 cksum 0x%04x -> 0x%04x!] ",
udp_sum,
in_cksum_shouldbe(udp_sum, sum));
else
ND_PRINT("[icmp6 sum ok] ");
}
}
icmp6_type = GET_U_1(dp->icmp6_type);
ND_PRINT("ICMP6, %s", tok2str(icmp6_type_values,"unknown icmp6 type (%u)",icmp6_type));
/* display cosmetics: print the packet length for printer that use the vflag now */
if (ndo->ndo_vflag && (icmp6_type == ND_ROUTER_SOLICIT ||
icmp6_type == ND_ROUTER_ADVERT ||
icmp6_type == ND_NEIGHBOR_ADVERT ||
icmp6_type == ND_NEIGHBOR_SOLICIT ||
icmp6_type == ND_REDIRECT ||
icmp6_type == ICMP6_HADISCOV_REPLY ||
icmp6_type == ICMP6_MOBILEPREFIX_ADVERT ))
ND_PRINT(", length %u", length);
icmp6_code = GET_U_1(dp->icmp6_code);
switch (icmp6_type) {
case ICMP6_DST_UNREACH:
ND_PRINT(", %s", tok2str(icmp6_dst_unreach_code_values,"unknown unreach code (%u)",icmp6_code));
switch (icmp6_code) {
case ICMP6_DST_UNREACH_NOROUTE: /* fall through */
case ICMP6_DST_UNREACH_ADMIN:
case ICMP6_DST_UNREACH_ADDR:
ND_PRINT(" %s",GET_IP6ADDR_STRING(oip->ip6_dst));
break;
case ICMP6_DST_UNREACH_BEYONDSCOPE:
ND_PRINT(" %s, source address %s",
GET_IP6ADDR_STRING(oip->ip6_dst),
GET_IP6ADDR_STRING(oip->ip6_src));
break;
case ICMP6_DST_UNREACH_NOPORT:
if ((ouh = get_upperlayer(ndo, (const u_char *)oip, &prot))
== NULL)
goto trunc;
dport = GET_BE_U_2(ouh->uh_dport);
switch (prot) {
case IPPROTO_TCP:
ND_PRINT(", %s tcp port %s",
GET_IP6ADDR_STRING(oip->ip6_dst),
tcpport_string(ndo, dport));
break;
case IPPROTO_UDP:
ND_PRINT(", %s udp port %s",
GET_IP6ADDR_STRING(oip->ip6_dst),
udpport_string(ndo, dport));
break;
default:
ND_PRINT(", %s protocol %u port %u unreachable",
GET_IP6ADDR_STRING(oip->ip6_dst),
prot, dport);
break;
}
break;
default:
if (ndo->ndo_vflag <= 1) {
print_unknown_data(ndo, bp,"\n\t",length);
return;
}
break;
}
break;
case ICMP6_PACKET_TOO_BIG:
ND_PRINT(", mtu %u", GET_BE_U_4(dp->icmp6_mtu));
break;
case ICMP6_TIME_EXCEEDED:
switch (icmp6_code) {
case ICMP6_TIME_EXCEED_TRANSIT:
ND_PRINT(" for %s",
GET_IP6ADDR_STRING(oip->ip6_dst));
break;
case ICMP6_TIME_EXCEED_REASSEMBLY:
ND_PRINT(" (reassembly)");
break;
default:
ND_PRINT(", unknown code (%u)", icmp6_code);
break;
}
break;
case ICMP6_PARAM_PROB:
ND_TCHECK_16(oip->ip6_dst);
switch (icmp6_code) {
case ICMP6_PARAMPROB_HEADER:
ND_PRINT(", erroneous - octet %u",
GET_BE_U_4(dp->icmp6_pptr));
break;
case ICMP6_PARAMPROB_NEXTHEADER:
ND_PRINT(", next header - octet %u",
GET_BE_U_4(dp->icmp6_pptr));
break;
case ICMP6_PARAMPROB_OPTION:
ND_PRINT(", option - octet %u",
GET_BE_U_4(dp->icmp6_pptr));
break;
case ICMP6_PARAMPROB_FRAGHDRCHAIN:
ND_PRINT(", incomplete header chain - octet %u",
GET_BE_U_4(dp->icmp6_pptr));
break;
default:
ND_PRINT(", code-#%u",
icmp6_code);
break;
}
break;
case ICMP6_ECHO_REQUEST:
case ICMP6_ECHO_REPLY:
ND_PRINT(", id %u, seq %u", GET_BE_U_2(dp->icmp6_id),
GET_BE_U_2(dp->icmp6_seq));
break;
case ICMP6_MEMBERSHIP_QUERY:
if (length == MLD_MINLEN) {
mld6_print(ndo, (const u_char *)dp);
} else if (length >= MLDV2_MINLEN) {
ND_PRINT(" v2");
mldv2_query_print(ndo, (const u_char *)dp, length);
} else {
ND_PRINT(" unknown-version (len %u) ", length);
}
break;
case ICMP6_MEMBERSHIP_REPORT:
mld6_print(ndo, (const u_char *)dp);
break;
case ICMP6_MEMBERSHIP_REDUCTION:
mld6_print(ndo, (const u_char *)dp);
break;
case ND_ROUTER_SOLICIT:
#define RTSOLLEN 8
if (ndo->ndo_vflag) {
if (icmp6_opt_print(ndo, (const u_char *)dp + RTSOLLEN,
length - RTSOLLEN) == -1)
goto trunc;
}
break;
case ND_ROUTER_ADVERT:
#define RTADVLEN 16
if (ndo->ndo_vflag) {
const struct nd_router_advert *p;
p = (const struct nd_router_advert *)dp;
ND_PRINT("\n\thop limit %u, Flags [%s]"
", pref %s, router lifetime %us, reachable time %ums, retrans timer %ums",
GET_U_1(p->nd_ra_curhoplimit),
bittok2str(icmp6_opt_ra_flag_values,"none",GET_U_1(p->nd_ra_flags_reserved)),
get_rtpref(GET_U_1(p->nd_ra_flags_reserved)),
GET_BE_U_2(p->nd_ra_router_lifetime),
GET_BE_U_4(p->nd_ra_reachable),
GET_BE_U_4(p->nd_ra_retransmit));
if (icmp6_opt_print(ndo, (const u_char *)dp + RTADVLEN,
length - RTADVLEN) == -1)
goto trunc;
}
break;
case ND_NEIGHBOR_SOLICIT:
{
const struct nd_neighbor_solicit *p;
p = (const struct nd_neighbor_solicit *)dp;
ND_PRINT(", who has %s", GET_IP6ADDR_STRING(p->nd_ns_target));
if (ndo->ndo_vflag) {
#define NDSOLLEN 24
if (icmp6_opt_print(ndo, (const u_char *)dp + NDSOLLEN,
length - NDSOLLEN) == -1)
goto trunc;
}
}
break;
case ND_NEIGHBOR_ADVERT:
{
const struct nd_neighbor_advert *p;
p = (const struct nd_neighbor_advert *)dp;
ND_PRINT(", tgt is %s",
GET_IP6ADDR_STRING(p->nd_na_target));
if (ndo->ndo_vflag) {
ND_PRINT(", Flags [%s]",
bittok2str(icmp6_nd_na_flag_values,
"none",
GET_BE_U_4(p->nd_na_flags_reserved)));
#define NDADVLEN 24
if (icmp6_opt_print(ndo, (const u_char *)dp + NDADVLEN,
length - NDADVLEN) == -1)
goto trunc;
#undef NDADVLEN
}
}
break;
case ND_REDIRECT:
{
const struct nd_redirect *p;
p = (const struct nd_redirect *)dp;
ND_PRINT(", %s", GET_IP6ADDR_STRING(p->nd_rd_dst));
ND_PRINT(" to %s", GET_IP6ADDR_STRING(p->nd_rd_target));
#define REDIRECTLEN 40
if (ndo->ndo_vflag) {
if (icmp6_opt_print(ndo, (const u_char *)dp + REDIRECTLEN,
length - REDIRECTLEN) == -1)
goto trunc;
#undef REDIRECTLEN
}
}
break;
case ICMP6_ROUTER_RENUMBERING:
icmp6_rrenum_print(ndo, bp, ep);
break;
case ICMP6_NI_QUERY:
case ICMP6_NI_REPLY:
icmp6_nodeinfo_print(ndo, length, bp, ep);
break;
case IND_SOLICIT:
case IND_ADVERT:
break;
case ICMP6_V2_MEMBERSHIP_REPORT:
mldv2_report_print(ndo, (const u_char *) dp, length);
break;
case ICMP6_MOBILEPREFIX_SOLICIT: /* fall through */
case ICMP6_HADISCOV_REQUEST:
ND_PRINT(", id 0x%04x", GET_BE_U_2(dp->icmp6_data16[0]));
break;
case ICMP6_HADISCOV_REPLY:
if (ndo->ndo_vflag) {
const u_char *cp;
const u_char *p;
ND_PRINT(", id 0x%04x",
GET_BE_U_2(dp->icmp6_data16[0]));
- cp = (const u_char *)dp + length;
+ cp = (const u_char *)dp +
+ ND_MIN(length, ND_BYTES_AVAILABLE_AFTER(dp));
p = (const u_char *)(dp + 1);
while (p < cp) {
ND_PRINT(", %s", GET_IP6ADDR_STRING(p));
p += 16;
}
}
break;
case ICMP6_MOBILEPREFIX_ADVERT:
if (ndo->ndo_vflag) {
uint16_t flags;
ND_PRINT(", id 0x%04x",
GET_BE_U_2(dp->icmp6_data16[0]));
flags = GET_BE_U_2(dp->icmp6_data16[1]);
if (flags & 0xc000)
ND_PRINT(" ");
if (flags & 0x8000)
ND_PRINT("M");
if (flags & 0x4000)
ND_PRINT("O");
#define MPADVLEN 8
if (icmp6_opt_print(ndo, (const u_char *)dp + MPADVLEN,
length - MPADVLEN) == -1)
goto trunc;
}
break;
case ND_RPL_MESSAGE:
/* plus 4, because struct icmp6_hdr contains 4 bytes of icmp payload */
rpl_print(ndo, icmp6_code, dp->icmp6_data, length-sizeof(struct icmp6_hdr)+4);
break;
default:
ND_PRINT(", length %u", length);
if (ndo->ndo_vflag <= 1)
print_unknown_data(ndo, bp,"\n\t", length);
return;
}
if (!ndo->ndo_vflag)
ND_PRINT(", length %u", length);
return;
trunc:
nd_print_trunc(ndo);
}
static const struct udphdr *
get_upperlayer(netdissect_options *ndo, const u_char *bp, u_int *prot)
{
const u_char *ep;
const struct ip6_hdr *ip6 = (const struct ip6_hdr *)bp;
const struct udphdr *uh;
const struct ip6_hbh *hbh;
const struct ip6_frag *fragh;
const struct ah *ah;
u_int nh;
int hlen;
/* 'ep' points to the end of available data. */
ep = ndo->ndo_snapend;
if (!ND_TTEST_1(ip6->ip6_nxt))
return NULL;
nh = GET_U_1(ip6->ip6_nxt);
hlen = sizeof(struct ip6_hdr);
while (bp < ep) {
bp += hlen;
switch(nh) {
case IPPROTO_UDP:
case IPPROTO_TCP:
uh = (const struct udphdr *)bp;
if (ND_TTEST_2(uh->uh_dport)) {
*prot = nh;
return(uh);
- }
- else
+ } else
return(NULL);
/* NOTREACHED */
case IPPROTO_HOPOPTS:
case IPPROTO_DSTOPTS:
case IPPROTO_ROUTING:
hbh = (const struct ip6_hbh *)bp;
if (!ND_TTEST_1(hbh->ip6h_len))
return(NULL);
nh = GET_U_1(hbh->ip6h_nxt);
hlen = (GET_U_1(hbh->ip6h_len) + 1) << 3;
break;
case IPPROTO_FRAGMENT: /* this should be odd, but try anyway */
fragh = (const struct ip6_frag *)bp;
if (!ND_TTEST_2(fragh->ip6f_offlg))
return(NULL);
/* fragments with non-zero offset are meaningless */
if ((GET_BE_U_2(fragh->ip6f_offlg) & IP6F_OFF_MASK) != 0)
return(NULL);
nh = GET_U_1(fragh->ip6f_nxt);
hlen = sizeof(struct ip6_frag);
break;
case IPPROTO_AH:
ah = (const struct ah *)bp;
if (!ND_TTEST_1(ah->ah_len))
return(NULL);
nh = GET_U_1(ah->ah_nxt);
hlen = (GET_U_1(ah->ah_len) + 2) << 2;
break;
default: /* unknown or undecodable header */
*prot = nh; /* meaningless, but set here anyway */
return(NULL);
}
}
return(NULL); /* should be notreached, though */
}
static int
icmp6_opt_print(netdissect_options *ndo, const u_char *bp, int resid)
{
const struct nd_opt_hdr *op;
uint8_t opt_type;
u_int opt_len;
const struct nd_opt_prefix_info *opp;
const struct nd_opt_mtu *opm;
const struct nd_opt_rdnss *oprd;
const struct nd_opt_dnssl *opds;
const struct nd_opt_advinterval *opa;
const struct nd_opt_homeagent_info *oph;
const struct nd_opt_route_info *opri;
const u_char *cp, *ep, *domp;
nd_ipv6 in6;
size_t l;
u_int i;
cp = bp;
/* 'ep' points to the end of available data. */
ep = ndo->ndo_snapend;
while (cp < ep) {
op = (const struct nd_opt_hdr *)cp;
ND_TCHECK_1(op->nd_opt_len);
if (resid <= 0)
return 0;
opt_type = GET_U_1(op->nd_opt_type);
opt_len = GET_U_1(op->nd_opt_len);
if (opt_len == 0)
goto trunc;
if (cp + (opt_len << 3) > ep)
goto trunc;
ND_PRINT("\n\t %s option (%u), length %u (%u): ",
tok2str(icmp6_opt_values, "unknown", opt_type),
opt_type,
opt_len << 3,
opt_len);
switch (opt_type) {
case ND_OPT_SOURCE_LINKADDR:
l = (opt_len << 3) - 2;
print_lladdr(ndo, cp + 2, l);
break;
case ND_OPT_TARGET_LINKADDR:
l = (opt_len << 3) - 2;
print_lladdr(ndo, cp + 2, l);
break;
case ND_OPT_PREFIX_INFORMATION:
opp = (const struct nd_opt_prefix_info *)op;
ND_PRINT("%s/%u%s, Flags [%s], valid time %s",
GET_IP6ADDR_STRING(opp->nd_opt_pi_prefix),
GET_U_1(opp->nd_opt_pi_prefix_len),
(opt_len != 4) ? "badlen" : "",
bittok2str(icmp6_opt_pi_flag_values, "none", GET_U_1(opp->nd_opt_pi_flags_reserved)),
get_lifetime(GET_BE_U_4(opp->nd_opt_pi_valid_time)));
ND_PRINT(", pref. time %s",
get_lifetime(GET_BE_U_4(opp->nd_opt_pi_preferred_time)));
break;
case ND_OPT_REDIRECTED_HEADER:
print_unknown_data(ndo, bp,"\n\t ",opt_len<<3);
/* xxx */
break;
case ND_OPT_MTU:
opm = (const struct nd_opt_mtu *)op;
ND_PRINT(" %u%s",
GET_BE_U_4(opm->nd_opt_mtu_mtu),
(opt_len != 1) ? "bad option length" : "" );
break;
case ND_OPT_RDNSS:
oprd = (const struct nd_opt_rdnss *)op;
l = (opt_len - 1) / 2;
ND_PRINT(" lifetime %us,",
GET_BE_U_4(oprd->nd_opt_rdnss_lifetime));
for (i = 0; i < l; i++) {
ND_PRINT(" addr: %s",
GET_IP6ADDR_STRING(oprd->nd_opt_rdnss_addr[i]));
}
break;
case ND_OPT_DNSSL:
opds = (const struct nd_opt_dnssl *)op;
ND_PRINT(" lifetime %us, domain(s):",
GET_BE_U_4(opds->nd_opt_dnssl_lifetime));
domp = cp + 8; /* domain names, variable-sized, RFC1035-encoded */
- while (domp < cp + (opt_len << 3) && GET_U_1(domp) != '\0')
- {
+ while (domp < cp + (opt_len << 3) && GET_U_1(domp) != '\0') {
ND_PRINT(" ");
if ((domp = fqdn_print(ndo, domp, bp)) == NULL)
goto trunc;
}
break;
case ND_OPT_ADVINTERVAL:
opa = (const struct nd_opt_advinterval *)op;
ND_PRINT(" %ums",
GET_BE_U_4(opa->nd_opt_adv_interval));
break;
case ND_OPT_HOMEAGENT_INFO:
oph = (const struct nd_opt_homeagent_info *)op;
ND_PRINT(" preference %u, lifetime %u",
GET_BE_U_2(oph->nd_opt_hai_preference),
GET_BE_U_2(oph->nd_opt_hai_lifetime));
break;
case ND_OPT_ROUTE_INFO:
opri = (const struct nd_opt_route_info *)op;
ND_TCHECK_4(opri->nd_opt_rti_lifetime);
memset(&in6, 0, sizeof(in6));
switch (opt_len) {
case 1:
break;
case 2:
GET_CPY_BYTES(&in6, opri + 1, 8);
break;
case 3:
GET_CPY_BYTES(&in6, opri + 1, 16);
break;
default:
goto trunc;
}
ND_PRINT(" %s/%u", ip6addr_string(ndo, (const u_char *)&in6), /* local buffer, not packet data; don't use GET_IP6ADDR_STRING() */
GET_U_1(opri->nd_opt_rti_prefixlen));
ND_PRINT(", pref=%s",
get_rtpref(GET_U_1(opri->nd_opt_rti_flags)));
ND_PRINT(", lifetime=%s",
get_lifetime(GET_BE_U_4(opri->nd_opt_rti_lifetime)));
break;
default:
if (ndo->ndo_vflag <= 1) {
print_unknown_data(ndo,cp+2,"\n\t ", (opt_len << 3) - 2); /* skip option header */
return 0;
}
break;
}
/* do we want to see an additional hexdump ? */
if (ndo->ndo_vflag> 1)
print_unknown_data(ndo, cp+2,"\n\t ", (opt_len << 3) - 2); /* skip option header */
cp += opt_len << 3;
resid -= opt_len << 3;
}
return 0;
trunc:
return -1;
}
static void
mld6_print(netdissect_options *ndo, const u_char *bp)
{
const struct mld6_hdr *mp = (const struct mld6_hdr *)bp;
const u_char *ep;
/* 'ep' points to the end of available data. */
ep = ndo->ndo_snapend;
if ((const u_char *)mp + sizeof(*mp) > ep)
return;
ND_PRINT("max resp delay: %u ", GET_BE_U_2(mp->mld6_maxdelay));
ND_PRINT("addr: %s", GET_IP6ADDR_STRING(mp->mld6_addr));
}
static void
mldv2_report_print(netdissect_options *ndo, const u_char *bp, u_int len)
{
const struct icmp6_hdr *icp = (const struct icmp6_hdr *) bp;
u_int group, nsrcs, ngroups;
u_int i, j;
/* Minimum len is 8 */
if (len < 8) {
ND_PRINT(" [invalid len %u]", len);
return;
}
ngroups = GET_BE_U_2(icp->icmp6_data16[1]);
ND_PRINT(", %u group record(s)", ngroups);
if (ndo->ndo_vflag > 0) {
/* Print the group records */
group = 8;
for (i = 0; i < ngroups; i++) {
/* type(1) + auxlen(1) + numsrc(2) + grp(16) */
if (len < group + 20) {
ND_PRINT(" [invalid number of groups]");
return;
}
ND_PRINT(" [gaddr %s", GET_IP6ADDR_STRING(bp + group + 4));
ND_PRINT(" %s", tok2str(mldv2report2str, " [v2-report-#%u]",
GET_U_1(bp + group)));
nsrcs = GET_BE_U_2(bp + group + 2);
/* Check the number of sources and print them */
if (len < group + 20 + (nsrcs * sizeof(nd_ipv6))) {
ND_PRINT(" [invalid number of sources %u]", nsrcs);
return;
}
if (ndo->ndo_vflag == 1)
ND_PRINT(", %u source(s)", nsrcs);
else {
/* Print the sources */
ND_PRINT(" {");
for (j = 0; j < nsrcs; j++) {
ND_PRINT(" %s", GET_IP6ADDR_STRING(bp + group + 20 + (j * sizeof(nd_ipv6))));
}
ND_PRINT(" }");
}
/* Next group record */
group += 20 + nsrcs * sizeof(nd_ipv6);
ND_PRINT("]");
}
}
}
static void
mldv2_query_print(netdissect_options *ndo, const u_char *bp, u_int len)
{
const struct icmp6_hdr *icp = (const struct icmp6_hdr *) bp;
u_int mrc;
u_int mrt, qqi;
u_int nsrcs;
u_int i;
/* Minimum len is 28 */
if (len < 28) {
ND_PRINT(" [invalid len %u]", len);
return;
}
mrc = GET_BE_U_2(icp->icmp6_data16[0]);
if (mrc < 32768) {
mrt = mrc;
} else {
mrt = ((mrc & 0x0fff) | 0x1000) << (((mrc & 0x7000) >> 12) + 3);
}
if (ndo->ndo_vflag) {
ND_PRINT(" [max resp delay=%u]", mrt);
}
ND_PRINT(" [gaddr %s", GET_IP6ADDR_STRING(bp + 8));
if (ndo->ndo_vflag) {
if (GET_U_1(bp + 24) & 0x08) {
ND_PRINT(" sflag");
}
if (GET_U_1(bp + 24) & 0x07) {
ND_PRINT(" robustness=%u", GET_U_1(bp + 24) & 0x07);
}
if (GET_U_1(bp + 25) < 128) {
qqi = GET_U_1(bp + 25);
} else {
qqi = ((GET_U_1(bp + 25) & 0x0f) | 0x10) <<
(((GET_U_1(bp + 25) & 0x70) >> 4) + 3);
}
ND_PRINT(" qqi=%u", qqi);
}
nsrcs = GET_BE_U_2(bp + 26);
if (nsrcs > 0) {
if (len < 28 + nsrcs * sizeof(nd_ipv6))
ND_PRINT(" [invalid number of sources]");
else if (ndo->ndo_vflag > 1) {
ND_PRINT(" {");
for (i = 0; i < nsrcs; i++) {
ND_PRINT(" %s", GET_IP6ADDR_STRING(bp + 28 + (i * sizeof(nd_ipv6))));
}
ND_PRINT(" }");
} else
ND_PRINT(", %u source(s)", nsrcs);
}
ND_PRINT("]");
}
static void
dnsname_print(netdissect_options *ndo, const u_char *cp, const u_char *ep)
{
int i;
/* DNS name decoding - no decompression */
ND_PRINT(", \"");
while (cp < ep) {
i = GET_U_1(cp);
cp++;
if (i) {
if (i > ep - cp) {
ND_PRINT("???");
break;
}
while (i-- && cp < ep) {
fn_print_char(ndo, GET_U_1(cp));
cp++;
}
if (cp + 1 < ep && GET_U_1(cp))
ND_PRINT(".");
} else {
if (cp == ep) {
/* FQDN */
ND_PRINT(".");
} else if (cp + 1 == ep && GET_U_1(cp) == '\0') {
/* truncated */
} else {
/* invalid */
ND_PRINT("???");
}
break;
}
}
ND_PRINT("\"");
}
static void
icmp6_nodeinfo_print(netdissect_options *ndo, u_int icmp6len, const u_char *bp, const u_char *ep)
{
const struct icmp6_nodeinfo *ni6;
const struct icmp6_hdr *dp;
const u_char *cp;
size_t siz, i;
int needcomma;
if (ep < bp)
return;
dp = (const struct icmp6_hdr *)bp;
ni6 = (const struct icmp6_nodeinfo *)bp;
siz = ep - bp;
switch (GET_U_1(ni6->ni_type)) {
case ICMP6_NI_QUERY:
if (siz == sizeof(*dp) + 4) {
/* KAME who-are-you */
ND_PRINT(" who-are-you request");
break;
}
ND_PRINT(" node information query");
ND_TCHECK_LEN(dp, sizeof(*ni6));
ni6 = (const struct icmp6_nodeinfo *)dp;
ND_PRINT(" ("); /*)*/
switch (GET_BE_U_2(ni6->ni_qtype)) {
case NI_QTYPE_NOOP:
ND_PRINT("noop");
break;
case NI_QTYPE_SUPTYPES:
ND_PRINT("supported qtypes");
i = GET_BE_U_2(ni6->ni_flags);
if (i)
ND_PRINT(" [%s]", (i & 0x01) ? "C" : "");
break;
case NI_QTYPE_FQDN:
ND_PRINT("DNS name");
break;
case NI_QTYPE_NODEADDR:
ND_PRINT("node addresses");
i = GET_BE_U_2(ni6->ni_flags);
if (!i)
break;
/* NI_NODEADDR_FLAG_TRUNCATE undefined for query */
ND_PRINT(" [%s%s%s%s%s%s]",
(i & NI_NODEADDR_FLAG_ANYCAST) ? "a" : "",
(i & NI_NODEADDR_FLAG_GLOBAL) ? "G" : "",
(i & NI_NODEADDR_FLAG_SITELOCAL) ? "S" : "",
(i & NI_NODEADDR_FLAG_LINKLOCAL) ? "L" : "",
(i & NI_NODEADDR_FLAG_COMPAT) ? "C" : "",
(i & NI_NODEADDR_FLAG_ALL) ? "A" : "");
break;
default:
ND_PRINT("unknown");
break;
}
if (GET_BE_U_2(ni6->ni_qtype) == NI_QTYPE_NOOP ||
GET_BE_U_2(ni6->ni_qtype) == NI_QTYPE_SUPTYPES) {
if (siz != sizeof(*ni6))
if (ndo->ndo_vflag)
ND_PRINT(", invalid len");
/*(*/
ND_PRINT(")");
break;
}
/* XXX backward compat, icmp-name-lookup-03 */
if (siz == sizeof(*ni6)) {
ND_PRINT(", 03 draft");
/*(*/
ND_PRINT(")");
break;
}
cp = (const u_char *)(ni6 + 1);
switch (GET_U_1(ni6->ni_code)) {
case ICMP6_NI_SUBJ_IPV6:
if (!ND_TTEST_LEN(dp, sizeof(*ni6) + sizeof(nd_ipv6)))
break;
if (siz != sizeof(*ni6) + sizeof(nd_ipv6)) {
if (ndo->ndo_vflag)
ND_PRINT(", invalid subject len");
break;
}
ND_PRINT(", subject=%s",
GET_IP6ADDR_STRING(cp));
break;
case ICMP6_NI_SUBJ_FQDN:
ND_PRINT(", subject=DNS name");
if (GET_U_1(cp) == ep - cp - 1) {
/* icmp-name-lookup-03, pascal string */
if (ndo->ndo_vflag)
ND_PRINT(", 03 draft");
cp++;
ND_PRINT(", \"");
while (cp < ep) {
fn_print_char(ndo, GET_U_1(cp));
cp++;
}
ND_PRINT("\"");
} else
dnsname_print(ndo, cp, ep);
break;
case ICMP6_NI_SUBJ_IPV4:
if (!ND_TTEST_LEN(dp, sizeof(*ni6) + sizeof(nd_ipv4)))
break;
if (siz != sizeof(*ni6) + sizeof(nd_ipv4)) {
if (ndo->ndo_vflag)
ND_PRINT(", invalid subject len");
break;
}
ND_PRINT(", subject=%s",
GET_IPADDR_STRING(cp));
break;
default:
ND_PRINT(", unknown subject");
break;
}
/*(*/
ND_PRINT(")");
break;
case ICMP6_NI_REPLY:
if (icmp6len > siz)
goto trunc;
needcomma = 0;
ND_TCHECK_LEN(dp, sizeof(*ni6));
ni6 = (const struct icmp6_nodeinfo *)dp;
ND_PRINT(" node information reply");
ND_PRINT(" ("); /*)*/
switch (GET_U_1(ni6->ni_code)) {
case ICMP6_NI_SUCCESS:
if (ndo->ndo_vflag) {
ND_PRINT("success");
needcomma++;
}
break;
case ICMP6_NI_REFUSED:
ND_PRINT("refused");
needcomma++;
if (siz != sizeof(*ni6))
if (ndo->ndo_vflag)
ND_PRINT(", invalid length");
break;
case ICMP6_NI_UNKNOWN:
ND_PRINT("unknown");
needcomma++;
if (siz != sizeof(*ni6))
if (ndo->ndo_vflag)
ND_PRINT(", invalid length");
break;
}
if (GET_U_1(ni6->ni_code) != ICMP6_NI_SUCCESS) {
/*(*/
ND_PRINT(")");
break;
}
switch (GET_BE_U_2(ni6->ni_qtype)) {
case NI_QTYPE_NOOP:
if (needcomma)
ND_PRINT(", ");
ND_PRINT("noop");
if (siz != sizeof(*ni6))
if (ndo->ndo_vflag)
ND_PRINT(", invalid length");
break;
case NI_QTYPE_SUPTYPES:
if (needcomma)
ND_PRINT(", ");
ND_PRINT("supported qtypes");
i = GET_BE_U_2(ni6->ni_flags);
if (i)
ND_PRINT(" [%s]", (i & 0x01) ? "C" : "");
break;
case NI_QTYPE_FQDN:
if (needcomma)
ND_PRINT(", ");
ND_PRINT("DNS name");
cp = (const u_char *)(ni6 + 1) + 4;
if (GET_U_1(cp) == ep - cp - 1) {
/* icmp-name-lookup-03, pascal string */
if (ndo->ndo_vflag)
ND_PRINT(", 03 draft");
cp++;
ND_PRINT(", \"");
while (cp < ep) {
fn_print_char(ndo, GET_U_1(cp));
cp++;
}
ND_PRINT("\"");
} else
dnsname_print(ndo, cp, ep);
if ((GET_BE_U_2(ni6->ni_flags) & 0x01) != 0)
ND_PRINT(" [TTL=%u]", GET_BE_U_4(ni6 + 1));
break;
case NI_QTYPE_NODEADDR:
if (needcomma)
ND_PRINT(", ");
ND_PRINT("node addresses");
i = sizeof(*ni6);
while (i < siz) {
if (i + sizeof(uint32_t) + sizeof(nd_ipv6) > siz)
break;
ND_PRINT(" %s(%u)",
GET_IP6ADDR_STRING(bp + i + sizeof(uint32_t)),
GET_BE_U_4(bp + i));
i += sizeof(uint32_t) + sizeof(nd_ipv6);
}
i = GET_BE_U_2(ni6->ni_flags);
if (!i)
break;
ND_PRINT(" [%s%s%s%s%s%s%s]",
(i & NI_NODEADDR_FLAG_ANYCAST) ? "a" : "",
(i & NI_NODEADDR_FLAG_GLOBAL) ? "G" : "",
(i & NI_NODEADDR_FLAG_SITELOCAL) ? "S" : "",
(i & NI_NODEADDR_FLAG_LINKLOCAL) ? "L" : "",
(i & NI_NODEADDR_FLAG_COMPAT) ? "C" : "",
(i & NI_NODEADDR_FLAG_ALL) ? "A" : "",
(i & NI_NODEADDR_FLAG_TRUNCATE) ? "T" : "");
break;
default:
if (needcomma)
ND_PRINT(", ");
ND_PRINT("unknown");
break;
}
/*(*/
ND_PRINT(")");
break;
}
return;
trunc:
nd_print_trunc(ndo);
}
static void
icmp6_rrenum_print(netdissect_options *ndo, const u_char *bp, const u_char *ep)
{
const struct icmp6_router_renum *rr6;
const char *cp;
const struct rr_pco_match *match;
const struct rr_pco_use *use;
char hbuf[NI_MAXHOST];
int n;
if (ep < bp)
return;
rr6 = (const struct icmp6_router_renum *)bp;
cp = (const char *)(rr6 + 1);
ND_TCHECK_4(rr6->rr_reserved);
switch (GET_U_1(rr6->rr_code)) {
case ICMP6_ROUTER_RENUMBERING_COMMAND:
ND_PRINT(", command");
break;
case ICMP6_ROUTER_RENUMBERING_RESULT:
ND_PRINT(", result");
break;
case ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET:
ND_PRINT(", sequence number reset");
break;
default:
ND_PRINT(", code-#%u", GET_U_1(rr6->rr_code));
break;
}
ND_PRINT(", seq=%u", GET_BE_U_4(rr6->rr_seqnum));
if (ndo->ndo_vflag) {
uint8_t rr_flags = GET_U_1(rr6->rr_flags);
#define F(x, y) (rr_flags & (x) ? (y) : "")
ND_PRINT("["); /*]*/
if (rr_flags) {
ND_PRINT("%s%s%s%s%s,", F(ICMP6_RR_FLAGS_TEST, "T"),
F(ICMP6_RR_FLAGS_REQRESULT, "R"),
F(ICMP6_RR_FLAGS_FORCEAPPLY, "A"),
F(ICMP6_RR_FLAGS_SPECSITE, "S"),
F(ICMP6_RR_FLAGS_PREVDONE, "P"));
}
ND_PRINT("seg=%u,", GET_U_1(rr6->rr_segnum));
ND_PRINT("maxdelay=%u", GET_BE_U_2(rr6->rr_maxdelay));
if (GET_BE_U_4(rr6->rr_reserved))
ND_PRINT("rsvd=0x%x", GET_BE_U_4(rr6->rr_reserved));
/*[*/
ND_PRINT("]");
#undef F
}
if (GET_U_1(rr6->rr_code) == ICMP6_ROUTER_RENUMBERING_COMMAND) {
match = (const struct rr_pco_match *)cp;
cp = (const char *)(match + 1);
ND_TCHECK_16(match->rpm_prefix);
if (ndo->ndo_vflag > 1)
ND_PRINT("\n\t");
else
ND_PRINT(" ");
ND_PRINT("match("); /*)*/
switch (GET_U_1(match->rpm_code)) {
case RPM_PCO_ADD: ND_PRINT("add"); break;
case RPM_PCO_CHANGE: ND_PRINT("change"); break;
case RPM_PCO_SETGLOBAL: ND_PRINT("setglobal"); break;
default: ND_PRINT("#%u",
GET_U_1(match->rpm_code)); break;
}
if (ndo->ndo_vflag) {
ND_PRINT(",ord=%u", GET_U_1(match->rpm_ordinal));
ND_PRINT(",min=%u", GET_U_1(match->rpm_minlen));
ND_PRINT(",max=%u", GET_U_1(match->rpm_maxlen));
}
if (addrtostr6(match->rpm_prefix, hbuf, sizeof(hbuf)))
ND_PRINT(",%s/%u", hbuf, GET_U_1(match->rpm_matchlen));
else
ND_PRINT(",?/%u", GET_U_1(match->rpm_matchlen));
/*(*/
ND_PRINT(")");
n = GET_U_1(match->rpm_len) - 3;
if (n % 4)
goto trunc;
n /= 4;
while (n-- > 0) {
use = (const struct rr_pco_use *)cp;
cp = (const char *)(use + 1);
ND_TCHECK_16(use->rpu_prefix);
if (ndo->ndo_vflag > 1)
ND_PRINT("\n\t");
else
ND_PRINT(" ");
ND_PRINT("use("); /*)*/
if (GET_U_1(use->rpu_flags)) {
#define F(x, y) (GET_U_1(use->rpu_flags) & (x) ? (y) : "")
ND_PRINT("%s%s,",
F(ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME, "V"),
F(ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME, "P"));
#undef F
}
if (ndo->ndo_vflag) {
ND_PRINT("mask=0x%x,",
GET_U_1(use->rpu_ramask));
ND_PRINT("raflags=0x%x,",
GET_U_1(use->rpu_raflags));
if (GET_BE_U_4(use->rpu_vltime) == 0xffffffff)
ND_PRINT("vltime=infty,");
else
ND_PRINT("vltime=%u,",
GET_BE_U_4(use->rpu_vltime));
if (GET_BE_U_4(use->rpu_pltime) == 0xffffffff)
ND_PRINT("pltime=infty,");
else
ND_PRINT("pltime=%u,",
GET_BE_U_4(use->rpu_pltime));
}
if (addrtostr6(use->rpu_prefix, hbuf, sizeof(hbuf)))
ND_PRINT("%s/%u/%u", hbuf,
GET_U_1(use->rpu_uselen),
GET_U_1(use->rpu_keeplen));
else
ND_PRINT("?/%u/%u", GET_U_1(use->rpu_uselen),
GET_U_1(use->rpu_keeplen));
/*(*/
ND_PRINT(")");
}
}
return;
trunc:
nd_print_trunc(ndo);
}
diff --git a/contrib/tcpdump/print-igmp.c b/contrib/tcpdump/print-igmp.c
index 914e3d6b342c..68bb5d77cf80 100644
--- a/contrib/tcpdump/print-igmp.c
+++ b/contrib/tcpdump/print-igmp.c
@@ -1,301 +1,299 @@
/*
* Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994, 1995, 1996
* 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.
*/
/* \summary: Internet Group Management Protocol (IGMP) printer */
/*
* specification:
*
* RFC 2236 for IGMPv2
* RFC 3376 for IGMPv3
* draft-asaeda-mboned-mtrace-v2 for the mtrace message
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#ifndef IN_CLASSD
#define IN_CLASSD(i) (((int32_t)(i) & 0xf0000000) == 0xe0000000)
#endif
/* (following from ipmulti/mrouted/prune.h) */
/*
* The packet format for a traceroute request.
*/
struct tr_query {
nd_uint32_t tr_src; /* traceroute source */
nd_uint32_t tr_dst; /* traceroute destination */
nd_uint32_t tr_raddr; /* traceroute response address */
nd_uint8_t tr_rttl; /* response ttl */
nd_uint24_t tr_qid; /* qid */
};
/*
* Traceroute response format. A traceroute response has a tr_query at the
* beginning, followed by one tr_resp for each hop taken.
*/
struct tr_resp {
nd_uint32_t tr_qarr; /* query arrival time */
nd_uint32_t tr_inaddr; /* incoming interface address */
nd_uint32_t tr_outaddr; /* outgoing interface address */
nd_uint32_t tr_rmtaddr; /* parent address in source tree */
nd_uint32_t tr_vifin; /* input packet count on interface */
nd_uint32_t tr_vifout; /* output packet count on interface */
nd_uint32_t tr_pktcnt; /* total incoming packets for src-grp */
nd_uint8_t tr_rproto; /* routing proto deployed on router */
nd_uint8_t tr_fttl; /* ttl required to forward on outvif */
nd_uint8_t tr_smask; /* subnet mask for src addr */
nd_uint8_t tr_rflags; /* forwarding error codes */
};
/* defs within mtrace */
#define TR_QUERY 1
#define TR_RESP 2
/* fields for tr_rflags (forwarding error codes) */
#define TR_NO_ERR 0
#define TR_WRONG_IF 1
#define TR_PRUNED 2
#define TR_OPRUNED 3
#define TR_SCOPED 4
#define TR_NO_RTE 5
#define TR_NO_FWD 7
#define TR_NO_SPACE 0x81
#define TR_OLD_ROUTER 0x82
/* fields for tr_rproto (routing protocol) */
#define TR_PROTO_DVMRP 1
#define TR_PROTO_MOSPF 2
#define TR_PROTO_PIM 3
#define TR_PROTO_CBT 4
/* igmpv3 report types */
static const struct tok igmpv3report2str[] = {
{ 1, "is_in" },
{ 2, "is_ex" },
{ 3, "to_in" },
{ 4, "to_ex" },
{ 5, "allow" },
{ 6, "block" },
{ 0, NULL }
};
static void
print_mtrace(netdissect_options *ndo,
const char *typename,
const u_char *bp, u_int len)
{
const struct tr_query *tr = (const struct tr_query *)(bp + 8);
if (len < 8 + sizeof (struct tr_query)) {
ND_PRINT(" [invalid len %u]", len);
return;
}
ND_PRINT("%s %u: %s to %s reply-to %s",
typename,
GET_BE_U_3(tr->tr_qid),
GET_IPADDR_STRING(tr->tr_src), GET_IPADDR_STRING(tr->tr_dst),
GET_IPADDR_STRING(tr->tr_raddr));
if (IN_CLASSD(GET_BE_U_4(tr->tr_raddr)))
ND_PRINT(" with-ttl %u", GET_U_1(tr->tr_rttl));
}
static void
print_igmpv3_report(netdissect_options *ndo,
const u_char *bp, u_int len)
{
u_int group, nsrcs, ngroups;
u_int i, j;
/* Minimum len is 16, and should be a multiple of 4 */
if (len < 16 || len & 0x03) {
ND_PRINT(" [invalid len %u]", len);
return;
}
ngroups = GET_BE_U_2(bp + 6);
ND_PRINT(", %u group record(s)", ngroups);
if (ndo->ndo_vflag > 0) {
/* Print the group records */
group = 8;
for (i=0; i<ngroups; i++) {
if (len < group+8) {
ND_PRINT(" [invalid number of groups]");
return;
}
ND_PRINT(" [gaddr %s", GET_IPADDR_STRING(bp + group + 4));
ND_PRINT(" %s", tok2str(igmpv3report2str, " [v3-report-#%u]",
GET_U_1(bp + group)));
nsrcs = GET_BE_U_2(bp + group + 2);
/* Check the number of sources and print them */
if (len < group+8+(nsrcs<<2)) {
ND_PRINT(" [invalid number of sources %u]", nsrcs);
return;
}
if (ndo->ndo_vflag == 1)
ND_PRINT(", %u source(s)", nsrcs);
else {
/* Print the sources */
ND_PRINT(" {");
for (j=0; j<nsrcs; j++) {
ND_PRINT(" %s", GET_IPADDR_STRING(bp + group + 8 + (j << 2)));
}
ND_PRINT(" }");
}
/* Next group record */
group += 8 + (nsrcs << 2);
ND_PRINT("]");
}
}
}
static void
print_igmpv3_query(netdissect_options *ndo,
const u_char *bp, u_int len)
{
u_int mrc;
u_int mrt;
u_int nsrcs;
u_int i;
ND_PRINT(" v3");
/* Minimum len is 12, and should be a multiple of 4 */
if (len < 12 || len & 0x03) {
ND_PRINT(" [invalid len %u]", len);
return;
}
mrc = GET_U_1(bp + 1);
if (mrc < 128) {
mrt = mrc;
} else {
mrt = ((mrc & 0x0f) | 0x10) << (((mrc & 0x70) >> 4) + 3);
}
if (mrc != 100) {
ND_PRINT(" [max resp time ");
if (mrt < 600) {
ND_PRINT("%.1fs", mrt * 0.1);
} else {
unsigned_relts_print(ndo, mrt / 10);
}
ND_PRINT("]");
}
if (GET_BE_U_4(bp + 4) == 0)
return;
ND_PRINT(" [gaddr %s", GET_IPADDR_STRING(bp + 4));
nsrcs = GET_BE_U_2(bp + 10);
if (nsrcs > 0) {
if (len < 12 + (nsrcs << 2))
ND_PRINT(" [invalid number of sources]");
else if (ndo->ndo_vflag > 1) {
ND_PRINT(" {");
for (i=0; i<nsrcs; i++) {
ND_PRINT(" %s", GET_IPADDR_STRING(bp + 12 + (i << 2)));
}
ND_PRINT(" }");
} else
ND_PRINT(", %u source(s)", nsrcs);
}
ND_PRINT("]");
}
void
igmp_print(netdissect_options *ndo,
const u_char *bp, u_int len)
{
struct cksum_vec vec[1];
ndo->ndo_protocol = "igmp";
if (ndo->ndo_qflag) {
ND_PRINT("igmp");
return;
}
switch (GET_U_1(bp)) {
case 0x11:
ND_PRINT("igmp query");
if (len >= 12)
print_igmpv3_query(ndo, bp, len);
else {
if (GET_U_1(bp + 1)) {
ND_PRINT(" v2");
if (GET_U_1(bp + 1) != 100)
ND_PRINT(" [max resp time %u]", GET_U_1(bp + 1));
} else
ND_PRINT(" v1");
if (GET_BE_U_4(bp + 4))
ND_PRINT(" [gaddr %s]", GET_IPADDR_STRING(bp + 4));
if (len != 8)
ND_PRINT(" [len %u]", len);
}
break;
case 0x12:
ND_PRINT("igmp v1 report %s", GET_IPADDR_STRING(bp + 4));
if (len != 8)
ND_PRINT(" [len %u]", len);
break;
case 0x16:
ND_PRINT("igmp v2 report %s", GET_IPADDR_STRING(bp + 4));
break;
case 0x22:
ND_PRINT("igmp v3 report");
print_igmpv3_report(ndo, bp, len);
break;
case 0x17:
ND_PRINT("igmp leave %s", GET_IPADDR_STRING(bp + 4));
break;
case 0x13:
ND_PRINT("igmp dvmrp");
if (len < 8)
ND_PRINT(" [len %u]", len);
else
dvmrp_print(ndo, bp, len);
break;
case 0x14:
ND_PRINT("igmp pimv1");
pimv1_print(ndo, bp, len);
break;
case 0x1e:
print_mtrace(ndo, "mresp", bp, len);
break;
case 0x1f:
print_mtrace(ndo, "mtrace", bp, len);
break;
default:
ND_PRINT("igmp-%u", GET_U_1(bp));
break;
}
if (ndo->ndo_vflag && len >= 4 && ND_TTEST_LEN(bp, len)) {
/* Check the IGMP checksum */
vec[0].ptr = bp;
vec[0].len = len;
if (in_cksum(vec, 1))
ND_PRINT(" bad igmp cksum %x!", GET_BE_U_2(bp + 2));
}
}
diff --git a/contrib/tcpdump/print-igrp.c b/contrib/tcpdump/print-igrp.c
index 23dc1f5688af..26259b46d7b1 100644
--- a/contrib/tcpdump/print-igrp.c
+++ b/contrib/tcpdump/print-igrp.c
@@ -1,149 +1,147 @@
/*
* Copyright (c) 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.
*
* Initial contribution from Francis Dupont (francis.dupont@inria.fr)
*/
/* \summary: Interior Gateway Routing Protocol (IGRP) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "extract.h"
/* Cisco IGRP definitions */
/* IGRP Header */
struct igrphdr {
nd_uint8_t ig_vop; /* protocol version number / opcode */
#define IGRP_V(x) (((x) & 0xf0) >> 4)
#define IGRP_OP(x) ((x) & 0x0f)
nd_uint8_t ig_ed; /* edition number */
nd_uint16_t ig_as; /* autonomous system number */
nd_uint16_t ig_ni; /* number of subnet in local net */
nd_uint16_t ig_ns; /* number of networks in AS */
nd_uint16_t ig_nx; /* number of networks outside AS */
nd_uint16_t ig_sum; /* checksum of IGRP header & data */
};
#define IGRP_UPDATE 1
#define IGRP_REQUEST 2
/* IGRP routing entry */
struct igrprte {
nd_byte igr_net[3]; /* 3 significant octets of IP address */
nd_uint24_t igr_dly; /* delay in tens of microseconds */
nd_uint24_t igr_bw; /* bandwidth in units of 1 kb/s */
nd_uint16_t igr_mtu; /* MTU in octets */
nd_uint8_t igr_rel; /* percent packets successfully tx/rx */
nd_uint8_t igr_ld; /* percent of channel occupied */
nd_uint8_t igr_hct; /* hop count */
};
#define IGRP_RTE_SIZE 14 /* sizeof() is accurate now */
static void
igrp_entry_print(netdissect_options *ndo, const struct igrprte *igr)
{
u_int delay, bandwidth;
u_int metric, mtu;
delay = GET_BE_U_3(igr->igr_dly);
bandwidth = GET_BE_U_3(igr->igr_bw);
metric = ND_MIN(bandwidth + delay, 0xffffff);
mtu = GET_BE_U_2(igr->igr_mtu);
ND_PRINT(" d=%u b=%u r=%u l=%u M=%u mtu=%u in %u hops",
10 * delay, bandwidth == 0 ? 0 : 10000000 / bandwidth,
GET_U_1(igr->igr_rel), GET_U_1(igr->igr_ld), metric,
mtu, GET_U_1(igr->igr_hct));
}
static const struct tok op2str[] = {
{ IGRP_UPDATE, "update" },
{ IGRP_REQUEST, "request" },
{ 0, NULL }
};
void
igrp_print(netdissect_options *ndo, const u_char *bp, u_int length)
{
const struct igrphdr *hdr;
const u_char *cp;
u_int nint, nsys, next;
uint16_t cksum;
ndo->ndo_protocol = "igrp";
hdr = (const struct igrphdr *)bp;
cp = (const u_char *)(hdr + 1);
ND_PRINT("igrp:");
/* Header */
nint = GET_BE_U_2(hdr->ig_ni);
nsys = GET_BE_U_2(hdr->ig_ns);
next = GET_BE_U_2(hdr->ig_nx);
ND_PRINT(" %s V%u edit=%u AS=%u (%u/%u/%u)",
tok2str(op2str, "op-#%u", IGRP_OP(GET_U_1(hdr->ig_vop))),
IGRP_V(GET_U_1(hdr->ig_vop)),
GET_U_1(hdr->ig_ed),
GET_BE_U_2(hdr->ig_as),
nint,
nsys,
next);
cksum = GET_BE_U_2(hdr->ig_sum);
if (ndo->ndo_vflag)
ND_PRINT(" checksum=0x%04x", cksum);
length -= sizeof(*hdr);
while (length >= IGRP_RTE_SIZE) {
const struct igrprte *igr = (const struct igrprte *)cp;
uint8_t net0 = GET_U_1(&igr->igr_net[0]);
uint8_t net1 = GET_U_1(&igr->igr_net[1]);
uint8_t net2 = GET_U_1(&igr->igr_net[2]);
if (nint > 0) {
ND_PRINT(" *.%u.%u.%u", net0, net1, net2);
igrp_entry_print(ndo, igr);
--nint;
} else if (nsys > 0) {
ND_PRINT(" %u.%u.%u.0", net0, net1, net2);
igrp_entry_print(ndo, igr);
--nsys;
} else if (next > 0) {
ND_PRINT(" X%u.%u.%u.0", net0, net1, net2);
igrp_entry_print(ndo, igr);
--next;
} else {
ND_PRINT(" [extra bytes %u]", length);
break;
}
cp += IGRP_RTE_SIZE;
length -= IGRP_RTE_SIZE;
}
if (nint || nsys || next || length)
nd_print_invalid(ndo);
}
diff --git a/contrib/tcpdump/print-ip-demux.c b/contrib/tcpdump/print-ip-demux.c
index 758601910881..f2102bb55d73 100644
--- a/contrib/tcpdump/print-ip-demux.c
+++ b/contrib/tcpdump/print-ip-demux.c
@@ -1,237 +1,235 @@
/*
* Copyright (c) 1988, 1989, 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.
*/
/* \summary: IPv4/IPv6 payload printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#include "ip.h"
#include "ipproto.h"
void
ip_demux_print(netdissect_options *ndo,
const u_char *bp,
u_int length, u_int ver, int fragmented, u_int ttl_hl,
uint8_t nh, const u_char *iph)
{
int advance;
const char *p_name;
advance = 0;
again:
switch (nh) {
case IPPROTO_AH:
if (!ND_TTEST_1(bp)) {
ndo->ndo_protocol = "ah";
nd_print_trunc(ndo);
break;
}
nh = GET_U_1(bp);
advance = ah_print(ndo, bp);
if (advance <= 0)
break;
bp += advance;
length -= advance;
goto again;
case IPPROTO_ESP:
{
esp_print(ndo, bp, length, iph, ver, fragmented, ttl_hl);
/*
* Either this has decrypted the payload and
* printed it, in which case there's nothing more
* to do, or it hasn't, in which case there's
* nothing more to do.
*/
break;
}
case IPPROTO_IPCOMP:
{
ipcomp_print(ndo, bp);
/*
* Either this has decompressed the payload and
* printed it, in which case there's nothing more
* to do, or it hasn't, in which case there's
* nothing more to do.
*/
break;
}
case IPPROTO_SCTP:
sctp_print(ndo, bp, iph, length);
break;
case IPPROTO_DCCP:
dccp_print(ndo, bp, iph, length);
break;
case IPPROTO_TCP:
tcp_print(ndo, bp, length, iph, fragmented);
break;
case IPPROTO_UDP:
udp_print(ndo, bp, length, iph, fragmented, ttl_hl);
break;
case IPPROTO_ICMP:
if (ver == 4)
icmp_print(ndo, bp, length, iph, fragmented);
else {
ND_PRINT("[%s requires IPv4]",
tok2str(ipproto_values,"unknown",nh));
nd_print_invalid(ndo);
}
break;
case IPPROTO_ICMPV6:
if (ver == 6)
icmp6_print(ndo, bp, length, iph, fragmented);
else {
ND_PRINT("[%s requires IPv6]",
tok2str(ipproto_values,"unknown",nh));
nd_print_invalid(ndo);
}
break;
case IPPROTO_PIGP:
/*
* XXX - the current IANA protocol number assignments
* page lists 9 as "any private interior gateway
* (used by Cisco for their IGRP)" and 88 as
* "EIGRP" from Cisco.
*
* Recent BSD <netinet/in.h> headers define
* IP_PROTO_PIGP as 9 and IP_PROTO_IGRP as 88.
* We define IP_PROTO_PIGP as 9 and
* IP_PROTO_EIGRP as 88; those names better
* match was the current protocol number
* assignments say.
*/
igrp_print(ndo, bp, length);
break;
case IPPROTO_EIGRP:
eigrp_print(ndo, bp, length);
break;
case IPPROTO_ND:
ND_PRINT(" nd %u", length);
break;
case IPPROTO_EGP:
egp_print(ndo, bp, length);
break;
case IPPROTO_OSPF:
if (ver == 6)
ospf6_print(ndo, bp, length);
else
ospf_print(ndo, bp, length, iph);
break;
case IPPROTO_IGMP:
if (ver == 4)
igmp_print(ndo, bp, length);
else {
ND_PRINT("[%s requires IPv4]",
tok2str(ipproto_values,"unknown",nh));
nd_print_invalid(ndo);
}
break;
case IPPROTO_IPV4:
/* ipv4-in-ip encapsulation */
ip_print(ndo, bp, length);
break;
case IPPROTO_IPV6:
/* ip6-in-ip encapsulation */
ip6_print(ndo, bp, length);
break;
case IPPROTO_RSVP:
rsvp_print(ndo, bp, length);
break;
case IPPROTO_GRE:
gre_print(ndo, bp, length);
break;
case IPPROTO_MOBILE:
mobile_print(ndo, bp, length);
break;
case IPPROTO_PIM:
pim_print(ndo, bp, length, iph);
break;
case IPPROTO_VRRP:
if (ndo->ndo_packettype == PT_CARP) {
carp_print(ndo, bp, length, ttl_hl);
} else {
vrrp_print(ndo, bp, length, iph, ttl_hl, ver);
}
break;
case IPPROTO_PGM:
pgm_print(ndo, bp, length, iph);
break;
case IPPROTO_ETHERNET:
if (ver == 6)
ether_print(ndo, bp, length, ND_BYTES_AVAILABLE_AFTER(bp), NULL, NULL);
else {
ND_PRINT("[%s requires IPv6]",
tok2str(ipproto_values,"unknown",nh));
nd_print_invalid(ndo);
}
break;
#ifdef HAVE_NET_IF_PFLOG_H
case IPPROTO_PFSYNC:
pfsync_ip_print(ndo, bp, length);
break;
#endif
case IPPROTO_NONE:
ND_PRINT("no next header");
break;
default:
if (ndo->ndo_nflag==0 && (p_name = netdb_protoname(nh)) != NULL)
ND_PRINT(" %s", p_name);
else
ND_PRINT(" ip-proto-%u", nh);
ND_PRINT(" %u", length);
break;
}
}
diff --git a/contrib/tcpdump/print-ip.c b/contrib/tcpdump/print-ip.c
index 23ba99c97007..5edc62215e27 100644
--- a/contrib/tcpdump/print-ip.c
+++ b/contrib/tcpdump/print-ip.c
@@ -1,538 +1,528 @@
/*
* Copyright (c) 1988, 1989, 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.
*/
/* \summary: IP printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#include "ip.h"
#include "ipproto.h"
static const struct tok ip_option_values[] = {
{ IPOPT_EOL, "EOL" },
{ IPOPT_NOP, "NOP" },
{ IPOPT_TS, "timestamp" },
{ IPOPT_SECURITY, "security" },
{ IPOPT_RR, "RR" },
{ IPOPT_SSRR, "SSRR" },
{ IPOPT_LSRR, "LSRR" },
{ IPOPT_RA, "RA" },
{ IPOPT_RFC1393, "traceroute" },
{ 0, NULL }
};
/*
* print the recorded route in an IP RR, LSRR or SSRR option.
*/
static int
ip_printroute(netdissect_options *ndo,
const u_char *cp, u_int length)
{
u_int ptr;
u_int len;
if (length < 3) {
ND_PRINT(" [bad length %u]", length);
return (0);
}
if ((length + 1) & 3)
ND_PRINT(" [bad length %u]", length);
ptr = GET_U_1(cp + 2) - 1;
if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1)
ND_PRINT(" [bad ptr %u]", GET_U_1(cp + 2));
for (len = 3; len < length; len += 4) {
ND_TCHECK_4(cp + len); /* Needed to print the IP addresses */
ND_PRINT(" %s", GET_IPADDR_STRING(cp + len));
if (ptr > len)
ND_PRINT(",");
}
return (0);
trunc:
return (-1);
}
/*
* If source-routing is present and valid, return the final destination.
* Otherwise, return IP destination.
*
* This is used for UDP and TCP pseudo-header in the checksum
* calculation.
*/
static uint32_t
ip_finddst(netdissect_options *ndo,
const struct ip *ip)
{
u_int length;
u_int len;
const u_char *cp;
cp = (const u_char *)(ip + 1);
length = IP_HL(ip) * 4;
if (length < sizeof(struct ip))
goto trunc;
length -= sizeof(struct ip);
for (; length != 0; cp += len, length -= len) {
int tt;
tt = GET_U_1(cp);
if (tt == IPOPT_EOL)
break;
else if (tt == IPOPT_NOP)
len = 1;
else {
len = GET_U_1(cp + 1);
if (len < 2)
break;
}
if (length < len)
goto trunc;
ND_TCHECK_LEN(cp, len);
switch (tt) {
case IPOPT_SSRR:
case IPOPT_LSRR:
if (len < 7)
break;
return (GET_IPV4_TO_NETWORK_ORDER(cp + len - 4));
}
}
trunc:
return (GET_IPV4_TO_NETWORK_ORDER(ip->ip_dst));
}
/*
* Compute a V4-style checksum by building a pseudoheader.
*/
uint16_t
nextproto4_cksum(netdissect_options *ndo,
const struct ip *ip, const uint8_t *data,
u_int len, u_int covlen, uint8_t next_proto)
{
struct phdr {
uint32_t src;
uint32_t dst;
uint8_t mbz;
uint8_t proto;
uint16_t len;
} ph;
struct cksum_vec vec[2];
/* pseudo-header.. */
ph.len = htons((uint16_t)len);
ph.mbz = 0;
ph.proto = next_proto;
ph.src = GET_IPV4_TO_NETWORK_ORDER(ip->ip_src);
if (IP_HL(ip) == 5)
ph.dst = GET_IPV4_TO_NETWORK_ORDER(ip->ip_dst);
else
ph.dst = ip_finddst(ndo, ip);
vec[0].ptr = (const uint8_t *)(void *)&ph;
vec[0].len = sizeof(ph);
vec[1].ptr = data;
vec[1].len = covlen;
return (in_cksum(vec, 2));
}
static int
ip_printts(netdissect_options *ndo,
const u_char *cp, u_int length)
{
u_int ptr;
u_int len;
u_int hoplen;
const char *type;
if (length < 4) {
ND_PRINT("[bad length %u]", length);
return (0);
}
ND_PRINT(" TS{");
hoplen = ((GET_U_1(cp + 3) & 0xF) != IPOPT_TS_TSONLY) ? 8 : 4;
if ((length - 4) & (hoplen-1))
ND_PRINT("[bad length %u]", length);
ptr = GET_U_1(cp + 2) - 1;
len = 0;
if (ptr < 4 || ((ptr - 4) & (hoplen-1)) || ptr > length + 1)
ND_PRINT("[bad ptr %u]", GET_U_1(cp + 2));
switch (GET_U_1(cp + 3)&0xF) {
case IPOPT_TS_TSONLY:
ND_PRINT("TSONLY");
break;
case IPOPT_TS_TSANDADDR:
ND_PRINT("TS+ADDR");
break;
case IPOPT_TS_PRESPEC:
ND_PRINT("PRESPEC");
break;
default:
ND_PRINT("[bad ts type %u]", GET_U_1(cp + 3)&0xF);
goto done;
}
type = " ";
for (len = 4; len < length; len += hoplen) {
if (ptr == len)
type = " ^ ";
ND_TCHECK_LEN(cp + len, hoplen);
ND_PRINT("%s%u@%s", type, GET_BE_U_4(cp + len + hoplen - 4),
hoplen!=8 ? "" : GET_IPADDR_STRING(cp + len));
type = " ";
}
done:
ND_PRINT("%s", ptr == len ? " ^ " : "");
if (GET_U_1(cp + 3) >> 4)
ND_PRINT(" [%u hops not recorded]} ", GET_U_1(cp + 3)>>4);
else
ND_PRINT("}");
return (0);
trunc:
return (-1);
}
/*
* print IP options.
If truncated return -1, else 0.
*/
static int
ip_optprint(netdissect_options *ndo,
const u_char *cp, u_int length)
{
u_int option_len;
const char *sep = "";
for (; length > 0; cp += option_len, length -= option_len) {
u_int option_code;
ND_PRINT("%s", sep);
sep = ",";
option_code = GET_U_1(cp);
ND_PRINT("%s",
tok2str(ip_option_values,"unknown %u",option_code));
if (option_code == IPOPT_NOP ||
option_code == IPOPT_EOL)
option_len = 1;
else {
option_len = GET_U_1(cp + 1);
if (option_len < 2) {
ND_PRINT(" [bad length %u]", option_len);
return 0;
}
}
if (option_len > length) {
ND_PRINT(" [bad length %u]", option_len);
return 0;
}
ND_TCHECK_LEN(cp, option_len);
switch (option_code) {
case IPOPT_EOL:
return 0;
case IPOPT_TS:
if (ip_printts(ndo, cp, option_len) == -1)
goto trunc;
break;
case IPOPT_RR: /* fall through */
case IPOPT_SSRR:
case IPOPT_LSRR:
if (ip_printroute(ndo, cp, option_len) == -1)
goto trunc;
break;
case IPOPT_RA:
if (option_len < 4) {
ND_PRINT(" [bad length %u]", option_len);
break;
}
ND_TCHECK_1(cp + 3);
if (GET_BE_U_2(cp + 2) != 0)
ND_PRINT(" value %u", GET_BE_U_2(cp + 2));
break;
case IPOPT_NOP: /* nothing to print - fall through */
case IPOPT_SECURITY:
default:
break;
}
}
return 0;
trunc:
return -1;
}
#define IP_RES 0x8000
static const struct tok ip_frag_values[] = {
{ IP_MF, "+" },
{ IP_DF, "DF" },
{ IP_RES, "rsvd" }, /* The RFC3514 evil ;-) bit */
{ 0, NULL }
};
/*
* print an IP datagram.
*/
void
ip_print(netdissect_options *ndo,
const u_char *bp,
- u_int length)
+ const u_int length)
{
const struct ip *ip;
u_int off;
u_int hlen;
u_int len;
struct cksum_vec vec[1];
uint8_t ip_tos, ip_ttl, ip_proto;
uint16_t sum, ip_sum;
const char *p_name;
int truncated = 0;
+ int presumed_tso = 0;
ndo->ndo_protocol = "ip";
ip = (const struct ip *)bp;
- if (IP_V(ip) != 4) { /* print version and fail if != 4 */
- if (IP_V(ip) == 6)
- ND_PRINT("IP6, wrong link-layer encapsulation");
- else
- ND_PRINT("IP%u", IP_V(ip));
- nd_print_invalid(ndo);
- return;
- }
- if (!ndo->ndo_eflag)
- ND_PRINT("IP ");
- ND_TCHECK_SIZE(ip);
- if (length < sizeof (struct ip)) {
- ND_PRINT("truncated-ip %u", length);
- return;
+ if (!ndo->ndo_eflag) {
+ nd_print_protocol_caps(ndo);
+ ND_PRINT(" ");
}
+
+ ND_ICHECK_ZU(length, <, sizeof (struct ip));
+ ND_ICHECKMSG_U("version", IP_V(ip), !=, 4);
+
hlen = IP_HL(ip) * 4;
- if (hlen < sizeof (struct ip)) {
- ND_PRINT("bad-hlen %u", hlen);
- return;
- }
+ ND_ICHECKMSG_ZU("header length", hlen, <, sizeof (struct ip));
len = GET_BE_U_2(ip->ip_len);
- if (length < len)
- ND_PRINT("truncated-ip - %u bytes missing! ",
- len - length);
- if (len < hlen) {
-#ifdef GUESS_TSO
- if (len) {
- ND_PRINT("bad-len %u", len);
- return;
- }
- else {
- /* we guess that it is a TSO send */
- len = length;
- }
-#else
- ND_PRINT("bad-len %u", len);
- return;
-#endif /* GUESS_TSO */
+ if (len > length) {
+ ND_PRINT("[total length %u > length %u]", len, length);
+ nd_print_invalid(ndo);
+ ND_PRINT(" ");
}
+ if (len == 0) {
+ /* we guess that it is a TSO send */
+ len = length;
+ presumed_tso = 1;
+ } else
+ ND_ICHECKMSG_U("total length", len, <, hlen);
+ ND_TCHECK_SIZE(ip);
/*
* Cut off the snapshot length to the end of the IP payload.
*/
if (!nd_push_snaplen(ndo, bp, len)) {
(*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC,
"%s: can't push snaplen on buffer stack", __func__);
}
len -= hlen;
off = GET_BE_U_2(ip->ip_off);
ip_proto = GET_U_1(ip->ip_p);
if (ndo->ndo_vflag) {
ip_tos = GET_U_1(ip->ip_tos);
ND_PRINT("(tos 0x%x", ip_tos);
/* ECN bits */
switch (ip_tos & 0x03) {
case 0:
break;
case 1:
ND_PRINT(",ECT(1)");
break;
case 2:
ND_PRINT(",ECT(0)");
break;
case 3:
ND_PRINT(",CE");
break;
}
ip_ttl = GET_U_1(ip->ip_ttl);
if (ip_ttl >= 1)
ND_PRINT(", ttl %u", ip_ttl);
/*
* for the firewall guys, print id, offset.
* On all but the last stick a "+" in the flags portion.
* For unfragmented datagrams, note the don't fragment flag.
*/
ND_PRINT(", id %u, offset %u, flags [%s], proto %s (%u)",
GET_BE_U_2(ip->ip_id),
(off & IP_OFFMASK) * 8,
bittok2str(ip_frag_values, "none", off & (IP_RES|IP_DF|IP_MF)),
tok2str(ipproto_values, "unknown", ip_proto),
ip_proto);
- ND_PRINT(", length %u", GET_BE_U_2(ip->ip_len));
+ if (presumed_tso)
+ ND_PRINT(", length %u [was 0, presumed TSO]", length);
+ else
+ ND_PRINT(", length %u", GET_BE_U_2(ip->ip_len));
if ((hlen - sizeof(struct ip)) > 0) {
ND_PRINT(", options (");
if (ip_optprint(ndo, (const u_char *)(ip + 1),
hlen - sizeof(struct ip)) == -1) {
ND_PRINT(" [truncated-option]");
truncated = 1;
}
ND_PRINT(")");
}
if (!ndo->ndo_Kflag && (const u_char *)ip + hlen <= ndo->ndo_snapend) {
vec[0].ptr = (const uint8_t *)(const void *)ip;
vec[0].len = hlen;
sum = in_cksum(vec, 1);
if (sum != 0) {
ip_sum = GET_BE_U_2(ip->ip_sum);
ND_PRINT(", bad cksum %x (->%x)!", ip_sum,
in_cksum_shouldbe(ip_sum, sum));
}
}
ND_PRINT(")\n ");
if (truncated) {
ND_PRINT("%s > %s: ",
GET_IPADDR_STRING(ip->ip_src),
GET_IPADDR_STRING(ip->ip_dst));
nd_print_trunc(ndo);
nd_pop_packet_info(ndo);
return;
}
}
/*
* If this is fragment zero, hand it to the next higher
* level protocol. Let them know whether there are more
* fragments.
*/
if ((off & IP_OFFMASK) == 0) {
uint8_t nh = GET_U_1(ip->ip_p);
if (nh != IPPROTO_TCP && nh != IPPROTO_UDP &&
nh != IPPROTO_SCTP && nh != IPPROTO_DCCP) {
ND_PRINT("%s > %s: ",
GET_IPADDR_STRING(ip->ip_src),
GET_IPADDR_STRING(ip->ip_dst));
}
/*
* Do a bounds check before calling ip_demux_print().
* At least the header data is required.
*/
if (!ND_TTEST_LEN((const u_char *)ip, hlen)) {
ND_PRINT(" [remaining caplen(%u) < header length(%u)]",
ND_BYTES_AVAILABLE_AFTER((const u_char *)ip),
hlen);
nd_trunc_longjmp(ndo);
}
ip_demux_print(ndo, (const u_char *)ip + hlen, len, 4,
off & IP_MF, GET_U_1(ip->ip_ttl), nh, bp);
} else {
/*
* Ultra quiet now means that all this stuff should be
* suppressed.
*/
if (ndo->ndo_qflag > 1) {
nd_pop_packet_info(ndo);
return;
}
/*
* This isn't the first frag, so we're missing the
* next level protocol header. print the ip addr
* and the protocol.
*/
ND_PRINT("%s > %s:", GET_IPADDR_STRING(ip->ip_src),
GET_IPADDR_STRING(ip->ip_dst));
if (!ndo->ndo_nflag && (p_name = netdb_protoname(ip_proto)) != NULL)
ND_PRINT(" %s", p_name);
else
ND_PRINT(" ip-proto-%u", ip_proto);
}
nd_pop_packet_info(ndo);
return;
trunc:
nd_print_trunc(ndo);
+ return;
+
+invalid:
+ nd_print_invalid(ndo);
}
void
ipN_print(netdissect_options *ndo, const u_char *bp, u_int length)
{
ndo->ndo_protocol = "ipn";
if (length < 1) {
ND_PRINT("truncated-ip %u", length);
return;
}
switch (GET_U_1(bp) & 0xF0) {
case 0x40:
ip_print(ndo, bp, length);
break;
case 0x60:
ip6_print(ndo, bp, length);
break;
default:
ND_PRINT("unknown ip %u", (GET_U_1(bp) & 0xF0) >> 4);
break;
}
}
diff --git a/contrib/tcpdump/print-ip6.c b/contrib/tcpdump/print-ip6.c
index 2f1183c00699..dc4aa268b9ca 100644
--- a/contrib/tcpdump/print-ip6.c
+++ b/contrib/tcpdump/print-ip6.c
@@ -1,502 +1,505 @@
/*
* Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994
* 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.
*/
/* \summary: IPv6 printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <string.h>
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#include "ip6.h"
#include "ipproto.h"
/*
* If routing headers are presend and valid, set dst to the final destination.
* Otherwise, set it to the IPv6 destination.
*
* This is used for UDP and TCP pseudo-header in the checksum
* calculation.
*/
static void
ip6_finddst(netdissect_options *ndo, nd_ipv6 *dst,
const struct ip6_hdr *ip6)
{
const u_char *cp;
u_int advance;
u_int nh;
const void *dst_addr;
const struct ip6_rthdr *dp;
const struct ip6_rthdr0 *dp0;
const struct ip6_srh *srh;
const u_char *p;
int i, len;
cp = (const u_char *)ip6;
advance = sizeof(struct ip6_hdr);
nh = GET_U_1(ip6->ip6_nxt);
dst_addr = (const void *)ip6->ip6_dst;
while (cp < ndo->ndo_snapend) {
cp += advance;
switch (nh) {
case IPPROTO_HOPOPTS:
case IPPROTO_DSTOPTS:
case IPPROTO_MOBILITY_OLD:
case IPPROTO_MOBILITY:
/*
* These have a header length byte, following
* the next header byte, giving the length of
* the header, in units of 8 octets, excluding
* the first 8 octets.
*/
advance = (GET_U_1(cp + 1) + 1) << 3;
nh = GET_U_1(cp);
break;
case IPPROTO_FRAGMENT:
/*
* The byte following the next header byte is
* marked as reserved, and the header is always
* the same size.
*/
advance = sizeof(struct ip6_frag);
nh = GET_U_1(cp);
break;
case IPPROTO_ROUTING:
/*
* OK, we found it.
*/
dp = (const struct ip6_rthdr *)cp;
ND_TCHECK_SIZE(dp);
len = GET_U_1(dp->ip6r_len);
switch (GET_U_1(dp->ip6r_type)) {
case IPV6_RTHDR_TYPE_0:
case IPV6_RTHDR_TYPE_2: /* Mobile IPv6 ID-20 */
dp0 = (const struct ip6_rthdr0 *)dp;
if (len % 2 == 1)
goto trunc;
len >>= 1;
p = (const u_char *) dp0->ip6r0_addr;
for (i = 0; i < len; i++) {
ND_TCHECK_16(p);
dst_addr = (const void *)p;
p += 16;
}
break;
case IPV6_RTHDR_TYPE_4:
/* IPv6 Segment Routing Header (SRH) */
srh = (const struct ip6_srh *)dp;
if (len % 2 == 1)
goto trunc;
p = (const u_char *) srh->srh_segments;
/*
* The list of segments are encoded in the reverse order.
* Accordingly, the final DA is encoded in srh_segments[0]
*/
ND_TCHECK_16(p);
dst_addr = (const void *)p;
break;
default:
break;
}
/*
* Only one routing header to a customer.
*/
goto done;
case IPPROTO_AH:
case IPPROTO_ESP:
case IPPROTO_IPCOMP:
default:
/*
* AH and ESP are, in the RFCs that describe them,
* described as being "viewed as an end-to-end
* payload" "in the IPv6 context, so that they
* "should appear after hop-by-hop, routing, and
* fragmentation extension headers". We assume
* that's the case, and stop as soon as we see
* one. (We can't handle an ESP header in
* the general case anyway, as its length depends
* on the encryption algorithm.)
*
* IPComp is also "viewed as an end-to-end
* payload" "in the IPv6 context".
*
* All other protocols are assumed to be the final
* protocol.
*/
goto done;
}
}
done:
trunc:
GET_CPY_BYTES(dst, dst_addr, sizeof(nd_ipv6));
}
/*
* Compute a V6-style checksum by building a pseudoheader.
*/
uint16_t
nextproto6_cksum(netdissect_options *ndo,
const struct ip6_hdr *ip6, const uint8_t *data,
u_int len, u_int covlen, uint8_t next_proto)
{
struct {
nd_ipv6 ph_src;
nd_ipv6 ph_dst;
uint32_t ph_len;
uint8_t ph_zero[3];
uint8_t ph_nxt;
} ph;
struct cksum_vec vec[2];
u_int nh;
/* pseudo-header */
memset(&ph, 0, sizeof(ph));
GET_CPY_BYTES(&ph.ph_src, ip6->ip6_src, sizeof(nd_ipv6));
nh = GET_U_1(ip6->ip6_nxt);
switch (nh) {
case IPPROTO_HOPOPTS:
case IPPROTO_DSTOPTS:
case IPPROTO_MOBILITY_OLD:
case IPPROTO_MOBILITY:
case IPPROTO_FRAGMENT:
case IPPROTO_ROUTING:
/*
* The next header is either a routing header or a header
* after which there might be a routing header, so scan
* for a routing header.
*/
ip6_finddst(ndo, &ph.ph_dst, ip6);
break;
default:
GET_CPY_BYTES(&ph.ph_dst, ip6->ip6_dst, sizeof(nd_ipv6));
break;
}
ph.ph_len = htonl(len);
ph.ph_nxt = next_proto;
vec[0].ptr = (const uint8_t *)(void *)&ph;
vec[0].len = sizeof(ph);
vec[1].ptr = data;
vec[1].len = covlen;
return in_cksum(vec, 2);
}
/*
* print an IP6 datagram.
*/
void
ip6_print(netdissect_options *ndo, const u_char *bp, u_int length)
{
const struct ip6_hdr *ip6;
int advance;
u_int len;
u_int total_advance;
const u_char *cp;
uint32_t payload_len;
uint8_t ph, nh;
int fragmented = 0;
u_int flow;
int found_extension_header;
int found_jumbo;
int found_hbh;
ndo->ndo_protocol = "ip6";
ip6 = (const struct ip6_hdr *)bp;
- ND_TCHECK_SIZE(ip6);
- if (length < sizeof (struct ip6_hdr)) {
- ND_PRINT("truncated-ip6 %u", length);
- return;
+ if (!ndo->ndo_eflag) {
+ nd_print_protocol_caps(ndo);
+ ND_PRINT(" ");
}
- if (!ndo->ndo_eflag)
- ND_PRINT("IP6 ");
-
- if (IP6_VERSION(ip6) != 6) {
- ND_PRINT("version error: %u != 6", IP6_VERSION(ip6));
- return;
- }
+ ND_ICHECK_ZU(length, <, sizeof (struct ip6_hdr));
+ ND_ICHECKMSG_U("version", IP6_VERSION(ip6), !=, 6);
payload_len = GET_BE_U_2(ip6->ip6_plen);
/*
* RFC 1883 says:
*
* The Payload Length field in the IPv6 header must be set to zero
* in every packet that carries the Jumbo Payload option. If a
* packet is received with a valid Jumbo Payload option present and
* a non-zero IPv6 Payload Length field, an ICMP Parameter Problem
* message, Code 0, should be sent to the packet's source, pointing
* to the Option Type field of the Jumbo Payload option.
*
* Later versions of the IPv6 spec don't discuss the Jumbo Payload
* option.
*
* If the payload length is 0, we temporarily just set the total
* length to the remaining data in the packet (which, for Ethernet,
* could include frame padding, but if it's a Jumbo Payload frame,
* it shouldn't even be sendable over Ethernet, so we don't worry
* about that), so we can process the extension headers in order
* to *find* a Jumbo Payload hop-by-hop option and, when we've
* processed all the extension headers, check whether we found
* a Jumbo Payload option, and fail if we haven't.
*/
if (payload_len != 0) {
len = payload_len + sizeof(struct ip6_hdr);
- if (length < len)
- ND_PRINT("truncated-ip6 - %u bytes missing!",
- len - length);
+ if (len > length) {
+ ND_PRINT("[header+payload length %u > length %u]",
+ len, length);
+ nd_print_invalid(ndo);
+ ND_PRINT(" ");
+ }
} else
len = length + sizeof(struct ip6_hdr);
ph = 255;
nh = GET_U_1(ip6->ip6_nxt);
if (ndo->ndo_vflag) {
flow = GET_BE_U_4(ip6->ip6_flow);
ND_PRINT("(");
/* RFC 2460 */
if (flow & 0x0ff00000)
ND_PRINT("class 0x%02x, ", (flow & 0x0ff00000) >> 20);
if (flow & 0x000fffff)
ND_PRINT("flowlabel 0x%05x, ", flow & 0x000fffff);
ND_PRINT("hlim %u, next-header %s (%u) payload length: %u) ",
GET_U_1(ip6->ip6_hlim),
tok2str(ipproto_values,"unknown",nh),
nh,
payload_len);
}
+ ND_TCHECK_SIZE(ip6);
/*
* Cut off the snapshot length to the end of the IP payload.
*/
if (!nd_push_snaplen(ndo, bp, len)) {
(*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC,
"%s: can't push snaplen on buffer stack", __func__);
}
cp = (const u_char *)ip6;
advance = sizeof(struct ip6_hdr);
total_advance = 0;
/* Process extension headers */
found_extension_header = 0;
found_jumbo = 0;
found_hbh = 0;
while (cp < ndo->ndo_snapend && advance > 0) {
if (len < (u_int)advance)
goto trunc;
cp += advance;
len -= advance;
total_advance += advance;
if (cp == (const u_char *)(ip6 + 1) &&
nh != IPPROTO_TCP && nh != IPPROTO_UDP &&
nh != IPPROTO_DCCP && nh != IPPROTO_SCTP) {
ND_PRINT("%s > %s: ", GET_IP6ADDR_STRING(ip6->ip6_src),
- GET_IP6ADDR_STRING(ip6->ip6_dst));
+ GET_IP6ADDR_STRING(ip6->ip6_dst));
}
switch (nh) {
case IPPROTO_HOPOPTS:
/*
* The Hop-by-Hop Options header, when present,
* must immediately follow the IPv6 header (RFC 8200)
*/
if (found_hbh == 1) {
ND_PRINT("[The Hop-by-Hop Options header was already found]");
nd_print_invalid(ndo);
return;
}
if (ph != 255) {
ND_PRINT("[The Hop-by-Hop Options header don't follow the IPv6 header]");
nd_print_invalid(ndo);
return;
}
advance = hbhopt_process(ndo, cp, &found_jumbo, &payload_len);
if (payload_len == 0 && found_jumbo == 0) {
ND_PRINT("[No valid Jumbo Payload Hop-by-Hop option found]");
nd_print_invalid(ndo);
return;
}
if (advance < 0) {
nd_pop_packet_info(ndo);
return;
}
found_extension_header = 1;
found_hbh = 1;
nh = GET_U_1(cp);
break;
case IPPROTO_DSTOPTS:
advance = dstopt_process(ndo, cp);
if (advance < 0) {
nd_pop_packet_info(ndo);
return;
}
found_extension_header = 1;
nh = GET_U_1(cp);
break;
case IPPROTO_FRAGMENT:
advance = frag6_print(ndo, cp, (const u_char *)ip6);
if (advance < 0 || ndo->ndo_snapend <= cp + advance) {
nd_pop_packet_info(ndo);
return;
}
found_extension_header = 1;
nh = GET_U_1(cp);
fragmented = 1;
break;
case IPPROTO_MOBILITY_OLD:
case IPPROTO_MOBILITY:
/*
- * XXX - we don't use "advance"; RFC 3775 says that
+ * RFC 3775 says that
* the next header field in a mobility header
* should be IPPROTO_NONE, but speaks of
* the possibility of a future extension in
* which payload can be piggybacked atop a
* mobility header.
*/
advance = mobility_print(ndo, cp, (const u_char *)ip6);
if (advance < 0) {
nd_pop_packet_info(ndo);
return;
}
found_extension_header = 1;
nh = GET_U_1(cp);
nd_pop_packet_info(ndo);
return;
case IPPROTO_ROUTING:
ND_TCHECK_1(cp);
advance = rt6_print(ndo, cp, (const u_char *)ip6);
if (advance < 0) {
nd_pop_packet_info(ndo);
return;
}
found_extension_header = 1;
nh = GET_U_1(cp);
break;
default:
/*
* Not an extension header; hand off to the
* IP protocol demuxer.
*/
if (found_jumbo) {
/*
* We saw a Jumbo Payload option.
* Set the length to the payload length
* plus the IPv6 header length, and
* change the snapshot length accordingly.
*
* But make sure it's not shorter than
* the total number of bytes we've
* processed so far.
*/
len = payload_len + sizeof(struct ip6_hdr);
if (len < total_advance)
goto trunc;
- if (length < len)
- ND_PRINT("truncated-ip6 - %u bytes missing!",
- len - length);
+ if (len > length) {
+ ND_PRINT("[header+payload length %u > length %u]",
+ len, length);
+ nd_print_invalid(ndo);
+ ND_PRINT(" ");
+ }
nd_change_snaplen(ndo, bp, len);
/*
* Now subtract the length of the IPv6
* header plus extension headers to get
* the payload length.
*/
len -= total_advance;
} else {
/*
* We didn't see a Jumbo Payload option;
* was the payload length zero?
*/
if (payload_len == 0) {
/*
* Yes. If we found an extension
* header, treat that as a truncated
* packet header, as there was
* no payload to contain an
* extension header.
*/
if (found_extension_header)
goto trunc;
/*
* OK, we didn't see any extension
* header, but that means we have
* no payload, so set the length
* to the IPv6 header length,
* and change the snapshot length
* accordingly.
*/
len = sizeof(struct ip6_hdr);
nd_change_snaplen(ndo, bp, len);
/*
* Now subtract the length of
* the IPv6 header plus extension
* headers (there weren't any, so
* that's just the IPv6 header
* length) to get the payload length.
*/
len -= total_advance;
}
}
ip_demux_print(ndo, cp, len, 6, fragmented,
GET_U_1(ip6->ip6_hlim), nh, bp);
nd_pop_packet_info(ndo);
return;
}
ph = nh;
/* ndo_protocol reassignment after xxx_print() calls */
ndo->ndo_protocol = "ip6";
}
nd_pop_packet_info(ndo);
return;
trunc:
nd_print_trunc(ndo);
+ return;
+
+invalid:
+ nd_print_invalid(ndo);
}
diff --git a/contrib/tcpdump/print-ip6opts.c b/contrib/tcpdump/print-ip6opts.c
index a78c76daa27d..cbd2d9667310 100644
--- a/contrib/tcpdump/print-ip6opts.c
+++ b/contrib/tcpdump/print-ip6opts.c
@@ -1,265 +1,263 @@
/*
* Copyright (C) 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* \summary: IPv6 header option printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#include "ip6.h"
static int
ip6_sopt_print(netdissect_options *ndo, const u_char *bp, int len)
{
int i;
int optlen;
for (i = 0; i < len; i += optlen) {
if (GET_U_1(bp + i) == IP6OPT_PAD1)
optlen = 1;
else {
if (i + 1 < len)
optlen = GET_U_1(bp + i + 1) + 2;
else
goto trunc;
}
if (i + optlen > len)
goto trunc;
switch (GET_U_1(bp + i)) {
case IP6OPT_PAD1:
ND_PRINT(", pad1");
break;
case IP6OPT_PADN:
if (len - i < IP6OPT_MINLEN) {
ND_PRINT(", padn: trunc");
goto trunc;
}
ND_PRINT(", padn");
break;
default:
if (len - i < IP6OPT_MINLEN) {
ND_PRINT(", sopt_type %u: trunc)", GET_U_1(bp + i));
goto trunc;
}
ND_PRINT(", sopt_type 0x%02x: len=%u", GET_U_1(bp + i),
GET_U_1(bp + i + 1));
break;
}
}
return 0;
trunc:
return -1;
}
static int
ip6_opt_process(netdissect_options *ndo, const u_char *bp, int len,
int *found_jumbop, uint32_t *payload_len)
{
int i;
int optlen = 0;
int found_jumbo = 0;
uint32_t jumbolen = 0;
if (len == 0)
return 0;
for (i = 0; i < len; i += optlen) {
if (GET_U_1(bp + i) == IP6OPT_PAD1)
optlen = 1;
else {
if (i + 1 < len)
optlen = GET_U_1(bp + i + 1) + 2;
else
goto trunc;
}
if (i + optlen > len)
goto trunc;
switch (GET_U_1(bp + i)) {
case IP6OPT_PAD1:
if (ndo->ndo_vflag)
ND_PRINT("(pad1)");
break;
case IP6OPT_PADN:
if (len - i < IP6OPT_MINLEN) {
ND_PRINT("(padn: trunc)");
goto trunc;
}
if (ndo->ndo_vflag)
ND_PRINT("(padn)");
break;
case IP6OPT_ROUTER_ALERT:
if (len - i < IP6OPT_RTALERT_LEN) {
ND_PRINT("(rtalert: trunc)");
goto trunc;
}
if (GET_U_1(bp + i + 1) != IP6OPT_RTALERT_LEN - 2) {
ND_PRINT("(rtalert: invalid len %u)", GET_U_1(bp + i + 1));
goto trunc;
}
if (ndo->ndo_vflag)
ND_PRINT("(rtalert: 0x%04x) ", GET_BE_U_2(bp + i + 2));
break;
case IP6OPT_JUMBO:
if (len - i < IP6OPT_JUMBO_LEN) {
ND_PRINT("(jumbo: trunc)");
goto trunc;
}
if (GET_U_1(bp + i + 1) != IP6OPT_JUMBO_LEN - 2) {
ND_PRINT("(jumbo: invalid len %u)", GET_U_1(bp + i + 1));
goto trunc;
}
jumbolen = GET_BE_U_4(bp + i + 2);
if (found_jumbo) {
/* More than one Jumbo Payload option */
if (ndo->ndo_vflag)
ND_PRINT("(jumbo: %u - already seen) ", jumbolen);
} else {
found_jumbo = 1;
if (payload_len == NULL) {
/* Not a hop-by-hop option - not valid */
if (ndo->ndo_vflag)
ND_PRINT("(jumbo: %u - not a hop-by-hop option) ", jumbolen);
} else if (*payload_len != 0) {
/* Payload length was non-zero - not valid */
if (ndo->ndo_vflag)
ND_PRINT("(jumbo: %u - payload len != 0) ", jumbolen);
} else {
/*
* This is a hop-by-hop option, and Payload length
* was zero in the IPv6 header.
*/
if (jumbolen < 65536) {
/* Too short */
if (ndo->ndo_vflag)
ND_PRINT("(jumbo: %u - < 65536) ", jumbolen);
} else {
/* OK, this is valid */
*found_jumbop = 1;
*payload_len = jumbolen;
if (ndo->ndo_vflag)
ND_PRINT("(jumbo: %u) ", jumbolen);
}
}
}
break;
case IP6OPT_HOME_ADDRESS:
if (len - i < IP6OPT_HOMEADDR_MINLEN) {
ND_PRINT("(homeaddr: trunc)");
goto trunc;
}
if (GET_U_1(bp + i + 1) < IP6OPT_HOMEADDR_MINLEN - 2) {
ND_PRINT("(homeaddr: invalid len %u)", GET_U_1(bp + i + 1));
goto trunc;
}
if (ndo->ndo_vflag) {
ND_PRINT("(homeaddr: %s", GET_IP6ADDR_STRING(bp + i + 2));
if (GET_U_1(bp + i + 1) > IP6OPT_HOMEADDR_MINLEN - 2) {
if (ip6_sopt_print(ndo, bp + i + IP6OPT_HOMEADDR_MINLEN,
(optlen - IP6OPT_HOMEADDR_MINLEN)) == -1)
goto trunc;
}
ND_PRINT(")");
}
break;
default:
if (len - i < IP6OPT_MINLEN) {
ND_PRINT("(type %u: trunc)", GET_U_1(bp + i));
goto trunc;
}
if (ndo->ndo_vflag)
ND_PRINT("(opt_type 0x%02x: len=%u)", GET_U_1(bp + i),
GET_U_1(bp + i + 1));
break;
}
}
if (ndo->ndo_vflag)
ND_PRINT(" ");
return 0;
trunc:
return -1;
}
int
hbhopt_process(netdissect_options *ndo, const u_char *bp, int *found_jumbo,
uint32_t *jumbolen)
{
const struct ip6_hbh *dp = (const struct ip6_hbh *)bp;
u_int hbhlen = 0;
ndo->ndo_protocol = "hbhopt";
hbhlen = (GET_U_1(dp->ip6h_len) + 1) << 3;
ND_TCHECK_LEN(dp, hbhlen);
ND_PRINT("HBH ");
if (ip6_opt_process(ndo, (const u_char *)dp + sizeof(*dp),
hbhlen - sizeof(*dp), found_jumbo, jumbolen) == -1)
goto trunc;
return hbhlen;
trunc:
nd_print_trunc(ndo);
return -1;
}
int
dstopt_process(netdissect_options *ndo, const u_char *bp)
{
const struct ip6_dest *dp = (const struct ip6_dest *)bp;
u_int dstoptlen = 0;
ndo->ndo_protocol = "dstopt";
dstoptlen = (GET_U_1(dp->ip6d_len) + 1) << 3;
ND_TCHECK_LEN(dp, dstoptlen);
ND_PRINT("DSTOPT ");
if (ndo->ndo_vflag) {
/*
* The Jumbo Payload option is a hop-by-hop option; we don't
* honor Jumbo Payload destination options, reporting them
* as invalid.
*/
if (ip6_opt_process(ndo, (const u_char *)dp + sizeof(*dp),
dstoptlen - sizeof(*dp), NULL, NULL) == -1)
goto trunc;
}
return dstoptlen;
trunc:
nd_print_trunc(ndo);
return -1;
}
diff --git a/contrib/tcpdump/print-ipcomp.c b/contrib/tcpdump/print-ipcomp.c
index c0c184ddc839..a88f67975062 100644
--- a/contrib/tcpdump/print-ipcomp.c
+++ b/contrib/tcpdump/print-ipcomp.c
@@ -1,64 +1,62 @@
/*
* Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994
* 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.
*/
/* \summary: IP Payload Compression Protocol (IPComp) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "extract.h"
struct ipcomp {
nd_uint8_t comp_nxt; /* Next Header */
nd_uint8_t comp_flags; /* Length of data, in 32bit */
nd_uint16_t comp_cpi; /* Compression parameter index */
};
void
ipcomp_print(netdissect_options *ndo, const u_char *bp)
{
const struct ipcomp *ipcomp;
uint16_t cpi;
ndo->ndo_protocol = "ipcomp";
ipcomp = (const struct ipcomp *)bp;
cpi = GET_BE_U_2(ipcomp->comp_cpi);
ND_PRINT("IPComp(cpi=0x%04x)", cpi);
/*
* XXX - based on the CPI, we could decompress the packet here.
* Packet buffer management is a headache (if we decompress,
* packet will become larger).
*
* We would decompress the packet and then call a routine that,
* based on ipcomp->comp_nxt, dissects the decompressed data.
*
* Until we do that, however, we just return -1, so that
* the loop that processes "protocol"/"next header" types
* stops - there's nothing more it can do with a compressed
* payload.
*/
}
diff --git a/contrib/tcpdump/print-ipfc.c b/contrib/tcpdump/print-ipfc.c
index ab5a81312f68..c707170a232c 100644
--- a/contrib/tcpdump/print-ipfc.c
+++ b/contrib/tcpdump/print-ipfc.c
@@ -1,143 +1,141 @@
/*
* Copyright (c) 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.
*/
/* \summary: IP over Fibre Channel printer */
/* specification: RFC 2625 */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <string.h>
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "addrtoname.h"
struct ipfc_header {
nd_byte ipfc_dhost[2+MAC_ADDR_LEN];
nd_byte ipfc_shost[2+MAC_ADDR_LEN];
};
#define IPFC_HDRLEN 16
/* Extract src, dst addresses */
static void
extract_ipfc_addrs(const struct ipfc_header *ipfcp, char *ipfcsrc,
char *ipfcdst)
{
/*
* We assume that, as per RFC 2625, the lower 48 bits of the
* source and destination addresses are MAC addresses.
*/
memcpy(ipfcdst, (const char *)&ipfcp->ipfc_dhost[2], MAC_ADDR_LEN);
memcpy(ipfcsrc, (const char *)&ipfcp->ipfc_shost[2], MAC_ADDR_LEN);
}
/*
* Print the Network_Header
*/
static void
ipfc_hdr_print(netdissect_options *ndo,
const struct ipfc_header *ipfcp _U_, u_int length,
const u_char *ipfcsrc, const u_char *ipfcdst)
{
const char *srcname, *dstname;
srcname = etheraddr_string(ndo, ipfcsrc);
dstname = etheraddr_string(ndo, ipfcdst);
/*
* XXX - should we show the upper 16 bits of the addresses?
* Do so only if "vflag" is set?
* Section 3.3 "FC Port and Node Network Addresses" says that
*
* In this specification, both the Source and Destination
* 4-bit NAA identifiers SHALL be set to binary '0001'
* indicating that an IEEE 48-bit MAC address is contained
* in the lower 48 bits of the network address fields. The
* high order 12 bits in the network address fields SHALL
* be set to 0x0000.
*
* so, for captures following this specification, the upper 16
* bits should be 0x1000, followed by a MAC address.
*/
ND_PRINT("%s > %s, length %u: ", srcname, dstname, length);
}
static u_int
ipfc_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen)
{
const struct ipfc_header *ipfcp = (const struct ipfc_header *)p;
nd_mac_addr srcmac, dstmac;
struct lladdr_info src, dst;
int llc_hdrlen;
ndo->ndo_protocol = "ipfc";
ND_TCHECK_LEN(p, IPFC_HDRLEN);
/*
* Get the network addresses into a canonical form
*/
extract_ipfc_addrs(ipfcp, (char *)srcmac, (char *)dstmac);
if (ndo->ndo_eflag)
ipfc_hdr_print(ndo, ipfcp, length, srcmac, dstmac);
src.addr = srcmac;
src.addr_string = etheraddr_string;
dst.addr = dstmac;
dst.addr_string = etheraddr_string;
/* Skip over Network_Header */
length -= IPFC_HDRLEN;
p += IPFC_HDRLEN;
caplen -= IPFC_HDRLEN;
/* Try to print the LLC-layer header & higher layers */
llc_hdrlen = llc_print(ndo, p, length, caplen, &src, &dst);
if (llc_hdrlen < 0) {
/*
* Some kinds of LLC packet we cannot
* handle intelligently
*/
if (!ndo->ndo_suppress_default_print)
ND_DEFAULTPRINT(p, caplen);
llc_hdrlen = -llc_hdrlen;
}
return (IPFC_HDRLEN + llc_hdrlen);
}
/*
* This is the top level routine of the printer. 'p' points
* to the Network_Header of the packet, 'h->ts' is the timestamp,
* 'h->len' is the length of the packet off the wire, and 'h->caplen'
* is the number of bytes actually captured.
*/
void
ipfc_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
{
ndo->ndo_protocol = "ipfc";
ndo->ndo_ll_hdr_len += ipfc_print(ndo, p, h->len, h->caplen);
}
diff --git a/contrib/tcpdump/print-ipnet.c b/contrib/tcpdump/print-ipnet.c
index eddcc1d7546f..65f626163b6d 100644
--- a/contrib/tcpdump/print-ipnet.c
+++ b/contrib/tcpdump/print-ipnet.c
@@ -1,110 +1,108 @@
/* \summary: Solaris DLT_IPNET printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
typedef struct ipnet_hdr {
nd_uint8_t iph_version;
nd_uint8_t iph_family;
nd_uint16_t iph_htype;
nd_uint32_t iph_pktlen;
nd_uint32_t iph_ifindex;
nd_uint32_t iph_grifindex;
nd_uint32_t iph_zsrc;
nd_uint32_t iph_zdst;
} ipnet_hdr_t;
#define IPH_AF_INET 2 /* Matches Solaris's AF_INET */
#define IPH_AF_INET6 26 /* Matches Solaris's AF_INET6 */
#ifdef DLT_IPNET
static const struct tok ipnet_values[] = {
{ IPH_AF_INET, "IPv4" },
{ IPH_AF_INET6, "IPv6" },
{ 0, NULL }
};
static void
ipnet_hdr_print(netdissect_options *ndo, const u_char *bp, u_int length)
{
const ipnet_hdr_t *hdr;
hdr = (const ipnet_hdr_t *)bp;
ND_PRINT("%u > %u", GET_BE_U_4(hdr->iph_zsrc),
GET_BE_U_4(hdr->iph_zdst));
if (!ndo->ndo_qflag) {
ND_PRINT(", family %s (%u)",
tok2str(ipnet_values, "Unknown",
GET_U_1(hdr->iph_family)),
GET_U_1(hdr->iph_family));
} else {
ND_PRINT(", %s",
tok2str(ipnet_values,
"Unknown Ethertype (0x%04x)",
GET_U_1(hdr->iph_family)));
}
ND_PRINT(", length %u: ", length);
}
static void
ipnet_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen)
{
const ipnet_hdr_t *hdr;
ND_TCHECK_LEN(p, sizeof(ipnet_hdr_t));
ndo->ndo_ll_hdr_len += sizeof(ipnet_hdr_t);
if (ndo->ndo_eflag)
ipnet_hdr_print(ndo, p, length);
length -= sizeof(ipnet_hdr_t);
caplen -= sizeof(ipnet_hdr_t);
hdr = (const ipnet_hdr_t *)p;
p += sizeof(ipnet_hdr_t);
switch (GET_U_1(hdr->iph_family)) {
case IPH_AF_INET:
ip_print(ndo, p, length);
break;
case IPH_AF_INET6:
ip6_print(ndo, p, length);
break;
default:
if (!ndo->ndo_eflag)
ipnet_hdr_print(ndo, (const u_char *)hdr,
length + sizeof(ipnet_hdr_t));
if (!ndo->ndo_suppress_default_print)
ND_DEFAULTPRINT(p, caplen);
break;
}
}
/*
* This is the top level routine of the printer. 'p' points
* to the ether header of the packet, 'h->ts' is the timestamp,
* 'h->len' is the length of the packet off the wire, and 'h->caplen'
* is the number of bytes actually captured.
*/
void
ipnet_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h, const u_char *p)
{
ndo->ndo_protocol = "ipnet";
ipnet_print(ndo, p, h->len, h->caplen);
}
#endif /* DLT_IPNET */
diff --git a/contrib/tcpdump/print-ipoib.c b/contrib/tcpdump/print-ipoib.c
index 3d43123505a1..87ae97c8f515 100644
--- a/contrib/tcpdump/print-ipoib.c
+++ b/contrib/tcpdump/print-ipoib.c
@@ -1,125 +1,123 @@
/*
* Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
* 1997, 2000, 2011, 2012
* 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.
*/
/*
* Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
*/
/* \summary: IP-over-InfiniBand (IPoIB) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "extract.h"
#include "addrtoname.h"
extern const struct tok ethertype_values[];
#define IPOIB_HDRLEN 44
static inline void
ipoib_hdr_print(netdissect_options *ndo, const u_char *bp, u_int length)
{
uint16_t ether_type;
ether_type = GET_BE_U_2(bp + 40);
if (!ndo->ndo_qflag) {
ND_PRINT(", ethertype %s (0x%04x)",
tok2str(ethertype_values,"Unknown", ether_type),
ether_type);
} else {
ND_PRINT(", ethertype %s",
tok2str(ethertype_values,"Unknown", ether_type));
}
ND_PRINT(", length %u: ", length);
}
/*
* Print an InfiniBand frame.
* This might be encapsulated within another frame; we might be passed
* a pointer to a function that can print header information for that
* frame's protocol, and an argument to pass to that function.
*/
static void
ipoib_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen,
void (*print_encap_header)(const u_char *), const u_char *encap_header_arg)
{
const u_char *orig_hdr = p;
u_int orig_length;
u_short ether_type;
if (caplen < IPOIB_HDRLEN) {
nd_print_trunc(ndo);
ndo->ndo_ll_hdr_len += caplen;
return;
}
if (length < IPOIB_HDRLEN) {
nd_print_trunc(ndo);
ndo->ndo_ll_hdr_len += length;
return;
}
if (ndo->ndo_eflag) {
nd_print_protocol_caps(ndo);
if (print_encap_header != NULL)
(*print_encap_header)(encap_header_arg);
ipoib_hdr_print(ndo, p, length);
}
orig_length = length;
ndo->ndo_ll_hdr_len += IPOIB_HDRLEN;
length -= IPOIB_HDRLEN;
caplen -= IPOIB_HDRLEN;
ether_type = GET_BE_U_2(p + 40);
p += IPOIB_HDRLEN;
if (ethertype_print(ndo, ether_type, p, length, caplen, NULL, NULL) == 0) {
/* ether_type not known, print raw packet */
if (!ndo->ndo_eflag) {
if (print_encap_header != NULL)
(*print_encap_header)(encap_header_arg);
ipoib_hdr_print(ndo, orig_hdr , orig_length);
}
if (!ndo->ndo_suppress_default_print)
ND_DEFAULTPRINT(p, caplen);
}
}
/*
* This is the top level routine of the printer. 'p' points
* to the ether header of the packet, 'h->ts' is the timestamp,
* 'h->len' is the length of the packet off the wire, and 'h->caplen'
* is the number of bytes actually captured.
*/
void
ipoib_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
{
ndo->ndo_protocol = "ipoib";
ipoib_print(ndo, p, h->len, h->caplen, NULL, NULL);
}
diff --git a/contrib/tcpdump/print-ipx.c b/contrib/tcpdump/print-ipx.c
index f8c0ce7c2213..ebe7c51b01c1 100644
--- a/contrib/tcpdump/print-ipx.c
+++ b/contrib/tcpdump/print-ipx.c
@@ -1,267 +1,265 @@
/*
* Copyright (c) 1994, 1995, 1996
* 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.
*
* Contributed by Brad Parker (brad@fcr.com).
*/
/* \summary: Novell IPX printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <stdio.h>
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
/* well-known sockets */
#define IPX_SKT_NCP 0x0451
#define IPX_SKT_SAP 0x0452
#define IPX_SKT_RIP 0x0453
#define IPX_SKT_NETBIOS 0x0455
#define IPX_SKT_DIAGNOSTICS 0x0456
#define IPX_SKT_NWLINK_DGM 0x0553 /* NWLink datagram, may contain SMB */
#define IPX_SKT_EIGRP 0x85be /* Cisco EIGRP over IPX */
/* IPX transport header */
struct ipxHdr {
nd_uint16_t cksum; /* Checksum */
nd_uint16_t length; /* Length, in bytes, including header */
nd_uint8_t tCtl; /* Transport Control (i.e. hop count) */
nd_uint8_t pType; /* Packet Type (i.e. level 2 protocol) */
nd_uint32_t dstNet; /* destination net */
nd_mac_addr dstNode; /* destination node */
nd_uint16_t dstSkt; /* destination socket */
nd_uint32_t srcNet; /* source net */
nd_mac_addr srcNode; /* source node */
nd_uint16_t srcSkt; /* source socket */
};
#define ipxSize 30
static const char *ipxaddr_string(netdissect_options *, uint32_t, const u_char *);
static void ipx_decode(netdissect_options *, const struct ipxHdr *, const u_char *, u_int);
static void ipx_sap_print(netdissect_options *, const u_char *, u_int);
static void ipx_rip_print(netdissect_options *, const u_char *, u_int);
/*
* Print IPX datagram packets.
*/
void
ipx_print(netdissect_options *ndo, const u_char *p, u_int length)
{
const struct ipxHdr *ipx = (const struct ipxHdr *)p;
ndo->ndo_protocol = "ipx";
if (!ndo->ndo_eflag)
ND_PRINT("IPX ");
ND_PRINT("%s.%04x > ",
ipxaddr_string(ndo, GET_BE_U_4(ipx->srcNet), ipx->srcNode),
GET_BE_U_2(ipx->srcSkt));
ND_PRINT("%s.%04x: ",
ipxaddr_string(ndo, GET_BE_U_4(ipx->dstNet), ipx->dstNode),
GET_BE_U_2(ipx->dstSkt));
/* take length from ipx header */
length = GET_BE_U_2(ipx->length);
if (length < ipxSize) {
ND_PRINT("[length %u < %u]", length, ipxSize);
nd_print_invalid(ndo);
return;
}
ipx_decode(ndo, ipx, p + ipxSize, length - ipxSize);
}
static const char *
ipxaddr_string(netdissect_options *ndo, uint32_t net, const u_char *node)
{
static char line[256];
snprintf(line, sizeof(line), "%08x.%02x:%02x:%02x:%02x:%02x:%02x",
net, GET_U_1(node), GET_U_1(node + 1),
GET_U_1(node + 2), GET_U_1(node + 3),
GET_U_1(node + 4), GET_U_1(node + 5));
return line;
}
static void
ipx_decode(netdissect_options *ndo, const struct ipxHdr *ipx, const u_char *datap, u_int length)
{
u_short dstSkt;
dstSkt = GET_BE_U_2(ipx->dstSkt);
switch (dstSkt) {
case IPX_SKT_NCP:
ND_PRINT("ipx-ncp %u", length);
break;
case IPX_SKT_SAP:
ipx_sap_print(ndo, datap, length);
break;
case IPX_SKT_RIP:
ipx_rip_print(ndo, datap, length);
break;
case IPX_SKT_NETBIOS:
ND_PRINT("ipx-netbios %u", length);
#ifdef ENABLE_SMB
ipx_netbios_print(ndo, datap, length);
#endif
break;
case IPX_SKT_DIAGNOSTICS:
ND_PRINT("ipx-diags %u", length);
break;
case IPX_SKT_NWLINK_DGM:
ND_PRINT("ipx-nwlink-dgm %u", length);
#ifdef ENABLE_SMB
ipx_netbios_print(ndo, datap, length);
#endif
break;
case IPX_SKT_EIGRP:
eigrp_print(ndo, datap, length);
break;
default:
ND_PRINT("ipx-#%x %u", dstSkt, length);
break;
}
}
static void
ipx_sap_print(netdissect_options *ndo, const u_char *ipx, u_int length)
{
int command, i;
command = GET_BE_U_2(ipx);
- ND_LCHECK_U(length, 2);
+ ND_ICHECK_U(length, <, 2);
ipx += 2;
length -= 2;
switch (command) {
case 1:
case 3:
if (command == 1)
ND_PRINT("ipx-sap-req");
else
ND_PRINT("ipx-sap-nearest-req");
ND_PRINT(" %s", ipxsap_string(ndo, htons(GET_BE_U_2(ipx))));
break;
case 2:
case 4:
if (command == 2)
ND_PRINT("ipx-sap-resp");
else
ND_PRINT("ipx-sap-nearest-resp");
for (i = 0; i < 8 && length != 0; i++) {
ND_TCHECK_2(ipx);
if (length < 2)
goto invalid;
ND_PRINT(" %s '", ipxsap_string(ndo, htons(GET_BE_U_2(ipx))));
ipx += 2;
length -= 2;
if (length < 48) {
ND_PRINT("'");
goto invalid;
}
nd_printjnp(ndo, ipx, 48);
ND_PRINT("'");
ipx += 48;
length -= 48;
/*
* 10 bytes of IPX address.
*/
ND_TCHECK_LEN(ipx, 10);
if (length < 10)
goto invalid;
ND_PRINT(" addr %s",
ipxaddr_string(ndo, GET_BE_U_4(ipx), ipx + 4));
ipx += 10;
length -= 10;
/*
* 2 bytes of socket and 2 bytes of number of intermediate
* networks.
*/
ND_TCHECK_4(ipx);
if (length < 4)
goto invalid;
ipx += 4;
length -= 4;
}
break;
default:
ND_PRINT("ipx-sap-?%x", command);
break;
}
return;
invalid:
nd_print_invalid(ndo);
}
static void
ipx_rip_print(netdissect_options *ndo, const u_char *ipx, u_int length)
{
int command, i;
command = GET_BE_U_2(ipx);
- ND_LCHECK_U(length, 2);
+ ND_ICHECK_U(length, <, 2);
ipx += 2;
length -= 2;
switch (command) {
case 1:
ND_PRINT("ipx-rip-req");
if (length != 0) {
if (length < 8)
goto invalid;
ND_PRINT(" %08x/%u.%u", GET_BE_U_4(ipx),
GET_BE_U_2(ipx + 4), GET_BE_U_2(ipx + 6));
}
break;
case 2:
ND_PRINT("ipx-rip-resp");
for (i = 0; i < 50 && length != 0; i++) {
if (length < 8)
goto invalid;
ND_PRINT(" %08x/%u.%u", GET_BE_U_4(ipx),
GET_BE_U_2(ipx + 4), GET_BE_U_2(ipx + 6));
ipx += 8;
length -= 8;
}
break;
default:
ND_PRINT("ipx-rip-?%x", command);
break;
}
return;
invalid:
nd_print_invalid(ndo);
}
diff --git a/contrib/tcpdump/print-isakmp.c b/contrib/tcpdump/print-isakmp.c
index c08bbc08d858..471935e55a45 100644
--- a/contrib/tcpdump/print-isakmp.c
+++ b/contrib/tcpdump/print-isakmp.c
@@ -1,3141 +1,3134 @@
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
/* \summary: Internet Security Association and Key Management Protocol (ISAKMP) printer */
/* specification: RFC 2407, RFC 2408, RFC 5996 */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
-
-/* The functions from print-esp.c used in this file are only defined when both
- * OpenSSL and evp.h are detected. Employ the same preprocessor device here.
- */
-#ifndef HAVE_OPENSSL_EVP_H
-#undef HAVE_LIBCRYPTO
-#endif
#include "netdissect-stdinc.h"
#include <string.h>
#include "netdissect-ctype.h"
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#include "ip.h"
#include "ip6.h"
#include "ipproto.h"
typedef nd_byte cookie_t[8];
typedef nd_byte msgid_t[4];
#define PORT_ISAKMP 500
/* 3.1 ISAKMP Header Format (IKEv1 and IKEv2)
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Initiator !
! Cookie !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Responder !
! Cookie !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload ! MjVer ! MnVer ! Exchange Type ! Flags !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Message ID !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct isakmp {
cookie_t i_ck; /* Initiator Cookie */
cookie_t r_ck; /* Responder Cookie */
nd_uint8_t np; /* Next Payload Type */
nd_uint8_t vers;
#define ISAKMP_VERS_MAJOR 0xf0
#define ISAKMP_VERS_MAJOR_SHIFT 4
#define ISAKMP_VERS_MINOR 0x0f
#define ISAKMP_VERS_MINOR_SHIFT 0
nd_uint8_t etype; /* Exchange Type */
nd_uint8_t flags; /* Flags */
msgid_t msgid;
nd_uint32_t len; /* Length */
};
/* Next Payload Type */
#define ISAKMP_NPTYPE_NONE 0 /* NONE*/
#define ISAKMP_NPTYPE_SA 1 /* Security Association */
#define ISAKMP_NPTYPE_P 2 /* Proposal */
#define ISAKMP_NPTYPE_T 3 /* Transform */
#define ISAKMP_NPTYPE_KE 4 /* Key Exchange */
#define ISAKMP_NPTYPE_ID 5 /* Identification */
#define ISAKMP_NPTYPE_CERT 6 /* Certificate */
#define ISAKMP_NPTYPE_CR 7 /* Certificate Request */
#define ISAKMP_NPTYPE_HASH 8 /* Hash */
#define ISAKMP_NPTYPE_SIG 9 /* Signature */
#define ISAKMP_NPTYPE_NONCE 10 /* Nonce */
#define ISAKMP_NPTYPE_N 11 /* Notification */
#define ISAKMP_NPTYPE_D 12 /* Delete */
#define ISAKMP_NPTYPE_VID 13 /* Vendor ID */
#define ISAKMP_NPTYPE_v2E 46 /* v2 Encrypted payload */
#define IKEv1_MAJOR_VERSION 1
#define IKEv1_MINOR_VERSION 0
#define IKEv2_MAJOR_VERSION 2
#define IKEv2_MINOR_VERSION 0
/* Flags */
#define ISAKMP_FLAG_E 0x01 /* Encryption Bit */
#define ISAKMP_FLAG_C 0x02 /* Commit Bit */
#define ISAKMP_FLAG_extra 0x04
/* IKEv2 */
#define ISAKMP_FLAG_I (1 << 3) /* (I)nitiator */
#define ISAKMP_FLAG_V (1 << 4) /* (V)ersion */
#define ISAKMP_FLAG_R (1 << 5) /* (R)esponse */
/* 3.2 Payload Generic Header
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload ! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct isakmp_gen {
nd_uint8_t np; /* Next Payload */
nd_uint8_t critical; /* bit 7 - critical, rest is RESERVED */
nd_uint16_t len; /* Payload Length */
};
/* 3.3 Data Attributes
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
!A! Attribute Type ! AF=0 Attribute Length !
!F! ! AF=1 Attribute Value !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
. AF=0 Attribute Value .
. AF=1 Not Transmitted .
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct isakmp_data {
nd_uint16_t type; /* defined by DOI-spec, and Attribute Format */
nd_uint16_t lorv; /* if f equal 1, Attribute Length */
/* if f equal 0, Attribute Value */
/* if f equal 1, Attribute Value */
};
/* 3.4 Security Association Payload */
/* MAY NOT be used, because of being defined in ipsec-doi. */
/*
If the current payload is the last in the message,
then the value of the next payload field will be 0.
This field MUST NOT contain the
values for the Proposal or Transform payloads as they are considered
part of the security association negotiation. For example, this
field would contain the value "10" (Nonce payload) in the first
message of a Base Exchange (see Section 4.4) and the value "0" in the
first message of an Identity Protect Exchange (see Section 4.5).
*/
struct ikev1_pl_sa {
struct isakmp_gen h;
nd_uint32_t doi; /* Domain of Interpretation */
nd_uint32_t sit; /* Situation */
};
/* 3.5 Proposal Payload */
/*
The value of the next payload field MUST only contain the value "2"
or "0". If there are additional Proposal payloads in the message,
then this field will be 2. If the current Proposal payload is the
last within the security association proposal, then this field will
be 0.
*/
struct ikev1_pl_p {
struct isakmp_gen h;
nd_uint8_t p_no; /* Proposal # */
nd_uint8_t prot_id; /* Protocol */
nd_uint8_t spi_size; /* SPI Size */
nd_uint8_t num_t; /* Number of Transforms */
/* SPI */
};
/* 3.6 Transform Payload */
/*
The value of the next payload field MUST only contain the value "3"
or "0". If there are additional Transform payloads in the proposal,
then this field will be 3. If the current Transform payload is the
last within the proposal, then this field will be 0.
*/
struct ikev1_pl_t {
struct isakmp_gen h;
nd_uint8_t t_no; /* Transform # */
nd_uint8_t t_id; /* Transform-Id */
nd_byte reserved[2]; /* RESERVED2 */
/* SA Attributes */
};
/* 3.7 Key Exchange Payload */
struct ikev1_pl_ke {
struct isakmp_gen h;
/* Key Exchange Data */
};
/* 3.8 Identification Payload */
/* MUST NOT to be used, because of being defined in ipsec-doi. */
struct ikev1_pl_id {
struct isakmp_gen h;
union {
nd_uint8_t id_type; /* ID Type */
nd_uint32_t doi_data; /* DOI Specific ID Data */
} d;
/* Identification Data */
};
/* 3.9 Certificate Payload */
struct ikev1_pl_cert {
struct isakmp_gen h;
nd_uint8_t encode; /* Cert Encoding */
nd_uint8_t cert; /* Certificate Data */
/*
This field indicates the type of
certificate or certificate-related information contained in the
Certificate Data field.
*/
};
/* 3.10 Certificate Request Payload */
struct ikev1_pl_cr {
struct isakmp_gen h;
nd_uint8_t num_cert; /* # Cert. Types */
/*
Certificate Types (variable length)
-- Contains a list of the types of certificates requested,
sorted in order of preference. Each individual certificate
type is 1 octet. This field is NOT requiredo
*/
/* # Certificate Authorities (1 octet) */
/* Certificate Authorities (variable length) */
};
/* 3.11 Hash Payload */
/* may not be used, because of having only data. */
struct ikev1_pl_hash {
struct isakmp_gen h;
/* Hash Data */
};
/* 3.12 Signature Payload */
/* may not be used, because of having only data. */
struct ikev1_pl_sig {
struct isakmp_gen h;
/* Signature Data */
};
/* 3.13 Nonce Payload */
/* may not be used, because of having only data. */
struct ikev1_pl_nonce {
struct isakmp_gen h;
/* Nonce Data */
};
/* 3.14 Notification Payload */
struct ikev1_pl_n {
struct isakmp_gen h;
nd_uint32_t doi; /* Domain of Interpretation */
nd_uint8_t prot_id; /* Protocol-ID */
nd_uint8_t spi_size; /* SPI Size */
nd_uint16_t type; /* Notify Message Type */
/* SPI */
/* Notification Data */
};
/* 3.14.1 Notify Message Types */
/* NOTIFY MESSAGES - ERROR TYPES */
#define ISAKMP_NTYPE_INVALID_PAYLOAD_TYPE 1
#define ISAKMP_NTYPE_DOI_NOT_SUPPORTED 2
#define ISAKMP_NTYPE_SITUATION_NOT_SUPPORTED 3
#define ISAKMP_NTYPE_INVALID_COOKIE 4
#define ISAKMP_NTYPE_INVALID_MAJOR_VERSION 5
#define ISAKMP_NTYPE_INVALID_MINOR_VERSION 6
#define ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE 7
#define ISAKMP_NTYPE_INVALID_FLAGS 8
#define ISAKMP_NTYPE_INVALID_MESSAGE_ID 9
#define ISAKMP_NTYPE_INVALID_PROTOCOL_ID 10
#define ISAKMP_NTYPE_INVALID_SPI 11
#define ISAKMP_NTYPE_INVALID_TRANSFORM_ID 12
#define ISAKMP_NTYPE_ATTRIBUTES_NOT_SUPPORTED 13
#define ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN 14
#define ISAKMP_NTYPE_BAD_PROPOSAL_SYNTAX 15
#define ISAKMP_NTYPE_PAYLOAD_MALFORMED 16
#define ISAKMP_NTYPE_INVALID_KEY_INFORMATION 17
#define ISAKMP_NTYPE_INVALID_ID_INFORMATION 18
#define ISAKMP_NTYPE_INVALID_CERT_ENCODING 19
#define ISAKMP_NTYPE_INVALID_CERTIFICATE 20
#define ISAKMP_NTYPE_BAD_CERT_REQUEST_SYNTAX 21
#define ISAKMP_NTYPE_INVALID_CERT_AUTHORITY 22
#define ISAKMP_NTYPE_INVALID_HASH_INFORMATION 23
#define ISAKMP_NTYPE_AUTHENTICATION_FAILED 24
#define ISAKMP_NTYPE_INVALID_SIGNATURE 25
#define ISAKMP_NTYPE_ADDRESS_NOTIFICATION 26
/* 3.15 Delete Payload */
struct ikev1_pl_d {
struct isakmp_gen h;
nd_uint32_t doi; /* Domain of Interpretation */
nd_uint8_t prot_id; /* Protocol-Id */
nd_uint8_t spi_size; /* SPI Size */
nd_uint16_t num_spi; /* # of SPIs */
/* SPI(es) */
};
/* IKEv2 (RFC4306) */
/* 3.3 Security Association Payload -- generic header */
/* 3.3.1. Proposal Substructure */
struct ikev2_p {
struct isakmp_gen h;
nd_uint8_t p_no; /* Proposal # */
nd_uint8_t prot_id; /* Protocol */
nd_uint8_t spi_size; /* SPI Size */
nd_uint8_t num_t; /* Number of Transforms */
};
/* 3.3.2. Transform Substructure */
struct ikev2_t {
struct isakmp_gen h;
nd_uint8_t t_type; /* Transform Type (ENCR,PRF,INTEG,etc.*/
nd_byte res2; /* reserved byte */
nd_uint16_t t_id; /* Transform ID */
};
enum ikev2_t_type {
IV2_T_ENCR = 1,
IV2_T_PRF = 2,
IV2_T_INTEG= 3,
IV2_T_DH = 4,
IV2_T_ESN = 5
};
/* 3.4. Key Exchange Payload */
struct ikev2_ke {
struct isakmp_gen h;
nd_uint16_t ke_group;
nd_uint16_t ke_res1;
/* KE data */
};
/* 3.5. Identification Payloads */
enum ikev2_id_type {
ID_IPV4_ADDR=1,
ID_FQDN=2,
ID_RFC822_ADDR=3,
ID_IPV6_ADDR=5,
ID_DER_ASN1_DN=9,
ID_DER_ASN1_GN=10,
ID_KEY_ID=11
};
struct ikev2_id {
struct isakmp_gen h;
nd_uint8_t type; /* ID type */
nd_byte res1;
nd_byte res2[2];
/* SPI */
/* Notification Data */
};
/* 3.10 Notification Payload */
struct ikev2_n {
struct isakmp_gen h;
nd_uint8_t prot_id; /* Protocol-ID */
nd_uint8_t spi_size; /* SPI Size */
nd_uint16_t type; /* Notify Message Type */
};
enum ikev2_n_type {
IV2_NOTIFY_UNSUPPORTED_CRITICAL_PAYLOAD = 1,
IV2_NOTIFY_INVALID_IKE_SPI = 4,
IV2_NOTIFY_INVALID_MAJOR_VERSION = 5,
IV2_NOTIFY_INVALID_SYNTAX = 7,
IV2_NOTIFY_INVALID_MESSAGE_ID = 9,
IV2_NOTIFY_INVALID_SPI =11,
IV2_NOTIFY_NO_PROPOSAL_CHOSEN =14,
IV2_NOTIFY_INVALID_KE_PAYLOAD =17,
IV2_NOTIFY_AUTHENTICATION_FAILED =24,
IV2_NOTIFY_SINGLE_PAIR_REQUIRED =34,
IV2_NOTIFY_NO_ADDITIONAL_SAS =35,
IV2_NOTIFY_INTERNAL_ADDRESS_FAILURE =36,
IV2_NOTIFY_FAILED_CP_REQUIRED =37,
IV2_NOTIFY_INVALID_SELECTORS =39,
IV2_NOTIFY_INITIAL_CONTACT =16384,
IV2_NOTIFY_SET_WINDOW_SIZE =16385,
IV2_NOTIFY_ADDITIONAL_TS_POSSIBLE =16386,
IV2_NOTIFY_IPCOMP_SUPPORTED =16387,
IV2_NOTIFY_NAT_DETECTION_SOURCE_IP =16388,
IV2_NOTIFY_NAT_DETECTION_DESTINATION_IP =16389,
IV2_NOTIFY_COOKIE =16390,
IV2_NOTIFY_USE_TRANSPORT_MODE =16391,
IV2_NOTIFY_HTTP_CERT_LOOKUP_SUPPORTED =16392,
IV2_NOTIFY_REKEY_SA =16393,
IV2_NOTIFY_ESP_TFC_PADDING_NOT_SUPPORTED =16394,
IV2_NOTIFY_NON_FIRST_FRAGMENTS_ALSO =16395
};
struct notify_messages {
uint16_t type;
char *msg;
};
/* 3.8 Authentication Payload */
struct ikev2_auth {
struct isakmp_gen h;
nd_uint8_t auth_method; /* Protocol-ID */
nd_byte reserved[3];
/* authentication data */
};
enum ikev2_auth_type {
IV2_RSA_SIG = 1,
IV2_SHARED = 2,
IV2_DSS_SIG = 3
};
/* refer to RFC 2409 */
#if 0
/* isakmp sa structure */
struct oakley_sa {
uint8_t proto_id; /* OAKLEY */
vchar_t *spi; /* spi */
uint8_t dhgrp; /* DH; group */
uint8_t auth_t; /* method of authentication */
uint8_t prf_t; /* type of prf */
uint8_t hash_t; /* type of hash */
uint8_t enc_t; /* type of cipher */
uint8_t life_t; /* type of duration of lifetime */
uint32_t ldur; /* life duration */
};
#endif
/* refer to RFC 2407 */
#define IPSEC_DOI 1
/* 4.2 IPSEC Situation Definition */
#define IPSECDOI_SIT_IDENTITY_ONLY 0x00000001
#define IPSECDOI_SIT_SECRECY 0x00000002
#define IPSECDOI_SIT_INTEGRITY 0x00000004
/* 4.4.1 IPSEC Security Protocol Identifiers */
/* 4.4.2 IPSEC ISAKMP Transform Values */
#define IPSECDOI_PROTO_ISAKMP 1
#define IPSECDOI_KEY_IKE 1
/* 4.4.1 IPSEC Security Protocol Identifiers */
#define IPSECDOI_PROTO_IPSEC_AH 2
/* 4.4.3 IPSEC AH Transform Values */
#define IPSECDOI_AH_MD5 2
#define IPSECDOI_AH_SHA 3
#define IPSECDOI_AH_DES 4
#define IPSECDOI_AH_SHA2_256 5
#define IPSECDOI_AH_SHA2_384 6
#define IPSECDOI_AH_SHA2_512 7
/* 4.4.1 IPSEC Security Protocol Identifiers */
#define IPSECDOI_PROTO_IPSEC_ESP 3
/* 4.4.4 IPSEC ESP Transform Identifiers */
#define IPSECDOI_ESP_DES_IV64 1
#define IPSECDOI_ESP_DES 2
#define IPSECDOI_ESP_3DES 3
#define IPSECDOI_ESP_RC5 4
#define IPSECDOI_ESP_IDEA 5
#define IPSECDOI_ESP_CAST 6
#define IPSECDOI_ESP_BLOWFISH 7
#define IPSECDOI_ESP_3IDEA 8
#define IPSECDOI_ESP_DES_IV32 9
#define IPSECDOI_ESP_RC4 10
#define IPSECDOI_ESP_NULL 11
#define IPSECDOI_ESP_RIJNDAEL 12
#define IPSECDOI_ESP_AES 12
/* 4.4.1 IPSEC Security Protocol Identifiers */
#define IPSECDOI_PROTO_IPCOMP 4
/* 4.4.5 IPSEC IPCOMP Transform Identifiers */
#define IPSECDOI_IPCOMP_OUI 1
#define IPSECDOI_IPCOMP_DEFLATE 2
#define IPSECDOI_IPCOMP_LZS 3
/* 4.5 IPSEC Security Association Attributes */
#define IPSECDOI_ATTR_SA_LTYPE 1 /* B */
#define IPSECDOI_ATTR_SA_LTYPE_DEFAULT 1
#define IPSECDOI_ATTR_SA_LTYPE_SEC 1
#define IPSECDOI_ATTR_SA_LTYPE_KB 2
#define IPSECDOI_ATTR_SA_LDUR 2 /* V */
#define IPSECDOI_ATTR_SA_LDUR_DEFAULT 28800 /* 8 hours */
#define IPSECDOI_ATTR_GRP_DESC 3 /* B */
#define IPSECDOI_ATTR_ENC_MODE 4 /* B */
/* default value: host dependent */
#define IPSECDOI_ATTR_ENC_MODE_TUNNEL 1
#define IPSECDOI_ATTR_ENC_MODE_TRNS 2
#define IPSECDOI_ATTR_AUTH 5 /* B */
/* 0 means not to use authentication. */
#define IPSECDOI_ATTR_AUTH_HMAC_MD5 1
#define IPSECDOI_ATTR_AUTH_HMAC_SHA1 2
#define IPSECDOI_ATTR_AUTH_DES_MAC 3
#define IPSECDOI_ATTR_AUTH_KPDK 4 /*RFC-1826(Key/Pad/Data/Key)*/
/*
* When negotiating ESP without authentication, the Auth
* Algorithm attribute MUST NOT be included in the proposal.
* When negotiating ESP without confidentiality, the Auth
* Algorithm attribute MUST be included in the proposal and
* the ESP transform ID must be ESP_NULL.
*/
#define IPSECDOI_ATTR_KEY_LENGTH 6 /* B */
#define IPSECDOI_ATTR_KEY_ROUNDS 7 /* B */
#define IPSECDOI_ATTR_COMP_DICT_SIZE 8 /* B */
#define IPSECDOI_ATTR_COMP_PRIVALG 9 /* V */
/* 4.6.1 Security Association Payload */
struct ipsecdoi_sa {
struct isakmp_gen h;
nd_uint32_t doi; /* Domain of Interpretation */
nd_uint32_t sit; /* Situation */
};
struct ipsecdoi_secrecy_h {
nd_uint16_t len;
nd_uint16_t reserved;
};
/* 4.6.2.1 Identification Type Values */
struct ipsecdoi_id {
struct isakmp_gen h;
nd_uint8_t type; /* ID Type */
nd_uint8_t proto_id; /* Protocol ID */
nd_uint16_t port; /* Port */
/* Identification Data */
};
#define IPSECDOI_ID_IPV4_ADDR 1
#define IPSECDOI_ID_FQDN 2
#define IPSECDOI_ID_USER_FQDN 3
#define IPSECDOI_ID_IPV4_ADDR_SUBNET 4
#define IPSECDOI_ID_IPV6_ADDR 5
#define IPSECDOI_ID_IPV6_ADDR_SUBNET 6
#define IPSECDOI_ID_IPV4_ADDR_RANGE 7
#define IPSECDOI_ID_IPV6_ADDR_RANGE 8
#define IPSECDOI_ID_DER_ASN1_DN 9
#define IPSECDOI_ID_DER_ASN1_GN 10
#define IPSECDOI_ID_KEY_ID 11
/* 4.6.3 IPSEC DOI Notify Message Types */
/* Notify Messages - Status Types */
#define IPSECDOI_NTYPE_RESPONDER_LIFETIME 24576
#define IPSECDOI_NTYPE_REPLAY_STATUS 24577
#define IPSECDOI_NTYPE_INITIAL_CONTACT 24578
#define DECLARE_PRINTER(func) static const u_char *ike##func##_print( \
netdissect_options *ndo, u_char tpay, \
const struct isakmp_gen *ext, \
u_int item_len, \
const u_char *end_pointer, \
uint32_t phase,\
uint32_t doi0, \
uint32_t proto0, int depth)
DECLARE_PRINTER(v1_sa);
DECLARE_PRINTER(v1_p);
DECLARE_PRINTER(v1_t);
DECLARE_PRINTER(v1_ke);
DECLARE_PRINTER(v1_id);
DECLARE_PRINTER(v1_cert);
DECLARE_PRINTER(v1_cr);
DECLARE_PRINTER(v1_sig);
DECLARE_PRINTER(v1_hash);
DECLARE_PRINTER(v1_nonce);
DECLARE_PRINTER(v1_n);
DECLARE_PRINTER(v1_d);
DECLARE_PRINTER(v1_vid);
DECLARE_PRINTER(v2_sa);
DECLARE_PRINTER(v2_ke);
DECLARE_PRINTER(v2_ID);
DECLARE_PRINTER(v2_cert);
DECLARE_PRINTER(v2_cr);
DECLARE_PRINTER(v2_auth);
DECLARE_PRINTER(v2_nonce);
DECLARE_PRINTER(v2_n);
DECLARE_PRINTER(v2_d);
DECLARE_PRINTER(v2_vid);
DECLARE_PRINTER(v2_TS);
DECLARE_PRINTER(v2_cp);
DECLARE_PRINTER(v2_eap);
static const u_char *ikev2_e_print(netdissect_options *ndo,
const struct isakmp *base,
u_char tpay,
const struct isakmp_gen *ext,
u_int item_len,
const u_char *end_pointer,
uint32_t phase,
uint32_t doi0,
uint32_t proto0, int depth);
static const u_char *ike_sub0_print(netdissect_options *ndo,u_char, const struct isakmp_gen *,
const u_char *, uint32_t, uint32_t, uint32_t, int);
static const u_char *ikev1_sub_print(netdissect_options *ndo,u_char, const struct isakmp_gen *,
const u_char *, uint32_t, uint32_t, uint32_t, int);
static const u_char *ikev2_sub_print(netdissect_options *ndo,
const struct isakmp *base,
u_char np, const struct isakmp_gen *ext,
const u_char *ep, uint32_t phase,
uint32_t doi, uint32_t proto,
int depth);
static char *numstr(u_int);
static void
ikev1_print(netdissect_options *ndo,
const u_char *bp, u_int length,
const u_char *bp2, const struct isakmp *base);
#define MAXINITIATORS 20
static int ninitiator = 0;
union inaddr_u {
nd_ipv4 in4;
nd_ipv6 in6;
};
static struct {
cookie_t initiator;
u_int version;
union inaddr_u iaddr;
union inaddr_u raddr;
} cookiecache[MAXINITIATORS];
/* protocol id */
static const char *protoidstr[] = {
NULL, "isakmp", "ipsec-ah", "ipsec-esp", "ipcomp",
};
/* isakmp->np */
static const char *npstr[] = {
"none", "sa", "p", "t", "ke", "id", "cert", "cr", "hash", /* 0 - 8 */
"sig", "nonce", "n", "d", "vid", /* 9 - 13 */
"pay14", "pay15", "pay16", "pay17", "pay18", /* 14- 18 */
"pay19", "pay20", "pay21", "pay22", "pay23", /* 19- 23 */
"pay24", "pay25", "pay26", "pay27", "pay28", /* 24- 28 */
"pay29", "pay30", "pay31", "pay32", /* 29- 32 */
"v2sa", "v2ke", "v2IDi", "v2IDr", "v2cert",/* 33- 37 */
"v2cr", "v2auth","v2nonce", "v2n", "v2d", /* 38- 42 */
"v2vid", "v2TSi", "v2TSr", "v2e", "v2cp", /* 43- 47 */
"v2eap", /* 48 */
};
/* isakmp->np */
static const u_char *(*npfunc[])(netdissect_options *ndo, u_char tpay,
const struct isakmp_gen *ext,
u_int item_len,
const u_char *end_pointer,
uint32_t phase,
uint32_t doi0,
uint32_t proto0, int depth) = {
NULL,
ikev1_sa_print,
ikev1_p_print,
ikev1_t_print,
ikev1_ke_print,
ikev1_id_print,
ikev1_cert_print,
ikev1_cr_print,
ikev1_hash_print,
ikev1_sig_print,
ikev1_nonce_print,
ikev1_n_print,
ikev1_d_print,
ikev1_vid_print, /* 13 */
NULL, NULL, NULL, NULL, NULL, /* 14- 18 */
NULL, NULL, NULL, NULL, NULL, /* 19- 23 */
NULL, NULL, NULL, NULL, NULL, /* 24- 28 */
NULL, NULL, NULL, NULL, /* 29- 32 */
ikev2_sa_print, /* 33 */
ikev2_ke_print, /* 34 */
ikev2_ID_print, /* 35 */
ikev2_ID_print, /* 36 */
ikev2_cert_print, /* 37 */
ikev2_cr_print, /* 38 */
ikev2_auth_print, /* 39 */
ikev2_nonce_print, /* 40 */
ikev2_n_print, /* 41 */
ikev2_d_print, /* 42 */
ikev2_vid_print, /* 43 */
ikev2_TS_print, /* 44 */
ikev2_TS_print, /* 45 */
NULL, /* ikev2_e_print,*/ /* 46 - special */
ikev2_cp_print, /* 47 */
ikev2_eap_print, /* 48 */
};
/* isakmp->etype */
static const char *etypestr[] = {
/* IKEv1 exchange types */
"none", "base", "ident", "auth", "agg", "inf", NULL, NULL, /* 0-7 */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 8-15 */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 16-23 */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 24-31 */
"oakley-quick", "oakley-newgroup", /* 32-33 */
/* IKEv2 exchange types */
"ikev2_init", "ikev2_auth", "child_sa", "inf2" /* 34-37 */
};
#define STR_OR_ID(x, tab) \
(((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)]) ? tab[(x)] : numstr(x))
#define PROTOIDSTR(x) STR_OR_ID(x, protoidstr)
#define NPSTR(x) STR_OR_ID(x, npstr)
#define ETYPESTR(x) STR_OR_ID(x, etypestr)
#define CHECKLEN(p, np) \
if (ep < (const u_char *)(p)) { \
ND_PRINT(" [|%s]", NPSTR(np)); \
goto done; \
}
#define NPFUNC(x) \
(((x) < sizeof(npfunc)/sizeof(npfunc[0]) && npfunc[(x)]) \
? npfunc[(x)] : NULL)
static int
iszero(netdissect_options *ndo, const u_char *p, size_t l)
{
while (l != 0) {
if (GET_U_1(p))
return 0;
p++;
l--;
}
return 1;
}
/* find cookie from initiator cache */
static int
cookie_find(const cookie_t *in)
{
int i;
for (i = 0; i < MAXINITIATORS; i++) {
if (memcmp(in, &cookiecache[i].initiator, sizeof(*in)) == 0)
return i;
}
return -1;
}
/* record initiator */
static void
cookie_record(netdissect_options *ndo, const cookie_t *in, const u_char *bp2)
{
int i;
const struct ip *ip;
const struct ip6_hdr *ip6;
i = cookie_find(in);
if (0 <= i) {
ninitiator = (i + 1) % MAXINITIATORS;
return;
}
ip = (const struct ip *)bp2;
switch (IP_V(ip)) {
case 4:
cookiecache[ninitiator].version = 4;
UNALIGNED_MEMCPY(&cookiecache[ninitiator].iaddr.in4,
ip->ip_src, sizeof(nd_ipv4));
UNALIGNED_MEMCPY(&cookiecache[ninitiator].raddr.in4,
ip->ip_dst, sizeof(nd_ipv4));
break;
case 6:
ip6 = (const struct ip6_hdr *)bp2;
cookiecache[ninitiator].version = 6;
UNALIGNED_MEMCPY(&cookiecache[ninitiator].iaddr.in6,
ip6->ip6_src, sizeof(nd_ipv6));
UNALIGNED_MEMCPY(&cookiecache[ninitiator].raddr.in6,
ip6->ip6_dst, sizeof(nd_ipv6));
break;
default:
return;
}
UNALIGNED_MEMCPY(&cookiecache[ninitiator].initiator, in, sizeof(*in));
ninitiator = (ninitiator + 1) % MAXINITIATORS;
}
#define cookie_isinitiator(ndo, x, y) cookie_sidecheck(ndo, (x), (y), 1)
#define cookie_isresponder(ndo, x, y) cookie_sidecheck(ndo, (x), (y), 0)
static int
cookie_sidecheck(netdissect_options *ndo, int i, const u_char *bp2, int initiator)
{
const struct ip *ip;
const struct ip6_hdr *ip6;
ip = (const struct ip *)bp2;
switch (IP_V(ip)) {
case 4:
if (cookiecache[i].version != 4)
return 0;
if (initiator) {
if (UNALIGNED_MEMCMP(ip->ip_src, &cookiecache[i].iaddr.in4, sizeof(nd_ipv4)) == 0)
return 1;
} else {
if (UNALIGNED_MEMCMP(ip->ip_src, &cookiecache[i].raddr.in4, sizeof(nd_ipv4)) == 0)
return 1;
}
break;
case 6:
if (cookiecache[i].version != 6)
return 0;
ip6 = (const struct ip6_hdr *)bp2;
if (initiator) {
if (UNALIGNED_MEMCMP(ip6->ip6_src, &cookiecache[i].iaddr.in6, sizeof(nd_ipv6)) == 0)
return 1;
} else {
if (UNALIGNED_MEMCMP(ip6->ip6_src, &cookiecache[i].raddr.in6, sizeof(nd_ipv6)) == 0)
return 1;
}
break;
default:
break;
}
return 0;
}
static void
hexprint(netdissect_options *ndo, const uint8_t *loc, size_t len)
{
const uint8_t *p;
size_t i;
p = loc;
for (i = 0; i < len; i++)
ND_PRINT("%02x", p[i] & 0xff);
}
static int
rawprint(netdissect_options *ndo, const uint8_t *loc, size_t len)
{
ND_TCHECK_LEN(loc, len);
hexprint(ndo, loc, len);
return 1;
trunc:
return 0;
}
/*
* returns false if we run out of data buffer
*/
static int ike_show_somedata(netdissect_options *ndo,
const u_char *cp, const u_char *ep)
{
/* there is too much data, just show some of it */
const u_char *end = ep - 20;
size_t elen = 20;
size_t len = ep - cp;
if(len > 10) {
len = 10;
}
/* really shouldn't happen because of above */
if(end < cp + len) {
end = cp+len;
elen = ep - end;
}
ND_PRINT(" data=(");
if(!rawprint(ndo, (const uint8_t *)(cp), len)) goto trunc;
ND_PRINT("...");
if(elen) {
if(!rawprint(ndo, (const uint8_t *)(end), elen)) goto trunc;
}
ND_PRINT(")");
return 1;
trunc:
return 0;
}
struct attrmap {
const char *type;
u_int nvalue;
const char *value[30]; /*XXX*/
};
static const u_char *
ikev1_attrmap_print(netdissect_options *ndo,
const u_char *p, const u_char *ep2,
const struct attrmap *map, size_t nmap)
{
u_int totlen;
uint32_t t, v;
if (GET_U_1(p) & 0x80)
totlen = 4;
else {
totlen = 4 + GET_BE_U_2(p + 2);
}
if (ep2 < p + totlen) {
ND_PRINT("[|attr]");
return ep2 + 1;
}
ND_PRINT("(");
t = GET_BE_U_2(p) & 0x7fff;
if (map && t < nmap && map[t].type)
ND_PRINT("type=%s ", map[t].type);
else
ND_PRINT("type=#%u ", t);
if (GET_U_1(p) & 0x80) {
ND_PRINT("value=");
v = GET_BE_U_2(p + 2);
if (map && t < nmap && v < map[t].nvalue && map[t].value[v])
ND_PRINT("%s", map[t].value[v]);
else {
if (!rawprint(ndo, (const uint8_t *)(p + 2), 2)) {
ND_PRINT(")");
goto trunc;
}
}
} else {
ND_PRINT("len=%u value=", totlen - 4);
if (!rawprint(ndo, (const uint8_t *)(p + 4), totlen - 4)) {
ND_PRINT(")");
goto trunc;
}
}
ND_PRINT(")");
return p + totlen;
trunc:
return NULL;
}
static const u_char *
ikev1_attr_print(netdissect_options *ndo, const u_char *p, const u_char *ep2)
{
u_int totlen;
uint32_t t;
if (GET_U_1(p) & 0x80)
totlen = 4;
else {
totlen = 4 + GET_BE_U_2(p + 2);
}
if (ep2 < p + totlen) {
ND_PRINT("[|attr]");
return ep2 + 1;
}
ND_PRINT("(");
t = GET_BE_U_2(p) & 0x7fff;
ND_PRINT("type=#%u ", t);
if (GET_U_1(p) & 0x80) {
ND_PRINT("value=");
t = GET_U_1(p + 2);
if (!rawprint(ndo, (const uint8_t *)(p + 2), 2)) {
ND_PRINT(")");
goto trunc;
}
} else {
ND_PRINT("len=%u value=", totlen - 4);
if (!rawprint(ndo, (const uint8_t *)(p + 4), totlen - 4)) {
ND_PRINT(")");
goto trunc;
}
}
ND_PRINT(")");
return p + totlen;
trunc:
return NULL;
}
static const u_char *
ikev1_sa_print(netdissect_options *ndo, u_char tpay _U_,
const struct isakmp_gen *ext,
u_int item_len _U_,
const u_char *ep, uint32_t phase, uint32_t doi0 _U_,
uint32_t proto0, int depth)
{
const struct ikev1_pl_sa *p;
uint32_t doi, sit, ident;
const u_char *cp, *np;
int t;
ND_PRINT("%s:", NPSTR(ISAKMP_NPTYPE_SA));
p = (const struct ikev1_pl_sa *)ext;
ND_TCHECK_SIZE(p);
doi = GET_BE_U_4(p->doi);
sit = GET_BE_U_4(p->sit);
if (doi != 1) {
ND_PRINT(" doi=%u", doi);
ND_PRINT(" situation=%u", sit);
return (const u_char *)(p + 1);
}
ND_PRINT(" doi=ipsec");
ND_PRINT(" situation=");
t = 0;
if (sit & 0x01) {
ND_PRINT("identity");
t++;
}
if (sit & 0x02) {
ND_PRINT("%ssecrecy", t ? "+" : "");
t++;
}
if (sit & 0x04)
ND_PRINT("%sintegrity", t ? "+" : "");
np = (const u_char *)ext + sizeof(struct ikev1_pl_sa);
if (sit != 0x01) {
ident = GET_BE_U_4(ext + 1);
ND_PRINT(" ident=%u", ident);
np += sizeof(ident);
}
ext = (const struct isakmp_gen *)np;
ND_TCHECK_SIZE(ext);
cp = ikev1_sub_print(ndo, ISAKMP_NPTYPE_P, ext, ep, phase, doi, proto0,
depth);
return cp;
trunc:
ND_PRINT(" [|%s]", NPSTR(ISAKMP_NPTYPE_SA));
return NULL;
}
static const u_char *
ikev1_p_print(netdissect_options *ndo, u_char tpay _U_,
const struct isakmp_gen *ext, u_int item_len _U_,
const u_char *ep, uint32_t phase, uint32_t doi0,
uint32_t proto0 _U_, int depth)
{
const struct ikev1_pl_p *p;
const u_char *cp;
uint8_t spi_size;
ND_PRINT("%s:", NPSTR(ISAKMP_NPTYPE_P));
p = (const struct ikev1_pl_p *)ext;
ND_TCHECK_SIZE(p);
ND_PRINT(" #%u protoid=%s transform=%u",
GET_U_1(p->p_no), PROTOIDSTR(GET_U_1(p->prot_id)),
GET_U_1(p->num_t));
spi_size = GET_U_1(p->spi_size);
if (spi_size) {
ND_PRINT(" spi=");
if (!rawprint(ndo, (const uint8_t *)(p + 1), spi_size))
goto trunc;
}
ext = (const struct isakmp_gen *)((const u_char *)(p + 1) + spi_size);
ND_TCHECK_SIZE(ext);
cp = ikev1_sub_print(ndo, ISAKMP_NPTYPE_T, ext, ep, phase, doi0,
GET_U_1(p->prot_id), depth);
return cp;
trunc:
ND_PRINT(" [|%s]", NPSTR(ISAKMP_NPTYPE_P));
return NULL;
}
static const char *ikev1_p_map[] = {
NULL, "ike",
};
static const char *ikev2_t_type_map[]={
NULL, "encr", "prf", "integ", "dh", "esn"
};
static const char *ah_p_map[] = {
NULL, "(reserved)", "md5", "sha", "1des",
"sha2-256", "sha2-384", "sha2-512",
};
static const char *prf_p_map[] = {
NULL, "hmac-md5", "hmac-sha", "hmac-tiger",
"aes128_xcbc"
};
static const char *integ_p_map[] = {
NULL, "hmac-md5", "hmac-sha", "dec-mac",
"kpdk-md5", "aes-xcbc"
};
static const char *esn_p_map[] = {
"no-esn", "esn"
};
static const char *dh_p_map[] = {
NULL, "modp768",
"modp1024", /* group 2 */
"EC2N 2^155", /* group 3 */
"EC2N 2^185", /* group 4 */
"modp1536", /* group 5 */
"iana-grp06", "iana-grp07", /* reserved */
"iana-grp08", "iana-grp09",
"iana-grp10", "iana-grp11",
"iana-grp12", "iana-grp13",
"modp2048", /* group 14 */
"modp3072", /* group 15 */
"modp4096", /* group 16 */
"modp6144", /* group 17 */
"modp8192", /* group 18 */
};
static const char *esp_p_map[] = {
NULL, "1des-iv64", "1des", "3des", "rc5", "idea", "cast",
"blowfish", "3idea", "1des-iv32", "rc4", "null", "aes"
};
static const char *ipcomp_p_map[] = {
NULL, "oui", "deflate", "lzs",
};
static const struct attrmap ipsec_t_map[] = {
{ NULL, 0, { NULL } },
{ "lifetype", 3, { NULL, "sec", "kb", }, },
{ "life", 0, { NULL } },
{ "group desc", 18, { NULL, "modp768",
"modp1024", /* group 2 */
"EC2N 2^155", /* group 3 */
"EC2N 2^185", /* group 4 */
"modp1536", /* group 5 */
"iana-grp06", "iana-grp07", /* reserved */
"iana-grp08", "iana-grp09",
"iana-grp10", "iana-grp11",
"iana-grp12", "iana-grp13",
"modp2048", /* group 14 */
"modp3072", /* group 15 */
"modp4096", /* group 16 */
"modp6144", /* group 17 */
"modp8192", /* group 18 */
}, },
{ "enc mode", 3, { NULL, "tunnel", "transport", }, },
{ "auth", 5, { NULL, "hmac-md5", "hmac-sha1", "1des-mac", "keyed", }, },
{ "keylen", 0, { NULL } },
{ "rounds", 0, { NULL } },
{ "dictsize", 0, { NULL } },
{ "privalg", 0, { NULL } },
};
static const struct attrmap encr_t_map[] = {
{ NULL, 0, { NULL } }, { NULL, 0, { NULL } }, /* 0, 1 */
{ NULL, 0, { NULL } }, { NULL, 0, { NULL } }, /* 2, 3 */
{ NULL, 0, { NULL } }, { NULL, 0, { NULL } }, /* 4, 5 */
{ NULL, 0, { NULL } }, { NULL, 0, { NULL } }, /* 6, 7 */
{ NULL, 0, { NULL } }, { NULL, 0, { NULL } }, /* 8, 9 */
{ NULL, 0, { NULL } }, { NULL, 0, { NULL } }, /* 10,11*/
{ NULL, 0, { NULL } }, { NULL, 0, { NULL } }, /* 12,13*/
{ "keylen", 14, { NULL }},
};
static const struct attrmap oakley_t_map[] = {
{ NULL, 0, { NULL } },
{ "enc", 8, { NULL, "1des", "idea", "blowfish", "rc5",
"3des", "cast", "aes", }, },
{ "hash", 7, { NULL, "md5", "sha1", "tiger",
"sha2-256", "sha2-384", "sha2-512", }, },
{ "auth", 6, { NULL, "preshared", "dss", "rsa sig", "rsa enc",
"rsa enc revised", }, },
{ "group desc", 18, { NULL, "modp768",
"modp1024", /* group 2 */
"EC2N 2^155", /* group 3 */
"EC2N 2^185", /* group 4 */
"modp1536", /* group 5 */
"iana-grp06", "iana-grp07", /* reserved */
"iana-grp08", "iana-grp09",
"iana-grp10", "iana-grp11",
"iana-grp12", "iana-grp13",
"modp2048", /* group 14 */
"modp3072", /* group 15 */
"modp4096", /* group 16 */
"modp6144", /* group 17 */
"modp8192", /* group 18 */
}, },
{ "group type", 4, { NULL, "MODP", "ECP", "EC2N", }, },
{ "group prime", 0, { NULL } },
{ "group gen1", 0, { NULL } },
{ "group gen2", 0, { NULL } },
{ "group curve A", 0, { NULL } },
{ "group curve B", 0, { NULL } },
{ "lifetype", 3, { NULL, "sec", "kb", }, },
{ "lifeduration", 0, { NULL } },
{ "prf", 0, { NULL } },
{ "keylen", 0, { NULL } },
{ "field", 0, { NULL } },
{ "order", 0, { NULL } },
};
static const u_char *
ikev1_t_print(netdissect_options *ndo, u_char tpay _U_,
const struct isakmp_gen *ext, u_int item_len,
const u_char *ep, uint32_t phase _U_, uint32_t doi _U_,
uint32_t proto, int depth _U_)
{
const struct ikev1_pl_t *p;
const u_char *cp;
const char *idstr;
const struct attrmap *map;
size_t nmap;
const u_char *ep2;
ND_PRINT("%s:", NPSTR(ISAKMP_NPTYPE_T));
p = (const struct ikev1_pl_t *)ext;
ND_TCHECK_SIZE(p);
switch (proto) {
case 1:
idstr = STR_OR_ID(GET_U_1(p->t_id), ikev1_p_map);
map = oakley_t_map;
nmap = sizeof(oakley_t_map)/sizeof(oakley_t_map[0]);
break;
case 2:
idstr = STR_OR_ID(GET_U_1(p->t_id), ah_p_map);
map = ipsec_t_map;
nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]);
break;
case 3:
idstr = STR_OR_ID(GET_U_1(p->t_id), esp_p_map);
map = ipsec_t_map;
nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]);
break;
case 4:
idstr = STR_OR_ID(GET_U_1(p->t_id), ipcomp_p_map);
map = ipsec_t_map;
nmap = sizeof(ipsec_t_map)/sizeof(ipsec_t_map[0]);
break;
default:
idstr = NULL;
map = NULL;
nmap = 0;
break;
}
if (idstr)
ND_PRINT(" #%u id=%s ", GET_U_1(p->t_no), idstr);
else
ND_PRINT(" #%u id=%u ", GET_U_1(p->t_no), GET_U_1(p->t_id));
cp = (const u_char *)(p + 1);
ep2 = (const u_char *)p + item_len;
while (cp < ep && cp < ep2) {
if (map && nmap)
cp = ikev1_attrmap_print(ndo, cp, ep2, map, nmap);
else
cp = ikev1_attr_print(ndo, cp, ep2);
if (cp == NULL)
goto trunc;
}
if (ep < ep2)
ND_PRINT("...");
return cp;
trunc:
ND_PRINT(" [|%s]", NPSTR(ISAKMP_NPTYPE_T));
return NULL;
}
static const u_char *
ikev1_ke_print(netdissect_options *ndo, u_char tpay _U_,
const struct isakmp_gen *ext, u_int item_len,
const u_char *ep _U_, uint32_t phase _U_, uint32_t doi _U_,
uint32_t proto _U_, int depth _U_)
{
ND_PRINT("%s:", NPSTR(ISAKMP_NPTYPE_KE));
ND_TCHECK_SIZE(ext);
/*
* Our caller has ensured that the length is >= 4.
*/
ND_PRINT(" key len=%u", item_len - 4);
if (2 < ndo->ndo_vflag && item_len > 4) {
/* Print the entire payload in hex */
ND_PRINT(" ");
if (!rawprint(ndo, (const uint8_t *)(ext + 1), item_len - 4))
goto trunc;
}
return (const u_char *)ext + item_len;
trunc:
ND_PRINT(" [|%s]", NPSTR(ISAKMP_NPTYPE_KE));
return NULL;
}
static const u_char *
ikev1_id_print(netdissect_options *ndo, u_char tpay _U_,
const struct isakmp_gen *ext, u_int item_len,
const u_char *ep _U_, uint32_t phase, uint32_t doi _U_,
uint32_t proto _U_, int depth _U_)
{
#define USE_IPSECDOI_IN_PHASE1 1
const struct ikev1_pl_id *p;
static const char *idtypestr[] = {
"IPv4", "IPv4net", "IPv6", "IPv6net",
};
static const char *ipsecidtypestr[] = {
NULL, "IPv4", "FQDN", "user FQDN", "IPv4net", "IPv6",
"IPv6net", "IPv4range", "IPv6range", "ASN1 DN", "ASN1 GN",
"keyid",
};
u_int len;
const u_char *data;
ND_PRINT("%s:", NPSTR(ISAKMP_NPTYPE_ID));
p = (const struct ikev1_pl_id *)ext;
ND_TCHECK_SIZE(p);
if (sizeof(*p) < item_len) {
data = (const u_char *)(p + 1);
len = item_len - sizeof(*p);
} else {
data = NULL;
len = 0;
}
#if 0 /*debug*/
ND_PRINT(" [phase=%u doi=%u proto=%u]", phase, doi, proto);
#endif
switch (phase) {
#ifndef USE_IPSECDOI_IN_PHASE1
case 1:
#endif
default:
ND_PRINT(" idtype=%s",
STR_OR_ID(GET_U_1(p->d.id_type), idtypestr));
ND_PRINT(" doi_data=%u",
GET_BE_U_4(p->d.doi_data) & 0xffffff);
break;
#ifdef USE_IPSECDOI_IN_PHASE1
case 1:
#endif
case 2:
{
const struct ipsecdoi_id *doi_p;
const char *p_name;
uint8_t type, proto_id;
doi_p = (const struct ipsecdoi_id *)ext;
ND_TCHECK_SIZE(doi_p);
type = GET_U_1(doi_p->type);
ND_PRINT(" idtype=%s", STR_OR_ID(type, ipsecidtypestr));
/* A protocol ID of 0 DOES NOT mean IPPROTO_IP! */
proto_id = GET_U_1(doi_p->proto_id);
if (!ndo->ndo_nflag && proto_id && (p_name = netdb_protoname(proto_id)) != NULL)
ND_PRINT(" protoid=%s", p_name);
else
ND_PRINT(" protoid=%u", proto_id);
ND_PRINT(" port=%u", GET_BE_U_2(doi_p->port));
if (!len)
break;
if (data == NULL)
goto trunc;
ND_TCHECK_LEN(data, len);
switch (type) {
case IPSECDOI_ID_IPV4_ADDR:
if (len < 4)
ND_PRINT(" len=%u [bad: < 4]", len);
else
ND_PRINT(" len=%u %s", len, GET_IPADDR_STRING(data));
len = 0;
break;
case IPSECDOI_ID_FQDN:
case IPSECDOI_ID_USER_FQDN:
{
u_int i;
ND_PRINT(" len=%u ", len);
for (i = 0; i < len; i++)
fn_print_char(ndo, GET_U_1(data + i));
len = 0;
break;
}
case IPSECDOI_ID_IPV4_ADDR_SUBNET:
{
const u_char *mask;
if (len < 8)
ND_PRINT(" len=%u [bad: < 8]", len);
else {
mask = data + sizeof(nd_ipv4);
ND_PRINT(" len=%u %s/%u.%u.%u.%u", len,
GET_IPADDR_STRING(data),
GET_U_1(mask), GET_U_1(mask + 1),
GET_U_1(mask + 2),
GET_U_1(mask + 3));
}
len = 0;
break;
}
case IPSECDOI_ID_IPV6_ADDR:
if (len < 16)
ND_PRINT(" len=%u [bad: < 16]", len);
else
ND_PRINT(" len=%u %s", len, GET_IP6ADDR_STRING(data));
len = 0;
break;
case IPSECDOI_ID_IPV6_ADDR_SUBNET:
{
const u_char *mask;
if (len < 32)
ND_PRINT(" len=%u [bad: < 32]", len);
else {
mask = (const u_char *)(data + sizeof(nd_ipv6));
/*XXX*/
ND_PRINT(" len=%u %s/0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", len,
GET_IP6ADDR_STRING(data),
GET_U_1(mask), GET_U_1(mask + 1),
GET_U_1(mask + 2),
GET_U_1(mask + 3),
GET_U_1(mask + 4),
GET_U_1(mask + 5),
GET_U_1(mask + 6),
GET_U_1(mask + 7),
GET_U_1(mask + 8),
GET_U_1(mask + 9),
GET_U_1(mask + 10),
GET_U_1(mask + 11),
GET_U_1(mask + 12),
GET_U_1(mask + 13),
GET_U_1(mask + 14),
GET_U_1(mask + 15));
}
len = 0;
break;
}
case IPSECDOI_ID_IPV4_ADDR_RANGE:
if (len < 8)
ND_PRINT(" len=%u [bad: < 8]", len);
else {
ND_PRINT(" len=%u %s-%s", len,
GET_IPADDR_STRING(data),
GET_IPADDR_STRING(data + sizeof(nd_ipv4)));
}
len = 0;
break;
case IPSECDOI_ID_IPV6_ADDR_RANGE:
if (len < 32)
ND_PRINT(" len=%u [bad: < 32]", len);
else {
ND_PRINT(" len=%u %s-%s", len,
GET_IP6ADDR_STRING(data),
GET_IP6ADDR_STRING(data + sizeof(nd_ipv6)));
}
len = 0;
break;
case IPSECDOI_ID_DER_ASN1_DN:
case IPSECDOI_ID_DER_ASN1_GN:
case IPSECDOI_ID_KEY_ID:
break;
}
break;
}
}
if (data && len) {
ND_PRINT(" len=%u", len);
if (2 < ndo->ndo_vflag) {
ND_PRINT(" ");
if (!rawprint(ndo, (const uint8_t *)data, len))
goto trunc;
}
}
return (const u_char *)ext + item_len;
trunc:
ND_PRINT(" [|%s]", NPSTR(ISAKMP_NPTYPE_ID));
return NULL;
}
static const u_char *
ikev1_cert_print(netdissect_options *ndo, u_char tpay _U_,
const struct isakmp_gen *ext, u_int item_len,
const u_char *ep _U_, uint32_t phase _U_,
uint32_t doi0 _U_,
uint32_t proto0 _U_, int depth _U_)
{
const struct ikev1_pl_cert *p;
static const char *certstr[] = {
"none", "pkcs7", "pgp", "dns",
"x509sign", "x509ke", "kerberos", "crl",
"arl", "spki", "x509attr",
};
ND_PRINT("%s:", NPSTR(ISAKMP_NPTYPE_CERT));
p = (const struct ikev1_pl_cert *)ext;
ND_TCHECK_SIZE(p);
/*
* Our caller has ensured that the length is >= 4.
*/
ND_PRINT(" len=%u", item_len - 4);
ND_PRINT(" type=%s", STR_OR_ID(GET_U_1(p->encode), certstr));
if (2 < ndo->ndo_vflag && 4 < item_len) {
/* Print the entire payload in hex */
ND_PRINT(" ");
if (!rawprint(ndo, (const uint8_t *)(ext + 1), item_len - 4))
goto trunc;
}
return (const u_char *)ext + item_len;
trunc:
ND_PRINT(" [|%s]", NPSTR(ISAKMP_NPTYPE_CERT));
return NULL;
}
static const u_char *
ikev1_cr_print(netdissect_options *ndo, u_char tpay _U_,
const struct isakmp_gen *ext, u_int item_len,
const u_char *ep _U_, uint32_t phase _U_, uint32_t doi0 _U_,
uint32_t proto0 _U_, int depth _U_)
{
const struct ikev1_pl_cert *p;
static const char *certstr[] = {
"none", "pkcs7", "pgp", "dns",
"x509sign", "x509ke", "kerberos", "crl",
"arl", "spki", "x509attr",
};
ND_PRINT("%s:", NPSTR(ISAKMP_NPTYPE_CR));
p = (const struct ikev1_pl_cert *)ext;
ND_TCHECK_SIZE(p);
/*
* Our caller has ensured that the length is >= 4.
*/
ND_PRINT(" len=%u", item_len - 4);
ND_PRINT(" type=%s", STR_OR_ID(GET_U_1(p->encode), certstr));
if (2 < ndo->ndo_vflag && 4 < item_len) {
/* Print the entire payload in hex */
ND_PRINT(" ");
if (!rawprint(ndo, (const uint8_t *)(ext + 1), item_len - 4))
goto trunc;
}
return (const u_char *)ext + item_len;
trunc:
ND_PRINT(" [|%s]", NPSTR(ISAKMP_NPTYPE_CR));
return NULL;
}
static const u_char *
ikev1_hash_print(netdissect_options *ndo, u_char tpay _U_,
const struct isakmp_gen *ext, u_int item_len,
const u_char *ep _U_, uint32_t phase _U_, uint32_t doi _U_,
uint32_t proto _U_, int depth _U_)
{
ND_PRINT("%s:", NPSTR(ISAKMP_NPTYPE_HASH));
ND_TCHECK_SIZE(ext);
/*
* Our caller has ensured that the length is >= 4.
*/
ND_PRINT(" len=%u", item_len - 4);
if (2 < ndo->ndo_vflag && 4 < item_len) {
/* Print the entire payload in hex */
ND_PRINT(" ");
if (!rawprint(ndo, (const uint8_t *)(ext + 1), item_len - 4))
goto trunc;
}
return (const u_char *)ext + item_len;
trunc:
ND_PRINT(" [|%s]", NPSTR(ISAKMP_NPTYPE_HASH));
return NULL;
}
static const u_char *
ikev1_sig_print(netdissect_options *ndo, u_char tpay _U_,
const struct isakmp_gen *ext, u_int item_len,
const u_char *ep _U_, uint32_t phase _U_, uint32_t doi _U_,
uint32_t proto _U_, int depth _U_)
{
ND_PRINT("%s:", NPSTR(ISAKMP_NPTYPE_SIG));
ND_TCHECK_SIZE(ext);
/*
* Our caller has ensured that the length is >= 4.
*/
ND_PRINT(" len=%u", item_len - 4);
if (2 < ndo->ndo_vflag && 4 < item_len) {
/* Print the entire payload in hex */
ND_PRINT(" ");
if (!rawprint(ndo, (const uint8_t *)(ext + 1), item_len - 4))
goto trunc;
}
return (const u_char *)ext + item_len;
trunc:
ND_PRINT(" [|%s]", NPSTR(ISAKMP_NPTYPE_SIG));
return NULL;
}
static const u_char *
ikev1_nonce_print(netdissect_options *ndo, u_char tpay _U_,
const struct isakmp_gen *ext,
u_int item_len,
const u_char *ep,
uint32_t phase _U_, uint32_t doi _U_,
uint32_t proto _U_, int depth _U_)
{
ND_PRINT("%s:", NPSTR(ISAKMP_NPTYPE_NONCE));
ND_TCHECK_SIZE(ext);
/*
* Our caller has ensured that the length is >= 4.
*/
ND_PRINT(" n len=%u", item_len - 4);
if (item_len > 4) {
if (ndo->ndo_vflag > 2) {
ND_PRINT(" ");
if (!rawprint(ndo, (const uint8_t *)(ext + 1), item_len - 4))
goto trunc;
} else if (ndo->ndo_vflag > 1) {
ND_PRINT(" ");
if (!ike_show_somedata(ndo, (const u_char *)(ext + 1), ep))
goto trunc;
}
}
return (const u_char *)ext + item_len;
trunc:
ND_PRINT(" [|%s]", NPSTR(ISAKMP_NPTYPE_NONCE));
return NULL;
}
static const u_char *
ikev1_n_print(netdissect_options *ndo, u_char tpay _U_,
const struct isakmp_gen *ext, u_int item_len,
const u_char *ep, uint32_t phase _U_, uint32_t doi0 _U_,
uint32_t proto0 _U_, int depth _U_)
{
const struct ikev1_pl_n *p;
const u_char *cp;
const u_char *ep2;
uint32_t doi;
uint32_t proto;
uint16_t type;
uint8_t spi_size;
static const char *notify_error_str[] = {
NULL, "INVALID-PAYLOAD-TYPE",
"DOI-NOT-SUPPORTED", "SITUATION-NOT-SUPPORTED",
"INVALID-COOKIE", "INVALID-MAJOR-VERSION",
"INVALID-MINOR-VERSION", "INVALID-EXCHANGE-TYPE",
"INVALID-FLAGS", "INVALID-MESSAGE-ID",
"INVALID-PROTOCOL-ID", "INVALID-SPI",
"INVALID-TRANSFORM-ID", "ATTRIBUTES-NOT-SUPPORTED",
"NO-PROPOSAL-CHOSEN", "BAD-PROPOSAL-SYNTAX",
"PAYLOAD-MALFORMED", "INVALID-KEY-INFORMATION",
"INVALID-ID-INFORMATION", "INVALID-CERT-ENCODING",
"INVALID-CERTIFICATE", "CERT-TYPE-UNSUPPORTED",
"INVALID-CERT-AUTHORITY", "INVALID-HASH-INFORMATION",
"AUTHENTICATION-FAILED", "INVALID-SIGNATURE",
"ADDRESS-NOTIFICATION", "NOTIFY-SA-LIFETIME",
"CERTIFICATE-UNAVAILABLE", "UNSUPPORTED-EXCHANGE-TYPE",
"UNEQUAL-PAYLOAD-LENGTHS",
};
static const char *ipsec_notify_error_str[] = {
"RESERVED",
};
static const char *notify_status_str[] = {
"CONNECTED",
};
static const char *ipsec_notify_status_str[] = {
"RESPONDER-LIFETIME", "REPLAY-STATUS",
"INITIAL-CONTACT",
};
/* NOTE: these macro must be called with x in proper range */
/* 0 - 8191 */
#define NOTIFY_ERROR_STR(x) \
STR_OR_ID((x), notify_error_str)
/* 8192 - 16383 */
#define IPSEC_NOTIFY_ERROR_STR(x) \
STR_OR_ID((u_int)((x) - 8192), ipsec_notify_error_str)
/* 16384 - 24575 */
#define NOTIFY_STATUS_STR(x) \
STR_OR_ID((u_int)((x) - 16384), notify_status_str)
/* 24576 - 32767 */
#define IPSEC_NOTIFY_STATUS_STR(x) \
STR_OR_ID((u_int)((x) - 24576), ipsec_notify_status_str)
ND_PRINT("%s:", NPSTR(ISAKMP_NPTYPE_N));
p = (const struct ikev1_pl_n *)ext;
ND_TCHECK_SIZE(p);
doi = GET_BE_U_4(p->doi);
proto = GET_U_1(p->prot_id);
if (doi != 1) {
ND_PRINT(" doi=%u", doi);
ND_PRINT(" proto=%u", proto);
type = GET_BE_U_2(p->type);
if (type < 8192)
ND_PRINT(" type=%s", NOTIFY_ERROR_STR(type));
else if (type < 16384)
ND_PRINT(" type=%s", numstr(type));
else if (type < 24576)
ND_PRINT(" type=%s", NOTIFY_STATUS_STR(type));
else
ND_PRINT(" type=%s", numstr(type));
spi_size = GET_U_1(p->spi_size);
if (spi_size) {
ND_PRINT(" spi=");
if (!rawprint(ndo, (const uint8_t *)(p + 1), spi_size))
goto trunc;
}
return (const u_char *)(p + 1) + spi_size;
}
ND_PRINT(" doi=ipsec");
ND_PRINT(" proto=%s", PROTOIDSTR(proto));
type = GET_BE_U_2(p->type);
if (type < 8192)
ND_PRINT(" type=%s", NOTIFY_ERROR_STR(type));
else if (type < 16384)
ND_PRINT(" type=%s", IPSEC_NOTIFY_ERROR_STR(type));
else if (type < 24576)
ND_PRINT(" type=%s", NOTIFY_STATUS_STR(type));
else if (type < 32768)
ND_PRINT(" type=%s", IPSEC_NOTIFY_STATUS_STR(type));
else
ND_PRINT(" type=%s", numstr(type));
spi_size = GET_U_1(p->spi_size);
if (spi_size) {
ND_PRINT(" spi=");
if (!rawprint(ndo, (const uint8_t *)(p + 1), spi_size))
goto trunc;
}
cp = (const u_char *)(p + 1) + spi_size;
ep2 = (const u_char *)p + item_len;
if (cp < ep) {
switch (type) {
case IPSECDOI_NTYPE_RESPONDER_LIFETIME:
{
const struct attrmap *map = oakley_t_map;
size_t nmap = sizeof(oakley_t_map)/sizeof(oakley_t_map[0]);
ND_PRINT(" attrs=(");
while (cp < ep && cp < ep2) {
cp = ikev1_attrmap_print(ndo, cp, ep2, map, nmap);
if (cp == NULL) {
ND_PRINT(")");
goto trunc;
}
}
ND_PRINT(")");
break;
}
case IPSECDOI_NTYPE_REPLAY_STATUS:
ND_PRINT(" status=(");
ND_PRINT("replay detection %sabled",
GET_BE_U_4(cp) ? "en" : "dis");
ND_PRINT(")");
break;
default:
/*
* XXX - fill in more types here; see, for example,
* draft-ietf-ipsec-notifymsg-04.
*/
if (ndo->ndo_vflag > 3) {
ND_PRINT(" data=(");
if (!rawprint(ndo, (const uint8_t *)(cp), ep - cp))
goto trunc;
ND_PRINT(")");
} else {
if (!ike_show_somedata(ndo, cp, ep))
goto trunc;
}
break;
}
}
return (const u_char *)ext + item_len;
trunc:
ND_PRINT(" [|%s]", NPSTR(ISAKMP_NPTYPE_N));
return NULL;
}
static const u_char *
ikev1_d_print(netdissect_options *ndo, u_char tpay _U_,
const struct isakmp_gen *ext, u_int item_len _U_,
const u_char *ep _U_, uint32_t phase _U_, uint32_t doi0 _U_,
uint32_t proto0 _U_, int depth _U_)
{
const struct ikev1_pl_d *p;
const uint8_t *q;
uint32_t doi;
uint32_t proto;
uint8_t spi_size;
uint16_t num_spi;
u_int i;
ND_PRINT("%s:", NPSTR(ISAKMP_NPTYPE_D));
p = (const struct ikev1_pl_d *)ext;
ND_TCHECK_SIZE(p);
doi = GET_BE_U_4(p->doi);
proto = GET_U_1(p->prot_id);
if (doi != 1) {
ND_PRINT(" doi=%u", doi);
ND_PRINT(" proto=%u", proto);
} else {
ND_PRINT(" doi=ipsec");
ND_PRINT(" proto=%s", PROTOIDSTR(proto));
}
spi_size = GET_U_1(p->spi_size);
ND_PRINT(" spilen=%u", spi_size);
num_spi = GET_BE_U_2(p->num_spi);
ND_PRINT(" nspi=%u", num_spi);
- ND_PRINT(" spi=");
q = (const uint8_t *)(p + 1);
- for (i = 0; i < num_spi; i++) {
- if (i != 0)
- ND_PRINT(",");
- if (!rawprint(ndo, (const uint8_t *)q, spi_size))
- goto trunc;
- q += spi_size;
+ if (spi_size) {
+ ND_PRINT(" spi=");
+ for (i = 0; i < num_spi; i++) {
+ if (i != 0)
+ ND_PRINT(",");
+ if (!rawprint(ndo, (const uint8_t *)q, spi_size))
+ goto trunc;
+ q += spi_size;
+ }
}
return q;
trunc:
ND_PRINT(" [|%s]", NPSTR(ISAKMP_NPTYPE_D));
return NULL;
}
static const u_char *
ikev1_vid_print(netdissect_options *ndo, u_char tpay _U_,
const struct isakmp_gen *ext,
u_int item_len, const u_char *ep _U_,
uint32_t phase _U_, uint32_t doi _U_,
uint32_t proto _U_, int depth _U_)
{
ND_PRINT("%s:", NPSTR(ISAKMP_NPTYPE_VID));
ND_TCHECK_SIZE(ext);
/*
* Our caller has ensured that the length is >= 4.
*/
ND_PRINT(" len=%u", item_len - 4);
if (2 < ndo->ndo_vflag && 4 < item_len) {
/* Print the entire payload in hex */
ND_PRINT(" ");
if (!rawprint(ndo, (const uint8_t *)(ext + 1), item_len - 4))
goto trunc;
}
return (const u_char *)ext + item_len;
trunc:
ND_PRINT(" [|%s]", NPSTR(ISAKMP_NPTYPE_VID));
return NULL;
}
/************************************************************/
/* */
/* IKE v2 - rfc4306 - dissector */
/* */
/************************************************************/
static void
ikev2_pay_print(netdissect_options *ndo, const char *payname, uint8_t critical)
{
ND_PRINT("%s%s:", payname, critical&0x80 ? "[C]" : "");
}
static const u_char *
ikev2_gen_print(netdissect_options *ndo, u_char tpay,
const struct isakmp_gen *ext, u_int item_len)
{
const struct isakmp_gen *p = (const struct isakmp_gen *)ext;
ND_TCHECK_SIZE(ext);
ikev2_pay_print(ndo, NPSTR(tpay), GET_U_1(p->critical));
/*
* Our caller has ensured that the length is >= 4.
*/
ND_PRINT(" len=%u", item_len - 4);
if (2 < ndo->ndo_vflag && 4 < item_len) {
/* Print the entire payload in hex */
ND_PRINT(" ");
if (!rawprint(ndo, (const uint8_t *)(ext + 1), item_len - 4))
goto trunc;
}
return (const u_char *)ext + item_len;
trunc:
ND_PRINT(" [|%s]", NPSTR(tpay));
return NULL;
}
static const u_char *
ikev2_t_print(netdissect_options *ndo, int tcount,
const struct isakmp_gen *ext, u_int item_len,
const u_char *ep)
{
const struct ikev2_t *p;
uint16_t t_id;
uint8_t t_type;
const u_char *cp;
const char *idstr;
const struct attrmap *map;
size_t nmap;
const u_char *ep2;
p = (const struct ikev2_t *)ext;
ND_TCHECK_SIZE(p);
ikev2_pay_print(ndo, NPSTR(ISAKMP_NPTYPE_T), GET_U_1(p->h.critical));
t_id = GET_BE_U_2(p->t_id);
map = NULL;
nmap = 0;
t_type = GET_U_1(p->t_type);
switch (t_type) {
case IV2_T_ENCR:
idstr = STR_OR_ID(t_id, esp_p_map);
map = encr_t_map;
nmap = sizeof(encr_t_map)/sizeof(encr_t_map[0]);
break;
case IV2_T_PRF:
idstr = STR_OR_ID(t_id, prf_p_map);
break;
case IV2_T_INTEG:
idstr = STR_OR_ID(t_id, integ_p_map);
break;
case IV2_T_DH:
idstr = STR_OR_ID(t_id, dh_p_map);
break;
case IV2_T_ESN:
idstr = STR_OR_ID(t_id, esn_p_map);
break;
default:
idstr = NULL;
break;
}
if (idstr)
ND_PRINT(" #%u type=%s id=%s ", tcount,
STR_OR_ID(t_type, ikev2_t_type_map),
idstr);
else
ND_PRINT(" #%u type=%s id=%u ", tcount,
STR_OR_ID(t_type, ikev2_t_type_map),
t_id);
cp = (const u_char *)(p + 1);
ep2 = (const u_char *)p + item_len;
while (cp < ep && cp < ep2) {
if (map && nmap) {
cp = ikev1_attrmap_print(ndo, cp, ep2, map, nmap);
} else
cp = ikev1_attr_print(ndo, cp, ep2);
if (cp == NULL)
goto trunc;
}
if (ep < ep2)
ND_PRINT("...");
return cp;
trunc:
ND_PRINT(" [|%s]", NPSTR(ISAKMP_NPTYPE_T));
return NULL;
}
static const u_char *
ikev2_p_print(netdissect_options *ndo, u_char tpay _U_, int pcount _U_,
const struct isakmp_gen *ext, u_int oprop_length,
const u_char *ep, int depth)
{
const struct ikev2_p *p;
u_int prop_length;
uint8_t spi_size;
const u_char *cp;
int i;
int tcount;
u_char np;
u_int item_len;
p = (const struct ikev2_p *)ext;
ND_TCHECK_SIZE(p);
ikev2_pay_print(ndo, NPSTR(ISAKMP_NPTYPE_P), GET_U_1(p->h.critical));
/*
* ikev2_sa_print() guarantees that this is >= 4.
*/
prop_length = oprop_length - 4;
ND_PRINT(" #%u protoid=%s transform=%u len=%u",
GET_U_1(p->p_no), PROTOIDSTR(GET_U_1(p->prot_id)),
GET_U_1(p->num_t), oprop_length);
cp = (const u_char *)(p + 1);
spi_size = GET_U_1(p->spi_size);
if (spi_size) {
if (prop_length < spi_size)
goto toolong;
ND_PRINT(" spi=");
if (!rawprint(ndo, (const uint8_t *)cp, spi_size))
goto trunc;
cp += spi_size;
prop_length -= spi_size;
}
/*
* Print the transforms.
*/
tcount = 0;
for (np = ISAKMP_NPTYPE_T; np != 0; np = GET_U_1(ext->np)) {
tcount++;
ext = (const struct isakmp_gen *)cp;
if (prop_length < sizeof(*ext))
goto toolong;
ND_TCHECK_SIZE(ext);
/*
* Since we can't have a payload length of less than 4 bytes,
* we need to bail out here if the generic header is nonsensical
* or truncated, otherwise we could loop forever processing
* zero-length items or otherwise misdissect the packet.
*/
item_len = GET_BE_U_2(ext->len);
if (item_len <= 4)
goto trunc;
if (prop_length < item_len)
goto toolong;
ND_TCHECK_LEN(cp, item_len);
depth++;
ND_PRINT("\n");
for (i = 0; i < depth; i++)
ND_PRINT(" ");
ND_PRINT("(");
if (np == ISAKMP_NPTYPE_T) {
cp = ikev2_t_print(ndo, tcount, ext, item_len, ep);
if (cp == NULL) {
/* error, already reported */
return NULL;
}
} else {
ND_PRINT("%s", NPSTR(np));
cp += item_len;
}
ND_PRINT(")");
depth--;
prop_length -= item_len;
}
return cp;
toolong:
/*
* Skip the rest of the proposal.
*/
cp += prop_length;
ND_PRINT(" [|%s]", NPSTR(ISAKMP_NPTYPE_P));
return cp;
trunc:
ND_PRINT(" [|%s]", NPSTR(ISAKMP_NPTYPE_P));
return NULL;
}
static const u_char *
ikev2_sa_print(netdissect_options *ndo, u_char tpay,
const struct isakmp_gen *ext1,
u_int osa_length, const u_char *ep,
uint32_t phase _U_, uint32_t doi _U_,
uint32_t proto _U_, int depth)
{
const struct isakmp_gen *ext;
u_int sa_length;
const u_char *cp;
int i;
int pcount;
u_char np;
u_int item_len;
ND_TCHECK_SIZE(ext1);
ikev2_pay_print(ndo, "sa", GET_U_1(ext1->critical));
/*
* ikev2_sub0_print() guarantees that this is >= 4.
*/
osa_length= GET_BE_U_2(ext1->len);
sa_length = osa_length - 4;
ND_PRINT(" len=%u", sa_length);
/*
* Print the payloads.
*/
cp = (const u_char *)(ext1 + 1);
pcount = 0;
for (np = ISAKMP_NPTYPE_P; np != 0; np = GET_U_1(ext->np)) {
pcount++;
ext = (const struct isakmp_gen *)cp;
if (sa_length < sizeof(*ext))
goto toolong;
ND_TCHECK_SIZE(ext);
/*
* Since we can't have a payload length of less than 4 bytes,
* we need to bail out here if the generic header is nonsensical
* or truncated, otherwise we could loop forever processing
* zero-length items or otherwise misdissect the packet.
*/
item_len = GET_BE_U_2(ext->len);
if (item_len <= 4)
goto trunc;
if (sa_length < item_len)
goto toolong;
ND_TCHECK_LEN(cp, item_len);
depth++;
ND_PRINT("\n");
for (i = 0; i < depth; i++)
ND_PRINT(" ");
ND_PRINT("(");
if (np == ISAKMP_NPTYPE_P) {
cp = ikev2_p_print(ndo, np, pcount, ext, item_len,
ep, depth);
if (cp == NULL) {
/* error, already reported */
return NULL;
}
} else {
ND_PRINT("%s", NPSTR(np));
cp += item_len;
}
ND_PRINT(")");
depth--;
sa_length -= item_len;
}
return cp;
toolong:
/*
* Skip the rest of the SA.
*/
cp += sa_length;
ND_PRINT(" [|%s]", NPSTR(tpay));
return cp;
trunc:
ND_PRINT(" [|%s]", NPSTR(tpay));
return NULL;
}
static const u_char *
ikev2_ke_print(netdissect_options *ndo, u_char tpay,
const struct isakmp_gen *ext,
u_int item_len, const u_char *ep _U_,
uint32_t phase _U_, uint32_t doi _U_,
uint32_t proto _U_, int depth _U_)
{
const struct ikev2_ke *k;
k = (const struct ikev2_ke *)ext;
ND_TCHECK_SIZE(k);
ikev2_pay_print(ndo, NPSTR(tpay), GET_U_1(k->h.critical));
if (item_len < 8) {
ND_PRINT(" len=%u < 8", item_len);
return (const u_char *)ext + item_len;
}
ND_PRINT(" len=%u group=%s", item_len - 8,
STR_OR_ID(GET_BE_U_2(k->ke_group), dh_p_map));
if (2 < ndo->ndo_vflag && 8 < item_len) {
ND_PRINT(" ");
if (!rawprint(ndo, (const uint8_t *)(k + 1), item_len - 8))
goto trunc;
}
return (const u_char *)ext + item_len;
trunc:
ND_PRINT(" [|%s]", NPSTR(tpay));
return NULL;
}
static const u_char *
ikev2_ID_print(netdissect_options *ndo, u_char tpay,
const struct isakmp_gen *ext,
u_int item_len, const u_char *ep _U_,
uint32_t phase _U_, uint32_t doi _U_,
uint32_t proto _U_, int depth _U_)
{
const struct ikev2_id *idp;
u_int idtype_len, i;
unsigned int dumpascii, dumphex;
const unsigned char *typedata;
idp = (const struct ikev2_id *)ext;
ND_TCHECK_SIZE(idp);
ikev2_pay_print(ndo, NPSTR(tpay), GET_U_1(idp->h.critical));
/*
* Our caller has ensured that the length is >= 4.
*/
ND_PRINT(" len=%u", item_len - 4);
if (2 < ndo->ndo_vflag && 4 < item_len) {
/* Print the entire payload in hex */
ND_PRINT(" ");
if (!rawprint(ndo, (const uint8_t *)(ext + 1), item_len - 4))
goto trunc;
}
idtype_len =item_len - sizeof(struct ikev2_id);
dumpascii = 0;
dumphex = 0;
typedata = (const unsigned char *)(ext)+sizeof(struct ikev2_id);
switch(GET_U_1(idp->type)) {
case ID_IPV4_ADDR:
ND_PRINT(" ipv4:");
dumphex=1;
break;
case ID_FQDN:
ND_PRINT(" fqdn:");
dumpascii=1;
break;
case ID_RFC822_ADDR:
ND_PRINT(" rfc822:");
dumpascii=1;
break;
case ID_IPV6_ADDR:
ND_PRINT(" ipv6:");
dumphex=1;
break;
case ID_DER_ASN1_DN:
ND_PRINT(" dn:");
dumphex=1;
break;
case ID_DER_ASN1_GN:
ND_PRINT(" gn:");
dumphex=1;
break;
case ID_KEY_ID:
ND_PRINT(" keyid:");
dumphex=1;
break;
}
if(dumpascii) {
ND_TCHECK_LEN(typedata, idtype_len);
for(i=0; i<idtype_len; i++) {
if(ND_ASCII_ISPRINT(GET_U_1(typedata + i))) {
ND_PRINT("%c", GET_U_1(typedata + i));
} else {
ND_PRINT(".");
}
}
}
if(dumphex) {
if (!rawprint(ndo, (const uint8_t *)typedata, idtype_len))
goto trunc;
}
return (const u_char *)ext + item_len;
trunc:
ND_PRINT(" [|%s]", NPSTR(tpay));
return NULL;
}
static const u_char *
ikev2_cert_print(netdissect_options *ndo, u_char tpay,
const struct isakmp_gen *ext,
u_int item_len, const u_char *ep _U_,
uint32_t phase _U_, uint32_t doi _U_,
uint32_t proto _U_, int depth _U_)
{
return ikev2_gen_print(ndo, tpay, ext, item_len);
}
static const u_char *
ikev2_cr_print(netdissect_options *ndo, u_char tpay,
const struct isakmp_gen *ext,
u_int item_len, const u_char *ep _U_,
uint32_t phase _U_, uint32_t doi _U_,
uint32_t proto _U_, int depth _U_)
{
return ikev2_gen_print(ndo, tpay, ext, item_len);
}
static const u_char *
ikev2_auth_print(netdissect_options *ndo, u_char tpay,
const struct isakmp_gen *ext,
u_int item_len, const u_char *ep,
uint32_t phase _U_, uint32_t doi _U_,
uint32_t proto _U_, int depth _U_)
{
const struct ikev2_auth *p;
const char *v2_auth[]={ "invalid", "rsasig",
"shared-secret", "dsssig" };
const u_char *authdata = (const u_char *)ext + sizeof(struct ikev2_auth);
ND_TCHECK_LEN(ext, sizeof(struct ikev2_auth));
p = (const struct ikev2_auth *)ext;
ikev2_pay_print(ndo, NPSTR(tpay), GET_U_1(p->h.critical));
/*
* Our caller has ensured that the length is >= 4.
*/
ND_PRINT(" len=%u method=%s", item_len-4,
STR_OR_ID(GET_U_1(p->auth_method), v2_auth));
if (item_len > 4) {
if (ndo->ndo_vflag > 1) {
ND_PRINT(" authdata=(");
if (!rawprint(ndo, (const uint8_t *)authdata, item_len - sizeof(struct ikev2_auth)))
goto trunc;
ND_PRINT(") ");
} else if (ndo->ndo_vflag) {
if (!ike_show_somedata(ndo, authdata, ep))
goto trunc;
}
}
return (const u_char *)ext + item_len;
trunc:
ND_PRINT(" [|%s]", NPSTR(tpay));
return NULL;
}
static const u_char *
ikev2_nonce_print(netdissect_options *ndo, u_char tpay,
const struct isakmp_gen *ext,
u_int item_len, const u_char *ep,
uint32_t phase _U_, uint32_t doi _U_,
uint32_t proto _U_, int depth _U_)
{
ND_TCHECK_SIZE(ext);
ikev2_pay_print(ndo, "nonce", GET_U_1(ext->critical));
/*
* Our caller has ensured that the length is >= 4.
*/
ND_PRINT(" len=%u", item_len - 4);
if (1 < ndo->ndo_vflag && 4 < item_len) {
ND_PRINT(" nonce=(");
if (!rawprint(ndo, (const uint8_t *)(ext + 1), item_len - 4))
goto trunc;
ND_PRINT(") ");
} else if(ndo->ndo_vflag && 4 < item_len) {
if(!ike_show_somedata(ndo, (const u_char *)(ext+1), ep)) goto trunc;
}
return (const u_char *)ext + item_len;
trunc:
ND_PRINT(" [|%s]", NPSTR(tpay));
return NULL;
}
/* notify payloads */
static const u_char *
ikev2_n_print(netdissect_options *ndo, u_char tpay _U_,
const struct isakmp_gen *ext,
u_int item_len, const u_char *ep,
uint32_t phase _U_, uint32_t doi _U_,
uint32_t proto _U_, int depth _U_)
{
const struct ikev2_n *p;
uint16_t type;
uint8_t spi_size;
const u_char *cp;
u_char showspi, showsomedata;
const char *notify_name;
p = (const struct ikev2_n *)ext;
ND_TCHECK_SIZE(p);
ikev2_pay_print(ndo, NPSTR(ISAKMP_NPTYPE_N), GET_U_1(p->h.critical));
showspi = 1;
showsomedata=0;
notify_name=NULL;
ND_PRINT(" prot_id=%s", PROTOIDSTR(GET_U_1(p->prot_id)));
type = GET_BE_U_2(p->type);
/* notify space is annoying sparse */
switch(type) {
case IV2_NOTIFY_UNSUPPORTED_CRITICAL_PAYLOAD:
notify_name = "unsupported_critical_payload";
showspi = 0;
break;
case IV2_NOTIFY_INVALID_IKE_SPI:
notify_name = "invalid_ike_spi";
showspi = 1;
break;
case IV2_NOTIFY_INVALID_MAJOR_VERSION:
notify_name = "invalid_major_version";
showspi = 0;
break;
case IV2_NOTIFY_INVALID_SYNTAX:
notify_name = "invalid_syntax";
showspi = 1;
break;
case IV2_NOTIFY_INVALID_MESSAGE_ID:
notify_name = "invalid_message_id";
showspi = 1;
break;
case IV2_NOTIFY_INVALID_SPI:
notify_name = "invalid_spi";
showspi = 1;
break;
case IV2_NOTIFY_NO_PROPOSAL_CHOSEN:
notify_name = "no_protocol_chosen";
showspi = 1;
break;
case IV2_NOTIFY_INVALID_KE_PAYLOAD:
notify_name = "invalid_ke_payload";
showspi = 1;
break;
case IV2_NOTIFY_AUTHENTICATION_FAILED:
notify_name = "authentication_failed";
showspi = 1;
break;
case IV2_NOTIFY_SINGLE_PAIR_REQUIRED:
notify_name = "single_pair_required";
showspi = 1;
break;
case IV2_NOTIFY_NO_ADDITIONAL_SAS:
notify_name = "no_additional_sas";
showspi = 0;
break;
case IV2_NOTIFY_INTERNAL_ADDRESS_FAILURE:
notify_name = "internal_address_failure";
showspi = 0;
break;
case IV2_NOTIFY_FAILED_CP_REQUIRED:
notify_name = "failed:cp_required";
showspi = 0;
break;
case IV2_NOTIFY_INVALID_SELECTORS:
notify_name = "invalid_selectors";
showspi = 0;
break;
case IV2_NOTIFY_INITIAL_CONTACT:
notify_name = "initial_contact";
showspi = 0;
break;
case IV2_NOTIFY_SET_WINDOW_SIZE:
notify_name = "set_window_size";
showspi = 0;
break;
case IV2_NOTIFY_ADDITIONAL_TS_POSSIBLE:
notify_name = "additional_ts_possible";
showspi = 0;
break;
case IV2_NOTIFY_IPCOMP_SUPPORTED:
notify_name = "ipcomp_supported";
showspi = 0;
break;
case IV2_NOTIFY_NAT_DETECTION_SOURCE_IP:
notify_name = "nat_detection_source_ip";
showspi = 1;
break;
case IV2_NOTIFY_NAT_DETECTION_DESTINATION_IP:
notify_name = "nat_detection_destination_ip";
showspi = 1;
break;
case IV2_NOTIFY_COOKIE:
notify_name = "cookie";
showspi = 1;
showsomedata= 1;
break;
case IV2_NOTIFY_USE_TRANSPORT_MODE:
notify_name = "use_transport_mode";
showspi = 0;
break;
case IV2_NOTIFY_HTTP_CERT_LOOKUP_SUPPORTED:
notify_name = "http_cert_lookup_supported";
showspi = 0;
break;
case IV2_NOTIFY_REKEY_SA:
notify_name = "rekey_sa";
showspi = 1;
break;
case IV2_NOTIFY_ESP_TFC_PADDING_NOT_SUPPORTED:
notify_name = "tfc_padding_not_supported";
showspi = 0;
break;
case IV2_NOTIFY_NON_FIRST_FRAGMENTS_ALSO:
notify_name = "non_first_fragment_also";
showspi = 0;
break;
default:
if (type < 8192) {
notify_name="error";
} else if(type < 16384) {
notify_name="private-error";
} else if(type < 40960) {
notify_name="status";
} else {
notify_name="private-status";
}
}
if(notify_name) {
ND_PRINT(" type=%u(%s)", type, notify_name);
}
spi_size = GET_U_1(p->spi_size);
if (showspi && spi_size) {
ND_PRINT(" spi=");
if (!rawprint(ndo, (const uint8_t *)(p + 1), spi_size))
goto trunc;
}
cp = (const u_char *)(p + 1) + spi_size;
if (cp < ep) {
if (ndo->ndo_vflag > 3 || (showsomedata && ep-cp < 30)) {
ND_PRINT(" data=(");
if (!rawprint(ndo, (const uint8_t *)(cp), ep - cp))
goto trunc;
ND_PRINT(")");
} else if (showsomedata) {
if (!ike_show_somedata(ndo, cp, ep))
goto trunc;
}
}
return (const u_char *)ext + item_len;
trunc:
ND_PRINT(" [|%s]", NPSTR(ISAKMP_NPTYPE_N));
return NULL;
}
static const u_char *
ikev2_d_print(netdissect_options *ndo, u_char tpay,
const struct isakmp_gen *ext,
u_int item_len, const u_char *ep _U_,
uint32_t phase _U_, uint32_t doi _U_,
uint32_t proto _U_, int depth _U_)
{
return ikev2_gen_print(ndo, tpay, ext, item_len);
}
static const u_char *
ikev2_vid_print(netdissect_options *ndo, u_char tpay,
const struct isakmp_gen *ext,
u_int item_len, const u_char *ep _U_,
uint32_t phase _U_, uint32_t doi _U_,
uint32_t proto _U_, int depth _U_)
{
const u_char *vid;
u_int i, len;
ND_TCHECK_SIZE(ext);
ikev2_pay_print(ndo, NPSTR(tpay), GET_U_1(ext->critical));
/*
* Our caller has ensured that the length is >= 4.
*/
ND_PRINT(" len=%u vid=", item_len - 4);
vid = (const u_char *)(ext+1);
len = item_len - 4;
ND_TCHECK_LEN(vid, len);
for(i=0; i<len; i++) {
if(ND_ASCII_ISPRINT(GET_U_1(vid + i)))
ND_PRINT("%c", GET_U_1(vid + i));
else ND_PRINT(".");
}
if (2 < ndo->ndo_vflag && 4 < len) {
/* Print the entire payload in hex */
ND_PRINT(" ");
if (!rawprint(ndo, (const uint8_t *)(ext + 1), item_len - 4))
goto trunc;
}
return (const u_char *)ext + item_len;
trunc:
ND_PRINT(" [|%s]", NPSTR(tpay));
return NULL;
}
static const u_char *
ikev2_TS_print(netdissect_options *ndo, u_char tpay,
const struct isakmp_gen *ext,
u_int item_len, const u_char *ep _U_,
uint32_t phase _U_, uint32_t doi _U_,
uint32_t proto _U_, int depth _U_)
{
return ikev2_gen_print(ndo, tpay, ext, item_len);
}
static const u_char *
ikev2_e_print(netdissect_options *ndo,
#ifndef HAVE_LIBCRYPTO
_U_
#endif
const struct isakmp *base,
u_char tpay,
const struct isakmp_gen *ext,
u_int item_len, const u_char *ep _U_,
#ifndef HAVE_LIBCRYPTO
_U_
#endif
uint32_t phase,
#ifndef HAVE_LIBCRYPTO
_U_
#endif
uint32_t doi,
#ifndef HAVE_LIBCRYPTO
_U_
#endif
uint32_t proto,
#ifndef HAVE_LIBCRYPTO
_U_
#endif
int depth)
{
const u_char *dat;
u_int dlen;
#ifdef HAVE_LIBCRYPTO
uint8_t np;
#endif
ND_TCHECK_SIZE(ext);
ikev2_pay_print(ndo, NPSTR(tpay), GET_U_1(ext->critical));
dlen = item_len-4;
ND_PRINT(" len=%u", dlen);
if (2 < ndo->ndo_vflag && 4 < dlen) {
ND_PRINT(" ");
if (!rawprint(ndo, (const uint8_t *)(ext + 1), dlen))
goto trunc;
}
dat = (const u_char *)(ext+1);
ND_TCHECK_LEN(dat, dlen);
#ifdef HAVE_LIBCRYPTO
np = GET_U_1(ext->np);
/* try to decrypt it! */
if(esp_decrypt_buffer_by_ikev2_print(ndo,
GET_U_1(base->flags) & ISAKMP_FLAG_I,
base->i_ck, base->r_ck,
dat, dat+dlen)) {
ext = (const struct isakmp_gen *)ndo->ndo_packetp;
/* got it decrypted, print stuff inside. */
ikev2_sub_print(ndo, base, np, ext,
ndo->ndo_snapend, phase, doi, proto, depth+1);
/*
* esp_decrypt_buffer_by_ikev2_print pushed information
* on the buffer stack; we're done with the buffer, so
* pop it (which frees the buffer)
*/
nd_pop_packet_info(ndo);
}
#endif
/* always return NULL, because E must be at end, and NP refers
* to what was inside.
*/
return NULL;
trunc:
ND_PRINT(" [|%s]", NPSTR(tpay));
return NULL;
}
static const u_char *
ikev2_cp_print(netdissect_options *ndo, u_char tpay,
const struct isakmp_gen *ext,
u_int item_len, const u_char *ep _U_,
uint32_t phase _U_, uint32_t doi _U_,
uint32_t proto _U_, int depth _U_)
{
return ikev2_gen_print(ndo, tpay, ext, item_len);
}
static const u_char *
ikev2_eap_print(netdissect_options *ndo, u_char tpay,
const struct isakmp_gen *ext,
u_int item_len, const u_char *ep _U_,
uint32_t phase _U_, uint32_t doi _U_,
uint32_t proto _U_, int depth _U_)
{
return ikev2_gen_print(ndo, tpay, ext, item_len);
}
static const u_char *
ike_sub0_print(netdissect_options *ndo,
u_char np, const struct isakmp_gen *ext, const u_char *ep,
uint32_t phase, uint32_t doi, uint32_t proto, int depth)
{
const u_char *cp;
u_int item_len;
cp = (const u_char *)ext;
ND_TCHECK_SIZE(ext);
/*
* Since we can't have a payload length of less than 4 bytes,
* we need to bail out here if the generic header is nonsensical
* or truncated, otherwise we could loop forever processing
* zero-length items or otherwise misdissect the packet.
*/
item_len = GET_BE_U_2(ext->len);
if (item_len <= 4)
return NULL;
if (NPFUNC(np)) {
/*
* XXX - what if item_len is too short, or too long,
* for this payload type?
*/
cp = (*npfunc[np])(ndo, np, ext, item_len, ep, phase, doi, proto, depth);
} else {
ND_PRINT("%s", NPSTR(np));
cp += item_len;
}
return cp;
trunc:
nd_print_trunc(ndo);
return NULL;
}
static const u_char *
ikev1_sub_print(netdissect_options *ndo,
u_char np, const struct isakmp_gen *ext, const u_char *ep,
uint32_t phase, uint32_t doi, uint32_t proto, int depth)
{
const u_char *cp;
int i;
u_int item_len;
cp = (const u_char *)ext;
while (np) {
ND_TCHECK_SIZE(ext);
item_len = GET_BE_U_2(ext->len);
ND_TCHECK_LEN(ext, item_len);
depth++;
ND_PRINT("\n");
for (i = 0; i < depth; i++)
ND_PRINT(" ");
ND_PRINT("(");
cp = ike_sub0_print(ndo, np, ext, ep, phase, doi, proto, depth);
ND_PRINT(")");
depth--;
if (cp == NULL) {
/* Zero-length subitem */
return NULL;
}
np = GET_U_1(ext->np);
ext = (const struct isakmp_gen *)cp;
}
return cp;
trunc:
ND_PRINT(" [|%s]", NPSTR(np));
return NULL;
}
static char *
numstr(u_int x)
{
static char buf[20];
snprintf(buf, sizeof(buf), "#%u", x);
return buf;
}
static void
ikev1_print(netdissect_options *ndo,
const u_char *bp, u_int length,
const u_char *bp2, const struct isakmp *base)
{
const struct isakmp *p;
const u_char *ep;
u_int flags;
u_char np;
int i;
u_int phase;
p = (const struct isakmp *)bp;
ep = ndo->ndo_snapend;
phase = (GET_BE_U_4(base->msgid) == 0) ? 1 : 2;
if (phase == 1)
ND_PRINT(" phase %u", phase);
else
ND_PRINT(" phase %u/others", phase);
i = cookie_find(&base->i_ck);
if (i < 0) {
if (iszero(ndo, base->r_ck, sizeof(base->r_ck))) {
/* the first packet */
ND_PRINT(" I");
if (bp2)
cookie_record(ndo, &base->i_ck, bp2);
} else
ND_PRINT(" ?");
} else {
if (bp2 && cookie_isinitiator(ndo, i, bp2))
ND_PRINT(" I");
else if (bp2 && cookie_isresponder(ndo, i, bp2))
ND_PRINT(" R");
else
ND_PRINT(" ?");
}
ND_PRINT(" %s", ETYPESTR(GET_U_1(base->etype)));
flags = GET_U_1(base->flags);
if (flags) {
ND_PRINT("[%s%s]", flags & ISAKMP_FLAG_E ? "E" : "",
flags & ISAKMP_FLAG_C ? "C" : "");
}
if (ndo->ndo_vflag) {
const struct isakmp_gen *ext;
ND_PRINT(":");
np = GET_U_1(base->np);
/* regardless of phase... */
if (flags & ISAKMP_FLAG_E) {
/*
* encrypted, nothing we can do right now.
* we hope to decrypt the packet in the future...
*/
ND_PRINT(" [encrypted %s]", NPSTR(np));
goto done;
}
CHECKLEN(p + 1, np);
ext = (const struct isakmp_gen *)(p + 1);
ikev1_sub_print(ndo, np, ext, ep, phase, 0, 0, 0);
}
done:
if (ndo->ndo_vflag) {
if (GET_BE_U_4(base->len) != length) {
ND_PRINT(" (len mismatch: isakmp %u/ip %u)",
GET_BE_U_4(base->len), length);
}
}
}
static const u_char *
ikev2_sub0_print(netdissect_options *ndo, const struct isakmp *base,
u_char np,
const struct isakmp_gen *ext, const u_char *ep,
uint32_t phase, uint32_t doi, uint32_t proto, int depth)
{
const u_char *cp;
u_int item_len;
cp = (const u_char *)ext;
ND_TCHECK_SIZE(ext);
/*
* Since we can't have a payload length of less than 4 bytes,
* we need to bail out here if the generic header is nonsensical
* or truncated, otherwise we could loop forever processing
* zero-length items or otherwise misdissect the packet.
*/
item_len = GET_BE_U_2(ext->len);
if (item_len <= 4)
return NULL;
if (np == ISAKMP_NPTYPE_v2E) {
cp = ikev2_e_print(ndo, base, np, ext, item_len,
ep, phase, doi, proto, depth);
} else if (NPFUNC(np)) {
/*
* XXX - what if item_len is too short, or too long,
* for this payload type?
*/
cp = (*npfunc[np])(ndo, np, ext, item_len,
ep, phase, doi, proto, depth);
} else {
ND_PRINT("%s", NPSTR(np));
cp += item_len;
}
return cp;
trunc:
nd_print_trunc(ndo);
return NULL;
}
static const u_char *
ikev2_sub_print(netdissect_options *ndo,
const struct isakmp *base,
u_char np, const struct isakmp_gen *ext, const u_char *ep,
uint32_t phase, uint32_t doi, uint32_t proto, int depth)
{
const u_char *cp;
int i;
cp = (const u_char *)ext;
while (np) {
ND_TCHECK_SIZE(ext);
ND_TCHECK_LEN(ext, GET_BE_U_2(ext->len));
depth++;
ND_PRINT("\n");
for (i = 0; i < depth; i++)
ND_PRINT(" ");
ND_PRINT("(");
cp = ikev2_sub0_print(ndo, base, np,
ext, ep, phase, doi, proto, depth);
ND_PRINT(")");
depth--;
if (cp == NULL) {
/* Zero-length subitem */
return NULL;
}
np = GET_U_1(ext->np);
ext = (const struct isakmp_gen *)cp;
}
return cp;
trunc:
ND_PRINT(" [|%s]", NPSTR(np));
return NULL;
}
static void
ikev2_print(netdissect_options *ndo,
const u_char *bp, u_int length,
const u_char *bp2 _U_, const struct isakmp *base)
{
const struct isakmp *p;
const u_char *ep;
uint8_t flags;
u_char np;
u_int phase;
p = (const struct isakmp *)bp;
ep = ndo->ndo_snapend;
phase = (GET_BE_U_4(base->msgid) == 0) ? 1 : 2;
if (phase == 1)
ND_PRINT(" parent_sa");
else
ND_PRINT(" child_sa ");
ND_PRINT(" %s", ETYPESTR(GET_U_1(base->etype)));
flags = GET_U_1(base->flags);
if (flags) {
ND_PRINT("[%s%s%s]",
flags & ISAKMP_FLAG_I ? "I" : "",
flags & ISAKMP_FLAG_V ? "V" : "",
flags & ISAKMP_FLAG_R ? "R" : "");
}
if (ndo->ndo_vflag) {
const struct isakmp_gen *ext;
ND_PRINT(":");
np = GET_U_1(base->np);
/* regardless of phase... */
if (flags & ISAKMP_FLAG_E) {
/*
* encrypted, nothing we can do right now.
* we hope to decrypt the packet in the future...
*/
ND_PRINT(" [encrypted %s]", NPSTR(np));
goto done;
}
CHECKLEN(p + 1, np)
ext = (const struct isakmp_gen *)(p + 1);
ikev2_sub_print(ndo, base, np, ext, ep, phase, 0, 0, 0);
}
done:
if (ndo->ndo_vflag) {
if (GET_BE_U_4(base->len) != length) {
ND_PRINT(" (len mismatch: isakmp %u/ip %u)",
GET_BE_U_4(base->len), length);
}
}
}
void
isakmp_print(netdissect_options *ndo,
const u_char *bp, u_int length,
const u_char *bp2)
{
const struct isakmp *p;
const u_char *ep;
u_int major, minor;
ndo->ndo_protocol = "isakmp";
#ifdef HAVE_LIBCRYPTO
/* initialize SAs */
if (ndo->ndo_sa_list_head == NULL) {
if (ndo->ndo_espsecret)
esp_decodesecret_print(ndo);
}
#endif
p = (const struct isakmp *)bp;
ep = ndo->ndo_snapend;
if ((const struct isakmp *)ep < p + 1) {
nd_print_trunc(ndo);
return;
}
ND_PRINT("isakmp");
major = (GET_U_1(p->vers) & ISAKMP_VERS_MAJOR)
>> ISAKMP_VERS_MAJOR_SHIFT;
minor = (GET_U_1(p->vers) & ISAKMP_VERS_MINOR)
>> ISAKMP_VERS_MINOR_SHIFT;
if (ndo->ndo_vflag) {
ND_PRINT(" %u.%u", major, minor);
}
if (ndo->ndo_vflag) {
ND_PRINT(" msgid ");
hexprint(ndo, p->msgid, sizeof(p->msgid));
}
if (1 < ndo->ndo_vflag) {
ND_PRINT(" cookie ");
hexprint(ndo, p->i_ck, sizeof(p->i_ck));
ND_PRINT("->");
hexprint(ndo, p->r_ck, sizeof(p->r_ck));
}
ND_PRINT(":");
switch(major) {
case IKEv1_MAJOR_VERSION:
ikev1_print(ndo, bp, length, bp2, p);
break;
case IKEv2_MAJOR_VERSION:
ikev2_print(ndo, bp, length, bp2, p);
break;
}
}
void
isakmp_rfc3948_print(netdissect_options *ndo,
const u_char *bp, u_int length,
const u_char *bp2, int ver, int fragmented, u_int ttl_hl)
{
ndo->ndo_protocol = "isakmp_rfc3948";
if(length == 1 && GET_U_1(bp)==0xff) {
ND_PRINT("isakmp-nat-keep-alive");
return;
}
if(length < 4) {
goto trunc;
}
/*
* see if this is an IKE packet
*/
if (GET_BE_U_4(bp) == 0) {
ND_PRINT("NONESP-encap: ");
isakmp_print(ndo, bp+4, length-4, bp2);
return;
}
/* must be an ESP packet */
{
ND_PRINT("UDP-encap: ");
esp_print(ndo, bp, length, bp2, ver, fragmented, ttl_hl);
/*
* Either this has decrypted the payload and
* printed it, in which case there's nothing more
* to do, or it hasn't, in which case there's
* nothing more to do.
*/
return;
}
trunc:
nd_print_trunc(ndo);
}
diff --git a/contrib/tcpdump/print-isoclns.c b/contrib/tcpdump/print-isoclns.c
index ddd559532abd..5b8c2c2db80f 100644
--- a/contrib/tcpdump/print-isoclns.c
+++ b/contrib/tcpdump/print-isoclns.c
@@ -1,3561 +1,3553 @@
/*
* Copyright (c) 1992, 1993, 1994, 1995, 1996
* 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.
*
* Original code by Matt Thomas, Digital Equipment Corporation
*
* Extensively modified by Hannes Gredler (hannes@gredler.at) for more
* complete IS-IS & CLNP support.
*/
/* \summary: ISO CLNS, ESIS, and ISIS printer */
/*
* specification:
*
* CLNP: ISO 8473 (respective ITU version is at https://www.itu.int/rec/T-REC-X.233/en/)
* ES-IS: ISO 9542
* IS-IS: ISO 10589
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <string.h>
#include "netdissect.h"
#include "addrtoname.h"
#include "nlpid.h"
#include "extract.h"
#include "gmpls.h"
#include "oui.h"
#include "signature.h"
/*
* IS-IS is defined in ISO 10589. Look there for protocol definitions.
*/
#define SYSTEM_ID_LEN MAC_ADDR_LEN
#define NODE_ID_LEN (SYSTEM_ID_LEN+1)
#define LSP_ID_LEN (SYSTEM_ID_LEN+2)
#define ISIS_VERSION 1
#define ESIS_VERSION 1
#define CLNP_VERSION 1
#define ISIS_PDU_TYPE_MASK 0x1F
#define ESIS_PDU_TYPE_MASK 0x1F
#define CLNP_PDU_TYPE_MASK 0x1F
#define CLNP_FLAG_MASK 0xE0
#define ISIS_LAN_PRIORITY_MASK 0x7F
#define ISIS_PDU_L1_LAN_IIH 15
#define ISIS_PDU_L2_LAN_IIH 16
#define ISIS_PDU_PTP_IIH 17
#define ISIS_PDU_L1_LSP 18
#define ISIS_PDU_L2_LSP 20
#define ISIS_PDU_L1_CSNP 24
#define ISIS_PDU_L2_CSNP 25
#define ISIS_PDU_L1_PSNP 26
#define ISIS_PDU_L2_PSNP 27
static const struct tok isis_pdu_values[] = {
{ ISIS_PDU_L1_LAN_IIH, "L1 Lan IIH"},
{ ISIS_PDU_L2_LAN_IIH, "L2 Lan IIH"},
{ ISIS_PDU_PTP_IIH, "p2p IIH"},
{ ISIS_PDU_L1_LSP, "L1 LSP"},
{ ISIS_PDU_L2_LSP, "L2 LSP"},
{ ISIS_PDU_L1_CSNP, "L1 CSNP"},
{ ISIS_PDU_L2_CSNP, "L2 CSNP"},
{ ISIS_PDU_L1_PSNP, "L1 PSNP"},
{ ISIS_PDU_L2_PSNP, "L2 PSNP"},
{ 0, NULL}
};
/*
* A TLV is a tuple of a type, length and a value and is normally used for
* encoding information in all sorts of places. This is an enumeration of
* the well known types.
*
* list taken from rfc3359 plus some memory from veterans ;-)
*/
#define ISIS_TLV_AREA_ADDR 1 /* iso10589 */
#define ISIS_TLV_IS_REACH 2 /* iso10589 */
#define ISIS_TLV_ESNEIGH 3 /* iso10589 */
#define ISIS_TLV_PART_DIS 4 /* iso10589 */
#define ISIS_TLV_PREFIX_NEIGH 5 /* iso10589 */
#define ISIS_TLV_ISNEIGH 6 /* iso10589 */
#define ISIS_TLV_INSTANCE_ID 7 /* rfc8202 */
#define ISIS_TLV_PADDING 8 /* iso10589 */
#define ISIS_TLV_LSP 9 /* iso10589 */
#define ISIS_TLV_AUTH 10 /* iso10589, rfc3567 */
#define ISIS_TLV_CHECKSUM 12 /* rfc3358 */
#define ISIS_TLV_CHECKSUM_MINLEN 2
#define ISIS_TLV_POI 13 /* rfc6232 */
#define ISIS_TLV_LSP_BUFFERSIZE 14 /* iso10589 rev2 */
#define ISIS_TLV_EXT_IS_REACH 22 /* rfc5305 */
#define ISIS_TLV_IS_ALIAS_ID 24 /* rfc5311 */
#define ISIS_TLV_DECNET_PHASE4 42
#define ISIS_TLV_LUCENT_PRIVATE 66
#define ISIS_TLV_INT_IP_REACH 128 /* rfc1195, rfc2966 */
#define ISIS_TLV_PROTOCOLS 129 /* rfc1195 */
#define ISIS_TLV_EXT_IP_REACH 130 /* rfc1195, rfc2966 */
#define ISIS_TLV_IDRP_INFO 131 /* rfc1195 */
#define ISIS_TLV_IPADDR 132 /* rfc1195 */
#define ISIS_TLV_IPAUTH 133 /* rfc1195 */
#define ISIS_TLV_TE_ROUTER_ID 134 /* rfc5305 */
#define ISIS_TLV_EXTD_IP_REACH 135 /* rfc5305 */
#define ISIS_TLV_HOSTNAME 137 /* rfc2763 */
#define ISIS_TLV_SHARED_RISK_GROUP 138 /* draft-ietf-isis-gmpls-extensions */
#define ISIS_TLV_MT_PORT_CAP 143 /* rfc6165 */
#define ISIS_TLV_MT_CAPABILITY 144 /* rfc6329 */
#define ISIS_TLV_NORTEL_PRIVATE1 176
#define ISIS_TLV_NORTEL_PRIVATE2 177
#define ISIS_TLV_RESTART_SIGNALING 211 /* rfc3847 */
#define ISIS_TLV_RESTART_SIGNALING_FLAGLEN 1
#define ISIS_TLV_RESTART_SIGNALING_HOLDTIMELEN 2
#define ISIS_TLV_MT_IS_REACH 222 /* draft-ietf-isis-wg-multi-topology-05 */
#define ISIS_TLV_MT_SUPPORTED 229 /* draft-ietf-isis-wg-multi-topology-05 */
#define ISIS_TLV_IP6ADDR 232 /* draft-ietf-isis-ipv6-02 */
#define ISIS_TLV_MT_IP_REACH 235 /* draft-ietf-isis-wg-multi-topology-05 */
#define ISIS_TLV_IP6_REACH 236 /* draft-ietf-isis-ipv6-02 */
#define ISIS_TLV_MT_IP6_REACH 237 /* draft-ietf-isis-wg-multi-topology-05 */
#define ISIS_TLV_PTP_ADJ 240 /* rfc3373 */
#define ISIS_TLV_IIH_SEQNR 241 /* draft-shen-isis-iih-sequence-00 */
#define ISIS_TLV_ROUTER_CAPABILITY 242 /* rfc7981 */
#define ISIS_TLV_VENDOR_PRIVATE 250 /* draft-ietf-isis-experimental-tlv-01 */
#define ISIS_TLV_VENDOR_PRIVATE_MINLEN 3
static const struct tok isis_tlv_values[] = {
{ ISIS_TLV_AREA_ADDR, "Area address(es)"},
{ ISIS_TLV_IS_REACH, "IS Reachability"},
{ ISIS_TLV_ESNEIGH, "ES Neighbor(s)"},
{ ISIS_TLV_PART_DIS, "Partition DIS"},
{ ISIS_TLV_PREFIX_NEIGH, "Prefix Neighbors"},
{ ISIS_TLV_ISNEIGH, "IS Neighbor(s)"},
{ ISIS_TLV_INSTANCE_ID, "Instance Identifier"},
{ ISIS_TLV_PADDING, "Padding"},
{ ISIS_TLV_LSP, "LSP entries"},
{ ISIS_TLV_AUTH, "Authentication"},
{ ISIS_TLV_CHECKSUM, "Checksum"},
{ ISIS_TLV_POI, "Purge Originator Identifier"},
{ ISIS_TLV_LSP_BUFFERSIZE, "LSP Buffersize"},
{ ISIS_TLV_EXT_IS_REACH, "Extended IS Reachability"},
{ ISIS_TLV_IS_ALIAS_ID, "IS Alias ID"},
{ ISIS_TLV_DECNET_PHASE4, "DECnet Phase IV"},
{ ISIS_TLV_LUCENT_PRIVATE, "Lucent Proprietary"},
{ ISIS_TLV_INT_IP_REACH, "IPv4 Internal Reachability"},
{ ISIS_TLV_PROTOCOLS, "Protocols supported"},
{ ISIS_TLV_EXT_IP_REACH, "IPv4 External Reachability"},
{ ISIS_TLV_IDRP_INFO, "Inter-Domain Information Type"},
{ ISIS_TLV_IPADDR, "IPv4 Interface address(es)"},
{ ISIS_TLV_IPAUTH, "IPv4 authentication (deprecated)"},
{ ISIS_TLV_TE_ROUTER_ID, "Traffic Engineering Router ID"},
{ ISIS_TLV_EXTD_IP_REACH, "Extended IPv4 Reachability"},
{ ISIS_TLV_SHARED_RISK_GROUP, "Shared Risk Link Group"},
{ ISIS_TLV_MT_PORT_CAP, "Multi-Topology-Aware Port Capability"},
{ ISIS_TLV_MT_CAPABILITY, "Multi-Topology Capability"},
{ ISIS_TLV_NORTEL_PRIVATE1, "Nortel Proprietary"},
{ ISIS_TLV_NORTEL_PRIVATE2, "Nortel Proprietary"},
{ ISIS_TLV_HOSTNAME, "Hostname"},
{ ISIS_TLV_RESTART_SIGNALING, "Restart Signaling"},
{ ISIS_TLV_MT_IS_REACH, "Multi Topology IS Reachability"},
{ ISIS_TLV_MT_SUPPORTED, "Multi Topology"},
{ ISIS_TLV_IP6ADDR, "IPv6 Interface address(es)"},
{ ISIS_TLV_MT_IP_REACH, "Multi-Topology IPv4 Reachability"},
{ ISIS_TLV_IP6_REACH, "IPv6 reachability"},
{ ISIS_TLV_MT_IP6_REACH, "Multi-Topology IP6 Reachability"},
{ ISIS_TLV_PTP_ADJ, "Point-to-point Adjacency State"},
{ ISIS_TLV_IIH_SEQNR, "Hello PDU Sequence Number"},
{ ISIS_TLV_ROUTER_CAPABILITY, "IS-IS Router Capability"},
{ ISIS_TLV_VENDOR_PRIVATE, "Vendor Private"},
{ 0, NULL }
};
#define ESIS_OPTION_PROTOCOLS 129
#define ESIS_OPTION_QOS_MAINTENANCE 195 /* iso9542 */
#define ESIS_OPTION_SECURITY 197 /* iso9542 */
#define ESIS_OPTION_ES_CONF_TIME 198 /* iso9542 */
#define ESIS_OPTION_PRIORITY 205 /* iso9542 */
#define ESIS_OPTION_ADDRESS_MASK 225 /* iso9542 */
#define ESIS_OPTION_SNPA_MASK 226 /* iso9542 */
static const struct tok esis_option_values[] = {
{ ESIS_OPTION_PROTOCOLS, "Protocols supported"},
{ ESIS_OPTION_QOS_MAINTENANCE, "QoS Maintenance" },
{ ESIS_OPTION_SECURITY, "Security" },
{ ESIS_OPTION_ES_CONF_TIME, "ES Configuration Time" },
{ ESIS_OPTION_PRIORITY, "Priority" },
- { ESIS_OPTION_ADDRESS_MASK, "Addressk Mask" },
+ { ESIS_OPTION_ADDRESS_MASK, "Address Mask" },
{ ESIS_OPTION_SNPA_MASK, "SNPA Mask" },
{ 0, NULL }
};
#define CLNP_OPTION_DISCARD_REASON 193
#define CLNP_OPTION_QOS_MAINTENANCE 195 /* iso8473 */
#define CLNP_OPTION_SECURITY 197 /* iso8473 */
#define CLNP_OPTION_SOURCE_ROUTING 200 /* iso8473 */
#define CLNP_OPTION_ROUTE_RECORDING 203 /* iso8473 */
#define CLNP_OPTION_PADDING 204 /* iso8473 */
#define CLNP_OPTION_PRIORITY 205 /* iso8473 */
static const struct tok clnp_option_values[] = {
{ CLNP_OPTION_DISCARD_REASON, "Discard Reason"},
{ CLNP_OPTION_PRIORITY, "Priority"},
{ CLNP_OPTION_QOS_MAINTENANCE, "QoS Maintenance"},
{ CLNP_OPTION_SECURITY, "Security"},
{ CLNP_OPTION_SOURCE_ROUTING, "Source Routing"},
{ CLNP_OPTION_ROUTE_RECORDING, "Route Recording"},
{ CLNP_OPTION_PADDING, "Padding"},
{ 0, NULL }
};
static const struct tok clnp_option_rfd_class_values[] = {
{ 0x0, "General"},
{ 0x8, "Address"},
{ 0x9, "Source Routeing"},
{ 0xa, "Lifetime"},
{ 0xb, "PDU Discarded"},
{ 0xc, "Reassembly"},
{ 0, NULL }
};
static const struct tok clnp_option_rfd_general_values[] = {
{ 0x0, "Reason not specified"},
{ 0x1, "Protocol procedure error"},
{ 0x2, "Incorrect checksum"},
{ 0x3, "PDU discarded due to congestion"},
{ 0x4, "Header syntax error (cannot be parsed)"},
{ 0x5, "Segmentation needed but not permitted"},
{ 0x6, "Incomplete PDU received"},
{ 0x7, "Duplicate option"},
{ 0, NULL }
};
static const struct tok clnp_option_rfd_address_values[] = {
{ 0x0, "Destination address unreachable"},
{ 0x1, "Destination address unknown"},
{ 0, NULL }
};
static const struct tok clnp_option_rfd_source_routeing_values[] = {
{ 0x0, "Unspecified source routeing error"},
{ 0x1, "Syntax error in source routeing field"},
{ 0x2, "Unknown address in source routeing field"},
{ 0x3, "Path not acceptable"},
{ 0, NULL }
};
static const struct tok clnp_option_rfd_lifetime_values[] = {
{ 0x0, "Lifetime expired while data unit in transit"},
{ 0x1, "Lifetime expired during reassembly"},
{ 0, NULL }
};
static const struct tok clnp_option_rfd_pdu_discard_values[] = {
{ 0x0, "Unsupported option not specified"},
{ 0x1, "Unsupported protocol version"},
{ 0x2, "Unsupported security option"},
{ 0x3, "Unsupported source routeing option"},
{ 0x4, "Unsupported recording of route option"},
{ 0, NULL }
};
static const struct tok clnp_option_rfd_reassembly_values[] = {
{ 0x0, "Reassembly interference"},
{ 0, NULL }
};
/* array of 16 error-classes */
static const struct tok *clnp_option_rfd_error_class[] = {
clnp_option_rfd_general_values,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
clnp_option_rfd_address_values,
clnp_option_rfd_source_routeing_values,
clnp_option_rfd_lifetime_values,
clnp_option_rfd_pdu_discard_values,
clnp_option_rfd_reassembly_values,
NULL,
NULL,
NULL
};
#define CLNP_OPTION_OPTION_QOS_MASK 0x3f
#define CLNP_OPTION_SCOPE_MASK 0xc0
#define CLNP_OPTION_SCOPE_SA_SPEC 0x40
#define CLNP_OPTION_SCOPE_DA_SPEC 0x80
#define CLNP_OPTION_SCOPE_GLOBAL 0xc0
static const struct tok clnp_option_scope_values[] = {
{ CLNP_OPTION_SCOPE_SA_SPEC, "Source Address Specific"},
{ CLNP_OPTION_SCOPE_DA_SPEC, "Destination Address Specific"},
{ CLNP_OPTION_SCOPE_GLOBAL, "Globally unique"},
{ 0, NULL }
};
static const struct tok clnp_option_sr_rr_values[] = {
{ 0x0, "partial"},
{ 0x1, "complete"},
{ 0, NULL }
};
static const struct tok clnp_option_sr_rr_string_values[] = {
{ CLNP_OPTION_SOURCE_ROUTING, "source routing"},
{ CLNP_OPTION_ROUTE_RECORDING, "recording of route in progress"},
{ 0, NULL }
};
static const struct tok clnp_option_qos_global_values[] = {
{ 0x20, "reserved"},
{ 0x10, "sequencing vs. delay"},
{ 0x08, "congested"},
{ 0x04, "delay vs. cost"},
{ 0x02, "error vs. delay"},
{ 0x01, "error vs. cost"},
{ 0, NULL }
};
static const struct tok isis_tlv_router_capability_flags[] = {
{ 0x01, "S bit"},
{ 0x02, "D bit"},
{ 0, NULL }
};
#define ISIS_SUBTLV_ROUTER_CAP_SR 2 /* rfc 8667 */
static const struct tok isis_router_capability_subtlv_values[] = {
{ ISIS_SUBTLV_ROUTER_CAP_SR, "SR-Capabilities"},
{ 0, NULL }
};
static const struct tok isis_router_capability_sr_flags[] = {
{ 0x80, "ipv4"},
{ 0x40, "ipv6"},
{ 0, NULL }
};
#define ISIS_SUBTLV_EXT_IS_REACH_ADMIN_GROUP 3 /* rfc5305 */
#define ISIS_SUBTLV_EXT_IS_REACH_LINK_LOCAL_REMOTE_ID 4 /* rfc4205 */
#define ISIS_SUBTLV_EXT_IS_REACH_LINK_REMOTE_ID 5 /* rfc5305 */
#define ISIS_SUBTLV_EXT_IS_REACH_IPV4_INTF_ADDR 6 /* rfc5305 */
#define ISIS_SUBTLV_EXT_IS_REACH_IPV4_NEIGHBOR_ADDR 8 /* rfc5305 */
#define ISIS_SUBTLV_EXT_IS_REACH_MAX_LINK_BW 9 /* rfc5305 */
#define ISIS_SUBTLV_EXT_IS_REACH_RESERVABLE_BW 10 /* rfc5305 */
#define ISIS_SUBTLV_EXT_IS_REACH_UNRESERVED_BW 11 /* rfc4124 */
#define ISIS_SUBTLV_EXT_IS_REACH_BW_CONSTRAINTS_OLD 12 /* draft-ietf-tewg-diff-te-proto-06 */
#define ISIS_SUBTLV_EXT_IS_REACH_TE_METRIC 18 /* rfc5305 */
#define ISIS_SUBTLV_EXT_IS_REACH_LINK_ATTRIBUTE 19 /* draft-ietf-isis-link-attr-01 */
#define ISIS_SUBTLV_EXT_IS_REACH_LINK_PROTECTION_TYPE 20 /* rfc4205 */
#define ISIS_SUBTLV_EXT_IS_REACH_INTF_SW_CAP_DESCR 21 /* rfc4205 */
#define ISIS_SUBTLV_EXT_IS_REACH_BW_CONSTRAINTS 22 /* rfc4124 */
#define ISIS_SUBTLV_EXT_IS_REACH_LAN_ADJ_SEGMENT_ID 32 /* rfc8667 */
#define ISIS_SUBTLV_SPB_METRIC 29 /* rfc6329 */
static const struct tok isis_ext_is_reach_subtlv_values[] = {
{ ISIS_SUBTLV_EXT_IS_REACH_ADMIN_GROUP, "Administrative groups" },
{ ISIS_SUBTLV_EXT_IS_REACH_LINK_LOCAL_REMOTE_ID, "Link Local/Remote Identifier" },
{ ISIS_SUBTLV_EXT_IS_REACH_LINK_REMOTE_ID, "Link Remote Identifier" },
{ ISIS_SUBTLV_EXT_IS_REACH_IPV4_INTF_ADDR, "IPv4 interface address" },
{ ISIS_SUBTLV_EXT_IS_REACH_IPV4_NEIGHBOR_ADDR, "IPv4 neighbor address" },
{ ISIS_SUBTLV_EXT_IS_REACH_MAX_LINK_BW, "Maximum link bandwidth" },
{ ISIS_SUBTLV_EXT_IS_REACH_RESERVABLE_BW, "Reservable link bandwidth" },
{ ISIS_SUBTLV_EXT_IS_REACH_UNRESERVED_BW, "Unreserved bandwidth" },
{ ISIS_SUBTLV_EXT_IS_REACH_TE_METRIC, "Traffic Engineering Metric" },
{ ISIS_SUBTLV_EXT_IS_REACH_LINK_ATTRIBUTE, "Link Attribute" },
{ ISIS_SUBTLV_EXT_IS_REACH_LINK_PROTECTION_TYPE, "Link Protection Type" },
{ ISIS_SUBTLV_EXT_IS_REACH_INTF_SW_CAP_DESCR, "Interface Switching Capability" },
{ ISIS_SUBTLV_EXT_IS_REACH_BW_CONSTRAINTS_OLD, "Bandwidth Constraints (old)" },
{ ISIS_SUBTLV_EXT_IS_REACH_BW_CONSTRAINTS, "Bandwidth Constraints" },
{ ISIS_SUBTLV_EXT_IS_REACH_LAN_ADJ_SEGMENT_ID, "LAN Adjacency Segment Identifier" },
{ ISIS_SUBTLV_SPB_METRIC, "SPB Metric" },
{ 250, "Reserved for cisco specific extensions" },
{ 251, "Reserved for cisco specific extensions" },
{ 252, "Reserved for cisco specific extensions" },
{ 253, "Reserved for cisco specific extensions" },
{ 254, "Reserved for cisco specific extensions" },
{ 255, "Reserved for future expansion" },
{ 0, NULL }
};
#define ISIS_SUBTLV_EXTD_IP_REACH_ADMIN_TAG32 1 /* draft-ietf-isis-admin-tags-01 */
#define ISIS_SUBTLV_EXTD_IP_REACH_ADMIN_TAG64 2 /* draft-ietf-isis-admin-tags-01 */
#define ISIS_SUBTLV_EXTD_IP_REACH_PREFIX_SID 3 /* rfc8667 */
#define ISIS_SUBTLV_EXTD_IP_REACH_MGMT_PREFIX_COLOR 117 /* draft-ietf-isis-wg-multi-topology-05 */
static const struct tok isis_ext_ip_reach_subtlv_values[] = {
{ ISIS_SUBTLV_EXTD_IP_REACH_ADMIN_TAG32, "32-Bit Administrative tag" },
{ ISIS_SUBTLV_EXTD_IP_REACH_ADMIN_TAG64, "64-Bit Administrative tag" },
{ ISIS_SUBTLV_EXTD_IP_REACH_PREFIX_SID, "Prefix SID" },
{ ISIS_SUBTLV_EXTD_IP_REACH_MGMT_PREFIX_COLOR, "Management Prefix Color" },
{ 0, NULL }
};
#define ISIS_PREFIX_SID_FLAG_R 0x80 /* rfc 8667 */
#define ISIS_PREFIX_SID_FLAG_N 0x40 /* rfc 8667 */
#define ISIS_PREFIX_SID_FLAG_P 0x20 /* rfc 8667 */
#define ISIS_PREFIX_SID_FLAG_E 0x10 /* rfc 8667 */
#define ISIS_PREFIX_SID_FLAG_V 0x08 /* rfc 8667 */
#define ISIS_PREFIX_SID_FLAG_L 0x04 /* rfc 8667 */
static const struct tok prefix_sid_flag_values[] = {
{ ISIS_PREFIX_SID_FLAG_R, "Readvertisement"},
{ ISIS_PREFIX_SID_FLAG_N, "Node"},
{ ISIS_PREFIX_SID_FLAG_P, "No-PHP"},
{ ISIS_PREFIX_SID_FLAG_E, "Explicit NULL"},
{ ISIS_PREFIX_SID_FLAG_V, "Value"},
{ ISIS_PREFIX_SID_FLAG_L, "Local"},
{ 0, NULL}
};
/* rfc 8667 */
static const struct tok prefix_sid_algo_values[] = {
{ 0, "SPF"},
{ 1, "strict-SPF"},
{ 0, NULL}
};
static const struct tok isis_subtlv_link_attribute_values[] = {
{ 0x01, "Local Protection Available" },
{ 0x02, "Link excluded from local protection path" },
{ 0x04, "Local maintenance required"},
{ 0, NULL }
};
static const struct tok isis_lan_adj_sid_flag_values[] = {
{ 0x80, "Address family IPv6" },
{ 0x40, "Backup" },
{ 0x20, "Value" },
{ 0x10, "Local significance" },
{ 0x08, "Set of adjacencies" },
{ 0x04, "Persistent" },
{ 0, NULL }
};
#define ISIS_SUBTLV_AUTH_SIMPLE 1
#define ISIS_SUBTLV_AUTH_GENERIC 3 /* rfc 5310 */
#define ISIS_SUBTLV_AUTH_MD5 54
#define ISIS_SUBTLV_AUTH_MD5_LEN 16
#define ISIS_SUBTLV_AUTH_PRIVATE 255
static const struct tok isis_subtlv_auth_values[] = {
{ ISIS_SUBTLV_AUTH_SIMPLE, "simple text password"},
{ ISIS_SUBTLV_AUTH_GENERIC, "Generic Crypto key-id"},
{ ISIS_SUBTLV_AUTH_MD5, "HMAC-MD5 password"},
{ ISIS_SUBTLV_AUTH_PRIVATE, "Routing Domain private password"},
{ 0, NULL }
};
#define ISIS_SUBTLV_IDRP_RES 0
#define ISIS_SUBTLV_IDRP_LOCAL 1
#define ISIS_SUBTLV_IDRP_ASN 2
static const struct tok isis_subtlv_idrp_values[] = {
{ ISIS_SUBTLV_IDRP_RES, "Reserved"},
{ ISIS_SUBTLV_IDRP_LOCAL, "Routing-Domain Specific"},
{ ISIS_SUBTLV_IDRP_ASN, "AS Number Tag"},
{ 0, NULL}
};
#define ISIS_SUBTLV_SPB_MCID 4
#define ISIS_SUBTLV_SPB_DIGEST 5
#define ISIS_SUBTLV_SPB_BVID 6
#define ISIS_SUBTLV_SPB_INSTANCE 1
#define ISIS_SUBTLV_SPBM_SI 3
#define ISIS_SPB_MCID_LEN 51
#define ISIS_SUBTLV_SPB_MCID_MIN_LEN 102
#define ISIS_SUBTLV_SPB_DIGEST_MIN_LEN 33
#define ISIS_SUBTLV_SPB_BVID_MIN_LEN 6
#define ISIS_SUBTLV_SPB_INSTANCE_MIN_LEN 19
#define ISIS_SUBTLV_SPB_INSTANCE_VLAN_TUPLE_LEN 8
static const struct tok isis_mt_port_cap_subtlv_values[] = {
{ ISIS_SUBTLV_SPB_MCID, "SPB MCID" },
{ ISIS_SUBTLV_SPB_DIGEST, "SPB Digest" },
{ ISIS_SUBTLV_SPB_BVID, "SPB BVID" },
{ 0, NULL }
};
static const struct tok isis_mt_capability_subtlv_values[] = {
{ ISIS_SUBTLV_SPB_INSTANCE, "SPB Instance" },
{ ISIS_SUBTLV_SPBM_SI, "SPBM Service Identifier and Unicast Address" },
{ 0, NULL }
};
struct isis_spb_mcid {
nd_uint8_t format_id;
nd_byte name[32];
nd_uint16_t revision_lvl;
nd_byte digest[16];
};
struct isis_subtlv_spb_mcid {
struct isis_spb_mcid mcid;
struct isis_spb_mcid aux_mcid;
};
struct isis_subtlv_spb_instance {
nd_byte cist_root_id[8];
nd_uint32_t cist_external_root_path_cost;
nd_uint16_t bridge_priority;
nd_uint32_t spsourceid;
nd_uint8_t no_of_trees;
};
#define CLNP_SEGMENT_PART 0x80
#define CLNP_MORE_SEGMENTS 0x40
#define CLNP_REQUEST_ER 0x20
static const struct tok clnp_flag_values[] = {
{ CLNP_SEGMENT_PART, "Segmentation permitted"},
{ CLNP_MORE_SEGMENTS, "more Segments"},
{ CLNP_REQUEST_ER, "request Error Report"},
{ 0, NULL}
};
#define ISIS_MASK_LSP_OL_BIT(x) (GET_U_1(x)&0x4)
#define ISIS_MASK_LSP_ISTYPE_BITS(x) (GET_U_1(x)&0x3)
#define ISIS_MASK_LSP_PARTITION_BIT(x) (GET_U_1(x)&0x80)
#define ISIS_MASK_LSP_ATT_BITS(x) (GET_U_1(x)&0x78)
#define ISIS_MASK_LSP_ATT_ERROR_BIT(x) (GET_U_1(x)&0x40)
#define ISIS_MASK_LSP_ATT_EXPENSE_BIT(x) (GET_U_1(x)&0x20)
#define ISIS_MASK_LSP_ATT_DELAY_BIT(x) (GET_U_1(x)&0x10)
#define ISIS_MASK_LSP_ATT_DEFAULT_BIT(x) (GET_U_1(x)&0x8)
#define ISIS_MASK_MTID(x) ((x)&0x0fff)
#define ISIS_MASK_MTFLAGS(x) ((x)&0xf000)
static const struct tok isis_mt_flag_values[] = {
{ 0x4000, "ATT bit set"},
{ 0x8000, "Overload bit set"},
{ 0, NULL}
};
#define ISIS_MASK_TLV_EXTD_IP_UPDOWN(x) ((x)&0x80)
#define ISIS_MASK_TLV_EXTD_IP_SUBTLV(x) ((x)&0x40)
#define ISIS_MASK_TLV_EXTD_IP6_IE(x) ((x)&0x40)
#define ISIS_MASK_TLV_EXTD_IP6_SUBTLV(x) ((x)&0x20)
#define ISIS_LSP_TLV_METRIC_SUPPORTED(x) (GET_U_1(x)&0x80)
#define ISIS_LSP_TLV_METRIC_IE(x) (GET_U_1(x)&0x40)
#define ISIS_LSP_TLV_METRIC_UPDOWN(x) (GET_U_1(x)&0x80)
#define ISIS_LSP_TLV_METRIC_VALUE(x) (GET_U_1(x)&0x3f)
#define ISIS_MASK_TLV_SHARED_RISK_GROUP(x) ((x)&0x1)
static const struct tok isis_mt_values[] = {
{ 0, "IPv4 unicast"},
{ 1, "In-Band Management"},
{ 2, "IPv6 unicast"},
{ 3, "Multicast"},
{ 4095, "Development, Experimental or Proprietary"},
{ 0, NULL }
};
static const struct tok isis_iih_circuit_type_values[] = {
{ 1, "Level 1 only"},
{ 2, "Level 2 only"},
{ 3, "Level 1, Level 2"},
{ 0, NULL}
};
#define ISIS_LSP_TYPE_UNUSED0 0
#define ISIS_LSP_TYPE_LEVEL_1 1
#define ISIS_LSP_TYPE_UNUSED2 2
#define ISIS_LSP_TYPE_LEVEL_2 3
static const struct tok isis_lsp_istype_values[] = {
{ ISIS_LSP_TYPE_UNUSED0, "Unused 0x0 (invalid)"},
{ ISIS_LSP_TYPE_LEVEL_1, "L1 IS"},
{ ISIS_LSP_TYPE_UNUSED2, "Unused 0x2 (invalid)"},
{ ISIS_LSP_TYPE_LEVEL_2, "L2 IS"},
{ 0, NULL }
};
/*
* Katz's point to point adjacency TLV uses codes to tell us the state of
* the remote adjacency. Enumerate them.
*/
#define ISIS_PTP_ADJ_UP 0
#define ISIS_PTP_ADJ_INIT 1
#define ISIS_PTP_ADJ_DOWN 2
-static const struct tok isis_ptp_adjancey_values[] = {
+static const struct tok isis_ptp_adjacency_values[] = {
{ ISIS_PTP_ADJ_UP, "Up" },
{ ISIS_PTP_ADJ_INIT, "Initializing" },
{ ISIS_PTP_ADJ_DOWN, "Down" },
{ 0, NULL}
};
struct isis_tlv_ptp_adj {
nd_uint8_t adjacency_state;
nd_uint32_t extd_local_circuit_id;
nd_byte neighbor_sysid[SYSTEM_ID_LEN];
nd_uint32_t neighbor_extd_local_circuit_id;
};
static void osi_print_cksum(netdissect_options *, const uint8_t *pptr,
uint16_t checksum, int checksum_offset, u_int length);
static int clnp_print(netdissect_options *, const uint8_t *, u_int);
static void esis_print(netdissect_options *, const uint8_t *, u_int);
static int isis_print(netdissect_options *, const uint8_t *, u_int);
struct isis_metric_block {
nd_uint8_t metric_default;
nd_uint8_t metric_delay;
nd_uint8_t metric_expense;
nd_uint8_t metric_error;
};
struct isis_tlv_is_reach {
struct isis_metric_block isis_metric_block;
nd_byte neighbor_nodeid[NODE_ID_LEN];
};
struct isis_tlv_es_reach {
struct isis_metric_block isis_metric_block;
nd_byte neighbor_sysid[SYSTEM_ID_LEN];
};
struct isis_tlv_ip_reach {
struct isis_metric_block isis_metric_block;
nd_ipv4 prefix;
nd_ipv4 mask;
};
static const struct tok isis_is_reach_virtual_values[] = {
{ 0, "IsNotVirtual"},
{ 1, "IsVirtual"},
{ 0, NULL }
};
static const struct tok isis_restart_flag_values[] = {
{ 0x1, "Restart Request"},
{ 0x2, "Restart Acknowledgement"},
{ 0x4, "Suppress adjacency advertisement"},
{ 0, NULL }
};
struct isis_common_header {
nd_uint8_t nlpid;
nd_uint8_t fixed_len;
nd_uint8_t version; /* Protocol version */
nd_uint8_t id_length;
nd_uint8_t pdu_type; /* 3 MSbits are reserved */
nd_uint8_t pdu_version; /* Packet format version */
nd_byte reserved;
nd_uint8_t max_area;
};
struct isis_iih_lan_header {
nd_uint8_t circuit_type;
nd_byte source_id[SYSTEM_ID_LEN];
nd_uint16_t holding_time;
nd_uint16_t pdu_len;
nd_uint8_t priority;
nd_byte lan_id[NODE_ID_LEN];
};
struct isis_iih_ptp_header {
nd_uint8_t circuit_type;
nd_byte source_id[SYSTEM_ID_LEN];
nd_uint16_t holding_time;
nd_uint16_t pdu_len;
nd_uint8_t circuit_id;
};
struct isis_lsp_header {
nd_uint16_t pdu_len;
nd_uint16_t remaining_lifetime;
nd_byte lsp_id[LSP_ID_LEN];
nd_uint32_t sequence_number;
nd_uint16_t checksum;
nd_uint8_t typeblock;
};
struct isis_csnp_header {
nd_uint16_t pdu_len;
nd_byte source_id[NODE_ID_LEN];
nd_byte start_lsp_id[LSP_ID_LEN];
nd_byte end_lsp_id[LSP_ID_LEN];
};
struct isis_psnp_header {
nd_uint16_t pdu_len;
nd_byte source_id[NODE_ID_LEN];
};
struct isis_tlv_lsp {
nd_uint16_t remaining_lifetime;
nd_byte lsp_id[LSP_ID_LEN];
nd_uint32_t sequence_number;
nd_uint16_t checksum;
};
#define ISIS_COMMON_HEADER_SIZE (sizeof(struct isis_common_header))
#define ISIS_IIH_LAN_HEADER_SIZE (sizeof(struct isis_iih_lan_header))
#define ISIS_IIH_PTP_HEADER_SIZE (sizeof(struct isis_iih_ptp_header))
#define ISIS_LSP_HEADER_SIZE (sizeof(struct isis_lsp_header))
#define ISIS_CSNP_HEADER_SIZE (sizeof(struct isis_csnp_header))
#define ISIS_PSNP_HEADER_SIZE (sizeof(struct isis_psnp_header))
void
isoclns_print(netdissect_options *ndo, const u_char *p, u_int length)
{
ndo->ndo_protocol = "isoclns";
if (ndo->ndo_eflag)
ND_PRINT("OSI NLPID %s (0x%02x): ",
tok2str(nlpid_values, "Unknown", GET_U_1(p)),
GET_U_1(p));
switch (GET_U_1(p)) {
case NLPID_CLNP:
if (!clnp_print(ndo, p, length))
print_unknown_data(ndo, p, "\n\t", length);
break;
case NLPID_ESIS:
esis_print(ndo, p, length);
return;
case NLPID_ISIS:
if (!isis_print(ndo, p, length))
print_unknown_data(ndo, p, "\n\t", length);
break;
case NLPID_NULLNS:
ND_PRINT("%slength: %u", ndo->ndo_eflag ? "" : ", ", length);
break;
case NLPID_Q933:
q933_print(ndo, p + 1, length - 1);
break;
case NLPID_IP:
ip_print(ndo, p + 1, length - 1);
break;
case NLPID_IP6:
ip6_print(ndo, p + 1, length - 1);
break;
case NLPID_PPP:
ppp_print(ndo, p + 1, length - 1);
break;
default:
if (!ndo->ndo_eflag)
ND_PRINT("OSI NLPID 0x%02x unknown", GET_U_1(p));
ND_PRINT("%slength: %u", ndo->ndo_eflag ? "" : ", ", length);
if (length > 1)
print_unknown_data(ndo, p, "\n\t", length);
break;
}
}
#define CLNP_PDU_ER 1
#define CLNP_PDU_DT 28
#define CLNP_PDU_MD 29
#define CLNP_PDU_ERQ 30
#define CLNP_PDU_ERP 31
static const struct tok clnp_pdu_values[] = {
{ CLNP_PDU_ER, "Error Report"},
{ CLNP_PDU_MD, "MD"},
{ CLNP_PDU_DT, "Data"},
{ CLNP_PDU_ERQ, "Echo Request"},
{ CLNP_PDU_ERP, "Echo Response"},
{ 0, NULL }
};
struct clnp_header_t {
nd_uint8_t nlpid;
nd_uint8_t length_indicator;
nd_uint8_t version;
nd_uint8_t lifetime; /* units of 500ms */
nd_uint8_t type;
nd_uint16_t segment_length;
nd_uint16_t cksum;
};
struct clnp_segment_header_t {
nd_uint16_t data_unit_id;
nd_uint16_t segment_offset;
nd_uint16_t total_length;
};
/*
* clnp_print
* Decode CLNP packets. Return 0 on error.
*/
static int
clnp_print(netdissect_options *ndo,
const uint8_t *pptr, u_int length)
{
const uint8_t *optr,*source_address,*dest_address;
u_int li,li_remaining,tlen,nsap_offset,source_address_length,dest_address_length, clnp_pdu_type, clnp_flags;
const struct clnp_header_t *clnp_header;
const struct clnp_segment_header_t *clnp_segment_header;
uint8_t rfd_error,rfd_error_major,rfd_error_minor;
ndo->ndo_protocol = "clnp";
clnp_header = (const struct clnp_header_t *) pptr;
ND_TCHECK_SIZE(clnp_header);
li = GET_U_1(clnp_header->length_indicator);
li_remaining = li;
optr = pptr;
if (!ndo->ndo_eflag)
nd_print_protocol_caps(ndo);
/*
* Sanity checking of the header.
*/
if (GET_U_1(clnp_header->version) != CLNP_VERSION) {
ND_PRINT("version %u packet not supported",
GET_U_1(clnp_header->version));
return (0);
}
if (li > length) {
ND_PRINT(" length indicator(%u) > PDU size (%u)!", li, length);
return (0);
}
if (li < sizeof(struct clnp_header_t)) {
ND_PRINT(" length indicator %u < min PDU size:", li);
while (pptr < ndo->ndo_snapend) {
ND_PRINT("%02X", GET_U_1(pptr));
pptr++;
}
return (0);
}
/* FIXME further header sanity checking */
clnp_pdu_type = GET_U_1(clnp_header->type) & CLNP_PDU_TYPE_MASK;
clnp_flags = GET_U_1(clnp_header->type) & CLNP_FLAG_MASK;
pptr += sizeof(struct clnp_header_t);
li_remaining -= sizeof(struct clnp_header_t);
if (li_remaining < 1) {
ND_PRINT("li < size of fixed part of CLNP header and addresses");
return (0);
}
dest_address_length = GET_U_1(pptr);
pptr += 1;
li_remaining -= 1;
if (li_remaining < dest_address_length) {
ND_PRINT("li < size of fixed part of CLNP header and addresses");
return (0);
}
ND_TCHECK_LEN(pptr, dest_address_length);
dest_address = pptr;
pptr += dest_address_length;
li_remaining -= dest_address_length;
if (li_remaining < 1) {
ND_PRINT("li < size of fixed part of CLNP header and addresses");
return (0);
}
source_address_length = GET_U_1(pptr);
pptr += 1;
li_remaining -= 1;
if (li_remaining < source_address_length) {
ND_PRINT("li < size of fixed part of CLNP header and addresses");
return (0);
}
ND_TCHECK_LEN(pptr, source_address_length);
source_address = pptr;
pptr += source_address_length;
li_remaining -= source_address_length;
if (ndo->ndo_vflag < 1) {
ND_PRINT("%s%s > %s, %s, length %u",
ndo->ndo_eflag ? "" : ", ",
GET_ISONSAP_STRING(source_address, source_address_length),
GET_ISONSAP_STRING(dest_address, dest_address_length),
tok2str(clnp_pdu_values,"unknown (%u)",clnp_pdu_type),
length);
return (1);
}
ND_PRINT("%slength %u", ndo->ndo_eflag ? "" : ", ", length);
ND_PRINT("\n\t%s PDU, hlen: %u, v: %u, lifetime: %u.%us, Segment PDU length: %u, checksum: 0x%04x",
tok2str(clnp_pdu_values, "unknown (%u)",clnp_pdu_type),
GET_U_1(clnp_header->length_indicator),
GET_U_1(clnp_header->version),
GET_U_1(clnp_header->lifetime)/2,
(GET_U_1(clnp_header->lifetime)%2)*5,
GET_BE_U_2(clnp_header->segment_length),
GET_BE_U_2(clnp_header->cksum));
osi_print_cksum(ndo, optr, GET_BE_U_2(clnp_header->cksum), 7,
GET_U_1(clnp_header->length_indicator));
ND_PRINT("\n\tFlags [%s]",
bittok2str(clnp_flag_values, "none", clnp_flags));
ND_PRINT("\n\tsource address (length %u): %s\n\tdest address (length %u): %s",
source_address_length,
GET_ISONSAP_STRING(source_address, source_address_length),
dest_address_length,
GET_ISONSAP_STRING(dest_address, dest_address_length));
if (clnp_flags & CLNP_SEGMENT_PART) {
if (li_remaining < sizeof(struct clnp_segment_header_t)) {
ND_PRINT("li < size of fixed part of CLNP header, addresses, and segment part");
return (0);
}
clnp_segment_header = (const struct clnp_segment_header_t *) pptr;
ND_TCHECK_SIZE(clnp_segment_header);
ND_PRINT("\n\tData Unit ID: 0x%04x, Segment Offset: %u, Total PDU Length: %u",
GET_BE_U_2(clnp_segment_header->data_unit_id),
GET_BE_U_2(clnp_segment_header->segment_offset),
GET_BE_U_2(clnp_segment_header->total_length));
pptr+=sizeof(struct clnp_segment_header_t);
li_remaining-=sizeof(struct clnp_segment_header_t);
}
/* now walk the options */
while (li_remaining != 0) {
u_int op, opli;
const uint8_t *tptr;
if (li_remaining < 2) {
ND_PRINT(", bad opts/li");
return (0);
}
op = GET_U_1(pptr);
opli = GET_U_1(pptr + 1);
pptr += 2;
li_remaining -= 2;
if (opli > li_remaining) {
ND_PRINT(", opt (%u) too long", op);
return (0);
}
ND_TCHECK_LEN(pptr, opli);
li_remaining -= opli;
tptr = pptr;
tlen = opli;
ND_PRINT("\n\t %s Option #%u, length %u, value: ",
tok2str(clnp_option_values,"Unknown",op),
op,
opli);
/*
* We've already checked that the entire option is present
* in the captured packet with the ND_TCHECK_LEN() call.
* Therefore, we don't need to do ND_TCHECK()/ND_TCHECK_LEN()
* checks.
* We do, however, need to check tlen, to make sure we
* don't run past the end of the option.
*/
switch (op) {
case CLNP_OPTION_ROUTE_RECORDING: /* those two options share the format */
case CLNP_OPTION_SOURCE_ROUTING:
if (tlen < 2) {
ND_PRINT(", bad opt len");
return (0);
}
ND_PRINT("%s %s",
tok2str(clnp_option_sr_rr_values,"Unknown",GET_U_1(tptr)),
tok2str(clnp_option_sr_rr_string_values, "Unknown Option %u", op));
nsap_offset=GET_U_1(tptr + 1);
if (nsap_offset == 0) {
ND_PRINT(" Bad NSAP offset (0)");
break;
}
nsap_offset-=1; /* offset to nsap list */
if (nsap_offset > tlen) {
ND_PRINT(" Bad NSAP offset (past end of option)");
break;
}
tptr+=nsap_offset;
tlen-=nsap_offset;
while (tlen > 0) {
source_address_length=GET_U_1(tptr);
if (tlen < source_address_length+1) {
ND_PRINT("\n\t NSAP address goes past end of option");
break;
}
if (source_address_length > 0) {
source_address=(tptr+1);
ND_PRINT("\n\t NSAP address (length %u): %s",
source_address_length,
GET_ISONSAP_STRING(source_address, source_address_length));
}
tlen-=source_address_length+1;
}
break;
case CLNP_OPTION_PRIORITY:
if (tlen < 1) {
ND_PRINT(", bad opt len");
return (0);
}
ND_PRINT("0x%1x", GET_U_1(tptr)&0x0f);
break;
case CLNP_OPTION_QOS_MAINTENANCE:
if (tlen < 1) {
ND_PRINT(", bad opt len");
return (0);
}
ND_PRINT("\n\t Format Code: %s",
tok2str(clnp_option_scope_values, "Reserved", GET_U_1(tptr) & CLNP_OPTION_SCOPE_MASK));
if ((GET_U_1(tptr)&CLNP_OPTION_SCOPE_MASK) == CLNP_OPTION_SCOPE_GLOBAL)
ND_PRINT("\n\t QoS Flags [%s]",
bittok2str(clnp_option_qos_global_values,
"none",
GET_U_1(tptr)&CLNP_OPTION_OPTION_QOS_MASK));
break;
case CLNP_OPTION_SECURITY:
if (tlen < 2) {
ND_PRINT(", bad opt len");
return (0);
}
ND_PRINT("\n\t Format Code: %s, Security-Level %u",
tok2str(clnp_option_scope_values,"Reserved",GET_U_1(tptr)&CLNP_OPTION_SCOPE_MASK),
GET_U_1(tptr + 1));
break;
case CLNP_OPTION_DISCARD_REASON:
if (tlen < 1) {
ND_PRINT(", bad opt len");
return (0);
}
rfd_error = GET_U_1(tptr);
rfd_error_major = (rfd_error&0xf0) >> 4;
rfd_error_minor = rfd_error&0x0f;
ND_PRINT("\n\t Class: %s Error (0x%01x), %s (0x%01x)",
tok2str(clnp_option_rfd_class_values,"Unknown",rfd_error_major),
rfd_error_major,
tok2str(clnp_option_rfd_error_class[rfd_error_major],"Unknown",rfd_error_minor),
rfd_error_minor);
break;
case CLNP_OPTION_PADDING:
ND_PRINT("padding data");
break;
/*
* FIXME those are the defined Options that lack a decoder
* you are welcome to contribute code ;-)
*/
default:
print_unknown_data(ndo, tptr, "\n\t ", opli);
break;
}
if (ndo->ndo_vflag > 1)
print_unknown_data(ndo, pptr, "\n\t ", opli);
pptr += opli;
}
switch (clnp_pdu_type) {
case CLNP_PDU_ER: /* fall through */
case CLNP_PDU_ERP:
if (GET_U_1(pptr) == NLPID_CLNP) {
ND_PRINT("\n\t-----original packet-----\n\t");
/* FIXME recursion protection */
clnp_print(ndo, pptr, length - li);
break;
}
/* The cases above break from the switch block if they see and print
* a CLNP header in the Data part. For an Error Report PDU this is
* described in Section 7.9.6 of ITU X.233 (1997 E), also known as
* ISO/IEC 8473-1:1998(E). It is not clear why in this code the same
* applies to an Echo Response PDU, as the standard does not specify
* the contents -- could be a proprietary extension or a bug. In either
* case, if the Data part does not contain a CLNP header, its structure
* is considered unknown and the decoding falls through to print the
* contents as-is.
*/
ND_FALL_THROUGH;
case CLNP_PDU_DT:
case CLNP_PDU_MD:
case CLNP_PDU_ERQ:
default:
/* dump the PDU specific data */
- if (length > ND_BYTES_BETWEEN(pptr, optr)) {
+ if (length > ND_BYTES_BETWEEN(optr, pptr)) {
ND_PRINT("\n\t undecoded non-header data, length %u", length-li);
- print_unknown_data(ndo, pptr, "\n\t ", length - ND_BYTES_BETWEEN(pptr, optr));
+ print_unknown_data(ndo, pptr, "\n\t ",
+ length - ND_BYTES_BETWEEN(optr, pptr));
}
}
return (1);
trunc:
nd_print_trunc(ndo);
return (1);
}
#define ESIS_PDU_REDIRECT 6
#define ESIS_PDU_ESH 2
#define ESIS_PDU_ISH 4
static const struct tok esis_pdu_values[] = {
{ ESIS_PDU_REDIRECT, "redirect"},
{ ESIS_PDU_ESH, "ESH"},
{ ESIS_PDU_ISH, "ISH"},
{ 0, NULL }
};
struct esis_header_t {
nd_uint8_t nlpid;
nd_uint8_t length_indicator;
nd_uint8_t version;
nd_byte reserved;
nd_uint8_t type;
nd_uint16_t holdtime;
nd_uint16_t cksum;
};
static void
esis_print(netdissect_options *ndo,
const uint8_t *pptr, u_int length)
{
const uint8_t *optr;
u_int li, version, esis_pdu_type, source_address_length, source_address_number;
const struct esis_header_t *esis_header;
ndo->ndo_protocol = "esis";
if (!ndo->ndo_eflag)
ND_PRINT("ES-IS");
if (length <= 2) {
ND_PRINT(ndo->ndo_qflag ? "bad pkt!" : "no header at all!");
return;
}
esis_header = (const struct esis_header_t *) pptr;
ND_TCHECK_SIZE(esis_header);
li = GET_U_1(esis_header->length_indicator);
optr = pptr;
/*
* Sanity checking of the header.
*/
if (GET_U_1(esis_header->nlpid) != NLPID_ESIS) {
ND_PRINT(" nlpid 0x%02x packet not supported",
GET_U_1(esis_header->nlpid));
return;
}
version = GET_U_1(esis_header->version);
if (version != ESIS_VERSION) {
ND_PRINT(" version %u packet not supported", version);
return;
}
if (li > length) {
ND_PRINT(" length indicator(%u) > PDU size (%u)!", li, length);
return;
}
if (li < sizeof(struct esis_header_t) + 2) {
ND_PRINT(" length indicator %u < min PDU size:", li);
while (pptr < ndo->ndo_snapend) {
ND_PRINT("%02X", GET_U_1(pptr));
pptr++;
}
return;
}
esis_pdu_type = GET_U_1(esis_header->type) & ESIS_PDU_TYPE_MASK;
if (ndo->ndo_vflag < 1) {
ND_PRINT("%s%s, length %u",
ndo->ndo_eflag ? "" : ", ",
tok2str(esis_pdu_values,"unknown type (%u)",esis_pdu_type),
length);
return;
} else
ND_PRINT("%slength %u\n\t%s (%u)",
ndo->ndo_eflag ? "" : ", ",
length,
tok2str(esis_pdu_values,"unknown type: %u", esis_pdu_type),
esis_pdu_type);
ND_PRINT(", v: %u%s", version, version == ESIS_VERSION ? "" : "unsupported" );
ND_PRINT(", checksum: 0x%04x", GET_BE_U_2(esis_header->cksum));
osi_print_cksum(ndo, pptr, GET_BE_U_2(esis_header->cksum), 7,
li);
ND_PRINT(", holding time: %us, length indicator: %u",
GET_BE_U_2(esis_header->holdtime), li);
if (ndo->ndo_vflag > 1)
print_unknown_data(ndo, optr, "\n\t", sizeof(struct esis_header_t));
pptr += sizeof(struct esis_header_t);
li -= sizeof(struct esis_header_t);
switch (esis_pdu_type) {
case ESIS_PDU_REDIRECT: {
const uint8_t *dst, *snpa, *neta;
u_int dstl, snpal, netal;
ND_TCHECK_1(pptr);
if (li < 1) {
ND_PRINT(", bad redirect/li");
return;
}
dstl = GET_U_1(pptr);
pptr++;
li--;
ND_TCHECK_LEN(pptr, dstl);
if (li < dstl) {
ND_PRINT(", bad redirect/li");
return;
}
dst = pptr;
pptr += dstl;
li -= dstl;
ND_PRINT("\n\t %s", GET_ISONSAP_STRING(dst, dstl));
ND_TCHECK_1(pptr);
if (li < 1) {
ND_PRINT(", bad redirect/li");
return;
}
snpal = GET_U_1(pptr);
pptr++;
li--;
ND_TCHECK_LEN(pptr, snpal);
if (li < snpal) {
ND_PRINT(", bad redirect/li");
return;
}
snpa = pptr;
pptr += snpal;
li -= snpal;
ND_TCHECK_1(pptr);
if (li < 1) {
ND_PRINT(", bad redirect/li");
return;
}
netal = GET_U_1(pptr);
pptr++;
ND_TCHECK_LEN(pptr, netal);
if (li < netal) {
ND_PRINT(", bad redirect/li");
return;
}
neta = pptr;
pptr += netal;
li -= netal;
if (snpal == MAC_ADDR_LEN)
ND_PRINT("\n\t SNPA (length: %u): %s",
snpal,
GET_ETHERADDR_STRING(snpa));
else
ND_PRINT("\n\t SNPA (length: %u): %s",
snpal,
GET_LINKADDR_STRING(snpa, LINKADDR_OTHER, snpal));
if (netal != 0)
ND_PRINT("\n\t NET (length: %u) %s",
netal,
GET_ISONSAP_STRING(neta, netal));
break;
}
case ESIS_PDU_ESH:
ND_TCHECK_1(pptr);
if (li < 1) {
ND_PRINT(", bad esh/li");
return;
}
source_address_number = GET_U_1(pptr);
pptr++;
li--;
ND_PRINT("\n\t Number of Source Addresses: %u", source_address_number);
while (source_address_number > 0) {
ND_TCHECK_1(pptr);
if (li < 1) {
ND_PRINT(", bad esh/li");
return;
}
source_address_length = GET_U_1(pptr);
pptr++;
li--;
ND_TCHECK_LEN(pptr, source_address_length);
if (li < source_address_length) {
ND_PRINT(", bad esh/li");
return;
}
ND_PRINT("\n\t NET (length: %u): %s",
source_address_length,
GET_ISONSAP_STRING(pptr, source_address_length));
pptr += source_address_length;
li -= source_address_length;
source_address_number--;
}
break;
case ESIS_PDU_ISH: {
ND_TCHECK_1(pptr);
if (li < 1) {
ND_PRINT(", bad ish/li");
return;
}
source_address_length = GET_U_1(pptr);
pptr++;
li--;
ND_TCHECK_LEN(pptr, source_address_length);
if (li < source_address_length) {
ND_PRINT(", bad ish/li");
return;
}
ND_PRINT("\n\t NET (length: %u): %s", source_address_length, GET_ISONSAP_STRING(pptr, source_address_length));
pptr += source_address_length;
li -= source_address_length;
break;
}
default:
if (ndo->ndo_vflag <= 1) {
/*
* If there's at least one byte to print, print
* it/them.
*/
if (ND_TTEST_LEN(pptr, 1))
print_unknown_data(ndo, pptr, "\n\t ", ND_BYTES_AVAILABLE_AFTER(pptr));
}
return;
}
/* now walk the options */
while (li != 0) {
u_int op, opli;
const uint8_t *tptr;
if (li < 2) {
ND_PRINT(", bad opts/li");
return;
}
op = GET_U_1(pptr);
opli = GET_U_1(pptr + 1);
pptr += 2;
li -= 2;
if (opli > li) {
ND_PRINT(", opt (%u) too long", op);
return;
}
li -= opli;
tptr = pptr;
ND_PRINT("\n\t %s Option #%u, length %u, value: ",
tok2str(esis_option_values,"Unknown",op),
op,
opli);
switch (op) {
case ESIS_OPTION_ES_CONF_TIME:
if (opli == 2) {
ND_TCHECK_2(pptr);
ND_PRINT("%us", GET_BE_U_2(tptr));
} else
ND_PRINT("(bad length)");
break;
case ESIS_OPTION_PROTOCOLS:
while (opli>0) {
ND_PRINT("%s (0x%02x)",
tok2str(nlpid_values,
"unknown",
GET_U_1(tptr)),
GET_U_1(tptr));
if (opli>1) /* further NPLIDs ? - put comma */
ND_PRINT(", ");
tptr++;
opli--;
}
break;
/*
* FIXME those are the defined Options that lack a decoder
* you are welcome to contribute code ;-)
*/
case ESIS_OPTION_QOS_MAINTENANCE:
case ESIS_OPTION_SECURITY:
case ESIS_OPTION_PRIORITY:
case ESIS_OPTION_ADDRESS_MASK:
case ESIS_OPTION_SNPA_MASK:
default:
print_unknown_data(ndo, tptr, "\n\t ", opli);
break;
}
if (ndo->ndo_vflag > 1)
print_unknown_data(ndo, pptr, "\n\t ", opli);
pptr += opli;
}
return;
trunc:
nd_print_trunc(ndo);
}
static void
isis_print_mcid(netdissect_options *ndo,
const struct isis_spb_mcid *mcid)
{
int i;
ND_TCHECK_SIZE(mcid);
ND_PRINT("ID: %u, Name: ", GET_U_1(mcid->format_id));
nd_printjnp(ndo, mcid->name, sizeof(mcid->name));
ND_PRINT("\n\t Lvl: %u", GET_BE_U_2(mcid->revision_lvl));
ND_PRINT(", Digest: ");
for(i=0;i<16;i++)
ND_PRINT("%.2x ", mcid->digest[i]);
return;
trunc:
nd_print_trunc(ndo);
}
static int
isis_print_mt_port_cap_subtlv(netdissect_options *ndo,
const uint8_t *tptr, u_int len)
{
u_int stlv_type, stlv_len;
const struct isis_subtlv_spb_mcid *subtlv_spb_mcid;
int i;
- while (len > 2)
- {
+ while (len > 2) {
stlv_type = GET_U_1(tptr);
stlv_len = GET_U_1(tptr + 1);
/* first lets see if we know the subTLVs name*/
ND_PRINT("\n\t %s subTLV #%u, length: %u",
tok2str(isis_mt_port_cap_subtlv_values, "unknown", stlv_type),
stlv_type,
stlv_len);
tptr += 2;
/*len -= TLV_TYPE_LEN_OFFSET;*/
len -= 2;
/* Make sure the subTLV fits within the space left */
if (len < stlv_len)
goto subtlv_too_long;
/* Make sure the entire subTLV is in the captured data */
ND_TCHECK_LEN(tptr, stlv_len);
- switch (stlv_type)
- {
+ switch (stlv_type) {
case ISIS_SUBTLV_SPB_MCID:
{
if (stlv_len < ISIS_SUBTLV_SPB_MCID_MIN_LEN)
goto subtlv_too_short;
subtlv_spb_mcid = (const struct isis_subtlv_spb_mcid *)tptr;
ND_PRINT("\n\t MCID: ");
isis_print_mcid(ndo, &(subtlv_spb_mcid->mcid));
/*tptr += SPB_MCID_MIN_LEN;
len -= SPB_MCID_MIN_LEN; */
ND_PRINT("\n\t AUX-MCID: ");
isis_print_mcid(ndo, &(subtlv_spb_mcid->aux_mcid));
/*tptr += SPB_MCID_MIN_LEN;
len -= SPB_MCID_MIN_LEN; */
tptr += ISIS_SUBTLV_SPB_MCID_MIN_LEN;
len -= ISIS_SUBTLV_SPB_MCID_MIN_LEN;
stlv_len -= ISIS_SUBTLV_SPB_MCID_MIN_LEN;
break;
}
case ISIS_SUBTLV_SPB_DIGEST:
{
if (stlv_len < ISIS_SUBTLV_SPB_DIGEST_MIN_LEN)
goto subtlv_too_short;
ND_PRINT("\n\t RES: %u V: %u A: %u D: %u",
(GET_U_1(tptr) >> 5),
((GET_U_1(tptr) >> 4) & 0x01),
((GET_U_1(tptr) >> 2) & 0x03),
(GET_U_1(tptr) & 0x03));
tptr++;
ND_PRINT("\n\t Digest: ");
- for(i=1;i<=8; i++)
- {
+ for(i=1;i<=8; i++) {
ND_PRINT("%08x ", GET_BE_U_4(tptr));
if (i%4 == 0 && i != 8)
ND_PRINT("\n\t ");
tptr += 4;
}
len -= ISIS_SUBTLV_SPB_DIGEST_MIN_LEN;
stlv_len -= ISIS_SUBTLV_SPB_DIGEST_MIN_LEN;
break;
}
case ISIS_SUBTLV_SPB_BVID:
{
- while (stlv_len != 0)
- {
+ while (stlv_len != 0) {
if (stlv_len < 4)
goto subtlv_too_short;
ND_PRINT("\n\t ECT: %08x",
GET_BE_U_4(tptr));
tptr += 4;
len -= 4;
stlv_len -= 4;
if (stlv_len < 2)
goto subtlv_too_short;
ND_PRINT(" BVID: %u, U:%01x M:%01x ",
(GET_BE_U_2(tptr) >> 4) ,
(GET_BE_U_2(tptr) >> 3) & 0x01,
(GET_BE_U_2(tptr) >> 2) & 0x01);
tptr += 2;
len -= 2;
stlv_len -= 2;
}
break;
}
default:
break;
}
tptr += stlv_len;
len -= stlv_len;
}
return (0);
trunc:
nd_print_trunc(ndo);
return (1);
subtlv_too_long:
ND_PRINT(" (> containing TLV length)");
return (1);
subtlv_too_short:
ND_PRINT(" (too short)");
return (1);
}
static int
isis_print_mt_capability_subtlv(netdissect_options *ndo,
const uint8_t *tptr, u_int len)
{
u_int stlv_type, stlv_len, treecount;
- while (len > 2)
- {
+ while (len > 2) {
stlv_type = GET_U_1(tptr);
stlv_len = GET_U_1(tptr + 1);
tptr += 2;
len -= 2;
/* first lets see if we know the subTLVs name*/
ND_PRINT("\n\t %s subTLV #%u, length: %u",
tok2str(isis_mt_capability_subtlv_values, "unknown", stlv_type),
stlv_type,
stlv_len);
/* Make sure the subTLV fits within the space left */
if (len < stlv_len)
goto subtlv_too_long;
/* Make sure the entire subTLV is in the captured data */
ND_TCHECK_LEN(tptr, stlv_len);
- switch (stlv_type)
- {
+ switch (stlv_type) {
case ISIS_SUBTLV_SPB_INSTANCE:
if (stlv_len < ISIS_SUBTLV_SPB_INSTANCE_MIN_LEN)
goto subtlv_too_short;
ND_PRINT("\n\t CIST Root-ID: %08x", GET_BE_U_4(tptr));
tptr += 4;
ND_PRINT(" %08x", GET_BE_U_4(tptr));
tptr += 4;
ND_PRINT(", Path Cost: %08x", GET_BE_U_4(tptr));
tptr += 4;
ND_PRINT(", Prio: %u", GET_BE_U_2(tptr));
tptr += 2;
ND_PRINT("\n\t RES: %u",
GET_BE_U_2(tptr) >> 5);
ND_PRINT(", V: %u",
(GET_BE_U_2(tptr) >> 4) & 0x0001);
ND_PRINT(", SPSource-ID: %u",
(GET_BE_U_4(tptr) & 0x000fffff));
tptr += 4;
ND_PRINT(", No of Trees: %x", GET_U_1(tptr));
treecount = GET_U_1(tptr);
tptr++;
len -= ISIS_SUBTLV_SPB_INSTANCE_MIN_LEN;
stlv_len -= ISIS_SUBTLV_SPB_INSTANCE_MIN_LEN;
- while (treecount)
- {
+ while (treecount) {
if (stlv_len < ISIS_SUBTLV_SPB_INSTANCE_VLAN_TUPLE_LEN)
goto trunc;
ND_PRINT("\n\t U:%u, M:%u, A:%u, RES:%u",
GET_U_1(tptr) >> 7,
(GET_U_1(tptr) >> 6) & 0x01,
(GET_U_1(tptr) >> 5) & 0x01,
(GET_U_1(tptr) & 0x1f));
tptr++;
ND_PRINT(", ECT: %08x", GET_BE_U_4(tptr));
tptr += 4;
ND_PRINT(", BVID: %u, SPVID: %u",
(GET_BE_U_3(tptr) >> 12) & 0x000fff,
GET_BE_U_3(tptr) & 0x000fff);
tptr += 3;
len -= ISIS_SUBTLV_SPB_INSTANCE_VLAN_TUPLE_LEN;
stlv_len -= ISIS_SUBTLV_SPB_INSTANCE_VLAN_TUPLE_LEN;
treecount--;
}
break;
case ISIS_SUBTLV_SPBM_SI:
if (stlv_len < 8)
goto trunc;
ND_PRINT("\n\t BMAC: %08x", GET_BE_U_4(tptr));
tptr += 4;
ND_PRINT("%04x", GET_BE_U_2(tptr));
tptr += 2;
ND_PRINT(", RES: %u, VID: %u", GET_BE_U_2(tptr) >> 12,
(GET_BE_U_2(tptr)) & 0x0fff);
tptr += 2;
len -= 8;
stlv_len -= 8;
while (stlv_len >= 4) {
ND_PRINT("\n\t T: %u, R: %u, RES: %u, ISID: %u",
(GET_BE_U_4(tptr) >> 31),
(GET_BE_U_4(tptr) >> 30) & 0x01,
(GET_BE_U_4(tptr) >> 24) & 0x03f,
(GET_BE_U_4(tptr)) & 0x0ffffff);
tptr += 4;
len -= 4;
stlv_len -= 4;
}
break;
default:
break;
}
tptr += stlv_len;
len -= stlv_len;
}
return (0);
trunc:
nd_print_trunc(ndo);
return (1);
subtlv_too_long:
ND_PRINT(" (> containing TLV length)");
return (1);
subtlv_too_short:
ND_PRINT(" (too short)");
return (1);
}
/* shared routine for printing system, node and lsp-ids */
static char *
isis_print_id(netdissect_options *ndo, const uint8_t *cp, u_int id_len)
{
u_int i;
static char id[sizeof("xxxx.xxxx.xxxx.yy-zz")];
char *pos = id;
u_int sysid_len;
sysid_len = SYSTEM_ID_LEN;
if (sysid_len > id_len)
sysid_len = id_len;
for (i = 1; i <= sysid_len; i++) {
snprintf(pos, sizeof(id) - (pos - id), "%02x", GET_U_1(cp));
cp++;
pos += strlen(pos);
if (i == 2 || i == 4)
*pos++ = '.';
}
if (id_len >= NODE_ID_LEN) {
snprintf(pos, sizeof(id) - (pos - id), ".%02x", GET_U_1(cp));
cp++;
pos += strlen(pos);
}
if (id_len == LSP_ID_LEN)
snprintf(pos, sizeof(id) - (pos - id), "-%02x", GET_U_1(cp));
return (id);
}
/* print the 4-byte metric block which is common found in the old-style TLVs */
static int
isis_print_metric_block(netdissect_options *ndo,
const struct isis_metric_block *isis_metric_block)
{
ND_PRINT(", Default Metric: %u, %s",
ISIS_LSP_TLV_METRIC_VALUE(isis_metric_block->metric_default),
ISIS_LSP_TLV_METRIC_IE(isis_metric_block->metric_default) ? "External" : "Internal");
if (!ISIS_LSP_TLV_METRIC_SUPPORTED(isis_metric_block->metric_delay))
ND_PRINT("\n\t\t Delay Metric: %u, %s",
ISIS_LSP_TLV_METRIC_VALUE(isis_metric_block->metric_delay),
ISIS_LSP_TLV_METRIC_IE(isis_metric_block->metric_delay) ? "External" : "Internal");
if (!ISIS_LSP_TLV_METRIC_SUPPORTED(isis_metric_block->metric_expense))
ND_PRINT("\n\t\t Expense Metric: %u, %s",
ISIS_LSP_TLV_METRIC_VALUE(isis_metric_block->metric_expense),
ISIS_LSP_TLV_METRIC_IE(isis_metric_block->metric_expense) ? "External" : "Internal");
if (!ISIS_LSP_TLV_METRIC_SUPPORTED(isis_metric_block->metric_error))
ND_PRINT("\n\t\t Error Metric: %u, %s",
ISIS_LSP_TLV_METRIC_VALUE(isis_metric_block->metric_error),
ISIS_LSP_TLV_METRIC_IE(isis_metric_block->metric_error) ? "External" : "Internal");
return(1); /* everything is ok */
}
static int
isis_print_tlv_ip_reach(netdissect_options *ndo,
const uint8_t *cp, const char *ident, u_int length)
{
int prefix_len;
const struct isis_tlv_ip_reach *tlv_ip_reach;
tlv_ip_reach = (const struct isis_tlv_ip_reach *)cp;
while (length > 0) {
if ((size_t)length < sizeof(*tlv_ip_reach)) {
ND_PRINT("short IPv4 Reachability (%u vs %zu)",
length,
sizeof(*tlv_ip_reach));
return (0);
}
ND_TCHECK_SIZE(tlv_ip_reach);
prefix_len = mask2plen(GET_IPV4_TO_HOST_ORDER(tlv_ip_reach->mask));
if (prefix_len == -1)
ND_PRINT("%sIPv4 prefix: %s mask %s",
ident,
GET_IPADDR_STRING(tlv_ip_reach->prefix),
GET_IPADDR_STRING(tlv_ip_reach->mask));
else
ND_PRINT("%sIPv4 prefix: %15s/%u",
ident,
GET_IPADDR_STRING(tlv_ip_reach->prefix),
prefix_len);
ND_PRINT(", Distribution: %s, Metric: %u, %s",
ISIS_LSP_TLV_METRIC_UPDOWN(tlv_ip_reach->isis_metric_block.metric_default) ? "down" : "up",
ISIS_LSP_TLV_METRIC_VALUE(tlv_ip_reach->isis_metric_block.metric_default),
ISIS_LSP_TLV_METRIC_IE(tlv_ip_reach->isis_metric_block.metric_default) ? "External" : "Internal");
if (!ISIS_LSP_TLV_METRIC_SUPPORTED(tlv_ip_reach->isis_metric_block.metric_delay))
ND_PRINT("%s Delay Metric: %u, %s",
ident,
ISIS_LSP_TLV_METRIC_VALUE(tlv_ip_reach->isis_metric_block.metric_delay),
ISIS_LSP_TLV_METRIC_IE(tlv_ip_reach->isis_metric_block.metric_delay) ? "External" : "Internal");
if (!ISIS_LSP_TLV_METRIC_SUPPORTED(tlv_ip_reach->isis_metric_block.metric_expense))
ND_PRINT("%s Expense Metric: %u, %s",
ident,
ISIS_LSP_TLV_METRIC_VALUE(tlv_ip_reach->isis_metric_block.metric_expense),
ISIS_LSP_TLV_METRIC_IE(tlv_ip_reach->isis_metric_block.metric_expense) ? "External" : "Internal");
if (!ISIS_LSP_TLV_METRIC_SUPPORTED(tlv_ip_reach->isis_metric_block.metric_error))
ND_PRINT("%s Error Metric: %u, %s",
ident,
ISIS_LSP_TLV_METRIC_VALUE(tlv_ip_reach->isis_metric_block.metric_error),
ISIS_LSP_TLV_METRIC_IE(tlv_ip_reach->isis_metric_block.metric_error) ? "External" : "Internal");
length -= sizeof(struct isis_tlv_ip_reach);
tlv_ip_reach++;
}
return (1);
trunc:
return 0;
}
/*
* this is the common IP-REACH subTLV decoder it is called
* from various EXTD-IP REACH TLVs (135,235,236,237)
*/
static int
isis_print_ip_reach_subtlv(netdissect_options *ndo,
const uint8_t *tptr, u_int subt, u_int subl,
const char *ident)
{
/* first lets see if we know the subTLVs name*/
ND_PRINT("%s%s subTLV #%u, length: %u",
ident, tok2str(isis_ext_ip_reach_subtlv_values, "unknown", subt),
subt, subl);
ND_TCHECK_LEN(tptr, subl);
switch(subt) {
case ISIS_SUBTLV_EXTD_IP_REACH_MGMT_PREFIX_COLOR: /* fall through */
case ISIS_SUBTLV_EXTD_IP_REACH_ADMIN_TAG32:
while (subl >= 4) {
ND_PRINT(", 0x%08x (=%u)",
GET_BE_U_4(tptr),
GET_BE_U_4(tptr));
tptr+=4;
subl-=4;
}
break;
case ISIS_SUBTLV_EXTD_IP_REACH_ADMIN_TAG64:
while (subl >= 8) {
ND_PRINT(", 0x%08x%08x",
GET_BE_U_4(tptr),
GET_BE_U_4(tptr + 4));
tptr+=8;
subl-=8;
}
break;
case ISIS_SUBTLV_EXTD_IP_REACH_PREFIX_SID:
{
uint8_t algo, flags;
uint32_t sid;
flags = GET_U_1(tptr);
algo = GET_U_1(tptr+1);
if (flags & ISIS_PREFIX_SID_FLAG_V) {
if (subl < 5)
goto trunc;
sid = GET_BE_U_3(tptr+2);
tptr+=5;
subl-=5;
} else {
if (subl < 6)
goto trunc;
sid = GET_BE_U_4(tptr+2);
tptr+=6;
subl-=6;
}
ND_PRINT(", Flags [%s], Algo %s (%u), %s %u",
bittok2str(prefix_sid_flag_values, "None", flags),
tok2str(prefix_sid_algo_values, "Unknown", algo), algo,
flags & ISIS_PREFIX_SID_FLAG_V ? "label" : "index",
sid);
}
break;
default:
if (!print_unknown_data(ndo, tptr, "\n\t\t ", subl))
return(0);
break;
}
return(1);
trunc:
nd_print_trunc(ndo);
return(0);
}
/*
* this is the common IS-REACH decoder it is called
* from various EXTD-IS REACH style TLVs (22,24,222)
*/
static int
isis_print_ext_is_reach(netdissect_options *ndo,
const uint8_t *tptr, const char *ident, u_int tlv_type,
u_int tlv_remaining)
{
char ident_buffer[20];
u_int subtlv_type,subtlv_len,subtlv_sum_len;
int proc_bytes = 0; /* how many bytes did we process ? */
u_int te_class,priority_level,gmpls_switch_cap;
union { /* int to float conversion buffer for several subTLVs */
float f;
uint32_t i;
} bw;
ND_TCHECK_LEN(tptr, NODE_ID_LEN);
if (tlv_remaining < NODE_ID_LEN)
return(0);
ND_PRINT("%sIS Neighbor: %s", ident, isis_print_id(ndo, tptr, NODE_ID_LEN));
tptr+=NODE_ID_LEN;
tlv_remaining-=NODE_ID_LEN;
proc_bytes+=NODE_ID_LEN;
if (tlv_type != ISIS_TLV_IS_ALIAS_ID) { /* the Alias TLV Metric field is implicit 0 */
ND_TCHECK_3(tptr);
if (tlv_remaining < 3)
return(0);
ND_PRINT(", Metric: %u", GET_BE_U_3(tptr));
tptr+=3;
tlv_remaining-=3;
proc_bytes+=3;
}
ND_TCHECK_1(tptr);
if (tlv_remaining < 1)
return(0);
subtlv_sum_len=GET_U_1(tptr); /* read out subTLV length */
tptr++;
tlv_remaining--;
proc_bytes++;
ND_PRINT(", %ssub-TLVs present",subtlv_sum_len ? "" : "no ");
if (subtlv_sum_len) {
ND_PRINT(" (%u)", subtlv_sum_len);
/* prepend the indent string */
snprintf(ident_buffer, sizeof(ident_buffer), "%s ",ident);
ident = ident_buffer;
while (subtlv_sum_len != 0) {
ND_TCHECK_2(tptr);
if (tlv_remaining < 2) {
ND_PRINT("%sRemaining data in TLV shorter than a subTLV header",ident);
proc_bytes += tlv_remaining;
break;
}
if (subtlv_sum_len < 2) {
ND_PRINT("%sRemaining data in subTLVs shorter than a subTLV header",ident);
proc_bytes += subtlv_sum_len;
break;
}
subtlv_type=GET_U_1(tptr);
subtlv_len=GET_U_1(tptr + 1);
tptr += 2;
tlv_remaining -= 2;
subtlv_sum_len -= 2;
proc_bytes += 2;
ND_PRINT("%s%s subTLV #%u, length: %u",
ident, tok2str(isis_ext_is_reach_subtlv_values, "unknown", subtlv_type),
subtlv_type, subtlv_len);
if (subtlv_sum_len < subtlv_len) {
ND_PRINT(" (remaining data in subTLVs shorter than the current subTLV)");
proc_bytes += subtlv_sum_len;
break;
}
if (tlv_remaining < subtlv_len) {
ND_PRINT(" (> remaining tlv length)");
proc_bytes += tlv_remaining;
break;
}
ND_TCHECK_LEN(tptr, subtlv_len);
switch(subtlv_type) {
case ISIS_SUBTLV_EXT_IS_REACH_ADMIN_GROUP:
case ISIS_SUBTLV_EXT_IS_REACH_LINK_LOCAL_REMOTE_ID:
case ISIS_SUBTLV_EXT_IS_REACH_LINK_REMOTE_ID:
if (subtlv_len >= 4) {
ND_PRINT(", 0x%08x", GET_BE_U_4(tptr));
if (subtlv_len == 8) /* rfc4205 */
ND_PRINT(", 0x%08x", GET_BE_U_4(tptr + 4));
}
break;
case ISIS_SUBTLV_EXT_IS_REACH_IPV4_INTF_ADDR:
case ISIS_SUBTLV_EXT_IS_REACH_IPV4_NEIGHBOR_ADDR:
if (subtlv_len >= sizeof(nd_ipv4))
ND_PRINT(", %s", GET_IPADDR_STRING(tptr));
break;
case ISIS_SUBTLV_EXT_IS_REACH_MAX_LINK_BW :
case ISIS_SUBTLV_EXT_IS_REACH_RESERVABLE_BW:
if (subtlv_len >= 4) {
bw.i = GET_BE_U_4(tptr);
ND_PRINT(", %.3f Mbps", bw.f * 8 / 1000000);
}
break;
case ISIS_SUBTLV_EXT_IS_REACH_UNRESERVED_BW :
if (subtlv_len >= 32) {
for (te_class = 0; te_class < 8; te_class++) {
bw.i = GET_BE_U_4(tptr);
ND_PRINT("%s TE-Class %u: %.3f Mbps",
ident,
te_class,
bw.f * 8 / 1000000);
tptr += 4;
subtlv_len -= 4;
subtlv_sum_len -= 4;
proc_bytes += 4;
}
}
break;
case ISIS_SUBTLV_EXT_IS_REACH_BW_CONSTRAINTS: /* fall through */
case ISIS_SUBTLV_EXT_IS_REACH_BW_CONSTRAINTS_OLD:
if (subtlv_len == 0)
break;
ND_PRINT("%sBandwidth Constraints Model ID: %s (%u)",
ident,
tok2str(diffserv_te_bc_values, "unknown", GET_U_1(tptr)),
GET_U_1(tptr));
tptr++;
subtlv_len--;
subtlv_sum_len--;
proc_bytes++;
/* decode BCs until the subTLV ends */
for (te_class = 0; subtlv_len != 0; te_class++) {
if (subtlv_len < 4)
break;
bw.i = GET_BE_U_4(tptr);
ND_PRINT("%s Bandwidth constraint CT%u: %.3f Mbps",
ident,
te_class,
bw.f * 8 / 1000000);
tptr += 4;
subtlv_len -= 4;
subtlv_sum_len -= 4;
proc_bytes += 4;
}
break;
case ISIS_SUBTLV_EXT_IS_REACH_TE_METRIC:
if (subtlv_len >= 3)
ND_PRINT(", %u", GET_BE_U_3(tptr));
break;
case ISIS_SUBTLV_EXT_IS_REACH_LINK_ATTRIBUTE:
if (subtlv_len == 2) {
ND_PRINT(", [ %s ] (0x%04x)",
bittok2str(isis_subtlv_link_attribute_values,
"Unknown",
GET_BE_U_2(tptr)),
GET_BE_U_2(tptr));
}
break;
case ISIS_SUBTLV_EXT_IS_REACH_LINK_PROTECTION_TYPE:
if (subtlv_len >= 2) {
ND_PRINT(", %s, Priority %u",
bittok2str(gmpls_link_prot_values, "none", GET_U_1(tptr)),
GET_U_1(tptr + 1));
}
break;
case ISIS_SUBTLV_SPB_METRIC:
if (subtlv_len >= 6) {
ND_PRINT(", LM: %u", GET_BE_U_3(tptr));
tptr += 3;
subtlv_len -= 3;
subtlv_sum_len -= 3;
proc_bytes += 3;
ND_PRINT(", P: %u", GET_U_1(tptr));
tptr++;
subtlv_len--;
subtlv_sum_len--;
proc_bytes++;
ND_PRINT(", P-ID: %u", GET_BE_U_2(tptr));
}
break;
case ISIS_SUBTLV_EXT_IS_REACH_INTF_SW_CAP_DESCR:
if (subtlv_len >= 36) {
gmpls_switch_cap = GET_U_1(tptr);
ND_PRINT("%s Interface Switching Capability:%s",
ident,
tok2str(gmpls_switch_cap_values, "Unknown", gmpls_switch_cap));
ND_PRINT(", LSP Encoding: %s",
tok2str(gmpls_encoding_values, "Unknown", GET_U_1((tptr + 1))));
tptr += 4;
subtlv_len -= 4;
subtlv_sum_len -= 4;
proc_bytes += 4;
ND_PRINT("%s Max LSP Bandwidth:", ident);
for (priority_level = 0; priority_level < 8; priority_level++) {
bw.i = GET_BE_U_4(tptr);
ND_PRINT("%s priority level %u: %.3f Mbps",
ident,
priority_level,
bw.f * 8 / 1000000);
tptr += 4;
subtlv_len -= 4;
subtlv_sum_len -= 4;
proc_bytes += 4;
}
switch (gmpls_switch_cap) {
case GMPLS_PSC1:
case GMPLS_PSC2:
case GMPLS_PSC3:
case GMPLS_PSC4:
if (subtlv_len < 6)
break;
bw.i = GET_BE_U_4(tptr);
ND_PRINT("%s Min LSP Bandwidth: %.3f Mbps", ident, bw.f * 8 / 1000000);
ND_PRINT("%s Interface MTU: %u", ident,
GET_BE_U_2(tptr + 4));
break;
case GMPLS_TSC:
if (subtlv_len < 8)
break;
bw.i = GET_BE_U_4(tptr);
ND_PRINT("%s Min LSP Bandwidth: %.3f Mbps", ident, bw.f * 8 / 1000000);
ND_PRINT("%s Indication %s", ident,
tok2str(gmpls_switch_cap_tsc_indication_values, "Unknown (%u)", GET_U_1((tptr + 4))));
break;
default:
/* there is some optional stuff left to decode but this is as of yet
not specified so just lets hexdump what is left */
if (subtlv_len != 0) {
if (!print_unknown_data(ndo, tptr, "\n\t\t ", subtlv_len))
return(0);
}
}
}
break;
case ISIS_SUBTLV_EXT_IS_REACH_LAN_ADJ_SEGMENT_ID:
if (subtlv_len >= 8) {
ND_PRINT("%s Flags: [%s]", ident,
bittok2str(isis_lan_adj_sid_flag_values,
"none",
GET_U_1(tptr)));
int vflag = (GET_U_1(tptr) & 0x20) ? 1:0;
int lflag = (GET_U_1(tptr) & 0x10) ? 1:0;
tptr++;
subtlv_len--;
subtlv_sum_len--;
proc_bytes++;
ND_PRINT("%s Weight: %u", ident, GET_U_1(tptr));
tptr++;
subtlv_len--;
subtlv_sum_len--;
proc_bytes++;
if(subtlv_len>=SYSTEM_ID_LEN) {
ND_TCHECK_LEN(tptr, SYSTEM_ID_LEN);
ND_PRINT("%s Neighbor System-ID: %s", ident,
isis_print_id(ndo, tptr, SYSTEM_ID_LEN));
}
/* RFC 8667 section 2.2.2 */
/* if V-flag is set to 1 and L-flag is set to 1 ==> 3 octet label */
/* if V-flag is set to 0 and L-flag is set to 0 ==> 4 octet index */
if (vflag && lflag) {
ND_PRINT("%s Label: %u",
ident, GET_BE_U_3(tptr+SYSTEM_ID_LEN));
} else if ((!vflag) && (!lflag)) {
ND_PRINT("%s Index: %u",
ident, GET_BE_U_4(tptr+SYSTEM_ID_LEN));
} else
nd_print_invalid(ndo);
}
break;
default:
if (!print_unknown_data(ndo, tptr, "\n\t\t ", subtlv_len))
return(0);
break;
}
tptr += subtlv_len;
tlv_remaining -= subtlv_len;
subtlv_sum_len -= subtlv_len;
proc_bytes += subtlv_len;
}
}
return(proc_bytes);
trunc:
return(0);
}
/*
* this is the common Multi Topology ID decoder
* it is called from various MT-TLVs (222,229,235,237)
*/
static uint8_t
isis_print_mtid(netdissect_options *ndo,
const uint8_t *tptr, const char *ident, u_int tlv_remaining)
{
if (tlv_remaining < 2)
goto trunc;
ND_PRINT("%s%s",
ident,
tok2str(isis_mt_values,
"Reserved for IETF Consensus",
ISIS_MASK_MTID(GET_BE_U_2(tptr))));
ND_PRINT(" Topology (0x%03x), Flags: [%s]",
ISIS_MASK_MTID(GET_BE_U_2(tptr)),
bittok2str(isis_mt_flag_values, "none",ISIS_MASK_MTFLAGS(GET_BE_U_2(tptr))));
return(2);
trunc:
return 0;
}
/*
* this is the common extended IP reach decoder
* it is called from TLVs (135,235,236,237)
* we process the TLV and optional subTLVs and return
* the amount of processed bytes
*/
static u_int
isis_print_extd_ip_reach(netdissect_options *ndo,
const uint8_t *tptr, const char *ident, uint16_t afi)
{
char ident_buffer[20];
uint8_t prefix[sizeof(nd_ipv6)]; /* shared copy buffer for IPv4 and IPv6 prefixes */
u_int metric, status_byte, bit_length, byte_length, sublen, processed, subtlvtype, subtlvlen;
metric = GET_BE_U_4(tptr);
processed=4;
tptr+=4;
if (afi == AF_INET) {
status_byte=GET_U_1(tptr);
tptr++;
bit_length = status_byte&0x3f;
if (bit_length > 32) {
ND_PRINT("%sIPv4 prefix: bad bit length %u",
ident,
bit_length);
return (0);
}
processed++;
} else if (afi == AF_INET6) {
status_byte=GET_U_1(tptr);
bit_length=GET_U_1(tptr + 1);
if (bit_length > 128) {
ND_PRINT("%sIPv6 prefix: bad bit length %u",
ident,
bit_length);
return (0);
}
tptr+=2;
processed+=2;
} else
return (0); /* somebody is fooling us */
byte_length = (bit_length + 7) / 8; /* prefix has variable length encoding */
memset(prefix, 0, sizeof(prefix)); /* clear the copy buffer */
GET_CPY_BYTES(prefix,tptr,byte_length); /* copy as much as is stored in the TLV */
tptr+=byte_length;
processed+=byte_length;
if (afi == AF_INET)
ND_PRINT("%sIPv4 prefix: %15s/%u",
ident,
ipaddr_string(ndo, prefix), /* local buffer, not packet data; don't use GET_IPADDR_STRING() */
bit_length);
else if (afi == AF_INET6)
ND_PRINT("%sIPv6 prefix: %s/%u",
ident,
ip6addr_string(ndo, prefix), /* local buffer, not packet data; don't use GET_IP6ADDR_STRING() */
bit_length);
ND_PRINT(", Distribution: %s, Metric: %u",
ISIS_MASK_TLV_EXTD_IP_UPDOWN(status_byte) ? "down" : "up",
metric);
if (afi == AF_INET && ISIS_MASK_TLV_EXTD_IP_SUBTLV(status_byte))
ND_PRINT(", sub-TLVs present");
else if (afi == AF_INET6)
ND_PRINT(", %s%s",
ISIS_MASK_TLV_EXTD_IP6_IE(status_byte) ? "External" : "Internal",
ISIS_MASK_TLV_EXTD_IP6_SUBTLV(status_byte) ? ", sub-TLVs present" : "");
if ((afi == AF_INET && ISIS_MASK_TLV_EXTD_IP_SUBTLV(status_byte))
|| (afi == AF_INET6 && ISIS_MASK_TLV_EXTD_IP6_SUBTLV(status_byte))
) {
/* assume that one prefix can hold more
than one subTLV - therefore the first byte must reflect
the aggregate bytecount of the subTLVs for this prefix
*/
sublen=GET_U_1(tptr);
tptr++;
processed+=sublen+1;
ND_PRINT(" (%u)", sublen); /* print out subTLV length */
while (sublen>0) {
subtlvtype=GET_U_1(tptr);
subtlvlen=GET_U_1(tptr + 1);
tptr+=2;
/* prepend the indent string */
snprintf(ident_buffer, sizeof(ident_buffer), "%s ",ident);
if (!isis_print_ip_reach_subtlv(ndo, tptr, subtlvtype, subtlvlen, ident_buffer))
return(0);
tptr+=subtlvlen;
sublen-=(subtlvlen+2);
}
}
return (processed);
}
static void
isis_print_router_cap_subtlv(netdissect_options *ndo, const uint8_t *tptr, uint8_t tlen)
{
uint8_t subt, subl;
while (tlen >= 2) {
subt = GET_U_1(tptr);
subl = GET_U_1(tptr+1);
tlen -= 2;
tptr += 2;
/* first lets see if we know the subTLVs name*/
ND_PRINT("\n\t\t%s subTLV #%u, length: %u",
tok2str(isis_router_capability_subtlv_values, "unknown", subt),
subt, subl);
/*
* Boundary check.
*/
if (subl > tlen) {
break;
}
ND_TCHECK_LEN(tptr, subl);
switch (subt) {
case ISIS_SUBTLV_ROUTER_CAP_SR:
{
uint8_t flags, sid_tlen, sid_type, sid_len;
uint32_t range;
const uint8_t *sid_ptr;
flags = GET_U_1(tptr);
range = GET_BE_U_3(tptr+1);
ND_PRINT(", Flags [%s], Range %u",
bittok2str(isis_router_capability_sr_flags, "None", flags),
range);
sid_ptr = tptr + 4;
sid_tlen = subl - 4;
while (sid_tlen >= 5) {
sid_type = GET_U_1(sid_ptr);
sid_len = GET_U_1(sid_ptr+1);
sid_tlen -= 2;
sid_ptr += 2;
/*
* Boundary check.
*/
if (sid_len > sid_tlen) {
break;
}
switch (sid_type) {
case 1:
if (sid_len == 3) {
ND_PRINT(", SID value %u", GET_BE_U_3(sid_ptr));
} else if (sid_len == 4) {
ND_PRINT(", SID value %u", GET_BE_U_4(sid_ptr));
} else {
ND_PRINT(", Unknown SID length%u", sid_len);
}
break;
default:
print_unknown_data(ndo, sid_ptr, "\n\t\t ", sid_len);
}
sid_ptr += sid_len;
sid_tlen -= sid_len;
}
}
break;
default:
print_unknown_data(ndo, tptr, "\n\t\t", subl);
break;
}
tlen -= subl;
tptr += subl;
}
trunc:
return;
}
/*
* Clear checksum and lifetime prior to signature verification.
*/
static void
isis_clear_checksum_lifetime(void *header)
{
struct isis_lsp_header *header_lsp = (struct isis_lsp_header *) header;
header_lsp->checksum[0] = 0;
header_lsp->checksum[1] = 0;
header_lsp->remaining_lifetime[0] = 0;
header_lsp->remaining_lifetime[1] = 0;
}
/*
* isis_print
* Decode IS-IS packets. Return 0 on error.
*/
#define INVALID_OR_DECREMENT(length,decr) \
if ((length) < (decr)) { \
ND_PRINT(" [packet length %u < %zu]", (length), (decr)); \
nd_print_invalid(ndo); \
return 1; \
} \
length -= (decr);
static int
isis_print(netdissect_options *ndo,
const uint8_t *p, u_int length)
{
const struct isis_common_header *isis_header;
const struct isis_iih_lan_header *header_iih_lan;
const struct isis_iih_ptp_header *header_iih_ptp;
const struct isis_lsp_header *header_lsp;
const struct isis_csnp_header *header_csnp;
const struct isis_psnp_header *header_psnp;
const struct isis_tlv_lsp *tlv_lsp;
const struct isis_tlv_ptp_adj *tlv_ptp_adj;
const struct isis_tlv_is_reach *tlv_is_reach;
const struct isis_tlv_es_reach *tlv_es_reach;
uint8_t version, pdu_version, fixed_len;
uint8_t pdu_type, pdu_max_area, max_area, pdu_id_length, id_length, tlv_type, tlv_len, tlen, alen, prefix_len;
u_int ext_is_len, ext_ip_len;
uint8_t mt_len;
uint8_t isis_subtlv_idrp;
const uint8_t *optr, *pptr, *tptr;
u_int packet_len;
u_short pdu_len, key_id;
u_int i,vendor_id, num_vals;
uint8_t auth_type;
uint8_t num_system_ids;
int sigcheck;
ndo->ndo_protocol = "isis";
packet_len=length;
optr = p; /* initialize the _o_riginal pointer to the packet start -
need it for parsing the checksum TLV and authentication
TLV verification */
isis_header = (const struct isis_common_header *)p;
ND_TCHECK_SIZE(isis_header);
if (length < ISIS_COMMON_HEADER_SIZE)
goto trunc;
pptr = p+(ISIS_COMMON_HEADER_SIZE);
header_iih_lan = (const struct isis_iih_lan_header *)pptr;
header_iih_ptp = (const struct isis_iih_ptp_header *)pptr;
header_lsp = (const struct isis_lsp_header *)pptr;
header_csnp = (const struct isis_csnp_header *)pptr;
header_psnp = (const struct isis_psnp_header *)pptr;
if (!ndo->ndo_eflag)
ND_PRINT("IS-IS");
/*
* Sanity checking of the header.
*/
version = GET_U_1(isis_header->version);
if (version != ISIS_VERSION) {
ND_PRINT("version %u packet not supported", version);
return (0);
}
pdu_id_length = GET_U_1(isis_header->id_length);
if ((pdu_id_length != SYSTEM_ID_LEN) && (pdu_id_length != 0)) {
ND_PRINT("system ID length of %u is not supported",
pdu_id_length);
return (0);
}
pdu_version = GET_U_1(isis_header->pdu_version);
if (pdu_version != ISIS_VERSION) {
ND_PRINT("version %u packet not supported", pdu_version);
return (0);
}
fixed_len = GET_U_1(isis_header->fixed_len);
if (length < fixed_len) {
ND_PRINT("fixed header length %u > packet length %u", fixed_len, length);
return (0);
}
if (fixed_len < ISIS_COMMON_HEADER_SIZE) {
ND_PRINT("fixed header length %u < minimum header size %u", fixed_len, (u_int)ISIS_COMMON_HEADER_SIZE);
return (0);
}
pdu_max_area = GET_U_1(isis_header->max_area);
switch(pdu_max_area) {
case 0:
max_area = 3; /* silly shit */
break;
case 255:
ND_PRINT("bad packet -- 255 areas");
return (0);
default:
max_area = pdu_max_area;
break;
}
switch(pdu_id_length) {
case 0:
id_length = 6; /* silly shit again */
break;
case 1: /* 1-8 are valid sys-ID lengths */
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
id_length = pdu_id_length;
break;
case 255:
id_length = 0; /* entirely useless */
break;
default:
id_length = pdu_id_length;
break;
}
/* toss any non 6-byte sys-ID len PDUs */
if (id_length != 6 ) {
ND_PRINT("bad packet -- illegal sys-ID length (%u)", id_length);
return (0);
}
pdu_type = GET_U_1(isis_header->pdu_type);
/* in non-verbose mode print the basic PDU Type plus PDU specific brief information*/
if (ndo->ndo_vflag == 0) {
ND_PRINT("%s%s",
ndo->ndo_eflag ? "" : ", ",
tok2str(isis_pdu_values, "unknown PDU-Type %u", pdu_type));
} else {
/* ok they seem to want to know everything - lets fully decode it */
ND_PRINT("%slength %u", ndo->ndo_eflag ? "" : ", ", length);
ND_PRINT("\n\t%s, hlen: %u, v: %u, pdu-v: %u, sys-id-len: %u (%u), max-area: %u (%u)",
tok2str(isis_pdu_values,
"unknown, type %u",
pdu_type),
fixed_len,
version,
pdu_version,
id_length,
pdu_id_length,
max_area,
pdu_max_area);
if (ndo->ndo_vflag > 1) {
if (!print_unknown_data(ndo, optr, "\n\t", 8)) /* provide the _o_riginal pointer */
return (0); /* for optionally debugging the common header */
}
}
switch (pdu_type) {
case ISIS_PDU_L1_LAN_IIH:
case ISIS_PDU_L2_LAN_IIH:
if (fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE)) {
ND_PRINT(", bogus fixed header length %u should be %zu",
fixed_len, ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE);
return (0);
}
ND_TCHECK_SIZE(header_iih_lan);
if (length < ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE)
goto trunc;
if (ndo->ndo_vflag == 0) {
ND_PRINT(", src-id %s",
isis_print_id(ndo, header_iih_lan->source_id, SYSTEM_ID_LEN));
ND_PRINT(", lan-id %s, prio %u",
isis_print_id(ndo, header_iih_lan->lan_id,NODE_ID_LEN),
GET_U_1(header_iih_lan->priority));
ND_PRINT(", length %u", length);
return (1);
}
pdu_len=GET_BE_U_2(header_iih_lan->pdu_len);
if (packet_len>pdu_len) {
packet_len=pdu_len; /* do TLV decoding as long as it makes sense */
length=pdu_len;
}
ND_PRINT("\n\t source-id: %s, holding time: %us, Flags: [%s]",
isis_print_id(ndo, header_iih_lan->source_id,SYSTEM_ID_LEN),
GET_BE_U_2(header_iih_lan->holding_time),
tok2str(isis_iih_circuit_type_values,
"unknown circuit type 0x%02x",
GET_U_1(header_iih_lan->circuit_type)));
ND_PRINT("\n\t lan-id: %s, Priority: %u, PDU length: %u",
isis_print_id(ndo, header_iih_lan->lan_id, NODE_ID_LEN),
GET_U_1(header_iih_lan->priority) & ISIS_LAN_PRIORITY_MASK,
pdu_len);
if (ndo->ndo_vflag > 1) {
if (!print_unknown_data(ndo, pptr, "\n\t ", ISIS_IIH_LAN_HEADER_SIZE))
return (0);
}
INVALID_OR_DECREMENT(packet_len,ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE);
pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE);
break;
case ISIS_PDU_PTP_IIH:
if (fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE)) {
ND_PRINT(", bogus fixed header length %u should be %zu",
fixed_len, ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE);
return (0);
}
ND_TCHECK_SIZE(header_iih_ptp);
if (length < ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE)
goto trunc;
if (ndo->ndo_vflag == 0) {
ND_PRINT(", src-id %s", isis_print_id(ndo, header_iih_ptp->source_id, SYSTEM_ID_LEN));
ND_PRINT(", length %u", length);
return (1);
}
pdu_len=GET_BE_U_2(header_iih_ptp->pdu_len);
if (packet_len>pdu_len) {
packet_len=pdu_len; /* do TLV decoding as long as it makes sense */
length=pdu_len;
}
ND_PRINT("\n\t source-id: %s, holding time: %us, Flags: [%s]",
isis_print_id(ndo, header_iih_ptp->source_id,SYSTEM_ID_LEN),
GET_BE_U_2(header_iih_ptp->holding_time),
tok2str(isis_iih_circuit_type_values,
"unknown circuit type 0x%02x",
GET_U_1(header_iih_ptp->circuit_type)));
ND_PRINT("\n\t circuit-id: 0x%02x, PDU length: %u",
GET_U_1(header_iih_ptp->circuit_id),
pdu_len);
if (ndo->ndo_vflag > 1) {
if (!print_unknown_data(ndo, pptr, "\n\t ", ISIS_IIH_PTP_HEADER_SIZE))
return (0);
}
INVALID_OR_DECREMENT(packet_len,ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE);
pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE);
break;
case ISIS_PDU_L1_LSP:
case ISIS_PDU_L2_LSP:
if (fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_LSP_HEADER_SIZE)) {
ND_PRINT(", bogus fixed header length %u should be %zu",
fixed_len, ISIS_LSP_HEADER_SIZE);
return (0);
}
ND_TCHECK_SIZE(header_lsp);
if (length < ISIS_COMMON_HEADER_SIZE+ISIS_LSP_HEADER_SIZE)
goto trunc;
if (ndo->ndo_vflag == 0) {
ND_PRINT(", lsp-id %s, seq 0x%08x, lifetime %5us",
isis_print_id(ndo, header_lsp->lsp_id, LSP_ID_LEN),
GET_BE_U_4(header_lsp->sequence_number),
GET_BE_U_2(header_lsp->remaining_lifetime));
ND_PRINT(", length %u", length);
return (1);
}
pdu_len=GET_BE_U_2(header_lsp->pdu_len);
if (packet_len>pdu_len) {
packet_len=pdu_len; /* do TLV decoding as long as it makes sense */
length=pdu_len;
}
ND_PRINT("\n\t lsp-id: %s, seq: 0x%08x, lifetime: %5us\n\t chksum: 0x%04x",
isis_print_id(ndo, header_lsp->lsp_id, LSP_ID_LEN),
GET_BE_U_4(header_lsp->sequence_number),
GET_BE_U_2(header_lsp->remaining_lifetime),
GET_BE_U_2(header_lsp->checksum));
osi_print_cksum(ndo, (const uint8_t *)header_lsp->lsp_id,
GET_BE_U_2(header_lsp->checksum),
12, length-12);
ND_PRINT(", PDU length: %u, Flags: [ %s",
pdu_len,
ISIS_MASK_LSP_OL_BIT(header_lsp->typeblock) ? "Overload bit set, " : "");
if (ISIS_MASK_LSP_ATT_BITS(header_lsp->typeblock)) {
ND_PRINT("%s", ISIS_MASK_LSP_ATT_DEFAULT_BIT(header_lsp->typeblock) ? "default " : "");
ND_PRINT("%s", ISIS_MASK_LSP_ATT_DELAY_BIT(header_lsp->typeblock) ? "delay " : "");
ND_PRINT("%s", ISIS_MASK_LSP_ATT_EXPENSE_BIT(header_lsp->typeblock) ? "expense " : "");
ND_PRINT("%s", ISIS_MASK_LSP_ATT_ERROR_BIT(header_lsp->typeblock) ? "error " : "");
ND_PRINT("ATT bit set, ");
}
ND_PRINT("%s", ISIS_MASK_LSP_PARTITION_BIT(header_lsp->typeblock) ? "P bit set, " : "");
ND_PRINT("%s ]", tok2str(isis_lsp_istype_values, "Unknown(0x%x)",
ISIS_MASK_LSP_ISTYPE_BITS(header_lsp->typeblock)));
if (ndo->ndo_vflag > 1) {
if (!print_unknown_data(ndo, pptr, "\n\t ", ISIS_LSP_HEADER_SIZE))
return (0);
}
INVALID_OR_DECREMENT(packet_len,ISIS_COMMON_HEADER_SIZE+ISIS_LSP_HEADER_SIZE);
pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_LSP_HEADER_SIZE);
break;
case ISIS_PDU_L1_CSNP:
case ISIS_PDU_L2_CSNP:
if (fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE)) {
ND_PRINT(", bogus fixed header length %u should be %zu",
fixed_len, ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE);
return (0);
}
ND_TCHECK_SIZE(header_csnp);
if (length < ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE)
goto trunc;
if (ndo->ndo_vflag == 0) {
ND_PRINT(", src-id %s", isis_print_id(ndo, header_csnp->source_id, NODE_ID_LEN));
ND_PRINT(", length %u", length);
return (1);
}
pdu_len=GET_BE_U_2(header_csnp->pdu_len);
if (packet_len>pdu_len) {
packet_len=pdu_len; /* do TLV decoding as long as it makes sense */
length=pdu_len;
}
ND_PRINT("\n\t source-id: %s, PDU length: %u",
isis_print_id(ndo, header_csnp->source_id, NODE_ID_LEN),
pdu_len);
ND_PRINT("\n\t start lsp-id: %s",
isis_print_id(ndo, header_csnp->start_lsp_id, LSP_ID_LEN));
ND_PRINT("\n\t end lsp-id: %s",
isis_print_id(ndo, header_csnp->end_lsp_id, LSP_ID_LEN));
if (ndo->ndo_vflag > 1) {
if (!print_unknown_data(ndo, pptr, "\n\t ", ISIS_CSNP_HEADER_SIZE))
return (0);
}
INVALID_OR_DECREMENT(packet_len,ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE);
pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE);
break;
case ISIS_PDU_L1_PSNP:
case ISIS_PDU_L2_PSNP:
if (fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE)) {
ND_PRINT("- bogus fixed header length %u should be %zu",
fixed_len, ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE);
return (0);
}
ND_TCHECK_SIZE(header_psnp);
if (length < ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE)
goto trunc;
if (ndo->ndo_vflag == 0) {
ND_PRINT(", src-id %s", isis_print_id(ndo, header_psnp->source_id, NODE_ID_LEN));
ND_PRINT(", length %u", length);
return (1);
}
pdu_len=GET_BE_U_2(header_psnp->pdu_len);
if (packet_len>pdu_len) {
packet_len=pdu_len; /* do TLV decoding as long as it makes sense */
length=pdu_len;
}
ND_PRINT("\n\t source-id: %s, PDU length: %u",
isis_print_id(ndo, header_psnp->source_id, NODE_ID_LEN),
pdu_len);
if (ndo->ndo_vflag > 1) {
if (!print_unknown_data(ndo, pptr, "\n\t ", ISIS_PSNP_HEADER_SIZE))
return (0);
}
INVALID_OR_DECREMENT(packet_len,ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE);
pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE);
break;
default:
if (ndo->ndo_vflag == 0) {
ND_PRINT(", length %u", length);
return (1);
}
(void)print_unknown_data(ndo, pptr, "\n\t ", length);
return (0);
}
/*
* Now print the TLV's.
*/
while (packet_len > 0) {
ND_TCHECK_2(pptr);
if (packet_len < 2)
goto trunc;
tlv_type = GET_U_1(pptr);
tlv_len = GET_U_1(pptr + 1);
pptr += 2;
packet_len -= 2;
tlen = tlv_len; /* copy temporary len & pointer to packet data */
tptr = pptr;
/* first lets see if we know the TLVs name*/
ND_PRINT("\n\t %s TLV #%u, length: %u",
tok2str(isis_tlv_values,
"unknown",
tlv_type),
tlv_type,
tlv_len);
if (packet_len < tlv_len)
goto trunc;
/* now check if we have a decoder otherwise do a hexdump at the end*/
switch (tlv_type) {
case ISIS_TLV_AREA_ADDR:
while (tlen != 0) {
alen = GET_U_1(tptr);
tptr++;
tlen--;
if (tlen < alen)
goto tlv_trunc;
ND_PRINT("\n\t Area address (length: %u): %s",
alen,
GET_ISONSAP_STRING(tptr, alen));
tptr += alen;
tlen -= alen;
}
break;
case ISIS_TLV_ISNEIGH:
while (tlen != 0) {
if (tlen < MAC_ADDR_LEN)
goto tlv_trunc;
ND_TCHECK_LEN(tptr, MAC_ADDR_LEN);
ND_PRINT("\n\t SNPA: %s", isis_print_id(ndo, tptr, MAC_ADDR_LEN));
tlen -= MAC_ADDR_LEN;
tptr += MAC_ADDR_LEN;
}
break;
case ISIS_TLV_INSTANCE_ID:
if (tlen < 4)
goto tlv_trunc;
num_vals = (tlen-2)/2;
ND_PRINT("\n\t Instance ID: %u, ITIDs(%u)%s ",
GET_BE_U_2(tptr), num_vals,
num_vals ? ":" : "");
tptr += 2;
tlen -= 2;
for (i=0; i < num_vals; i++) {
ND_PRINT("%u", GET_BE_U_2(tptr));
if (i < (num_vals - 1)) {
ND_PRINT(", ");
}
tptr += 2;
tlen -= 2;
}
break;
case ISIS_TLV_PADDING:
break;
case ISIS_TLV_MT_IS_REACH:
mt_len = isis_print_mtid(ndo, tptr, "\n\t ", tlen);
if (mt_len == 0) /* did something go wrong ? */
goto trunc;
tptr+=mt_len;
tlen-=mt_len;
while (tlen != 0) {
ext_is_len = isis_print_ext_is_reach(ndo, tptr, "\n\t ", tlv_type, tlen);
if (ext_is_len == 0) /* did something go wrong ? */
goto trunc;
if (tlen < ext_is_len) {
ND_PRINT(" [remaining tlv length %u < %u]", tlen, ext_is_len);
nd_print_invalid(ndo);
break;
}
tlen-=(uint8_t)ext_is_len;
tptr+=(uint8_t)ext_is_len;
}
break;
case ISIS_TLV_IS_ALIAS_ID:
while (tlen != 0) {
ext_is_len = isis_print_ext_is_reach(ndo, tptr, "\n\t ", tlv_type, tlen);
if (ext_is_len == 0) /* did something go wrong ? */
goto trunc;
if (tlen < ext_is_len) {
ND_PRINT(" [remaining tlv length %u < %u]", tlen, ext_is_len);
nd_print_invalid(ndo);
break;
}
tlen-=(uint8_t)ext_is_len;
tptr+=(uint8_t)ext_is_len;
}
break;
case ISIS_TLV_EXT_IS_REACH:
while (tlen != 0) {
ext_is_len = isis_print_ext_is_reach(ndo, tptr, "\n\t ", tlv_type, tlen);
if (ext_is_len == 0) /* did something go wrong ? */
goto trunc;
if (tlen < ext_is_len) {
ND_PRINT(" [remaining tlv length %u < %u]", tlen, ext_is_len);
nd_print_invalid(ndo);
break;
}
tlen-=(uint8_t)ext_is_len;
tptr+=(uint8_t)ext_is_len;
}
break;
case ISIS_TLV_IS_REACH:
if (tlen < 1)
goto tlv_trunc;
ND_PRINT("\n\t %s",
tok2str(isis_is_reach_virtual_values,
"bogus virtual flag 0x%02x",
GET_U_1(tptr)));
tptr++;
tlen--;
tlv_is_reach = (const struct isis_tlv_is_reach *)tptr;
while (tlen != 0) {
if (tlen < sizeof(struct isis_tlv_is_reach))
goto tlv_trunc;
ND_TCHECK_SIZE(tlv_is_reach);
ND_PRINT("\n\t IS Neighbor: %s",
isis_print_id(ndo, tlv_is_reach->neighbor_nodeid, NODE_ID_LEN));
isis_print_metric_block(ndo, &tlv_is_reach->isis_metric_block);
tlen -= sizeof(struct isis_tlv_is_reach);
tlv_is_reach++;
}
break;
case ISIS_TLV_ESNEIGH:
tlv_es_reach = (const struct isis_tlv_es_reach *)tptr;
while (tlen != 0) {
if (tlen < sizeof(struct isis_tlv_es_reach))
goto tlv_trunc;
ND_TCHECK_SIZE(tlv_es_reach);
ND_PRINT("\n\t ES Neighbor: %s",
isis_print_id(ndo, tlv_es_reach->neighbor_sysid, SYSTEM_ID_LEN));
isis_print_metric_block(ndo, &tlv_es_reach->isis_metric_block);
tlen -= sizeof(struct isis_tlv_es_reach);
tlv_es_reach++;
}
break;
/* those two TLVs share the same format */
case ISIS_TLV_INT_IP_REACH:
case ISIS_TLV_EXT_IP_REACH:
if (!isis_print_tlv_ip_reach(ndo, pptr, "\n\t ", tlv_len))
return (1);
break;
case ISIS_TLV_EXTD_IP_REACH:
while (tlen != 0) {
ext_ip_len = isis_print_extd_ip_reach(ndo, tptr, "\n\t ", AF_INET);
if (ext_ip_len == 0) /* did something go wrong ? */
goto trunc;
if (tlen < ext_ip_len) {
ND_PRINT(" [remaining tlv length %u < %u]", tlen, ext_ip_len);
nd_print_invalid(ndo);
break;
}
tlen-=(uint8_t)ext_ip_len;
tptr+=(uint8_t)ext_ip_len;
}
break;
case ISIS_TLV_MT_IP_REACH:
mt_len = isis_print_mtid(ndo, tptr, "\n\t ", tlen);
if (mt_len == 0) { /* did something go wrong ? */
goto trunc;
}
tptr+=mt_len;
tlen-=mt_len;
while (tlen != 0) {
ext_ip_len = isis_print_extd_ip_reach(ndo, tptr, "\n\t ", AF_INET);
if (ext_ip_len == 0) /* did something go wrong ? */
goto trunc;
if (tlen < ext_ip_len) {
ND_PRINT(" [remaining tlv length %u < %u]", tlen, ext_ip_len);
nd_print_invalid(ndo);
break;
}
tlen-=(uint8_t)ext_ip_len;
tptr+=(uint8_t)ext_ip_len;
}
break;
case ISIS_TLV_IP6_REACH:
while (tlen != 0) {
ext_ip_len = isis_print_extd_ip_reach(ndo, tptr, "\n\t ", AF_INET6);
if (ext_ip_len == 0) /* did something go wrong ? */
goto trunc;
if (tlen < ext_ip_len) {
ND_PRINT(" [remaining tlv length %u < %u]", tlen, ext_ip_len);
nd_print_invalid(ndo);
break;
}
tlen-=(uint8_t)ext_ip_len;
tptr+=(uint8_t)ext_ip_len;
}
break;
case ISIS_TLV_MT_IP6_REACH:
mt_len = isis_print_mtid(ndo, tptr, "\n\t ", tlen);
if (mt_len == 0) { /* did something go wrong ? */
goto trunc;
}
tptr+=mt_len;
tlen-=mt_len;
while (tlen != 0) {
ext_ip_len = isis_print_extd_ip_reach(ndo, tptr, "\n\t ", AF_INET6);
if (ext_ip_len == 0) /* did something go wrong ? */
goto trunc;
if (tlen < ext_ip_len) {
ND_PRINT(" [remaining tlv length %u < %u]", tlen, ext_ip_len);
nd_print_invalid(ndo);
break;
}
tlen-=(uint8_t)ext_ip_len;
tptr+=(uint8_t)ext_ip_len;
}
break;
case ISIS_TLV_IP6ADDR:
while (tlen != 0) {
if (tlen < sizeof(nd_ipv6))
goto tlv_trunc;
ND_PRINT("\n\t IPv6 interface address: %s",
GET_IP6ADDR_STRING(tptr));
tptr += sizeof(nd_ipv6);
tlen -= sizeof(nd_ipv6);
}
break;
case ISIS_TLV_AUTH:
if (tlen < 1)
goto tlv_trunc;
auth_type = GET_U_1(tptr);
tptr++;
tlen--;
ND_PRINT("\n\t %s: ",
tok2str(isis_subtlv_auth_values,
"unknown Authentication type 0x%02x",
auth_type));
switch (auth_type) {
case ISIS_SUBTLV_AUTH_SIMPLE:
nd_printjnp(ndo, tptr, tlen);
break;
case ISIS_SUBTLV_AUTH_MD5:
for(i=0;i<tlen;i++) {
ND_PRINT("%02x", GET_U_1(tptr + i));
}
if (tlen != ISIS_SUBTLV_AUTH_MD5_LEN)
ND_PRINT(", (invalid subTLV) ");
sigcheck = signature_verify(ndo, optr, length, tptr,
isis_clear_checksum_lifetime,
header_lsp);
ND_PRINT(" (%s)", tok2str(signature_check_values, "Unknown", sigcheck));
break;
case ISIS_SUBTLV_AUTH_GENERIC:
if (tlen < 2)
goto tlv_trunc;
key_id = GET_BE_U_2(tptr);
ND_PRINT("%u, password: ", key_id);
tptr += 2;
tlen -= 2;
for(i=0;i<tlen;i++) {
ND_PRINT("%02x", GET_U_1(tptr + i));
}
break;
case ISIS_SUBTLV_AUTH_PRIVATE:
default:
if (!print_unknown_data(ndo, tptr, "\n\t\t ", tlen))
return(0);
break;
}
break;
case ISIS_TLV_PTP_ADJ:
tlv_ptp_adj = (const struct isis_tlv_ptp_adj *)tptr;
if(tlen>=1) {
ND_PRINT("\n\t Adjacency State: %s (%u)",
- tok2str(isis_ptp_adjancey_values, "unknown", GET_U_1(tptr)),
+ tok2str(isis_ptp_adjacency_values, "unknown", GET_U_1(tptr)),
GET_U_1(tptr));
tlen--;
}
if(tlen>sizeof(tlv_ptp_adj->extd_local_circuit_id)) {
ND_PRINT("\n\t Extended Local circuit-ID: 0x%08x",
GET_BE_U_4(tlv_ptp_adj->extd_local_circuit_id));
tlen-=sizeof(tlv_ptp_adj->extd_local_circuit_id);
}
if(tlen>=SYSTEM_ID_LEN) {
ND_TCHECK_LEN(tlv_ptp_adj->neighbor_sysid, SYSTEM_ID_LEN);
ND_PRINT("\n\t Neighbor System-ID: %s",
isis_print_id(ndo, tlv_ptp_adj->neighbor_sysid, SYSTEM_ID_LEN));
tlen-=SYSTEM_ID_LEN;
}
if(tlen>=sizeof(tlv_ptp_adj->neighbor_extd_local_circuit_id)) {
ND_PRINT("\n\t Neighbor Extended Local circuit-ID: 0x%08x",
GET_BE_U_4(tlv_ptp_adj->neighbor_extd_local_circuit_id));
}
break;
case ISIS_TLV_PROTOCOLS:
ND_PRINT("\n\t NLPID(s): ");
while (tlen != 0) {
ND_PRINT("%s (0x%02x)",
tok2str(nlpid_values,
"unknown",
GET_U_1(tptr)),
GET_U_1(tptr));
if (tlen>1) /* further NPLIDs ? - put comma */
ND_PRINT(", ");
tptr++;
tlen--;
}
break;
case ISIS_TLV_MT_PORT_CAP:
{
if (tlen < 2)
goto tlv_trunc;
ND_PRINT("\n\t RES: %u, MTID(s): %u",
(GET_BE_U_2(tptr) >> 12),
(GET_BE_U_2(tptr) & 0x0fff));
tptr += 2;
tlen -= 2;
if (tlen)
isis_print_mt_port_cap_subtlv(ndo, tptr, tlen);
break;
}
case ISIS_TLV_MT_CAPABILITY:
if (tlen < 2)
goto tlv_trunc;
ND_PRINT("\n\t O: %u, RES: %u, MTID(s): %u",
(GET_BE_U_2(tptr) >> 15) & 0x01,
(GET_BE_U_2(tptr) >> 12) & 0x07,
GET_BE_U_2(tptr) & 0x0fff);
tptr += 2;
tlen -= 2;
if (tlen)
isis_print_mt_capability_subtlv(ndo, tptr, tlen);
break;
case ISIS_TLV_TE_ROUTER_ID:
if (tlen < sizeof(nd_ipv4))
goto tlv_trunc;
ND_PRINT("\n\t Traffic Engineering Router ID: %s", GET_IPADDR_STRING(pptr));
break;
case ISIS_TLV_IPADDR:
while (tlen != 0) {
if (tlen < sizeof(nd_ipv4))
goto tlv_trunc;
ND_PRINT("\n\t IPv4 interface address: %s", GET_IPADDR_STRING(tptr));
tptr += sizeof(nd_ipv4);
tlen -= sizeof(nd_ipv4);
}
break;
case ISIS_TLV_HOSTNAME:
ND_PRINT("\n\t Hostname: ");
nd_printjnp(ndo, tptr, tlen);
break;
case ISIS_TLV_SHARED_RISK_GROUP:
if (tlen < NODE_ID_LEN)
break;
ND_TCHECK_LEN(tptr, NODE_ID_LEN);
ND_PRINT("\n\t IS Neighbor: %s", isis_print_id(ndo, tptr, NODE_ID_LEN));
tptr+=NODE_ID_LEN;
tlen-=NODE_ID_LEN;
if (tlen < 1)
break;
ND_PRINT(", Flags: [%s]",
ISIS_MASK_TLV_SHARED_RISK_GROUP(GET_U_1(tptr)) ? "numbered" : "unnumbered");
tptr++;
tlen--;
if (tlen < sizeof(nd_ipv4))
break;
ND_PRINT("\n\t IPv4 interface address: %s", GET_IPADDR_STRING(tptr));
tptr+=sizeof(nd_ipv4);
tlen-=sizeof(nd_ipv4);
if (tlen < sizeof(nd_ipv4))
break;
ND_PRINT("\n\t IPv4 neighbor address: %s", GET_IPADDR_STRING(tptr));
tptr+=sizeof(nd_ipv4);
tlen-=sizeof(nd_ipv4);
while (tlen != 0) {
if (tlen < 4)
goto tlv_trunc;
ND_PRINT("\n\t Link-ID: 0x%08x", GET_BE_U_4(tptr));
tptr+=4;
tlen-=4;
}
break;
case ISIS_TLV_LSP:
tlv_lsp = (const struct isis_tlv_lsp *)tptr;
while (tlen != 0) {
if (tlen < sizeof(struct isis_tlv_lsp))
goto tlv_trunc;
ND_TCHECK_1(tlv_lsp->lsp_id + LSP_ID_LEN - 1);
ND_PRINT("\n\t lsp-id: %s",
isis_print_id(ndo, tlv_lsp->lsp_id, LSP_ID_LEN));
ND_PRINT(", seq: 0x%08x",
GET_BE_U_4(tlv_lsp->sequence_number));
ND_PRINT(", lifetime: %5ds",
GET_BE_U_2(tlv_lsp->remaining_lifetime));
ND_PRINT(", chksum: 0x%04x", GET_BE_U_2(tlv_lsp->checksum));
tlen-=sizeof(struct isis_tlv_lsp);
tlv_lsp++;
}
break;
case ISIS_TLV_CHECKSUM:
if (tlen < ISIS_TLV_CHECKSUM_MINLEN)
break;
ND_TCHECK_LEN(tptr, ISIS_TLV_CHECKSUM_MINLEN);
ND_PRINT("\n\t checksum: 0x%04x ", GET_BE_U_2(tptr));
/* do not attempt to verify the checksum if it is zero
* most likely a HMAC-MD5 TLV is also present and
* to avoid conflicts the checksum TLV is zeroed.
* see rfc3358 for details
*/
osi_print_cksum(ndo, optr, GET_BE_U_2(tptr), (int)(tptr-optr),
length);
break;
case ISIS_TLV_POI:
if (tlen < 1)
goto tlv_trunc;
num_system_ids = GET_U_1(tptr);
tptr++;
tlen--;
if (num_system_ids == 0) {
/* Not valid */
ND_PRINT(" No system IDs supplied");
} else {
if (tlen < SYSTEM_ID_LEN)
goto tlv_trunc;
ND_TCHECK_LEN(tptr, SYSTEM_ID_LEN);
ND_PRINT("\n\t Purge Originator System-ID: %s",
isis_print_id(ndo, tptr, SYSTEM_ID_LEN));
tptr += SYSTEM_ID_LEN;
tlen -= SYSTEM_ID_LEN;
if (num_system_ids > 1) {
if (tlen < SYSTEM_ID_LEN)
goto tlv_trunc;
ND_TCHECK_LEN(tptr, SYSTEM_ID_LEN);
ND_TCHECK_LEN(tptr, 2 * SYSTEM_ID_LEN + 1);
ND_PRINT("\n\t Received from System-ID: %s",
isis_print_id(ndo, tptr, SYSTEM_ID_LEN));
}
}
break;
case ISIS_TLV_MT_SUPPORTED:
while (tlen != 0) {
/* length can only be a multiple of 2, otherwise there is
something broken -> so decode down until length is 1 */
if (tlen!=1) {
mt_len = isis_print_mtid(ndo, tptr, "\n\t ", tlen);
if (mt_len == 0) /* did something go wrong ? */
goto trunc;
tptr+=mt_len;
tlen-=mt_len;
} else {
ND_PRINT("\n\t invalid MT-ID");
break;
}
}
break;
case ISIS_TLV_RESTART_SIGNALING:
/* first attempt to decode the flags */
if (tlen < ISIS_TLV_RESTART_SIGNALING_FLAGLEN)
break;
ND_TCHECK_LEN(tptr, ISIS_TLV_RESTART_SIGNALING_FLAGLEN);
ND_PRINT("\n\t Flags [%s]",
bittok2str(isis_restart_flag_values, "none", GET_U_1(tptr)));
tptr+=ISIS_TLV_RESTART_SIGNALING_FLAGLEN;
tlen-=ISIS_TLV_RESTART_SIGNALING_FLAGLEN;
/* is there anything other than the flags field? */
if (tlen == 0)
break;
if (tlen < ISIS_TLV_RESTART_SIGNALING_HOLDTIMELEN)
break;
ND_TCHECK_LEN(tptr, ISIS_TLV_RESTART_SIGNALING_HOLDTIMELEN);
ND_PRINT(", Remaining holding time %us", GET_BE_U_2(tptr));
tptr+=ISIS_TLV_RESTART_SIGNALING_HOLDTIMELEN;
tlen-=ISIS_TLV_RESTART_SIGNALING_HOLDTIMELEN;
/* is there an additional sysid field present ?*/
if (tlen == SYSTEM_ID_LEN) {
ND_TCHECK_LEN(tptr, SYSTEM_ID_LEN);
ND_PRINT(", for %s", isis_print_id(ndo, tptr,SYSTEM_ID_LEN));
}
break;
case ISIS_TLV_IDRP_INFO:
if (tlen < 1)
break;
isis_subtlv_idrp = GET_U_1(tptr);
ND_PRINT("\n\t Inter-Domain Information Type: %s",
tok2str(isis_subtlv_idrp_values,
"Unknown (0x%02x)",
isis_subtlv_idrp));
tptr++;
tlen--;
switch (isis_subtlv_idrp) {
case ISIS_SUBTLV_IDRP_ASN:
if (tlen < 2)
goto tlv_trunc;
ND_PRINT("AS Number: %u", GET_BE_U_2(tptr));
break;
case ISIS_SUBTLV_IDRP_LOCAL:
case ISIS_SUBTLV_IDRP_RES:
default:
if (!print_unknown_data(ndo, tptr, "\n\t ", tlen))
return(0);
break;
}
break;
case ISIS_TLV_LSP_BUFFERSIZE:
if (tlen < 2)
break;
ND_PRINT("\n\t LSP Buffersize: %u", GET_BE_U_2(tptr));
break;
case ISIS_TLV_PART_DIS:
while (tlen != 0) {
if (tlen < SYSTEM_ID_LEN)
goto tlv_trunc;
ND_TCHECK_LEN(tptr, SYSTEM_ID_LEN);
ND_PRINT("\n\t %s", isis_print_id(ndo, tptr, SYSTEM_ID_LEN));
tptr+=SYSTEM_ID_LEN;
tlen-=SYSTEM_ID_LEN;
}
break;
case ISIS_TLV_PREFIX_NEIGH:
if (tlen < sizeof(struct isis_metric_block))
break;
ND_TCHECK_LEN(tptr, sizeof(struct isis_metric_block));
ND_PRINT("\n\t Metric Block");
isis_print_metric_block(ndo, (const struct isis_metric_block *)tptr);
tptr+=sizeof(struct isis_metric_block);
tlen-=sizeof(struct isis_metric_block);
while (tlen != 0) {
prefix_len=GET_U_1(tptr); /* read out prefix length in semioctets*/
tptr++;
tlen--;
if (prefix_len < 2) {
ND_PRINT("\n\t\tAddress: prefix length %u < 2", prefix_len);
break;
}
if (tlen < prefix_len/2)
break;
ND_PRINT("\n\t\tAddress: %s/%u",
GET_ISONSAP_STRING(tptr, prefix_len / 2), prefix_len * 4);
tptr+=prefix_len/2;
tlen-=prefix_len/2;
}
break;
case ISIS_TLV_IIH_SEQNR:
if (tlen < 4)
break;
ND_PRINT("\n\t Sequence number: %u", GET_BE_U_4(tptr));
break;
case ISIS_TLV_ROUTER_CAPABILITY:
if (tlen < 5) {
ND_PRINT(" [object length %u < 5]", tlen);
nd_print_invalid(ndo);
break;
}
ND_PRINT("\n\t Router-ID %s", GET_IPADDR_STRING(tptr));
ND_PRINT(", Flags [%s]",
bittok2str(isis_tlv_router_capability_flags, "none", GET_U_1(tptr+4)));
/* Optional set of sub-TLV */
if (tlen > 5) {
isis_print_router_cap_subtlv(ndo, tptr+5, tlen-5);
}
break;
case ISIS_TLV_VENDOR_PRIVATE:
if (tlen < 3)
break;
vendor_id = GET_BE_U_3(tptr);
ND_PRINT("\n\t Vendor: %s (%u)",
tok2str(oui_values, "Unknown", vendor_id),
vendor_id);
tptr+=3;
tlen-=3;
if (tlen != 0) /* hexdump the rest */
if (!print_unknown_data(ndo, tptr, "\n\t\t", tlen))
return(0);
break;
/*
* FIXME those are the defined TLVs that lack a decoder
* you are welcome to contribute code ;-)
*/
case ISIS_TLV_DECNET_PHASE4:
case ISIS_TLV_LUCENT_PRIVATE:
case ISIS_TLV_IPAUTH:
case ISIS_TLV_NORTEL_PRIVATE1:
case ISIS_TLV_NORTEL_PRIVATE2:
default:
if (ndo->ndo_vflag <= 1) {
if (!print_unknown_data(ndo, pptr, "\n\t\t", tlv_len))
return(0);
}
break;
}
tlv_trunc:
/* do we want to see an additionally hexdump ? */
if (ndo->ndo_vflag> 1) {
if (!print_unknown_data(ndo, pptr, "\n\t ", tlv_len))
return(0);
}
pptr += tlv_len;
packet_len -= tlv_len;
}
if (packet_len != 0) {
ND_PRINT("\n\t %u straggler bytes", packet_len);
}
return (1);
trunc:
nd_print_trunc(ndo);
return (1);
}
static void
osi_print_cksum(netdissect_options *ndo, const uint8_t *pptr,
uint16_t checksum, int checksum_offset, u_int length)
{
uint16_t calculated_checksum;
/* do not attempt to verify the checksum if it is zero,
* if the offset is nonsense,
* or the base pointer is not sane
*/
if (!checksum
|| checksum_offset < 0
|| !ND_TTEST_2(pptr + checksum_offset)
|| (u_int)checksum_offset > length
|| !ND_TTEST_LEN(pptr, length)) {
ND_PRINT(" (unverified)");
} else {
#if 0
ND_PRINT("\nosi_print_cksum: %p %d %u\n", pptr, checksum_offset, length);
#endif
calculated_checksum = create_osi_cksum(pptr, checksum_offset, length);
if (checksum == calculated_checksum) {
ND_PRINT(" (correct)");
} else {
ND_PRINT(" (incorrect should be 0x%04x)", calculated_checksum);
}
}
}
diff --git a/contrib/tcpdump/print-juniper.c b/contrib/tcpdump/print-juniper.c
index 2fc0b5537e4a..f2d5c75977a0 100644
--- a/contrib/tcpdump/print-juniper.c
+++ b/contrib/tcpdump/print-juniper.c
@@ -1,1626 +1,1625 @@
/* NetBSD: print-juniper.c,v 1.2 2007/07/24 11:53:45 drochner Exp */
/*
* 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.
*
* Original code by Hannes Gredler (hannes@gredler.at)
*/
/* \summary: DLT_JUNIPER_* printers */
#ifndef lint
#else
__RCSID("NetBSD: print-juniper.c,v 1.3 2007/07/25 06:31:32 dogcow Exp ");
#endif
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <string.h>
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#include "ppp.h"
#include "llc.h"
#include "nlpid.h"
#include "ethertype.h"
#include "atm.h"
/*
* If none of the Juniper DLT_s are defined, there's nothing to do.
*/
#if defined(DLT_JUNIPER_GGSN) || defined(DLT_JUNIPER_ES) || \
defined(DLT_JUNIPER_MONITOR) || defined(DLT_JUNIPER_SERVICES) || \
defined(DLT_JUNIPER_PPPOE) || defined(DLT_JUNIPER_ETHER) || \
defined(DLT_JUNIPER_PPP) || defined(DLT_JUNIPER_FRELAY) || \
defined(DLT_JUNIPER_CHDLC) || defined(DLT_JUNIPER_PPPOE_ATM) || \
defined(DLT_JUNIPER_MLPPP) || defined(DLT_JUNIPER_MFR) || \
defined(DLT_JUNIPER_MLFR) || defined(DLT_JUNIPER_ATM1) || \
defined(DLT_JUNIPER_ATM2)
#define JUNIPER_BPF_OUT 0 /* Outgoing packet */
#define JUNIPER_BPF_IN 1 /* Incoming packet */
#define JUNIPER_BPF_PKT_IN 0x1 /* Incoming packet */
#define JUNIPER_BPF_NO_L2 0x2 /* L2 header stripped */
#define JUNIPER_BPF_IIF 0x4 /* IIF is valid */
#define JUNIPER_BPF_FILTER 0x40 /* BPF filtering is supported */
#define JUNIPER_BPF_EXT 0x80 /* extensions present */
#define JUNIPER_MGC_NUMBER 0x4d4743 /* = "MGC" */
#define JUNIPER_LSQ_COOKIE_RE (1 << 3)
#define JUNIPER_LSQ_COOKIE_DIR (1 << 2)
#define JUNIPER_LSQ_L3_PROTO_SHIFT 4
#define JUNIPER_LSQ_L3_PROTO_MASK (0x17 << JUNIPER_LSQ_L3_PROTO_SHIFT)
#define JUNIPER_LSQ_L3_PROTO_IPV4 (0 << JUNIPER_LSQ_L3_PROTO_SHIFT)
#define JUNIPER_LSQ_L3_PROTO_IPV6 (1 << JUNIPER_LSQ_L3_PROTO_SHIFT)
#define JUNIPER_LSQ_L3_PROTO_MPLS (2 << JUNIPER_LSQ_L3_PROTO_SHIFT)
#define JUNIPER_LSQ_L3_PROTO_ISO (3 << JUNIPER_LSQ_L3_PROTO_SHIFT)
#define AS_PIC_COOKIE_LEN 8
#define JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE 1
#define JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE 2
#define JUNIPER_IPSEC_O_ESP_AUTHENTICATION_TYPE 3
#define JUNIPER_IPSEC_O_AH_AUTHENTICATION_TYPE 4
#define JUNIPER_IPSEC_O_ESP_ENCRYPTION_TYPE 5
#ifdef DLT_JUNIPER_ES
static const struct tok juniper_ipsec_type_values[] = {
{ JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE, "ESP ENCR-AUTH" },
{ JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE, "ESP ENCR-AH AUTH" },
{ JUNIPER_IPSEC_O_ESP_AUTHENTICATION_TYPE, "ESP AUTH" },
{ JUNIPER_IPSEC_O_AH_AUTHENTICATION_TYPE, "AH AUTH" },
{ JUNIPER_IPSEC_O_ESP_ENCRYPTION_TYPE, "ESP ENCR" },
{ 0, NULL}
};
#endif
static const struct tok juniper_direction_values[] = {
{ JUNIPER_BPF_IN, "In"},
{ JUNIPER_BPF_OUT, "Out"},
{ 0, NULL}
};
/* codepoints for encoding extensions to a .pcap file */
enum {
JUNIPER_EXT_TLV_IFD_IDX = 1,
JUNIPER_EXT_TLV_IFD_NAME = 2,
JUNIPER_EXT_TLV_IFD_MEDIATYPE = 3,
JUNIPER_EXT_TLV_IFL_IDX = 4,
JUNIPER_EXT_TLV_IFL_UNIT = 5,
JUNIPER_EXT_TLV_IFL_ENCAPS = 6,
JUNIPER_EXT_TLV_TTP_IFD_MEDIATYPE = 7,
JUNIPER_EXT_TLV_TTP_IFL_ENCAPS = 8
};
/* 1 byte type and 1-byte length */
#define JUNIPER_EXT_TLV_OVERHEAD 2U
static const struct tok jnx_ext_tlv_values[] = {
{ JUNIPER_EXT_TLV_IFD_IDX, "Device Interface Index" },
{ JUNIPER_EXT_TLV_IFD_NAME,"Device Interface Name" },
{ JUNIPER_EXT_TLV_IFD_MEDIATYPE, "Device Media Type" },
{ JUNIPER_EXT_TLV_IFL_IDX, "Logical Interface Index" },
{ JUNIPER_EXT_TLV_IFL_UNIT,"Logical Unit Number" },
{ JUNIPER_EXT_TLV_IFL_ENCAPS, "Logical Interface Encapsulation" },
{ JUNIPER_EXT_TLV_TTP_IFD_MEDIATYPE, "TTP derived Device Media Type" },
{ JUNIPER_EXT_TLV_TTP_IFL_ENCAPS, "TTP derived Logical Interface Encapsulation" },
{ 0, NULL }
};
static const struct tok jnx_flag_values[] = {
{ JUNIPER_BPF_EXT, "Ext" },
{ JUNIPER_BPF_FILTER, "Filter" },
{ JUNIPER_BPF_IIF, "IIF" },
{ JUNIPER_BPF_NO_L2, "no-L2" },
{ JUNIPER_BPF_PKT_IN, "In" },
{ 0, NULL }
};
#define JUNIPER_IFML_ETHER 1
#define JUNIPER_IFML_FDDI 2
#define JUNIPER_IFML_TOKENRING 3
#define JUNIPER_IFML_PPP 4
#define JUNIPER_IFML_FRAMERELAY 5
#define JUNIPER_IFML_CISCOHDLC 6
#define JUNIPER_IFML_SMDSDXI 7
#define JUNIPER_IFML_ATMPVC 8
#define JUNIPER_IFML_PPP_CCC 9
#define JUNIPER_IFML_FRAMERELAY_CCC 10
#define JUNIPER_IFML_IPIP 11
#define JUNIPER_IFML_GRE 12
#define JUNIPER_IFML_PIM 13
#define JUNIPER_IFML_PIMD 14
#define JUNIPER_IFML_CISCOHDLC_CCC 15
#define JUNIPER_IFML_VLAN_CCC 16
#define JUNIPER_IFML_MLPPP 17
#define JUNIPER_IFML_MLFR 18
#define JUNIPER_IFML_ML 19
#define JUNIPER_IFML_LSI 20
#define JUNIPER_IFML_DFE 21
#define JUNIPER_IFML_ATM_CELLRELAY_CCC 22
#define JUNIPER_IFML_CRYPTO 23
#define JUNIPER_IFML_GGSN 24
#define JUNIPER_IFML_LSI_PPP 25
#define JUNIPER_IFML_LSI_CISCOHDLC 26
#define JUNIPER_IFML_PPP_TCC 27
#define JUNIPER_IFML_FRAMERELAY_TCC 28
#define JUNIPER_IFML_CISCOHDLC_TCC 29
#define JUNIPER_IFML_ETHERNET_CCC 30
#define JUNIPER_IFML_VT 31
#define JUNIPER_IFML_EXTENDED_VLAN_CCC 32
#define JUNIPER_IFML_ETHER_OVER_ATM 33
#define JUNIPER_IFML_MONITOR 34
#define JUNIPER_IFML_ETHERNET_TCC 35
#define JUNIPER_IFML_VLAN_TCC 36
#define JUNIPER_IFML_EXTENDED_VLAN_TCC 37
#define JUNIPER_IFML_CONTROLLER 38
#define JUNIPER_IFML_MFR 39
#define JUNIPER_IFML_LS 40
#define JUNIPER_IFML_ETHERNET_VPLS 41
#define JUNIPER_IFML_ETHERNET_VLAN_VPLS 42
#define JUNIPER_IFML_ETHERNET_EXTENDED_VLAN_VPLS 43
#define JUNIPER_IFML_LT 44
#define JUNIPER_IFML_SERVICES 45
#define JUNIPER_IFML_ETHER_VPLS_OVER_ATM 46
#define JUNIPER_IFML_FR_PORT_CCC 47
#define JUNIPER_IFML_FRAMERELAY_EXT_CCC 48
#define JUNIPER_IFML_FRAMERELAY_EXT_TCC 49
#define JUNIPER_IFML_FRAMERELAY_FLEX 50
#define JUNIPER_IFML_GGSNI 51
#define JUNIPER_IFML_ETHERNET_FLEX 52
#define JUNIPER_IFML_COLLECTOR 53
#define JUNIPER_IFML_AGGREGATOR 54
#define JUNIPER_IFML_LAPD 55
#define JUNIPER_IFML_PPPOE 56
#define JUNIPER_IFML_PPP_SUBORDINATE 57
#define JUNIPER_IFML_CISCOHDLC_SUBORDINATE 58
#define JUNIPER_IFML_DFC 59
#define JUNIPER_IFML_PICPEER 60
static const struct tok juniper_ifmt_values[] = {
{ JUNIPER_IFML_ETHER, "Ethernet" },
{ JUNIPER_IFML_FDDI, "FDDI" },
{ JUNIPER_IFML_TOKENRING, "Token-Ring" },
{ JUNIPER_IFML_PPP, "PPP" },
{ JUNIPER_IFML_PPP_SUBORDINATE, "PPP-Subordinate" },
{ JUNIPER_IFML_FRAMERELAY, "Frame-Relay" },
{ JUNIPER_IFML_CISCOHDLC, "Cisco-HDLC" },
{ JUNIPER_IFML_SMDSDXI, "SMDS-DXI" },
{ JUNIPER_IFML_ATMPVC, "ATM-PVC" },
{ JUNIPER_IFML_PPP_CCC, "PPP-CCC" },
{ JUNIPER_IFML_FRAMERELAY_CCC, "Frame-Relay-CCC" },
{ JUNIPER_IFML_FRAMERELAY_EXT_CCC, "Extended FR-CCC" },
{ JUNIPER_IFML_IPIP, "IP-over-IP" },
{ JUNIPER_IFML_GRE, "GRE" },
{ JUNIPER_IFML_PIM, "PIM-Encapsulator" },
{ JUNIPER_IFML_PIMD, "PIM-Decapsulator" },
{ JUNIPER_IFML_CISCOHDLC_CCC, "Cisco-HDLC-CCC" },
{ JUNIPER_IFML_VLAN_CCC, "VLAN-CCC" },
{ JUNIPER_IFML_EXTENDED_VLAN_CCC, "Extended-VLAN-CCC" },
{ JUNIPER_IFML_MLPPP, "Multilink-PPP" },
{ JUNIPER_IFML_MLFR, "Multilink-FR" },
{ JUNIPER_IFML_MFR, "Multilink-FR-UNI-NNI" },
{ JUNIPER_IFML_ML, "Multilink" },
{ JUNIPER_IFML_LS, "LinkService" },
{ JUNIPER_IFML_LSI, "LSI" },
{ JUNIPER_IFML_ATM_CELLRELAY_CCC, "ATM-CCC-Cell-Relay" },
{ JUNIPER_IFML_CRYPTO, "IPSEC-over-IP" },
{ JUNIPER_IFML_GGSN, "GGSN" },
{ JUNIPER_IFML_PPP_TCC, "PPP-TCC" },
{ JUNIPER_IFML_FRAMERELAY_TCC, "Frame-Relay-TCC" },
{ JUNIPER_IFML_FRAMERELAY_EXT_TCC, "Extended FR-TCC" },
{ JUNIPER_IFML_CISCOHDLC_TCC, "Cisco-HDLC-TCC" },
{ JUNIPER_IFML_ETHERNET_CCC, "Ethernet-CCC" },
{ JUNIPER_IFML_VT, "VPN-Loopback-tunnel" },
{ JUNIPER_IFML_ETHER_OVER_ATM, "Ethernet-over-ATM" },
{ JUNIPER_IFML_ETHER_VPLS_OVER_ATM, "Ethernet-VPLS-over-ATM" },
{ JUNIPER_IFML_MONITOR, "Monitor" },
{ JUNIPER_IFML_ETHERNET_TCC, "Ethernet-TCC" },
{ JUNIPER_IFML_VLAN_TCC, "VLAN-TCC" },
{ JUNIPER_IFML_EXTENDED_VLAN_TCC, "Extended-VLAN-TCC" },
{ JUNIPER_IFML_CONTROLLER, "Controller" },
{ JUNIPER_IFML_ETHERNET_VPLS, "VPLS" },
{ JUNIPER_IFML_ETHERNET_VLAN_VPLS, "VLAN-VPLS" },
{ JUNIPER_IFML_ETHERNET_EXTENDED_VLAN_VPLS, "Extended-VLAN-VPLS" },
{ JUNIPER_IFML_LT, "Logical-tunnel" },
{ JUNIPER_IFML_SERVICES, "General-Services" },
{ JUNIPER_IFML_PPPOE, "PPPoE" },
{ JUNIPER_IFML_ETHERNET_FLEX, "Flexible-Ethernet-Services" },
{ JUNIPER_IFML_FRAMERELAY_FLEX, "Flexible-FrameRelay" },
{ JUNIPER_IFML_COLLECTOR, "Flow-collection" },
{ JUNIPER_IFML_PICPEER, "PIC Peer" },
{ JUNIPER_IFML_DFC, "Dynamic-Flow-Capture" },
{0, NULL}
};
#define JUNIPER_IFLE_ATM_SNAP 2
#define JUNIPER_IFLE_ATM_NLPID 3
#define JUNIPER_IFLE_ATM_VCMUX 4
#define JUNIPER_IFLE_ATM_LLC 5
#define JUNIPER_IFLE_ATM_PPP_VCMUX 6
#define JUNIPER_IFLE_ATM_PPP_LLC 7
#define JUNIPER_IFLE_ATM_PPP_FUNI 8
#define JUNIPER_IFLE_ATM_CCC 9
#define JUNIPER_IFLE_FR_NLPID 10
#define JUNIPER_IFLE_FR_SNAP 11
#define JUNIPER_IFLE_FR_PPP 12
#define JUNIPER_IFLE_FR_CCC 13
#define JUNIPER_IFLE_ENET2 14
#define JUNIPER_IFLE_IEEE8023_SNAP 15
#define JUNIPER_IFLE_IEEE8023_LLC 16
#define JUNIPER_IFLE_PPP 17
#define JUNIPER_IFLE_CISCOHDLC 18
#define JUNIPER_IFLE_PPP_CCC 19
#define JUNIPER_IFLE_IPIP_NULL 20
#define JUNIPER_IFLE_PIM_NULL 21
#define JUNIPER_IFLE_GRE_NULL 22
#define JUNIPER_IFLE_GRE_PPP 23
#define JUNIPER_IFLE_PIMD_DECAPS 24
#define JUNIPER_IFLE_CISCOHDLC_CCC 25
#define JUNIPER_IFLE_ATM_CISCO_NLPID 26
#define JUNIPER_IFLE_VLAN_CCC 27
#define JUNIPER_IFLE_MLPPP 28
#define JUNIPER_IFLE_MLFR 29
#define JUNIPER_IFLE_LSI_NULL 30
#define JUNIPER_IFLE_AGGREGATE_UNUSED 31
#define JUNIPER_IFLE_ATM_CELLRELAY_CCC 32
#define JUNIPER_IFLE_CRYPTO 33
#define JUNIPER_IFLE_GGSN 34
#define JUNIPER_IFLE_ATM_TCC 35
#define JUNIPER_IFLE_FR_TCC 36
#define JUNIPER_IFLE_PPP_TCC 37
#define JUNIPER_IFLE_CISCOHDLC_TCC 38
#define JUNIPER_IFLE_ETHERNET_CCC 39
#define JUNIPER_IFLE_VT 40
#define JUNIPER_IFLE_ATM_EOA_LLC 41
#define JUNIPER_IFLE_EXTENDED_VLAN_CCC 42
#define JUNIPER_IFLE_ATM_SNAP_TCC 43
#define JUNIPER_IFLE_MONITOR 44
#define JUNIPER_IFLE_ETHERNET_TCC 45
#define JUNIPER_IFLE_VLAN_TCC 46
#define JUNIPER_IFLE_EXTENDED_VLAN_TCC 47
#define JUNIPER_IFLE_MFR 48
#define JUNIPER_IFLE_ETHERNET_VPLS 49
#define JUNIPER_IFLE_ETHERNET_VLAN_VPLS 50
#define JUNIPER_IFLE_ETHERNET_EXTENDED_VLAN_VPLS 51
#define JUNIPER_IFLE_SERVICES 52
#define JUNIPER_IFLE_ATM_ETHER_VPLS_ATM_LLC 53
#define JUNIPER_IFLE_FR_PORT_CCC 54
#define JUNIPER_IFLE_ATM_MLPPP_LLC 55
#define JUNIPER_IFLE_ATM_EOA_CCC 56
#define JUNIPER_IFLE_LT_VLAN 57
#define JUNIPER_IFLE_COLLECTOR 58
#define JUNIPER_IFLE_AGGREGATOR 59
#define JUNIPER_IFLE_LAPD 60
#define JUNIPER_IFLE_ATM_PPPOE_LLC 61
#define JUNIPER_IFLE_ETHERNET_PPPOE 62
#define JUNIPER_IFLE_PPPOE 63
#define JUNIPER_IFLE_PPP_SUBORDINATE 64
#define JUNIPER_IFLE_CISCOHDLC_SUBORDINATE 65
#define JUNIPER_IFLE_DFC 66
#define JUNIPER_IFLE_PICPEER 67
static const struct tok juniper_ifle_values[] = {
{ JUNIPER_IFLE_AGGREGATOR, "Aggregator" },
{ JUNIPER_IFLE_ATM_CCC, "CCC over ATM" },
{ JUNIPER_IFLE_ATM_CELLRELAY_CCC, "ATM CCC Cell Relay" },
{ JUNIPER_IFLE_ATM_CISCO_NLPID, "CISCO compatible NLPID" },
{ JUNIPER_IFLE_ATM_EOA_CCC, "Ethernet over ATM CCC" },
{ JUNIPER_IFLE_ATM_EOA_LLC, "Ethernet over ATM LLC" },
{ JUNIPER_IFLE_ATM_ETHER_VPLS_ATM_LLC, "Ethernet VPLS over ATM LLC" },
{ JUNIPER_IFLE_ATM_LLC, "ATM LLC" },
{ JUNIPER_IFLE_ATM_MLPPP_LLC, "MLPPP over ATM LLC" },
{ JUNIPER_IFLE_ATM_NLPID, "ATM NLPID" },
{ JUNIPER_IFLE_ATM_PPPOE_LLC, "PPPoE over ATM LLC" },
{ JUNIPER_IFLE_ATM_PPP_FUNI, "PPP over FUNI" },
{ JUNIPER_IFLE_ATM_PPP_LLC, "PPP over ATM LLC" },
{ JUNIPER_IFLE_ATM_PPP_VCMUX, "PPP over ATM VCMUX" },
{ JUNIPER_IFLE_ATM_SNAP, "ATM SNAP" },
{ JUNIPER_IFLE_ATM_SNAP_TCC, "ATM SNAP TCC" },
{ JUNIPER_IFLE_ATM_TCC, "ATM VCMUX TCC" },
{ JUNIPER_IFLE_ATM_VCMUX, "ATM VCMUX" },
{ JUNIPER_IFLE_CISCOHDLC, "C-HDLC" },
{ JUNIPER_IFLE_CISCOHDLC_CCC, "C-HDLC CCC" },
{ JUNIPER_IFLE_CISCOHDLC_SUBORDINATE, "C-HDLC via dialer" },
{ JUNIPER_IFLE_CISCOHDLC_TCC, "C-HDLC TCC" },
{ JUNIPER_IFLE_COLLECTOR, "Collector" },
{ JUNIPER_IFLE_CRYPTO, "Crypto" },
{ JUNIPER_IFLE_ENET2, "Ethernet" },
{ JUNIPER_IFLE_ETHERNET_CCC, "Ethernet CCC" },
{ JUNIPER_IFLE_ETHERNET_EXTENDED_VLAN_VPLS, "Extended VLAN VPLS" },
{ JUNIPER_IFLE_ETHERNET_PPPOE, "PPPoE over Ethernet" },
{ JUNIPER_IFLE_ETHERNET_TCC, "Ethernet TCC" },
{ JUNIPER_IFLE_ETHERNET_VLAN_VPLS, "VLAN VPLS" },
{ JUNIPER_IFLE_ETHERNET_VPLS, "VPLS" },
{ JUNIPER_IFLE_EXTENDED_VLAN_CCC, "Extended VLAN CCC" },
{ JUNIPER_IFLE_EXTENDED_VLAN_TCC, "Extended VLAN TCC" },
{ JUNIPER_IFLE_FR_CCC, "FR CCC" },
{ JUNIPER_IFLE_FR_NLPID, "FR NLPID" },
{ JUNIPER_IFLE_FR_PORT_CCC, "FR CCC" },
{ JUNIPER_IFLE_FR_PPP, "FR PPP" },
{ JUNIPER_IFLE_FR_SNAP, "FR SNAP" },
{ JUNIPER_IFLE_FR_TCC, "FR TCC" },
{ JUNIPER_IFLE_GGSN, "GGSN" },
{ JUNIPER_IFLE_GRE_NULL, "GRE NULL" },
{ JUNIPER_IFLE_GRE_PPP, "PPP over GRE" },
{ JUNIPER_IFLE_IPIP_NULL, "IPIP" },
{ JUNIPER_IFLE_LAPD, "LAPD" },
{ JUNIPER_IFLE_LSI_NULL, "LSI Null" },
{ JUNIPER_IFLE_LT_VLAN, "LT VLAN" },
{ JUNIPER_IFLE_MFR, "MFR" },
{ JUNIPER_IFLE_MLFR, "MLFR" },
{ JUNIPER_IFLE_MLPPP, "MLPPP" },
{ JUNIPER_IFLE_MONITOR, "Monitor" },
{ JUNIPER_IFLE_PIMD_DECAPS, "PIMd" },
{ JUNIPER_IFLE_PIM_NULL, "PIM Null" },
{ JUNIPER_IFLE_PPP, "PPP" },
{ JUNIPER_IFLE_PPPOE, "PPPoE" },
{ JUNIPER_IFLE_PPP_CCC, "PPP CCC" },
{ JUNIPER_IFLE_PPP_SUBORDINATE, "" },
{ JUNIPER_IFLE_PPP_TCC, "PPP TCC" },
{ JUNIPER_IFLE_SERVICES, "General Services" },
{ JUNIPER_IFLE_VLAN_CCC, "VLAN CCC" },
{ JUNIPER_IFLE_VLAN_TCC, "VLAN TCC" },
{ JUNIPER_IFLE_VT, "VT" },
{0, NULL}
};
struct juniper_cookie_table_t {
uint32_t pictype; /* pic type */
uint8_t cookie_len; /* cookie len */
const char *s; /* pic name */
};
static const struct juniper_cookie_table_t juniper_cookie_table[] = {
#ifdef DLT_JUNIPER_ATM1
{ DLT_JUNIPER_ATM1, 4, "ATM1"},
#endif
#ifdef DLT_JUNIPER_ATM2
{ DLT_JUNIPER_ATM2, 8, "ATM2"},
#endif
#ifdef DLT_JUNIPER_MLPPP
{ DLT_JUNIPER_MLPPP, 2, "MLPPP"},
#endif
#ifdef DLT_JUNIPER_MLFR
{ DLT_JUNIPER_MLFR, 2, "MLFR"},
#endif
#ifdef DLT_JUNIPER_MFR
{ DLT_JUNIPER_MFR, 4, "MFR"},
#endif
#ifdef DLT_JUNIPER_PPPOE
{ DLT_JUNIPER_PPPOE, 0, "PPPoE"},
#endif
#ifdef DLT_JUNIPER_PPPOE_ATM
{ DLT_JUNIPER_PPPOE_ATM, 0, "PPPoE ATM"},
#endif
#ifdef DLT_JUNIPER_GGSN
{ DLT_JUNIPER_GGSN, 8, "GGSN"},
#endif
#ifdef DLT_JUNIPER_MONITOR
{ DLT_JUNIPER_MONITOR, 8, "MONITOR"},
#endif
#ifdef DLT_JUNIPER_SERVICES
{ DLT_JUNIPER_SERVICES, 8, "AS"},
#endif
#ifdef DLT_JUNIPER_ES
{ DLT_JUNIPER_ES, 0, "ES"},
#endif
{ 0, 0, NULL }
};
struct juniper_l2info_t {
uint32_t length;
uint32_t caplen;
uint32_t pictype;
uint8_t direction;
u_int header_len;
uint8_t cookie_len;
uint8_t cookie_type;
uint8_t cookie[8];
u_int bundle;
uint16_t proto;
uint8_t flags;
};
#define LS_COOKIE_ID 0x54
#define AS_COOKIE_ID 0x47
#define LS_MLFR_COOKIE_LEN 4
#define ML_MLFR_COOKIE_LEN 2
#define LS_MFR_COOKIE_LEN 6
#define ATM1_COOKIE_LEN 4
#define ATM2_COOKIE_LEN 8
#define ATM2_PKT_TYPE_MASK 0x70
#define ATM2_GAP_COUNT_MASK 0x3F
#define JUNIPER_PROTO_NULL 1
#define JUNIPER_PROTO_IPV4 2
#define JUNIPER_PROTO_IPV6 6
#define MFR_BE_MASK 0xc0
#ifdef DLT_JUNIPER_GGSN
static const struct tok juniper_protocol_values[] = {
{ JUNIPER_PROTO_NULL, "Null" },
{ JUNIPER_PROTO_IPV4, "IPv4" },
{ JUNIPER_PROTO_IPV6, "IPv6" },
{ 0, NULL}
};
#endif
static int ip_heuristic_guess(netdissect_options *, const u_char *, u_int);
#ifdef DLT_JUNIPER_ATM2
static int juniper_ppp_heuristic_guess(netdissect_options *, const u_char *, u_int);
#endif
static int juniper_parse_header(netdissect_options *, const u_char *, const struct pcap_pkthdr *, struct juniper_l2info_t *);
#ifdef DLT_JUNIPER_GGSN
void
juniper_ggsn_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h, const u_char *p)
{
struct juniper_l2info_t l2info;
struct juniper_ggsn_header {
nd_uint8_t svc_id;
nd_uint8_t flags_len;
nd_uint8_t proto;
nd_uint8_t flags;
nd_uint16_t vlan_id;
nd_byte res[2];
};
const struct juniper_ggsn_header *gh;
uint8_t proto;
ndo->ndo_protocol = "juniper_ggsn";
memset(&l2info, 0, sizeof(l2info));
l2info.pictype = DLT_JUNIPER_GGSN;
if (juniper_parse_header(ndo, p, h, &l2info) == 0) {
ndo->ndo_ll_hdr_len += l2info.header_len;
return;
}
p+=l2info.header_len;
gh = (struct juniper_ggsn_header *)&l2info.cookie;
/* use EXTRACT_, not GET_ (not packet buffer pointer) */
proto = EXTRACT_U_1(gh->proto);
if (ndo->ndo_eflag) {
ND_PRINT("proto %s (%u), vlan %u: ",
tok2str(juniper_protocol_values,"Unknown",proto),
proto,
EXTRACT_BE_U_2(gh->vlan_id));
}
switch (proto) {
case JUNIPER_PROTO_IPV4:
ip_print(ndo, p, l2info.length);
break;
case JUNIPER_PROTO_IPV6:
ip6_print(ndo, p, l2info.length);
break;
default:
if (!ndo->ndo_eflag)
ND_PRINT("unknown GGSN proto (%u)", proto);
}
ndo->ndo_ll_hdr_len += l2info.header_len;
}
#endif
#ifdef DLT_JUNIPER_ES
void
juniper_es_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h, const u_char *p)
{
struct juniper_l2info_t l2info;
struct juniper_ipsec_header {
nd_uint16_t sa_index;
nd_uint8_t ttl;
nd_uint8_t type;
nd_uint32_t spi;
nd_ipv4 src_ip;
nd_ipv4 dst_ip;
};
u_int rewrite_len,es_type_bundle;
const struct juniper_ipsec_header *ih;
ndo->ndo_protocol = "juniper_es";
memset(&l2info, 0, sizeof(l2info));
l2info.pictype = DLT_JUNIPER_ES;
if (juniper_parse_header(ndo, p, h, &l2info) == 0) {
ndo->ndo_ll_hdr_len += l2info.header_len;
return;
}
p+=l2info.header_len;
ih = (const struct juniper_ipsec_header *)p;
ND_TCHECK_SIZE(ih);
switch (GET_U_1(ih->type)) {
case JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE:
case JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE:
rewrite_len = 0;
es_type_bundle = 1;
break;
case JUNIPER_IPSEC_O_ESP_AUTHENTICATION_TYPE:
case JUNIPER_IPSEC_O_AH_AUTHENTICATION_TYPE:
case JUNIPER_IPSEC_O_ESP_ENCRYPTION_TYPE:
rewrite_len = 16;
es_type_bundle = 0;
break;
default:
ND_PRINT("ES Invalid type %u, length %u",
GET_U_1(ih->type),
l2info.length);
ndo->ndo_ll_hdr_len += l2info.header_len;
return;
}
l2info.length-=rewrite_len;
p+=rewrite_len;
if (ndo->ndo_eflag) {
if (!es_type_bundle) {
ND_PRINT("ES SA, index %u, ttl %u type %s (%u), spi %u, Tunnel %s > %s, length %u\n",
GET_BE_U_2(ih->sa_index),
GET_U_1(ih->ttl),
tok2str(juniper_ipsec_type_values,"Unknown",GET_U_1(ih->type)),
GET_U_1(ih->type),
GET_BE_U_4(ih->spi),
GET_IPADDR_STRING(ih->src_ip),
GET_IPADDR_STRING(ih->dst_ip),
l2info.length);
} else {
ND_PRINT("ES SA, index %u, ttl %u type %s (%u), length %u\n",
GET_BE_U_2(ih->sa_index),
GET_U_1(ih->ttl),
tok2str(juniper_ipsec_type_values,"Unknown",GET_U_1(ih->type)),
GET_U_1(ih->type),
l2info.length);
}
}
ip_print(ndo, p, l2info.length);
ndo->ndo_ll_hdr_len += l2info.header_len;
}
#endif
#ifdef DLT_JUNIPER_MONITOR
void
juniper_monitor_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h, const u_char *p)
{
struct juniper_l2info_t l2info;
struct juniper_monitor_header {
nd_uint8_t pkt_type;
nd_byte padding;
nd_uint16_t iif;
nd_uint32_t service_id;
};
const struct juniper_monitor_header *mh;
ndo->ndo_protocol = "juniper_monitor";
memset(&l2info, 0, sizeof(l2info));
l2info.pictype = DLT_JUNIPER_MONITOR;
if (juniper_parse_header(ndo, p, h, &l2info) == 0) {
ndo->ndo_ll_hdr_len += l2info.header_len;
return;
}
p+=l2info.header_len;
mh = (const struct juniper_monitor_header *)p;
ND_TCHECK_SIZE(mh);
if (ndo->ndo_eflag)
ND_PRINT("service-id %u, iif %u, pkt-type %u: ",
GET_BE_U_4(mh->service_id),
GET_BE_U_2(mh->iif),
GET_U_1(mh->pkt_type));
/* no proto field - lets guess by first byte of IP header*/
ip_heuristic_guess (ndo, p, l2info.length);
ndo->ndo_ll_hdr_len += l2info.header_len;
}
#endif
#ifdef DLT_JUNIPER_SERVICES
void
juniper_services_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h, const u_char *p)
{
struct juniper_l2info_t l2info;
struct juniper_services_header {
nd_uint8_t svc_id;
nd_uint8_t flags_len;
nd_uint16_t svc_set_id;
nd_byte pad;
nd_uint24_t dir_iif;
};
const struct juniper_services_header *sh;
ndo->ndo_protocol = "juniper_services";
memset(&l2info, 0, sizeof(l2info));
l2info.pictype = DLT_JUNIPER_SERVICES;
if (juniper_parse_header(ndo, p, h, &l2info) == 0) {
ndo->ndo_ll_hdr_len += l2info.header_len;
return;
}
p+=l2info.header_len;
sh = (const struct juniper_services_header *)p;
ND_TCHECK_SIZE(sh);
if (ndo->ndo_eflag)
ND_PRINT("service-id %u flags 0x%02x service-set-id 0x%04x iif %u: ",
GET_U_1(sh->svc_id),
GET_U_1(sh->flags_len),
GET_BE_U_2(sh->svc_set_id),
GET_BE_U_3(sh->dir_iif));
/* no proto field - lets guess by first byte of IP header*/
ip_heuristic_guess (ndo, p, l2info.length);
ndo->ndo_ll_hdr_len += l2info.header_len;
}
#endif
#ifdef DLT_JUNIPER_PPPOE
void
juniper_pppoe_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h, const u_char *p)
{
struct juniper_l2info_t l2info;
ndo->ndo_protocol = "juniper_pppoe";
memset(&l2info, 0, sizeof(l2info));
l2info.pictype = DLT_JUNIPER_PPPOE;
if (juniper_parse_header(ndo, p, h, &l2info) == 0) {
ndo->ndo_ll_hdr_len += l2info.header_len;
return;
}
p+=l2info.header_len;
/* this DLT contains nothing but raw ethernet frames */
ether_print(ndo, p, l2info.length, l2info.caplen, NULL, NULL);
ndo->ndo_ll_hdr_len += l2info.header_len;
}
#endif
#ifdef DLT_JUNIPER_ETHER
void
juniper_ether_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h, const u_char *p)
{
struct juniper_l2info_t l2info;
ndo->ndo_protocol = "juniper_ether";
memset(&l2info, 0, sizeof(l2info));
l2info.pictype = DLT_JUNIPER_ETHER;
if (juniper_parse_header(ndo, p, h, &l2info) == 0) {
ndo->ndo_ll_hdr_len += l2info.header_len;
return;
}
p+=l2info.header_len;
/* this DLT contains nothing but raw Ethernet frames */
ndo->ndo_ll_hdr_len +=
l2info.header_len +
ether_print(ndo, p, l2info.length, l2info.caplen, NULL, NULL);
}
#endif
#ifdef DLT_JUNIPER_PPP
void
juniper_ppp_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h, const u_char *p)
{
struct juniper_l2info_t l2info;
ndo->ndo_protocol = "juniper_ppp";
memset(&l2info, 0, sizeof(l2info));
l2info.pictype = DLT_JUNIPER_PPP;
if (juniper_parse_header(ndo, p, h, &l2info) == 0) {
ndo->ndo_ll_hdr_len += l2info.header_len;
return;
}
p+=l2info.header_len;
/* this DLT contains nothing but raw ppp frames */
ppp_print(ndo, p, l2info.length);
ndo->ndo_ll_hdr_len += l2info.header_len;
}
#endif
#ifdef DLT_JUNIPER_FRELAY
void
juniper_frelay_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h, const u_char *p)
{
struct juniper_l2info_t l2info;
ndo->ndo_protocol = "juniper_frelay";
memset(&l2info, 0, sizeof(l2info));
l2info.pictype = DLT_JUNIPER_FRELAY;
if (juniper_parse_header(ndo, p, h, &l2info) == 0) {
ndo->ndo_ll_hdr_len += l2info.header_len;
return;
}
p+=l2info.header_len;
/* this DLT contains nothing but raw frame-relay frames */
fr_print(ndo, p, l2info.length);
ndo->ndo_ll_hdr_len += l2info.header_len;
}
#endif
#ifdef DLT_JUNIPER_CHDLC
void
juniper_chdlc_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h, const u_char *p)
{
struct juniper_l2info_t l2info;
ndo->ndo_protocol = "juniper_chdlc";
memset(&l2info, 0, sizeof(l2info));
l2info.pictype = DLT_JUNIPER_CHDLC;
if (juniper_parse_header(ndo, p, h, &l2info) == 0) {
ndo->ndo_ll_hdr_len += l2info.header_len;
return;
}
p+=l2info.header_len;
/* this DLT contains nothing but raw c-hdlc frames */
chdlc_print(ndo, p, l2info.length);
ndo->ndo_ll_hdr_len += l2info.header_len;
}
#endif
#ifdef DLT_JUNIPER_PPPOE_ATM
void
juniper_pppoe_atm_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h, const u_char *p)
{
struct juniper_l2info_t l2info;
uint16_t extracted_ethertype;
ndo->ndo_protocol = "juniper_pppoe_atm";
memset(&l2info, 0, sizeof(l2info));
l2info.pictype = DLT_JUNIPER_PPPOE_ATM;
if (juniper_parse_header(ndo, p, h, &l2info) == 0) {
ndo->ndo_ll_hdr_len += l2info.header_len;
return;
}
p+=l2info.header_len;
extracted_ethertype = GET_BE_U_2(p);
/* this DLT contains nothing but raw PPPoE frames,
* prepended with a type field*/
if (ethertype_print(ndo, extracted_ethertype,
p+ETHERTYPE_LEN,
l2info.length-ETHERTYPE_LEN,
l2info.caplen-ETHERTYPE_LEN,
NULL, NULL) == 0)
/* ether_type not known, probably it wasn't one */
ND_PRINT("unknown ethertype 0x%04x", extracted_ethertype);
ndo->ndo_ll_hdr_len += l2info.header_len;
}
#endif
#ifdef DLT_JUNIPER_MLPPP
void
juniper_mlppp_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h, const u_char *p)
{
struct juniper_l2info_t l2info;
ndo->ndo_protocol = "juniper_mlppp";
memset(&l2info, 0, sizeof(l2info));
l2info.pictype = DLT_JUNIPER_MLPPP;
if (juniper_parse_header(ndo, p, h, &l2info) == 0) {
ndo->ndo_ll_hdr_len += l2info.header_len;
return;
}
/* suppress Bundle-ID if frame was captured on a child-link
* best indicator if the cookie looks like a proto */
if (ndo->ndo_eflag &&
/* use EXTRACT_, not GET_ (not packet buffer pointer) */
EXTRACT_BE_U_2(&l2info.cookie) != PPP_OSI &&
/* use EXTRACT_, not GET_ (not packet buffer pointer) */
EXTRACT_BE_U_2(&l2info.cookie) != (PPP_ADDRESS << 8 | PPP_CONTROL))
ND_PRINT("Bundle-ID %u: ", l2info.bundle);
p+=l2info.header_len;
/* first try the LSQ protos */
switch(l2info.proto) {
case JUNIPER_LSQ_L3_PROTO_IPV4:
/* IP traffic going to the RE would not have a cookie
* -> this must be incoming IS-IS over PPP
*/
if (l2info.cookie[4] == (JUNIPER_LSQ_COOKIE_RE|JUNIPER_LSQ_COOKIE_DIR))
ppp_print(ndo, p, l2info.length);
else
ip_print(ndo, p, l2info.length);
ndo->ndo_ll_hdr_len += l2info.header_len;
return;
case JUNIPER_LSQ_L3_PROTO_IPV6:
ip6_print(ndo, p,l2info.length);
ndo->ndo_ll_hdr_len += l2info.header_len;
return;
case JUNIPER_LSQ_L3_PROTO_MPLS:
mpls_print(ndo, p, l2info.length);
ndo->ndo_ll_hdr_len += l2info.header_len;
return;
case JUNIPER_LSQ_L3_PROTO_ISO:
isoclns_print(ndo, p, l2info.length);
ndo->ndo_ll_hdr_len += l2info.header_len;
return;
default:
break;
}
/* zero length cookie ? */
/* use EXTRACT_, not GET_ (not packet buffer pointer) */
switch (EXTRACT_BE_U_2(&l2info.cookie)) {
case PPP_OSI:
ppp_print(ndo, p - 2, l2info.length + 2);
break;
case (PPP_ADDRESS << 8 | PPP_CONTROL): /* fall through */
default:
ppp_print(ndo, p, l2info.length);
break;
}
ndo->ndo_ll_hdr_len += l2info.header_len;
}
#endif
#ifdef DLT_JUNIPER_MFR
void
juniper_mfr_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h, const u_char *p)
{
struct juniper_l2info_t l2info;
ndo->ndo_protocol = "juniper_mfr";
memset(&l2info, 0, sizeof(l2info));
l2info.pictype = DLT_JUNIPER_MFR;
if (juniper_parse_header(ndo, p, h, &l2info) == 0) {
ndo->ndo_ll_hdr_len += l2info.header_len;
return;
}
p+=l2info.header_len;
/* child-link ? */
if (l2info.cookie_len == 0) {
mfr_print(ndo, p, l2info.length);
ndo->ndo_ll_hdr_len += l2info.header_len;
return;
}
/* first try the LSQ protos */
if (l2info.cookie_len == AS_PIC_COOKIE_LEN) {
switch(l2info.proto) {
case JUNIPER_LSQ_L3_PROTO_IPV4:
ip_print(ndo, p, l2info.length);
ndo->ndo_ll_hdr_len += l2info.header_len;
return;
case JUNIPER_LSQ_L3_PROTO_IPV6:
ip6_print(ndo, p,l2info.length);
ndo->ndo_ll_hdr_len += l2info.header_len;
return;
case JUNIPER_LSQ_L3_PROTO_MPLS:
mpls_print(ndo, p, l2info.length);
ndo->ndo_ll_hdr_len += l2info.header_len;
return;
case JUNIPER_LSQ_L3_PROTO_ISO:
isoclns_print(ndo, p, l2info.length);
ndo->ndo_ll_hdr_len += l2info.header_len;
return;
default:
break;
}
ndo->ndo_ll_hdr_len += l2info.header_len;
return;
}
/* suppress Bundle-ID if frame was captured on a child-link */
/* use EXTRACT_, not GET_ (not packet buffer pointer) */
if (ndo->ndo_eflag && EXTRACT_BE_U_4(l2info.cookie) != 1)
ND_PRINT("Bundle-ID %u, ", l2info.bundle);
switch (l2info.proto) {
case (LLCSAP_ISONS<<8 | LLCSAP_ISONS):
/* At least one byte is required */
ND_TCHECK_LEN(p, 1);
isoclns_print(ndo, p + 1, l2info.length - 1);
break;
case (LLC_UI<<8 | NLPID_Q933):
case (LLC_UI<<8 | NLPID_IP):
case (LLC_UI<<8 | NLPID_IP6):
/* pass IP{4,6} to the OSI layer for proper link-layer printing */
isoclns_print(ndo, p - 1, l2info.length + 1);
break;
default:
ND_PRINT("unknown protocol 0x%04x, length %u", l2info.proto, l2info.length);
}
ndo->ndo_ll_hdr_len += l2info.header_len;
}
#endif
#ifdef DLT_JUNIPER_MLFR
void
juniper_mlfr_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h, const u_char *p)
{
struct juniper_l2info_t l2info;
ndo->ndo_protocol = "juniper_mlfr";
memset(&l2info, 0, sizeof(l2info));
l2info.pictype = DLT_JUNIPER_MLFR;
if (juniper_parse_header(ndo, p, h, &l2info) == 0) {
ndo->ndo_ll_hdr_len += l2info.header_len;
return;
}
p+=l2info.header_len;
/* suppress Bundle-ID if frame was captured on a child-link */
/* use EXTRACT_, not GET_ (not packet buffer pointer) */
if (ndo->ndo_eflag && EXTRACT_BE_U_4(l2info.cookie) != 1)
ND_PRINT("Bundle-ID %u, ", l2info.bundle);
switch (l2info.proto) {
case (LLC_UI):
case (LLC_UI<<8):
isoclns_print(ndo, p, l2info.length);
break;
case (LLC_UI<<8 | NLPID_Q933):
case (LLC_UI<<8 | NLPID_IP):
case (LLC_UI<<8 | NLPID_IP6):
/* pass IP{4,6} to the OSI layer for proper link-layer printing */
isoclns_print(ndo, p - 1, l2info.length + 1);
break;
default:
ND_PRINT("unknown protocol 0x%04x, length %u", l2info.proto, l2info.length);
}
ndo->ndo_ll_hdr_len += l2info.header_len;
}
#endif
/*
* ATM1 PIC cookie format
*
* +-----+-------------------------+-------------------------------+
* |fmtid| vc index | channel ID |
* +-----+-------------------------+-------------------------------+
*/
#ifdef DLT_JUNIPER_ATM1
void
juniper_atm1_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h, const u_char *p)
{
int llc_hdrlen;
struct juniper_l2info_t l2info;
ndo->ndo_protocol = "juniper_atm1";
memset(&l2info, 0, sizeof(l2info));
l2info.pictype = DLT_JUNIPER_ATM1;
if (juniper_parse_header(ndo, p, h, &l2info) == 0) {
ndo->ndo_ll_hdr_len += l2info.header_len;
return;
}
p+=l2info.header_len;
if (l2info.cookie[0] == 0x80) { /* OAM cell ? */
oam_print(ndo, p, l2info.length, ATM_OAM_NOHEC);
ndo->ndo_ll_hdr_len += l2info.header_len;
return;
}
if (GET_BE_U_3(p) == 0xfefe03 || /* NLPID encaps ? */
GET_BE_U_3(p) == 0xaaaa03) { /* SNAP encaps ? */
llc_hdrlen = llc_print(ndo, p, l2info.length, l2info.caplen, NULL, NULL);
if (llc_hdrlen > 0) {
ndo->ndo_ll_hdr_len += l2info.header_len;
return;
}
}
if (GET_U_1(p) == 0x03) { /* Cisco style NLPID encaps ? */
/* At least one byte is required */
ND_TCHECK_LEN(p, 1);
isoclns_print(ndo, p + 1, l2info.length - 1);
/* FIXME check if frame was recognized */
ndo->ndo_ll_hdr_len += l2info.header_len;
return;
}
if (ip_heuristic_guess(ndo, p, l2info.length) != 0) { /* last try - vcmux encaps ? */
ndo->ndo_ll_hdr_len += l2info.header_len;
return;
}
ndo->ndo_ll_hdr_len += l2info.header_len;
}
#endif
/*
* ATM2 PIC cookie format
*
* +-------------------------------+---------+---+-----+-----------+
* | channel ID | reserv |AAL| CCRQ| gap cnt |
* +-------------------------------+---------+---+-----+-----------+
*/
#ifdef DLT_JUNIPER_ATM2
void
juniper_atm2_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h, const u_char *p)
{
int llc_hdrlen;
struct juniper_l2info_t l2info;
ndo->ndo_protocol = "juniper_atm2";
memset(&l2info, 0, sizeof(l2info));
l2info.pictype = DLT_JUNIPER_ATM2;
if (juniper_parse_header(ndo, p, h, &l2info) == 0) {
ndo->ndo_ll_hdr_len += l2info.header_len;
return;
}
p+=l2info.header_len;
if (l2info.cookie[7] & ATM2_PKT_TYPE_MASK) { /* OAM cell ? */
oam_print(ndo, p, l2info.length, ATM_OAM_NOHEC);
ndo->ndo_ll_hdr_len += l2info.header_len;
return;
}
if (GET_BE_U_3(p) == 0xfefe03 || /* NLPID encaps ? */
GET_BE_U_3(p) == 0xaaaa03) { /* SNAP encaps ? */
llc_hdrlen = llc_print(ndo, p, l2info.length, l2info.caplen, NULL, NULL);
if (llc_hdrlen > 0) {
ndo->ndo_ll_hdr_len += l2info.header_len;
return;
}
}
if (l2info.direction != JUNIPER_BPF_PKT_IN && /* ether-over-1483 encaps ? */
/* use EXTRACT_, not GET_ (not packet buffer pointer) */
(EXTRACT_BE_U_4(l2info.cookie) & ATM2_GAP_COUNT_MASK)) {
ether_print(ndo, p, l2info.length, l2info.caplen, NULL, NULL);
ndo->ndo_ll_hdr_len += l2info.header_len;
return;
}
if (GET_U_1(p) == 0x03) { /* Cisco style NLPID encaps ? */
/* At least one byte is required */
ND_TCHECK_LEN(p, 1);
isoclns_print(ndo, p + 1, l2info.length - 1);
/* FIXME check if frame was recognized */
ndo->ndo_ll_hdr_len += l2info.header_len;
return;
}
if(juniper_ppp_heuristic_guess(ndo, p, l2info.length) != 0) { /* PPPoA vcmux encaps ? */
ndo->ndo_ll_hdr_len += l2info.header_len;
return;
}
if (ip_heuristic_guess(ndo, p, l2info.length) != 0) { /* last try - vcmux encaps ? */
ndo->ndo_ll_hdr_len += l2info.header_len;
return;
}
ndo->ndo_ll_hdr_len += l2info.header_len;
}
/* try to guess, based on all PPP protos that are supported in
* a juniper router if the payload data is encapsulated using PPP */
static int
juniper_ppp_heuristic_guess(netdissect_options *ndo,
const u_char *p, u_int length)
{
switch(GET_BE_U_2(p)) {
case PPP_IP :
case PPP_OSI :
case PPP_MPLS_UCAST :
case PPP_MPLS_MCAST :
case PPP_IPCP :
case PPP_OSICP :
case PPP_MPLSCP :
case PPP_LCP :
case PPP_PAP :
case PPP_CHAP :
case PPP_ML :
case PPP_IPV6 :
case PPP_IPV6CP :
ppp_print(ndo, p, length);
break;
default:
return 0; /* did not find a ppp header */
break;
}
return 1; /* we printed a ppp packet */
}
#endif
static int
ip_heuristic_guess(netdissect_options *ndo,
const u_char *p, u_int length)
{
switch(GET_U_1(p)) {
case 0x45:
case 0x46:
case 0x47:
case 0x48:
case 0x49:
case 0x4a:
case 0x4b:
case 0x4c:
case 0x4d:
case 0x4e:
case 0x4f:
ip_print(ndo, p, length);
break;
case 0x60:
case 0x61:
case 0x62:
case 0x63:
case 0x64:
case 0x65:
case 0x66:
case 0x67:
case 0x68:
case 0x69:
case 0x6a:
case 0x6b:
case 0x6c:
case 0x6d:
case 0x6e:
case 0x6f:
ip6_print(ndo, p, length);
break;
default:
return 0; /* did not find a ip header */
break;
}
return 1; /* we printed an v4/v6 packet */
}
static int
juniper_read_tlv_value(netdissect_options *ndo,
const u_char *p, u_int tlv_type, u_int tlv_len)
{
int tlv_value;
/* TLVs < 128 are little endian encoded */
if (tlv_type < 128) {
switch (tlv_len) {
case 1:
tlv_value = GET_U_1(p);
break;
case 2:
tlv_value = GET_LE_U_2(p);
break;
case 3:
tlv_value = GET_LE_U_3(p);
break;
case 4:
tlv_value = GET_LE_U_4(p);
break;
default:
tlv_value = -1;
break;
}
} else {
/* TLVs >= 128 are big endian encoded */
switch (tlv_len) {
case 1:
tlv_value = GET_U_1(p);
break;
case 2:
tlv_value = GET_BE_U_2(p);
break;
case 3:
tlv_value = GET_BE_U_3(p);
break;
case 4:
tlv_value = GET_BE_U_4(p);
break;
default:
tlv_value = -1;
break;
}
}
return tlv_value;
}
static int
juniper_parse_header(netdissect_options *ndo,
const u_char *p, const struct pcap_pkthdr *h, struct juniper_l2info_t *l2info)
{
const struct juniper_cookie_table_t *lp;
u_int idx, extension_length, jnx_header_len = 0;
uint8_t tlv_type,tlv_len;
#ifdef DLT_JUNIPER_ATM2
uint32_t control_word;
#endif
int tlv_value;
const u_char *tptr;
l2info->header_len = 0;
l2info->cookie_len = 0;
l2info->proto = 0;
l2info->length = h->len;
l2info->caplen = h->caplen;
l2info->flags = GET_U_1(p + 3);
l2info->direction = GET_U_1(p + 3) & JUNIPER_BPF_PKT_IN;
if (GET_BE_U_3(p) != JUNIPER_MGC_NUMBER) { /* magic number found ? */
ND_PRINT("no magic-number found!");
return 0;
}
if (ndo->ndo_eflag) /* print direction */
ND_PRINT("%3s ", tok2str(juniper_direction_values, "---", l2info->direction));
/* magic number + flags */
jnx_header_len = 4;
if (ndo->ndo_vflag > 1)
ND_PRINT("\n\tJuniper PCAP Flags [%s]",
bittok2str(jnx_flag_values, "none", l2info->flags));
/* extensions present ? - calculate how much bytes to skip */
if ((l2info->flags & JUNIPER_BPF_EXT ) == JUNIPER_BPF_EXT ) {
tptr = p+jnx_header_len;
/* ok to read extension length ? */
extension_length = GET_BE_U_2(tptr);
jnx_header_len += 2;
tptr +=2;
/* nail up the total length -
* just in case something goes wrong
* with TLV parsing */
jnx_header_len += extension_length;
if (ndo->ndo_vflag > 1)
ND_PRINT(", PCAP Extension(s) total length %u", extension_length);
ND_TCHECK_LEN(tptr, extension_length);
while (extension_length > JUNIPER_EXT_TLV_OVERHEAD) {
tlv_type = GET_U_1(tptr);
tptr++;
tlv_len = GET_U_1(tptr);
tptr++;
tlv_value = 0;
/* sanity checks */
if (tlv_type == 0 || tlv_len == 0)
break;
- ND_LCHECK_U(extension_length, tlv_len + JUNIPER_EXT_TLV_OVERHEAD);
+ ND_ICHECK_U(extension_length, <,
+ tlv_len + JUNIPER_EXT_TLV_OVERHEAD);
if (ndo->ndo_vflag > 1)
ND_PRINT("\n\t %s Extension TLV #%u, length %u, value ",
tok2str(jnx_ext_tlv_values,"Unknown",tlv_type),
tlv_type,
tlv_len);
tlv_value = juniper_read_tlv_value(ndo, tptr, tlv_type, tlv_len);
switch (tlv_type) {
case JUNIPER_EXT_TLV_IFD_NAME:
/* FIXME */
break;
case JUNIPER_EXT_TLV_IFD_MEDIATYPE:
case JUNIPER_EXT_TLV_TTP_IFD_MEDIATYPE:
if (tlv_value != -1) {
if (ndo->ndo_vflag > 1)
ND_PRINT("%s (%u)",
tok2str(juniper_ifmt_values, "Unknown", tlv_value),
tlv_value);
}
break;
case JUNIPER_EXT_TLV_IFL_ENCAPS:
case JUNIPER_EXT_TLV_TTP_IFL_ENCAPS:
if (tlv_value != -1) {
if (ndo->ndo_vflag > 1)
ND_PRINT("%s (%u)",
tok2str(juniper_ifle_values, "Unknown", tlv_value),
tlv_value);
}
break;
case JUNIPER_EXT_TLV_IFL_IDX: /* fall through */
case JUNIPER_EXT_TLV_IFL_UNIT:
case JUNIPER_EXT_TLV_IFD_IDX:
default:
if (tlv_value != -1) {
if (ndo->ndo_vflag > 1)
ND_PRINT("%u", tlv_value);
}
break;
}
tptr+=tlv_len;
extension_length -= tlv_len+JUNIPER_EXT_TLV_OVERHEAD;
}
if (ndo->ndo_vflag > 1)
ND_PRINT("\n\t-----original packet-----\n\t");
}
if ((l2info->flags & JUNIPER_BPF_NO_L2 ) == JUNIPER_BPF_NO_L2 ) {
if (ndo->ndo_eflag)
ND_PRINT("no-L2-hdr, ");
/* there is no link-layer present -
* perform the v4/v6 heuristics
* to figure out what it is
*/
ND_TCHECK_1(p + (jnx_header_len + 4));
if (ip_heuristic_guess(ndo, p + jnx_header_len + 4,
l2info->length - (jnx_header_len + 4)) == 0)
ND_PRINT("no IP-hdr found!");
l2info->header_len=jnx_header_len+4;
return 0; /* stop parsing the output further */
}
l2info->header_len = jnx_header_len;
p+=l2info->header_len;
l2info->length -= l2info->header_len;
l2info->caplen -= l2info->header_len;
/* search through the cookie table for one matching our PIC type */
lp = NULL;
for (const struct juniper_cookie_table_t *table_lp = juniper_cookie_table;
table_lp->s != NULL; table_lp++) {
if (table_lp->pictype == l2info->pictype) {
lp = table_lp;
break;
}
}
/* If we found one matching our PIC type, copy its values */
if (lp != NULL) {
l2info->cookie_len += lp->cookie_len;
switch (GET_U_1(p)) {
case LS_COOKIE_ID:
l2info->cookie_type = LS_COOKIE_ID;
l2info->cookie_len += 2;
break;
case AS_COOKIE_ID:
l2info->cookie_type = AS_COOKIE_ID;
l2info->cookie_len = 8;
break;
default:
l2info->bundle = l2info->cookie[0];
break;
}
#ifdef DLT_JUNIPER_MFR
/* MFR child links don't carry cookies */
if (l2info->pictype == DLT_JUNIPER_MFR &&
(GET_U_1(p) & MFR_BE_MASK) == MFR_BE_MASK) {
l2info->cookie_len = 0;
}
#endif
l2info->header_len += l2info->cookie_len;
l2info->length -= l2info->cookie_len;
l2info->caplen -= l2info->cookie_len;
if (ndo->ndo_eflag)
ND_PRINT("%s-PIC, cookie-len %u",
lp->s,
l2info->cookie_len);
if (l2info->cookie_len > 8) {
nd_print_invalid(ndo);
return 0;
}
if (l2info->cookie_len > 0) {
ND_TCHECK_LEN(p, l2info->cookie_len);
if (ndo->ndo_eflag)
ND_PRINT(", cookie 0x");
for (idx = 0; idx < l2info->cookie_len; idx++) {
l2info->cookie[idx] = GET_U_1(p + idx); /* copy cookie data */
if (ndo->ndo_eflag) ND_PRINT("%02x", GET_U_1(p + idx));
}
}
if (ndo->ndo_eflag) ND_PRINT(": "); /* print demarc b/w L2/L3*/
l2info->proto = GET_BE_U_2(p + l2info->cookie_len);
}
p+=l2info->cookie_len;
/* DLT_ specific parsing */
switch(l2info->pictype) {
#ifdef DLT_JUNIPER_MLPPP
case DLT_JUNIPER_MLPPP:
switch (l2info->cookie_type) {
case LS_COOKIE_ID:
l2info->bundle = l2info->cookie[1];
break;
case AS_COOKIE_ID:
/* use EXTRACT_, not GET_ (not packet buffer pointer) */
l2info->bundle = (EXTRACT_BE_U_2(&l2info->cookie[6])>>3)&0xfff;
l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK;
break;
default:
l2info->bundle = l2info->cookie[0];
break;
}
break;
#endif
#ifdef DLT_JUNIPER_MLFR
case DLT_JUNIPER_MLFR:
switch (l2info->cookie_type) {
case LS_COOKIE_ID:
l2info->bundle = l2info->cookie[1];
l2info->proto = GET_BE_U_2(p);
l2info->header_len += 2;
l2info->length -= 2;
l2info->caplen -= 2;
break;
case AS_COOKIE_ID:
/* use EXTRACT_, not GET_ (not packet buffer pointer) */
l2info->bundle = (EXTRACT_BE_U_2(&l2info->cookie[6])>>3)&0xfff;
l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK;
break;
default:
l2info->bundle = l2info->cookie[0];
l2info->header_len += 2;
l2info->length -= 2;
l2info->caplen -= 2;
break;
}
break;
#endif
#ifdef DLT_JUNIPER_MFR
case DLT_JUNIPER_MFR:
switch (l2info->cookie_type) {
case LS_COOKIE_ID:
l2info->bundle = l2info->cookie[1];
l2info->proto = GET_BE_U_2(p);
l2info->header_len += 2;
l2info->length -= 2;
l2info->caplen -= 2;
break;
case AS_COOKIE_ID:
/* use EXTRACT_, not GET_ (not packet buffer pointer) */
l2info->bundle = (EXTRACT_BE_U_2(&l2info->cookie[6])>>3)&0xfff;
l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK;
break;
default:
l2info->bundle = l2info->cookie[0];
break;
}
break;
#endif
#ifdef DLT_JUNIPER_ATM2
case DLT_JUNIPER_ATM2:
ND_TCHECK_4(p);
/* ATM cell relay control word present ? */
if (l2info->cookie[7] & ATM2_PKT_TYPE_MASK) {
control_word = GET_BE_U_4(p);
/* some control word heuristics */
switch(control_word) {
case 0: /* zero control word */
case 0x08000000: /* < JUNOS 7.4 control-word */
case 0x08380000: /* cntl word plus cell length (56) >= JUNOS 7.4*/
l2info->header_len += 4;
break;
default:
break;
}
if (ndo->ndo_eflag)
ND_PRINT("control-word 0x%08x ", control_word);
}
break;
#endif
#ifdef DLT_JUNIPER_ES
case DLT_JUNIPER_ES:
break;
#endif
#ifdef DLT_JUNIPER_GGSN
case DLT_JUNIPER_GGSN:
break;
#endif
#ifdef DLT_JUNIPER_SERVICES
case DLT_JUNIPER_SERVICES:
break;
#endif
#ifdef DLT_JUNIPER_ATM1
case DLT_JUNIPER_ATM1:
break;
#endif
#ifdef DLT_JUNIPER_PPP
case DLT_JUNIPER_PPP:
break;
#endif
#ifdef DLT_JUNIPER_CHDLC
case DLT_JUNIPER_CHDLC:
break;
#endif
#ifdef DLT_JUNIPER_ETHER
case DLT_JUNIPER_ETHER:
break;
#endif
#ifdef DLT_JUNIPER_FRELAY
case DLT_JUNIPER_FRELAY:
break;
#endif
#ifdef DLT_JUNIPER_MONITOR
case DLT_JUNIPER_MONITOR:
break;
#endif
#ifdef DLT_JUNIPER_PPPOE
case DLT_JUNIPER_PPPOE:
break;
#endif
#ifdef DLT_JUNIPER_PPPOE_ATM
case DLT_JUNIPER_PPPOE_ATM:
break;
#endif
default:
ND_PRINT("Unknown Juniper DLT_ type %u: ", l2info->pictype);
break;
}
if (ndo->ndo_eflag)
ND_PRINT("hlen %u, proto 0x%04x, ", l2info->header_len, l2info->proto);
return 1; /* everything went ok so far. continue parsing */
invalid:
nd_print_invalid(ndo);
return 0;
}
#endif /* defined(DLT_JUNIPER_GGSN) || defined(DLT_JUNIPER_ES) || \
defined(DLT_JUNIPER_MONITOR) || defined(DLT_JUNIPER_SERVICES) || \
defined(DLT_JUNIPER_PPPOE) || defined(DLT_JUNIPER_ETHER) || \
defined(DLT_JUNIPER_PPP) || defined(DLT_JUNIPER_FRELAY) || \
defined(DLT_JUNIPER_CHDLC) || defined(DLT_JUNIPER_PPPOE_ATM) || \
defined(DLT_JUNIPER_MLPPP) || defined(DLT_JUNIPER_MFR) || \
defined(DLT_JUNIPER_MLFR) || defined(DLT_JUNIPER_ATM1) || \
defined(DLT_JUNIPER_ATM2) */
diff --git a/contrib/tcpdump/print-krb.c b/contrib/tcpdump/print-krb.c
index 959b555c7033..69a0c1155e21 100644
--- a/contrib/tcpdump/print-krb.c
+++ b/contrib/tcpdump/print-krb.c
@@ -1,259 +1,254 @@
/*
* Copyright (c) 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.
*
* Initial contribution from John Hawkinson (jhawk@mit.edu).
*/
/* \summary: Kerberos printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "extract.h"
/*
* Kerberos 4:
*
* Athena Technical Plan
* Section E.2.1
* Kerberos Authentication and Authorization System
* by S. P. Miller, B. C. Neuman, J. I. Schiller, and J. H. Saltzer
*
* https://web.mit.edu/Saltzer/www/publications/athenaplan/e.2.1.pdf
*
* 7. Appendix I Design Specifications
*
* Kerberos 5:
*
* RFC 1510, RFC 2630, etc.
*/
static const u_char *c_print(netdissect_options *, const u_char *, const u_char *);
static const u_char *krb4_print_hdr(netdissect_options *, const u_char *);
static void krb4_print(netdissect_options *, const u_char *);
#define AUTH_MSG_KDC_REQUEST 1<<1
#define AUTH_MSG_KDC_REPLY 2<<1
#define AUTH_MSG_APPL_REQUEST 3<<1
#define AUTH_MSG_APPL_REQUEST_MUTUAL 4<<1
#define AUTH_MSG_ERR_REPLY 5<<1
#define AUTH_MSG_PRIVATE 6<<1
#define AUTH_MSG_SAFE 7<<1
#define AUTH_MSG_APPL_ERR 8<<1
#define AUTH_MSG_DIE 63<<1
#define KERB_ERR_OK 0
#define KERB_ERR_NAME_EXP 1
#define KERB_ERR_SERVICE_EXP 2
#define KERB_ERR_AUTH_EXP 3
#define KERB_ERR_PKT_VER 4
#define KERB_ERR_NAME_MAST_KEY_VER 5
#define KERB_ERR_SERV_MAST_KEY_VER 6
#define KERB_ERR_BYTE_ORDER 7
#define KERB_ERR_PRINCIPAL_UNKNOWN 8
#define KERB_ERR_PRINCIPAL_NOT_UNIQUE 9
#define KERB_ERR_NULL_KEY 10
struct krb {
nd_uint8_t pvno; /* Protocol Version */
nd_uint8_t type; /* Type+B */
};
static const struct tok type2str[] = {
{ AUTH_MSG_KDC_REQUEST, "KDC_REQUEST" },
{ AUTH_MSG_KDC_REPLY, "KDC_REPLY" },
{ AUTH_MSG_APPL_REQUEST, "APPL_REQUEST" },
{ AUTH_MSG_APPL_REQUEST_MUTUAL, "APPL_REQUEST_MUTUAL" },
{ AUTH_MSG_ERR_REPLY, "ERR_REPLY" },
{ AUTH_MSG_PRIVATE, "PRIVATE" },
{ AUTH_MSG_SAFE, "SAFE" },
{ AUTH_MSG_APPL_ERR, "APPL_ERR" },
{ AUTH_MSG_DIE, "DIE" },
{ 0, NULL }
};
static const struct tok kerr2str[] = {
{ KERB_ERR_OK, "OK" },
{ KERB_ERR_NAME_EXP, "NAME_EXP" },
{ KERB_ERR_SERVICE_EXP, "SERVICE_EXP" },
{ KERB_ERR_AUTH_EXP, "AUTH_EXP" },
{ KERB_ERR_PKT_VER, "PKT_VER" },
{ KERB_ERR_NAME_MAST_KEY_VER, "NAME_MAST_KEY_VER" },
{ KERB_ERR_SERV_MAST_KEY_VER, "SERV_MAST_KEY_VER" },
{ KERB_ERR_BYTE_ORDER, "BYTE_ORDER" },
{ KERB_ERR_PRINCIPAL_UNKNOWN, "PRINCIPAL_UNKNOWN" },
{ KERB_ERR_PRINCIPAL_NOT_UNIQUE,"PRINCIPAL_NOT_UNIQUE" },
{ KERB_ERR_NULL_KEY, "NULL_KEY"},
{ 0, NULL}
};
static const u_char *
c_print(netdissect_options *ndo,
const u_char *s, const u_char *ep)
{
u_char c;
int flag;
flag = 1;
while (s < ep) {
c = GET_U_1(s);
s++;
if (c == '\0') {
flag = 0;
break;
}
fn_print_char(ndo, c);
}
if (flag)
return NULL;
return (s);
}
static const u_char *
krb4_print_hdr(netdissect_options *ndo,
const u_char *cp)
{
cp += 2;
#define PRINT if ((cp = c_print(ndo, cp, ndo->ndo_snapend)) == NULL) goto trunc
PRINT;
ND_PRINT(".");
PRINT;
ND_PRINT("@");
PRINT;
return (cp);
trunc:
nd_print_trunc(ndo);
return (NULL);
#undef PRINT
}
static void
krb4_print(netdissect_options *ndo,
const u_char *cp)
{
const struct krb *kp;
u_char type;
u_short len;
#define PRINT if ((cp = c_print(ndo, cp, ndo->ndo_snapend)) == NULL) goto trunc
/* True if struct krb is little endian */
#define IS_LENDIAN(kp) ((GET_U_1((kp)->type) & 0x01) != 0)
#define KTOHSP(kp, cp) (IS_LENDIAN(kp) ? GET_LE_U_2(cp) : GET_BE_U_2(cp))
kp = (const struct krb *)cp;
type = GET_U_1(kp->type) & (0xFF << 1);
ND_PRINT(" %s %s: ",
IS_LENDIAN(kp) ? "le" : "be", tok2str(type2str, NULL, type));
switch (type) {
case AUTH_MSG_KDC_REQUEST:
if ((cp = krb4_print_hdr(ndo, cp)) == NULL)
return;
cp += 4; /* ctime */
ND_PRINT(" %umin ", GET_U_1(cp) * 5);
cp++;
PRINT;
ND_PRINT(".");
PRINT;
break;
case AUTH_MSG_APPL_REQUEST:
cp += 2;
ND_PRINT("v%u ", GET_U_1(cp));
cp++;
PRINT;
ND_PRINT(" (%u)", GET_U_1(cp));
cp++;
ND_PRINT(" (%u)", GET_U_1(cp));
break;
case AUTH_MSG_KDC_REPLY:
if ((cp = krb4_print_hdr(ndo, cp)) == NULL)
return;
cp += 10; /* timestamp + n + exp + kvno */
len = KTOHSP(kp, cp);
ND_PRINT(" (%u)", len);
break;
case AUTH_MSG_ERR_REPLY:
if ((cp = krb4_print_hdr(ndo, cp)) == NULL)
return;
cp += 4; /* timestamp */
ND_PRINT(" %s ", tok2str(kerr2str, NULL, KTOHSP(kp, cp)));
cp += 4;
PRINT;
break;
default:
ND_PRINT("(unknown)");
break;
}
return;
trunc:
nd_print_trunc(ndo);
}
void
krb_print(netdissect_options *ndo,
const u_char *dat)
{
const struct krb *kp;
- ndo->ndo_protocol = "krb";
- kp = (const struct krb *)dat;
+ ndo->ndo_protocol = "kerberos";
+ nd_print_protocol(ndo);
- if (dat >= ndo->ndo_snapend) {
- nd_print_trunc(ndo);
- return;
- }
+ kp = (const struct krb *)dat;
switch (GET_U_1(kp->pvno)) {
case 1:
case 2:
case 3:
ND_PRINT(" v%u", GET_U_1(kp->pvno));
break;
case 4:
ND_PRINT(" v%u", GET_U_1(kp->pvno));
krb4_print(ndo, (const u_char *)kp);
break;
case 106:
case 107:
ND_PRINT(" v5");
/* Decode ASN.1 here "someday" */
break;
}
}
diff --git a/contrib/tcpdump/print-l2tp.c b/contrib/tcpdump/print-l2tp.c
index 895efd21f008..605c20d8cf0b 100644
--- a/contrib/tcpdump/print-l2tp.c
+++ b/contrib/tcpdump/print-l2tp.c
@@ -1,859 +1,857 @@
/*
* Copyright (c) 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.
*
* L2TP support contributed by Motonori Shindo (mshindo@mshindo.net)
*/
/* \summary: Layer Two Tunneling Protocol (L2TP) printer */
/* specification: RFC 2661 */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "extract.h"
#define L2TP_FLAG_TYPE 0x8000 /* Type (0=Data, 1=Control) */
#define L2TP_FLAG_LENGTH 0x4000 /* Length */
#define L2TP_FLAG_SEQUENCE 0x0800 /* Sequence */
#define L2TP_FLAG_OFFSET 0x0200 /* Offset */
#define L2TP_FLAG_PRIORITY 0x0100 /* Priority */
#define L2TP_VERSION_MASK 0x000f /* Version Mask */
#define L2TP_VERSION_L2F 0x0001 /* L2F */
#define L2TP_VERSION_L2TP 0x0002 /* L2TP */
#define L2TP_AVP_HDR_FLAG_MANDATORY 0x8000 /* Mandatory Flag */
#define L2TP_AVP_HDR_FLAG_HIDDEN 0x4000 /* Hidden Flag */
#define L2TP_AVP_HDR_LEN_MASK 0x03ff /* Length Mask */
#define L2TP_FRAMING_CAP_SYNC_MASK 0x00000001 /* Synchronous */
#define L2TP_FRAMING_CAP_ASYNC_MASK 0x00000002 /* Asynchronous */
#define L2TP_FRAMING_TYPE_SYNC_MASK 0x00000001 /* Synchronous */
#define L2TP_FRAMING_TYPE_ASYNC_MASK 0x00000002 /* Asynchronous */
#define L2TP_BEARER_CAP_DIGITAL_MASK 0x00000001 /* Digital */
#define L2TP_BEARER_CAP_ANALOG_MASK 0x00000002 /* Analog */
#define L2TP_BEARER_TYPE_DIGITAL_MASK 0x00000001 /* Digital */
#define L2TP_BEARER_TYPE_ANALOG_MASK 0x00000002 /* Analog */
/* Authen Type */
#define L2TP_AUTHEN_TYPE_RESERVED 0x0000 /* Reserved */
#define L2TP_AUTHEN_TYPE_TEXTUAL 0x0001 /* Textual username/password exchange */
#define L2TP_AUTHEN_TYPE_CHAP 0x0002 /* PPP CHAP */
#define L2TP_AUTHEN_TYPE_PAP 0x0003 /* PPP PAP */
#define L2TP_AUTHEN_TYPE_NO_AUTH 0x0004 /* No Authentication */
#define L2TP_AUTHEN_TYPE_MSCHAPv1 0x0005 /* MSCHAPv1 */
#define L2TP_PROXY_AUTH_ID_MASK 0x00ff
#define L2TP_MSGTYPE_SCCRQ 1 /* Start-Control-Connection-Request */
#define L2TP_MSGTYPE_SCCRP 2 /* Start-Control-Connection-Reply */
#define L2TP_MSGTYPE_SCCCN 3 /* Start-Control-Connection-Connected */
#define L2TP_MSGTYPE_STOPCCN 4 /* Stop-Control-Connection-Notification */
#define L2TP_MSGTYPE_HELLO 6 /* Hello */
#define L2TP_MSGTYPE_OCRQ 7 /* Outgoing-Call-Request */
#define L2TP_MSGTYPE_OCRP 8 /* Outgoing-Call-Reply */
#define L2TP_MSGTYPE_OCCN 9 /* Outgoing-Call-Connected */
#define L2TP_MSGTYPE_ICRQ 10 /* Incoming-Call-Request */
#define L2TP_MSGTYPE_ICRP 11 /* Incoming-Call-Reply */
#define L2TP_MSGTYPE_ICCN 12 /* Incoming-Call-Connected */
#define L2TP_MSGTYPE_CDN 14 /* Call-Disconnect-Notify */
#define L2TP_MSGTYPE_WEN 15 /* WAN-Error-Notify */
#define L2TP_MSGTYPE_SLI 16 /* Set-Link-Info */
static const struct tok l2tp_msgtype2str[] = {
{ L2TP_MSGTYPE_SCCRQ, "SCCRQ" },
{ L2TP_MSGTYPE_SCCRP, "SCCRP" },
{ L2TP_MSGTYPE_SCCCN, "SCCCN" },
{ L2TP_MSGTYPE_STOPCCN, "StopCCN" },
{ L2TP_MSGTYPE_HELLO, "HELLO" },
{ L2TP_MSGTYPE_OCRQ, "OCRQ" },
{ L2TP_MSGTYPE_OCRP, "OCRP" },
{ L2TP_MSGTYPE_OCCN, "OCCN" },
{ L2TP_MSGTYPE_ICRQ, "ICRQ" },
{ L2TP_MSGTYPE_ICRP, "ICRP" },
{ L2TP_MSGTYPE_ICCN, "ICCN" },
{ L2TP_MSGTYPE_CDN, "CDN" },
{ L2TP_MSGTYPE_WEN, "WEN" },
{ L2TP_MSGTYPE_SLI, "SLI" },
{ 0, NULL }
};
#define L2TP_AVP_MSGTYPE 0 /* Message Type */
#define L2TP_AVP_RESULT_CODE 1 /* Result Code */
#define L2TP_AVP_PROTO_VER 2 /* Protocol Version */
#define L2TP_AVP_FRAMING_CAP 3 /* Framing Capabilities */
#define L2TP_AVP_BEARER_CAP 4 /* Bearer Capabilities */
#define L2TP_AVP_TIE_BREAKER 5 /* Tie Breaker */
#define L2TP_AVP_FIRM_VER 6 /* Firmware Revision */
#define L2TP_AVP_HOST_NAME 7 /* Host Name */
#define L2TP_AVP_VENDOR_NAME 8 /* Vendor Name */
#define L2TP_AVP_ASSND_TUN_ID 9 /* Assigned Tunnel ID */
#define L2TP_AVP_RECV_WIN_SIZE 10 /* Receive Window Size */
#define L2TP_AVP_CHALLENGE 11 /* Challenge */
#define L2TP_AVP_Q931_CC 12 /* Q.931 Cause Code */
#define L2TP_AVP_CHALLENGE_RESP 13 /* Challenge Response */
#define L2TP_AVP_ASSND_SESS_ID 14 /* Assigned Session ID */
#define L2TP_AVP_CALL_SER_NUM 15 /* Call Serial Number */
#define L2TP_AVP_MINIMUM_BPS 16 /* Minimum BPS */
#define L2TP_AVP_MAXIMUM_BPS 17 /* Maximum BPS */
#define L2TP_AVP_BEARER_TYPE 18 /* Bearer Type */
#define L2TP_AVP_FRAMING_TYPE 19 /* Framing Type */
#define L2TP_AVP_PACKET_PROC_DELAY 20 /* Packet Processing Delay (OBSOLETE) */
#define L2TP_AVP_CALLED_NUMBER 21 /* Called Number */
#define L2TP_AVP_CALLING_NUMBER 22 /* Calling Number */
#define L2TP_AVP_SUB_ADDRESS 23 /* Sub-Address */
#define L2TP_AVP_TX_CONN_SPEED 24 /* (Tx) Connect Speed */
#define L2TP_AVP_PHY_CHANNEL_ID 25 /* Physical Channel ID */
#define L2TP_AVP_INI_RECV_LCP 26 /* Initial Received LCP CONFREQ */
#define L2TP_AVP_LAST_SENT_LCP 27 /* Last Sent LCP CONFREQ */
#define L2TP_AVP_LAST_RECV_LCP 28 /* Last Received LCP CONFREQ */
#define L2TP_AVP_PROXY_AUTH_TYPE 29 /* Proxy Authen Type */
#define L2TP_AVP_PROXY_AUTH_NAME 30 /* Proxy Authen Name */
#define L2TP_AVP_PROXY_AUTH_CHAL 31 /* Proxy Authen Challenge */
#define L2TP_AVP_PROXY_AUTH_ID 32 /* Proxy Authen ID */
#define L2TP_AVP_PROXY_AUTH_RESP 33 /* Proxy Authen Response */
#define L2TP_AVP_CALL_ERRORS 34 /* Call Errors */
#define L2TP_AVP_ACCM 35 /* ACCM */
#define L2TP_AVP_RANDOM_VECTOR 36 /* Random Vector */
#define L2TP_AVP_PRIVATE_GRP_ID 37 /* Private Group ID */
#define L2TP_AVP_RX_CONN_SPEED 38 /* (Rx) Connect Speed */
#define L2TP_AVP_SEQ_REQUIRED 39 /* Sequencing Required */
#define L2TP_AVP_PPP_DISCON_CC 46 /* PPP Disconnect Cause Code - RFC 3145 */
static const struct tok l2tp_avp2str[] = {
{ L2TP_AVP_MSGTYPE, "MSGTYPE" },
{ L2TP_AVP_RESULT_CODE, "RESULT_CODE" },
{ L2TP_AVP_PROTO_VER, "PROTO_VER" },
{ L2TP_AVP_FRAMING_CAP, "FRAMING_CAP" },
{ L2TP_AVP_BEARER_CAP, "BEARER_CAP" },
{ L2TP_AVP_TIE_BREAKER, "TIE_BREAKER" },
{ L2TP_AVP_FIRM_VER, "FIRM_VER" },
{ L2TP_AVP_HOST_NAME, "HOST_NAME" },
{ L2TP_AVP_VENDOR_NAME, "VENDOR_NAME" },
{ L2TP_AVP_ASSND_TUN_ID, "ASSND_TUN_ID" },
{ L2TP_AVP_RECV_WIN_SIZE, "RECV_WIN_SIZE" },
{ L2TP_AVP_CHALLENGE, "CHALLENGE" },
{ L2TP_AVP_Q931_CC, "Q931_CC", },
{ L2TP_AVP_CHALLENGE_RESP, "CHALLENGE_RESP" },
{ L2TP_AVP_ASSND_SESS_ID, "ASSND_SESS_ID" },
{ L2TP_AVP_CALL_SER_NUM, "CALL_SER_NUM" },
{ L2TP_AVP_MINIMUM_BPS, "MINIMUM_BPS" },
{ L2TP_AVP_MAXIMUM_BPS, "MAXIMUM_BPS" },
{ L2TP_AVP_BEARER_TYPE, "BEARER_TYPE" },
{ L2TP_AVP_FRAMING_TYPE, "FRAMING_TYPE" },
{ L2TP_AVP_PACKET_PROC_DELAY, "PACKET_PROC_DELAY" },
{ L2TP_AVP_CALLED_NUMBER, "CALLED_NUMBER" },
{ L2TP_AVP_CALLING_NUMBER, "CALLING_NUMBER" },
{ L2TP_AVP_SUB_ADDRESS, "SUB_ADDRESS" },
{ L2TP_AVP_TX_CONN_SPEED, "TX_CONN_SPEED" },
{ L2TP_AVP_PHY_CHANNEL_ID, "PHY_CHANNEL_ID" },
{ L2TP_AVP_INI_RECV_LCP, "INI_RECV_LCP" },
{ L2TP_AVP_LAST_SENT_LCP, "LAST_SENT_LCP" },
{ L2TP_AVP_LAST_RECV_LCP, "LAST_RECV_LCP" },
{ L2TP_AVP_PROXY_AUTH_TYPE, "PROXY_AUTH_TYPE" },
{ L2TP_AVP_PROXY_AUTH_NAME, "PROXY_AUTH_NAME" },
{ L2TP_AVP_PROXY_AUTH_CHAL, "PROXY_AUTH_CHAL" },
{ L2TP_AVP_PROXY_AUTH_ID, "PROXY_AUTH_ID" },
{ L2TP_AVP_PROXY_AUTH_RESP, "PROXY_AUTH_RESP" },
{ L2TP_AVP_CALL_ERRORS, "CALL_ERRORS" },
{ L2TP_AVP_ACCM, "ACCM" },
{ L2TP_AVP_RANDOM_VECTOR, "RANDOM_VECTOR" },
{ L2TP_AVP_PRIVATE_GRP_ID, "PRIVATE_GRP_ID" },
{ L2TP_AVP_RX_CONN_SPEED, "RX_CONN_SPEED" },
{ L2TP_AVP_SEQ_REQUIRED, "SEQ_REQUIRED" },
{ L2TP_AVP_PPP_DISCON_CC, "PPP_DISCON_CC" },
{ 0, NULL }
};
static const struct tok l2tp_authentype2str[] = {
{ L2TP_AUTHEN_TYPE_RESERVED, "Reserved" },
{ L2TP_AUTHEN_TYPE_TEXTUAL, "Textual" },
{ L2TP_AUTHEN_TYPE_CHAP, "CHAP" },
{ L2TP_AUTHEN_TYPE_PAP, "PAP" },
{ L2TP_AUTHEN_TYPE_NO_AUTH, "No Auth" },
{ L2TP_AUTHEN_TYPE_MSCHAPv1, "MS-CHAPv1" },
{ 0, NULL }
};
#define L2TP_PPP_DISCON_CC_DIRECTION_GLOBAL 0
#define L2TP_PPP_DISCON_CC_DIRECTION_AT_PEER 1
#define L2TP_PPP_DISCON_CC_DIRECTION_AT_LOCAL 2
static const struct tok l2tp_cc_direction2str[] = {
{ L2TP_PPP_DISCON_CC_DIRECTION_GLOBAL, "global error" },
{ L2TP_PPP_DISCON_CC_DIRECTION_AT_PEER, "at peer" },
{ L2TP_PPP_DISCON_CC_DIRECTION_AT_LOCAL,"at local" },
{ 0, NULL }
};
#if 0
static char *l2tp_result_code_StopCCN[] = {
"Reserved",
"General request to clear control connection",
"General error--Error Code indicates the problem",
"Control channel already exists",
"Requester is not authorized to establish a control channel",
"The protocol version of the requester is not supported",
"Requester is being shut down",
"Finite State Machine error"
#define L2TP_MAX_RESULT_CODE_STOPCC_INDEX 8
};
#endif
#if 0
static char *l2tp_result_code_CDN[] = {
"Reserved",
"Call disconnected due to loss of carrier",
"Call disconnected for the reason indicated in error code",
"Call disconnected for administrative reasons",
"Call failed due to lack of appropriate facilities being "
"available (temporary condition)",
"Call failed due to lack of appropriate facilities being "
"available (permanent condition)",
"Invalid destination",
"Call failed due to no carrier detected",
"Call failed due to detection of a busy signal",
"Call failed due to lack of a dial tone",
"Call was not established within time allotted by LAC",
"Call was connected but no appropriate framing was detected"
#define L2TP_MAX_RESULT_CODE_CDN_INDEX 12
};
#endif
#if 0
static char *l2tp_error_code_general[] = {
"No general error",
"No control connection exists yet for this LAC-LNS pair",
"Length is wrong",
"One of the field values was out of range or "
"reserved field was non-zero"
"Insufficient resources to handle this operation now",
"The Session ID is invalid in this context",
"A generic vendor-specific error occurred in the LAC",
"Try another"
#define L2TP_MAX_ERROR_CODE_GENERAL_INDEX 8
};
#endif
/******************************/
/* generic print out routines */
/******************************/
static void
print_string(netdissect_options *ndo, const u_char *dat, u_int length)
{
u_int i;
for (i=0; i<length; i++) {
fn_print_char(ndo, GET_U_1(dat));
dat++;
}
}
static void
print_octets(netdissect_options *ndo, const u_char *dat, u_int length)
{
u_int i;
for (i=0; i<length; i++) {
ND_PRINT("%02x", GET_U_1(dat));
dat++;
}
}
static void
print_16bits_val(netdissect_options *ndo, const uint8_t *dat)
{
ND_PRINT("%u", GET_BE_U_2(dat));
}
static void
print_32bits_val(netdissect_options *ndo, const uint8_t *dat)
{
ND_PRINT("%u", GET_BE_U_4(dat));
}
/***********************************/
/* AVP-specific print out routines */
/***********************************/
static void
l2tp_msgtype_print(netdissect_options *ndo, const u_char *dat, u_int length)
{
if (length < 2) {
ND_PRINT("AVP too short");
return;
}
ND_PRINT("%s", tok2str(l2tp_msgtype2str, "MSGTYPE-#%u",
GET_BE_U_2(dat)));
}
static void
l2tp_result_code_print(netdissect_options *ndo, const u_char *dat, u_int length)
{
/* Result Code */
if (length < 2) {
ND_PRINT("AVP too short");
return;
}
ND_PRINT("%u", GET_BE_U_2(dat));
dat += 2;
length -= 2;
/* Error Code (opt) */
if (length == 0)
return;
if (length < 2) {
ND_PRINT(" AVP too short");
return;
}
ND_PRINT("/%u", GET_BE_U_2(dat));
dat += 2;
length -= 2;
/* Error Message (opt) */
if (length == 0)
return;
ND_PRINT(" ");
print_string(ndo, dat, length);
}
static void
l2tp_proto_ver_print(netdissect_options *ndo, const u_char *dat, u_int length)
{
if (length < 2) {
ND_PRINT("AVP too short");
return;
}
ND_PRINT("%u.%u", (GET_BE_U_2(dat) >> 8),
(GET_BE_U_2(dat) & 0xff));
}
static void
l2tp_framing_cap_print(netdissect_options *ndo, const u_char *dat, u_int length)
{
if (length < 4) {
ND_PRINT("AVP too short");
return;
}
if (GET_BE_U_4(dat) & L2TP_FRAMING_CAP_ASYNC_MASK) {
ND_PRINT("A");
}
if (GET_BE_U_4(dat) & L2TP_FRAMING_CAP_SYNC_MASK) {
ND_PRINT("S");
}
}
static void
l2tp_bearer_cap_print(netdissect_options *ndo, const u_char *dat, u_int length)
{
if (length < 4) {
ND_PRINT("AVP too short");
return;
}
if (GET_BE_U_4(dat) & L2TP_BEARER_CAP_ANALOG_MASK) {
ND_PRINT("A");
}
if (GET_BE_U_4(dat) & L2TP_BEARER_CAP_DIGITAL_MASK) {
ND_PRINT("D");
}
}
static void
l2tp_q931_cc_print(netdissect_options *ndo, const u_char *dat, u_int length)
{
if (length < 3) {
ND_PRINT("AVP too short");
return;
}
print_16bits_val(ndo, dat);
ND_PRINT(", %02x", GET_U_1(dat + 2));
dat += 3;
length -= 3;
if (length != 0) {
ND_PRINT(" ");
print_string(ndo, dat, length);
}
}
static void
l2tp_bearer_type_print(netdissect_options *ndo, const u_char *dat, u_int length)
{
if (length < 4) {
ND_PRINT("AVP too short");
return;
}
if (GET_BE_U_4(dat) & L2TP_BEARER_TYPE_ANALOG_MASK) {
ND_PRINT("A");
}
if (GET_BE_U_4(dat) & L2TP_BEARER_TYPE_DIGITAL_MASK) {
ND_PRINT("D");
}
}
static void
l2tp_framing_type_print(netdissect_options *ndo, const u_char *dat, u_int length)
{
if (length < 4) {
ND_PRINT("AVP too short");
return;
}
if (GET_BE_U_4(dat) & L2TP_FRAMING_TYPE_ASYNC_MASK) {
ND_PRINT("A");
}
if (GET_BE_U_4(dat) & L2TP_FRAMING_TYPE_SYNC_MASK) {
ND_PRINT("S");
}
}
static void
l2tp_packet_proc_delay_print(netdissect_options *ndo)
{
ND_PRINT("obsolete");
}
static void
l2tp_proxy_auth_type_print(netdissect_options *ndo, const u_char *dat, u_int length)
{
if (length < 2) {
ND_PRINT("AVP too short");
return;
}
ND_PRINT("%s", tok2str(l2tp_authentype2str,
"AuthType-#%u", GET_BE_U_2(dat)));
}
static void
l2tp_proxy_auth_id_print(netdissect_options *ndo, const u_char *dat, u_int length)
{
if (length < 2) {
ND_PRINT("AVP too short");
return;
}
ND_PRINT("%u", GET_BE_U_2(dat) & L2TP_PROXY_AUTH_ID_MASK);
}
static void
l2tp_call_errors_print(netdissect_options *ndo, const u_char *dat, u_int length)
{
uint32_t val;
if (length < 2) {
ND_PRINT("AVP too short");
return;
}
dat += 2; /* skip "Reserved" */
length -= 2;
if (length < 4) {
ND_PRINT("AVP too short");
return;
}
val = GET_BE_U_4(dat); dat += 4; length -= 4;
ND_PRINT("CRCErr=%u ", val);
if (length < 4) {
ND_PRINT("AVP too short");
return;
}
val = GET_BE_U_4(dat); dat += 4; length -= 4;
ND_PRINT("FrameErr=%u ", val);
if (length < 4) {
ND_PRINT("AVP too short");
return;
}
val = GET_BE_U_4(dat); dat += 4; length -= 4;
ND_PRINT("HardOver=%u ", val);
if (length < 4) {
ND_PRINT("AVP too short");
return;
}
val = GET_BE_U_4(dat); dat += 4; length -= 4;
ND_PRINT("BufOver=%u ", val);
if (length < 4) {
ND_PRINT("AVP too short");
return;
}
val = GET_BE_U_4(dat); dat += 4; length -= 4;
ND_PRINT("Timeout=%u ", val);
if (length < 4) {
ND_PRINT("AVP too short");
return;
}
val = GET_BE_U_4(dat); dat += 4; length -= 4;
ND_PRINT("AlignErr=%u ", val);
}
static void
l2tp_accm_print(netdissect_options *ndo, const u_char *dat, u_int length)
{
uint32_t val;
if (length < 2) {
ND_PRINT("AVP too short");
return;
}
dat += 2; /* skip "Reserved" */
length -= 2;
if (length < 4) {
ND_PRINT("AVP too short");
return;
}
val = GET_BE_U_4(dat); dat += 4; length -= 4;
ND_PRINT("send=%08x ", val);
if (length < 4) {
ND_PRINT("AVP too short");
return;
}
val = GET_BE_U_4(dat); dat += 4; length -= 4;
ND_PRINT("recv=%08x ", val);
}
static void
l2tp_ppp_discon_cc_print(netdissect_options *ndo, const u_char *dat, u_int length)
{
if (length < 5) {
ND_PRINT("AVP too short");
return;
}
/* Disconnect Code */
ND_PRINT("%04x, ", GET_BE_U_2(dat));
dat += 2;
length -= 2;
/* Control Protocol Number */
ND_PRINT("%04x ", GET_BE_U_2(dat));
dat += 2;
length -= 2;
/* Direction */
ND_PRINT("%s", tok2str(l2tp_cc_direction2str,
"Direction-#%u", GET_U_1(dat)));
dat++;
length--;
if (length != 0) {
ND_PRINT(" ");
print_string(ndo, (const u_char *)dat, length);
}
}
static u_int
l2tp_avp_print(netdissect_options *ndo, const u_char *dat, u_int length)
{
u_int len;
uint16_t attr_type;
int hidden = FALSE;
ND_PRINT(" ");
/* Flags & Length */
len = GET_BE_U_2(dat) & L2TP_AVP_HDR_LEN_MASK;
/* If it is not long enough to contain the header, we'll give up. */
if (len < 6)
goto trunc;
/* If it goes past the end of the remaining length of the packet,
we'll give up. */
if (len > (u_int)length)
goto trunc;
/* If it goes past the end of the remaining length of the captured
data, we'll give up. */
ND_TCHECK_LEN(dat, len);
/*
* After this point, we don't need to check whether we go past
* the length of the captured data; however, we *do* need to
* check whether we go past the end of the AVP.
*/
if (GET_BE_U_2(dat) & L2TP_AVP_HDR_FLAG_MANDATORY) {
ND_PRINT("*");
}
if (GET_BE_U_2(dat) & L2TP_AVP_HDR_FLAG_HIDDEN) {
hidden = TRUE;
ND_PRINT("?");
}
dat += 2;
if (GET_BE_U_2(dat)) {
/* Vendor Specific Attribute */
ND_PRINT("VENDOR%04x:", GET_BE_U_2(dat)); dat += 2;
ND_PRINT("ATTR%04x", GET_BE_U_2(dat)); dat += 2;
ND_PRINT("(");
print_octets(ndo, dat, len-6);
ND_PRINT(")");
} else {
/* IETF-defined Attributes */
dat += 2;
attr_type = GET_BE_U_2(dat); dat += 2;
ND_PRINT("%s", tok2str(l2tp_avp2str, "AVP-#%u", attr_type));
ND_PRINT("(");
if (hidden) {
ND_PRINT("???");
} else {
switch (attr_type) {
case L2TP_AVP_MSGTYPE:
l2tp_msgtype_print(ndo, dat, len-6);
break;
case L2TP_AVP_RESULT_CODE:
l2tp_result_code_print(ndo, dat, len-6);
break;
case L2TP_AVP_PROTO_VER:
l2tp_proto_ver_print(ndo, dat, len-6);
break;
case L2TP_AVP_FRAMING_CAP:
l2tp_framing_cap_print(ndo, dat, len-6);
break;
case L2TP_AVP_BEARER_CAP:
l2tp_bearer_cap_print(ndo, dat, len-6);
break;
case L2TP_AVP_TIE_BREAKER:
if (len-6 < 8) {
ND_PRINT("AVP too short");
break;
}
print_octets(ndo, dat, 8);
break;
case L2TP_AVP_FIRM_VER:
case L2TP_AVP_ASSND_TUN_ID:
case L2TP_AVP_RECV_WIN_SIZE:
case L2TP_AVP_ASSND_SESS_ID:
if (len-6 < 2) {
ND_PRINT("AVP too short");
break;
}
print_16bits_val(ndo, dat);
break;
case L2TP_AVP_HOST_NAME:
case L2TP_AVP_VENDOR_NAME:
case L2TP_AVP_CALLING_NUMBER:
case L2TP_AVP_CALLED_NUMBER:
case L2TP_AVP_SUB_ADDRESS:
case L2TP_AVP_PROXY_AUTH_NAME:
case L2TP_AVP_PRIVATE_GRP_ID:
print_string(ndo, dat, len-6);
break;
case L2TP_AVP_CHALLENGE:
case L2TP_AVP_INI_RECV_LCP:
case L2TP_AVP_LAST_SENT_LCP:
case L2TP_AVP_LAST_RECV_LCP:
case L2TP_AVP_PROXY_AUTH_CHAL:
case L2TP_AVP_PROXY_AUTH_RESP:
case L2TP_AVP_RANDOM_VECTOR:
print_octets(ndo, dat, len-6);
break;
case L2TP_AVP_Q931_CC:
l2tp_q931_cc_print(ndo, dat, len-6);
break;
case L2TP_AVP_CHALLENGE_RESP:
if (len-6 < 16) {
ND_PRINT("AVP too short");
break;
}
print_octets(ndo, dat, 16);
break;
case L2TP_AVP_CALL_SER_NUM:
case L2TP_AVP_MINIMUM_BPS:
case L2TP_AVP_MAXIMUM_BPS:
case L2TP_AVP_TX_CONN_SPEED:
case L2TP_AVP_PHY_CHANNEL_ID:
case L2TP_AVP_RX_CONN_SPEED:
if (len-6 < 4) {
ND_PRINT("AVP too short");
break;
}
print_32bits_val(ndo, dat);
break;
case L2TP_AVP_BEARER_TYPE:
l2tp_bearer_type_print(ndo, dat, len-6);
break;
case L2TP_AVP_FRAMING_TYPE:
l2tp_framing_type_print(ndo, dat, len-6);
break;
case L2TP_AVP_PACKET_PROC_DELAY:
l2tp_packet_proc_delay_print(ndo);
break;
case L2TP_AVP_PROXY_AUTH_TYPE:
l2tp_proxy_auth_type_print(ndo, dat, len-6);
break;
case L2TP_AVP_PROXY_AUTH_ID:
l2tp_proxy_auth_id_print(ndo, dat, len-6);
break;
case L2TP_AVP_CALL_ERRORS:
l2tp_call_errors_print(ndo, dat, len-6);
break;
case L2TP_AVP_ACCM:
l2tp_accm_print(ndo, dat, len-6);
break;
case L2TP_AVP_SEQ_REQUIRED:
break; /* No Attribute Value */
case L2TP_AVP_PPP_DISCON_CC:
l2tp_ppp_discon_cc_print(ndo, dat, len-6);
break;
default:
break;
}
}
ND_PRINT(")");
}
return (len);
trunc:
nd_print_trunc(ndo);
return (0);
}
void
l2tp_print(netdissect_options *ndo, const u_char *dat, u_int length)
{
const u_char *ptr = dat;
u_int cnt = 0; /* total octets consumed */
uint16_t pad;
int flag_t, flag_l, flag_s, flag_o;
uint16_t l2tp_len;
ndo->ndo_protocol = "l2tp";
flag_t = flag_l = flag_s = flag_o = FALSE;
if ((GET_BE_U_2(ptr) & L2TP_VERSION_MASK) == L2TP_VERSION_L2TP) {
ND_PRINT(" l2tp:");
} else if ((GET_BE_U_2(ptr) & L2TP_VERSION_MASK) == L2TP_VERSION_L2F) {
ND_PRINT(" l2f:");
return; /* nothing to do */
} else {
ND_PRINT(" Unknown Version, neither L2F(1) nor L2TP(2)");
return; /* nothing we can do */
}
ND_PRINT("[");
if (GET_BE_U_2(ptr) & L2TP_FLAG_TYPE) {
flag_t = TRUE;
ND_PRINT("T");
}
if (GET_BE_U_2(ptr) & L2TP_FLAG_LENGTH) {
flag_l = TRUE;
ND_PRINT("L");
}
if (GET_BE_U_2(ptr) & L2TP_FLAG_SEQUENCE) {
flag_s = TRUE;
ND_PRINT("S");
}
if (GET_BE_U_2(ptr) & L2TP_FLAG_OFFSET) {
flag_o = TRUE;
ND_PRINT("O");
}
if (GET_BE_U_2(ptr) & L2TP_FLAG_PRIORITY)
ND_PRINT("P");
ND_PRINT("]");
ptr += 2;
cnt += 2;
if (flag_l) {
l2tp_len = GET_BE_U_2(ptr);
ptr += 2;
cnt += 2;
} else {
l2tp_len = 0;
}
/* Tunnel ID */
ND_PRINT("(%u/", GET_BE_U_2(ptr));
ptr += 2;
cnt += 2;
/* Session ID */
ND_PRINT("%u)", GET_BE_U_2(ptr));
ptr += 2;
cnt += 2;
if (flag_s) {
ND_PRINT("Ns=%u,", GET_BE_U_2(ptr));
ptr += 2;
cnt += 2;
ND_PRINT("Nr=%u", GET_BE_U_2(ptr));
ptr += 2;
cnt += 2;
}
if (flag_o) { /* Offset Size */
pad = GET_BE_U_2(ptr);
/* Offset padding octets in packet buffer? */
ND_TCHECK_LEN(ptr + 2, pad);
ptr += (2 + pad);
cnt += (2 + pad);
}
if (flag_l) {
if (length < l2tp_len) {
ND_PRINT(" Length %u larger than packet", l2tp_len);
return;
}
length = l2tp_len;
}
if (length < cnt) {
ND_PRINT(" Length %u smaller than header length", length);
return;
}
if (flag_t) {
if (!flag_l) {
ND_PRINT(" No length");
return;
}
if (length - cnt == 0) {
ND_PRINT(" ZLB");
} else {
/*
* Print AVPs.
*/
while (length - cnt != 0) {
u_int avp_length;
avp_length = l2tp_avp_print(ndo, ptr, length - cnt);
if (avp_length == 0) {
/*
* Truncated.
*/
break;
}
cnt += avp_length;
ptr += avp_length;
}
}
} else {
ND_PRINT(" {");
ppp_print(ndo, ptr, length - cnt);
ND_PRINT("}");
}
return;
trunc:
nd_print_trunc(ndo);
}
diff --git a/contrib/tcpdump/print-lane.c b/contrib/tcpdump/print-lane.c
index c5fa33beb4a8..5ae35acf1bde 100644
--- a/contrib/tcpdump/print-lane.c
+++ b/contrib/tcpdump/print-lane.c
@@ -1,110 +1,108 @@
/*
* Marko Kiiskila carnil@cs.tut.fi
*
* Tampere University of Technology - Telecommunications Laboratory
*
* Permission to use, copy, modify and distribute this
* software and its documentation is hereby granted,
* provided that both the copyright notice and this
* permission notice appear in all copies of the software,
* derivative works or modified versions, and any portions
* thereof, that both notices appear in supporting
* documentation, and that the use of this software is
* acknowledged in any publications resulting from using
* the software.
*
* TUT ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION AND DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS
* SOFTWARE.
*
*/
/* \summary: ATM LANE printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
struct lecdatahdr_8023 {
nd_uint16_t le_header;
nd_mac_addr h_dest;
nd_mac_addr h_source;
nd_uint16_t h_type;
};
struct lane_controlhdr {
nd_uint16_t lec_header;
nd_uint8_t lec_proto;
nd_uint8_t lec_vers;
nd_uint16_t lec_opcode;
};
static const struct tok lecop2str[] = {
{ 0x0001, "configure request" },
{ 0x0101, "configure response" },
{ 0x0002, "join request" },
{ 0x0102, "join response" },
{ 0x0003, "ready query" },
{ 0x0103, "ready indication" },
{ 0x0004, "register request" },
{ 0x0104, "register response" },
{ 0x0005, "unregister request" },
{ 0x0105, "unregister response" },
{ 0x0006, "ARP request" },
{ 0x0106, "ARP response" },
{ 0x0007, "flush request" },
{ 0x0107, "flush response" },
{ 0x0008, "NARP request" },
{ 0x0009, "topology request" },
{ 0, NULL }
};
static void
lane_hdr_print(netdissect_options *ndo, const u_char *bp)
{
ND_PRINT("lecid:%x ", GET_BE_U_2(bp));
}
/*
* This assumes 802.3, not 802.5, LAN emulation.
*/
void
lane_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen)
{
const struct lane_controlhdr *lec;
ndo->ndo_protocol = "lane";
lec = (const struct lane_controlhdr *)p;
if (GET_BE_U_2(lec->lec_header) == 0xff00) {
/*
* LE Control.
*/
ND_PRINT("lec: proto %x vers %x %s",
GET_U_1(lec->lec_proto),
GET_U_1(lec->lec_vers),
tok2str(lecop2str, "opcode-#%u", GET_BE_U_2(lec->lec_opcode)));
return;
}
/*
* Go past the LE header.
*/
ND_TCHECK_2(p); /* Needed */
length -= 2;
caplen -= 2;
p += 2;
/*
* Now print the encapsulated frame, under the assumption
* that it's an Ethernet frame.
*/
ether_print(ndo, p, length, caplen, lane_hdr_print, p - 2);
}
diff --git a/contrib/tcpdump/print-ldp.c b/contrib/tcpdump/print-ldp.c
index 896bc40395fa..1ee453b20f5c 100644
--- a/contrib/tcpdump/print-ldp.c
+++ b/contrib/tcpdump/print-ldp.c
@@ -1,700 +1,702 @@
/*
* 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.
*
* Original code by Hannes Gredler (hannes@gredler.at)
* and Steinar Haug (sthaug@nethelp.no)
*/
/* \summary: Label Distribution Protocol (LDP) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "extract.h"
#include "addrtoname.h"
#include "l2vpn.h"
#include "af.h"
/*
* ldp common header
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Version | PDU Length |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | LDP Identifier |
* + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*/
struct ldp_common_header {
nd_uint16_t version;
nd_uint16_t pdu_length;
nd_ipv4 lsr_id;
nd_uint16_t label_space;
};
#define LDP_VERSION 1
/*
* ldp message header
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |U| Message Type | Message Length |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Message ID |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* + +
* | Mandatory Parameters |
* + +
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* + +
* | Optional Parameters |
* + +
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct ldp_msg_header {
nd_uint16_t type;
nd_uint16_t length;
nd_uint32_t id;
};
#define LDP_MASK_MSG_TYPE(x) ((x)&0x7fff)
#define LDP_MASK_U_BIT(x) ((x)&0x8000)
#define LDP_MSG_NOTIF 0x0001
#define LDP_MSG_HELLO 0x0100
#define LDP_MSG_INIT 0x0200
#define LDP_MSG_KEEPALIVE 0x0201
#define LDP_MSG_ADDRESS 0x0300
#define LDP_MSG_ADDRESS_WITHDRAW 0x0301
#define LDP_MSG_LABEL_MAPPING 0x0400
#define LDP_MSG_LABEL_REQUEST 0x0401
#define LDP_MSG_LABEL_WITHDRAW 0x0402
#define LDP_MSG_LABEL_RELEASE 0x0403
#define LDP_MSG_LABEL_ABORT_REQUEST 0x0404
#define LDP_VENDOR_PRIVATE_MIN 0x3e00
#define LDP_VENDOR_PRIVATE_MAX 0x3eff
#define LDP_EXPERIMENTAL_MIN 0x3f00
#define LDP_EXPERIMENTAL_MAX 0x3fff
static const struct tok ldp_msg_values[] = {
{ LDP_MSG_NOTIF, "Notification" },
{ LDP_MSG_HELLO, "Hello" },
{ LDP_MSG_INIT, "Initialization" },
{ LDP_MSG_KEEPALIVE, "Keepalive" },
{ LDP_MSG_ADDRESS, "Address" },
{ LDP_MSG_ADDRESS_WITHDRAW, "Address Withdraw" },
{ LDP_MSG_LABEL_MAPPING, "Label Mapping" },
{ LDP_MSG_LABEL_REQUEST, "Label Request" },
{ LDP_MSG_LABEL_WITHDRAW, "Label Withdraw" },
{ LDP_MSG_LABEL_RELEASE, "Label Release" },
{ LDP_MSG_LABEL_ABORT_REQUEST, "Label Abort Request" },
{ 0, NULL}
};
#define LDP_MASK_TLV_TYPE(x) ((x)&0x3fff)
#define LDP_MASK_F_BIT(x) ((x)&0x4000)
#define LDP_TLV_FEC 0x0100
#define LDP_TLV_ADDRESS_LIST 0x0101
#define LDP_TLV_ADDRESS_LIST_AFNUM_LEN 2
#define LDP_TLV_HOP_COUNT 0x0103
#define LDP_TLV_PATH_VECTOR 0x0104
#define LDP_TLV_GENERIC_LABEL 0x0200
#define LDP_TLV_ATM_LABEL 0x0201
#define LDP_TLV_FR_LABEL 0x0202
#define LDP_TLV_STATUS 0x0300
#define LDP_TLV_EXTD_STATUS 0x0301
#define LDP_TLV_RETURNED_PDU 0x0302
#define LDP_TLV_RETURNED_MSG 0x0303
#define LDP_TLV_COMMON_HELLO 0x0400
#define LDP_TLV_IPV4_TRANSPORT_ADDR 0x0401
#define LDP_TLV_CONFIG_SEQ_NUMBER 0x0402
#define LDP_TLV_IPV6_TRANSPORT_ADDR 0x0403
#define LDP_TLV_COMMON_SESSION 0x0500
#define LDP_TLV_ATM_SESSION_PARM 0x0501
#define LDP_TLV_FR_SESSION_PARM 0x0502
#define LDP_TLV_FT_SESSION 0x0503
#define LDP_TLV_LABEL_REQUEST_MSG_ID 0x0600
#define LDP_TLV_MTU 0x0601 /* rfc 3988 */
static const struct tok ldp_tlv_values[] = {
{ LDP_TLV_FEC, "FEC" },
{ LDP_TLV_ADDRESS_LIST, "Address List" },
{ LDP_TLV_HOP_COUNT, "Hop Count" },
{ LDP_TLV_PATH_VECTOR, "Path Vector" },
{ LDP_TLV_GENERIC_LABEL, "Generic Label" },
{ LDP_TLV_ATM_LABEL, "ATM Label" },
{ LDP_TLV_FR_LABEL, "Frame-Relay Label" },
{ LDP_TLV_STATUS, "Status" },
{ LDP_TLV_EXTD_STATUS, "Extended Status" },
{ LDP_TLV_RETURNED_PDU, "Returned PDU" },
{ LDP_TLV_RETURNED_MSG, "Returned Message" },
{ LDP_TLV_COMMON_HELLO, "Common Hello Parameters" },
{ LDP_TLV_IPV4_TRANSPORT_ADDR, "IPv4 Transport Address" },
{ LDP_TLV_CONFIG_SEQ_NUMBER, "Configuration Sequence Number" },
{ LDP_TLV_IPV6_TRANSPORT_ADDR, "IPv6 Transport Address" },
{ LDP_TLV_COMMON_SESSION, "Common Session Parameters" },
{ LDP_TLV_ATM_SESSION_PARM, "ATM Session Parameters" },
{ LDP_TLV_FR_SESSION_PARM, "Frame-Relay Session Parameters" },
{ LDP_TLV_FT_SESSION, "Fault-Tolerant Session Parameters" },
{ LDP_TLV_LABEL_REQUEST_MSG_ID, "Label Request Message ID" },
{ LDP_TLV_MTU, "MTU" },
{ 0, NULL}
};
#define LDP_FEC_WILDCARD 0x01
#define LDP_FEC_PREFIX 0x02
#define LDP_FEC_HOSTADDRESS 0x03
/* From RFC 4906; should probably be updated to RFC 4447 (e.g., VC -> PW) */
#define LDP_FEC_MARTINI_VC 0x80
static const struct tok ldp_fec_values[] = {
{ LDP_FEC_WILDCARD, "Wildcard" },
{ LDP_FEC_PREFIX, "Prefix" },
{ LDP_FEC_HOSTADDRESS, "Host address" },
{ LDP_FEC_MARTINI_VC, "Martini VC" },
{ 0, NULL}
};
#define LDP_FEC_MARTINI_IFPARM_MTU 0x01
#define LDP_FEC_MARTINI_IFPARM_DESC 0x03
#define LDP_FEC_MARTINI_IFPARM_VCCV 0x0c
static const struct tok ldp_fec_martini_ifparm_values[] = {
{ LDP_FEC_MARTINI_IFPARM_MTU, "MTU" },
{ LDP_FEC_MARTINI_IFPARM_DESC, "Description" },
{ LDP_FEC_MARTINI_IFPARM_VCCV, "VCCV" },
{ 0, NULL}
};
/* draft-ietf-pwe3-vccv-04.txt */
static const struct tok ldp_fec_martini_ifparm_vccv_cc_values[] = {
{ 0x01, "PWE3 control word" },
{ 0x02, "MPLS Router Alert Label" },
{ 0x04, "MPLS inner label TTL = 1" },
{ 0, NULL}
};
/* draft-ietf-pwe3-vccv-04.txt */
static const struct tok ldp_fec_martini_ifparm_vccv_cv_values[] = {
{ 0x01, "ICMP Ping" },
{ 0x02, "LSP Ping" },
{ 0x04, "BFD" },
{ 0, NULL}
};
static u_int ldp_pdu_print(netdissect_options *, const u_char *);
/*
* ldp tlv header
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |U|F| Type | Length |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* | Value |
* ~ ~
* | |
* | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
#define TLV_TCHECK(minlen) \
if (tlv_tlen < minlen) { \
ND_PRINT(" [tlv length %u < %u]", tlv_tlen, minlen); \
nd_print_invalid(ndo); \
goto invalid; \
}
static u_int
ldp_tlv_print(netdissect_options *ndo,
const u_char *tptr,
u_int msg_tlen)
{
struct ldp_tlv_header {
nd_uint16_t type;
nd_uint16_t length;
};
const struct ldp_tlv_header *ldp_tlv_header;
u_short tlv_type,tlv_len,tlv_tlen,af,ft_flags;
u_char fec_type;
u_int ui,vc_info_len, vc_info_tlv_type, vc_info_tlv_len,idx;
char buf[100];
int i;
ldp_tlv_header = (const struct ldp_tlv_header *)tptr;
ND_TCHECK_SIZE(ldp_tlv_header);
tlv_len=GET_BE_U_2(ldp_tlv_header->length);
if (tlv_len + 4U > msg_tlen) {
ND_PRINT("\n\t\t TLV contents go past end of message");
return 0;
}
tlv_tlen=tlv_len;
tlv_type=LDP_MASK_TLV_TYPE(GET_BE_U_2(ldp_tlv_header->type));
/* FIXME vendor private / experimental check */
ND_PRINT("\n\t %s TLV (0x%04x), length: %u, Flags: [%s and %s forward if unknown]",
tok2str(ldp_tlv_values,
"Unknown",
tlv_type),
tlv_type,
tlv_len,
LDP_MASK_U_BIT(GET_BE_U_2(ldp_tlv_header->type)) ? "continue processing" : "ignore",
LDP_MASK_F_BIT(GET_BE_U_2(ldp_tlv_header->type)) ? "do" : "don't");
tptr+=sizeof(struct ldp_tlv_header);
switch(tlv_type) {
case LDP_TLV_COMMON_HELLO:
TLV_TCHECK(4);
ND_PRINT("\n\t Hold Time: %us, Flags: [%s Hello%s]",
GET_BE_U_2(tptr),
(GET_BE_U_2(tptr + 2)&0x8000) ? "Targeted" : "Link",
(GET_BE_U_2(tptr + 2)&0x4000) ? ", Request for targeted Hellos" : "");
break;
case LDP_TLV_IPV4_TRANSPORT_ADDR:
TLV_TCHECK(4);
ND_PRINT("\n\t IPv4 Transport Address: %s", GET_IPADDR_STRING(tptr));
break;
case LDP_TLV_IPV6_TRANSPORT_ADDR:
TLV_TCHECK(16);
ND_PRINT("\n\t IPv6 Transport Address: %s", GET_IP6ADDR_STRING(tptr));
break;
case LDP_TLV_CONFIG_SEQ_NUMBER:
TLV_TCHECK(4);
ND_PRINT("\n\t Sequence Number: %u", GET_BE_U_4(tptr));
break;
case LDP_TLV_ADDRESS_LIST:
TLV_TCHECK(LDP_TLV_ADDRESS_LIST_AFNUM_LEN);
af = GET_BE_U_2(tptr);
tptr+=LDP_TLV_ADDRESS_LIST_AFNUM_LEN;
tlv_tlen -= LDP_TLV_ADDRESS_LIST_AFNUM_LEN;
ND_PRINT("\n\t Address Family: %s, addresses",
tok2str(af_values, "Unknown (%u)", af));
switch (af) {
case AFNUM_INET:
while(tlv_tlen >= sizeof(nd_ipv4)) {
ND_PRINT(" %s", GET_IPADDR_STRING(tptr));
tlv_tlen-=sizeof(nd_ipv4);
tptr+=sizeof(nd_ipv4);
}
break;
case AFNUM_INET6:
while(tlv_tlen >= sizeof(nd_ipv6)) {
ND_PRINT(" %s", GET_IP6ADDR_STRING(tptr));
tlv_tlen-=sizeof(nd_ipv6);
tptr+=sizeof(nd_ipv6);
}
break;
default:
/* unknown AF */
break;
}
break;
case LDP_TLV_COMMON_SESSION:
- TLV_TCHECK(8);
+ TLV_TCHECK(14);
ND_PRINT("\n\t Version: %u, Keepalive: %us, Flags: [Downstream %s, Loop Detection %s]",
GET_BE_U_2(tptr), GET_BE_U_2(tptr + 2),
- (GET_BE_U_2(tptr + 6)&0x8000) ? "On Demand" : "Unsolicited",
- (GET_BE_U_2(tptr + 6)&0x4000) ? "Enabled" : "Disabled"
+ (GET_BE_U_2(tptr + 4)&0x8000) ? "On Demand" : "Unsolicited",
+ (GET_BE_U_2(tptr + 4)&0x4000) ? "Enabled" : "Disabled"
+ );
+ ND_PRINT("\n\t Path Vector Limit %u, Max-PDU length: %u, Receiver Label-Space-ID %s:%u",
+ GET_U_1(tptr+5),
+ GET_BE_U_2(tptr+6),
+ GET_IPADDR_STRING(tptr+8),
+ GET_BE_U_2(tptr+12)
);
break;
case LDP_TLV_FEC:
TLV_TCHECK(1);
fec_type = GET_U_1(tptr);
ND_PRINT("\n\t %s FEC (0x%02x)",
tok2str(ldp_fec_values, "Unknown", fec_type),
fec_type);
tptr+=1;
tlv_tlen-=1;
switch(fec_type) {
case LDP_FEC_WILDCARD:
break;
case LDP_FEC_PREFIX:
TLV_TCHECK(2);
af = GET_BE_U_2(tptr);
tptr+=2;
tlv_tlen-=2;
if (af == AFNUM_INET) {
i=decode_prefix4(ndo, tptr, tlv_tlen, buf, sizeof(buf));
if (i == -2)
goto trunc;
if (i == -3)
ND_PRINT(": IPv4 prefix (goes past end of TLV)");
else if (i == -1)
ND_PRINT(": IPv4 prefix (invalid length)");
else
ND_PRINT(": IPv4 prefix %s", buf);
- }
- else if (af == AFNUM_INET6) {
+ } else if (af == AFNUM_INET6) {
i=decode_prefix6(ndo, tptr, tlv_tlen, buf, sizeof(buf));
if (i == -2)
goto trunc;
if (i == -3)
ND_PRINT(": IPv4 prefix (goes past end of TLV)");
else if (i == -1)
ND_PRINT(": IPv6 prefix (invalid length)");
else
ND_PRINT(": IPv6 prefix %s", buf);
- }
- else
+ } else
ND_PRINT(": Address family %u prefix", af);
break;
case LDP_FEC_HOSTADDRESS:
break;
case LDP_FEC_MARTINI_VC:
/*
* We assume the type was supposed to be one of the MPLS
* Pseudowire Types.
*/
TLV_TCHECK(7);
vc_info_len = GET_U_1(tptr + 2);
/*
* According to RFC 4908, the VC info Length field can be zero,
* in which case not only are there no interface parameters,
* there's no VC ID.
*/
if (vc_info_len == 0) {
ND_PRINT(": %s, %scontrol word, group-ID %u, VC-info-length: %u",
tok2str(mpls_pw_types_values, "Unknown", GET_BE_U_2(tptr)&0x7fff),
GET_BE_U_2(tptr)&0x8000 ? "" : "no ",
GET_BE_U_4(tptr + 3),
vc_info_len);
break;
}
/* Make sure we have the VC ID as well */
TLV_TCHECK(11);
ND_PRINT(": %s, %scontrol word, group-ID %u, VC-ID %u, VC-info-length: %u",
tok2str(mpls_pw_types_values, "Unknown", GET_BE_U_2(tptr)&0x7fff),
GET_BE_U_2(tptr)&0x8000 ? "" : "no ",
GET_BE_U_4(tptr + 3),
GET_BE_U_4(tptr + 7),
vc_info_len);
if (vc_info_len < 4) {
/* minimum 4, for the VC ID */
ND_PRINT(" (invalid, < 4");
return(tlv_len+4); /* Type & Length fields not included */
}
vc_info_len -= 4; /* subtract out the VC ID, giving the length of the interface parameters */
/* Skip past the fixed information and the VC ID */
tptr+=11;
tlv_tlen-=11;
TLV_TCHECK(vc_info_len);
while (vc_info_len > 2) {
vc_info_tlv_type = GET_U_1(tptr);
vc_info_tlv_len = GET_U_1(tptr + 1);
if (vc_info_tlv_len < 2)
break;
if (vc_info_len < vc_info_tlv_len)
break;
ND_PRINT("\n\t\tInterface Parameter: %s (0x%02x), len %u",
tok2str(ldp_fec_martini_ifparm_values,"Unknown",vc_info_tlv_type),
vc_info_tlv_type,
vc_info_tlv_len);
switch(vc_info_tlv_type) {
case LDP_FEC_MARTINI_IFPARM_MTU:
ND_PRINT(": %u", GET_BE_U_2(tptr + 2));
break;
case LDP_FEC_MARTINI_IFPARM_DESC:
ND_PRINT(": ");
for (idx = 2; idx < vc_info_tlv_len; idx++)
fn_print_char(ndo, GET_U_1(tptr + idx));
break;
case LDP_FEC_MARTINI_IFPARM_VCCV:
ND_PRINT("\n\t\t Control Channels (0x%02x) = [%s]",
GET_U_1((tptr + 2)),
bittok2str(ldp_fec_martini_ifparm_vccv_cc_values, "none", GET_U_1((tptr + 2))));
ND_PRINT("\n\t\t CV Types (0x%02x) = [%s]",
GET_U_1((tptr + 3)),
bittok2str(ldp_fec_martini_ifparm_vccv_cv_values, "none", GET_U_1((tptr + 3))));
break;
default:
print_unknown_data(ndo, tptr+2, "\n\t\t ", vc_info_tlv_len-2);
break;
}
vc_info_len -= vc_info_tlv_len;
tptr += vc_info_tlv_len;
}
break;
}
break;
case LDP_TLV_GENERIC_LABEL:
TLV_TCHECK(4);
ND_PRINT("\n\t Label: %u", GET_BE_U_4(tptr) & 0xfffff);
break;
case LDP_TLV_STATUS:
TLV_TCHECK(8);
ui = GET_BE_U_4(tptr);
tptr+=4;
ND_PRINT("\n\t Status: 0x%02x, Flags: [%s and %s forward]",
ui&0x3fffffff,
ui&0x80000000 ? "Fatal error" : "Advisory Notification",
ui&0x40000000 ? "do" : "don't");
ui = GET_BE_U_4(tptr);
tptr+=4;
if (ui)
ND_PRINT(", causing Message ID: 0x%08x", ui);
break;
case LDP_TLV_FT_SESSION:
TLV_TCHECK(12);
ft_flags = GET_BE_U_2(tptr);
ND_PRINT("\n\t Flags: [%sReconnect, %sSave State, %sAll-Label Protection, %s Checkpoint, %sRe-Learn State]",
ft_flags&0x8000 ? "" : "No ",
ft_flags&0x8 ? "" : "Don't ",
ft_flags&0x4 ? "" : "No ",
ft_flags&0x2 ? "Sequence Numbered Label" : "All Labels",
ft_flags&0x1 ? "" : "Don't ");
/* 16 bits (FT Flags) + 16 bits (Reserved) */
tptr+=4;
ui = GET_BE_U_4(tptr);
if (ui)
ND_PRINT(", Reconnect Timeout: %ums", ui);
tptr+=4;
ui = GET_BE_U_4(tptr);
if (ui)
ND_PRINT(", Recovery Time: %ums", ui);
break;
case LDP_TLV_MTU:
TLV_TCHECK(2);
ND_PRINT("\n\t MTU: %u", GET_BE_U_2(tptr));
break;
/*
* FIXME those are the defined TLVs that lack a decoder
* you are welcome to contribute code ;-)
*/
case LDP_TLV_HOP_COUNT:
case LDP_TLV_PATH_VECTOR:
case LDP_TLV_ATM_LABEL:
case LDP_TLV_FR_LABEL:
case LDP_TLV_EXTD_STATUS:
case LDP_TLV_RETURNED_PDU:
case LDP_TLV_RETURNED_MSG:
case LDP_TLV_ATM_SESSION_PARM:
case LDP_TLV_FR_SESSION_PARM:
case LDP_TLV_LABEL_REQUEST_MSG_ID:
default:
if (ndo->ndo_vflag <= 1)
print_unknown_data(ndo, tptr, "\n\t ", tlv_tlen);
break;
}
return(tlv_len+4); /* Type & Length fields not included */
trunc:
nd_trunc_longjmp(ndo);
invalid:
return(tlv_len+4); /* Type & Length fields not included */
}
void
ldp_print(netdissect_options *ndo,
const u_char *pptr, u_int len)
{
u_int processed;
ndo->ndo_protocol = "ldp";
while (len > (sizeof(struct ldp_common_header) + sizeof(struct ldp_msg_header))) {
processed = ldp_pdu_print(ndo, pptr);
if (processed == 0)
return;
if (len < processed) {
ND_PRINT(" [remaining length %u < %u]", len, processed);
nd_print_invalid(ndo);
break;
}
len -= processed;
pptr += processed;
}
}
static u_int
ldp_pdu_print(netdissect_options *ndo,
const u_char *pptr)
{
const struct ldp_common_header *ldp_com_header;
const struct ldp_msg_header *ldp_msg_header;
const u_char *tptr,*msg_tptr;
u_short tlen;
u_short pdu_len,msg_len,msg_type;
u_int msg_tlen;
int hexdump,processed;
ldp_com_header = (const struct ldp_common_header *)pptr;
ND_TCHECK_SIZE(ldp_com_header);
/*
* Sanity checking of the header.
*/
if (GET_BE_U_2(ldp_com_header->version) != LDP_VERSION) {
ND_PRINT("%sLDP version %u packet not supported",
(ndo->ndo_vflag < 1) ? "" : "\n\t",
GET_BE_U_2(ldp_com_header->version));
return 0;
}
pdu_len = GET_BE_U_2(ldp_com_header->pdu_length);
if (pdu_len < sizeof(struct ldp_common_header)-4) {
/* length too short */
ND_PRINT("%sLDP, pdu-length: %u (too short, < %zu)",
(ndo->ndo_vflag < 1) ? "" : "\n\t",
pdu_len,
sizeof(struct ldp_common_header)-4);
return 0;
}
/* print the LSR-ID, label-space & length */
ND_PRINT("%sLDP, Label-Space-ID: %s:%u, pdu-length: %u",
(ndo->ndo_vflag < 1) ? "" : "\n\t",
GET_IPADDR_STRING(ldp_com_header->lsr_id),
GET_BE_U_2(ldp_com_header->label_space),
pdu_len);
/* bail out if non-verbose */
if (ndo->ndo_vflag < 1)
return 0;
/* ok they seem to want to know everything - lets fully decode it */
tptr = pptr + sizeof(struct ldp_common_header);
tlen = pdu_len - (sizeof(struct ldp_common_header)-4); /* Type & Length fields not included */
while(tlen>0) {
/* did we capture enough for fully decoding the msg header ? */
ND_TCHECK_LEN(tptr, sizeof(struct ldp_msg_header));
ldp_msg_header = (const struct ldp_msg_header *)tptr;
msg_len=GET_BE_U_2(ldp_msg_header->length);
msg_type=LDP_MASK_MSG_TYPE(GET_BE_U_2(ldp_msg_header->type));
if (msg_len < sizeof(struct ldp_msg_header)-4) {
/* length too short */
/* FIXME vendor private / experimental check */
ND_PRINT("\n\t %s Message (0x%04x), length: %u (too short, < %zu)",
tok2str(ldp_msg_values,
"Unknown",
msg_type),
msg_type,
msg_len,
sizeof(struct ldp_msg_header)-4);
return 0;
}
/* FIXME vendor private / experimental check */
ND_PRINT("\n\t %s Message (0x%04x), length: %u, Message ID: 0x%08x, Flags: [%s if unknown]",
tok2str(ldp_msg_values,
"Unknown",
msg_type),
msg_type,
msg_len,
GET_BE_U_4(ldp_msg_header->id),
LDP_MASK_U_BIT(GET_BE_U_2(ldp_msg_header->type)) ? "continue processing" : "ignore");
msg_tptr=tptr+sizeof(struct ldp_msg_header);
msg_tlen=msg_len-(sizeof(struct ldp_msg_header)-4); /* Type & Length fields not included */
/* did we capture enough for fully decoding the message ? */
ND_TCHECK_LEN(tptr, msg_len);
hexdump=FALSE;
switch(msg_type) {
case LDP_MSG_NOTIF:
case LDP_MSG_HELLO:
case LDP_MSG_INIT:
case LDP_MSG_KEEPALIVE:
case LDP_MSG_ADDRESS:
case LDP_MSG_LABEL_MAPPING:
case LDP_MSG_ADDRESS_WITHDRAW:
case LDP_MSG_LABEL_WITHDRAW:
while(msg_tlen >= 4) {
processed = ldp_tlv_print(ndo, msg_tptr, msg_tlen);
if (processed == 0)
break;
msg_tlen-=processed;
msg_tptr+=processed;
}
break;
/*
* FIXME those are the defined messages that lack a decoder
* you are welcome to contribute code ;-)
*/
case LDP_MSG_LABEL_REQUEST:
case LDP_MSG_LABEL_RELEASE:
case LDP_MSG_LABEL_ABORT_REQUEST:
default:
if (ndo->ndo_vflag <= 1)
print_unknown_data(ndo, msg_tptr, "\n\t ", msg_tlen);
break;
}
/* do we want to see an additionally hexdump ? */
if (ndo->ndo_vflag > 1 || hexdump==TRUE)
print_unknown_data(ndo, tptr+sizeof(struct ldp_msg_header), "\n\t ",
msg_len);
tptr += msg_len+4;
tlen -= msg_len+4;
}
return pdu_len+4;
trunc:
nd_trunc_longjmp(ndo);
}
diff --git a/contrib/tcpdump/print-lisp.c b/contrib/tcpdump/print-lisp.c
index 756fff0ffc5a..da1312265797 100644
--- a/contrib/tcpdump/print-lisp.c
+++ b/contrib/tcpdump/print-lisp.c
@@ -1,453 +1,451 @@
/*
* Copyright (c) 2015 Ritesh Ranjan (r.ranjan789@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* \summary: - Locator/Identifier Separation Protocol (LISP) printer */
/*
* specification: RFC 6830
*
*
* The Map-Register message format is:
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |Type=3 |P|S|I|R| Reserved |M| Record Count |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Nonce . . . |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | . . . Nonce |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Key ID | Authentication Data Length |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* ~ Authentication Data ~
* +-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | | Record TTL |
* | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* R | Locator Count | EID mask-len | ACT |A| Reserved |
* e +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* c | Rsvd | Map-Version Number | EID-Prefix-AFI |
* o +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* r | EID-Prefix |
* d +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | /| Priority | Weight | M Priority | M Weight |
* | L +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | o | Unused Flags |L|p|R| Loc-AFI |
* | c +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | \| Locator |
* +-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*
* The Map-Notify message format is:
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |Type=4 |I|R| Reserved | Record Count |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Nonce . . . |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | . . . Nonce |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Key ID | Authentication Data Length |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* ~ Authentication Data ~
* +-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | | Record TTL |
* | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* R | Locator Count | EID mask-len | ACT |A| Reserved |
* e +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* c | Rsvd | Map-Version Number | EID-Prefix-AFI |
* o +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* r | EID-Prefix |
* d +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | /| Priority | Weight | M Priority | M Weight |
* | L +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | o | Unused Flags |L|p|R| Loc-AFI |
* | c +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | \| Locator |
* +-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "ip.h"
#include "ip6.h"
#include "extract.h"
#include "addrtoname.h"
#define IPv4_AFI 1
#define IPv6_AFI 2
#define TYPE_INDEX 4
#define LISP_MAP_NOTIFY_IBIT_MASK 8
#define LISP_MAP_REGISTER_IBIT_MASK 2
enum {
LISP_MAP_REQUEST = 1,
LISP_MAP_REPLY,
LISP_MAP_REGISTER,
LISP_MAP_NOTIFY,
LISP_ENCAPSULATED_CONTROL_MESSAGE = 8
};
enum {
LISP_AUTH_NONE,
LISP_AUTH_SHA1,
LISP_AUTH_SHA256
};
static const struct tok lisp_type [] = {
- { 0, "LISP-Reserved" },
- { 1, "LISP-Map-Request" },
- { 2, "LISP-Map-Reply" },
- { 3, "LISP-Map-Register" },
- { 4, "LISP-Map-Notify" },
- { 8, "LISP-Encapsulated-Contol-Message" },
+ { 0, "LISP-Reserved" },
+ { 1, "LISP-Map-Request" },
+ { 2, "LISP-Map-Reply" },
+ { 3, "LISP-Map-Register" },
+ { 4, "LISP-Map-Notify" },
+ { 8, "LISP-Encapsulated-Control-Message" },
{ 0, NULL }
};
/*
* P-Bit : Request for Proxy Map-Reply from the MS/MR
* S-Bit : Security Enhancement. ETR is LISP-SEC enabled. draft-ietf-lisp-sec
* I-Bit : 128 bit xTR-ID and 64 bit Site-ID present.
* xTR-ID and Site-ID help in differentiation of xTRs in multi xTR
* and multi Site deployment scenarios.
* R-Bit : Built for a Reencapsulating-Tunnel-Router. Used in Traffic
* Engineering and Service Chaining
*/
static const struct tok map_register_hdr_flag[] = {
{ 0x08000000, "P-Proxy-Map-Reply" },
{ 0x04000000, "S-LISP-SEC-Capable" },
{ 0x02000000, "I-xTR-ID-Present" },
{ 0x01000000, "R-Build-For-RTR" },
{ 0x00000100, "M-Want-Map-Notify" },
{ 0, NULL }
};
static const struct tok map_notify_hdr_flag[] = {
{ 0x08000000, "I-xTR-ID-Present" },
{ 0x04000000, "R-Build-For-RTR" },
{ 0, NULL }
};
static const struct tok auth_type[] = {
{ LISP_AUTH_NONE, "None" },
{ LISP_AUTH_SHA1, "SHA1" },
{ LISP_AUTH_SHA256, "SHA256" },
{ 0, NULL}
};
static const struct tok lisp_eid_action[] = {
{ 0, "No-Action" },
{ 1, "Natively-Forward" },
{ 2, "Send-Map-Request" },
{ 3, "Drop" },
{ 0, NULL}
};
static const struct tok lisp_loc_flag[] = {
{ 0x0004, "Local-Locator" },
{ 0x0002, "RLoc-Probed" },
{ 0x0001, "Reachable" },
{ 0, NULL }
};
typedef struct map_register_hdr {
nd_uint8_t type_and_flag;
nd_uint8_t reserved;
nd_uint8_t reserved_and_flag2;
nd_uint8_t record_count;
nd_uint64_t nonce;
nd_uint16_t key_id;
nd_uint16_t auth_data_len;
} lisp_map_register_hdr;
#define MAP_REGISTER_HDR_LEN sizeof(lisp_map_register_hdr)
typedef struct map_register_eid {
nd_uint32_t ttl;
nd_uint8_t locator_count;
nd_uint8_t eid_prefix_mask_length;
nd_uint8_t act_auth_inc_res;
nd_uint8_t reserved;
nd_uint16_t reserved_and_version;
nd_uint16_t eid_prefix_afi;
} lisp_map_register_eid;
#define MAP_REGISTER_EID_LEN sizeof(lisp_map_register_eid)
typedef struct map_register_loc {
nd_uint8_t priority;
nd_uint8_t weight;
nd_uint8_t m_priority;
nd_uint8_t m_weight;
nd_uint16_t unused_and_flag;
nd_uint16_t locator_afi;
} lisp_map_register_loc;
#define MAP_REGISTER_LOC_LEN sizeof(lisp_map_register_loc)
static uint8_t extract_lisp_type(uint8_t);
static uint8_t is_xtr_data_present(uint8_t, uint8_t);
static void lisp_hdr_flag(netdissect_options *, const lisp_map_register_hdr *);
static void action_flag(netdissect_options *, uint8_t);
static void loc_hdr_flag(netdissect_options *, uint16_t);
void
lisp_print(netdissect_options *ndo, const u_char *bp, u_int length)
{
uint8_t type_and_flag;
uint8_t type;
uint8_t mask_len;
uint8_t loc_count;
uint8_t xtr_present;
uint8_t record_count;
uint16_t key_id;
uint16_t eid_afi;
uint16_t loc_afi;
uint16_t map_version;
uint16_t packet_offset;
uint16_t auth_data_len;
uint32_t ttl;
const u_char *packet_iterator;
const u_char *loc_ip_pointer;
const lisp_map_register_hdr *lisp_hdr;
const lisp_map_register_eid *lisp_eid;
const lisp_map_register_loc *lisp_loc;
ndo->ndo_protocol = "lisp";
/* Check if enough bytes for header are available */
ND_TCHECK_LEN(bp, MAP_REGISTER_HDR_LEN);
lisp_hdr = (const lisp_map_register_hdr *) bp;
lisp_hdr_flag(ndo, lisp_hdr);
/* Supporting only MAP NOTIFY and MAP REGISTER LISP packets */
type_and_flag = GET_U_1(lisp_hdr->type_and_flag);
type = extract_lisp_type(type_and_flag);
if ((type != LISP_MAP_REGISTER) && (type != LISP_MAP_NOTIFY))
return;
/* Find if the packet contains xTR and Site-ID data */
xtr_present = is_xtr_data_present(type, type_and_flag);
/* Extract the number of EID records present */
auth_data_len = GET_BE_U_2(lisp_hdr->auth_data_len);
packet_iterator = (const u_char *)(lisp_hdr);
packet_offset = MAP_REGISTER_HDR_LEN;
record_count = GET_U_1(lisp_hdr->record_count);
if (ndo->ndo_vflag) {
key_id = GET_BE_U_2(lisp_hdr->key_id);
ND_PRINT("\n %u record(s), ", record_count);
ND_PRINT("Authentication %s,",
tok2str(auth_type, "unknown-type", key_id));
hex_print(ndo, "\n Authentication-Data: ", packet_iterator +
packet_offset, auth_data_len);
} else {
ND_PRINT(" %u record(s),", record_count);
}
packet_offset += auth_data_len;
if (record_count == 0)
goto invalid;
/* Print all the EID records */
while ((length > packet_offset) && (record_count != 0)) {
record_count--;
ND_TCHECK_LEN(packet_iterator + packet_offset,
MAP_REGISTER_EID_LEN);
ND_PRINT("\n");
lisp_eid = (const lisp_map_register_eid *)
((const u_char *)lisp_hdr + packet_offset);
packet_offset += MAP_REGISTER_EID_LEN;
mask_len = GET_U_1(lisp_eid->eid_prefix_mask_length);
eid_afi = GET_BE_U_2(lisp_eid->eid_prefix_afi);
loc_count = GET_U_1(lisp_eid->locator_count);
if (ndo->ndo_vflag) {
ttl = GET_BE_U_4(lisp_eid->ttl);
ND_PRINT(" Record TTL %u,", ttl);
action_flag(ndo, GET_U_1(lisp_eid->act_auth_inc_res));
map_version = GET_BE_U_2(lisp_eid->reserved_and_version) & 0x0FFF;
ND_PRINT(" Map Version: %u,", map_version);
}
switch (eid_afi) {
case IPv4_AFI:
ND_PRINT(" EID %s/%u,",
GET_IPADDR_STRING(packet_iterator + packet_offset),
mask_len);
packet_offset += 4;
break;
case IPv6_AFI:
ND_PRINT(" EID %s/%u,",
GET_IP6ADDR_STRING(packet_iterator + packet_offset),
mask_len);
packet_offset += 16;
break;
default:
/*
* No support for LCAF right now.
*/
return;
break;
}
ND_PRINT(" %u locator(s)", loc_count);
while (loc_count != 0) {
loc_count--;
ND_TCHECK_LEN(packet_iterator + packet_offset,
MAP_REGISTER_LOC_LEN);
lisp_loc = (const lisp_map_register_loc *) (packet_iterator + packet_offset);
loc_ip_pointer = (const u_char *) (lisp_loc + 1);
packet_offset += MAP_REGISTER_LOC_LEN;
loc_afi = GET_BE_U_2(lisp_loc->locator_afi);
if (ndo->ndo_vflag)
ND_PRINT("\n ");
switch (loc_afi) {
case IPv4_AFI:
ND_TCHECK_4(packet_iterator + packet_offset);
ND_PRINT(" LOC %s", GET_IPADDR_STRING(loc_ip_pointer));
packet_offset += 4;
break;
case IPv6_AFI:
ND_TCHECK_16(packet_iterator + packet_offset);
ND_PRINT(" LOC %s", GET_IP6ADDR_STRING(loc_ip_pointer));
packet_offset += 16;
break;
default:
break;
}
if (ndo->ndo_vflag) {
ND_PRINT("\n Priority/Weight %u/%u,"
" Multicast Priority/Weight %u/%u,",
GET_U_1(lisp_loc->priority),
GET_U_1(lisp_loc->weight),
GET_U_1(lisp_loc->m_priority),
GET_U_1(lisp_loc->m_weight));
loc_hdr_flag(ndo,
GET_BE_U_2(lisp_loc->unused_and_flag));
}
}
}
/*
* Print xTR and Site ID. Handle the fact that the packet could be invalid.
* If the xTR_ID_Present bit is not set, and we still have data to display,
* show it as hex data.
*/
if (xtr_present) {
if (!ND_TTEST_LEN(packet_iterator + packet_offset, 24))
goto invalid;
hex_print(ndo, "\n xTR-ID: ", packet_iterator + packet_offset, 16);
ND_PRINT("\n SITE-ID: %" PRIu64,
GET_BE_U_8(packet_iterator + packet_offset + 16));
} else {
/* Check if packet isn't over yet */
if (packet_iterator + packet_offset < ndo->ndo_snapend) {
hex_print(ndo, "\n Data: ", packet_iterator + packet_offset,
ND_BYTES_AVAILABLE_AFTER(packet_iterator + packet_offset));
}
}
return;
trunc:
nd_print_trunc(ndo);
return;
invalid:
nd_print_invalid(ndo);
}
static uint8_t
extract_lisp_type(uint8_t lisp_hdr_flags)
{
return (lisp_hdr_flags) >> TYPE_INDEX;
}
static uint8_t
is_xtr_data_present(uint8_t type, uint8_t lisp_hdr_flags)
{
uint8_t xtr_present = 0;
if (type == LISP_MAP_REGISTER)
xtr_present = (lisp_hdr_flags) & LISP_MAP_REGISTER_IBIT_MASK;
else if (type == LISP_MAP_NOTIFY)
xtr_present = (lisp_hdr_flags) & LISP_MAP_NOTIFY_IBIT_MASK;
return xtr_present;
}
static void lisp_hdr_flag(netdissect_options *ndo, const lisp_map_register_hdr *lisp_hdr)
{
uint8_t type = extract_lisp_type(GET_U_1(lisp_hdr->type_and_flag));
if (!ndo->ndo_vflag) {
ND_PRINT("%s,", tok2str(lisp_type, "unknown-type-%u", type));
return;
} else {
ND_PRINT("%s,", tok2str(lisp_type, "unknown-type-%u", type));
}
if (type == LISP_MAP_REGISTER) {
ND_PRINT(" flags [%s],", bittok2str(map_register_hdr_flag,
"none", GET_BE_U_4(lisp_hdr)));
} else if (type == LISP_MAP_NOTIFY) {
ND_PRINT(" flags [%s],", bittok2str(map_notify_hdr_flag,
"none", GET_BE_U_4(lisp_hdr)));
}
}
static void action_flag(netdissect_options *ndo, uint8_t act_auth_inc_res)
{
uint8_t action;
uint8_t authoritative;
authoritative = ((act_auth_inc_res >> 4) & 1);
if (authoritative)
ND_PRINT(" Authoritative,");
else
ND_PRINT(" Non-Authoritative,");
action = act_auth_inc_res >> 5;
ND_PRINT(" %s,", tok2str(lisp_eid_action, "unknown", action));
}
static void loc_hdr_flag(netdissect_options *ndo, uint16_t flag)
{
ND_PRINT(" flags [%s],", bittok2str(lisp_loc_flag, "none", flag));
}
diff --git a/contrib/tcpdump/print-llc.c b/contrib/tcpdump/print-llc.c
index ae3ae4cf5c34..ac6307a85210 100644
--- a/contrib/tcpdump/print-llc.c
+++ b/contrib/tcpdump/print-llc.c
@@ -1,610 +1,608 @@
/*
* Copyright (c) 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.
*
* Code by Matt Thomas, Digital Equipment Corporation
* with an awful lot of hacking by Jeffrey Mogul, DECWRL
*/
/* \summary: IEEE 802.2 LLC printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#include "llc.h"
#include "ethertype.h"
#include "oui.h"
static const struct tok llc_values[] = {
{ LLCSAP_NULL, "Null" },
{ LLCSAP_GLOBAL, "Global" },
{ LLCSAP_8021B_I, "802.1B I" },
{ LLCSAP_8021B_G, "802.1B G" },
{ LLCSAP_IP, "IP" },
{ LLCSAP_SNA, "SNA" },
{ LLCSAP_PROWAYNM, "ProWay NM" },
{ LLCSAP_8021D, "STP" },
{ LLCSAP_RS511, "RS511" },
{ LLCSAP_ISO8208, "ISO8208" },
{ LLCSAP_PROWAY, "ProWay" },
{ LLCSAP_SNAP, "SNAP" },
{ LLCSAP_IPX, "IPX" },
{ LLCSAP_NETBEUI, "NetBeui" },
{ LLCSAP_ISONS, "OSI" },
{ 0, NULL },
};
static const struct tok llc_cmd_values[] = {
{ LLC_UI, "ui" },
{ LLC_TEST, "test" },
{ LLC_XID, "xid" },
{ LLC_UA, "ua" },
{ LLC_DISC, "disc" },
{ LLC_DM, "dm" },
{ LLC_SABME, "sabme" },
{ LLC_FRMR, "frmr" },
{ 0, NULL }
};
static const struct tok llc_flag_values[] = {
{ 0, "Command" },
{ LLC_GSAP, "Response" },
{ LLC_U_POLL, "Poll" },
{ LLC_GSAP|LLC_U_POLL, "Final" },
{ LLC_IS_POLL, "Poll" },
{ LLC_GSAP|LLC_IS_POLL, "Final" },
{ 0, NULL }
};
static const struct tok llc_ig_flag_values[] = {
{ 0, "Individual" },
{ LLC_IG, "Group" },
{ 0, NULL }
};
static const struct tok llc_supervisory_values[] = {
{ 0, "Receiver Ready" },
{ 1, "Receiver not Ready" },
{ 2, "Reject" },
{ 0, NULL }
};
static const struct tok cisco_values[] = {
{ PID_CISCO_CDP, "CDP" },
{ PID_CISCO_VTP, "VTP" },
{ PID_CISCO_DTP, "DTP" },
{ PID_CISCO_UDLD, "UDLD" },
{ PID_CISCO_PVST, "PVST" },
{ PID_CISCO_VLANBRIDGE, "VLAN Bridge" },
{ 0, NULL }
};
static const struct tok bridged_values[] = {
{ PID_RFC2684_ETH_FCS, "Ethernet + FCS" },
{ PID_RFC2684_ETH_NOFCS, "Ethernet w/o FCS" },
{ PID_RFC2684_802_4_FCS, "802.4 + FCS" },
{ PID_RFC2684_802_4_NOFCS, "802.4 w/o FCS" },
{ PID_RFC2684_802_5_FCS, "Token Ring + FCS" },
{ PID_RFC2684_802_5_NOFCS, "Token Ring w/o FCS" },
{ PID_RFC2684_FDDI_FCS, "FDDI + FCS" },
{ PID_RFC2684_FDDI_NOFCS, "FDDI w/o FCS" },
{ PID_RFC2684_802_6_FCS, "802.6 + FCS" },
{ PID_RFC2684_802_6_NOFCS, "802.6 w/o FCS" },
{ PID_RFC2684_BPDU, "BPDU" },
{ 0, NULL },
};
static const struct tok null_values[] = {
{ 0, NULL }
};
struct oui_tok {
uint32_t oui;
const struct tok *tok;
};
static const struct oui_tok oui_to_tok[] = {
{ OUI_ENCAP_ETHER, ethertype_values },
{ OUI_CISCO_90, ethertype_values }, /* uses some Ethertype values */
{ OUI_APPLETALK, ethertype_values }, /* uses some Ethertype values */
{ OUI_CISCO, cisco_values },
{ OUI_RFC2684, bridged_values }, /* bridged, RFC 2427 FR or RFC 2864 ATM */
{ 0, NULL }
};
/*
* If we printed information about the payload, returns the length of the LLC
* header, plus the length of any SNAP header following it.
*
* Otherwise (for example, if the packet has unknown SAPs or has a SNAP
* header with an unknown OUI/PID combination), returns the *negative*
* of that value.
*/
int
llc_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen,
const struct lladdr_info *src, const struct lladdr_info *dst)
{
uint8_t dsap_field, dsap, ssap_field, ssap;
uint16_t control;
int hdrlen;
int is_u;
ndo->ndo_protocol = "llc";
if (caplen < 3) {
nd_print_trunc(ndo);
ND_DEFAULTPRINT((const u_char *)p, caplen);
return (caplen);
}
if (length < 3) {
nd_print_trunc(ndo);
ND_DEFAULTPRINT((const u_char *)p, caplen);
return (length);
}
dsap_field = GET_U_1(p);
ssap_field = GET_U_1(p + 1);
/*
* OK, what type of LLC frame is this? The length
* of the control field depends on that - I frames
* have a two-byte control field, and U frames have
* a one-byte control field.
*/
control = GET_U_1(p + 2);
if ((control & LLC_U_FMT) == LLC_U_FMT) {
/*
* U frame.
*/
is_u = 1;
hdrlen = 3; /* DSAP, SSAP, 1-byte control field */
} else {
/*
* The control field in I and S frames is
* 2 bytes...
*/
if (caplen < 4) {
nd_print_trunc(ndo);
ND_DEFAULTPRINT((const u_char *)p, caplen);
return (caplen);
}
if (length < 4) {
nd_print_trunc(ndo);
ND_DEFAULTPRINT((const u_char *)p, caplen);
return (length);
}
/*
* ...and is little-endian.
*/
control = GET_LE_U_2(p + 2);
is_u = 0;
hdrlen = 4; /* DSAP, SSAP, 2-byte control field */
}
if (ssap_field == LLCSAP_GLOBAL && dsap_field == LLCSAP_GLOBAL) {
/*
* This is an Ethernet_802.3 IPX frame; it has an
* 802.3 header (i.e., an Ethernet header where the
* type/length field is <= MAX_ETHERNET_LENGTH_VAL,
* i.e. it's a length field, not a type field), but
* has no 802.2 header - the IPX packet starts right
* after the Ethernet header, with a signature of two
* bytes of 0xFF (which is LLCSAP_GLOBAL).
*
* (It might also have been an Ethernet_802.3 IPX at
* one time, but got bridged onto another network,
* such as an 802.11 network; this has appeared in at
* least one capture file.)
*/
if (ndo->ndo_eflag)
ND_PRINT("IPX 802.3: ");
ipx_print(ndo, p, length);
return (0); /* no LLC header */
}
dsap = dsap_field & ~LLC_IG;
ssap = ssap_field & ~LLC_GSAP;
if (ndo->ndo_eflag) {
ND_PRINT("LLC, dsap %s (0x%02x) %s, ssap %s (0x%02x) %s",
tok2str(llc_values, "Unknown", dsap),
dsap,
tok2str(llc_ig_flag_values, "Unknown", dsap_field & LLC_IG),
tok2str(llc_values, "Unknown", ssap),
ssap,
tok2str(llc_flag_values, "Unknown", ssap_field & LLC_GSAP));
if (is_u) {
ND_PRINT(", ctrl 0x%02x: ", control);
} else {
ND_PRINT(", ctrl 0x%04x: ", control);
}
}
/*
* Skip LLC header.
*/
p += hdrlen;
length -= hdrlen;
caplen -= hdrlen;
if (ssap == LLCSAP_SNAP && dsap == LLCSAP_SNAP
&& control == LLC_UI) {
/*
* XXX - what *is* the right bridge pad value here?
* Does anybody ever bridge one form of LAN traffic
* over a networking type that uses 802.2 LLC?
*/
if (!snap_print(ndo, p, length, caplen, src, dst, 2)) {
/*
* Unknown packet type; tell our caller, by
* returning a negative value, so they
* can print the raw packet.
*/
return (-(hdrlen + 5)); /* include LLC and SNAP header */
} else
return (hdrlen + 5); /* include LLC and SNAP header */
}
if (ssap == LLCSAP_8021D && dsap == LLCSAP_8021D &&
control == LLC_UI) {
stp_print(ndo, p, length);
return (hdrlen);
}
if (ssap == LLCSAP_IP && dsap == LLCSAP_IP &&
control == LLC_UI) {
/*
* This is an RFC 948-style IP packet, with
* an 802.3 header and an 802.2 LLC header
* with the source and destination SAPs being
* the IP SAP.
*/
ip_print(ndo, p, length);
return (hdrlen);
}
if (ssap == LLCSAP_IPX && dsap == LLCSAP_IPX &&
control == LLC_UI) {
/*
* This is an Ethernet_802.2 IPX frame, with an 802.3
* header and an 802.2 LLC header with the source and
* destination SAPs being the IPX SAP.
*/
if (ndo->ndo_eflag)
ND_PRINT("IPX 802.2: ");
ipx_print(ndo, p, length);
return (hdrlen);
}
#ifdef ENABLE_SMB
if (ssap == LLCSAP_NETBEUI && dsap == LLCSAP_NETBEUI
&& (!(control & LLC_S_FMT) || control == LLC_U_FMT)) {
/*
* we don't actually have a full netbeui parser yet, but the
* smb parser can handle many smb-in-netbeui packets, which
* is very useful, so we call that
*
* We don't call it for S frames, however, just I frames
* (which are frames that don't have the low-order bit,
* LLC_S_FMT, set in the first byte of the control field)
* and UI frames (whose control field is just 3, LLC_U_FMT).
*/
netbeui_print(ndo, control, p, length);
return (hdrlen);
}
#endif
if (ssap == LLCSAP_ISONS && dsap == LLCSAP_ISONS
&& control == LLC_UI) {
isoclns_print(ndo, p, length);
return (hdrlen);
}
if (!ndo->ndo_eflag) {
if (ssap == dsap) {
if (src == NULL || dst == NULL)
ND_PRINT("%s ", tok2str(llc_values, "Unknown DSAP 0x%02x", dsap));
else
ND_PRINT("%s > %s %s ",
(src->addr_string)(ndo, src->addr),
(dst->addr_string)(ndo, dst->addr),
tok2str(llc_values, "Unknown DSAP 0x%02x", dsap));
} else {
if (src == NULL || dst == NULL)
ND_PRINT("%s > %s ",
tok2str(llc_values, "Unknown SSAP 0x%02x", ssap),
tok2str(llc_values, "Unknown DSAP 0x%02x", dsap));
else
ND_PRINT("%s %s > %s %s ",
(src->addr_string)(ndo, src->addr),
tok2str(llc_values, "Unknown SSAP 0x%02x", ssap),
(dst->addr_string)(ndo, dst->addr),
tok2str(llc_values, "Unknown DSAP 0x%02x", dsap));
}
}
if (is_u) {
ND_PRINT("Unnumbered, %s, Flags [%s], length %u",
tok2str(llc_cmd_values, "%02x", LLC_U_CMD(control)),
tok2str(llc_flag_values,"?",(ssap_field & LLC_GSAP) | (control & LLC_U_POLL)),
length + hdrlen);
if ((control & ~LLC_U_POLL) == LLC_XID) {
if (length == 0) {
/*
* XID with no payload.
* This could, for example, be an SNA
* "short form" XID.
*/
return (hdrlen);
}
if (caplen < 1) {
nd_print_trunc(ndo);
if (caplen > 0)
ND_DEFAULTPRINT((const u_char *)p, caplen);
return (hdrlen);
}
if (GET_U_1(p) == LLC_XID_FI) {
if (caplen < 3 || length < 3) {
nd_print_trunc(ndo);
if (caplen > 0)
ND_DEFAULTPRINT((const u_char *)p, caplen);
} else
ND_PRINT(": %02x %02x",
GET_U_1(p + 1),
GET_U_1(p + 2));
return (hdrlen);
}
}
} else {
if ((control & LLC_S_FMT) == LLC_S_FMT) {
ND_PRINT("Supervisory, %s, rcv seq %u, Flags [%s], length %u",
tok2str(llc_supervisory_values,"?",LLC_S_CMD(control)),
LLC_IS_NR(control),
tok2str(llc_flag_values,"?",(ssap_field & LLC_GSAP) | (control & LLC_IS_POLL)),
length + hdrlen);
return (hdrlen); /* no payload to print */
} else {
ND_PRINT("Information, send seq %u, rcv seq %u, Flags [%s], length %u",
LLC_I_NS(control),
LLC_IS_NR(control),
tok2str(llc_flag_values,"?",(ssap_field & LLC_GSAP) | (control & LLC_IS_POLL)),
length + hdrlen);
}
}
return (-hdrlen);
}
static const struct tok *
oui_to_struct_tok(uint32_t orgcode)
{
const struct tok *tok = null_values;
const struct oui_tok *otp;
for (otp = &oui_to_tok[0]; otp->tok != NULL; otp++) {
if (otp->oui == orgcode) {
tok = otp->tok;
break;
}
}
return (tok);
}
int
snap_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen,
const struct lladdr_info *src, const struct lladdr_info *dst,
u_int bridge_pad)
{
uint32_t orgcode;
u_short et;
int ret;
ndo->ndo_protocol = "snap";
ND_TCHECK_5(p);
if (caplen < 5 || length < 5)
goto trunc;
orgcode = GET_BE_U_3(p);
et = GET_BE_U_2(p + 3);
if (ndo->ndo_eflag) {
/*
* Somebody's already printed the MAC addresses, if there
* are any, so just print the SNAP header, not the MAC
* addresses.
*/
ND_PRINT("oui %s (0x%06x), %s %s (0x%04x), length %u: ",
tok2str(oui_values, "Unknown", orgcode),
orgcode,
(orgcode == 0x000000 ? "ethertype" : "pid"),
tok2str(oui_to_struct_tok(orgcode), "Unknown", et),
et, length - 5);
}
p += 5;
length -= 5;
caplen -= 5;
switch (orgcode) {
case OUI_ENCAP_ETHER:
case OUI_CISCO_90:
/*
* This is an encapsulated Ethernet packet,
* or a packet bridged by some piece of
* Cisco hardware; the protocol ID is
* an Ethernet protocol type.
*/
ret = ethertype_print(ndo, et, p, length, caplen, src, dst);
if (ret)
return (ret);
break;
case OUI_APPLETALK:
if (et == ETHERTYPE_ATALK) {
/*
* No, I have no idea why Apple used one
* of their own OUIs, rather than
* 0x000000, and an Ethernet packet
* type, for Appletalk data packets,
* but used 0x000000 and an Ethernet
* packet type for AARP packets.
*/
ret = ethertype_print(ndo, et, p, length, caplen, src, dst);
if (ret)
return (ret);
}
break;
case OUI_CISCO:
switch (et) {
case PID_CISCO_CDP:
cdp_print(ndo, p, length);
return (1);
case PID_CISCO_DTP:
dtp_print(ndo, p, length);
return (1);
case PID_CISCO_UDLD:
udld_print(ndo, p, length);
return (1);
case PID_CISCO_VTP:
vtp_print(ndo, p, length);
return (1);
case PID_CISCO_PVST:
case PID_CISCO_VLANBRIDGE:
stp_print(ndo, p, length);
return (1);
default:
break;
}
break;
case OUI_RFC2684:
switch (et) {
case PID_RFC2684_ETH_FCS:
case PID_RFC2684_ETH_NOFCS:
/*
* XXX - remove the last two bytes for
* PID_RFC2684_ETH_FCS?
*/
/*
* Skip the padding.
*/
ND_TCHECK_LEN(p, bridge_pad);
caplen -= bridge_pad;
length -= bridge_pad;
p += bridge_pad;
/*
* What remains is an Ethernet packet.
*/
ether_print(ndo, p, length, caplen, NULL, NULL);
return (1);
case PID_RFC2684_802_5_FCS:
case PID_RFC2684_802_5_NOFCS:
/*
* XXX - remove the last two bytes for
* PID_RFC2684_ETH_FCS?
*/
/*
* Skip the padding, but not the Access
* Control field.
*/
ND_TCHECK_LEN(p, bridge_pad);
caplen -= bridge_pad;
length -= bridge_pad;
p += bridge_pad;
/*
* What remains is an 802.5 Token Ring
* packet.
*/
token_print(ndo, p, length, caplen);
return (1);
case PID_RFC2684_FDDI_FCS:
case PID_RFC2684_FDDI_NOFCS:
/*
* XXX - remove the last two bytes for
* PID_RFC2684_ETH_FCS?
*/
/*
* Skip the padding.
*/
ND_TCHECK_LEN(p, bridge_pad + 1);
caplen -= bridge_pad + 1;
length -= bridge_pad + 1;
p += bridge_pad + 1;
/*
* What remains is an FDDI packet.
*/
fddi_print(ndo, p, length, caplen);
return (1);
case PID_RFC2684_BPDU:
stp_print(ndo, p, length);
return (1);
}
}
if (!ndo->ndo_eflag) {
/*
* Nobody printed the link-layer addresses, so print them, if
* we have any.
*/
if (src != NULL && dst != NULL) {
ND_PRINT("%s > %s ",
(src->addr_string)(ndo, src->addr),
(dst->addr_string)(ndo, dst->addr));
}
/*
* Print the SNAP header, but if the OUI is 000000, don't
* bother printing it, and report the PID as being an
* ethertype.
*/
if (orgcode == 0x000000) {
ND_PRINT("SNAP, ethertype %s (0x%04x), length %u: ",
tok2str(ethertype_values, "Unknown", et),
et, length);
} else {
ND_PRINT("SNAP, oui %s (0x%06x), pid %s (0x%04x), length %u: ",
tok2str(oui_values, "Unknown", orgcode),
orgcode,
tok2str(oui_to_struct_tok(orgcode), "Unknown", et),
et, length);
}
}
return (0);
trunc:
nd_print_trunc(ndo);
return (1);
}
diff --git a/contrib/tcpdump/print-lldp.c b/contrib/tcpdump/print-lldp.c
index f0e5f60c672d..a0bd6ac42001 100644
--- a/contrib/tcpdump/print-lldp.c
+++ b/contrib/tcpdump/print-lldp.c
@@ -1,1682 +1,1680 @@
/*
* Copyright (c) 1998-2007 The TCPDUMP project
*
* 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.
*
* Original code by Hannes Gredler (hannes@gredler.at)
* IEEE and TIA extensions by Carles Kishimoto <carles.kishimoto@gmail.com>
* DCBX extensions by Kaladhar Musunuru <kaladharm@sourceforge.net>
*/
/* \summary: IEEE 802.1ab Link Layer Discovery Protocol (LLDP) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <stdio.h>
#include "netdissect.h"
#include "extract.h"
#include "addrtoname.h"
#include "af.h"
#include "oui.h"
#define LLDP_EXTRACT_TYPE(x) (((x)&0xfe00)>>9)
#define LLDP_EXTRACT_LEN(x) ((x)&0x01ff)
/*
* TLV type codes
*/
#define LLDP_END_TLV 0
#define LLDP_CHASSIS_ID_TLV 1
#define LLDP_PORT_ID_TLV 2
#define LLDP_TTL_TLV 3
#define LLDP_PORT_DESCR_TLV 4
#define LLDP_SYSTEM_NAME_TLV 5
#define LLDP_SYSTEM_DESCR_TLV 6
#define LLDP_SYSTEM_CAP_TLV 7
#define LLDP_MGMT_ADDR_TLV 8
#define LLDP_PRIVATE_TLV 127
static const struct tok lldp_tlv_values[] = {
{ LLDP_END_TLV, "End" },
{ LLDP_CHASSIS_ID_TLV, "Chassis ID" },
{ LLDP_PORT_ID_TLV, "Port ID" },
{ LLDP_TTL_TLV, "Time to Live" },
{ LLDP_PORT_DESCR_TLV, "Port Description" },
{ LLDP_SYSTEM_NAME_TLV, "System Name" },
{ LLDP_SYSTEM_DESCR_TLV, "System Description" },
{ LLDP_SYSTEM_CAP_TLV, "System Capabilities" },
{ LLDP_MGMT_ADDR_TLV, "Management Address" },
{ LLDP_PRIVATE_TLV, "Organization specific" },
{ 0, NULL}
};
/*
* Chassis ID subtypes
*/
#define LLDP_CHASSIS_CHASSIS_COMP_SUBTYPE 1
#define LLDP_CHASSIS_INTF_ALIAS_SUBTYPE 2
#define LLDP_CHASSIS_PORT_COMP_SUBTYPE 3
#define LLDP_CHASSIS_MAC_ADDR_SUBTYPE 4
#define LLDP_CHASSIS_NETWORK_ADDR_SUBTYPE 5
#define LLDP_CHASSIS_INTF_NAME_SUBTYPE 6
#define LLDP_CHASSIS_LOCAL_SUBTYPE 7
static const struct tok lldp_chassis_subtype_values[] = {
{ LLDP_CHASSIS_CHASSIS_COMP_SUBTYPE, "Chassis component"},
{ LLDP_CHASSIS_INTF_ALIAS_SUBTYPE, "Interface alias"},
{ LLDP_CHASSIS_PORT_COMP_SUBTYPE, "Port component"},
{ LLDP_CHASSIS_MAC_ADDR_SUBTYPE, "MAC address"},
{ LLDP_CHASSIS_NETWORK_ADDR_SUBTYPE, "Network address"},
{ LLDP_CHASSIS_INTF_NAME_SUBTYPE, "Interface name"},
{ LLDP_CHASSIS_LOCAL_SUBTYPE, "Local"},
{ 0, NULL}
};
/*
* Port ID subtypes
*/
#define LLDP_PORT_INTF_ALIAS_SUBTYPE 1
#define LLDP_PORT_PORT_COMP_SUBTYPE 2
#define LLDP_PORT_MAC_ADDR_SUBTYPE 3
#define LLDP_PORT_NETWORK_ADDR_SUBTYPE 4
#define LLDP_PORT_INTF_NAME_SUBTYPE 5
#define LLDP_PORT_AGENT_CIRC_ID_SUBTYPE 6
#define LLDP_PORT_LOCAL_SUBTYPE 7
static const struct tok lldp_port_subtype_values[] = {
{ LLDP_PORT_INTF_ALIAS_SUBTYPE, "Interface alias"},
{ LLDP_PORT_PORT_COMP_SUBTYPE, "Port component"},
{ LLDP_PORT_MAC_ADDR_SUBTYPE, "MAC address"},
{ LLDP_PORT_NETWORK_ADDR_SUBTYPE, "Network Address"},
{ LLDP_PORT_INTF_NAME_SUBTYPE, "Interface Name"},
{ LLDP_PORT_AGENT_CIRC_ID_SUBTYPE, "Agent circuit ID"},
{ LLDP_PORT_LOCAL_SUBTYPE, "Local"},
{ 0, NULL}
};
/*
* System Capabilities
*/
#define LLDP_CAP_OTHER (1 << 0)
#define LLDP_CAP_REPEATER (1 << 1)
#define LLDP_CAP_BRIDGE (1 << 2)
#define LLDP_CAP_WLAN_AP (1 << 3)
#define LLDP_CAP_ROUTER (1 << 4)
#define LLDP_CAP_PHONE (1 << 5)
#define LLDP_CAP_DOCSIS (1 << 6)
#define LLDP_CAP_STATION_ONLY (1 << 7)
static const struct tok lldp_cap_values[] = {
{ LLDP_CAP_OTHER, "Other"},
{ LLDP_CAP_REPEATER, "Repeater"},
{ LLDP_CAP_BRIDGE, "Bridge"},
{ LLDP_CAP_WLAN_AP, "WLAN AP"},
{ LLDP_CAP_ROUTER, "Router"},
{ LLDP_CAP_PHONE, "Telephone"},
{ LLDP_CAP_DOCSIS, "Docsis"},
{ LLDP_CAP_STATION_ONLY, "Station Only"},
{ 0, NULL}
};
#define LLDP_PRIVATE_8021_SUBTYPE_PORT_VLAN_ID 1
#define LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_VLAN_ID 2
#define LLDP_PRIVATE_8021_SUBTYPE_VLAN_NAME 3
#define LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_IDENTITY 4
#define LLDP_PRIVATE_8021_SUBTYPE_LINKAGGR 7
#define LLDP_PRIVATE_8021_SUBTYPE_CONGESTION_NOTIFICATION 8
#define LLDP_PRIVATE_8021_SUBTYPE_ETS_CONFIGURATION 9
#define LLDP_PRIVATE_8021_SUBTYPE_ETS_RECOMMENDATION 10
#define LLDP_PRIVATE_8021_SUBTYPE_PFC_CONFIGURATION 11
#define LLDP_PRIVATE_8021_SUBTYPE_APPLICATION_PRIORITY 12
#define LLDP_PRIVATE_8021_SUBTYPE_EVB 13
#define LLDP_PRIVATE_8021_SUBTYPE_CDCP 14
static const struct tok lldp_8021_subtype_values[] = {
{ LLDP_PRIVATE_8021_SUBTYPE_PORT_VLAN_ID, "Port VLAN Id"},
{ LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_VLAN_ID, "Port and Protocol VLAN ID"},
{ LLDP_PRIVATE_8021_SUBTYPE_VLAN_NAME, "VLAN name"},
{ LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_IDENTITY, "Protocol Identity"},
{ LLDP_PRIVATE_8021_SUBTYPE_LINKAGGR, "Link aggregation"},
{ LLDP_PRIVATE_8021_SUBTYPE_CONGESTION_NOTIFICATION, "Congestion Notification"},
{ LLDP_PRIVATE_8021_SUBTYPE_ETS_CONFIGURATION, "ETS Configuration"},
{ LLDP_PRIVATE_8021_SUBTYPE_ETS_RECOMMENDATION, "ETS Recommendation"},
{ LLDP_PRIVATE_8021_SUBTYPE_PFC_CONFIGURATION, "Priority Flow Control Configuration"},
{ LLDP_PRIVATE_8021_SUBTYPE_APPLICATION_PRIORITY, "Application Priority"},
{ LLDP_PRIVATE_8021_SUBTYPE_EVB, "EVB"},
{ LLDP_PRIVATE_8021_SUBTYPE_CDCP,"CDCP"},
{ 0, NULL}
};
#define LLDP_8021_PORT_PROTOCOL_VLAN_SUPPORT (1 << 1)
#define LLDP_8021_PORT_PROTOCOL_VLAN_STATUS (1 << 2)
static const struct tok lldp_8021_port_protocol_id_values[] = {
{ LLDP_8021_PORT_PROTOCOL_VLAN_SUPPORT, "supported"},
{ LLDP_8021_PORT_PROTOCOL_VLAN_STATUS, "enabled"},
{ 0, NULL}
};
#define LLDP_PRIVATE_8023_SUBTYPE_MACPHY 1
#define LLDP_PRIVATE_8023_SUBTYPE_MDIPOWER 2
#define LLDP_PRIVATE_8023_SUBTYPE_LINKAGGR 3
#define LLDP_PRIVATE_8023_SUBTYPE_MTU 4
static const struct tok lldp_8023_subtype_values[] = {
{ LLDP_PRIVATE_8023_SUBTYPE_MACPHY, "MAC/PHY configuration/status"},
{ LLDP_PRIVATE_8023_SUBTYPE_MDIPOWER, "Power via MDI"},
{ LLDP_PRIVATE_8023_SUBTYPE_LINKAGGR, "Link aggregation"},
{ LLDP_PRIVATE_8023_SUBTYPE_MTU, "Max frame size"},
{ 0, NULL}
};
#define LLDP_PRIVATE_TIA_SUBTYPE_CAPABILITIES 1
#define LLDP_PRIVATE_TIA_SUBTYPE_NETWORK_POLICY 2
#define LLDP_PRIVATE_TIA_SUBTYPE_LOCAL_ID 3
#define LLDP_PRIVATE_TIA_SUBTYPE_EXTENDED_POWER_MDI 4
#define LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_HARDWARE_REV 5
#define LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_FIRMWARE_REV 6
#define LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SOFTWARE_REV 7
#define LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SERIAL_NUMBER 8
#define LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MANUFACTURER_NAME 9
#define LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MODEL_NAME 10
#define LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_ASSET_ID 11
static const struct tok lldp_tia_subtype_values[] = {
{ LLDP_PRIVATE_TIA_SUBTYPE_CAPABILITIES, "LLDP-MED Capabilities" },
{ LLDP_PRIVATE_TIA_SUBTYPE_NETWORK_POLICY, "Network policy" },
{ LLDP_PRIVATE_TIA_SUBTYPE_LOCAL_ID, "Location identification" },
{ LLDP_PRIVATE_TIA_SUBTYPE_EXTENDED_POWER_MDI, "Extended power-via-MDI" },
{ LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_HARDWARE_REV, "Inventory - hardware revision" },
{ LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_FIRMWARE_REV, "Inventory - firmware revision" },
{ LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SOFTWARE_REV, "Inventory - software revision" },
{ LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SERIAL_NUMBER, "Inventory - serial number" },
{ LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MANUFACTURER_NAME, "Inventory - manufacturer name" },
{ LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MODEL_NAME, "Inventory - model name" },
{ LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_ASSET_ID, "Inventory - asset ID" },
{ 0, NULL}
};
#define LLDP_PRIVATE_TIA_LOCATION_ALTITUDE_METERS 1
#define LLDP_PRIVATE_TIA_LOCATION_ALTITUDE_FLOORS 2
static const struct tok lldp_tia_location_altitude_type_values[] = {
{ LLDP_PRIVATE_TIA_LOCATION_ALTITUDE_METERS, "meters"},
{ LLDP_PRIVATE_TIA_LOCATION_ALTITUDE_FLOORS, "floors"},
{ 0, NULL}
};
/* ANSI/TIA-1057 - Annex B */
#define LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A1 1
#define LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A2 2
#define LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A3 3
#define LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A4 4
#define LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A5 5
#define LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A6 6
static const struct tok lldp_tia_location_lci_catype_values[] = {
{ LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A1, "national subdivisions (state,canton,region,province,prefecture)"},
{ LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A2, "county, parish, gun, district"},
{ LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A3, "city, township, shi"},
{ LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A4, "city division, borough, city district, ward chou"},
{ LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A5, "neighborhood, block"},
{ LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A6, "street"},
{ 0, NULL}
};
static const struct tok lldp_tia_location_lci_what_values[] = {
{ 0, "location of DHCP server"},
{ 1, "location of the network element believed to be closest to the client"},
{ 2, "location of the client"},
{ 0, NULL}
};
/*
* From RFC 3636 - dot3MauType
*/
#define LLDP_MAU_TYPE_UNKNOWN 0
#define LLDP_MAU_TYPE_AUI 1
#define LLDP_MAU_TYPE_10BASE_5 2
#define LLDP_MAU_TYPE_FOIRL 3
#define LLDP_MAU_TYPE_10BASE_2 4
#define LLDP_MAU_TYPE_10BASE_T 5
#define LLDP_MAU_TYPE_10BASE_FP 6
#define LLDP_MAU_TYPE_10BASE_FB 7
#define LLDP_MAU_TYPE_10BASE_FL 8
#define LLDP_MAU_TYPE_10BROAD36 9
#define LLDP_MAU_TYPE_10BASE_T_HD 10
#define LLDP_MAU_TYPE_10BASE_T_FD 11
#define LLDP_MAU_TYPE_10BASE_FL_HD 12
#define LLDP_MAU_TYPE_10BASE_FL_FD 13
#define LLDP_MAU_TYPE_100BASE_T4 14
#define LLDP_MAU_TYPE_100BASE_TX_HD 15
#define LLDP_MAU_TYPE_100BASE_TX_FD 16
#define LLDP_MAU_TYPE_100BASE_FX_HD 17
#define LLDP_MAU_TYPE_100BASE_FX_FD 18
#define LLDP_MAU_TYPE_100BASE_T2_HD 19
#define LLDP_MAU_TYPE_100BASE_T2_FD 20
#define LLDP_MAU_TYPE_1000BASE_X_HD 21
#define LLDP_MAU_TYPE_1000BASE_X_FD 22
#define LLDP_MAU_TYPE_1000BASE_LX_HD 23
#define LLDP_MAU_TYPE_1000BASE_LX_FD 24
#define LLDP_MAU_TYPE_1000BASE_SX_HD 25
#define LLDP_MAU_TYPE_1000BASE_SX_FD 26
#define LLDP_MAU_TYPE_1000BASE_CX_HD 27
#define LLDP_MAU_TYPE_1000BASE_CX_FD 28
#define LLDP_MAU_TYPE_1000BASE_T_HD 29
#define LLDP_MAU_TYPE_1000BASE_T_FD 30
#define LLDP_MAU_TYPE_10GBASE_X 31
#define LLDP_MAU_TYPE_10GBASE_LX4 32
#define LLDP_MAU_TYPE_10GBASE_R 33
#define LLDP_MAU_TYPE_10GBASE_ER 34
#define LLDP_MAU_TYPE_10GBASE_LR 35
#define LLDP_MAU_TYPE_10GBASE_SR 36
#define LLDP_MAU_TYPE_10GBASE_W 37
#define LLDP_MAU_TYPE_10GBASE_EW 38
#define LLDP_MAU_TYPE_10GBASE_LW 39
#define LLDP_MAU_TYPE_10GBASE_SW 40
static const struct tok lldp_mau_types_values[] = {
{ LLDP_MAU_TYPE_UNKNOWN, "Unknown"},
{ LLDP_MAU_TYPE_AUI, "AUI"},
{ LLDP_MAU_TYPE_10BASE_5, "10BASE_5"},
{ LLDP_MAU_TYPE_FOIRL, "FOIRL"},
{ LLDP_MAU_TYPE_10BASE_2, "10BASE2"},
{ LLDP_MAU_TYPE_10BASE_T, "10BASET duplex mode unknown"},
{ LLDP_MAU_TYPE_10BASE_FP, "10BASEFP"},
{ LLDP_MAU_TYPE_10BASE_FB, "10BASEFB"},
{ LLDP_MAU_TYPE_10BASE_FL, "10BASEFL duplex mode unknown"},
{ LLDP_MAU_TYPE_10BROAD36, "10BROAD36"},
{ LLDP_MAU_TYPE_10BASE_T_HD, "10BASET hdx"},
{ LLDP_MAU_TYPE_10BASE_T_FD, "10BASET fdx"},
{ LLDP_MAU_TYPE_10BASE_FL_HD, "10BASEFL hdx"},
{ LLDP_MAU_TYPE_10BASE_FL_FD, "10BASEFL fdx"},
{ LLDP_MAU_TYPE_100BASE_T4, "100BASET4"},
{ LLDP_MAU_TYPE_100BASE_TX_HD, "100BASETX hdx"},
{ LLDP_MAU_TYPE_100BASE_TX_FD, "100BASETX fdx"},
{ LLDP_MAU_TYPE_100BASE_FX_HD, "100BASEFX hdx"},
{ LLDP_MAU_TYPE_100BASE_FX_FD, "100BASEFX fdx"},
{ LLDP_MAU_TYPE_100BASE_T2_HD, "100BASET2 hdx"},
{ LLDP_MAU_TYPE_100BASE_T2_FD, "100BASET2 fdx"},
{ LLDP_MAU_TYPE_1000BASE_X_HD, "1000BASEX hdx"},
{ LLDP_MAU_TYPE_1000BASE_X_FD, "1000BASEX fdx"},
{ LLDP_MAU_TYPE_1000BASE_LX_HD, "1000BASELX hdx"},
{ LLDP_MAU_TYPE_1000BASE_LX_FD, "1000BASELX fdx"},
{ LLDP_MAU_TYPE_1000BASE_SX_HD, "1000BASESX hdx"},
{ LLDP_MAU_TYPE_1000BASE_SX_FD, "1000BASESX fdx"},
{ LLDP_MAU_TYPE_1000BASE_CX_HD, "1000BASECX hdx"},
{ LLDP_MAU_TYPE_1000BASE_CX_FD, "1000BASECX fdx"},
{ LLDP_MAU_TYPE_1000BASE_T_HD, "1000BASET hdx"},
{ LLDP_MAU_TYPE_1000BASE_T_FD, "1000BASET fdx"},
{ LLDP_MAU_TYPE_10GBASE_X, "10GBASEX"},
{ LLDP_MAU_TYPE_10GBASE_LX4, "10GBASELX4"},
{ LLDP_MAU_TYPE_10GBASE_R, "10GBASER"},
{ LLDP_MAU_TYPE_10GBASE_ER, "10GBASEER"},
{ LLDP_MAU_TYPE_10GBASE_LR, "10GBASELR"},
{ LLDP_MAU_TYPE_10GBASE_SR, "10GBASESR"},
{ LLDP_MAU_TYPE_10GBASE_W, "10GBASEW"},
{ LLDP_MAU_TYPE_10GBASE_EW, "10GBASEEW"},
{ LLDP_MAU_TYPE_10GBASE_LW, "10GBASELW"},
{ LLDP_MAU_TYPE_10GBASE_SW, "10GBASESW"},
{ 0, NULL}
};
#define LLDP_8023_AUTONEGOTIATION_SUPPORT (1 << 0)
#define LLDP_8023_AUTONEGOTIATION_STATUS (1 << 1)
static const struct tok lldp_8023_autonegotiation_values[] = {
{ LLDP_8023_AUTONEGOTIATION_SUPPORT, "supported"},
{ LLDP_8023_AUTONEGOTIATION_STATUS, "enabled"},
{ 0, NULL}
};
#define LLDP_TIA_CAPABILITY_MED (1 << 0)
#define LLDP_TIA_CAPABILITY_NETWORK_POLICY (1 << 1)
#define LLDP_TIA_CAPABILITY_LOCATION_IDENTIFICATION (1 << 2)
#define LLDP_TIA_CAPABILITY_EXTENDED_POWER_MDI_PSE (1 << 3)
#define LLDP_TIA_CAPABILITY_EXTENDED_POWER_MDI_PD (1 << 4)
#define LLDP_TIA_CAPABILITY_INVENTORY (1 << 5)
static const struct tok lldp_tia_capabilities_values[] = {
{ LLDP_TIA_CAPABILITY_MED, "LLDP-MED capabilities"},
{ LLDP_TIA_CAPABILITY_NETWORK_POLICY, "network policy"},
{ LLDP_TIA_CAPABILITY_LOCATION_IDENTIFICATION, "location identification"},
{ LLDP_TIA_CAPABILITY_EXTENDED_POWER_MDI_PSE, "extended power via MDI-PSE"},
{ LLDP_TIA_CAPABILITY_EXTENDED_POWER_MDI_PD, "extended power via MDI-PD"},
{ LLDP_TIA_CAPABILITY_INVENTORY, "Inventory"},
{ 0, NULL}
};
#define LLDP_TIA_DEVICE_TYPE_ENDPOINT_CLASS_1 1
#define LLDP_TIA_DEVICE_TYPE_ENDPOINT_CLASS_2 2
#define LLDP_TIA_DEVICE_TYPE_ENDPOINT_CLASS_3 3
#define LLDP_TIA_DEVICE_TYPE_NETWORK_CONNECTIVITY 4
static const struct tok lldp_tia_device_type_values[] = {
{ LLDP_TIA_DEVICE_TYPE_ENDPOINT_CLASS_1, "endpoint class 1"},
{ LLDP_TIA_DEVICE_TYPE_ENDPOINT_CLASS_2, "endpoint class 2"},
{ LLDP_TIA_DEVICE_TYPE_ENDPOINT_CLASS_3, "endpoint class 3"},
{ LLDP_TIA_DEVICE_TYPE_NETWORK_CONNECTIVITY, "network connectivity"},
{ 0, NULL}
};
#define LLDP_TIA_APPLICATION_TYPE_VOICE 1
#define LLDP_TIA_APPLICATION_TYPE_VOICE_SIGNALING 2
#define LLDP_TIA_APPLICATION_TYPE_GUEST_VOICE 3
#define LLDP_TIA_APPLICATION_TYPE_GUEST_VOICE_SIGNALING 4
#define LLDP_TIA_APPLICATION_TYPE_SOFTPHONE_VOICE 5
#define LLDP_TIA_APPLICATION_TYPE_VIDEO_CONFERENCING 6
#define LLDP_TIA_APPLICATION_TYPE_STREAMING_VIDEO 7
#define LLDP_TIA_APPLICATION_TYPE_VIDEO_SIGNALING 8
static const struct tok lldp_tia_application_type_values[] = {
{ LLDP_TIA_APPLICATION_TYPE_VOICE, "voice"},
{ LLDP_TIA_APPLICATION_TYPE_VOICE_SIGNALING, "voice signaling"},
{ LLDP_TIA_APPLICATION_TYPE_GUEST_VOICE, "guest voice"},
{ LLDP_TIA_APPLICATION_TYPE_GUEST_VOICE_SIGNALING, "guest voice signaling"},
{ LLDP_TIA_APPLICATION_TYPE_SOFTPHONE_VOICE, "softphone voice"},
{ LLDP_TIA_APPLICATION_TYPE_VIDEO_CONFERENCING, "video conferencing"},
{ LLDP_TIA_APPLICATION_TYPE_STREAMING_VIDEO, "streaming video"},
{ LLDP_TIA_APPLICATION_TYPE_VIDEO_SIGNALING, "video signaling"},
{ 0, NULL}
};
#define LLDP_TIA_NETWORK_POLICY_X_BIT (1 << 5)
#define LLDP_TIA_NETWORK_POLICY_T_BIT (1 << 6)
#define LLDP_TIA_NETWORK_POLICY_U_BIT (1 << 7)
static const struct tok lldp_tia_network_policy_bits_values[] = {
{ LLDP_TIA_NETWORK_POLICY_U_BIT, "Unknown"},
{ LLDP_TIA_NETWORK_POLICY_T_BIT, "Tagged"},
{ LLDP_TIA_NETWORK_POLICY_X_BIT, "reserved"},
{ 0, NULL}
};
#define LLDP_EXTRACT_NETWORK_POLICY_VLAN(x) (((x)&0x1ffe)>>1)
#define LLDP_EXTRACT_NETWORK_POLICY_L2_PRIORITY(x) (((x)&0x01ff)>>6)
#define LLDP_EXTRACT_NETWORK_POLICY_DSCP(x) ((x)&0x003f)
#define LLDP_TIA_LOCATION_DATA_FORMAT_COORDINATE_BASED 1
#define LLDP_TIA_LOCATION_DATA_FORMAT_CIVIC_ADDRESS 2
#define LLDP_TIA_LOCATION_DATA_FORMAT_ECS_ELIN 3
static const struct tok lldp_tia_location_data_format_values[] = {
{ LLDP_TIA_LOCATION_DATA_FORMAT_COORDINATE_BASED, "coordinate-based LCI"},
{ LLDP_TIA_LOCATION_DATA_FORMAT_CIVIC_ADDRESS, "civic address LCI"},
{ LLDP_TIA_LOCATION_DATA_FORMAT_ECS_ELIN, "ECS ELIN"},
{ 0, NULL}
};
#define LLDP_TIA_LOCATION_DATUM_WGS_84 1
#define LLDP_TIA_LOCATION_DATUM_NAD_83_NAVD_88 2
#define LLDP_TIA_LOCATION_DATUM_NAD_83_MLLW 3
static const struct tok lldp_tia_location_datum_type_values[] = {
{ LLDP_TIA_LOCATION_DATUM_WGS_84, "World Geodesic System 1984"},
{ LLDP_TIA_LOCATION_DATUM_NAD_83_NAVD_88, "North American Datum 1983 (NAVD88)"},
{ LLDP_TIA_LOCATION_DATUM_NAD_83_MLLW, "North American Datum 1983 (MLLW)"},
{ 0, NULL}
};
#define LLDP_TIA_POWER_SOURCE_PSE 1
#define LLDP_TIA_POWER_SOURCE_LOCAL 2
#define LLDP_TIA_POWER_SOURCE_PSE_AND_LOCAL 3
static const struct tok lldp_tia_power_source_values[] = {
{ LLDP_TIA_POWER_SOURCE_PSE, "PSE - primary power source"},
{ LLDP_TIA_POWER_SOURCE_LOCAL, "local - backup power source"},
{ LLDP_TIA_POWER_SOURCE_PSE_AND_LOCAL, "PSE+local - reserved"},
{ 0, NULL}
};
#define LLDP_TIA_POWER_PRIORITY_CRITICAL 1
#define LLDP_TIA_POWER_PRIORITY_HIGH 2
#define LLDP_TIA_POWER_PRIORITY_LOW 3
static const struct tok lldp_tia_power_priority_values[] = {
{ LLDP_TIA_POWER_PRIORITY_CRITICAL, "critical"},
{ LLDP_TIA_POWER_PRIORITY_HIGH, "high"},
{ LLDP_TIA_POWER_PRIORITY_LOW, "low"},
{ 0, NULL}
};
#define LLDP_TIA_POWER_VAL_MAX 1024
static const struct tok lldp_tia_inventory_values[] = {
{ LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_HARDWARE_REV, "Hardware revision" },
{ LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_FIRMWARE_REV, "Firmware revision" },
{ LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SOFTWARE_REV, "Software revision" },
{ LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SERIAL_NUMBER, "Serial number" },
{ LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MANUFACTURER_NAME, "Manufacturer name" },
{ LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MODEL_NAME, "Model name" },
{ LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_ASSET_ID, "Asset ID" },
{ 0, NULL}
};
/*
* From RFC 3636 - ifMauAutoNegCapAdvertisedBits
*/
#define LLDP_MAU_PMD_OTHER (1 << 15)
#define LLDP_MAU_PMD_10BASE_T (1 << 14)
#define LLDP_MAU_PMD_10BASE_T_FD (1 << 13)
#define LLDP_MAU_PMD_100BASE_T4 (1 << 12)
#define LLDP_MAU_PMD_100BASE_TX (1 << 11)
#define LLDP_MAU_PMD_100BASE_TX_FD (1 << 10)
#define LLDP_MAU_PMD_100BASE_T2 (1 << 9)
#define LLDP_MAU_PMD_100BASE_T2_FD (1 << 8)
#define LLDP_MAU_PMD_FDXPAUSE (1 << 7)
#define LLDP_MAU_PMD_FDXAPAUSE (1 << 6)
#define LLDP_MAU_PMD_FDXSPAUSE (1 << 5)
#define LLDP_MAU_PMD_FDXBPAUSE (1 << 4)
#define LLDP_MAU_PMD_1000BASE_X (1 << 3)
#define LLDP_MAU_PMD_1000BASE_X_FD (1 << 2)
#define LLDP_MAU_PMD_1000BASE_T (1 << 1)
#define LLDP_MAU_PMD_1000BASE_T_FD (1 << 0)
static const struct tok lldp_pmd_capability_values[] = {
{ LLDP_MAU_PMD_10BASE_T, "10BASE-T hdx"},
{ LLDP_MAU_PMD_10BASE_T_FD, "10BASE-T fdx"},
{ LLDP_MAU_PMD_100BASE_T4, "100BASE-T4"},
{ LLDP_MAU_PMD_100BASE_TX, "100BASE-TX hdx"},
{ LLDP_MAU_PMD_100BASE_TX_FD, "100BASE-TX fdx"},
{ LLDP_MAU_PMD_100BASE_T2, "100BASE-T2 hdx"},
{ LLDP_MAU_PMD_100BASE_T2_FD, "100BASE-T2 fdx"},
{ LLDP_MAU_PMD_FDXPAUSE, "Pause for fdx links"},
{ LLDP_MAU_PMD_FDXAPAUSE, "Asym PAUSE for fdx"},
{ LLDP_MAU_PMD_FDXSPAUSE, "Sym PAUSE for fdx"},
{ LLDP_MAU_PMD_FDXBPAUSE, "Asym and Sym PAUSE for fdx"},
{ LLDP_MAU_PMD_1000BASE_X, "1000BASE-{X LX SX CX} hdx"},
{ LLDP_MAU_PMD_1000BASE_X_FD, "1000BASE-{X LX SX CX} fdx"},
{ LLDP_MAU_PMD_1000BASE_T, "1000BASE-T hdx"},
{ LLDP_MAU_PMD_1000BASE_T_FD, "1000BASE-T fdx"},
{ 0, NULL}
};
#define LLDP_MDI_PORT_CLASS (1 << 0)
#define LLDP_MDI_POWER_SUPPORT (1 << 1)
#define LLDP_MDI_POWER_STATE (1 << 2)
#define LLDP_MDI_PAIR_CONTROL_ABILITY (1 << 3)
static const struct tok lldp_mdi_values[] = {
{ LLDP_MDI_PORT_CLASS, "PSE"},
{ LLDP_MDI_POWER_SUPPORT, "supported"},
{ LLDP_MDI_POWER_STATE, "enabled"},
{ LLDP_MDI_PAIR_CONTROL_ABILITY, "can be controlled"},
{ 0, NULL}
};
#define LLDP_MDI_PSE_PORT_POWER_PAIRS_SIGNAL 1
#define LLDP_MDI_PSE_PORT_POWER_PAIRS_SPARE 2
static const struct tok lldp_mdi_power_pairs_values[] = {
{ LLDP_MDI_PSE_PORT_POWER_PAIRS_SIGNAL, "signal"},
{ LLDP_MDI_PSE_PORT_POWER_PAIRS_SPARE, "spare"},
{ 0, NULL}
};
#define LLDP_MDI_POWER_CLASS0 1
#define LLDP_MDI_POWER_CLASS1 2
#define LLDP_MDI_POWER_CLASS2 3
#define LLDP_MDI_POWER_CLASS3 4
#define LLDP_MDI_POWER_CLASS4 5
static const struct tok lldp_mdi_power_class_values[] = {
{ LLDP_MDI_POWER_CLASS0, "class0"},
{ LLDP_MDI_POWER_CLASS1, "class1"},
{ LLDP_MDI_POWER_CLASS2, "class2"},
{ LLDP_MDI_POWER_CLASS3, "class3"},
{ LLDP_MDI_POWER_CLASS4, "class4"},
{ 0, NULL}
};
#define LLDP_AGGREGATION_CAPABILITY (1 << 0)
#define LLDP_AGGREGATION_STATUS (1 << 1)
static const struct tok lldp_aggregation_values[] = {
{ LLDP_AGGREGATION_CAPABILITY, "supported"},
{ LLDP_AGGREGATION_STATUS, "enabled"},
{ 0, NULL}
};
/*
* DCBX protocol subtypes.
*/
#define LLDP_DCBX_SUBTYPE_1 1
#define LLDP_DCBX_SUBTYPE_2 2
static const struct tok lldp_dcbx_subtype_values[] = {
{ LLDP_DCBX_SUBTYPE_1, "DCB Capability Exchange Protocol Rev 1" },
{ LLDP_DCBX_SUBTYPE_2, "DCB Capability Exchange Protocol Rev 1.01" },
{ 0, NULL}
};
#define LLDP_DCBX_CONTROL_TLV 1
#define LLDP_DCBX_PRIORITY_GROUPS_TLV 2
#define LLDP_DCBX_PRIORITY_FLOW_CONTROL_TLV 3
#define LLDP_DCBX_APPLICATION_TLV 4
/*
* Interface numbering subtypes.
*/
#define LLDP_INTF_NUMB_IFX_SUBTYPE 2
#define LLDP_INTF_NUMB_SYSPORT_SUBTYPE 3
static const struct tok lldp_intf_numb_subtype_values[] = {
{ LLDP_INTF_NUMB_IFX_SUBTYPE, "Interface Index" },
{ LLDP_INTF_NUMB_SYSPORT_SUBTYPE, "System Port Number" },
{ 0, NULL}
};
#define LLDP_INTF_NUM_LEN 5
#define LLDP_EVB_MODE_NOT_SUPPORTED 0
#define LLDP_EVB_MODE_EVB_BRIDGE 1
#define LLDP_EVB_MODE_EVB_STATION 2
#define LLDP_EVB_MODE_RESERVED 3
static const struct tok lldp_evb_mode_values[]={
{ LLDP_EVB_MODE_NOT_SUPPORTED, "Not Supported"},
{ LLDP_EVB_MODE_EVB_BRIDGE, "EVB Bridge"},
{ LLDP_EVB_MODE_EVB_STATION, "EVB Station"},
{ LLDP_EVB_MODE_RESERVED, "Reserved for future Standardization"},
{ 0, NULL},
};
#define NO_OF_BITS 8
#define LLDP_PRIVATE_8021_SUBTYPE_CONGESTION_NOTIFICATION_LENGTH 6
#define LLDP_PRIVATE_8021_SUBTYPE_ETS_CONFIGURATION_LENGTH 25
#define LLDP_PRIVATE_8021_SUBTYPE_ETS_RECOMMENDATION_LENGTH 25
#define LLDP_PRIVATE_8021_SUBTYPE_PFC_CONFIGURATION_LENGTH 6
#define LLDP_PRIVATE_8021_SUBTYPE_APPLICATION_PRIORITY_MIN_LENGTH 5
#define LLDP_PRIVATE_8021_SUBTYPE_EVB_LENGTH 9
#define LLDP_PRIVATE_8021_SUBTYPE_CDCP_MIN_LENGTH 8
#define LLDP_IANA_SUBTYPE_MUDURL 1
static const struct tok lldp_iana_subtype_values[] = {
{ LLDP_IANA_SUBTYPE_MUDURL, "MUD-URL" },
{ 0, NULL }
};
static void
print_ets_priority_assignment_table(netdissect_options *ndo,
const u_char *ptr)
{
ND_PRINT("\n\t Priority Assignment Table");
ND_PRINT("\n\t Priority : 0 1 2 3 4 5 6 7");
ND_PRINT("\n\t Value : %-3d %-3d %-3d %-3d %-3d %-3d %-3d %-3d",
GET_U_1(ptr) >> 4, GET_U_1(ptr) & 0x0f,
GET_U_1(ptr + 1) >> 4, GET_U_1(ptr + 1) & 0x0f,
GET_U_1(ptr + 2) >> 4, GET_U_1(ptr + 2) & 0x0f,
GET_U_1(ptr + 3) >> 4, GET_U_1(ptr + 3) & 0x0f);
}
static void
print_tc_bandwidth_table(netdissect_options *ndo,
const u_char *ptr)
{
ND_PRINT("\n\t TC Bandwidth Table");
ND_PRINT("\n\t TC%% : 0 1 2 3 4 5 6 7");
ND_PRINT("\n\t Value : %-3d %-3d %-3d %-3d %-3d %-3d %-3d %-3d",
GET_U_1(ptr), GET_U_1(ptr + 1), GET_U_1(ptr + 2),
GET_U_1(ptr + 3), GET_U_1(ptr + 4), GET_U_1(ptr + 5),
GET_U_1(ptr + 6), GET_U_1(ptr + 7));
}
static void
print_tsa_assignment_table(netdissect_options *ndo,
const u_char *ptr)
{
ND_PRINT("\n\t TSA Assignment Table");
ND_PRINT("\n\t Traffic Class: 0 1 2 3 4 5 6 7");
ND_PRINT("\n\t Value : %-3d %-3d %-3d %-3d %-3d %-3d %-3d %-3d",
GET_U_1(ptr), GET_U_1(ptr + 1), GET_U_1(ptr + 2),
GET_U_1(ptr + 3), GET_U_1(ptr + 4), GET_U_1(ptr + 5),
GET_U_1(ptr + 6), GET_U_1(ptr + 7));
}
/*
* Print IEEE 802.1 private extensions. (802.1AB annex E)
*/
static int
lldp_private_8021_print(netdissect_options *ndo,
const u_char *tptr, u_int tlv_len)
{
int hexdump = FALSE;
u_int subtype;
u_int sublen;
u_int tval;
u_int i;
if (tlv_len < 4) {
return hexdump;
}
subtype = GET_U_1(tptr + 3);
ND_PRINT("\n\t %s Subtype (%u)",
tok2str(lldp_8021_subtype_values, "unknown", subtype),
subtype);
switch (subtype) {
case LLDP_PRIVATE_8021_SUBTYPE_PORT_VLAN_ID:
if (tlv_len < 6) {
return hexdump;
}
ND_PRINT("\n\t port vlan id (PVID): %u",
GET_BE_U_2(tptr + 4));
break;
case LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_VLAN_ID:
if (tlv_len < 7) {
return hexdump;
}
ND_PRINT("\n\t port and protocol vlan id (PPVID): %u, flags [%s] (0x%02x)",
GET_BE_U_2(tptr + 5),
bittok2str(lldp_8021_port_protocol_id_values, "none", GET_U_1(tptr + 4)),
GET_U_1(tptr + 4));
break;
case LLDP_PRIVATE_8021_SUBTYPE_VLAN_NAME:
if (tlv_len < 6) {
return hexdump;
}
ND_PRINT("\n\t vlan id (VID): %u", GET_BE_U_2(tptr + 4));
if (tlv_len < 7) {
return hexdump;
}
sublen = GET_U_1(tptr + 6);
if (tlv_len < 7+sublen) {
return hexdump;
}
ND_PRINT("\n\t vlan name: ");
nd_printjnp(ndo, tptr + 7, sublen);
break;
case LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_IDENTITY:
if (tlv_len < 5) {
return hexdump;
}
sublen = GET_U_1(tptr + 4);
if (tlv_len < 5+sublen) {
return hexdump;
}
ND_PRINT("\n\t protocol identity: ");
nd_printjnp(ndo, tptr + 5, sublen);
break;
case LLDP_PRIVATE_8021_SUBTYPE_LINKAGGR:
if (tlv_len < 9) {
return hexdump;
}
ND_PRINT("\n\t aggregation status [%s], aggregation port ID %u",
bittok2str(lldp_aggregation_values, "none", GET_U_1((tptr + 4))),
GET_BE_U_4(tptr + 5));
break;
case LLDP_PRIVATE_8021_SUBTYPE_CONGESTION_NOTIFICATION:
if(tlv_len<LLDP_PRIVATE_8021_SUBTYPE_CONGESTION_NOTIFICATION_LENGTH){
return hexdump;
}
tval=GET_U_1(tptr + 4);
ND_PRINT("\n\t Pre-Priority CNPV Indicator");
ND_PRINT("\n\t Priority : 0 1 2 3 4 5 6 7");
ND_PRINT("\n\t Value : ");
for(i=0;i<NO_OF_BITS;i++)
ND_PRINT("%-2d ", (tval >> i) & 0x01);
tval=GET_U_1(tptr + 5);
ND_PRINT("\n\t Pre-Priority Ready Indicator");
ND_PRINT("\n\t Priority : 0 1 2 3 4 5 6 7");
ND_PRINT("\n\t Value : ");
for(i=0;i<NO_OF_BITS;i++)
ND_PRINT("%-2d ", (tval >> i) & 0x01);
break;
case LLDP_PRIVATE_8021_SUBTYPE_ETS_CONFIGURATION:
if(tlv_len<LLDP_PRIVATE_8021_SUBTYPE_ETS_CONFIGURATION_LENGTH) {
return hexdump;
}
tval=GET_U_1(tptr + 4);
ND_PRINT("\n\t Willing:%u, CBS:%u, RES:%u, Max TCs:%u",
tval >> 7, (tval >> 6) & 0x02, (tval >> 3) & 0x07, tval & 0x07);
/*Print Priority Assignment Table*/
print_ets_priority_assignment_table(ndo, tptr + 5);
/*Print TC Bandwidth Table*/
print_tc_bandwidth_table(ndo, tptr + 9);
/* Print TSA Assignment Table */
print_tsa_assignment_table(ndo, tptr + 17);
break;
case LLDP_PRIVATE_8021_SUBTYPE_ETS_RECOMMENDATION:
if(tlv_len<LLDP_PRIVATE_8021_SUBTYPE_ETS_RECOMMENDATION_LENGTH) {
return hexdump;
}
ND_PRINT("\n\t RES: %u", GET_U_1(tptr + 4));
/*Print Priority Assignment Table */
print_ets_priority_assignment_table(ndo, tptr + 5);
/*Print TC Bandwidth Table */
print_tc_bandwidth_table(ndo, tptr + 9);
/* Print TSA Assignment Table */
print_tsa_assignment_table(ndo, tptr + 17);
break;
case LLDP_PRIVATE_8021_SUBTYPE_PFC_CONFIGURATION:
if(tlv_len<LLDP_PRIVATE_8021_SUBTYPE_PFC_CONFIGURATION_LENGTH) {
return hexdump;
}
tval=GET_U_1(tptr + 4);
ND_PRINT("\n\t Willing: %u, MBC: %u, RES: %u, PFC cap:%u ",
tval >> 7, (tval >> 6) & 0x01, (tval >> 4) & 0x03, (tval & 0x0f));
ND_PRINT("\n\t PFC Enable");
tval=GET_U_1(tptr + 5);
ND_PRINT("\n\t Priority : 0 1 2 3 4 5 6 7");
ND_PRINT("\n\t Value : ");
for(i=0;i<NO_OF_BITS;i++)
ND_PRINT("%-2d ", (tval >> i) & 0x01);
break;
case LLDP_PRIVATE_8021_SUBTYPE_APPLICATION_PRIORITY:
if(tlv_len<LLDP_PRIVATE_8021_SUBTYPE_APPLICATION_PRIORITY_MIN_LENGTH) {
return hexdump;
}
ND_PRINT("\n\t RES: %u", GET_U_1(tptr + 4));
if(tlv_len<=LLDP_PRIVATE_8021_SUBTYPE_APPLICATION_PRIORITY_MIN_LENGTH){
return hexdump;
}
/* Length of Application Priority Table */
sublen=tlv_len-5;
if(sublen%3!=0){
return hexdump;
}
i=0;
ND_PRINT("\n\t Application Priority Table");
while(i<sublen) {
tval=GET_U_1(tptr + i + 5);
ND_PRINT("\n\t Priority: %u, RES: %u, Sel: %u, Protocol ID: %u",
tval >> 5, (tval >> 3) & 0x03, (tval & 0x07),
GET_BE_U_2(tptr + i + 6));
i=i+3;
}
break;
case LLDP_PRIVATE_8021_SUBTYPE_EVB:
if(tlv_len<LLDP_PRIVATE_8021_SUBTYPE_EVB_LENGTH){
return hexdump;
}
ND_PRINT("\n\t EVB Bridge Status");
tval=GET_U_1(tptr + 4);
ND_PRINT("\n\t RES: %u, BGID: %u, RRCAP: %u, RRCTR: %u",
tval >> 3, (tval >> 2) & 0x01, (tval >> 1) & 0x01, tval & 0x01);
ND_PRINT("\n\t EVB Station Status");
tval=GET_U_1(tptr + 5);
ND_PRINT("\n\t RES: %u, SGID: %u, RRREQ: %u,RRSTAT: %u",
tval >> 4, (tval >> 3) & 0x01, (tval >> 2) & 0x01, tval & 0x03);
tval=GET_U_1(tptr + 6);
ND_PRINT("\n\t R: %u, RTE: %u, ",tval >> 5, tval & 0x1f);
tval=GET_U_1(tptr + 7);
ND_PRINT("EVB Mode: %s [%u]",
tok2str(lldp_evb_mode_values, "unknown", tval >> 6), tval >> 6);
ND_PRINT("\n\t ROL: %u, RWD: %u, ", (tval >> 5) & 0x01, tval & 0x1f);
tval=GET_U_1(tptr + 8);
ND_PRINT("RES: %u, ROL: %u, RKA: %u", tval >> 6, (tval >> 5) & 0x01, tval & 0x1f);
break;
case LLDP_PRIVATE_8021_SUBTYPE_CDCP:
if(tlv_len<LLDP_PRIVATE_8021_SUBTYPE_CDCP_MIN_LENGTH){
return hexdump;
}
tval=GET_U_1(tptr + 4);
ND_PRINT("\n\t Role: %u, RES: %u, Scomp: %u ",
tval >> 7, (tval >> 4) & 0x07, (tval >> 3) & 0x01);
ND_PRINT("ChnCap: %u", GET_BE_U_2(tptr + 6) & 0x0fff);
sublen=tlv_len-8;
if(sublen%3!=0) {
return hexdump;
}
i=0;
while(i<sublen) {
tval=GET_BE_U_3(tptr + i + 8);
ND_PRINT("\n\t SCID: %u, SVID: %u",
tval >> 12, tval & 0x000fff);
i=i+3;
}
break;
default:
hexdump = TRUE;
break;
}
return hexdump;
}
/*
* Print IEEE 802.3 private extensions. (802.3bc)
*/
static int
lldp_private_8023_print(netdissect_options *ndo,
const u_char *tptr, u_int tlv_len)
{
int hexdump = FALSE;
u_int subtype;
if (tlv_len < 4) {
return hexdump;
}
subtype = GET_U_1(tptr + 3);
ND_PRINT("\n\t %s Subtype (%u)",
tok2str(lldp_8023_subtype_values, "unknown", subtype),
subtype);
switch (subtype) {
case LLDP_PRIVATE_8023_SUBTYPE_MACPHY:
if (tlv_len < 9) {
return hexdump;
}
ND_PRINT("\n\t autonegotiation [%s] (0x%02x)",
bittok2str(lldp_8023_autonegotiation_values, "none", GET_U_1(tptr + 4)),
GET_U_1(tptr + 4));
ND_PRINT("\n\t PMD autoneg capability [%s] (0x%04x)",
bittok2str(lldp_pmd_capability_values,"unknown", GET_BE_U_2(tptr + 5)),
GET_BE_U_2(tptr + 5));
ND_PRINT("\n\t MAU type %s (0x%04x)",
tok2str(lldp_mau_types_values, "unknown", GET_BE_U_2(tptr + 7)),
GET_BE_U_2(tptr + 7));
break;
case LLDP_PRIVATE_8023_SUBTYPE_MDIPOWER:
if (tlv_len < 7) {
return hexdump;
}
ND_PRINT("\n\t MDI power support [%s], power pair %s, power class %s",
bittok2str(lldp_mdi_values, "none", GET_U_1((tptr + 4))),
tok2str(lldp_mdi_power_pairs_values, "unknown", GET_U_1((tptr + 5))),
tok2str(lldp_mdi_power_class_values, "unknown", GET_U_1((tptr + 6))));
break;
case LLDP_PRIVATE_8023_SUBTYPE_LINKAGGR:
if (tlv_len < 9) {
return hexdump;
}
ND_PRINT("\n\t aggregation status [%s], aggregation port ID %u",
bittok2str(lldp_aggregation_values, "none", GET_U_1((tptr + 4))),
GET_BE_U_4(tptr + 5));
break;
case LLDP_PRIVATE_8023_SUBTYPE_MTU:
if (tlv_len < 6) {
return hexdump;
}
ND_PRINT("\n\t MTU size %u", GET_BE_U_2(tptr + 4));
break;
default:
hexdump = TRUE;
break;
}
return hexdump;
}
/*
* Extract 34bits of latitude/longitude coordinates.
*/
static uint64_t
lldp_extract_latlon(netdissect_options *ndo, const u_char *tptr)
{
uint64_t latlon;
latlon = GET_U_1(tptr) & 0x3;
latlon = (latlon << 32) | GET_BE_U_4(tptr + 1);
return latlon;
}
/* objects defined in IANA subtype 00 00 5e
* (right now there is only one)
*/
static int
lldp_private_iana_print(netdissect_options *ndo,
const u_char *tptr, u_int tlv_len)
{
int hexdump = FALSE;
u_int subtype;
if (tlv_len < 8) {
return hexdump;
}
subtype = GET_U_1(tptr + 3);
ND_PRINT("\n\t %s Subtype (%u)",
tok2str(lldp_iana_subtype_values, "unknown", subtype),
subtype);
switch (subtype) {
case LLDP_IANA_SUBTYPE_MUDURL:
ND_PRINT("\n\t MUD-URL=");
(void)nd_printn(ndo, tptr+4, tlv_len-4, NULL);
break;
default:
hexdump=TRUE;
}
return hexdump;
}
/*
* Print private TIA extensions.
*/
static int
lldp_private_tia_print(netdissect_options *ndo,
const u_char *tptr, u_int tlv_len)
{
int hexdump = FALSE;
u_int subtype;
uint8_t location_format;
uint16_t power_val;
u_int lci_len;
uint8_t ca_type, ca_len;
if (tlv_len < 4) {
return hexdump;
}
subtype = GET_U_1(tptr + 3);
ND_PRINT("\n\t %s Subtype (%u)",
tok2str(lldp_tia_subtype_values, "unknown", subtype),
subtype);
switch (subtype) {
case LLDP_PRIVATE_TIA_SUBTYPE_CAPABILITIES:
if (tlv_len < 7) {
return hexdump;
}
ND_PRINT("\n\t Media capabilities [%s] (0x%04x)",
bittok2str(lldp_tia_capabilities_values, "none",
GET_BE_U_2(tptr + 4)), GET_BE_U_2(tptr + 4));
ND_PRINT("\n\t Device type [%s] (0x%02x)",
tok2str(lldp_tia_device_type_values, "unknown", GET_U_1(tptr + 6)),
GET_U_1(tptr + 6));
break;
case LLDP_PRIVATE_TIA_SUBTYPE_NETWORK_POLICY:
if (tlv_len < 8) {
return hexdump;
}
ND_PRINT("\n\t Application type [%s] (0x%02x)",
tok2str(lldp_tia_application_type_values, "none", GET_U_1(tptr + 4)),
GET_U_1(tptr + 4));
ND_PRINT(", Flags [%s]", bittok2str(
lldp_tia_network_policy_bits_values, "none", GET_U_1((tptr + 5))));
ND_PRINT("\n\t Vlan id %u",
LLDP_EXTRACT_NETWORK_POLICY_VLAN(GET_BE_U_2(tptr + 5)));
ND_PRINT(", L2 priority %u",
LLDP_EXTRACT_NETWORK_POLICY_L2_PRIORITY(GET_BE_U_2(tptr + 6)));
ND_PRINT(", DSCP value %u",
LLDP_EXTRACT_NETWORK_POLICY_DSCP(GET_BE_U_2(tptr + 6)));
break;
case LLDP_PRIVATE_TIA_SUBTYPE_LOCAL_ID:
if (tlv_len < 5) {
return hexdump;
}
location_format = GET_U_1(tptr + 4);
ND_PRINT("\n\t Location data format %s (0x%02x)",
tok2str(lldp_tia_location_data_format_values, "unknown", location_format),
location_format);
switch (location_format) {
case LLDP_TIA_LOCATION_DATA_FORMAT_COORDINATE_BASED:
if (tlv_len < 21) {
return hexdump;
}
ND_PRINT("\n\t Latitude resolution %u, latitude value %" PRIu64,
(GET_U_1(tptr + 5) >> 2),
lldp_extract_latlon(ndo, tptr + 5));
ND_PRINT("\n\t Longitude resolution %u, longitude value %" PRIu64,
(GET_U_1(tptr + 10) >> 2),
lldp_extract_latlon(ndo, tptr + 10));
ND_PRINT("\n\t Altitude type %s (%u)",
tok2str(lldp_tia_location_altitude_type_values, "unknown",GET_U_1(tptr + 15) >> 4),
(GET_U_1(tptr + 15) >> 4));
ND_PRINT("\n\t Altitude resolution %u, altitude value 0x%x",
(GET_BE_U_2(tptr + 15)>>6)&0x3f,
(GET_BE_U_4(tptr + 16) & 0x3fffffff));
ND_PRINT("\n\t Datum %s (0x%02x)",
tok2str(lldp_tia_location_datum_type_values, "unknown", GET_U_1(tptr + 20)),
GET_U_1(tptr + 20));
break;
case LLDP_TIA_LOCATION_DATA_FORMAT_CIVIC_ADDRESS:
if (tlv_len < 6) {
return hexdump;
}
lci_len = GET_U_1(tptr + 5);
if (lci_len < 3) {
return hexdump;
}
if (tlv_len < 7+lci_len) {
return hexdump;
}
ND_PRINT("\n\t LCI length %u, LCI what %s (0x%02x), Country-code ",
lci_len,
tok2str(lldp_tia_location_lci_what_values, "unknown", GET_U_1(tptr + 6)),
GET_U_1(tptr + 6));
/* Country code */
nd_printjnp(ndo, tptr + 7, 2);
lci_len = lci_len-3;
tptr = tptr + 9;
/* Decode each civic address element */
while (lci_len > 0) {
if (lci_len < 2) {
return hexdump;
}
ca_type = GET_U_1(tptr);
ca_len = GET_U_1(tptr + 1);
tptr += 2;
lci_len -= 2;
- ND_PRINT("\n\t CA type \'%s\' (%u), length %u: ",
+ ND_PRINT("\n\t CA type '%s' (%u), length %u: ",
tok2str(lldp_tia_location_lci_catype_values, "unknown", ca_type),
ca_type, ca_len);
/* basic sanity check */
if ( ca_type == 0 || ca_len == 0) {
return hexdump;
}
if (lci_len < ca_len) {
return hexdump;
}
nd_printjnp(ndo, tptr, ca_len);
tptr += ca_len;
lci_len -= ca_len;
}
break;
case LLDP_TIA_LOCATION_DATA_FORMAT_ECS_ELIN:
ND_PRINT("\n\t ECS ELIN id ");
nd_printjnp(ndo, tptr + 5, tlv_len - 5);
break;
default:
ND_PRINT("\n\t Location ID ");
print_unknown_data(ndo, tptr + 5, "\n\t ", tlv_len - 5);
}
break;
case LLDP_PRIVATE_TIA_SUBTYPE_EXTENDED_POWER_MDI:
if (tlv_len < 7) {
return hexdump;
}
ND_PRINT("\n\t Power type [%s]",
(GET_U_1(tptr + 4) & 0xC0 >> 6) ? "PD device" : "PSE device");
ND_PRINT(", Power source [%s]",
tok2str(lldp_tia_power_source_values, "none", (GET_U_1((tptr + 4)) & 0x30) >> 4));
ND_PRINT("\n\t Power priority [%s] (0x%02x)",
tok2str(lldp_tia_power_priority_values, "none", GET_U_1(tptr + 4) & 0x0f),
GET_U_1(tptr + 4) & 0x0f);
power_val = GET_BE_U_2(tptr + 5);
if (power_val < LLDP_TIA_POWER_VAL_MAX) {
ND_PRINT(", Power %.1f Watts", ((float)power_val) / 10);
} else {
ND_PRINT(", Power %u (Reserved)", power_val);
}
break;
case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_HARDWARE_REV:
case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_FIRMWARE_REV:
case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SOFTWARE_REV:
case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SERIAL_NUMBER:
case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MANUFACTURER_NAME:
case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MODEL_NAME:
case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_ASSET_ID:
ND_PRINT("\n\t %s ",
tok2str(lldp_tia_inventory_values, "unknown", subtype));
nd_printjnp(ndo, tptr + 4, tlv_len - 4);
break;
default:
hexdump = TRUE;
break;
}
return hexdump;
}
/*
* Print DCBX Protocol fields (V 1.01).
*/
static int
lldp_private_dcbx_print(netdissect_options *ndo,
const u_char *pptr, u_int len)
{
int hexdump = FALSE;
u_int subtype;
uint16_t tval;
uint16_t tlv;
uint32_t i, pgval, uval;
u_int tlen, tlv_type;
uint16_t tlv_len;
const u_char *tptr, *mptr;
if (len < 4) {
return hexdump;
}
subtype = GET_U_1(pptr + 3);
ND_PRINT("\n\t %s Subtype (%u)",
tok2str(lldp_dcbx_subtype_values, "unknown", subtype),
subtype);
/* by passing old version */
if (subtype == LLDP_DCBX_SUBTYPE_1)
return TRUE;
tptr = pptr + 4;
tlen = len - 4;
while (tlen >= sizeof(tlv)) {
ND_TCHECK_LEN(tptr, sizeof(tlv));
tlv = GET_BE_U_2(tptr);
tlv_type = LLDP_EXTRACT_TYPE(tlv);
tlv_len = LLDP_EXTRACT_LEN(tlv);
hexdump = FALSE;
tlen -= sizeof(tlv);
tptr += sizeof(tlv);
/* loop check */
if (!tlv_type || !tlv_len) {
break;
}
ND_TCHECK_LEN(tptr, tlv_len);
if (tlen < tlv_len) {
goto trunc;
}
/* decode every tlv */
switch (tlv_type) {
case LLDP_DCBX_CONTROL_TLV:
if (tlv_len < 10) {
goto trunc;
}
ND_PRINT("\n\t Control - Protocol Control (type 0x%x, length %u)",
LLDP_DCBX_CONTROL_TLV, tlv_len);
ND_PRINT("\n\t Oper_Version: %u", GET_U_1(tptr));
ND_PRINT("\n\t Max_Version: %u", GET_U_1(tptr + 1));
ND_PRINT("\n\t Sequence Number: %u", GET_BE_U_4(tptr + 2));
ND_PRINT("\n\t Acknowledgement Number: %u",
GET_BE_U_4(tptr + 6));
break;
case LLDP_DCBX_PRIORITY_GROUPS_TLV:
if (tlv_len < 17) {
goto trunc;
}
ND_PRINT("\n\t Feature - Priority Group (type 0x%x, length %u)",
LLDP_DCBX_PRIORITY_GROUPS_TLV, tlv_len);
ND_PRINT("\n\t Oper_Version: %u", GET_U_1(tptr));
ND_PRINT("\n\t Max_Version: %u", GET_U_1(tptr + 1));
ND_PRINT("\n\t Info block(0x%02X): ", GET_U_1(tptr + 2));
tval = GET_U_1(tptr + 2);
ND_PRINT("Enable bit: %u, Willing bit: %u, Error Bit: %u",
(tval & 0x80) ? 1 : 0, (tval & 0x40) ? 1 : 0,
(tval & 0x20) ? 1 : 0);
ND_PRINT("\n\t SubType: %u", GET_U_1(tptr + 3));
ND_PRINT("\n\t Priority Allocation");
/*
* Array of 8 4-bit priority group ID values; we fetch all
* 32 bits and extract each nibble.
*/
pgval = GET_BE_U_4(tptr + 4);
for (i = 0; i <= 7; i++) {
ND_PRINT("\n\t PgId_%u: %u",
i, (pgval >> (28 - 4 * i)) & 0xF);
}
ND_PRINT("\n\t Priority Group Allocation");
for (i = 0; i <= 7; i++)
ND_PRINT("\n\t Pg percentage[%u]: %u", i,
GET_U_1(tptr + 8 + i));
ND_PRINT("\n\t NumTCsSupported: %u", GET_U_1(tptr + 8 + 8));
break;
case LLDP_DCBX_PRIORITY_FLOW_CONTROL_TLV:
if (tlv_len < 6) {
goto trunc;
}
ND_PRINT("\n\t Feature - Priority Flow Control");
ND_PRINT(" (type 0x%x, length %u)",
LLDP_DCBX_PRIORITY_FLOW_CONTROL_TLV, tlv_len);
ND_PRINT("\n\t Oper_Version: %u", GET_U_1(tptr));
ND_PRINT("\n\t Max_Version: %u", GET_U_1(tptr + 1));
ND_PRINT("\n\t Info block(0x%02X): ", GET_U_1(tptr + 2));
tval = GET_U_1(tptr + 2);
ND_PRINT("Enable bit: %u, Willing bit: %u, Error Bit: %u",
(tval & 0x80) ? 1 : 0, (tval & 0x40) ? 1 : 0,
(tval & 0x20) ? 1 : 0);
ND_PRINT("\n\t SubType: %u", GET_U_1(tptr + 3));
tval = GET_U_1(tptr + 4);
ND_PRINT("\n\t PFC Config (0x%02X)", GET_U_1(tptr + 4));
for (i = 0; i <= 7; i++)
ND_PRINT("\n\t Priority Bit %u: %s",
i, (tval & (1 << i)) ? "Enabled" : "Disabled");
ND_PRINT("\n\t NumTCPFCSupported: %u", GET_U_1(tptr + 5));
break;
case LLDP_DCBX_APPLICATION_TLV:
if (tlv_len < 4) {
goto trunc;
}
ND_PRINT("\n\t Feature - Application (type 0x%x, length %u)",
LLDP_DCBX_APPLICATION_TLV, tlv_len);
ND_PRINT("\n\t Oper_Version: %u", GET_U_1(tptr));
ND_PRINT("\n\t Max_Version: %u", GET_U_1(tptr + 1));
ND_PRINT("\n\t Info block(0x%02X): ", GET_U_1(tptr + 2));
tval = GET_U_1(tptr + 2);
ND_PRINT("Enable bit: %u, Willing bit: %u, Error Bit: %u",
(tval & 0x80) ? 1 : 0, (tval & 0x40) ? 1 : 0,
(tval & 0x20) ? 1 : 0);
ND_PRINT("\n\t SubType: %u", GET_U_1(tptr + 3));
tval = tlv_len - 4;
mptr = tptr + 4;
while (tval >= 6) {
ND_PRINT("\n\t Application Value");
ND_PRINT("\n\t Application Protocol ID: 0x%04x",
GET_BE_U_2(mptr));
uval = GET_BE_U_3(mptr + 2);
ND_PRINT("\n\t SF (0x%x) Application Protocol ID is %s",
(uval >> 22),
(uval >> 22) ? "Socket Number" : "L2 EtherType");
ND_PRINT("\n\t OUI: 0x%06x", uval & 0x3fffff);
ND_PRINT("\n\t User Priority Map: 0x%02x",
GET_U_1(mptr + 5));
tval = tval - 6;
mptr = mptr + 6;
}
break;
default:
hexdump = TRUE;
break;
}
/* do we also want to see a hex dump ? */
if (ndo->ndo_vflag > 1 || (ndo->ndo_vflag && hexdump)) {
print_unknown_data(ndo, tptr, "\n\t ", tlv_len);
}
tlen -= tlv_len;
tptr += tlv_len;
}
trunc:
return hexdump;
}
static char *
lldp_network_addr_print(netdissect_options *ndo, const u_char *tptr, u_int len)
{
uint8_t af;
static char buf[BUFSIZE];
const char * (*pfunc)(netdissect_options *, const u_char *);
if (len < 1)
return NULL;
len--;
af = GET_U_1(tptr);
switch (af) {
case AFNUM_INET:
if (len < sizeof(nd_ipv4))
return NULL;
pfunc = ipaddr_string;
break;
case AFNUM_INET6:
if (len < sizeof(nd_ipv6))
return NULL;
pfunc = ip6addr_string;
break;
case AFNUM_802:
if (len < MAC_ADDR_LEN)
return NULL;
pfunc = etheraddr_string;
break;
default:
pfunc = NULL;
break;
}
if (!pfunc) {
snprintf(buf, sizeof(buf), "AFI %s (%u), no AF printer !",
tok2str(af_values, "Unknown", af), af);
} else {
snprintf(buf, sizeof(buf), "AFI %s (%u): %s",
tok2str(af_values, "Unknown", af), af, (*pfunc)(ndo, tptr+1));
}
return buf;
}
static int
lldp_mgmt_addr_tlv_print(netdissect_options *ndo,
const u_char *pptr, u_int len)
{
uint8_t mgmt_addr_len, intf_num_subtype, oid_len;
const u_char *tptr;
u_int tlen;
char *mgmt_addr;
tlen = len;
tptr = pptr;
if (tlen < 1) {
return 0;
}
mgmt_addr_len = GET_U_1(tptr);
tptr++;
tlen--;
if (tlen < mgmt_addr_len) {
return 0;
}
mgmt_addr = lldp_network_addr_print(ndo, tptr, mgmt_addr_len);
if (mgmt_addr == NULL) {
return 0;
}
ND_PRINT("\n\t Management Address length %u, %s",
mgmt_addr_len, mgmt_addr);
tptr += mgmt_addr_len;
tlen -= mgmt_addr_len;
if (tlen < LLDP_INTF_NUM_LEN) {
return 0;
}
intf_num_subtype = GET_U_1(tptr);
ND_PRINT("\n\t %s Interface Numbering (%u): %u",
tok2str(lldp_intf_numb_subtype_values, "Unknown", intf_num_subtype),
intf_num_subtype,
GET_BE_U_4(tptr + 1));
tptr += LLDP_INTF_NUM_LEN;
tlen -= LLDP_INTF_NUM_LEN;
/*
* The OID is optional.
*/
if (tlen) {
oid_len = GET_U_1(tptr);
if (tlen < 1U + oid_len) {
return 0;
}
if (oid_len) {
ND_PRINT("\n\t OID length %u", oid_len);
nd_printjnp(ndo, tptr + 1, oid_len);
}
}
return 1;
}
void
lldp_print(netdissect_options *ndo,
const u_char *pptr, u_int len)
{
uint8_t subtype;
uint16_t tlv, cap, ena_cap;
u_int oui, tlen, hexdump, tlv_type, tlv_len;
const u_char *tptr;
char *network_addr;
ndo->ndo_protocol = "lldp";
tptr = pptr;
tlen = len;
ND_PRINT("LLDP, length %u", len);
while (tlen >= sizeof(tlv)) {
ND_TCHECK_LEN(tptr, sizeof(tlv));
tlv = GET_BE_U_2(tptr);
tlv_type = LLDP_EXTRACT_TYPE(tlv);
tlv_len = LLDP_EXTRACT_LEN(tlv);
hexdump = FALSE;
tlen -= sizeof(tlv);
tptr += sizeof(tlv);
if (ndo->ndo_vflag) {
ND_PRINT("\n\t%s TLV (%u), length %u",
tok2str(lldp_tlv_values, "Unknown", tlv_type),
tlv_type, tlv_len);
}
/* infinite loop check */
if (!tlv_type || !tlv_len) {
break;
}
ND_TCHECK_LEN(tptr, tlv_len);
if (tlen < tlv_len) {
goto trunc;
}
switch (tlv_type) {
case LLDP_CHASSIS_ID_TLV:
if (ndo->ndo_vflag) {
if (tlv_len < 2) {
goto trunc;
}
subtype = GET_U_1(tptr);
ND_PRINT("\n\t Subtype %s (%u): ",
tok2str(lldp_chassis_subtype_values, "Unknown", subtype),
subtype);
switch (subtype) {
case LLDP_CHASSIS_MAC_ADDR_SUBTYPE:
if (tlv_len < 1+6) {
goto trunc;
}
ND_PRINT("%s", GET_ETHERADDR_STRING(tptr + 1));
break;
case LLDP_CHASSIS_INTF_NAME_SUBTYPE: /* fall through */
case LLDP_CHASSIS_LOCAL_SUBTYPE:
case LLDP_CHASSIS_CHASSIS_COMP_SUBTYPE:
case LLDP_CHASSIS_INTF_ALIAS_SUBTYPE:
case LLDP_CHASSIS_PORT_COMP_SUBTYPE:
nd_printjnp(ndo, tptr + 1, tlv_len - 1);
break;
case LLDP_CHASSIS_NETWORK_ADDR_SUBTYPE:
network_addr = lldp_network_addr_print(ndo, tptr+1, tlv_len-1);
if (network_addr == NULL) {
goto trunc;
}
ND_PRINT("%s", network_addr);
break;
default:
hexdump = TRUE;
break;
}
}
break;
case LLDP_PORT_ID_TLV:
if (ndo->ndo_vflag) {
if (tlv_len < 2) {
goto trunc;
}
subtype = GET_U_1(tptr);
ND_PRINT("\n\t Subtype %s (%u): ",
tok2str(lldp_port_subtype_values, "Unknown", subtype),
subtype);
switch (subtype) {
case LLDP_PORT_MAC_ADDR_SUBTYPE:
if (tlv_len < 1+6) {
goto trunc;
}
ND_PRINT("%s", GET_ETHERADDR_STRING(tptr + 1));
break;
case LLDP_PORT_INTF_NAME_SUBTYPE: /* fall through */
case LLDP_PORT_LOCAL_SUBTYPE:
case LLDP_PORT_AGENT_CIRC_ID_SUBTYPE:
case LLDP_PORT_INTF_ALIAS_SUBTYPE:
case LLDP_PORT_PORT_COMP_SUBTYPE:
nd_printjnp(ndo, tptr + 1, tlv_len - 1);
break;
case LLDP_PORT_NETWORK_ADDR_SUBTYPE:
network_addr = lldp_network_addr_print(ndo, tptr+1, tlv_len-1);
if (network_addr == NULL) {
goto trunc;
}
ND_PRINT("%s", network_addr);
break;
default:
hexdump = TRUE;
break;
}
}
break;
case LLDP_TTL_TLV:
if (ndo->ndo_vflag) {
if (tlv_len < 2) {
goto trunc;
}
ND_PRINT(": TTL %us", GET_BE_U_2(tptr));
}
break;
case LLDP_PORT_DESCR_TLV:
if (ndo->ndo_vflag) {
ND_PRINT(": ");
nd_printjnp(ndo, tptr, tlv_len);
}
break;
case LLDP_SYSTEM_NAME_TLV:
/*
* The system name is also print in non-verbose mode
* similar to the CDP printer.
*/
ND_PRINT(": ");
nd_printjnp(ndo, tptr, tlv_len);
break;
case LLDP_SYSTEM_DESCR_TLV:
if (ndo->ndo_vflag) {
ND_PRINT("\n\t ");
nd_printjnp(ndo, tptr, tlv_len);
}
break;
case LLDP_SYSTEM_CAP_TLV:
if (ndo->ndo_vflag) {
/*
* XXX - IEEE Std 802.1AB-2009 says the first octet
* if a chassis ID subtype, with the system
* capabilities and enabled capabilities following
* it.
*/
if (tlv_len < 4) {
goto trunc;
}
cap = GET_BE_U_2(tptr);
ena_cap = GET_BE_U_2(tptr + 2);
ND_PRINT("\n\t System Capabilities [%s] (0x%04x)",
bittok2str(lldp_cap_values, "none", cap), cap);
ND_PRINT("\n\t Enabled Capabilities [%s] (0x%04x)",
bittok2str(lldp_cap_values, "none", ena_cap), ena_cap);
}
break;
case LLDP_MGMT_ADDR_TLV:
if (ndo->ndo_vflag) {
if (!lldp_mgmt_addr_tlv_print(ndo, tptr, tlv_len)) {
goto trunc;
}
}
break;
case LLDP_PRIVATE_TLV:
if (ndo->ndo_vflag) {
if (tlv_len < 3) {
goto trunc;
}
oui = GET_BE_U_3(tptr);
ND_PRINT(": OUI %s (0x%06x)", tok2str(oui_values, "Unknown", oui), oui);
switch (oui) {
case OUI_IEEE_8021_PRIVATE:
hexdump = lldp_private_8021_print(ndo, tptr, tlv_len);
break;
case OUI_IEEE_8023_PRIVATE:
hexdump = lldp_private_8023_print(ndo, tptr, tlv_len);
break;
case OUI_IANA:
hexdump = lldp_private_iana_print(ndo, tptr, tlv_len);
break;
case OUI_TIA:
hexdump = lldp_private_tia_print(ndo, tptr, tlv_len);
break;
case OUI_DCBX:
hexdump = lldp_private_dcbx_print(ndo, tptr, tlv_len);
break;
default:
hexdump = TRUE;
break;
}
}
break;
default:
hexdump = TRUE;
break;
}
/* do we also want to see a hex dump ? */
if (ndo->ndo_vflag > 1 || (ndo->ndo_vflag && hexdump)) {
print_unknown_data(ndo, tptr, "\n\t ", tlv_len);
}
tlen -= tlv_len;
tptr += tlv_len;
}
return;
trunc:
nd_print_trunc(ndo);
}
diff --git a/contrib/tcpdump/print-lmp.c b/contrib/tcpdump/print-lmp.c
index 925f3b07f354..66ac20301aae 100644
--- a/contrib/tcpdump/print-lmp.c
+++ b/contrib/tcpdump/print-lmp.c
@@ -1,1137 +1,1135 @@
/*
* 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.
*
* Original code by Hannes Gredler (hannes@gredler.at)
* Support for LMP service discovery extensions (defined by OIF UNI 1.0)
* added by Manu Pathak (mapathak@cisco.com), May 2005
*/
/* \summary: Link Management Protocol (LMP) printer */
/* specification: RFC 4204 */
/* OIF UNI 1.0: https://web.archive.org/web/20160401194747/http://www.oiforum.com/public/documents/OIF-UNI-01.0.pdf */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
#include "addrtoname.h"
#include "gmpls.h"
/*
* LMP common header
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Vers | (Reserved) | Flags | Msg Type |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | LMP Length | (Reserved) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct lmp_common_header {
nd_uint16_t version_res;
nd_uint8_t flags;
nd_uint8_t msg_type;
nd_uint16_t length;
nd_byte reserved[2];
};
#define LMP_VERSION 1
#define LMP_EXTRACT_VERSION(x) (((x)&0xf000)>>12)
static const struct tok lmp_header_flag_values[] = {
{ 0x01, "Control Channel Down"},
{ 0x02, "LMP restart"},
{ 0, NULL}
};
static const struct tok lmp_obj_te_link_flag_values[] = {
{ 0x01, "Fault Management Supported"},
{ 0x02, "Link Verification Supported"},
{ 0, NULL}
};
static const struct tok lmp_obj_data_link_flag_values[] = {
{ 0x01, "Data Link Port"},
{ 0x02, "Allocated for user traffic"},
{ 0x04, "Failed link"},
{ 0, NULL}
};
static const struct tok lmp_obj_channel_status_values[] = {
{ 1, "Signal Okay"},
{ 2, "Signal Degraded"},
{ 3, "Signal Fail"},
{ 0, NULL}
};
static const struct tok lmp_obj_begin_verify_flag_values[] = {
{ 0x0001, "Verify all links"},
{ 0x0002, "Data link type"},
{ 0, NULL}
};
static const struct tok lmp_obj_begin_verify_error_values[] = {
{ 0x01, "Link Verification Procedure Not supported"},
{ 0x02, "Unwilling to verify"},
{ 0x04, "Unsupported verification transport mechanism"},
{ 0x08, "Link-Id configuration error"},
{ 0x10, "Unknown object c-type"},
{ 0, NULL}
};
static const struct tok lmp_obj_link_summary_error_values[] = {
{ 0x01, "Unacceptable non-negotiable LINK-SUMMARY parameters"},
{ 0x02, "Renegotiate LINK-SUMMARY parameters"},
{ 0x04, "Invalid TE-LINK Object"},
{ 0x08, "Invalid DATA-LINK Object"},
{ 0x10, "Unknown TE-LINK Object c-type"},
{ 0x20, "Unknown DATA-LINK Object c-type"},
{ 0, NULL}
};
/* Service Config Supported Protocols Flags */
static const struct tok lmp_obj_service_config_sp_flag_values[] = {
{ 0x01, "RSVP Supported"},
{ 0x02, "LDP Supported"},
{ 0, NULL}
};
/* Service Config Client Port Service Attribute Transparency Flags */
static const struct tok lmp_obj_service_config_cpsa_tp_flag_values[] = {
{ 0x01, "Path/VC Overhead Transparency Supported"},
{ 0x02, "Line/MS Overhead Transparency Supported"},
{ 0x04, "Section/RS Overhead Transparency Supported"},
{ 0, NULL}
};
/* Service Config Client Port Service Attribute Contiguous Concatenation Types Flags */
static const struct tok lmp_obj_service_config_cpsa_cct_flag_values[] = {
{ 0x01, "Contiguous Concatenation Types Supported"},
{ 0, NULL}
};
/* Service Config Network Service Attributes Transparency Flags */
static const struct tok lmp_obj_service_config_nsa_transparency_flag_values[] = {
{ 0x01, "Standard SOH/RSOH Transparency Supported"},
{ 0x02, "Standard LOH/MSOH Transparency Supported"},
{ 0, NULL}
};
/* Service Config Network Service Attributes TCM Monitoring Flags */
static const struct tok lmp_obj_service_config_nsa_tcm_flag_values[] = {
{ 0x01, "Transparent Tandem Connection Monitoring Supported"},
{ 0, NULL}
};
/* Network Service Attributes Network Diversity Flags */
static const struct tok lmp_obj_service_config_nsa_network_diversity_flag_values[] = {
{ 0x01, "Node Diversity Supported"},
{ 0x02, "Link Diversity Supported"},
{ 0x04, "SRLG Diversity Supported"},
{ 0, NULL}
};
#define LMP_MSGTYPE_CONFIG 1
#define LMP_MSGTYPE_CONFIG_ACK 2
#define LMP_MSGTYPE_CONFIG_NACK 3
#define LMP_MSGTYPE_HELLO 4
#define LMP_MSGTYPE_VERIFY_BEGIN 5
#define LMP_MSGTYPE_VERIFY_BEGIN_ACK 6
#define LMP_MSGTYPE_VERIFY_BEGIN_NACK 7
#define LMP_MSGTYPE_VERIFY_END 8
#define LMP_MSGTYPE_VERIFY_END_ACK 9
#define LMP_MSGTYPE_TEST 10
#define LMP_MSGTYPE_TEST_STATUS_SUCCESS 11
#define LMP_MSGTYPE_TEST_STATUS_FAILURE 12
#define LMP_MSGTYPE_TEST_STATUS_ACK 13
#define LMP_MSGTYPE_LINK_SUMMARY 14
#define LMP_MSGTYPE_LINK_SUMMARY_ACK 15
#define LMP_MSGTYPE_LINK_SUMMARY_NACK 16
#define LMP_MSGTYPE_CHANNEL_STATUS 17
#define LMP_MSGTYPE_CHANNEL_STATUS_ACK 18
#define LMP_MSGTYPE_CHANNEL_STATUS_REQ 19
#define LMP_MSGTYPE_CHANNEL_STATUS_RESP 20
/* LMP Service Discovery message types defined by UNI 1.0 */
#define LMP_MSGTYPE_SERVICE_CONFIG 50
#define LMP_MSGTYPE_SERVICE_CONFIG_ACK 51
#define LMP_MSGTYPE_SERVICE_CONFIG_NACK 52
static const struct tok lmp_msg_type_values[] = {
{ LMP_MSGTYPE_CONFIG, "Config"},
{ LMP_MSGTYPE_CONFIG_ACK, "Config ACK"},
{ LMP_MSGTYPE_CONFIG_NACK, "Config NACK"},
{ LMP_MSGTYPE_HELLO, "Hello"},
{ LMP_MSGTYPE_VERIFY_BEGIN, "Begin Verify"},
{ LMP_MSGTYPE_VERIFY_BEGIN_ACK, "Begin Verify ACK"},
{ LMP_MSGTYPE_VERIFY_BEGIN_NACK, "Begin Verify NACK"},
{ LMP_MSGTYPE_VERIFY_END, "End Verify"},
{ LMP_MSGTYPE_VERIFY_END_ACK, "End Verify ACK"},
{ LMP_MSGTYPE_TEST, "Test"},
{ LMP_MSGTYPE_TEST_STATUS_SUCCESS, "Test Status Success"},
{ LMP_MSGTYPE_TEST_STATUS_FAILURE, "Test Status Failure"},
{ LMP_MSGTYPE_TEST_STATUS_ACK, "Test Status ACK"},
{ LMP_MSGTYPE_LINK_SUMMARY, "Link Summary"},
{ LMP_MSGTYPE_LINK_SUMMARY_ACK, "Link Summary ACK"},
{ LMP_MSGTYPE_LINK_SUMMARY_NACK, "Link Summary NACK"},
{ LMP_MSGTYPE_CHANNEL_STATUS, "Channel Status"},
{ LMP_MSGTYPE_CHANNEL_STATUS_ACK, "Channel Status ACK"},
{ LMP_MSGTYPE_CHANNEL_STATUS_REQ, "Channel Status Request"},
{ LMP_MSGTYPE_CHANNEL_STATUS_RESP, "Channel Status Response"},
{ LMP_MSGTYPE_SERVICE_CONFIG, "Service Config"},
{ LMP_MSGTYPE_SERVICE_CONFIG_ACK, "Service Config ACK"},
{ LMP_MSGTYPE_SERVICE_CONFIG_NACK, "Service Config NACK"},
{ 0, NULL}
};
/*
* LMP object header
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |N| C-Type | Class | Length |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* // (object contents) //
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct lmp_object_header {
nd_uint8_t ctype;
nd_uint8_t class_num;
nd_uint16_t length;
};
#define LMP_OBJ_CC_ID 1
#define LMP_OBJ_NODE_ID 2
#define LMP_OBJ_LINK_ID 3
#define LMP_OBJ_INTERFACE_ID 4
#define LMP_OBJ_MESSAGE_ID 5
#define LMP_OBJ_CONFIG 6
#define LMP_OBJ_HELLO 7
#define LMP_OBJ_VERIFY_BEGIN 8
#define LMP_OBJ_VERIFY_BEGIN_ACK 9
#define LMP_OBJ_VERIFY_ID 10
#define LMP_OBJ_TE_LINK 11
#define LMP_OBJ_DATA_LINK 12
#define LMP_OBJ_CHANNEL_STATUS 13
#define LMP_OBJ_CHANNEL_STATUS_REQ 14
#define LMP_OBJ_ERROR_CODE 20
#define LMP_OBJ_SERVICE_CONFIG 51 /* defined in UNI 1.0 */
static const struct tok lmp_obj_values[] = {
{ LMP_OBJ_CC_ID, "Control Channel ID" },
{ LMP_OBJ_NODE_ID, "Node ID" },
{ LMP_OBJ_LINK_ID, "Link ID" },
{ LMP_OBJ_INTERFACE_ID, "Interface ID" },
{ LMP_OBJ_MESSAGE_ID, "Message ID" },
{ LMP_OBJ_CONFIG, "Configuration" },
{ LMP_OBJ_HELLO, "Hello" },
{ LMP_OBJ_VERIFY_BEGIN, "Verify Begin" },
{ LMP_OBJ_VERIFY_BEGIN_ACK, "Verify Begin ACK" },
{ LMP_OBJ_VERIFY_ID, "Verify ID" },
{ LMP_OBJ_TE_LINK, "TE Link" },
{ LMP_OBJ_DATA_LINK, "Data Link" },
{ LMP_OBJ_CHANNEL_STATUS, "Channel Status" },
{ LMP_OBJ_CHANNEL_STATUS_REQ, "Channel Status Request" },
{ LMP_OBJ_ERROR_CODE, "Error Code" },
{ LMP_OBJ_SERVICE_CONFIG, "Service Config" },
{ 0, NULL}
};
#define INT_SWITCHING_TYPE_SUBOBJ 1
#define WAVELENGTH_SUBOBJ 2
static const struct tok lmp_data_link_subobj[] = {
{ INT_SWITCHING_TYPE_SUBOBJ, "Interface Switching Type" },
{ WAVELENGTH_SUBOBJ , "Wavelength" },
{ 0, NULL}
};
#define LMP_CTYPE_IPV4 1
#define LMP_CTYPE_IPV6 2
#define LMP_CTYPE_LOC 1
#define LMP_CTYPE_RMT 2
#define LMP_CTYPE_UNMD 3
#define LMP_CTYPE_IPV4_LOC 1
#define LMP_CTYPE_IPV4_RMT 2
#define LMP_CTYPE_IPV6_LOC 3
#define LMP_CTYPE_IPV6_RMT 4
#define LMP_CTYPE_UNMD_LOC 5
#define LMP_CTYPE_UNMD_RMT 6
#define LMP_CTYPE_1 1
#define LMP_CTYPE_2 2
#define LMP_CTYPE_HELLO_CONFIG 1
#define LMP_CTYPE_HELLO 1
#define LMP_CTYPE_BEGIN_VERIFY_ERROR 1
#define LMP_CTYPE_LINK_SUMMARY_ERROR 2
/* C-Types for Service Config Object */
#define LMP_CTYPE_SERVICE_CONFIG_SP 1
#define LMP_CTYPE_SERVICE_CONFIG_CPSA 2
#define LMP_CTYPE_SERVICE_CONFIG_TRANSPARENCY_TCM 3
#define LMP_CTYPE_SERVICE_CONFIG_NETWORK_DIVERSITY 4
/*
* Different link types allowed in the Client Port Service Attributes
* subobject defined for LMP Service Discovery in the UNI 1.0 spec
*/
#define LMP_SD_SERVICE_CONFIG_CPSA_LINK_TYPE_SDH 5 /* UNI 1.0 Sec 9.4.2 */
#define LMP_SD_SERVICE_CONFIG_CPSA_LINK_TYPE_SONET 6 /* UNI 1.0 Sec 9.4.2 */
/*
* the ctypes are not globally unique so for
* translating it to strings we build a table based
* on objects offsetted by the ctype
*/
static const struct tok lmp_ctype_values[] = {
{ 256*LMP_OBJ_CC_ID+LMP_CTYPE_LOC, "Local" },
{ 256*LMP_OBJ_CC_ID+LMP_CTYPE_RMT, "Remote" },
{ 256*LMP_OBJ_NODE_ID+LMP_CTYPE_LOC, "Local" },
{ 256*LMP_OBJ_NODE_ID+LMP_CTYPE_RMT, "Remote" },
{ 256*LMP_OBJ_LINK_ID+LMP_CTYPE_IPV4_LOC, "IPv4 Local" },
{ 256*LMP_OBJ_LINK_ID+LMP_CTYPE_IPV4_RMT, "IPv4 Remote" },
{ 256*LMP_OBJ_LINK_ID+LMP_CTYPE_IPV6_LOC, "IPv6 Local" },
{ 256*LMP_OBJ_LINK_ID+LMP_CTYPE_IPV6_RMT, "IPv6 Remote" },
{ 256*LMP_OBJ_LINK_ID+LMP_CTYPE_UNMD_LOC, "Unnumbered Local" },
{ 256*LMP_OBJ_LINK_ID+LMP_CTYPE_UNMD_RMT, "Unnumbered Remote" },
{ 256*LMP_OBJ_INTERFACE_ID+LMP_CTYPE_IPV4_LOC, "IPv4 Local" },
{ 256*LMP_OBJ_INTERFACE_ID+LMP_CTYPE_IPV4_RMT, "IPv4 Remote" },
{ 256*LMP_OBJ_INTERFACE_ID+LMP_CTYPE_IPV6_LOC, "IPv6 Local" },
{ 256*LMP_OBJ_INTERFACE_ID+LMP_CTYPE_IPV6_RMT, "IPv6 Remote" },
{ 256*LMP_OBJ_INTERFACE_ID+LMP_CTYPE_UNMD_LOC, "Unnumbered Local" },
{ 256*LMP_OBJ_INTERFACE_ID+LMP_CTYPE_UNMD_RMT, "Unnumbered Remote" },
{ 256*LMP_OBJ_MESSAGE_ID+LMP_CTYPE_1, "1" },
{ 256*LMP_OBJ_MESSAGE_ID+LMP_CTYPE_2, "2" },
{ 256*LMP_OBJ_CONFIG+LMP_CTYPE_1, "1" },
{ 256*LMP_OBJ_HELLO+LMP_CTYPE_1, "1" },
{ 256*LMP_OBJ_VERIFY_BEGIN+LMP_CTYPE_1, "1" },
{ 256*LMP_OBJ_VERIFY_BEGIN_ACK+LMP_CTYPE_1, "1" },
{ 256*LMP_OBJ_VERIFY_ID+LMP_CTYPE_1, "1" },
{ 256*LMP_OBJ_TE_LINK+LMP_CTYPE_IPV4, "IPv4" },
{ 256*LMP_OBJ_TE_LINK+LMP_CTYPE_IPV6, "IPv6" },
{ 256*LMP_OBJ_TE_LINK+LMP_CTYPE_UNMD, "Unnumbered" },
{ 256*LMP_OBJ_DATA_LINK+LMP_CTYPE_IPV4, "IPv4" },
{ 256*LMP_OBJ_DATA_LINK+LMP_CTYPE_IPV6, "IPv6" },
{ 256*LMP_OBJ_DATA_LINK+LMP_CTYPE_UNMD, "Unnumbered" },
{ 256*LMP_OBJ_CHANNEL_STATUS+LMP_CTYPE_IPV4, "IPv4" },
{ 256*LMP_OBJ_CHANNEL_STATUS+LMP_CTYPE_IPV6, "IPv6" },
{ 256*LMP_OBJ_CHANNEL_STATUS+LMP_CTYPE_UNMD, "Unnumbered" },
{ 256*LMP_OBJ_CHANNEL_STATUS_REQ+LMP_CTYPE_IPV4, "IPv4" },
{ 256*LMP_OBJ_CHANNEL_STATUS_REQ+LMP_CTYPE_IPV6, "IPv6" },
{ 256*LMP_OBJ_CHANNEL_STATUS_REQ+LMP_CTYPE_UNMD, "Unnumbered" },
{ 256*LMP_OBJ_ERROR_CODE+LMP_CTYPE_1, "1" },
{ 256*LMP_OBJ_ERROR_CODE+LMP_CTYPE_2, "2" },
{ 256*LMP_OBJ_SERVICE_CONFIG+LMP_CTYPE_SERVICE_CONFIG_SP, "1" },
{ 256*LMP_OBJ_SERVICE_CONFIG+LMP_CTYPE_SERVICE_CONFIG_CPSA, "2" },
{ 256*LMP_OBJ_SERVICE_CONFIG+LMP_CTYPE_SERVICE_CONFIG_TRANSPARENCY_TCM, "3" },
{ 256*LMP_OBJ_SERVICE_CONFIG+LMP_CTYPE_SERVICE_CONFIG_NETWORK_DIVERSITY, "4" },
{ 0, NULL}
};
static int
lmp_print_data_link_subobjs(netdissect_options *ndo, const u_char *obj_tptr,
int total_subobj_len, int offset)
{
int hexdump = FALSE;
int subobj_type, subobj_len;
union { /* int to float conversion buffer */
float f;
uint32_t i;
} bw;
while (total_subobj_len > 0 && hexdump == FALSE ) {
subobj_type = GET_U_1(obj_tptr + offset);
subobj_len = GET_U_1(obj_tptr + offset + 1);
ND_PRINT("\n\t Subobject, Type: %s (%u), Length: %u",
tok2str(lmp_data_link_subobj,
"Unknown",
subobj_type),
subobj_type,
subobj_len);
if (subobj_len < 4) {
ND_PRINT(" (too short)");
break;
}
if ((subobj_len % 4) != 0) {
ND_PRINT(" (not a multiple of 4)");
break;
}
if (total_subobj_len < subobj_len) {
ND_PRINT(" (goes past the end of the object)");
break;
}
switch(subobj_type) {
case INT_SWITCHING_TYPE_SUBOBJ:
ND_PRINT("\n\t Switching Type: %s (%u)",
tok2str(gmpls_switch_cap_values,
"Unknown",
GET_U_1(obj_tptr + offset + 2)),
GET_U_1(obj_tptr + offset + 2));
ND_PRINT("\n\t Encoding Type: %s (%u)",
tok2str(gmpls_encoding_values,
"Unknown",
GET_U_1(obj_tptr + offset + 3)),
GET_U_1(obj_tptr + offset + 3));
bw.i = GET_BE_U_4(obj_tptr + offset + 4);
ND_PRINT("\n\t Min Reservable Bandwidth: %.3f Mbps",
bw.f*8/1000000);
bw.i = GET_BE_U_4(obj_tptr + offset + 8);
ND_PRINT("\n\t Max Reservable Bandwidth: %.3f Mbps",
bw.f*8/1000000);
break;
case WAVELENGTH_SUBOBJ:
ND_PRINT("\n\t Wavelength: %u",
GET_BE_U_4(obj_tptr + offset + 4));
break;
default:
/* Any Unknown Subobject ==> Exit loop */
hexdump=TRUE;
break;
}
total_subobj_len-=subobj_len;
offset+=subobj_len;
}
return (hexdump);
}
void
lmp_print(netdissect_options *ndo,
const u_char *pptr, u_int length)
{
const struct lmp_common_header *lmp_com_header;
const u_char *tptr,*obj_tptr;
u_int version_res, tlen, lmp_obj_len, lmp_obj_ctype, obj_tlen;
int hexdump;
u_int offset;
u_int link_type;
union { /* int to float conversion buffer */
float f;
uint32_t i;
} bw;
ndo->ndo_protocol = "lmp";
tptr=pptr;
lmp_com_header = (const struct lmp_common_header *)pptr;
ND_TCHECK_SIZE(lmp_com_header);
version_res = GET_BE_U_2(lmp_com_header->version_res);
/*
* Sanity checking of the header.
*/
if (LMP_EXTRACT_VERSION(version_res) != LMP_VERSION) {
ND_PRINT("LMP version %u packet not supported",
LMP_EXTRACT_VERSION(version_res));
return;
}
/* in non-verbose mode just lets print the basic Message Type*/
if (ndo->ndo_vflag < 1) {
ND_PRINT("LMPv%u %s Message, length: %u",
LMP_EXTRACT_VERSION(version_res),
tok2str(lmp_msg_type_values, "unknown (%u)",GET_U_1(lmp_com_header->msg_type)),
length);
return;
}
/* ok they seem to want to know everything - lets fully decode it */
tlen=GET_BE_U_2(lmp_com_header->length);
ND_PRINT("\n\tLMPv%u, msg-type: %s, Flags: [%s], length: %u",
LMP_EXTRACT_VERSION(version_res),
tok2str(lmp_msg_type_values, "unknown, type: %u",GET_U_1(lmp_com_header->msg_type)),
bittok2str(lmp_header_flag_values,"none",GET_U_1(lmp_com_header->flags)),
tlen);
if (tlen < sizeof(struct lmp_common_header)) {
ND_PRINT(" (too short)");
return;
}
if (tlen > length) {
ND_PRINT(" (too long)");
tlen = length;
}
tptr+=sizeof(struct lmp_common_header);
tlen-=sizeof(struct lmp_common_header);
while(tlen>0) {
const struct lmp_object_header *lmp_obj_header =
(const struct lmp_object_header *)tptr;
lmp_obj_len=GET_BE_U_2(lmp_obj_header->length);
lmp_obj_ctype=GET_U_1(lmp_obj_header->ctype)&0x7f;
ND_PRINT("\n\t %s Object (%u), Class-Type: %s (%u) Flags: [%snegotiable], length: %u",
tok2str(lmp_obj_values,
"Unknown",
GET_U_1(lmp_obj_header->class_num)),
GET_U_1(lmp_obj_header->class_num),
tok2str(lmp_ctype_values,
"Unknown",
(GET_U_1(lmp_obj_header->class_num)<<8)+lmp_obj_ctype),
lmp_obj_ctype,
GET_U_1(lmp_obj_header->ctype)&0x80 ? "" : "non-",
lmp_obj_len);
if (lmp_obj_len < 4) {
ND_PRINT(" (too short)");
return;
}
if ((lmp_obj_len % 4) != 0) {
ND_PRINT(" (not a multiple of 4)");
return;
}
obj_tptr=tptr+sizeof(struct lmp_object_header);
obj_tlen=lmp_obj_len-sizeof(struct lmp_object_header);
/* did we capture enough for fully decoding the object ? */
ND_TCHECK_LEN(tptr, lmp_obj_len);
hexdump=FALSE;
switch(GET_U_1(lmp_obj_header->class_num)) {
case LMP_OBJ_CC_ID:
switch(lmp_obj_ctype) {
case LMP_CTYPE_LOC:
case LMP_CTYPE_RMT:
if (obj_tlen != 4) {
ND_PRINT(" (not correct for object)");
break;
}
ND_PRINT("\n\t Control Channel ID: %u (0x%08x)",
GET_BE_U_4(obj_tptr),
GET_BE_U_4(obj_tptr));
break;
default:
hexdump=TRUE;
}
break;
case LMP_OBJ_LINK_ID:
case LMP_OBJ_INTERFACE_ID:
switch(lmp_obj_ctype) {
case LMP_CTYPE_IPV4_LOC:
case LMP_CTYPE_IPV4_RMT:
if (obj_tlen != 4) {
ND_PRINT(" (not correct for object)");
break;
}
ND_PRINT("\n\t IPv4 Link ID: %s (0x%08x)",
GET_IPADDR_STRING(obj_tptr),
GET_BE_U_4(obj_tptr));
break;
case LMP_CTYPE_IPV6_LOC:
case LMP_CTYPE_IPV6_RMT:
if (obj_tlen != 16) {
ND_PRINT(" (not correct for object)");
break;
}
ND_PRINT("\n\t IPv6 Link ID: %s (0x%08x)",
GET_IP6ADDR_STRING(obj_tptr),
GET_BE_U_4(obj_tptr));
break;
case LMP_CTYPE_UNMD_LOC:
case LMP_CTYPE_UNMD_RMT:
if (obj_tlen != 4) {
ND_PRINT(" (not correct for object)");
break;
}
ND_PRINT("\n\t Link ID: %u (0x%08x)",
GET_BE_U_4(obj_tptr),
GET_BE_U_4(obj_tptr));
break;
default:
hexdump=TRUE;
}
break;
case LMP_OBJ_MESSAGE_ID:
switch(lmp_obj_ctype) {
case LMP_CTYPE_1:
if (obj_tlen != 4) {
ND_PRINT(" (not correct for object)");
break;
}
ND_PRINT("\n\t Message ID: %u (0x%08x)",
GET_BE_U_4(obj_tptr),
GET_BE_U_4(obj_tptr));
break;
case LMP_CTYPE_2:
if (obj_tlen != 4) {
ND_PRINT(" (not correct for object)");
break;
}
ND_PRINT("\n\t Message ID Ack: %u (0x%08x)",
GET_BE_U_4(obj_tptr),
GET_BE_U_4(obj_tptr));
break;
default:
hexdump=TRUE;
}
break;
case LMP_OBJ_NODE_ID:
switch(lmp_obj_ctype) {
case LMP_CTYPE_LOC:
case LMP_CTYPE_RMT:
if (obj_tlen != 4) {
ND_PRINT(" (not correct for object)");
break;
}
ND_PRINT("\n\t Node ID: %s (0x%08x)",
GET_IPADDR_STRING(obj_tptr),
GET_BE_U_4(obj_tptr));
break;
default:
hexdump=TRUE;
}
break;
case LMP_OBJ_CONFIG:
switch(lmp_obj_ctype) {
case LMP_CTYPE_HELLO_CONFIG:
if (obj_tlen != 4) {
ND_PRINT(" (not correct for object)");
break;
}
ND_PRINT("\n\t Hello Interval: %u\n\t Hello Dead Interval: %u",
GET_BE_U_2(obj_tptr),
GET_BE_U_2(obj_tptr + 2));
break;
default:
hexdump=TRUE;
}
break;
case LMP_OBJ_HELLO:
switch(lmp_obj_ctype) {
case LMP_CTYPE_HELLO:
if (obj_tlen != 8) {
ND_PRINT(" (not correct for object)");
break;
}
ND_PRINT("\n\t Tx Seq: %u, Rx Seq: %u",
GET_BE_U_4(obj_tptr),
GET_BE_U_4(obj_tptr + 4));
break;
default:
hexdump=TRUE;
}
break;
case LMP_OBJ_TE_LINK:
switch(lmp_obj_ctype) {
case LMP_CTYPE_IPV4:
if (obj_tlen != 12) {
ND_PRINT(" (not correct for object)");
break;
}
ND_PRINT("\n\t Flags: [%s]",
bittok2str(lmp_obj_te_link_flag_values,
"none",
GET_U_1(obj_tptr)));
ND_PRINT("\n\t Local Link-ID: %s (0x%08x)"
"\n\t Remote Link-ID: %s (0x%08x)",
GET_IPADDR_STRING(obj_tptr+4),
GET_BE_U_4(obj_tptr + 4),
GET_IPADDR_STRING(obj_tptr+8),
GET_BE_U_4(obj_tptr + 8));
break;
case LMP_CTYPE_IPV6:
if (obj_tlen != 36) {
ND_PRINT(" (not correct for object)");
break;
}
ND_PRINT("\n\t Flags: [%s]",
bittok2str(lmp_obj_te_link_flag_values,
"none",
GET_U_1(obj_tptr)));
ND_PRINT("\n\t Local Link-ID: %s (0x%08x)"
"\n\t Remote Link-ID: %s (0x%08x)",
GET_IP6ADDR_STRING(obj_tptr+4),
GET_BE_U_4(obj_tptr + 4),
GET_IP6ADDR_STRING(obj_tptr+20),
GET_BE_U_4(obj_tptr + 20));
break;
case LMP_CTYPE_UNMD:
if (obj_tlen != 12) {
ND_PRINT(" (not correct for object)");
break;
}
ND_PRINT("\n\t Flags: [%s]",
bittok2str(lmp_obj_te_link_flag_values,
"none",
GET_U_1(obj_tptr)));
ND_PRINT("\n\t Local Link-ID: %u (0x%08x)"
"\n\t Remote Link-ID: %u (0x%08x)",
GET_BE_U_4(obj_tptr + 4),
GET_BE_U_4(obj_tptr + 4),
GET_BE_U_4(obj_tptr + 8),
GET_BE_U_4(obj_tptr + 8));
break;
default:
hexdump=TRUE;
}
break;
case LMP_OBJ_DATA_LINK:
switch(lmp_obj_ctype) {
case LMP_CTYPE_IPV4:
if (obj_tlen < 12) {
ND_PRINT(" (not correct for object)");
break;
}
ND_PRINT("\n\t Flags: [%s]",
bittok2str(lmp_obj_data_link_flag_values,
"none",
GET_U_1(obj_tptr)));
ND_PRINT("\n\t Local Interface ID: %s (0x%08x)"
"\n\t Remote Interface ID: %s (0x%08x)",
GET_IPADDR_STRING(obj_tptr+4),
GET_BE_U_4(obj_tptr + 4),
GET_IPADDR_STRING(obj_tptr+8),
GET_BE_U_4(obj_tptr + 8));
if (lmp_print_data_link_subobjs(ndo, obj_tptr, obj_tlen - 12, 12))
hexdump=TRUE;
break;
case LMP_CTYPE_IPV6:
if (obj_tlen < 36) {
ND_PRINT(" (not correct for object)");
break;
}
ND_PRINT("\n\t Flags: [%s]",
bittok2str(lmp_obj_data_link_flag_values,
"none",
GET_U_1(obj_tptr)));
ND_PRINT("\n\t Local Interface ID: %s (0x%08x)"
"\n\t Remote Interface ID: %s (0x%08x)",
GET_IP6ADDR_STRING(obj_tptr+4),
GET_BE_U_4(obj_tptr + 4),
GET_IP6ADDR_STRING(obj_tptr+20),
GET_BE_U_4(obj_tptr + 20));
if (lmp_print_data_link_subobjs(ndo, obj_tptr, obj_tlen - 36, 36))
hexdump=TRUE;
break;
case LMP_CTYPE_UNMD:
if (obj_tlen < 12) {
ND_PRINT(" (not correct for object)");
break;
}
ND_PRINT("\n\t Flags: [%s]",
bittok2str(lmp_obj_data_link_flag_values,
"none",
GET_U_1(obj_tptr)));
ND_PRINT("\n\t Local Interface ID: %u (0x%08x)"
"\n\t Remote Interface ID: %u (0x%08x)",
GET_BE_U_4(obj_tptr + 4),
GET_BE_U_4(obj_tptr + 4),
GET_BE_U_4(obj_tptr + 8),
GET_BE_U_4(obj_tptr + 8));
if (lmp_print_data_link_subobjs(ndo, obj_tptr, obj_tlen - 12, 12))
hexdump=TRUE;
break;
default:
hexdump=TRUE;
}
break;
case LMP_OBJ_VERIFY_BEGIN:
switch(lmp_obj_ctype) {
case LMP_CTYPE_1:
if (obj_tlen != 20) {
ND_PRINT(" (not correct for object)");
break;
}
ND_PRINT("\n\t Flags: %s",
bittok2str(lmp_obj_begin_verify_flag_values,
"none",
GET_BE_U_2(obj_tptr)));
ND_PRINT("\n\t Verify Interval: %u",
GET_BE_U_2(obj_tptr + 2));
ND_PRINT("\n\t Data links: %u",
GET_BE_U_4(obj_tptr + 4));
ND_PRINT("\n\t Encoding type: %s",
tok2str(gmpls_encoding_values, "Unknown", GET_U_1((obj_tptr + 8))));
ND_PRINT("\n\t Verify Transport Mechanism: %u (0x%x)%s",
GET_BE_U_2(obj_tptr + 10),
GET_BE_U_2(obj_tptr + 10),
GET_BE_U_2(obj_tptr + 10)&8000 ? " (Payload test messages capable)" : "");
bw.i = GET_BE_U_4(obj_tptr + 12);
ND_PRINT("\n\t Transmission Rate: %.3f Mbps",bw.f*8/1000000);
ND_PRINT("\n\t Wavelength: %u",
GET_BE_U_4(obj_tptr + 16));
break;
default:
hexdump=TRUE;
}
break;
case LMP_OBJ_VERIFY_BEGIN_ACK:
switch(lmp_obj_ctype) {
case LMP_CTYPE_1:
if (obj_tlen != 4) {
ND_PRINT(" (not correct for object)");
break;
}
ND_PRINT("\n\t Verify Dead Interval: %u"
"\n\t Verify Transport Response: %u",
GET_BE_U_2(obj_tptr),
GET_BE_U_2(obj_tptr + 2));
break;
default:
hexdump=TRUE;
}
break;
case LMP_OBJ_VERIFY_ID:
switch(lmp_obj_ctype) {
case LMP_CTYPE_1:
if (obj_tlen != 4) {
ND_PRINT(" (not correct for object)");
break;
}
ND_PRINT("\n\t Verify ID: %u",
GET_BE_U_4(obj_tptr));
break;
default:
hexdump=TRUE;
}
break;
case LMP_OBJ_CHANNEL_STATUS:
switch(lmp_obj_ctype) {
case LMP_CTYPE_IPV4:
offset = 0;
/* Decode pairs: <Interface_ID (4 bytes), Channel_status (4 bytes)> */
while (offset+8 <= obj_tlen) {
ND_PRINT("\n\t Interface ID: %s (0x%08x)",
GET_IPADDR_STRING(obj_tptr+offset),
GET_BE_U_4(obj_tptr + offset));
ND_PRINT("\n\t\t Active: %s (%u)",
(GET_BE_U_4(obj_tptr + offset + 4)>>31) ?
"Allocated" : "Non-allocated",
(GET_BE_U_4(obj_tptr + offset + 4)>>31));
ND_PRINT("\n\t\t Direction: %s (%u)",
(GET_BE_U_4(obj_tptr + offset + 4)>>30)&0x1 ?
"Transmit" : "Receive",
(GET_BE_U_4(obj_tptr + offset + 4)>>30)&0x1);
ND_PRINT("\n\t\t Channel Status: %s (%u)",
tok2str(lmp_obj_channel_status_values,
"Unknown",
GET_BE_U_4(obj_tptr + offset + 4)&0x3FFFFFF),
GET_BE_U_4(obj_tptr + offset + 4)&0x3FFFFFF);
offset+=8;
}
break;
case LMP_CTYPE_IPV6:
offset = 0;
/* Decode pairs: <Interface_ID (16 bytes), Channel_status (4 bytes)> */
while (offset+20 <= obj_tlen) {
ND_PRINT("\n\t Interface ID: %s (0x%08x)",
GET_IP6ADDR_STRING(obj_tptr+offset),
GET_BE_U_4(obj_tptr + offset));
ND_PRINT("\n\t\t Active: %s (%u)",
(GET_BE_U_4(obj_tptr + offset + 16)>>31) ?
"Allocated" : "Non-allocated",
(GET_BE_U_4(obj_tptr + offset + 16)>>31));
ND_PRINT("\n\t\t Direction: %s (%u)",
(GET_BE_U_4(obj_tptr + offset + 16)>>30)&0x1 ?
"Transmit" : "Receive",
(GET_BE_U_4(obj_tptr + offset + 16)>>30)&0x1);
ND_PRINT("\n\t\t Channel Status: %s (%u)",
tok2str(lmp_obj_channel_status_values,
"Unknown",
GET_BE_U_4(obj_tptr + offset + 16)&0x3FFFFFF),
GET_BE_U_4(obj_tptr + offset + 16)&0x3FFFFFF);
offset+=20;
}
break;
case LMP_CTYPE_UNMD:
offset = 0;
/* Decode pairs: <Interface_ID (4 bytes), Channel_status (4 bytes)> */
while (offset+8 <= obj_tlen) {
ND_PRINT("\n\t Interface ID: %u (0x%08x)",
GET_BE_U_4(obj_tptr + offset),
GET_BE_U_4(obj_tptr + offset));
ND_PRINT("\n\t\t Active: %s (%u)",
(GET_BE_U_4(obj_tptr + offset + 4)>>31) ?
"Allocated" : "Non-allocated",
(GET_BE_U_4(obj_tptr + offset + 4)>>31));
ND_PRINT("\n\t\t Direction: %s (%u)",
(GET_BE_U_4(obj_tptr + offset + 4)>>30)&0x1 ?
"Transmit" : "Receive",
(GET_BE_U_4(obj_tptr + offset + 4)>>30)&0x1);
ND_PRINT("\n\t\t Channel Status: %s (%u)",
tok2str(lmp_obj_channel_status_values,
"Unknown",
GET_BE_U_4(obj_tptr + offset + 4)&0x3FFFFFF),
GET_BE_U_4(obj_tptr + offset + 4)&0x3FFFFFF);
offset+=8;
}
break;
default:
hexdump=TRUE;
}
break;
case LMP_OBJ_CHANNEL_STATUS_REQ:
switch(lmp_obj_ctype) {
case LMP_CTYPE_IPV4:
offset = 0;
while (offset+4 <= obj_tlen) {
ND_PRINT("\n\t Interface ID: %s (0x%08x)",
GET_IPADDR_STRING(obj_tptr+offset),
GET_BE_U_4(obj_tptr + offset));
offset+=4;
}
break;
case LMP_CTYPE_IPV6:
offset = 0;
while (offset+16 <= obj_tlen) {
ND_PRINT("\n\t Interface ID: %s (0x%08x)",
GET_IP6ADDR_STRING(obj_tptr+offset),
GET_BE_U_4(obj_tptr + offset));
offset+=16;
}
break;
case LMP_CTYPE_UNMD:
offset = 0;
while (offset+4 <= obj_tlen) {
ND_PRINT("\n\t Interface ID: %u (0x%08x)",
GET_BE_U_4(obj_tptr + offset),
GET_BE_U_4(obj_tptr + offset));
offset+=4;
}
break;
default:
hexdump=TRUE;
}
break;
case LMP_OBJ_ERROR_CODE:
switch(lmp_obj_ctype) {
case LMP_CTYPE_BEGIN_VERIFY_ERROR:
if (obj_tlen != 4) {
ND_PRINT(" (not correct for object)");
break;
}
ND_PRINT("\n\t Error Code: %s",
bittok2str(lmp_obj_begin_verify_error_values,
"none",
GET_BE_U_4(obj_tptr)));
break;
case LMP_CTYPE_LINK_SUMMARY_ERROR:
if (obj_tlen != 4) {
ND_PRINT(" (not correct for object)");
break;
}
ND_PRINT("\n\t Error Code: %s",
bittok2str(lmp_obj_link_summary_error_values,
"none",
GET_BE_U_4(obj_tptr)));
break;
default:
hexdump=TRUE;
}
break;
case LMP_OBJ_SERVICE_CONFIG:
switch (lmp_obj_ctype) {
case LMP_CTYPE_SERVICE_CONFIG_SP:
if (obj_tlen != 4) {
ND_PRINT(" (not correct for object)");
break;
}
ND_PRINT("\n\t Flags: %s",
bittok2str(lmp_obj_service_config_sp_flag_values,
"none",
GET_U_1(obj_tptr)));
ND_PRINT("\n\t UNI Version: %u",
GET_U_1(obj_tptr + 1));
break;
case LMP_CTYPE_SERVICE_CONFIG_CPSA:
if (obj_tlen != 16) {
ND_PRINT(" (not correct for object)");
break;
}
link_type = GET_U_1(obj_tptr);
ND_PRINT("\n\t Link Type: %s (%u)",
tok2str(lmp_sd_service_config_cpsa_link_type_values,
"Unknown", link_type),
link_type);
switch (link_type) {
case LMP_SD_SERVICE_CONFIG_CPSA_LINK_TYPE_SDH:
ND_PRINT("\n\t Signal Type: %s (%u)",
tok2str(lmp_sd_service_config_cpsa_signal_type_sdh_values,
"Unknown",
GET_U_1(obj_tptr + 1)),
GET_U_1(obj_tptr + 1));
break;
case LMP_SD_SERVICE_CONFIG_CPSA_LINK_TYPE_SONET:
ND_PRINT("\n\t Signal Type: %s (%u)",
tok2str(lmp_sd_service_config_cpsa_signal_type_sonet_values,
"Unknown",
GET_U_1(obj_tptr + 1)),
GET_U_1(obj_tptr + 1));
break;
}
ND_PRINT("\n\t Transparency: %s",
bittok2str(lmp_obj_service_config_cpsa_tp_flag_values,
"none",
GET_U_1(obj_tptr + 2)));
ND_PRINT("\n\t Contiguous Concatenation Types: %s",
bittok2str(lmp_obj_service_config_cpsa_cct_flag_values,
"none",
GET_U_1(obj_tptr + 3)));
ND_PRINT("\n\t Minimum NCC: %u",
GET_BE_U_2(obj_tptr + 4));
ND_PRINT("\n\t Maximum NCC: %u",
GET_BE_U_2(obj_tptr + 6));
ND_PRINT("\n\t Minimum NVC:%u",
GET_BE_U_2(obj_tptr + 8));
ND_PRINT("\n\t Maximum NVC:%u",
GET_BE_U_2(obj_tptr + 10));
ND_PRINT("\n\t Local Interface ID: %s (0x%08x)",
GET_IPADDR_STRING(obj_tptr+12),
GET_BE_U_4(obj_tptr + 12));
break;
case LMP_CTYPE_SERVICE_CONFIG_TRANSPARENCY_TCM:
if (obj_tlen != 8) {
ND_PRINT(" (not correct for object)");
break;
}
ND_PRINT("\n\t Transparency Flags: %s",
bittok2str(
lmp_obj_service_config_nsa_transparency_flag_values,
"none",
GET_BE_U_4(obj_tptr)));
ND_PRINT("\n\t TCM Monitoring Flags: %s",
bittok2str(
lmp_obj_service_config_nsa_tcm_flag_values,
"none",
GET_U_1(obj_tptr + 7)));
break;
case LMP_CTYPE_SERVICE_CONFIG_NETWORK_DIVERSITY:
if (obj_tlen != 4) {
ND_PRINT(" (not correct for object)");
break;
}
ND_PRINT("\n\t Diversity: Flags: %s",
bittok2str(
lmp_obj_service_config_nsa_network_diversity_flag_values,
"none",
GET_U_1(obj_tptr + 3)));
break;
default:
hexdump = TRUE;
}
break;
default:
if (ndo->ndo_vflag <= 1)
print_unknown_data(ndo,obj_tptr,"\n\t ",obj_tlen);
break;
}
/* do we want to see an additionally hexdump ? */
if (ndo->ndo_vflag > 1 || hexdump==TRUE)
print_unknown_data(ndo,tptr+sizeof(struct lmp_object_header),"\n\t ",
lmp_obj_len-sizeof(struct lmp_object_header));
if (tlen < lmp_obj_len) {
ND_PRINT(" [remaining objects length %u < %u]", tlen, lmp_obj_len);
nd_print_invalid(ndo);
break;
}
tptr+=lmp_obj_len;
tlen-=lmp_obj_len;
}
}
diff --git a/contrib/tcpdump/print-loopback.c b/contrib/tcpdump/print-loopback.c
index ee0caf3cfe4f..b96b63885642 100644
--- a/contrib/tcpdump/print-loopback.c
+++ b/contrib/tcpdump/print-loopback.c
@@ -1,135 +1,134 @@
/*
* Copyright (c) 2014 The TCPDUMP project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* \summary: Loopback Protocol printer */
/*
* originally defined as the Ethernet Configuration Testing Protocol.
- * specification: https://www.mit.edu/people/jhawk/ctp.pdf
+ * specification:
+ * https://web.archive.org/web/20060919181108/http://www.mit.edu/people/jhawk/ctp.pdf
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
#include "addrtoname.h"
#define LOOPBACK_REPLY 1
#define LOOPBACK_FWDDATA 2
static const struct tok fcode_str[] = {
{ LOOPBACK_REPLY, "Reply" },
{ LOOPBACK_FWDDATA, "Forward Data" },
{ 0, NULL }
};
static void
loopback_message_print(netdissect_options *ndo,
const u_char *cp, u_int len)
{
uint16_t function;
if (len < 2)
goto invalid;
/* function */
function = GET_LE_U_2(cp);
cp += 2;
len -= 2;
ND_PRINT(", %s", tok2str(fcode_str, " invalid (%u)", function));
switch (function) {
case LOOPBACK_REPLY:
if (len < 2)
goto invalid;
/* receipt number */
ND_PRINT(", receipt number %u", GET_LE_U_2(cp));
cp += 2;
len -= 2;
/* data */
ND_PRINT(", data (%u octets)", len);
ND_TCHECK_LEN(cp, len);
break;
case LOOPBACK_FWDDATA:
if (len < MAC_ADDR_LEN)
goto invalid;
/* forwarding address */
ND_PRINT(", forwarding address %s", GET_ETHERADDR_STRING(cp));
cp += MAC_ADDR_LEN;
len -= MAC_ADDR_LEN;
/* data */
ND_PRINT(", data (%u octets)", len);
ND_TCHECK_LEN(cp, len);
break;
default:
ND_TCHECK_LEN(cp, len);
break;
}
return;
invalid:
nd_print_invalid(ndo);
ND_TCHECK_LEN(cp, len);
}
void
loopback_print(netdissect_options *ndo,
const u_char *cp, u_int len)
{
uint16_t skipCount;
ndo->ndo_protocol = "loopback";
ND_PRINT("Loopback");
if (len < 2)
goto invalid;
/* skipCount */
skipCount = GET_LE_U_2(cp);
cp += 2;
len -= 2;
ND_PRINT(", skipCount %u", skipCount);
if (skipCount % 8)
ND_PRINT(" (bogus)");
if (skipCount > len)
goto invalid;
/* the octets to skip */
ND_TCHECK_LEN(cp, skipCount);
cp += skipCount;
len -= skipCount;
/* the first message to decode */
loopback_message_print(ndo, cp, len);
return;
invalid:
nd_print_invalid(ndo);
ND_TCHECK_LEN(cp, len);
}
diff --git a/contrib/tcpdump/print-lspping.c b/contrib/tcpdump/print-lspping.c
index f3183cb29299..837738a7ad55 100644
--- a/contrib/tcpdump/print-lspping.c
+++ b/contrib/tcpdump/print-lspping.c
@@ -1,1077 +1,1075 @@
/*
* 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.
*
* Original code by Hannes Gredler (hannes@gredler.at)
*/
/* \summary: MPLS LSP PING printer */
/* specification: RFC 4379 */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
#include "addrtoname.h"
#include "ntp.h"
#include "l2vpn.h"
#include "oui.h"
/*
* LSPPING common header
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Version Number | Must Be Zero |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Message Type | Reply mode | Return Code | Return Subcode|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Sender's Handle |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Sequence Number |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | TimeStamp Sent (seconds) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | TimeStamp Sent (microseconds) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | TimeStamp Received (seconds) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | TimeStamp Received (microseconds) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | TLVs ... |
* . .
* . .
* . .
*/
struct lspping_common_header {
nd_uint16_t version;
nd_uint16_t global_flags;
nd_uint8_t msg_type;
nd_uint8_t reply_mode;
nd_uint8_t return_code;
nd_uint8_t return_subcode;
nd_uint32_t sender_handle;
nd_uint32_t seq_number;
struct l_fixedpt ts_sent;
struct l_fixedpt ts_rcvd;
};
#define LSPPING_VERSION 1
static const struct tok lspping_msg_type_values[] = {
{ 1, "MPLS Echo Request"},
{ 2, "MPLS Echo Reply"},
{ 0, NULL}
};
static const struct tok lspping_reply_mode_values[] = {
{ 1, "Do not reply"},
{ 2, "Reply via an IPv4/IPv6 UDP packet"},
{ 3, "Reply via an IPv4/IPv6 UDP packet with Router Alert"},
{ 4, "Reply via application level control channel"},
{ 0, NULL}
};
static const struct tok lspping_return_code_values[] = {
{ 0, "No return code or return code contained in the Error Code TLV"},
{ 1, "Malformed echo request received"},
{ 2, "One or more of the TLVs was not understood"},
{ 3, "Replying router is an egress for the FEC at stack depth"},
{ 4, "Replying router has no mapping for the FEC at stack depth"},
{ 5, "Reserved"},
{ 6, "Reserved"},
{ 7, "Reserved"},
{ 8, "Label switched at stack-depth"},
{ 9, "Label switched but no MPLS forwarding at stack-depth"},
{ 10, "Mapping for this FEC is not the given label at stack depth"},
{ 11, "No label entry at stack-depth"},
{ 12, "Protocol not associated with interface at FEC stack depth"},
{ 13, "Premature termination of ping due to label stack shrinking to a single label"},
{ 0, NULL},
};
/*
* LSPPING TLV header
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Type | Length |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Value |
* . .
* . .
* . .
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct lspping_tlv_header {
nd_uint16_t type;
nd_uint16_t length;
};
#define LSPPING_TLV_TARGET_FEC_STACK 1
#define LSPPING_TLV_DOWNSTREAM_MAPPING 2
#define LSPPING_TLV_PAD 3
/* not assigned 4 */
#define LSPPING_TLV_VENDOR_ENTERPRISE 5
#define LSPPING_TLV_VENDOR_ENTERPRISE_LEN 4
/* not assigned 6 */
#define LSPPING_TLV_INTERFACE_LABEL_STACK 7
/* not assigned 8 */
#define LSPPING_TLV_ERROR_CODE 9
#define LSPPING_TLV_REPLY_TOS_BYTE 10
#define LSPPING_TLV_BFD_DISCRIMINATOR 15 /* draft-ietf-bfd-mpls-02 */
#define LSPPING_TLV_BFD_DISCRIMINATOR_LEN 4
#define LSPPING_TLV_VENDOR_PRIVATE 0xfc00
static const struct tok lspping_tlv_values[] = {
{ LSPPING_TLV_TARGET_FEC_STACK, "Target FEC Stack" },
{ LSPPING_TLV_DOWNSTREAM_MAPPING, "Downstream Mapping" },
{ LSPPING_TLV_PAD, "Pad" },
{ LSPPING_TLV_ERROR_CODE, "Error Code" },
{ LSPPING_TLV_VENDOR_ENTERPRISE, "Vendor Enterprise Code" },
{ LSPPING_TLV_INTERFACE_LABEL_STACK, "Interface Label Stack" },
{ LSPPING_TLV_REPLY_TOS_BYTE, "Reply TOS Byte" },
{ LSPPING_TLV_BFD_DISCRIMINATOR, "BFD Discriminator" },
{ LSPPING_TLV_VENDOR_PRIVATE, "Vendor Private Code" },
{ 0, NULL}
};
#define LSPPING_TLV_TARGETFEC_SUBTLV_LDP_IPV4 1
#define LSPPING_TLV_TARGETFEC_SUBTLV_LDP_IPV6 2
#define LSPPING_TLV_TARGETFEC_SUBTLV_RSVP_IPV4 3
#define LSPPING_TLV_TARGETFEC_SUBTLV_RSVP_IPV6 4
/* not assigned 5 */
#define LSPPING_TLV_TARGETFEC_SUBTLV_L3VPN_IPV4 6
#define LSPPING_TLV_TARGETFEC_SUBTLV_L3VPN_IPV6 7
#define LSPPING_TLV_TARGETFEC_SUBTLV_L2VPN_ENDPT 8
#define LSPPING_TLV_TARGETFEC_SUBTLV_FEC_128_PW_OLD 9
#define LSPPING_TLV_TARGETFEC_SUBTLV_FEC_128_PW 10
#define LSPPING_TLV_TARGETFEC_SUBTLV_FEC_129_PW 11
#define LSPPING_TLV_TARGETFEC_SUBTLV_BGP_IPV4 12
#define LSPPING_TLV_TARGETFEC_SUBTLV_BGP_IPV6 13
#define LSPPING_TLV_TARGETFEC_SUBTLV_GENERIC_IPV4 14
#define LSPPING_TLV_TARGETFEC_SUBTLV_GENERIC_IPV6 15
#define LSPPING_TLV_TARGETFEC_SUBTLV_NIL_FEC 16
static const struct tok lspping_tlvtargetfec_subtlv_values[] = {
{ LSPPING_TLV_TARGETFEC_SUBTLV_LDP_IPV4, "LDP IPv4 prefix"},
{ LSPPING_TLV_TARGETFEC_SUBTLV_LDP_IPV6, "LDP IPv6 prefix"},
{ LSPPING_TLV_TARGETFEC_SUBTLV_RSVP_IPV4, "RSVP IPv4 Session Query"},
{ LSPPING_TLV_TARGETFEC_SUBTLV_RSVP_IPV6, "RSVP IPv6 Session Query"},
{ 5, "Reserved"},
{ LSPPING_TLV_TARGETFEC_SUBTLV_L3VPN_IPV4, "VPN IPv4 prefix"},
{ LSPPING_TLV_TARGETFEC_SUBTLV_L3VPN_IPV6, "VPN IPv6 prefix"},
{ LSPPING_TLV_TARGETFEC_SUBTLV_L2VPN_ENDPT, "L2 VPN endpoint"},
{ LSPPING_TLV_TARGETFEC_SUBTLV_FEC_128_PW_OLD, "FEC 128 pseudowire (old)"},
{ LSPPING_TLV_TARGETFEC_SUBTLV_FEC_128_PW, "FEC 128 pseudowire"},
{ LSPPING_TLV_TARGETFEC_SUBTLV_BGP_IPV4, "BGP labeled IPv4 prefix"},
{ LSPPING_TLV_TARGETFEC_SUBTLV_BGP_IPV6, "BGP labeled IPv6 prefix"},
{ 0, NULL}
};
/*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | IPv4 prefix |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Prefix Length | Must Be Zero |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct lspping_tlv_targetfec_subtlv_ldp_ipv4_t {
nd_ipv4 prefix;
nd_uint8_t prefix_len;
};
/*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | IPv6 prefix |
* | (16 octets) |
* | |
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Prefix Length | Must Be Zero |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct lspping_tlv_targetfec_subtlv_ldp_ipv6_t {
nd_ipv6 prefix;
nd_uint8_t prefix_len;
};
/*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | IPv4 tunnel end point address |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Must Be Zero | Tunnel ID |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Extended Tunnel ID |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | IPv4 tunnel sender address |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Must Be Zero | LSP ID |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct lspping_tlv_targetfec_subtlv_rsvp_ipv4_t {
nd_ipv4 tunnel_endpoint;
nd_byte res[2];
nd_uint16_t tunnel_id;
nd_ipv4 extended_tunnel_id;
nd_ipv4 tunnel_sender;
nd_byte res2[2];
nd_uint16_t lsp_id;
};
/*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | IPv6 tunnel end point address |
* | |
* | |
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Must Be Zero | Tunnel ID |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Extended Tunnel ID |
* | |
* | |
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | IPv6 tunnel sender address |
* | |
* | |
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Must Be Zero | LSP ID |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct lspping_tlv_targetfec_subtlv_rsvp_ipv6_t {
nd_ipv6 tunnel_endpoint;
nd_byte res[2];
nd_uint16_t tunnel_id;
nd_ipv6 extended_tunnel_id;
nd_ipv6 tunnel_sender;
nd_byte res2[2];
nd_uint16_t lsp_id;
};
/*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Route Distinguisher |
* | (8 octets) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | IPv4 prefix |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Prefix Length | Must Be Zero |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct lspping_tlv_targetfec_subtlv_l3vpn_ipv4_t {
nd_byte rd[8];
nd_ipv4 prefix;
nd_uint8_t prefix_len;
};
/*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Route Distinguisher |
* | (8 octets) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | IPv6 prefix |
* | (16 octets) |
* | |
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Prefix Length | Must Be Zero |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct lspping_tlv_targetfec_subtlv_l3vpn_ipv6_t {
nd_byte rd[8];
nd_ipv6 prefix;
nd_uint8_t prefix_len;
};
/*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Route Distinguisher |
* | (8 octets) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Sender's VE ID | Receiver's VE ID |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Encapsulation Type | Must Be Zero |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* 0 1 2 3
*/
struct lspping_tlv_targetfec_subtlv_l2vpn_endpt_t {
nd_byte rd[8];
nd_uint16_t sender_ve_id;
nd_uint16_t receiver_ve_id;
nd_uint16_t encapsulation;
};
/*
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Remote PE Address |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | PW ID |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | PW Type | Must Be Zero |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct lspping_tlv_targetfec_subtlv_fec_128_pw_old {
nd_ipv4 remote_pe_address;
nd_uint32_t pw_id;
nd_uint16_t pw_type;
};
/*
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Sender's PE Address |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Remote PE Address |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | PW ID |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | PW Type | Must Be Zero |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct lspping_tlv_targetfec_subtlv_fec_128_pw {
nd_ipv4 sender_pe_address;
nd_ipv4 remote_pe_address;
nd_uint32_t pw_id;
nd_uint16_t pw_type;
};
/*
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | IPv4 prefix |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Prefix Length | Must Be Zero |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct lspping_tlv_targetfec_subtlv_bgp_ipv4_t {
nd_ipv4 prefix;
nd_uint8_t prefix_len;
};
/*
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | IPv6 prefix |
* | (16 octets) |
* | |
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Prefix Length | Must Be Zero |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct lspping_tlv_targetfec_subtlv_bgp_ipv6_t {
nd_ipv6 prefix;
nd_uint8_t prefix_len;
};
/*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | MTU | Address Type | Resvd (SBZ) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Downstream IP Address (4 or 16 octets) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Downstream Interface Address (4 or 16 octets) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Multipath Type| Depth Limit | Multipath Length |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* . .
* . (Multipath Information) .
* . .
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Downstream Label | Protocol |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* . .
* . .
* . .
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Downstream Label | Protocol |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/* Enough to get the address type */
struct lspping_tlv_downstream_map_t {
nd_uint16_t mtu;
nd_uint8_t address_type;
nd_uint8_t ds_flags;
};
struct lspping_tlv_downstream_map_ipv4_t {
nd_uint16_t mtu;
nd_uint8_t address_type;
nd_uint8_t ds_flags;
nd_ipv4 downstream_ip;
nd_ipv4 downstream_interface;
};
struct lspping_tlv_downstream_map_ipv4_unmb_t {
nd_uint16_t mtu;
nd_uint8_t address_type;
nd_uint8_t ds_flags;
nd_ipv4 downstream_ip;
nd_uint32_t downstream_interface;
};
struct lspping_tlv_downstream_map_ipv6_t {
nd_uint16_t mtu;
nd_uint8_t address_type;
nd_uint8_t ds_flags;
nd_ipv6 downstream_ip;
nd_ipv6 downstream_interface;
};
struct lspping_tlv_downstream_map_ipv6_unmb_t {
nd_uint16_t mtu;
nd_uint8_t address_type;
nd_uint8_t ds_flags;
nd_ipv6 downstream_ip;
nd_uint32_t downstream_interface;
};
struct lspping_tlv_downstream_map_info_t {
nd_uint8_t multipath_type;
nd_uint8_t depth_limit;
nd_uint16_t multipath_length;
};
#define LSPPING_AFI_IPV4 1
#define LSPPING_AFI_IPV4_UNMB 2
#define LSPPING_AFI_IPV6 3
#define LSPPING_AFI_IPV6_UNMB 4
static const struct tok lspping_tlv_downstream_addr_values[] = {
{ LSPPING_AFI_IPV4, "IPv4"},
{ LSPPING_AFI_IPV4_UNMB, "Unnumbered IPv4"},
{ LSPPING_AFI_IPV6, "IPv6"},
{ LSPPING_AFI_IPV6_UNMB, "IPv6"},
{ 0, NULL}
};
void
lspping_print(netdissect_options *ndo,
const u_char *pptr, u_int len)
{
const struct lspping_common_header *lspping_com_header;
const struct lspping_tlv_header *lspping_tlv_header;
const struct lspping_tlv_header *lspping_subtlv_header;
const u_char *tptr,*tlv_tptr,*subtlv_tptr;
u_int return_code, return_subcode;
u_int tlen,lspping_tlv_len,lspping_tlv_type,tlv_tlen;
int tlv_hexdump,subtlv_hexdump;
u_int lspping_subtlv_len,lspping_subtlv_type;
uint32_t int_part, fraction;
u_int address_type;
union {
const struct lspping_tlv_downstream_map_t *lspping_tlv_downstream_map;
const struct lspping_tlv_downstream_map_ipv4_t *lspping_tlv_downstream_map_ipv4;
const struct lspping_tlv_downstream_map_ipv4_unmb_t *lspping_tlv_downstream_map_ipv4_unmb;
const struct lspping_tlv_downstream_map_ipv6_t *lspping_tlv_downstream_map_ipv6;
const struct lspping_tlv_downstream_map_ipv6_unmb_t *lspping_tlv_downstream_map_ipv6_unmb;
const struct lspping_tlv_downstream_map_info_t *lspping_tlv_downstream_map_info;
} tlv_ptr;
union {
const struct lspping_tlv_targetfec_subtlv_ldp_ipv4_t *lspping_tlv_targetfec_subtlv_ldp_ipv4;
const struct lspping_tlv_targetfec_subtlv_ldp_ipv6_t *lspping_tlv_targetfec_subtlv_ldp_ipv6;
const struct lspping_tlv_targetfec_subtlv_rsvp_ipv4_t *lspping_tlv_targetfec_subtlv_rsvp_ipv4;
const struct lspping_tlv_targetfec_subtlv_rsvp_ipv6_t *lspping_tlv_targetfec_subtlv_rsvp_ipv6;
const struct lspping_tlv_targetfec_subtlv_l3vpn_ipv4_t *lspping_tlv_targetfec_subtlv_l3vpn_ipv4;
const struct lspping_tlv_targetfec_subtlv_l3vpn_ipv6_t *lspping_tlv_targetfec_subtlv_l3vpn_ipv6;
const struct lspping_tlv_targetfec_subtlv_l2vpn_endpt_t *lspping_tlv_targetfec_subtlv_l2vpn_endpt;
const struct lspping_tlv_targetfec_subtlv_fec_128_pw_old *lspping_tlv_targetfec_subtlv_l2vpn_vcid_old;
const struct lspping_tlv_targetfec_subtlv_fec_128_pw *lspping_tlv_targetfec_subtlv_l2vpn_vcid;
const struct lspping_tlv_targetfec_subtlv_bgp_ipv4_t *lspping_tlv_targetfec_subtlv_bgp_ipv4;
const struct lspping_tlv_targetfec_subtlv_bgp_ipv6_t *lspping_tlv_targetfec_subtlv_bgp_ipv6;
} subtlv_ptr;
ndo->ndo_protocol = "lspping";
tptr=pptr;
lspping_com_header = (const struct lspping_common_header *)pptr;
if (len < sizeof(struct lspping_common_header))
goto tooshort;
ND_TCHECK_SIZE(lspping_com_header);
/*
* Sanity checking of the header.
*/
if (GET_BE_U_2(lspping_com_header->version) != LSPPING_VERSION) {
ND_PRINT("LSP-PING version %u packet not supported",
GET_BE_U_2(lspping_com_header->version));
return;
}
/* in non-verbose mode just lets print the basic Message Type*/
if (ndo->ndo_vflag < 1) {
ND_PRINT("LSP-PINGv%u, %s, seq %u, length: %u",
GET_BE_U_2(lspping_com_header->version),
tok2str(lspping_msg_type_values, "unknown (%u)",GET_U_1(lspping_com_header->msg_type)),
GET_BE_U_4(lspping_com_header->seq_number),
len);
return;
}
/* ok they seem to want to know everything - lets fully decode it */
tlen=len;
ND_PRINT("\n\tLSP-PINGv%u, msg-type: %s (%u), length: %u\n\t reply-mode: %s (%u)",
GET_BE_U_2(lspping_com_header->version),
tok2str(lspping_msg_type_values, "unknown",GET_U_1(lspping_com_header->msg_type)),
GET_U_1(lspping_com_header->msg_type),
len,
tok2str(lspping_reply_mode_values, "unknown",GET_U_1(lspping_com_header->reply_mode)),
GET_U_1(lspping_com_header->reply_mode));
/*
* the following return codes require that the subcode is attached
* at the end of the translated token output
*/
return_code = GET_U_1(lspping_com_header->return_code);
return_subcode = GET_U_1(lspping_com_header->return_subcode);
if (return_code == 3 ||
return_code == 4 ||
return_code == 8 ||
return_code == 10 ||
return_code == 11 ||
return_code == 12 )
ND_PRINT("\n\t Return Code: %s %u (%u)\n\t Return Subcode: (%u)",
tok2str(lspping_return_code_values, "unknown",return_code),
return_subcode,
return_code,
return_subcode);
else
ND_PRINT("\n\t Return Code: %s (%u)\n\t Return Subcode: (%u)",
tok2str(lspping_return_code_values, "unknown",return_code),
return_code,
return_subcode);
ND_PRINT("\n\t Sender Handle: 0x%08x, Sequence: %u",
GET_BE_U_4(lspping_com_header->sender_handle),
GET_BE_U_4(lspping_com_header->seq_number));
ND_PRINT("\n\t Sender Timestamp: ");
p_ntp_time(ndo, &lspping_com_header->ts_sent);
ND_PRINT(" ");
int_part=GET_BE_U_4(lspping_com_header->ts_rcvd.int_part);
fraction=GET_BE_U_4(lspping_com_header->ts_rcvd.fraction);
ND_PRINT("Receiver Timestamp: ");
if (! (int_part == 0 && fraction == 0))
p_ntp_time(ndo, &lspping_com_header->ts_rcvd);
else
ND_PRINT("no timestamp");
tptr+=sizeof(struct lspping_common_header);
tlen-=sizeof(struct lspping_common_header);
while (tlen != 0) {
/* Does the TLV go past the end of the packet? */
if (tlen < sizeof(struct lspping_tlv_header))
goto tooshort;
lspping_tlv_header = (const struct lspping_tlv_header *)tptr;
lspping_tlv_type=GET_BE_U_2(lspping_tlv_header->type);
lspping_tlv_len=GET_BE_U_2(lspping_tlv_header->length);
ND_PRINT("\n\t %s TLV (%u), length: %u",
tok2str(lspping_tlv_values,
"Unknown",
lspping_tlv_type),
lspping_tlv_type,
lspping_tlv_len);
/* some little sanity checking */
if (lspping_tlv_len == 0) {
tptr+=sizeof(struct lspping_tlv_header);
tlen-=sizeof(struct lspping_tlv_header);
continue; /* no value to dissect */
}
tlv_tptr=tptr+sizeof(struct lspping_tlv_header);
tlv_tlen=lspping_tlv_len; /* header not included -> no adjustment */
/* Does the TLV go past the end of the packet? */
if (tlen < lspping_tlv_len+sizeof(struct lspping_tlv_header))
goto tooshort;
/* did we capture enough for fully decoding the tlv ? */
ND_TCHECK_LEN(tlv_tptr, lspping_tlv_len);
tlv_hexdump=FALSE;
switch(lspping_tlv_type) {
case LSPPING_TLV_TARGET_FEC_STACK:
while (tlv_tlen != 0) {
/* Does the subTLV header go past the end of the TLV? */
if (tlv_tlen < sizeof(struct lspping_tlv_header)) {
ND_PRINT("\n\t TLV is too short");
tlv_hexdump = TRUE;
goto tlv_tooshort;
}
subtlv_hexdump=FALSE;
lspping_subtlv_header = (const struct lspping_tlv_header *)tlv_tptr;
lspping_subtlv_type=GET_BE_U_2(lspping_subtlv_header->type);
lspping_subtlv_len=GET_BE_U_2(lspping_subtlv_header->length);
subtlv_tptr=tlv_tptr+sizeof(struct lspping_tlv_header);
/* Does the subTLV go past the end of the TLV? */
if (tlv_tlen < lspping_subtlv_len+sizeof(struct lspping_tlv_header)) {
ND_PRINT("\n\t TLV is too short");
tlv_hexdump = TRUE;
goto tlv_tooshort;
}
/* Did we capture enough for fully decoding the subTLV? */
ND_TCHECK_LEN(subtlv_tptr, lspping_subtlv_len);
ND_PRINT("\n\t %s subTLV (%u), length: %u",
tok2str(lspping_tlvtargetfec_subtlv_values,
"Unknown",
lspping_subtlv_type),
lspping_subtlv_type,
lspping_subtlv_len);
switch(lspping_subtlv_type) {
case LSPPING_TLV_TARGETFEC_SUBTLV_LDP_IPV4:
/* Is the subTLV length correct? */
if (lspping_subtlv_len != 5) {
ND_PRINT("\n\t invalid subTLV length, should be 5");
subtlv_hexdump=TRUE; /* unknown subTLV just hexdump it */
} else {
subtlv_ptr.lspping_tlv_targetfec_subtlv_ldp_ipv4 =
(const struct lspping_tlv_targetfec_subtlv_ldp_ipv4_t *)subtlv_tptr;
ND_PRINT("\n\t %s/%u",
GET_IPADDR_STRING(subtlv_ptr.lspping_tlv_targetfec_subtlv_ldp_ipv4->prefix),
GET_U_1(subtlv_ptr.lspping_tlv_targetfec_subtlv_ldp_ipv4->prefix_len));
}
break;
case LSPPING_TLV_TARGETFEC_SUBTLV_LDP_IPV6:
/* Is the subTLV length correct? */
if (lspping_subtlv_len != 17) {
ND_PRINT("\n\t invalid subTLV length, should be 17");
subtlv_hexdump=TRUE; /* unknown subTLV just hexdump it */
} else {
subtlv_ptr.lspping_tlv_targetfec_subtlv_ldp_ipv6 =
(const struct lspping_tlv_targetfec_subtlv_ldp_ipv6_t *)subtlv_tptr;
ND_PRINT("\n\t %s/%u",
GET_IP6ADDR_STRING(subtlv_ptr.lspping_tlv_targetfec_subtlv_ldp_ipv6->prefix),
GET_U_1(subtlv_ptr.lspping_tlv_targetfec_subtlv_ldp_ipv6->prefix_len));
}
break;
case LSPPING_TLV_TARGETFEC_SUBTLV_BGP_IPV4:
/* Is the subTLV length correct? */
if (lspping_subtlv_len != 5) {
ND_PRINT("\n\t invalid subTLV length, should be 5");
subtlv_hexdump=TRUE; /* unknown subTLV just hexdump it */
} else {
subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv4 =
(const struct lspping_tlv_targetfec_subtlv_bgp_ipv4_t *)subtlv_tptr;
ND_PRINT("\n\t %s/%u",
GET_IPADDR_STRING(subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv4->prefix),
GET_U_1(subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv4->prefix_len));
}
break;
case LSPPING_TLV_TARGETFEC_SUBTLV_BGP_IPV6:
/* Is the subTLV length correct? */
if (lspping_subtlv_len != 17) {
ND_PRINT("\n\t invalid subTLV length, should be 17");
subtlv_hexdump=TRUE; /* unknown subTLV just hexdump it */
} else {
subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv6 =
(const struct lspping_tlv_targetfec_subtlv_bgp_ipv6_t *)subtlv_tptr;
ND_PRINT("\n\t %s/%u",
GET_IP6ADDR_STRING(subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv6->prefix),
GET_U_1(subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv6->prefix_len));
}
break;
case LSPPING_TLV_TARGETFEC_SUBTLV_RSVP_IPV4:
/* Is the subTLV length correct? */
if (lspping_subtlv_len != 20) {
ND_PRINT("\n\t invalid subTLV length, should be 20");
subtlv_hexdump=TRUE; /* unknown subTLV just hexdump it */
} else {
subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv4 =
(const struct lspping_tlv_targetfec_subtlv_rsvp_ipv4_t *)subtlv_tptr;
ND_PRINT("\n\t tunnel end-point %s, tunnel sender %s, lsp-id 0x%04x"
"\n\t tunnel-id 0x%04x, extended tunnel-id %s",
GET_IPADDR_STRING(subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv4->tunnel_endpoint),
GET_IPADDR_STRING(subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv4->tunnel_sender),
GET_BE_U_2(subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv4->lsp_id),
GET_BE_U_2(subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv4->tunnel_id),
GET_IPADDR_STRING(subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv4->extended_tunnel_id));
}
break;
case LSPPING_TLV_TARGETFEC_SUBTLV_RSVP_IPV6:
/* Is the subTLV length correct? */
if (lspping_subtlv_len != 56) {
ND_PRINT("\n\t invalid subTLV length, should be 56");
subtlv_hexdump=TRUE; /* unknown subTLV just hexdump it */
} else {
subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv6 =
(const struct lspping_tlv_targetfec_subtlv_rsvp_ipv6_t *)subtlv_tptr;
ND_PRINT("\n\t tunnel end-point %s, tunnel sender %s, lsp-id 0x%04x"
"\n\t tunnel-id 0x%04x, extended tunnel-id %s",
GET_IP6ADDR_STRING(subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv6->tunnel_endpoint),
GET_IP6ADDR_STRING(subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv6->tunnel_sender),
GET_BE_U_2(subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv6->lsp_id),
GET_BE_U_2(subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv6->tunnel_id),
GET_IP6ADDR_STRING(subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv6->extended_tunnel_id));
}
break;
case LSPPING_TLV_TARGETFEC_SUBTLV_L3VPN_IPV4:
/* Is the subTLV length correct? */
if (lspping_subtlv_len != 13) {
ND_PRINT("\n\t invalid subTLV length, should be 13");
subtlv_hexdump=TRUE; /* unknown subTLV just hexdump it */
} else {
subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv4 =
(const struct lspping_tlv_targetfec_subtlv_l3vpn_ipv4_t *)subtlv_tptr;
ND_PRINT("\n\t RD: %s, %s/%u",
bgp_vpn_rd_print(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv4->rd),
GET_IPADDR_STRING(subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv4->prefix),
GET_U_1(subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv4->prefix_len));
}
break;
case LSPPING_TLV_TARGETFEC_SUBTLV_L3VPN_IPV6:
/* Is the subTLV length correct? */
if (lspping_subtlv_len != 25) {
ND_PRINT("\n\t invalid subTLV length, should be 25");
subtlv_hexdump=TRUE; /* unknown subTLV just hexdump it */
} else {
subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv6 =
(const struct lspping_tlv_targetfec_subtlv_l3vpn_ipv6_t *)subtlv_tptr;
ND_PRINT("\n\t RD: %s, %s/%u",
bgp_vpn_rd_print(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv6->rd),
GET_IP6ADDR_STRING(subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv6->prefix),
GET_U_1(subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv6->prefix_len));
}
break;
case LSPPING_TLV_TARGETFEC_SUBTLV_L2VPN_ENDPT:
/* Is the subTLV length correct? */
if (lspping_subtlv_len != 14) {
ND_PRINT("\n\t invalid subTLV length, should be 14");
subtlv_hexdump=TRUE; /* unknown subTLV just hexdump it */
} else {
subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_endpt =
(const struct lspping_tlv_targetfec_subtlv_l2vpn_endpt_t *)subtlv_tptr;
ND_PRINT("\n\t RD: %s, Sender VE ID: %u, Receiver VE ID: %u"
"\n\t Encapsulation Type: %s (%u)",
bgp_vpn_rd_print(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_endpt->rd),
GET_BE_U_2(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_endpt->sender_ve_id),
GET_BE_U_2(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_endpt->receiver_ve_id),
tok2str(mpls_pw_types_values,
"unknown",
GET_BE_U_2(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_endpt->encapsulation)),
GET_BE_U_2(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_endpt->encapsulation));
}
break;
/* the old L2VPN VCID subTLV does not have support for the sender field */
case LSPPING_TLV_TARGETFEC_SUBTLV_FEC_128_PW_OLD:
/* Is the subTLV length correct? */
if (lspping_subtlv_len != 10) {
ND_PRINT("\n\t invalid subTLV length, should be 10");
subtlv_hexdump=TRUE; /* unknown subTLV just hexdump it */
} else {
subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid_old =
(const struct lspping_tlv_targetfec_subtlv_fec_128_pw_old *)subtlv_tptr;
ND_PRINT("\n\t Remote PE: %s"
"\n\t PW ID: 0x%08x, PW Type: %s (%u)",
GET_IPADDR_STRING(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid_old->remote_pe_address),
GET_BE_U_4(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid_old->pw_id),
tok2str(mpls_pw_types_values,
"unknown",
GET_BE_U_2(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid_old->pw_type)),
GET_BE_U_2(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid_old->pw_type));
}
break;
case LSPPING_TLV_TARGETFEC_SUBTLV_FEC_128_PW:
/* Is the subTLV length correct? */
if (lspping_subtlv_len != 14) {
ND_PRINT("\n\t invalid subTLV length, should be 14");
subtlv_hexdump=TRUE; /* unknown subTLV just hexdump it */
} else {
subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid =
(const struct lspping_tlv_targetfec_subtlv_fec_128_pw *)subtlv_tptr;
ND_PRINT("\n\t Sender PE: %s, Remote PE: %s"
"\n\t PW ID: 0x%08x, PW Type: %s (%u)",
GET_IPADDR_STRING(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid->sender_pe_address),
GET_IPADDR_STRING(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid->remote_pe_address),
GET_BE_U_4(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid->pw_id),
tok2str(mpls_pw_types_values,
"unknown",
GET_BE_U_2(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid->pw_type)),
GET_BE_U_2(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid->pw_type));
}
break;
default:
subtlv_hexdump=TRUE; /* unknown subTLV just hexdump it */
break;
}
/* do we want to see an additionally subtlv hexdump ? */
if (ndo->ndo_vflag > 1 || subtlv_hexdump==TRUE)
print_unknown_data(ndo, tlv_tptr+sizeof(struct lspping_tlv_header),
"\n\t ",
lspping_subtlv_len);
/* All subTLVs are aligned to four octet boundary */
if (lspping_subtlv_len % 4) {
lspping_subtlv_len += 4 - (lspping_subtlv_len % 4);
/* Does the subTLV, including padding, go past the end of the TLV? */
if (tlv_tlen < lspping_subtlv_len+sizeof(struct lspping_tlv_header)) {
ND_PRINT("\n\t\t TLV is too short");
return;
}
}
tlv_tptr+=lspping_subtlv_len;
tlv_tlen-=lspping_subtlv_len+sizeof(struct lspping_tlv_header);
}
break;
case LSPPING_TLV_DOWNSTREAM_MAPPING:
/* Does the header go past the end of the TLV? */
if (tlv_tlen < sizeof(struct lspping_tlv_downstream_map_t)) {
ND_PRINT("\n\t TLV is too short");
tlv_hexdump = TRUE;
goto tlv_tooshort;
}
/* Did we capture enough to get the address family? */
ND_TCHECK_LEN(tlv_tptr,
sizeof(struct lspping_tlv_downstream_map_t));
tlv_ptr.lspping_tlv_downstream_map=
(const struct lspping_tlv_downstream_map_t *)tlv_tptr;
/* that strange thing with the downstream map TLV is that until now
* we do not know if its IPv4 or IPv6 or is unnumbered; after
* we find the address-type, we recast the tlv_tptr and move on. */
address_type = GET_U_1(tlv_ptr.lspping_tlv_downstream_map->address_type);
ND_PRINT("\n\t MTU: %u, Address-Type: %s (%u)",
GET_BE_U_2(tlv_ptr.lspping_tlv_downstream_map->mtu),
tok2str(lspping_tlv_downstream_addr_values,
"unknown",
address_type),
address_type);
switch(address_type) {
case LSPPING_AFI_IPV4:
/* Does the data go past the end of the TLV? */
if (tlv_tlen < sizeof(struct lspping_tlv_downstream_map_ipv4_t)) {
ND_PRINT("\n\t TLV is too short");
tlv_hexdump = TRUE;
goto tlv_tooshort;
}
/* Did we capture enough for this part of the TLV? */
ND_TCHECK_LEN(tlv_tptr,
sizeof(struct lspping_tlv_downstream_map_ipv4_t));
tlv_ptr.lspping_tlv_downstream_map_ipv4=
(const struct lspping_tlv_downstream_map_ipv4_t *)tlv_tptr;
ND_PRINT("\n\t Downstream IP: %s"
"\n\t Downstream Interface IP: %s",
GET_IPADDR_STRING(tlv_ptr.lspping_tlv_downstream_map_ipv4->downstream_ip),
GET_IPADDR_STRING(tlv_ptr.lspping_tlv_downstream_map_ipv4->downstream_interface));
tlv_tptr+=sizeof(struct lspping_tlv_downstream_map_ipv4_t);
tlv_tlen-=sizeof(struct lspping_tlv_downstream_map_ipv4_t);
break;
case LSPPING_AFI_IPV4_UNMB:
/* Does the data go past the end of the TLV? */
if (tlv_tlen < sizeof(struct lspping_tlv_downstream_map_ipv4_unmb_t)) {
ND_PRINT("\n\t TLV is too short");
tlv_hexdump = TRUE;
goto tlv_tooshort;
}
/* Did we capture enough for this part of the TLV? */
ND_TCHECK_LEN(tlv_tptr,
sizeof(struct lspping_tlv_downstream_map_ipv4_unmb_t));
tlv_ptr.lspping_tlv_downstream_map_ipv4_unmb=
(const struct lspping_tlv_downstream_map_ipv4_unmb_t *)tlv_tptr;
ND_PRINT("\n\t Downstream IP: %s"
"\n\t Downstream Interface Index: 0x%08x",
GET_IPADDR_STRING(tlv_ptr.lspping_tlv_downstream_map_ipv4_unmb->downstream_ip),
GET_BE_U_4(tlv_ptr.lspping_tlv_downstream_map_ipv4_unmb->downstream_interface));
tlv_tptr+=sizeof(struct lspping_tlv_downstream_map_ipv4_unmb_t);
tlv_tlen-=sizeof(struct lspping_tlv_downstream_map_ipv4_unmb_t);
break;
case LSPPING_AFI_IPV6:
/* Does the data go past the end of the TLV? */
if (tlv_tlen < sizeof(struct lspping_tlv_downstream_map_ipv6_t)) {
ND_PRINT("\n\t TLV is too short");
tlv_hexdump = TRUE;
goto tlv_tooshort;
}
/* Did we capture enough for this part of the TLV? */
ND_TCHECK_LEN(tlv_tptr,
sizeof(struct lspping_tlv_downstream_map_ipv6_t));
tlv_ptr.lspping_tlv_downstream_map_ipv6=
(const struct lspping_tlv_downstream_map_ipv6_t *)tlv_tptr;
ND_PRINT("\n\t Downstream IP: %s"
"\n\t Downstream Interface IP: %s",
GET_IP6ADDR_STRING(tlv_ptr.lspping_tlv_downstream_map_ipv6->downstream_ip),
GET_IP6ADDR_STRING(tlv_ptr.lspping_tlv_downstream_map_ipv6->downstream_interface));
tlv_tptr+=sizeof(struct lspping_tlv_downstream_map_ipv6_t);
tlv_tlen-=sizeof(struct lspping_tlv_downstream_map_ipv6_t);
break;
case LSPPING_AFI_IPV6_UNMB:
/* Does the data go past the end of the TLV? */
if (tlv_tlen < sizeof(struct lspping_tlv_downstream_map_ipv6_unmb_t)) {
ND_PRINT("\n\t TLV is too short");
tlv_hexdump = TRUE;
goto tlv_tooshort;
}
/* Did we capture enough for this part of the TLV? */
ND_TCHECK_LEN(tlv_tptr,
sizeof(struct lspping_tlv_downstream_map_ipv6_unmb_t));
tlv_ptr.lspping_tlv_downstream_map_ipv6_unmb=
(const struct lspping_tlv_downstream_map_ipv6_unmb_t *)tlv_tptr;
ND_PRINT("\n\t Downstream IP: %s"
"\n\t Downstream Interface Index: 0x%08x",
GET_IP6ADDR_STRING(tlv_ptr.lspping_tlv_downstream_map_ipv6_unmb->downstream_ip),
GET_BE_U_4(tlv_ptr.lspping_tlv_downstream_map_ipv6_unmb->downstream_interface));
tlv_tptr+=sizeof(struct lspping_tlv_downstream_map_ipv6_unmb_t);
tlv_tlen-=sizeof(struct lspping_tlv_downstream_map_ipv6_unmb_t);
break;
default:
/* should not happen ! - no error message - tok2str() has barked already */
break;
}
/* Does the data go past the end of the TLV? */
if (tlv_tlen < sizeof(struct lspping_tlv_downstream_map_info_t)) {
ND_PRINT("\n\t TLV is too short");
tlv_hexdump = TRUE;
goto tlv_tooshort;
}
/* Did we capture enough for this part of the TLV? */
ND_TCHECK_LEN(tlv_tptr,
sizeof(struct lspping_tlv_downstream_map_info_t));
tlv_ptr.lspping_tlv_downstream_map_info=
(const struct lspping_tlv_downstream_map_info_t *)tlv_tptr;
/* FIXME add hash-key type, depth limit, multipath processing */
/* FIXME print downstream labels */
tlv_hexdump=TRUE; /* dump the TLV until code complete */
break;
case LSPPING_TLV_BFD_DISCRIMINATOR:
if (tlv_tlen < LSPPING_TLV_BFD_DISCRIMINATOR_LEN) {
ND_PRINT("\n\t TLV is too short");
tlv_hexdump = TRUE;
goto tlv_tooshort;
} else {
ND_PRINT("\n\t BFD Discriminator 0x%08x", GET_BE_U_4(tlv_tptr));
}
break;
case LSPPING_TLV_VENDOR_ENTERPRISE:
{
uint32_t vendor_id;
if (tlv_tlen < LSPPING_TLV_VENDOR_ENTERPRISE_LEN) {
ND_PRINT("\n\t TLV is too short");
tlv_hexdump = TRUE;
goto tlv_tooshort;
} else {
vendor_id = GET_BE_U_4(tlv_tptr);
ND_PRINT("\n\t Vendor: %s (0x%04x)",
tok2str(smi_values, "Unknown", vendor_id),
vendor_id);
}
}
break;
/*
* FIXME those are the defined TLVs that lack a decoder
* you are welcome to contribute code ;-)
*/
case LSPPING_TLV_PAD:
case LSPPING_TLV_ERROR_CODE:
case LSPPING_TLV_VENDOR_PRIVATE:
default:
if (ndo->ndo_vflag <= 1)
print_unknown_data(ndo, tlv_tptr, "\n\t ", tlv_tlen);
break;
}
/* do we want to see an additionally tlv hexdump ? */
tlv_tooshort:
if (ndo->ndo_vflag > 1 || tlv_hexdump==TRUE)
print_unknown_data(ndo, tptr+sizeof(struct lspping_tlv_header), "\n\t ",
lspping_tlv_len);
/* All TLVs are aligned to four octet boundary */
if (lspping_tlv_len % 4) {
lspping_tlv_len += (4 - lspping_tlv_len % 4);
/* Does the TLV, including padding, go past the end of the packet? */
if (tlen < lspping_tlv_len+sizeof(struct lspping_tlv_header))
goto tooshort;
}
tptr+=lspping_tlv_len+sizeof(struct lspping_tlv_header);
tlen-=lspping_tlv_len+sizeof(struct lspping_tlv_header);
}
return;
tooshort:
ND_PRINT("\n\t\t packet is too short");
}
diff --git a/contrib/tcpdump/print-lwapp.c b/contrib/tcpdump/print-lwapp.c
index 10a2e0bed043..7cee32e02735 100644
--- a/contrib/tcpdump/print-lwapp.c
+++ b/contrib/tcpdump/print-lwapp.c
@@ -1,367 +1,365 @@
/*
* Copyright (c) 1998-2007 The TCPDUMP project
*
* 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.
*
* Original code by Carles Kishimoto <carles.kishimoto@gmail.com>
*/
/* \summary: Light Weight Access Point Protocol (LWAPP) printer */
/* specification: RFC 5412 */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "extract.h"
#include "addrtoname.h"
/*
* LWAPP transport (common) header
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |VER| RID |C|F|L| Frag ID | Length |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Status/WLANs | Payload... |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*/
struct lwapp_transport_header {
nd_uint8_t version;
nd_uint8_t frag_id;
nd_uint16_t length;
nd_uint16_t status;
};
/*
* LWAPP control header
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Message Type | Seq Num | Msg Element Length |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Session ID |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Msg Element [0..N] |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct lwapp_control_header {
nd_uint8_t msg_type;
nd_uint8_t seq_num;
nd_uint16_t len;
nd_uint32_t session_id;
};
#define LWAPP_VERSION 0
#define LWAPP_EXTRACT_VERSION(x) (((x)&0xC0)>>6)
#define LWAPP_EXTRACT_RID(x) (((x)&0x38)>>3)
#define LWAPP_EXTRACT_CONTROL_BIT(x) (((x)&0x04)>>2)
static const struct tok lwapp_header_bits_values[] = {
{ 0x01, "Last Fragment Bit"},
{ 0x02, "Fragment Bit"},
{ 0x04, "Control Bit"},
{ 0, NULL}
};
#define LWAPP_MSGTYPE_DISCOVERY_REQUEST 1
#define LWAPP_MSGTYPE_DISCOVERY_RESPONSE 2
#define LWAPP_MSGTYPE_JOIN_REQUEST 3
#define LWAPP_MSGTYPE_JOIN_RESPONSE 4
#define LWAPP_MSGTYPE_JOIN_ACK 5
#define LWAPP_MSGTYPE_JOIN_CONFIRM 6
#define LWAPP_MSGTYPE_CONFIGURE_REQUEST 10
#define LWAPP_MSGTYPE_CONFIGURE_RESPONSE 11
#define LWAPP_MSGTYPE_CONF_UPDATE_REQUEST 12
#define LWAPP_MSGTYPE_CONF_UPDATE_RESPONSE 13
#define LWAPP_MSGTYPE_WTP_EVENT_REQUEST 14
#define LWAPP_MSGTYPE_WTP_EVENT_RESPONSE 15
#define LWAPP_MSGTYPE_CHANGE_STATE_EVENT_REQUEST 16
#define LWAPP_MSGTYPE_CHANGE_STATE_EVENT_RESPONSE 17
#define LWAPP_MSGTYPE_ECHO_REQUEST 22
#define LWAPP_MSGTYPE_ECHO_RESPONSE 23
#define LWAPP_MSGTYPE_IMAGE_DATA_REQUEST 24
#define LWAPP_MSGTYPE_IMAGE_DATA_RESPONSE 25
#define LWAPP_MSGTYPE_RESET_REQUEST 26
#define LWAPP_MSGTYPE_RESET_RESPONSE 27
#define LWAPP_MSGTYPE_KEY_UPDATE_REQUEST 30
#define LWAPP_MSGTYPE_KEY_UPDATE_RESPONSE 31
#define LWAPP_MSGTYPE_PRIMARY_DISCOVERY_REQUEST 32
#define LWAPP_MSGTYPE_PRIMARY_DISCOVERY_RESPONSE 33
#define LWAPP_MSGTYPE_DATA_TRANSFER_REQUEST 34
#define LWAPP_MSGTYPE_DATA_TRANSFER_RESPONSE 35
#define LWAPP_MSGTYPE_CLEAR_CONFIG_INDICATION 36
#define LWAPP_MSGTYPE_WLAN_CONFIG_REQUEST 37
#define LWAPP_MSGTYPE_WLAN_CONFIG_RESPONSE 38
#define LWAPP_MSGTYPE_MOBILE_CONFIG_REQUEST 39
#define LWAPP_MSGTYPE_MOBILE_CONFIG_RESPONSE 40
static const struct tok lwapp_msg_type_values[] = {
{ LWAPP_MSGTYPE_DISCOVERY_REQUEST, "Discovery req"},
{ LWAPP_MSGTYPE_DISCOVERY_RESPONSE, "Discovery resp"},
{ LWAPP_MSGTYPE_JOIN_REQUEST, "Join req"},
{ LWAPP_MSGTYPE_JOIN_RESPONSE, "Join resp"},
{ LWAPP_MSGTYPE_JOIN_ACK, "Join ack"},
{ LWAPP_MSGTYPE_JOIN_CONFIRM, "Join confirm"},
{ LWAPP_MSGTYPE_CONFIGURE_REQUEST, "Configure req"},
{ LWAPP_MSGTYPE_CONFIGURE_RESPONSE, "Configure resp"},
{ LWAPP_MSGTYPE_CONF_UPDATE_REQUEST, "Update req"},
{ LWAPP_MSGTYPE_CONF_UPDATE_RESPONSE, "Update resp"},
{ LWAPP_MSGTYPE_WTP_EVENT_REQUEST, "WTP event req"},
{ LWAPP_MSGTYPE_WTP_EVENT_RESPONSE, "WTP event resp"},
{ LWAPP_MSGTYPE_CHANGE_STATE_EVENT_REQUEST, "Change state event req"},
{ LWAPP_MSGTYPE_CHANGE_STATE_EVENT_RESPONSE, "Change state event resp"},
{ LWAPP_MSGTYPE_ECHO_REQUEST, "Echo req"},
{ LWAPP_MSGTYPE_ECHO_RESPONSE, "Echo resp"},
{ LWAPP_MSGTYPE_IMAGE_DATA_REQUEST, "Image data req"},
{ LWAPP_MSGTYPE_IMAGE_DATA_RESPONSE, "Image data resp"},
{ LWAPP_MSGTYPE_RESET_REQUEST, "Channel status req"},
{ LWAPP_MSGTYPE_RESET_RESPONSE, "Channel status resp"},
{ LWAPP_MSGTYPE_KEY_UPDATE_REQUEST, "Key update req"},
{ LWAPP_MSGTYPE_KEY_UPDATE_RESPONSE, "Key update resp"},
{ LWAPP_MSGTYPE_PRIMARY_DISCOVERY_REQUEST, "Primary discovery req"},
{ LWAPP_MSGTYPE_PRIMARY_DISCOVERY_RESPONSE, "Primary discovery resp"},
{ LWAPP_MSGTYPE_DATA_TRANSFER_REQUEST, "Data transfer req"},
{ LWAPP_MSGTYPE_DATA_TRANSFER_RESPONSE, "Data transfer resp"},
{ LWAPP_MSGTYPE_CLEAR_CONFIG_INDICATION, "Clear config ind"},
{ LWAPP_MSGTYPE_WLAN_CONFIG_REQUEST, "Wlan config req"},
{ LWAPP_MSGTYPE_WLAN_CONFIG_RESPONSE, "Wlan config resp"},
{ LWAPP_MSGTYPE_MOBILE_CONFIG_REQUEST, "Mobile config req"},
{ LWAPP_MSGTYPE_MOBILE_CONFIG_RESPONSE, "Mobile config resp"},
{ 0, NULL}
};
/*
* LWAPP message elements
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Type | Length | Value ... |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct lwapp_message_header {
nd_uint8_t type;
nd_uint16_t length;
};
void
lwapp_control_print(netdissect_options *ndo,
const u_char *pptr, u_int len, int has_ap_ident)
{
const struct lwapp_transport_header *lwapp_trans_header;
const struct lwapp_control_header *lwapp_control_header;
const u_char *tptr;
uint8_t version;
u_int tlen;
u_int msg_type, msg_tlen;
ndo->ndo_protocol = "lwapp_control";
tptr=pptr;
if (has_ap_ident) {
/* check if enough bytes for AP identity */
ND_TCHECK_6(tptr);
lwapp_trans_header = (const struct lwapp_transport_header *)(pptr+6);
} else {
lwapp_trans_header = (const struct lwapp_transport_header *)pptr;
}
ND_TCHECK_SIZE(lwapp_trans_header);
version = GET_U_1(lwapp_trans_header->version);
/*
* Sanity checking of the header.
*/
if (LWAPP_EXTRACT_VERSION(version) != LWAPP_VERSION) {
ND_PRINT("LWAPP version %u packet not supported",
LWAPP_EXTRACT_VERSION(version));
return;
}
/* non-verbose */
if (ndo->ndo_vflag < 1) {
ND_PRINT("LWAPPv%u, %s frame, Flags [%s], length %u",
LWAPP_EXTRACT_VERSION(version),
LWAPP_EXTRACT_CONTROL_BIT(version) ? "Control" : "Data",
bittok2str(lwapp_header_bits_values,"none",version&0x07),
len);
return;
}
/* ok they seem to want to know everything - lets fully decode it */
tlen=GET_BE_U_2(lwapp_trans_header->length);
ND_PRINT("LWAPPv%u, %s frame, Radio-id %u, Flags [%s], Frag-id %u, length %u",
LWAPP_EXTRACT_VERSION(version),
LWAPP_EXTRACT_CONTROL_BIT(version) ? "Control" : "Data",
LWAPP_EXTRACT_RID(version),
bittok2str(lwapp_header_bits_values,"none",version&0x07),
GET_U_1(lwapp_trans_header->frag_id),
tlen);
if (has_ap_ident) {
ND_PRINT("\n\tAP identity: %s", GET_ETHERADDR_STRING(tptr));
tptr+=sizeof(struct lwapp_transport_header)+6;
} else {
tptr+=sizeof(struct lwapp_transport_header);
}
while(tlen!=0) {
/* did we capture enough for fully decoding the object header ? */
ND_TCHECK_LEN(tptr, sizeof(struct lwapp_control_header));
if (tlen < sizeof(struct lwapp_control_header)) {
ND_PRINT("\n\t Msg goes past end of PDU");
break;
}
lwapp_control_header = (const struct lwapp_control_header *)tptr;
msg_tlen = GET_BE_U_2(lwapp_control_header->len);
if (tlen < sizeof(struct lwapp_control_header) + msg_tlen) {
ND_PRINT("\n\t Msg goes past end of PDU");
break;
}
/* print message header */
msg_type = GET_U_1(lwapp_control_header->msg_type);
ND_PRINT("\n\t Msg type: %s (%u), Seqnum: %u, Msg len: %u, Session: 0x%08x",
tok2str(lwapp_msg_type_values,"Unknown",msg_type),
msg_type,
GET_U_1(lwapp_control_header->seq_num),
msg_tlen,
GET_BE_U_4(lwapp_control_header->session_id));
/* did we capture enough for fully decoding the message */
ND_TCHECK_LEN(tptr, msg_tlen);
/* XXX - Decode sub messages for each message */
switch(msg_type) {
case LWAPP_MSGTYPE_DISCOVERY_REQUEST:
case LWAPP_MSGTYPE_DISCOVERY_RESPONSE:
case LWAPP_MSGTYPE_JOIN_REQUEST:
case LWAPP_MSGTYPE_JOIN_RESPONSE:
case LWAPP_MSGTYPE_JOIN_ACK:
case LWAPP_MSGTYPE_JOIN_CONFIRM:
case LWAPP_MSGTYPE_CONFIGURE_REQUEST:
case LWAPP_MSGTYPE_CONFIGURE_RESPONSE:
case LWAPP_MSGTYPE_CONF_UPDATE_REQUEST:
case LWAPP_MSGTYPE_CONF_UPDATE_RESPONSE:
case LWAPP_MSGTYPE_WTP_EVENT_REQUEST:
case LWAPP_MSGTYPE_WTP_EVENT_RESPONSE:
case LWAPP_MSGTYPE_CHANGE_STATE_EVENT_REQUEST:
case LWAPP_MSGTYPE_CHANGE_STATE_EVENT_RESPONSE:
case LWAPP_MSGTYPE_ECHO_REQUEST:
case LWAPP_MSGTYPE_ECHO_RESPONSE:
case LWAPP_MSGTYPE_IMAGE_DATA_REQUEST:
case LWAPP_MSGTYPE_IMAGE_DATA_RESPONSE:
case LWAPP_MSGTYPE_RESET_REQUEST:
case LWAPP_MSGTYPE_RESET_RESPONSE:
case LWAPP_MSGTYPE_KEY_UPDATE_REQUEST:
case LWAPP_MSGTYPE_KEY_UPDATE_RESPONSE:
case LWAPP_MSGTYPE_PRIMARY_DISCOVERY_REQUEST:
case LWAPP_MSGTYPE_PRIMARY_DISCOVERY_RESPONSE:
case LWAPP_MSGTYPE_DATA_TRANSFER_REQUEST:
case LWAPP_MSGTYPE_DATA_TRANSFER_RESPONSE:
case LWAPP_MSGTYPE_CLEAR_CONFIG_INDICATION:
case LWAPP_MSGTYPE_WLAN_CONFIG_REQUEST:
case LWAPP_MSGTYPE_WLAN_CONFIG_RESPONSE:
case LWAPP_MSGTYPE_MOBILE_CONFIG_REQUEST:
case LWAPP_MSGTYPE_MOBILE_CONFIG_RESPONSE:
default:
break;
}
tptr += sizeof(struct lwapp_control_header) + msg_tlen;
tlen -= sizeof(struct lwapp_control_header) + msg_tlen;
}
return;
trunc:
nd_print_trunc(ndo);
}
void
lwapp_data_print(netdissect_options *ndo,
const u_char *pptr, u_int len)
{
const struct lwapp_transport_header *lwapp_trans_header;
const u_char *tptr;
u_int tlen;
u_int version;
ndo->ndo_protocol = "lwapp_data";
tptr=pptr;
/* check if enough bytes for AP identity */
ND_TCHECK_6(tptr);
lwapp_trans_header = (const struct lwapp_transport_header *)pptr;
ND_TCHECK_SIZE(lwapp_trans_header);
version = GET_U_1(lwapp_trans_header->version);
/*
* Sanity checking of the header.
*/
if (LWAPP_EXTRACT_VERSION(version) != LWAPP_VERSION) {
ND_PRINT("LWAPP version %u packet not supported",
LWAPP_EXTRACT_VERSION(version));
return;
}
/* non-verbose */
if (ndo->ndo_vflag < 1) {
ND_PRINT("LWAPPv%u, %s frame, Flags [%s], length %u",
LWAPP_EXTRACT_VERSION(version),
LWAPP_EXTRACT_CONTROL_BIT(version) ? "Control" : "Data",
bittok2str(lwapp_header_bits_values,"none",version&0x07),
len);
return;
}
/* ok they seem to want to know everything - lets fully decode it */
tlen=GET_BE_U_2(lwapp_trans_header->length);
if (tlen < sizeof(struct lwapp_transport_header)) {
ND_PRINT("LWAPPv%u, %s frame, Radio-id %u, Flags [%s], length %u < transport header length",
LWAPP_EXTRACT_VERSION(version),
LWAPP_EXTRACT_CONTROL_BIT(version) ? "Control" : "Data",
LWAPP_EXTRACT_RID(version),
bittok2str(lwapp_header_bits_values,"none",version&0x07),
tlen);
return;
}
ND_PRINT("LWAPPv%u, %s frame, Radio-id %u, Flags [%s], Frag-id %u, length %u",
LWAPP_EXTRACT_VERSION(version),
LWAPP_EXTRACT_CONTROL_BIT(version) ? "Control" : "Data",
LWAPP_EXTRACT_RID(version),
bittok2str(lwapp_header_bits_values,"none",version&0x07),
GET_U_1(lwapp_trans_header->frag_id),
tlen);
tptr+=sizeof(struct lwapp_transport_header);
tlen-=sizeof(struct lwapp_transport_header);
/* FIX - An IEEE 802.11 frame follows - hexdump for now */
print_unknown_data(ndo, tptr, "\n\t", tlen);
return;
trunc:
nd_print_trunc(ndo);
}
diff --git a/contrib/tcpdump/print-lwres.c b/contrib/tcpdump/print-lwres.c
index 97f176cb3005..4e4ae6d6becf 100644
--- a/contrib/tcpdump/print-lwres.c
+++ b/contrib/tcpdump/print-lwres.c
@@ -1,555 +1,555 @@
/*
* Copyright (C) 2001 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* \summary: BIND9 Lightweight Resolver protocol printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#include "nameser.h"
/* BIND9 lib/lwres/include/lwres */
/*
* Use nd_uint16_t for lwres_uint16_t
* Use nd_uint32_t for lwres_uint32_t
*/
struct lwres_lwpacket {
nd_uint32_t length;
nd_uint16_t version;
nd_uint16_t pktflags;
nd_uint32_t serial;
nd_uint32_t opcode;
nd_uint32_t result;
nd_uint32_t recvlength;
nd_uint16_t authtype;
nd_uint16_t authlength;
};
#define LWRES_LWPACKETFLAG_RESPONSE 0x0001U /* if set, pkt is a response */
#define LWRES_LWPACKETVERSION_0 0
#define LWRES_FLAG_TRUSTNOTREQUIRED 0x00000001U
#define LWRES_FLAG_SECUREDATA 0x00000002U
/*
* no-op
*/
#define LWRES_OPCODE_NOOP 0x00000000U
typedef struct {
/* public */
nd_uint16_t datalength;
/* data follows */
} lwres_nooprequest_t;
typedef struct {
/* public */
nd_uint16_t datalength;
/* data follows */
} lwres_noopresponse_t;
/*
* get addresses by name
*/
#define LWRES_OPCODE_GETADDRSBYNAME 0x00010001U
typedef struct lwres_addr lwres_addr_t;
struct lwres_addr {
nd_uint32_t family;
nd_uint16_t length;
/* address follows */
};
#define LWRES_ADDR_LEN 6
typedef struct {
/* public */
nd_uint32_t flags;
nd_uint32_t addrtypes;
nd_uint16_t namelen;
/* name follows */
} lwres_gabnrequest_t;
#define LWRES_GABNREQUEST_LEN 10
typedef struct {
/* public */
nd_uint32_t flags;
nd_uint16_t naliases;
nd_uint16_t naddrs;
nd_uint16_t realnamelen;
/* aliases follows */
/* addrs follows */
/* realname follows */
} lwres_gabnresponse_t;
#define LWRES_GABNRESPONSE_LEN 10
/*
* get name by address
*/
#define LWRES_OPCODE_GETNAMEBYADDR 0x00010002U
typedef struct {
/* public */
nd_uint32_t flags;
/* addr follows */
} lwres_gnbarequest_t;
#define LWRES_GNBAREQUEST_LEN 4
typedef struct {
/* public */
nd_uint32_t flags;
nd_uint16_t naliases;
nd_uint16_t realnamelen;
/* aliases follows */
/* realname follows */
} lwres_gnbaresponse_t;
#define LWRES_GNBARESPONSE_LEN 8
/*
* get rdata by name
*/
#define LWRES_OPCODE_GETRDATABYNAME 0x00010003U
typedef struct {
/* public */
nd_uint32_t flags;
nd_uint16_t rdclass;
nd_uint16_t rdtype;
nd_uint16_t namelen;
/* name follows */
} lwres_grbnrequest_t;
#define LWRES_GRBNREQUEST_LEN 10
typedef struct {
/* public */
nd_uint32_t flags;
nd_uint16_t rdclass;
nd_uint16_t rdtype;
nd_uint32_t ttl;
nd_uint16_t nrdatas;
nd_uint16_t nsigs;
/* realname here (len + name) */
/* rdata here (len + name) */
/* signatures here (len + name) */
} lwres_grbnresponse_t;
#define LWRES_GRBNRESPONSE_LEN 16
#define LWRDATA_VALIDATED 0x00000001
#define LWRES_ADDRTYPE_V4 0x00000001U /* ipv4 */
#define LWRES_ADDRTYPE_V6 0x00000002U /* ipv6 */
#define LWRES_MAX_ALIASES 16 /* max # of aliases */
#define LWRES_MAX_ADDRS 64 /* max # of addrs */
static const struct tok opcode[] = {
{ LWRES_OPCODE_NOOP, "noop", },
{ LWRES_OPCODE_GETADDRSBYNAME, "getaddrsbyname", },
{ LWRES_OPCODE_GETNAMEBYADDR, "getnamebyaddr", },
{ LWRES_OPCODE_GETRDATABYNAME, "getrdatabyname", },
{ 0, NULL, },
};
/* print-domain.c */
extern const struct tok ns_type2str[];
extern const struct tok ns_class2str[];
static unsigned
lwres_printname(netdissect_options *ndo,
u_int l, const u_char *p0)
{
ND_PRINT(" ");
(void)nd_printn(ndo, p0, l, NULL);
p0 += l;
if (GET_U_1(p0))
ND_PRINT(" (not NUL-terminated!)");
return l + 1;
}
static unsigned
lwres_printnamelen(netdissect_options *ndo,
const u_char *p)
{
uint16_t l;
int advance;
l = GET_BE_U_2(p);
advance = lwres_printname(ndo, l, p + 2);
return 2 + advance;
}
static unsigned
lwres_printbinlen(netdissect_options *ndo,
const u_char *p0)
{
const u_char *p;
uint16_t l;
int i;
p = p0;
l = GET_BE_U_2(p);
p += 2;
for (i = 0; i < l; i++) {
ND_PRINT("%02x", GET_U_1(p));
p++;
}
return 2 + l;
}
static int
lwres_printaddr(netdissect_options *ndo,
const u_char *p0)
{
const u_char *p;
const lwres_addr_t *ap;
uint16_t l;
int i;
p = p0;
ap = (const lwres_addr_t *)p;
l = GET_BE_U_2(ap->length);
p += LWRES_ADDR_LEN;
ND_TCHECK_LEN(p, l);
switch (GET_BE_U_4(ap->family)) {
case 1: /* IPv4 */
if (l < 4)
return -1;
ND_PRINT(" %s", GET_IPADDR_STRING(p));
p += sizeof(nd_ipv4);
break;
case 2: /* IPv6 */
if (l < 16)
return -1;
ND_PRINT(" %s", GET_IP6ADDR_STRING(p));
p += sizeof(nd_ipv6);
break;
default:
ND_PRINT(" %u/", GET_BE_U_4(ap->family));
for (i = 0; i < l; i++) {
ND_PRINT("%02x", GET_U_1(p));
p++;
}
}
- return ND_BYTES_BETWEEN(p, p0);
+ return ND_BYTES_BETWEEN(p0, p);
}
void
lwres_print(netdissect_options *ndo,
const u_char *bp, u_int length)
{
const u_char *p;
const struct lwres_lwpacket *np;
uint32_t v;
const u_char *s;
int response;
int advance;
int unsupported = 0;
ndo->ndo_protocol = "lwres";
np = (const struct lwres_lwpacket *)bp;
ND_TCHECK_2(np->authlength);
ND_PRINT(" lwres");
v = GET_BE_U_2(np->version);
if (ndo->ndo_vflag || v != LWRES_LWPACKETVERSION_0)
ND_PRINT(" v%u", v);
if (v != LWRES_LWPACKETVERSION_0) {
- s = bp + GET_BE_U_4(np->length);
+ uint32_t pkt_len = GET_BE_U_4(np->length);
+ ND_TCHECK_LEN(bp, pkt_len);
+ s = bp + pkt_len;
goto tail;
}
response = GET_BE_U_2(np->pktflags) & LWRES_LWPACKETFLAG_RESPONSE;
/* opcode and pktflags */
v = GET_BE_U_4(np->opcode);
ND_PRINT(" %s%s", tok2str(opcode, "#0x%x", v), response ? "" : "?");
/* pktflags */
v = GET_BE_U_2(np->pktflags);
if (v & ~LWRES_LWPACKETFLAG_RESPONSE)
ND_PRINT("[0x%x]", v);
if (ndo->ndo_vflag > 1) {
ND_PRINT(" ("); /*)*/
ND_PRINT("serial:0x%x", GET_BE_U_4(np->serial));
ND_PRINT(" result:0x%x", GET_BE_U_4(np->result));
ND_PRINT(" recvlen:%u", GET_BE_U_4(np->recvlength));
/* BIND910: not used */
if (ndo->ndo_vflag > 2) {
ND_PRINT(" authtype:0x%x", GET_BE_U_2(np->authtype));
ND_PRINT(" authlen:%u", GET_BE_U_2(np->authlength));
}
/*(*/
ND_PRINT(")");
}
/* per-opcode content */
if (!response) {
/*
* queries
*/
const lwres_gabnrequest_t *gabn;
const lwres_gnbarequest_t *gnba;
const lwres_grbnrequest_t *grbn;
uint32_t l;
gabn = NULL;
gnba = NULL;
grbn = NULL;
p = (const u_char *)(np + 1);
switch (GET_BE_U_4(np->opcode)) {
case LWRES_OPCODE_NOOP:
s = p;
break;
case LWRES_OPCODE_GETADDRSBYNAME:
gabn = (const lwres_gabnrequest_t *)p;
ND_TCHECK_2(gabn->namelen);
/* BIND910: not used */
if (ndo->ndo_vflag > 2) {
ND_PRINT(" flags:0x%x",
GET_BE_U_4(gabn->flags));
}
v = GET_BE_U_4(gabn->addrtypes);
switch (v & (LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6)) {
case LWRES_ADDRTYPE_V4:
ND_PRINT(" IPv4");
break;
case LWRES_ADDRTYPE_V6:
ND_PRINT(" IPv6");
break;
case LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6:
ND_PRINT(" IPv4/6");
break;
}
if (v & ~(LWRES_ADDRTYPE_V4 | LWRES_ADDRTYPE_V6))
ND_PRINT("[0x%x]", v);
s = p + LWRES_GABNREQUEST_LEN;
l = GET_BE_U_2(gabn->namelen);
advance = lwres_printname(ndo, l, s);
s += advance;
break;
case LWRES_OPCODE_GETNAMEBYADDR:
gnba = (const lwres_gnbarequest_t *)p;
ND_TCHECK_4(gnba->flags);
/* BIND910: not used */
if (ndo->ndo_vflag > 2) {
ND_PRINT(" flags:0x%x",
GET_BE_U_4(gnba->flags));
}
s = p + LWRES_GNBAREQUEST_LEN;
advance = lwres_printaddr(ndo, s);
if (advance < 0)
goto invalid;
s += advance;
break;
case LWRES_OPCODE_GETRDATABYNAME:
/* XXX no trace, not tested */
grbn = (const lwres_grbnrequest_t *)p;
ND_TCHECK_2(grbn->namelen);
/* BIND910: not used */
if (ndo->ndo_vflag > 2) {
ND_PRINT(" flags:0x%x",
GET_BE_U_4(grbn->flags));
}
ND_PRINT(" %s", tok2str(ns_type2str, "Type%u",
GET_BE_U_2(grbn->rdtype)));
if (GET_BE_U_2(grbn->rdclass) != C_IN) {
ND_PRINT(" %s", tok2str(ns_class2str, "Class%u",
GET_BE_U_2(grbn->rdclass)));
}
s = p + LWRES_GRBNREQUEST_LEN;
l = GET_BE_U_2(grbn->namelen);
advance = lwres_printname(ndo, l, s);
s += advance;
break;
default:
s = p;
unsupported++;
break;
}
} else {
/*
* responses
*/
const lwres_gabnresponse_t *gabn;
const lwres_gnbaresponse_t *gnba;
const lwres_grbnresponse_t *grbn;
uint32_t l, na;
uint32_t i;
gabn = NULL;
gnba = NULL;
grbn = NULL;
p = (const u_char *)(np + 1);
switch (GET_BE_U_4(np->opcode)) {
case LWRES_OPCODE_NOOP:
s = p;
break;
case LWRES_OPCODE_GETADDRSBYNAME:
gabn = (const lwres_gabnresponse_t *)p;
ND_TCHECK_2(gabn->realnamelen);
/* BIND910: not used */
if (ndo->ndo_vflag > 2) {
ND_PRINT(" flags:0x%x",
GET_BE_U_4(gabn->flags));
}
ND_PRINT(" %u/%u", GET_BE_U_2(gabn->naliases),
GET_BE_U_2(gabn->naddrs));
s = p + LWRES_GABNRESPONSE_LEN;
l = GET_BE_U_2(gabn->realnamelen);
advance = lwres_printname(ndo, l, s);
s += advance;
/* aliases */
na = GET_BE_U_2(gabn->naliases);
for (i = 0; i < na; i++) {
advance = lwres_printnamelen(ndo, s);
s += advance;
}
/* addrs */
na = GET_BE_U_2(gabn->naddrs);
for (i = 0; i < na; i++) {
advance = lwres_printaddr(ndo, s);
if (advance < 0)
goto invalid;
s += advance;
}
break;
case LWRES_OPCODE_GETNAMEBYADDR:
gnba = (const lwres_gnbaresponse_t *)p;
ND_TCHECK_2(gnba->realnamelen);
/* BIND910: not used */
if (ndo->ndo_vflag > 2) {
ND_PRINT(" flags:0x%x",
GET_BE_U_4(gnba->flags));
}
ND_PRINT(" %u", GET_BE_U_2(gnba->naliases));
s = p + LWRES_GNBARESPONSE_LEN;
l = GET_BE_U_2(gnba->realnamelen);
advance = lwres_printname(ndo, l, s);
s += advance;
/* aliases */
na = GET_BE_U_2(gnba->naliases);
for (i = 0; i < na; i++) {
advance = lwres_printnamelen(ndo, s);
s += advance;
}
break;
case LWRES_OPCODE_GETRDATABYNAME:
/* XXX no trace, not tested */
grbn = (const lwres_grbnresponse_t *)p;
ND_TCHECK_2(grbn->nsigs);
/* BIND910: not used */
if (ndo->ndo_vflag > 2) {
ND_PRINT(" flags:0x%x",
GET_BE_U_4(grbn->flags));
}
ND_PRINT(" %s", tok2str(ns_type2str, "Type%u",
GET_BE_U_2(grbn->rdtype)));
if (GET_BE_U_2(grbn->rdclass) != C_IN) {
ND_PRINT(" %s", tok2str(ns_class2str, "Class%u",
GET_BE_U_2(grbn->rdclass)));
}
ND_PRINT(" TTL ");
unsigned_relts_print(ndo,
GET_BE_U_4(grbn->ttl));
ND_PRINT(" %u/%u", GET_BE_U_2(grbn->nrdatas),
GET_BE_U_2(grbn->nsigs));
s = p + LWRES_GRBNRESPONSE_LEN;
advance = lwres_printnamelen(ndo, s);
s += advance;
/* rdatas */
na = GET_BE_U_2(grbn->nrdatas);
for (i = 0; i < na; i++) {
/* XXX should decode resource data */
advance = lwres_printbinlen(ndo, s);
s += advance;
}
/* sigs */
na = GET_BE_U_2(grbn->nsigs);
for (i = 0; i < na; i++) {
/* XXX how should we print it? */
advance = lwres_printbinlen(ndo, s);
s += advance;
}
break;
default:
s = p;
unsupported++;
break;
}
}
tail:
/* length mismatch */
if (GET_BE_U_4(np->length) != length) {
ND_PRINT(" [len: %u != %u]", GET_BE_U_4(np->length),
length);
}
- if (!unsupported && ND_BYTES_BETWEEN(s, bp) < GET_BE_U_4(np->length))
+ if (!unsupported && ND_BYTES_BETWEEN(bp, s) < GET_BE_U_4(np->length))
ND_PRINT("[extra]");
return;
invalid:
nd_print_invalid(ndo);
}
diff --git a/contrib/tcpdump/print-m3ua.c b/contrib/tcpdump/print-m3ua.c
index ecf7db834385..403a417b0202 100644
--- a/contrib/tcpdump/print-m3ua.c
+++ b/contrib/tcpdump/print-m3ua.c
@@ -1,337 +1,335 @@
/* Copyright (c) 2013, The TCPDUMP project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* \summary: Message Transfer Part 3 (MTP3) User Adaptation Layer (M3UA) printer */
/* RFC 4666 */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
#define M3UA_REL_1_0 1
struct m3ua_common_header {
nd_uint8_t v;
nd_uint8_t reserved;
nd_uint8_t msg_class;
nd_uint8_t msg_type;
nd_uint32_t len;
};
struct m3ua_param_header {
nd_uint16_t tag;
nd_uint16_t len;
};
/* message classes */
#define M3UA_MSGC_MGMT 0
#define M3UA_MSGC_TRANSFER 1
#define M3UA_MSGC_SSNM 2
#define M3UA_MSGC_ASPSM 3
#define M3UA_MSGC_ASPTM 4
/* reserved values */
#define M3UA_MSGC_RKM 9
static const struct tok MessageClasses[] = {
{ M3UA_MSGC_MGMT, "Management" },
{ M3UA_MSGC_TRANSFER, "Transfer" },
{ M3UA_MSGC_SSNM, "SS7" },
{ M3UA_MSGC_ASPSM, "ASP" },
{ M3UA_MSGC_ASPTM, "ASP" },
{ M3UA_MSGC_RKM, "Routing Key Management"},
{ 0, NULL }
};
/* management messages */
#define M3UA_MGMT_ERROR 0
#define M3UA_MGMT_NOTIFY 1
static const struct tok MgmtMessages[] = {
{ M3UA_MGMT_ERROR, "Error" },
{ M3UA_MGMT_NOTIFY, "Notify" },
{ 0, NULL }
};
/* transfer messages */
#define M3UA_TRANSFER_DATA 1
static const struct tok TransferMessages[] = {
{ M3UA_TRANSFER_DATA, "Data" },
{ 0, NULL }
};
/* SS7 Signaling Network Management messages */
#define M3UA_SSNM_DUNA 1
#define M3UA_SSNM_DAVA 2
#define M3UA_SSNM_DAUD 3
#define M3UA_SSNM_SCON 4
#define M3UA_SSNM_DUPU 5
#define M3UA_SSNM_DRST 6
static const struct tok SS7Messages[] = {
{ M3UA_SSNM_DUNA, "Destination Unavailable" },
{ M3UA_SSNM_DAVA, "Destination Available" },
{ M3UA_SSNM_DAUD, "Destination State Audit" },
{ M3UA_SSNM_SCON, "Signalling Congestion" },
{ M3UA_SSNM_DUPU, "Destination User Part Unavailable" },
{ M3UA_SSNM_DRST, "Destination Restricted" },
{ 0, NULL }
};
/* ASP State Maintenance messages */
#define M3UA_ASP_UP 1
#define M3UA_ASP_DN 2
#define M3UA_ASP_BEAT 3
#define M3UA_ASP_UP_ACK 4
#define M3UA_ASP_DN_ACK 5
#define M3UA_ASP_BEAT_ACK 6
static const struct tok ASPStateMessages[] = {
{ M3UA_ASP_UP, "Up" },
{ M3UA_ASP_DN, "Down" },
{ M3UA_ASP_BEAT, "Heartbeat" },
{ M3UA_ASP_UP_ACK, "Up Acknowledgement" },
{ M3UA_ASP_DN_ACK, "Down Acknowledgement" },
{ M3UA_ASP_BEAT_ACK, "Heartbeat Acknowledgement" },
{ 0, NULL }
};
/* ASP Traffic Maintenance messages */
#define M3UA_ASP_AC 1
#define M3UA_ASP_IA 2
#define M3UA_ASP_AC_ACK 3
#define M3UA_ASP_IA_ACK 4
static const struct tok ASPTrafficMessages[] = {
{ M3UA_ASP_AC, "Active" },
{ M3UA_ASP_IA, "Inactive" },
{ M3UA_ASP_AC_ACK, "Active Acknowledgement" },
{ M3UA_ASP_IA_ACK, "Inactive Acknowledgement" },
{ 0, NULL }
};
/* Routing Key Management messages */
#define M3UA_RKM_REQ 1
#define M3UA_RKM_RSP 2
#define M3UA_RKM_DEREQ 3
#define M3UA_RKM_DERSP 4
static const struct tok RoutingKeyMgmtMessages[] = {
{ M3UA_RKM_REQ, "Registration Request" },
{ M3UA_RKM_RSP, "Registration Response" },
{ M3UA_RKM_DEREQ, "Deregistration Request" },
{ M3UA_RKM_DERSP, "Deregistration Response" },
{ 0, NULL }
};
static const struct uint_tokary m3ua_msgc2tokary[] = {
{ M3UA_MSGC_MGMT, MgmtMessages },
{ M3UA_MSGC_TRANSFER, TransferMessages },
{ M3UA_MSGC_SSNM, SS7Messages },
{ M3UA_MSGC_ASPSM, ASPStateMessages },
{ M3UA_MSGC_ASPTM, ASPTrafficMessages },
{ M3UA_MSGC_RKM, RoutingKeyMgmtMessages },
/* uint2tokary() does not use array termination. */
};
/* M3UA Parameters */
#define M3UA_PARAM_INFO 0x0004
#define M3UA_PARAM_ROUTING_CTX 0x0006
#define M3UA_PARAM_DIAGNOSTIC 0x0007
#define M3UA_PARAM_HB_DATA 0x0009
#define M3UA_PARAM_TRAFFIC_MODE_TYPE 0x000b
#define M3UA_PARAM_ERROR_CODE 0x000c
#define M3UA_PARAM_STATUS 0x000d
#define M3UA_PARAM_ASP_ID 0x0011
#define M3UA_PARAM_AFFECTED_POINT_CODE 0x0012
#define M3UA_PARAM_CORR_ID 0x0013
#define M3UA_PARAM_NETWORK_APPEARANCE 0x0200
#define M3UA_PARAM_USER 0x0204
#define M3UA_PARAM_CONGESTION_INDICATION 0x0205
#define M3UA_PARAM_CONCERNED_DST 0x0206
#define M3UA_PARAM_ROUTING_KEY 0x0207
#define M3UA_PARAM_REG_RESULT 0x0208
#define M3UA_PARAM_DEREG_RESULT 0x0209
#define M3UA_PARAM_LOCAL_ROUTING_KEY_ID 0x020a
#define M3UA_PARAM_DST_POINT_CODE 0x020b
#define M3UA_PARAM_SI 0x020c
#define M3UA_PARAM_ORIGIN_POINT_CODE_LIST 0x020e
#define M3UA_PARAM_PROTO_DATA 0x0210
#define M3UA_PARAM_REG_STATUS 0x0212
#define M3UA_PARAM_DEREG_STATUS 0x0213
static const struct tok ParamName[] = {
{ M3UA_PARAM_INFO, "INFO String" },
{ M3UA_PARAM_ROUTING_CTX, "Routing Context" },
{ M3UA_PARAM_DIAGNOSTIC, "Diagnostic Info" },
{ M3UA_PARAM_HB_DATA, "Heartbeat Data" },
{ M3UA_PARAM_TRAFFIC_MODE_TYPE, "Traffic Mode Type" },
{ M3UA_PARAM_ERROR_CODE, "Error Code" },
{ M3UA_PARAM_STATUS, "Status" },
{ M3UA_PARAM_ASP_ID, "ASP Identifier" },
{ M3UA_PARAM_AFFECTED_POINT_CODE, "Affected Point Code" },
{ M3UA_PARAM_CORR_ID, "Correlation ID" },
{ M3UA_PARAM_NETWORK_APPEARANCE, "Network Appearance" },
{ M3UA_PARAM_USER, "User/Cause" },
{ M3UA_PARAM_CONGESTION_INDICATION, "Congestion Indications" },
{ M3UA_PARAM_CONCERNED_DST, "Concerned Destination" },
{ M3UA_PARAM_ROUTING_KEY, "Routing Key" },
{ M3UA_PARAM_REG_RESULT, "Registration Result" },
{ M3UA_PARAM_DEREG_RESULT, "Deregistration Result" },
{ M3UA_PARAM_LOCAL_ROUTING_KEY_ID, "Local Routing Key Identifier" },
{ M3UA_PARAM_DST_POINT_CODE, "Destination Point Code" },
{ M3UA_PARAM_SI, "Service Indicators" },
{ M3UA_PARAM_ORIGIN_POINT_CODE_LIST, "Originating Point Code List" },
{ M3UA_PARAM_PROTO_DATA, "Protocol Data" },
{ M3UA_PARAM_REG_STATUS, "Registration Status" },
{ M3UA_PARAM_DEREG_STATUS, "Deregistration Status" },
{ 0, NULL }
};
static void
tag_value_print(netdissect_options *ndo,
const u_char *buf, const uint16_t tag, const uint16_t size)
{
switch (tag) {
case M3UA_PARAM_NETWORK_APPEARANCE:
case M3UA_PARAM_ROUTING_CTX:
case M3UA_PARAM_CORR_ID:
/* buf and size don't include the header */
if (size < 4)
goto invalid;
ND_PRINT("0x%08x", GET_BE_U_4(buf));
break;
/* ... */
default:
ND_PRINT("(length %zu)", size + sizeof(struct m3ua_param_header));
}
ND_TCHECK_LEN(buf, size);
return;
invalid:
nd_print_invalid(ndo);
ND_TCHECK_LEN(buf, size);
}
/*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Parameter Tag | Parameter Length |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* \ \
* / Parameter Value /
* \ \
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
static void
m3ua_tags_print(netdissect_options *ndo,
const u_char *buf, const u_int size)
{
const u_char *p = buf;
int align;
uint16_t hdr_tag;
uint16_t hdr_len;
while (p < buf + size) {
if (p + sizeof(struct m3ua_param_header) > buf + size)
goto invalid;
/* Parameter Tag */
hdr_tag = GET_BE_U_2(p);
ND_PRINT("\n\t\t\t%s: ", tok2str(ParamName, "Unknown Parameter (0x%04x)", hdr_tag));
/* Parameter Length */
hdr_len = GET_BE_U_2(p + 2);
if (hdr_len < sizeof(struct m3ua_param_header))
goto invalid;
/* Parameter Value */
align = (p + hdr_len - buf) % 4;
align = align ? 4 - align : 0;
ND_TCHECK_LEN(p, hdr_len + align);
tag_value_print(ndo, p, hdr_tag, hdr_len - sizeof(struct m3ua_param_header));
p += hdr_len + align;
}
return;
invalid:
nd_print_invalid(ndo);
ND_TCHECK_LEN(buf, size);
}
/*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Version | Reserved | Message Class | Message Type |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Message Length |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* \ \
* / /
*/
void
m3ua_print(netdissect_options *ndo,
const u_char *buf, const u_int size)
{
const struct m3ua_common_header *hdr = (const struct m3ua_common_header *) buf;
const struct tok *dict;
uint8_t msg_class;
ndo->ndo_protocol = "m3ua";
/* size includes the header */
if (size < sizeof(struct m3ua_common_header))
goto invalid;
ND_TCHECK_SIZE(hdr);
if (GET_U_1(hdr->v) != M3UA_REL_1_0)
return;
msg_class = GET_U_1(hdr->msg_class);
dict = uint2tokary(m3ua_msgc2tokary, msg_class);
ND_PRINT("\n\t\t%s", tok2str(MessageClasses, "Unknown message class %i", msg_class));
if (dict != NULL)
ND_PRINT(" %s Message",
tok2str(dict, "Unknown (0x%02x)", GET_U_1(hdr->msg_type)));
if (size != GET_BE_U_4(hdr->len))
ND_PRINT("\n\t\t\t@@@@@@ Corrupted length %u of message @@@@@@",
GET_BE_U_4(hdr->len));
else
m3ua_tags_print(ndo, buf + sizeof(struct m3ua_common_header),
GET_BE_U_4(hdr->len) - sizeof(struct m3ua_common_header));
return;
invalid:
nd_print_invalid(ndo);
ND_TCHECK_LEN(buf, size);
}
diff --git a/contrib/tcpdump/print-macsec.c b/contrib/tcpdump/print-macsec.c
index 607f696ef265..0c9ea05f1335 100644
--- a/contrib/tcpdump/print-macsec.c
+++ b/contrib/tcpdump/print-macsec.c
@@ -1,256 +1,253 @@
/* Copyright (c) 2017, Sabrina Dubroca <sd@queasysnail.net>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. The names of the authors may not 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.
*/
/* \summary: MACsec printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "addrtoname.h"
-#include "ethertype.h"
#include "extract.h"
#define MACSEC_DEFAULT_ICV_LEN 16
/* Header format (SecTAG), following an Ethernet header
* IEEE 802.1AE-2006 9.3
*
* +---------------------------------+----------------+----------------+
* | (MACsec ethertype) | TCI_AN | SL |
* +---------------------------------+----------------+----------------+
* | Packet Number |
* +-------------------------------------------------------------------+
* | Secure Channel Identifier |
* | (optional) |
* +-------------------------------------------------------------------+
*
* MACsec ethertype = 0x88e5
* TCI: Tag Control Information, set of flags
* AN: association number, 2 bits
* SL (short length): 6-bit length of the protected payload, if < 48
* Packet Number: 32-bits packet identifier
* Secure Channel Identifier: 64-bit unique identifier, usually
* composed of a MAC address + 16-bit port number
*/
struct macsec_sectag {
nd_uint8_t tci_an;
nd_uint8_t short_length;
nd_uint32_t packet_number;
nd_uint8_t secure_channel_id[8]; /* optional */
};
/* IEEE 802.1AE-2006 9.5 */
#define MACSEC_TCI_VERSION 0x80
#define MACSEC_TCI_ES 0x40 /* end station */
#define MACSEC_TCI_SC 0x20 /* SCI present */
#define MACSEC_TCI_SCB 0x10 /* epon */
#define MACSEC_TCI_E 0x08 /* encryption */
#define MACSEC_TCI_C 0x04 /* changed text */
#define MACSEC_AN_MASK 0x03 /* association number */
#define MACSEC_TCI_FLAGS (MACSEC_TCI_ES | MACSEC_TCI_SC | MACSEC_TCI_SCB | MACSEC_TCI_E | MACSEC_TCI_C)
#define MACSEC_TCI_CONFID (MACSEC_TCI_E | MACSEC_TCI_C)
#define MACSEC_SL_MASK 0x3F /* short length */
#define MACSEC_SECTAG_LEN_NOSCI 6 /* length of MACsec header without SCI */
#define MACSEC_SECTAG_LEN_SCI 14 /* length of MACsec header with SCI */
#define SCI_FMT "%016" PRIx64
static const struct tok macsec_flag_values[] = {
{ MACSEC_TCI_E, "E" },
{ MACSEC_TCI_C, "C" },
{ MACSEC_TCI_ES, "S" },
{ MACSEC_TCI_SCB, "B" },
{ MACSEC_TCI_SC, "I" },
{ 0, NULL }
};
static void macsec_print_header(netdissect_options *ndo,
const struct macsec_sectag *sectag,
u_int short_length)
{
ND_PRINT("an %u, pn %u, flags %s",
GET_U_1(sectag->tci_an) & MACSEC_AN_MASK,
GET_BE_U_4(sectag->packet_number),
bittok2str_nosep(macsec_flag_values, "none",
GET_U_1(sectag->tci_an) & MACSEC_TCI_FLAGS));
if (short_length != 0)
ND_PRINT(", sl %u", short_length);
if (GET_U_1(sectag->tci_an) & MACSEC_TCI_SC)
ND_PRINT(", sci " SCI_FMT, GET_BE_U_8(sectag->secure_channel_id));
ND_PRINT(", ");
}
/* returns < 0 iff the packet can be decoded completely */
int macsec_print(netdissect_options *ndo, const u_char **bp,
u_int *lengthp, u_int *caplenp, u_int *hdrlenp,
const struct lladdr_info *src, const struct lladdr_info *dst)
{
const char *save_protocol;
const u_char *p = *bp;
u_int length = *lengthp;
u_int caplen = *caplenp;
u_int hdrlen = *hdrlenp;
const struct macsec_sectag *sectag = (const struct macsec_sectag *)p;
u_int sectag_len;
u_int short_length;
save_protocol = ndo->ndo_protocol;
ndo->ndo_protocol = "macsec";
/* we need the full MACsec header in the capture */
if (caplen < MACSEC_SECTAG_LEN_NOSCI) {
nd_print_trunc(ndo);
ndo->ndo_protocol = save_protocol;
return hdrlen + caplen;
}
if (length < MACSEC_SECTAG_LEN_NOSCI) {
nd_print_trunc(ndo);
ndo->ndo_protocol = save_protocol;
return hdrlen + caplen;
}
if (GET_U_1(sectag->tci_an) & MACSEC_TCI_SC) {
sectag_len = MACSEC_SECTAG_LEN_SCI;
if (caplen < MACSEC_SECTAG_LEN_SCI) {
nd_print_trunc(ndo);
ndo->ndo_protocol = save_protocol;
return hdrlen + caplen;
}
if (length < MACSEC_SECTAG_LEN_SCI) {
nd_print_trunc(ndo);
ndo->ndo_protocol = save_protocol;
return hdrlen + caplen;
}
} else
sectag_len = MACSEC_SECTAG_LEN_NOSCI;
if ((GET_U_1(sectag->short_length) & ~MACSEC_SL_MASK) != 0 ||
GET_U_1(sectag->tci_an) & MACSEC_TCI_VERSION) {
nd_print_invalid(ndo);
ndo->ndo_protocol = save_protocol;
return hdrlen + caplen;
}
short_length = GET_U_1(sectag->short_length) & MACSEC_SL_MASK;
if (ndo->ndo_eflag)
macsec_print_header(ndo, sectag, short_length);
/* Skip the MACsec header. */
*bp += sectag_len;
*hdrlenp += sectag_len;
/* Remove it from the lengths, as it's been processed. */
*lengthp -= sectag_len;
*caplenp -= sectag_len;
if ((GET_U_1(sectag->tci_an) & MACSEC_TCI_CONFID)) {
/*
* The payload is encrypted. Print link-layer
* information, if it hasn't already been printed.
*/
if (!ndo->ndo_eflag) {
/*
* Nobody printed the link-layer addresses,
* so print them, if we have any.
*/
if (src != NULL && dst != NULL) {
ND_PRINT("%s > %s ",
(src->addr_string)(ndo, src->addr),
(dst->addr_string)(ndo, dst->addr));
}
ND_PRINT("802.1AE MACsec, ");
/*
* Print the MACsec header.
*/
macsec_print_header(ndo, sectag, short_length);
}
/*
* Tell our caller it can't be dissected.
*/
ndo->ndo_protocol = save_protocol;
return 0;
}
/*
* The payload isn't encrypted; remove the
* ICV length from the lengths, so our caller
* doesn't treat it as payload.
*/
if (*lengthp < MACSEC_DEFAULT_ICV_LEN) {
nd_print_trunc(ndo);
ndo->ndo_protocol = save_protocol;
return hdrlen + caplen;
}
if (*caplenp < MACSEC_DEFAULT_ICV_LEN) {
nd_print_trunc(ndo);
ndo->ndo_protocol = save_protocol;
return hdrlen + caplen;
}
*lengthp -= MACSEC_DEFAULT_ICV_LEN;
*caplenp -= MACSEC_DEFAULT_ICV_LEN;
/*
* Update the snapend thus the ICV field is not in the payload for
* the caller.
* The ICV (Integrity Check Value) is at the end of the frame, after
* the secure data.
*/
ndo->ndo_snapend -= MACSEC_DEFAULT_ICV_LEN;
/*
* If the SL field is non-zero, then it's the length of the
* Secure Data; otherwise, the Secure Data is what's left
* ver after the MACsec header and ICV are removed.
*/
if (short_length != 0) {
/*
* If the short length is more than we *have*,
* that's an error.
*/
if (short_length > *lengthp) {
nd_print_trunc(ndo);
ndo->ndo_protocol = save_protocol;
return hdrlen + caplen;
}
if (short_length > *caplenp) {
nd_print_trunc(ndo);
ndo->ndo_protocol = save_protocol;
return hdrlen + caplen;
}
if (*lengthp > short_length)
*lengthp = short_length;
if (*caplenp > short_length)
*caplenp = short_length;
}
ndo->ndo_protocol = save_protocol;
return -1;
}
diff --git a/contrib/tcpdump/print-mobile.c b/contrib/tcpdump/print-mobile.c
index 528da79c9f3e..4ac71737c494 100644
--- a/contrib/tcpdump/print-mobile.c
+++ b/contrib/tcpdump/print-mobile.c
@@ -1,104 +1,102 @@
/* $NetBSD: print-mobile.c,v 1.2 1998/09/30 08:57:01 hwr Exp $ */
/*
* (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Heiko W.Rupp <hwr@pilhuhn.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation 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 BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* \summary: IPv4 mobility printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#define MOBILE_SIZE (8)
struct mobile_ip {
nd_uint16_t proto;
nd_uint16_t hcheck;
nd_uint32_t odst;
nd_uint32_t osrc;
};
#define OSRC_PRES 0x0080 /* old source is present */
/*
* Deencapsulate and print a mobile-tunneled IP datagram
*/
void
mobile_print(netdissect_options *ndo, const u_char *bp, u_int length)
{
const struct mobile_ip *mob;
struct cksum_vec vec[1];
u_short proto,crc;
u_char osp =0; /* old source address present */
ndo->ndo_protocol = "mobile";
mob = (const struct mobile_ip *)bp;
if (length < MOBILE_SIZE || !ND_TTEST_SIZE(mob)) {
nd_print_trunc(ndo);
return;
}
ND_PRINT("mobile: ");
proto = GET_BE_U_2(mob->proto);
crc = GET_BE_U_2(mob->hcheck);
if (proto & OSRC_PRES) {
osp=1;
}
if (osp) {
ND_PRINT("[S] ");
if (ndo->ndo_vflag)
ND_PRINT("%s ", GET_IPADDR_STRING(mob->osrc));
} else {
ND_PRINT("[] ");
}
if (ndo->ndo_vflag) {
ND_PRINT("> %s ", GET_IPADDR_STRING(mob->odst));
ND_PRINT("(oproto=%u)", proto>>8);
}
vec[0].ptr = (const uint8_t *)(const void *)mob;
vec[0].len = osp ? 12 : 8;
if (in_cksum(vec, 1)!=0) {
ND_PRINT(" (bad checksum %u)", crc);
}
}
diff --git a/contrib/tcpdump/print-mobility.c b/contrib/tcpdump/print-mobility.c
index 55340ca56d2f..945a8ca2b51c 100644
--- a/contrib/tcpdump/print-mobility.c
+++ b/contrib/tcpdump/print-mobility.c
@@ -1,334 +1,331 @@
/*
* Copyright (C) 2002 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* \summary: IPv6 mobility printer */
/* RFC 3775 */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#include "ip6.h"
/* Mobility header */
struct ip6_mobility {
nd_uint8_t ip6m_pproto; /* following payload protocol (for PG) */
nd_uint8_t ip6m_len; /* length in units of 8 octets */
nd_uint8_t ip6m_type; /* message type */
nd_uint8_t reserved; /* reserved */
nd_uint16_t ip6m_cksum; /* sum of IPv6 pseudo-header and MH */
union {
nd_uint16_t ip6m_un_data16[1]; /* type-specific field */
nd_uint8_t ip6m_un_data8[2]; /* type-specific field */
} ip6m_dataun;
};
#define ip6m_data16 ip6m_dataun.ip6m_un_data16
#define ip6m_data8 ip6m_dataun.ip6m_un_data8
#define IP6M_MINLEN 8
/* https://www.iana.org/assignments/mobility-parameters/mobility-parameters.xhtml */
/* message type */
#define IP6M_BINDING_REQUEST 0 /* Binding Refresh Request */
#define IP6M_HOME_TEST_INIT 1 /* Home Test Init */
#define IP6M_CAREOF_TEST_INIT 2 /* Care-of Test Init */
#define IP6M_HOME_TEST 3 /* Home Test */
#define IP6M_CAREOF_TEST 4 /* Care-of Test */
#define IP6M_BINDING_UPDATE 5 /* Binding Update */
#define IP6M_BINDING_ACK 6 /* Binding Acknowledgement */
#define IP6M_BINDING_ERROR 7 /* Binding Error */
#define IP6M_MAX 7
static const struct tok ip6m_str[] = {
{ IP6M_BINDING_REQUEST, "BRR" },
{ IP6M_HOME_TEST_INIT, "HoTI" },
{ IP6M_CAREOF_TEST_INIT, "CoTI" },
{ IP6M_HOME_TEST, "HoT" },
{ IP6M_CAREOF_TEST, "CoT" },
{ IP6M_BINDING_UPDATE, "BU" },
{ IP6M_BINDING_ACK, "BA" },
{ IP6M_BINDING_ERROR, "BE" },
{ 0, NULL }
};
static const unsigned ip6m_hdrlen[IP6M_MAX + 1] = {
IP6M_MINLEN, /* IP6M_BINDING_REQUEST */
IP6M_MINLEN + 8, /* IP6M_HOME_TEST_INIT */
IP6M_MINLEN + 8, /* IP6M_CAREOF_TEST_INIT */
IP6M_MINLEN + 16, /* IP6M_HOME_TEST */
IP6M_MINLEN + 16, /* IP6M_CAREOF_TEST */
IP6M_MINLEN + 4, /* IP6M_BINDING_UPDATE */
IP6M_MINLEN + 4, /* IP6M_BINDING_ACK */
IP6M_MINLEN + 16, /* IP6M_BINDING_ERROR */
};
/* Mobility Header Options */
#define IP6MOPT_MINLEN 2
#define IP6MOPT_PAD1 0x0 /* Pad1 */
#define IP6MOPT_PADN 0x1 /* PadN */
#define IP6MOPT_REFRESH 0x2 /* Binding Refresh Advice */
#define IP6MOPT_REFRESH_MINLEN 4
#define IP6MOPT_ALTCOA 0x3 /* Alternate Care-of Address */
#define IP6MOPT_ALTCOA_MINLEN 18
#define IP6MOPT_NONCEID 0x4 /* Nonce Indices */
#define IP6MOPT_NONCEID_MINLEN 6
#define IP6MOPT_AUTH 0x5 /* Binding Authorization Data */
#define IP6MOPT_AUTH_MINLEN 12
static const struct tok ip6m_binding_update_bits [] = {
{ 0x08, "A" },
{ 0x04, "H" },
{ 0x02, "L" },
{ 0x01, "K" },
{ 0, NULL }
};
static int
mobility_opt_print(netdissect_options *ndo,
const u_char *bp, const unsigned len)
{
unsigned i, optlen;
for (i = 0; i < len; i += optlen) {
if (GET_U_1(bp + i) == IP6MOPT_PAD1)
optlen = 1;
else {
if (i + 1 < len) {
optlen = GET_U_1(bp + i + 1) + 2;
- }
- else
+ } else
goto trunc;
}
if (i + optlen > len)
goto trunc;
ND_TCHECK_1(bp + i + optlen);
switch (GET_U_1(bp + i)) {
case IP6MOPT_PAD1:
ND_PRINT("(pad1)");
break;
case IP6MOPT_PADN:
if (len - i < IP6MOPT_MINLEN) {
ND_PRINT("(padn: trunc)");
goto trunc;
}
ND_PRINT("(padn)");
break;
case IP6MOPT_REFRESH:
if (len - i < IP6MOPT_REFRESH_MINLEN) {
ND_PRINT("(refresh: trunc)");
goto trunc;
}
/* units of 4 secs */
ND_PRINT("(refresh: %u)",
GET_BE_U_2(bp + i + 2) << 2);
break;
case IP6MOPT_ALTCOA:
if (len - i < IP6MOPT_ALTCOA_MINLEN) {
ND_PRINT("(altcoa: trunc)");
goto trunc;
}
ND_PRINT("(alt-CoA: %s)", GET_IP6ADDR_STRING(bp + i + 2));
break;
case IP6MOPT_NONCEID:
if (len - i < IP6MOPT_NONCEID_MINLEN) {
ND_PRINT("(ni: trunc)");
goto trunc;
}
ND_PRINT("(ni: ho=0x%04x co=0x%04x)",
GET_BE_U_2(bp + i + 2),
GET_BE_U_2(bp + i + 4));
break;
case IP6MOPT_AUTH:
if (len - i < IP6MOPT_AUTH_MINLEN) {
ND_PRINT("(auth: trunc)");
goto trunc;
}
ND_PRINT("(auth)");
break;
default:
if (len - i < IP6MOPT_MINLEN) {
ND_PRINT("(sopt_type %u: trunc)",
GET_U_1(bp + i));
goto trunc;
}
ND_PRINT("(type-0x%02x: len=%u)", GET_U_1(bp + i),
GET_U_1(bp + i + 1));
break;
}
}
return 0;
trunc:
return 1;
}
/*
* Mobility Header
*/
int
mobility_print(netdissect_options *ndo,
const u_char *bp, const u_char *bp2 _U_)
{
const struct ip6_mobility *mh;
const u_char *ep;
unsigned mhlen, hlen;
uint8_t type;
ndo->ndo_protocol = "mobility";
mh = (const struct ip6_mobility *)bp;
/* 'ep' points to the end of available data. */
ep = ndo->ndo_snapend;
if (!ND_TTEST_1(mh->ip6m_len)) {
/*
* There's not enough captured data to include the
* mobility header length.
*
* Our caller expects us to return the length, however,
* so return a value that will run to the end of the
* captured data.
*
* XXX - "ip6_print()" doesn't do anything with the
* returned length, however, as it breaks out of the
* header-processing loop.
*/
mhlen = (unsigned)(ep - bp);
goto trunc;
}
mhlen = (GET_U_1(mh->ip6m_len) + 1) << 3;
/* XXX ip6m_cksum */
type = GET_U_1(mh->ip6m_type);
if (type <= IP6M_MAX && mhlen < ip6m_hdrlen[type]) {
ND_PRINT("(header length %u is too small for type %u)", mhlen, type);
goto trunc;
}
ND_PRINT("mobility: %s", tok2str(ip6m_str, "type-#%u", type));
switch (type) {
case IP6M_BINDING_REQUEST:
hlen = IP6M_MINLEN;
break;
case IP6M_HOME_TEST_INIT:
case IP6M_CAREOF_TEST_INIT:
hlen = IP6M_MINLEN;
if (ndo->ndo_vflag) {
ND_PRINT(" %s Init Cookie=%08x:%08x",
type == IP6M_HOME_TEST_INIT ? "Home" : "Care-of",
GET_BE_U_4(bp + hlen),
GET_BE_U_4(bp + hlen + 4));
}
hlen += 8;
break;
case IP6M_HOME_TEST:
case IP6M_CAREOF_TEST:
ND_PRINT(" nonce id=0x%x", GET_BE_U_2(mh->ip6m_data16[0]));
hlen = IP6M_MINLEN;
if (ndo->ndo_vflag) {
ND_PRINT(" %s Init Cookie=%08x:%08x",
type == IP6M_HOME_TEST ? "Home" : "Care-of",
GET_BE_U_4(bp + hlen),
GET_BE_U_4(bp + hlen + 4));
}
hlen += 8;
if (ndo->ndo_vflag) {
ND_PRINT(" %s Keygen Token=%08x:%08x",
type == IP6M_HOME_TEST ? "Home" : "Care-of",
GET_BE_U_4(bp + hlen),
GET_BE_U_4(bp + hlen + 4));
}
hlen += 8;
break;
case IP6M_BINDING_UPDATE:
{
int bits;
ND_PRINT(" seq#=%u", GET_BE_U_2(mh->ip6m_data16[0]));
hlen = IP6M_MINLEN;
ND_TCHECK_2(bp + hlen);
bits = (GET_U_1(bp + hlen) & 0xf0) >> 4;
if (bits) {
ND_PRINT(" ");
ND_PRINT("%s",
bittok2str_nosep(ip6m_binding_update_bits,
"bits-#0x%x", bits));
}
/* Reserved (4bits) */
hlen += 1;
/* Reserved (8bits) */
hlen += 1;
/* units of 4 secs */
ND_PRINT(" lifetime=%u", GET_BE_U_2(bp + hlen) << 2);
hlen += 2;
break;
}
case IP6M_BINDING_ACK:
ND_PRINT(" status=%u", GET_U_1(mh->ip6m_data8[0]));
if (GET_U_1(mh->ip6m_data8[1]) & 0x80)
ND_PRINT(" K");
/* Reserved (7bits) */
hlen = IP6M_MINLEN;
ND_PRINT(" seq#=%u", GET_BE_U_2(bp + hlen));
hlen += 2;
/* units of 4 secs */
ND_PRINT(" lifetime=%u", GET_BE_U_2(bp + hlen) << 2);
hlen += 2;
break;
case IP6M_BINDING_ERROR:
ND_PRINT(" status=%u", GET_U_1(mh->ip6m_data8[0]));
/* Reserved */
hlen = IP6M_MINLEN;
ND_PRINT(" homeaddr %s", GET_IP6ADDR_STRING(bp + hlen));
hlen += 16;
break;
default:
ND_PRINT(" len=%u", GET_U_1(mh->ip6m_len));
return(mhlen);
break;
}
if (ndo->ndo_vflag)
if (mobility_opt_print(ndo, bp + hlen, mhlen - hlen))
goto trunc;
return(mhlen);
trunc:
nd_print_trunc(ndo);
return(-1);
}
diff --git a/contrib/tcpdump/print-mpcp.c b/contrib/tcpdump/print-mpcp.c
index 4ba873bf3fca..519f41b1112d 100644
--- a/contrib/tcpdump/print-mpcp.c
+++ b/contrib/tcpdump/print-mpcp.c
@@ -1,235 +1,233 @@
/*
* Copyright (c) 1998-2006 The TCPDUMP project
*
* 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.
*
* Original code by Hannes Gredler (hannes@gredler.at)
*/
/* \summary: IEEE 802.3ah Multi-Point Control Protocol (MPCP) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "extract.h"
struct mpcp_common_header_t {
nd_uint16_t opcode;
nd_uint32_t timestamp;
};
#define MPCP_OPCODE_PAUSE 0x0001
#define MPCP_OPCODE_GATE 0x0002
#define MPCP_OPCODE_REPORT 0x0003
#define MPCP_OPCODE_REG_REQ 0x0004
#define MPCP_OPCODE_REG 0x0005
#define MPCP_OPCODE_REG_ACK 0x0006
static const struct tok mpcp_opcode_values[] = {
{ MPCP_OPCODE_PAUSE, "Pause" },
{ MPCP_OPCODE_GATE, "Gate" },
{ MPCP_OPCODE_REPORT, "Report" },
{ MPCP_OPCODE_REG_REQ, "Register Request" },
{ MPCP_OPCODE_REG, "Register" },
{ MPCP_OPCODE_REG_ACK, "Register ACK" },
{ 0, NULL}
};
#define MPCP_GRANT_NUMBER_LEN 1
#define MPCP_GRANT_NUMBER_MASK 0x7
static const struct tok mpcp_grant_flag_values[] = {
{ 0x08, "Discovery" },
{ 0x10, "Force Grant #1" },
{ 0x20, "Force Grant #2" },
{ 0x40, "Force Grant #3" },
{ 0x80, "Force Grant #4" },
{ 0, NULL}
};
struct mpcp_grant_t {
nd_uint32_t starttime;
nd_uint16_t duration;
};
struct mpcp_reg_req_t {
nd_uint8_t flags;
nd_uint8_t pending_grants;
};
static const struct tok mpcp_reg_req_flag_values[] = {
{ 1, "Register" },
{ 3, "De-Register" },
{ 0, NULL}
};
struct mpcp_reg_t {
nd_uint16_t assigned_port;
nd_uint8_t flags;
nd_uint16_t sync_time;
nd_uint8_t echoed_pending_grants;
};
static const struct tok mpcp_reg_flag_values[] = {
{ 1, "Re-Register" },
{ 2, "De-Register" },
{ 3, "ACK" },
{ 4, "NACK" },
{ 0, NULL}
};
#define MPCP_REPORT_QUEUESETS_LEN 1
#define MPCP_REPORT_REPORTBITMAP_LEN 1
static const struct tok mpcp_report_bitmap_values[] = {
{ 0x01, "Q0" },
{ 0x02, "Q1" },
{ 0x04, "Q2" },
{ 0x08, "Q3" },
{ 0x10, "Q4" },
{ 0x20, "Q5" },
{ 0x40, "Q6" },
{ 0x80, "Q7" },
{ 0, NULL}
};
struct mpcp_reg_ack_t {
nd_uint8_t flags;
nd_uint16_t echoed_assigned_port;
nd_uint16_t echoed_sync_time;
};
static const struct tok mpcp_reg_ack_flag_values[] = {
{ 0, "NACK" },
{ 1, "ACK" },
{ 0, NULL}
};
void
mpcp_print(netdissect_options *ndo, const u_char *pptr, u_int length)
{
const struct mpcp_common_header_t *mpcp_common_header;
const struct mpcp_reg_req_t *mpcp_reg_req;
const struct mpcp_reg_t *mpcp_reg;
const struct mpcp_reg_ack_t *mpcp_reg_ack;
const u_char *tptr;
uint16_t opcode;
uint32_t timestamp;
uint8_t grant_numbers, grant;
uint8_t queue_sets, queue_set, report_bitmap, report;
ndo->ndo_protocol = "mpcp";
tptr=pptr;
mpcp_common_header = (const struct mpcp_common_header_t *)pptr;
opcode = GET_BE_U_2(mpcp_common_header->opcode);
timestamp = GET_BE_U_4(mpcp_common_header->timestamp);
ND_PRINT("MPCP, Opcode %s", tok2str(mpcp_opcode_values, "Unknown (%u)", opcode));
if (opcode != MPCP_OPCODE_PAUSE) {
ND_PRINT(", Timestamp %u ticks", timestamp);
}
ND_PRINT(", length %u", length);
if (!ndo->ndo_vflag)
return;
tptr += sizeof(struct mpcp_common_header_t);
switch (opcode) {
case MPCP_OPCODE_PAUSE:
break;
case MPCP_OPCODE_GATE:
grant_numbers = GET_U_1(tptr) & MPCP_GRANT_NUMBER_MASK;
ND_PRINT("\n\tGrant Numbers %u, Flags [ %s ]",
grant_numbers,
bittok2str(mpcp_grant_flag_values,
"?",
GET_U_1(tptr) & ~MPCP_GRANT_NUMBER_MASK));
tptr++;
for (grant = 1; grant <= grant_numbers; grant++) {
const struct mpcp_grant_t *mpcp_grant = (const struct mpcp_grant_t *)tptr;
ND_PRINT("\n\tGrant #%u, Start-Time %u ticks, duration %u ticks",
grant,
GET_BE_U_4(mpcp_grant->starttime),
GET_BE_U_2(mpcp_grant->duration));
tptr += sizeof(struct mpcp_grant_t);
}
ND_PRINT("\n\tSync-Time %u ticks", GET_BE_U_2(tptr));
break;
case MPCP_OPCODE_REPORT:
queue_sets = GET_U_1(tptr);
tptr+=MPCP_REPORT_QUEUESETS_LEN;
ND_PRINT("\n\tTotal Queue-Sets %u", queue_sets);
for (queue_set = 1; queue_set < queue_sets; queue_set++) {
report_bitmap = GET_U_1(tptr);
ND_PRINT("\n\t Queue-Set #%u, Report-Bitmap [ %s ]",
queue_sets,
bittok2str(mpcp_report_bitmap_values, "Unknown", report_bitmap));
tptr++;
report=1;
while (report_bitmap != 0) {
if (report_bitmap & 1) {
ND_PRINT("\n\t Q%u Report, Duration %u ticks",
report,
GET_BE_U_2(tptr));
tptr += 2;
}
report++;
report_bitmap = report_bitmap >> 1;
}
}
break;
case MPCP_OPCODE_REG_REQ:
mpcp_reg_req = (const struct mpcp_reg_req_t *)tptr;
ND_PRINT("\n\tFlags [ %s ], Pending-Grants %u",
bittok2str(mpcp_reg_req_flag_values, "Reserved", GET_U_1(mpcp_reg_req->flags)),
GET_U_1(mpcp_reg_req->pending_grants));
break;
case MPCP_OPCODE_REG:
mpcp_reg = (const struct mpcp_reg_t *)tptr;
ND_PRINT("\n\tAssigned-Port %u, Flags [ %s ]"
"\n\tSync-Time %u ticks, Echoed-Pending-Grants %u",
GET_BE_U_2(mpcp_reg->assigned_port),
bittok2str(mpcp_reg_flag_values, "Reserved", GET_U_1(mpcp_reg->flags)),
GET_BE_U_2(mpcp_reg->sync_time),
GET_U_1(mpcp_reg->echoed_pending_grants));
break;
case MPCP_OPCODE_REG_ACK:
mpcp_reg_ack = (const struct mpcp_reg_ack_t *)tptr;
ND_PRINT("\n\tEchoed-Assigned-Port %u, Flags [ %s ]"
"\n\tEchoed-Sync-Time %u ticks",
GET_BE_U_2(mpcp_reg_ack->echoed_assigned_port),
bittok2str(mpcp_reg_ack_flag_values, "Reserved", GET_U_1(mpcp_reg_ack->flags)),
GET_BE_U_2(mpcp_reg_ack->echoed_sync_time));
break;
default:
/* unknown opcode - hexdump for now */
print_unknown_data(ndo,pptr, "\n\t", length);
break;
}
}
diff --git a/contrib/tcpdump/print-mpls.c b/contrib/tcpdump/print-mpls.c
index c9be49649762..a80b722fa7e7 100644
--- a/contrib/tcpdump/print-mpls.c
+++ b/contrib/tcpdump/print-mpls.c
@@ -1,174 +1,172 @@
/*
* Copyright (C) 2001 WIDE Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* \summary: Multi-Protocol Label Switching (MPLS) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
#include "mpls.h"
static const char *mpls_labelname[] = {
/*0*/ "IPv4 explicit NULL", "router alert", "IPv6 explicit NULL",
"implicit NULL", "rsvd",
/*5*/ "rsvd", "rsvd", "rsvd", "rsvd", "rsvd",
/*10*/ "rsvd", "rsvd", "rsvd", "rsvd", "rsvd",
/*15*/ "rsvd",
};
enum mpls_packet_type {
PT_UNKNOWN,
PT_IPV4,
PT_IPV6,
PT_OSI
};
/*
* RFC3032: MPLS label stack encoding
*/
void
mpls_print(netdissect_options *ndo, const u_char *bp, u_int length)
{
const u_char *p;
uint32_t label_entry;
uint16_t label_stack_depth = 0;
uint8_t first;
enum mpls_packet_type pt = PT_UNKNOWN;
ndo->ndo_protocol = "mpls";
p = bp;
nd_print_protocol_caps(ndo);
do {
if (length < sizeof(label_entry))
goto invalid;
label_entry = GET_BE_U_4(p);
ND_PRINT("%s(label %u",
(label_stack_depth && ndo->ndo_vflag) ? "\n\t" : " ",
MPLS_LABEL(label_entry));
label_stack_depth++;
if (ndo->ndo_vflag &&
MPLS_LABEL(label_entry) < sizeof(mpls_labelname) / sizeof(mpls_labelname[0]))
ND_PRINT(" (%s)", mpls_labelname[MPLS_LABEL(label_entry)]);
ND_PRINT(", tc %u", MPLS_TC(label_entry));
if (MPLS_STACK(label_entry))
ND_PRINT(", [S]");
ND_PRINT(", ttl %u)", MPLS_TTL(label_entry));
p += sizeof(label_entry);
length -= sizeof(label_entry);
} while (!MPLS_STACK(label_entry));
/*
* Try to figure out the packet type.
*/
switch (MPLS_LABEL(label_entry)) {
case 0: /* IPv4 explicit NULL label */
case 3: /* IPv4 implicit NULL label */
pt = PT_IPV4;
break;
case 2: /* IPv6 explicit NULL label */
pt = PT_IPV6;
break;
default:
/*
* Generally there's no indication of protocol in MPLS label
* encoding.
*
* However, draft-hsmit-isis-aal5mux-00.txt describes a
* technique for encapsulating IS-IS and IP traffic on the
* same ATM virtual circuit; you look at the first payload
* byte to determine the network layer protocol, based on
* the fact that
*
* 1) the first byte of an IP header is 0x45-0x4f
* for IPv4 and 0x60-0x6f for IPv6;
*
* 2) the first byte of an OSI CLNP packet is 0x81,
* the first byte of an OSI ES-IS packet is 0x82,
* and the first byte of an OSI IS-IS packet is
* 0x83;
*
* so the network layer protocol can be inferred from the
* first byte of the packet, if the protocol is one of the
* ones listed above.
*
* Cisco sends control-plane traffic MPLS-encapsulated in
* this fashion.
*/
if (length < 1) {
/* nothing to print */
return;
}
first = GET_U_1(p);
pt =
(first >= 0x45 && first <= 0x4f) ? PT_IPV4 :
(first >= 0x60 && first <= 0x6f) ? PT_IPV6 :
(first >= 0x81 && first <= 0x83) ? PT_OSI :
/* ok bail out - we did not figure out what it is*/
PT_UNKNOWN;
}
/*
* Print the payload.
*/
switch (pt) {
case PT_UNKNOWN:
if (!ndo->ndo_suppress_default_print)
ND_DEFAULTPRINT(p, length);
break;
case PT_IPV4:
ND_PRINT(ndo->ndo_vflag ? "\n\t" : " ");
ip_print(ndo, p, length);
break;
case PT_IPV6:
ND_PRINT(ndo->ndo_vflag ? "\n\t" : " ");
ip6_print(ndo, p, length);
break;
case PT_OSI:
ND_PRINT(ndo->ndo_vflag ? "\n\t" : " ");
isoclns_print(ndo, p, length);
break;
}
return;
invalid:
nd_print_invalid(ndo);
ND_TCHECK_LEN(p, length);
}
diff --git a/contrib/tcpdump/print-mptcp.c b/contrib/tcpdump/print-mptcp.c
index 7ffb1f51a4c6..79a79ca06dfa 100644
--- a/contrib/tcpdump/print-mptcp.c
+++ b/contrib/tcpdump/print-mptcp.c
@@ -1,485 +1,483 @@
/**
* Copyright (c) 2012
*
* Gregory Detal <gregory.detal@uclouvain.be>
* Christoph Paasch <christoph.paasch@uclouvain.be>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the University nor of the Laboratory may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* \summary: Multipath TCP (MPTCP) printer */
/* specification: RFC 6824 */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "extract.h"
#include "addrtoname.h"
#include "tcp.h"
#define MPTCP_SUB_CAPABLE 0x0
#define MPTCP_SUB_JOIN 0x1
#define MPTCP_SUB_DSS 0x2
#define MPTCP_SUB_ADD_ADDR 0x3
#define MPTCP_SUB_REMOVE_ADDR 0x4
#define MPTCP_SUB_PRIO 0x5
#define MPTCP_SUB_FAIL 0x6
#define MPTCP_SUB_FCLOSE 0x7
struct mptcp_option {
nd_uint8_t kind;
nd_uint8_t len;
nd_uint8_t sub_etc; /* subtype upper 4 bits, other stuff lower 4 bits */
};
#define MPTCP_OPT_SUBTYPE(sub_etc) (((sub_etc) >> 4) & 0xF)
struct mp_capable {
nd_uint8_t kind;
nd_uint8_t len;
nd_uint8_t sub_ver;
nd_uint8_t flags;
nd_uint64_t sender_key;
nd_uint64_t receiver_key;
};
#define MP_CAPABLE_OPT_VERSION(sub_ver) (((sub_ver) >> 0) & 0xF)
#define MP_CAPABLE_C 0x80
#define MP_CAPABLE_S 0x01
struct mp_join {
nd_uint8_t kind;
nd_uint8_t len;
nd_uint8_t sub_b;
nd_uint8_t addr_id;
union {
struct {
nd_uint32_t token;
nd_uint32_t nonce;
} syn;
struct {
nd_uint64_t mac;
nd_uint32_t nonce;
} synack;
struct {
nd_byte mac[20];
} ack;
} u;
};
#define MP_JOIN_B 0x01
struct mp_dss {
nd_uint8_t kind;
nd_uint8_t len;
nd_uint8_t sub;
nd_uint8_t flags;
};
#define MP_DSS_F 0x10
#define MP_DSS_m 0x08
#define MP_DSS_M 0x04
#define MP_DSS_a 0x02
#define MP_DSS_A 0x01
static const struct tok mptcp_addr_subecho_bits[] = {
{ 0x6, "v0-ip6" },
{ 0x4, "v0-ip4" },
{ 0x1, "v1-echo" },
{ 0x0, "v1" },
{ 0, NULL }
};
struct mp_add_addr {
nd_uint8_t kind;
nd_uint8_t len;
nd_uint8_t sub_echo;
nd_uint8_t addr_id;
union {
struct {
nd_ipv4 addr;
nd_uint16_t port;
nd_uint64_t mac;
} v4;
struct {
nd_ipv4 addr;
nd_uint64_t mac;
} v4np;
struct {
nd_ipv6 addr;
nd_uint16_t port;
nd_uint64_t mac;
} v6;
struct {
nd_ipv6 addr;
nd_uint64_t mac;
} v6np;
} u;
};
struct mp_remove_addr {
nd_uint8_t kind;
nd_uint8_t len;
nd_uint8_t sub;
/* list of addr_id */
nd_uint8_t addrs_id[1];
};
struct mp_fail {
nd_uint8_t kind;
nd_uint8_t len;
nd_uint8_t sub;
nd_uint8_t resv;
nd_uint64_t data_seq;
};
struct mp_close {
nd_uint8_t kind;
nd_uint8_t len;
nd_uint8_t sub;
nd_uint8_t rsv;
nd_byte key[8];
};
struct mp_prio {
nd_uint8_t kind;
nd_uint8_t len;
nd_uint8_t sub_b;
nd_uint8_t addr_id;
};
#define MP_PRIO_B 0x01
static int
dummy_print(netdissect_options *ndo _U_,
const u_char *opt _U_, u_int opt_len _U_, u_char flags _U_)
{
return 1;
}
static int
mp_capable_print(netdissect_options *ndo,
const u_char *opt, u_int opt_len, u_char flags)
{
const struct mp_capable *mpc = (const struct mp_capable *) opt;
uint8_t version;
if (!((opt_len == 12 || opt_len == 4) && flags & TH_SYN) &&
!((opt_len == 20 || opt_len == 22) && (flags & (TH_SYN | TH_ACK)) ==
TH_ACK))
return 0;
version = MP_CAPABLE_OPT_VERSION(GET_U_1(mpc->sub_ver));
switch (version) {
case 0: /* fall through */
case 1:
ND_PRINT(" v%u", version);
break;
default:
ND_PRINT(" Unknown Version (%u)", version);
return 1;
}
if (GET_U_1(mpc->flags) & MP_CAPABLE_C)
ND_PRINT(" csum");
if (opt_len == 12 || opt_len >= 20) {
ND_PRINT(" {0x%" PRIx64, GET_BE_U_8(mpc->sender_key));
if (opt_len >= 20)
ND_PRINT(",0x%" PRIx64, GET_BE_U_8(mpc->receiver_key));
ND_PRINT("}");
}
return 1;
}
static int
mp_join_print(netdissect_options *ndo,
const u_char *opt, u_int opt_len, u_char flags)
{
const struct mp_join *mpj = (const struct mp_join *) opt;
if (!(opt_len == 12 && (flags & TH_SYN)) &&
!(opt_len == 16 && (flags & (TH_SYN | TH_ACK)) == (TH_SYN | TH_ACK)) &&
!(opt_len == 24 && (flags & TH_ACK)))
return 0;
if (opt_len != 24) {
if (GET_U_1(mpj->sub_b) & MP_JOIN_B)
ND_PRINT(" backup");
ND_PRINT(" id %u", GET_U_1(mpj->addr_id));
}
switch (opt_len) {
case 12: /* SYN */
ND_PRINT(" token 0x%x" " nonce 0x%x",
GET_BE_U_4(mpj->u.syn.token),
GET_BE_U_4(mpj->u.syn.nonce));
break;
case 16: /* SYN/ACK */
ND_PRINT(" hmac 0x%" PRIx64 " nonce 0x%x",
GET_BE_U_8(mpj->u.synack.mac),
GET_BE_U_4(mpj->u.synack.nonce));
break;
case 24: {/* ACK */
size_t i;
ND_PRINT(" hmac 0x");
for (i = 0; i < sizeof(mpj->u.ack.mac); ++i)
ND_PRINT("%02x", mpj->u.ack.mac[i]);
}
default:
break;
}
return 1;
}
static int
mp_dss_print(netdissect_options *ndo,
const u_char *opt, u_int opt_len, u_char flags)
{
const struct mp_dss *mdss = (const struct mp_dss *) opt;
uint8_t mdss_flags;
/* We need the flags, at a minimum. */
if (opt_len < 4)
return 0;
if (flags & TH_SYN)
return 0;
mdss_flags = GET_U_1(mdss->flags);
if (mdss_flags & MP_DSS_F)
ND_PRINT(" fin");
opt += 4;
opt_len -= 4;
if (mdss_flags & MP_DSS_A) {
/* Ack present */
ND_PRINT(" ack ");
/*
* If the a flag is set, we have an 8-byte ack; if it's
* clear, we have a 4-byte ack.
*/
if (mdss_flags & MP_DSS_a) {
if (opt_len < 8)
return 0;
ND_PRINT("%" PRIu64, GET_BE_U_8(opt));
opt += 8;
opt_len -= 8;
} else {
if (opt_len < 4)
return 0;
ND_PRINT("%u", GET_BE_U_4(opt));
opt += 4;
opt_len -= 4;
}
}
if (mdss_flags & MP_DSS_M) {
/*
* Data Sequence Number (DSN), Subflow Sequence Number (SSN),
* Data-Level Length present, and Checksum possibly present.
*/
ND_PRINT(" seq ");
/*
* If the m flag is set, we have an 8-byte NDS; if it's clear,
* we have a 4-byte DSN.
*/
if (mdss_flags & MP_DSS_m) {
if (opt_len < 8)
return 0;
ND_PRINT("%" PRIu64, GET_BE_U_8(opt));
opt += 8;
opt_len -= 8;
} else {
if (opt_len < 4)
return 0;
ND_PRINT("%u", GET_BE_U_4(opt));
opt += 4;
opt_len -= 4;
}
if (opt_len < 4)
return 0;
ND_PRINT(" subseq %u", GET_BE_U_4(opt));
opt += 4;
opt_len -= 4;
if (opt_len < 2)
return 0;
ND_PRINT(" len %u", GET_BE_U_2(opt));
opt += 2;
opt_len -= 2;
/*
* The Checksum is present only if negotiated.
* If there are at least 2 bytes left, process the next 2
* bytes as the Checksum.
*/
if (opt_len >= 2) {
ND_PRINT(" csum 0x%x", GET_BE_U_2(opt));
opt_len -= 2;
}
}
if (opt_len != 0)
return 0;
return 1;
}
static int
add_addr_print(netdissect_options *ndo,
const u_char *opt, u_int opt_len, u_char flags _U_)
{
const struct mp_add_addr *add_addr = (const struct mp_add_addr *) opt;
if (!(opt_len == 8 || opt_len == 10 || opt_len == 16 || opt_len == 18 ||
opt_len == 20 || opt_len == 22 || opt_len == 28 || opt_len == 30))
return 0;
ND_PRINT(" %s",
tok2str(mptcp_addr_subecho_bits, "[bad version/echo]",
GET_U_1(add_addr->sub_echo) & 0xF));
ND_PRINT(" id %u", GET_U_1(add_addr->addr_id));
if (opt_len == 8 || opt_len == 10 || opt_len == 16 || opt_len == 18) {
ND_PRINT(" %s", GET_IPADDR_STRING(add_addr->u.v4.addr));
if (opt_len == 10 || opt_len == 18)
ND_PRINT(":%u", GET_BE_U_2(add_addr->u.v4.port));
if (opt_len == 16)
ND_PRINT(" hmac 0x%" PRIx64, GET_BE_U_8(add_addr->u.v4np.mac));
if (opt_len == 18)
ND_PRINT(" hmac 0x%" PRIx64, GET_BE_U_8(add_addr->u.v4.mac));
}
if (opt_len == 20 || opt_len == 22 || opt_len == 28 || opt_len == 30) {
ND_PRINT(" %s", GET_IP6ADDR_STRING(add_addr->u.v6.addr));
if (opt_len == 22 || opt_len == 30)
ND_PRINT(":%u", GET_BE_U_2(add_addr->u.v6.port));
if (opt_len == 28)
ND_PRINT(" hmac 0x%" PRIx64, GET_BE_U_8(add_addr->u.v6np.mac));
if (opt_len == 30)
ND_PRINT(" hmac 0x%" PRIx64, GET_BE_U_8(add_addr->u.v6.mac));
}
return 1;
}
static int
remove_addr_print(netdissect_options *ndo,
const u_char *opt, u_int opt_len, u_char flags _U_)
{
const struct mp_remove_addr *remove_addr = (const struct mp_remove_addr *) opt;
u_int i;
if (opt_len < 4)
return 0;
opt_len -= 3;
ND_PRINT(" id");
for (i = 0; i < opt_len; i++)
ND_PRINT(" %u", GET_U_1(remove_addr->addrs_id[i]));
return 1;
}
static int
mp_prio_print(netdissect_options *ndo,
const u_char *opt, u_int opt_len, u_char flags _U_)
{
const struct mp_prio *mpp = (const struct mp_prio *) opt;
if (opt_len != 3 && opt_len != 4)
return 0;
if (GET_U_1(mpp->sub_b) & MP_PRIO_B)
ND_PRINT(" backup");
else
ND_PRINT(" non-backup");
if (opt_len == 4)
ND_PRINT(" id %u", GET_U_1(mpp->addr_id));
return 1;
}
static int
mp_fail_print(netdissect_options *ndo,
const u_char *opt, u_int opt_len, u_char flags _U_)
{
if (opt_len != 12)
return 0;
ND_PRINT(" seq %" PRIu64, GET_BE_U_8(opt + 4));
return 1;
}
static int
mp_fast_close_print(netdissect_options *ndo,
const u_char *opt, u_int opt_len, u_char flags _U_)
{
if (opt_len != 12)
return 0;
ND_PRINT(" key 0x%" PRIx64, GET_BE_U_8(opt + 4));
return 1;
}
static const struct {
const char *name;
int (*print)(netdissect_options *, const u_char *, u_int, u_char);
} mptcp_options[] = {
{ "capable", mp_capable_print },
{ "join", mp_join_print },
{ "dss", mp_dss_print },
{ "add-addr", add_addr_print },
{ "rem-addr", remove_addr_print },
{ "prio", mp_prio_print },
{ "fail", mp_fail_print },
{ "fast-close", mp_fast_close_print },
{ "unknown", dummy_print },
};
int
mptcp_print(netdissect_options *ndo,
const u_char *cp, u_int len, u_char flags)
{
const struct mptcp_option *opt;
u_int subtype;
ndo->ndo_protocol = "mptcp";
if (len < 3)
return 0;
opt = (const struct mptcp_option *) cp;
subtype = MPTCP_OPT_SUBTYPE(GET_U_1(opt->sub_etc));
subtype = ND_MIN(subtype, MPTCP_SUB_FCLOSE + 1);
ND_PRINT(" %u", len);
ND_PRINT(" %s", mptcp_options[subtype].name);
return mptcp_options[subtype].print(ndo, cp, len, flags);
}
diff --git a/contrib/tcpdump/print-msdp.c b/contrib/tcpdump/print-msdp.c
index 7845116bdc7e..61a332d9d6bd 100644
--- a/contrib/tcpdump/print-msdp.c
+++ b/contrib/tcpdump/print-msdp.c
@@ -1,97 +1,95 @@
/*
* Copyright (c) 2001 William C. Fenner.
* 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, 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.
* The name of William C. Fenner may not 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.
*/
/* \summary: Multicast Source Discovery Protocol (MSDP) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#define MSDP_TYPE_MAX 7
void
msdp_print(netdissect_options *ndo, const u_char *sp, u_int length)
{
unsigned int type, len;
ndo->ndo_protocol = "msdp";
ND_PRINT(": ");
nd_print_protocol(ndo);
/* See if we think we're at the beginning of a compound packet */
type = GET_U_1(sp);
len = GET_BE_U_2(sp + 1);
if (len > 1500 || len < 3 || type == 0 || type > MSDP_TYPE_MAX)
goto trunc; /* not really truncated, but still not decodable */
while (length != 0) {
type = GET_U_1(sp);
len = GET_BE_U_2(sp + 1);
if (len > 1400 || ndo->ndo_vflag)
ND_PRINT(" [len %u]", len);
if (len < 3)
goto trunc;
if (length < len)
goto trunc;
sp += 3;
length -= 3;
switch (type) {
case 1: /* IPv4 Source-Active */
case 3: /* IPv4 Source-Active Response */
if (type == 1)
ND_PRINT(" SA");
else
ND_PRINT(" SA-Response");
ND_PRINT(" %u entries", GET_U_1(sp));
if ((u_int)((GET_U_1(sp) * 12) + 8) < len) {
ND_PRINT(" [w/data]");
if (ndo->ndo_vflag > 1) {
ND_PRINT(" ");
ip_print(ndo, sp +
GET_U_1(sp) * 12 + 8 - 3,
len - (GET_U_1(sp) * 12 + 8));
}
}
break;
case 2:
ND_PRINT(" SA-Request");
ND_PRINT(" for %s", GET_IPADDR_STRING(sp + 1));
break;
case 4:
ND_PRINT(" Keepalive");
if (len != 3)
ND_PRINT("[len=%u] ", len);
break;
case 5:
ND_PRINT(" Notification");
break;
default:
ND_PRINT(" [type=%u len=%u]", type, len);
break;
}
sp += (len - 3);
length -= (len - 3);
}
return;
trunc:
nd_print_trunc(ndo);
}
diff --git a/contrib/tcpdump/print-msnlb.c b/contrib/tcpdump/print-msnlb.c
index 8afaa7fe7107..4e242df652cc 100644
--- a/contrib/tcpdump/print-msnlb.c
+++ b/contrib/tcpdump/print-msnlb.c
@@ -1,62 +1,60 @@
/*
* Copyright (c) 2013 Romain Francoise <romain@orebokech.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* \summary: MS Network Load Balancing's (NLB) heartbeat printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
struct msnlb_heartbeat_pkt {
nd_byte unknown1[4];
nd_byte unknown2[4];
nd_uint32_t host_prio; /* little-endian */
nd_ipv4 virtual_ip;
nd_ipv4 host_ip;
/* the protocol is undocumented so we ignore the rest */
};
void
msnlb_print(netdissect_options *ndo, const u_char *bp)
{
const struct msnlb_heartbeat_pkt *hb;
ndo->ndo_protocol = "msnlb";
hb = (const struct msnlb_heartbeat_pkt *)bp;
ND_PRINT("MS NLB heartbeat");
ND_PRINT(", host priority: %u", GET_LE_U_4((hb->host_prio)));
ND_PRINT(", cluster IP: %s", GET_IPADDR_STRING(hb->virtual_ip));
ND_PRINT(", host IP: %s", GET_IPADDR_STRING(hb->host_ip));
}
diff --git a/contrib/tcpdump/print-nflog.c b/contrib/tcpdump/print-nflog.c
index 1e75561b967d..a5f7a823489f 100644
--- a/contrib/tcpdump/print-nflog.c
+++ b/contrib/tcpdump/print-nflog.c
@@ -1,231 +1,239 @@
/*
* Copyright (c) 2013, Petar Alilovic,
* Faculty of Electrical Engineering and Computing, University of Zagreb
* All rights reserved
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
/* \summary: DLT_NFLOG printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "extract.h"
#ifdef DLT_NFLOG
/*
* Structure of an NFLOG header and TLV parts, as described at
* https://www.tcpdump.org/linktypes/LINKTYPE_NFLOG.html
*
* The NFLOG header is big-endian.
*
* The TLV length and type are in host byte order. The value is either
* big-endian or is an array of bytes in some externally-specified byte
* order (text string, link-layer address, link-layer header, packet
* data, etc.).
*/
typedef struct nflog_hdr {
nd_uint8_t nflog_family; /* address family */
nd_uint8_t nflog_version; /* version */
nd_uint16_t nflog_rid; /* resource ID */
} nflog_hdr_t;
#define NFLOG_HDR_LEN sizeof(nflog_hdr_t)
typedef struct nflog_tlv {
nd_uint16_t tlv_length; /* tlv length */
nd_uint16_t tlv_type; /* tlv type */
/* value follows this */
} nflog_tlv_t;
#define NFLOG_TLV_LEN sizeof(nflog_tlv_t)
typedef struct nflog_packet_hdr {
nd_uint16_t hw_protocol; /* hw protocol */
nd_uint8_t hook; /* netfilter hook */
nd_byte pad[1]; /* padding to 32 bits */
} nflog_packet_hdr_t;
typedef struct nflog_hwaddr {
nd_uint16_t hw_addrlen; /* address length */
nd_byte pad[2]; /* padding to 32-bit boundary */
nd_byte hw_addr[8]; /* address, up to 8 bytes */
} nflog_hwaddr_t;
typedef struct nflog_timestamp {
nd_uint64_t sec;
nd_uint64_t usec;
} nflog_timestamp_t;
/*
* TLV types.
*/
#define NFULA_PACKET_HDR 1 /* nflog_packet_hdr_t */
#define NFULA_MARK 2 /* packet mark from skbuff */
#define NFULA_TIMESTAMP 3 /* nflog_timestamp_t for skbuff's time stamp */
#define NFULA_IFINDEX_INDEV 4 /* ifindex of device on which packet received (possibly bridge group) */
#define NFULA_IFINDEX_OUTDEV 5 /* ifindex of device on which packet transmitted (possibly bridge group) */
#define NFULA_IFINDEX_PHYSINDEV 6 /* ifindex of physical device on which packet received (not bridge group) */
#define NFULA_IFINDEX_PHYSOUTDEV 7 /* ifindex of physical device on which packet transmitted (not bridge group) */
#define NFULA_HWADDR 8 /* nflog_hwaddr_t for hardware address */
#define NFULA_PAYLOAD 9 /* packet payload */
#define NFULA_PREFIX 10 /* text string - null-terminated, count includes NUL */
#define NFULA_UID 11 /* UID owning socket on which packet was sent/received */
#define NFULA_SEQ 12 /* sequence number of packets on this NFLOG socket */
-#define NFULA_SEQ_GLOBAL 13 /* sequence number of pakets on all NFLOG sockets */
+#define NFULA_SEQ_GLOBAL 13 /* sequence number of packets on all NFLOG sockets */
#define NFULA_GID 14 /* GID owning socket on which packet was sent/received */
#define NFULA_HWTYPE 15 /* ARPHRD_ type of skbuff's device */
#define NFULA_HWHEADER 16 /* skbuff's MAC-layer header */
#define NFULA_HWLEN 17 /* length of skbuff's MAC-layer header */
+/*
+ * Define two constants specifically for the two AF code points from the
+ * LINKTYPE_NFLOG specification above and use these constants instead of
+ * AF_INET and AF_INET6. This is the only way to dissect the "wire" encoding
+ * correctly because some BSD systems define AF_INET6 differently from Linux
+ * (see af.h) and Haiku defines both AF_INET and AF_INET6 differently from
+ * Linux.
+ */
+#define NFLOG_AF_INET 2
+#define NFLOG_AF_INET6 10
static const struct tok nflog_values[] = {
- { AF_INET, "IPv4" },
- { AF_INET6, "IPv6" },
+ { NFLOG_AF_INET, "IPv4" },
+ { NFLOG_AF_INET6, "IPv6" },
{ 0, NULL }
};
static void
nflog_hdr_print(netdissect_options *ndo, const nflog_hdr_t *hdr, u_int length)
{
ND_PRINT("version %u, resource ID %u",
GET_U_1(hdr->nflog_version), GET_BE_U_2(hdr->nflog_rid));
if (!ndo->ndo_qflag) {
ND_PRINT(", family %s (%u)",
tok2str(nflog_values, "Unknown",
GET_U_1(hdr->nflog_family)),
GET_U_1(hdr->nflog_family));
} else {
ND_PRINT(", %s",
tok2str(nflog_values,
"Unknown NFLOG (0x%02x)",
GET_U_1(hdr->nflog_family)));
}
ND_PRINT(", length %u: ", length);
}
void
nflog_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h, const u_char *p)
{
const nflog_hdr_t *hdr = (const nflog_hdr_t *)p;
uint16_t size;
uint16_t h_size = NFLOG_HDR_LEN;
u_int caplen = h->caplen;
u_int length = h->len;
ndo->ndo_protocol = "nflog";
if (caplen < NFLOG_HDR_LEN) {
nd_print_trunc(ndo);
ndo->ndo_ll_hdr_len += caplen;
return;
}
ndo->ndo_ll_hdr_len += NFLOG_HDR_LEN;
ND_TCHECK_SIZE(hdr);
if (GET_U_1(hdr->nflog_version) != 0) {
ND_PRINT("version %u (unknown)", GET_U_1(hdr->nflog_version));
return;
}
if (ndo->ndo_eflag)
nflog_hdr_print(ndo, hdr, length);
p += NFLOG_HDR_LEN;
length -= NFLOG_HDR_LEN;
caplen -= NFLOG_HDR_LEN;
while (length > 0) {
const nflog_tlv_t *tlv;
/* We have some data. Do we have enough for the TLV header? */
if (caplen < NFLOG_TLV_LEN)
goto trunc; /* No. */
tlv = (const nflog_tlv_t *) p;
ND_TCHECK_SIZE(tlv);
size = GET_HE_U_2(tlv->tlv_length);
if (size % 4 != 0)
size += 4 - size % 4;
/* Is the TLV's length less than the minimum? */
if (size < NFLOG_TLV_LEN)
goto trunc; /* Yes. Give up now. */
/* Do we have enough data for the full TLV? */
if (caplen < size)
goto trunc; /* No. */
if (GET_HE_U_2(tlv->tlv_type) == NFULA_PAYLOAD) {
/*
* This TLV's data is the packet payload.
* Skip past the TLV header, and break out
* of the loop so we print the packet data.
*/
p += NFLOG_TLV_LEN;
h_size += NFLOG_TLV_LEN;
length -= NFLOG_TLV_LEN;
caplen -= NFLOG_TLV_LEN;
break;
}
p += size;
h_size += size;
length -= size;
caplen -= size;
}
switch (GET_U_1(hdr->nflog_family)) {
- case AF_INET:
+ case NFLOG_AF_INET:
ip_print(ndo, p, length);
break;
- case AF_INET6:
+ case NFLOG_AF_INET6:
ip6_print(ndo, p, length);
break;
default:
if (!ndo->ndo_eflag)
nflog_hdr_print(ndo, hdr,
length + NFLOG_HDR_LEN);
if (!ndo->ndo_suppress_default_print)
ND_DEFAULTPRINT(p, caplen);
break;
}
ndo->ndo_ll_hdr_len += h_size - NFLOG_HDR_LEN;
return;
trunc:
nd_print_trunc(ndo);
ndo->ndo_ll_hdr_len += h_size - NFLOG_HDR_LEN;
}
#endif /* DLT_NFLOG */
diff --git a/contrib/tcpdump/print-nfs.c b/contrib/tcpdump/print-nfs.c
index af1b274f5f74..b67ec370ed67 100644
--- a/contrib/tcpdump/print-nfs.c
+++ b/contrib/tcpdump/print-nfs.c
@@ -1,1850 +1,1859 @@
/*
* Copyright (c) 1988, 1989, 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.
*/
/* \summary: Network File System (NFS) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#include "nfs.h"
#include "nfsfh.h"
#include "ip.h"
#include "ip6.h"
#include "rpc_auth.h"
#include "rpc_msg.h"
static void nfs_printfh(netdissect_options *, const uint32_t *, const u_int);
static int xid_map_enter(netdissect_options *, const struct sunrpc_msg *, const u_char *);
static int xid_map_find(netdissect_options *, const struct sunrpc_msg *, const u_char *, uint32_t *, uint32_t *);
static void interp_reply(netdissect_options *, const struct sunrpc_msg *, uint32_t, uint32_t, int);
static const uint32_t *parse_post_op_attr(netdissect_options *, const uint32_t *, int);
/*
* Mapping of old NFS Version 2 RPC numbers to generic numbers.
*/
static uint32_t nfsv3_procid[NFS_NPROCS] = {
NFSPROC_NULL,
NFSPROC_GETATTR,
NFSPROC_SETATTR,
NFSPROC_NOOP,
NFSPROC_LOOKUP,
NFSPROC_READLINK,
NFSPROC_READ,
NFSPROC_NOOP,
NFSPROC_WRITE,
NFSPROC_CREATE,
NFSPROC_REMOVE,
NFSPROC_RENAME,
NFSPROC_LINK,
NFSPROC_SYMLINK,
NFSPROC_MKDIR,
NFSPROC_RMDIR,
NFSPROC_READDIR,
NFSPROC_FSSTAT,
NFSPROC_NOOP,
NFSPROC_NOOP,
NFSPROC_NOOP,
NFSPROC_NOOP,
NFSPROC_NOOP,
NFSPROC_NOOP,
NFSPROC_NOOP,
NFSPROC_NOOP
};
static const struct tok nfsproc_str[] = {
{ NFSPROC_NOOP, "nop" },
{ NFSPROC_NULL, "null" },
{ NFSPROC_GETATTR, "getattr" },
{ NFSPROC_SETATTR, "setattr" },
{ NFSPROC_LOOKUP, "lookup" },
{ NFSPROC_ACCESS, "access" },
{ NFSPROC_READLINK, "readlink" },
{ NFSPROC_READ, "read" },
{ NFSPROC_WRITE, "write" },
{ NFSPROC_CREATE, "create" },
{ NFSPROC_MKDIR, "mkdir" },
{ NFSPROC_SYMLINK, "symlink" },
{ NFSPROC_MKNOD, "mknod" },
{ NFSPROC_REMOVE, "remove" },
{ NFSPROC_RMDIR, "rmdir" },
{ NFSPROC_RENAME, "rename" },
{ NFSPROC_LINK, "link" },
{ NFSPROC_READDIR, "readdir" },
{ NFSPROC_READDIRPLUS, "readdirplus" },
{ NFSPROC_FSSTAT, "fsstat" },
{ NFSPROC_FSINFO, "fsinfo" },
{ NFSPROC_PATHCONF, "pathconf" },
{ NFSPROC_COMMIT, "commit" },
{ 0, NULL }
};
/*
* NFS V2 and V3 status values.
*
* Some of these come from the RFCs for NFS V2 and V3, with the message
* strings taken from the FreeBSD C library "errlst.c".
*
* Others are errors that are not in the RFC but that I suspect some
* NFS servers could return; the values are FreeBSD errno values, as
* the first NFS server was the SunOS 2.0 one, and until 5.0 SunOS
* was primarily BSD-derived.
*/
static const struct tok status2str[] = {
{ 1, "Operation not permitted" }, /* EPERM */
{ 2, "No such file or directory" }, /* ENOENT */
{ 5, "Input/output error" }, /* EIO */
{ 6, "Device not configured" }, /* ENXIO */
{ 11, "Resource deadlock avoided" }, /* EDEADLK */
{ 12, "Cannot allocate memory" }, /* ENOMEM */
{ 13, "Permission denied" }, /* EACCES */
{ 17, "File exists" }, /* EEXIST */
{ 18, "Cross-device link" }, /* EXDEV */
{ 19, "Operation not supported by device" }, /* ENODEV */
{ 20, "Not a directory" }, /* ENOTDIR */
{ 21, "Is a directory" }, /* EISDIR */
{ 22, "Invalid argument" }, /* EINVAL */
{ 26, "Text file busy" }, /* ETXTBSY */
{ 27, "File too large" }, /* EFBIG */
{ 28, "No space left on device" }, /* ENOSPC */
{ 30, "Read-only file system" }, /* EROFS */
{ 31, "Too many links" }, /* EMLINK */
{ 45, "Operation not supported" }, /* EOPNOTSUPP */
{ 62, "Too many levels of symbolic links" }, /* ELOOP */
{ 63, "File name too long" }, /* ENAMETOOLONG */
{ 66, "Directory not empty" }, /* ENOTEMPTY */
{ 69, "Disc quota exceeded" }, /* EDQUOT */
{ 70, "Stale NFS file handle" }, /* ESTALE */
{ 71, "Too many levels of remote in path" }, /* EREMOTE */
{ 99, "Write cache flushed to disk" }, /* NFSERR_WFLUSH (not used) */
{ 10001, "Illegal NFS file handle" }, /* NFS3ERR_BADHANDLE */
{ 10002, "Update synchronization mismatch" }, /* NFS3ERR_NOT_SYNC */
{ 10003, "READDIR/READDIRPLUS cookie is stale" }, /* NFS3ERR_BAD_COOKIE */
{ 10004, "Operation not supported" }, /* NFS3ERR_NOTSUPP */
{ 10005, "Buffer or request is too small" }, /* NFS3ERR_TOOSMALL */
{ 10006, "Unspecified error on server" }, /* NFS3ERR_SERVERFAULT */
{ 10007, "Object of that type not supported" }, /* NFS3ERR_BADTYPE */
{ 10008, "Request couldn't be completed in time" }, /* NFS3ERR_JUKEBOX */
{ 0, NULL }
};
static const struct tok nfsv3_writemodes[] = {
{ 0, "unstable" },
{ 1, "datasync" },
{ 2, "filesync" },
{ 0, NULL }
};
static const struct tok type2str[] = {
{ NFNON, "NON" },
{ NFREG, "REG" },
{ NFDIR, "DIR" },
{ NFBLK, "BLK" },
{ NFCHR, "CHR" },
{ NFLNK, "LNK" },
{ NFFIFO, "FIFO" },
{ 0, NULL }
};
static const struct tok sunrpc_auth_str[] = {
{ SUNRPC_AUTH_OK, "OK" },
{ SUNRPC_AUTH_BADCRED, "Bogus Credentials (seal broken)" },
{ SUNRPC_AUTH_REJECTEDCRED, "Rejected Credentials (client should begin new session)" },
{ SUNRPC_AUTH_BADVERF, "Bogus Verifier (seal broken)" },
{ SUNRPC_AUTH_REJECTEDVERF, "Verifier expired or was replayed" },
{ SUNRPC_AUTH_TOOWEAK, "Credentials are too weak" },
{ SUNRPC_AUTH_INVALIDRESP, "Bogus response verifier" },
{ SUNRPC_AUTH_FAILED, "Unknown failure" },
{ 0, NULL }
};
static const struct tok sunrpc_str[] = {
{ SUNRPC_PROG_UNAVAIL, "PROG_UNAVAIL" },
{ SUNRPC_PROG_MISMATCH, "PROG_MISMATCH" },
{ SUNRPC_PROC_UNAVAIL, "PROC_UNAVAIL" },
{ SUNRPC_GARBAGE_ARGS, "GARBAGE_ARGS" },
{ SUNRPC_SYSTEM_ERR, "SYSTEM_ERR" },
{ 0, NULL }
};
static void
-print_nfsaddr(netdissect_options *ndo,
+nfsaddr_print(netdissect_options *ndo,
const u_char *bp, const char *s, const char *d)
{
const struct ip *ip;
const struct ip6_hdr *ip6;
char srcaddr[INET6_ADDRSTRLEN], dstaddr[INET6_ADDRSTRLEN];
srcaddr[0] = dstaddr[0] = '\0';
switch (IP_V((const struct ip *)bp)) {
case 4:
ip = (const struct ip *)bp;
strlcpy(srcaddr, GET_IPADDR_STRING(ip->ip_src), sizeof(srcaddr));
strlcpy(dstaddr, GET_IPADDR_STRING(ip->ip_dst), sizeof(dstaddr));
break;
case 6:
ip6 = (const struct ip6_hdr *)bp;
strlcpy(srcaddr, GET_IP6ADDR_STRING(ip6->ip6_src),
sizeof(srcaddr));
strlcpy(dstaddr, GET_IP6ADDR_STRING(ip6->ip6_dst),
sizeof(dstaddr));
break;
default:
strlcpy(srcaddr, "?", sizeof(srcaddr));
strlcpy(dstaddr, "?", sizeof(dstaddr));
break;
}
ND_PRINT("%s.%s > %s.%s: ", srcaddr, s, dstaddr, d);
}
/*
* NFS Version 3 sattr3 structure for the new node creation case.
* This does not have a fixed layout on the network, so this
* structure does not correspond to the layout of the data on
* the network; it's used to store the data when the sattr3
* is parsed for use when it's later printed.
*/
struct nfsv3_sattr {
uint32_t sa_modeset;
uint32_t sa_mode;
uint32_t sa_uidset;
uint32_t sa_uid;
uint32_t sa_gidset;
uint32_t sa_gid;
uint32_t sa_sizeset;
uint32_t sa_size;
uint32_t sa_atimetype;
struct {
uint32_t nfsv3_sec;
uint32_t nfsv3_nsec;
} sa_atime;
uint32_t sa_mtimetype;
struct {
uint32_t nfsv3_sec;
uint32_t nfsv3_nsec;
} sa_mtime;
};
static const uint32_t *
parse_sattr3(netdissect_options *ndo,
const uint32_t *dp, struct nfsv3_sattr *sa3)
{
sa3->sa_modeset = GET_BE_U_4(dp);
dp++;
if (sa3->sa_modeset) {
sa3->sa_mode = GET_BE_U_4(dp);
dp++;
}
sa3->sa_uidset = GET_BE_U_4(dp);
dp++;
if (sa3->sa_uidset) {
sa3->sa_uid = GET_BE_U_4(dp);
dp++;
}
sa3->sa_gidset = GET_BE_U_4(dp);
dp++;
if (sa3->sa_gidset) {
sa3->sa_gid = GET_BE_U_4(dp);
dp++;
}
sa3->sa_sizeset = GET_BE_U_4(dp);
dp++;
if (sa3->sa_sizeset) {
sa3->sa_size = GET_BE_U_4(dp);
dp++;
}
sa3->sa_atimetype = GET_BE_U_4(dp);
dp++;
if (sa3->sa_atimetype == NFSV3SATTRTIME_TOCLIENT) {
sa3->sa_atime.nfsv3_sec = GET_BE_U_4(dp);
dp++;
sa3->sa_atime.nfsv3_nsec = GET_BE_U_4(dp);
dp++;
}
sa3->sa_mtimetype = GET_BE_U_4(dp);
dp++;
if (sa3->sa_mtimetype == NFSV3SATTRTIME_TOCLIENT) {
sa3->sa_mtime.nfsv3_sec = GET_BE_U_4(dp);
dp++;
sa3->sa_mtime.nfsv3_nsec = GET_BE_U_4(dp);
dp++;
}
return dp;
}
static void
print_sattr3(netdissect_options *ndo,
const struct nfsv3_sattr *sa3, int verbose)
{
if (sa3->sa_modeset)
ND_PRINT(" mode %o", sa3->sa_mode);
if (sa3->sa_uidset)
ND_PRINT(" uid %u", sa3->sa_uid);
if (sa3->sa_gidset)
ND_PRINT(" gid %u", sa3->sa_gid);
if (verbose > 1) {
if (sa3->sa_atimetype == NFSV3SATTRTIME_TOCLIENT)
ND_PRINT(" atime %u.%06u", sa3->sa_atime.nfsv3_sec,
sa3->sa_atime.nfsv3_nsec);
if (sa3->sa_mtimetype == NFSV3SATTRTIME_TOCLIENT)
ND_PRINT(" mtime %u.%06u", sa3->sa_mtime.nfsv3_sec,
sa3->sa_mtime.nfsv3_nsec);
}
}
void
nfsreply_print(netdissect_options *ndo,
const u_char *bp, u_int length,
const u_char *bp2)
{
const struct sunrpc_msg *rp;
char srcid[20], dstid[20]; /*fits 32bit*/
ndo->ndo_protocol = "nfs";
rp = (const struct sunrpc_msg *)bp;
if (!ndo->ndo_nflag) {
strlcpy(srcid, "nfs", sizeof(srcid));
snprintf(dstid, sizeof(dstid), "%u",
GET_BE_U_4(rp->rm_xid));
} else {
snprintf(srcid, sizeof(srcid), "%u", NFS_PORT);
snprintf(dstid, sizeof(dstid), "%u",
GET_BE_U_4(rp->rm_xid));
}
- print_nfsaddr(ndo, bp2, srcid, dstid);
+ nfsaddr_print(ndo, bp2, srcid, dstid);
nfsreply_noaddr_print(ndo, bp, length, bp2);
}
void
nfsreply_noaddr_print(netdissect_options *ndo,
const u_char *bp, u_int length,
const u_char *bp2)
{
const struct sunrpc_msg *rp;
uint32_t proc, vers, reply_stat;
enum sunrpc_reject_stat rstat;
uint32_t rlow;
uint32_t rhigh;
enum sunrpc_auth_stat rwhy;
ndo->ndo_protocol = "nfs";
rp = (const struct sunrpc_msg *)bp;
ND_TCHECK_4(rp->rm_reply.rp_stat);
reply_stat = GET_BE_U_4(&rp->rm_reply.rp_stat);
switch (reply_stat) {
case SUNRPC_MSG_ACCEPTED:
ND_PRINT("reply ok %u", length);
if (xid_map_find(ndo, rp, bp2, &proc, &vers) >= 0)
interp_reply(ndo, rp, proc, vers, length);
break;
case SUNRPC_MSG_DENIED:
ND_PRINT("reply ERR %u: ", length);
ND_TCHECK_4(rp->rm_reply.rp_reject.rj_stat);
rstat = GET_BE_U_4(&rp->rm_reply.rp_reject.rj_stat);
switch (rstat) {
case SUNRPC_RPC_MISMATCH:
ND_TCHECK_4(rp->rm_reply.rp_reject.rj_vers.high);
rlow = GET_BE_U_4(&rp->rm_reply.rp_reject.rj_vers.low);
rhigh = GET_BE_U_4(&rp->rm_reply.rp_reject.rj_vers.high);
ND_PRINT("RPC Version mismatch (%u-%u)", rlow, rhigh);
break;
case SUNRPC_AUTH_ERROR:
ND_TCHECK_4(rp->rm_reply.rp_reject.rj_why);
rwhy = GET_BE_U_4(&rp->rm_reply.rp_reject.rj_why);
ND_PRINT("Auth %s", tok2str(sunrpc_auth_str, "Invalid failure code %u", rwhy));
break;
default:
ND_PRINT("Unknown reason for rejecting rpc message %u", (unsigned int)rstat);
break;
}
break;
default:
ND_PRINT("reply Unknown rpc response code=%u %u", reply_stat, length);
break;
}
return;
trunc:
nd_print_trunc(ndo);
}
/*
* Return a pointer to the first file handle in the packet.
* If the packet was truncated, return 0.
*/
static const uint32_t *
parsereq(netdissect_options *ndo,
const struct sunrpc_msg *rp, u_int length)
{
const uint32_t *dp;
u_int len, rounded_len;
/*
* Find the start of the req data (if we captured it).
* First, get the length of the credentials, and make sure
* we have all of the opaque part of the credentials.
*/
dp = (const uint32_t *)&rp->rm_call.cb_cred;
if (length < 2 * sizeof(*dp))
goto trunc;
len = GET_BE_U_4(dp + 1);
+ if (len > length) {
+ ND_PRINT(" [credentials length %u > %u]", len, length);
+ nd_print_invalid(ndo);
+ return NULL;
+ }
rounded_len = roundup2(len, 4);
ND_TCHECK_LEN(dp + 2, rounded_len);
if (2 * sizeof(*dp) + rounded_len <= length) {
/*
* We have all of the credentials. Skip past them; they
* consist of 4 bytes of flavor, 4 bytes of length,
* and len-rounded-up-to-a-multiple-of-4 bytes of
* data.
*/
dp += (len + (2 * sizeof(*dp) + 3)) / sizeof(*dp);
length -= 2 * sizeof(*dp) + rounded_len;
/*
* Now get the length of the verifier, and make sure
* we have all of the opaque part of the verifier.
*/
if (length < 2 * sizeof(*dp))
goto trunc;
len = GET_BE_U_4(dp + 1);
+ if (len > length) {
+ ND_PRINT(" [verifier length %u > %u]", len, length);
+ nd_print_invalid(ndo);
+ return NULL;
+ }
rounded_len = roundup2(len, 4);
ND_TCHECK_LEN(dp + 2, rounded_len);
if (2 * sizeof(*dp) + rounded_len < length) {
/*
* We have all of the verifier. Skip past it;
* it consists of 4 bytes of flavor, 4 bytes of
* length, and len-rounded-up-to-a-multiple-of-4
* bytes of data.
*/
dp += (len + (2 * sizeof(*dp) + 3)) / sizeof(*dp);
return (dp);
}
}
trunc:
return (NULL);
}
/*
* Print out an NFS file handle and return a pointer to following word.
* If packet was truncated, return 0.
*/
static const uint32_t *
parsefh(netdissect_options *ndo,
const uint32_t *dp, int v3)
{
u_int len;
if (v3) {
len = GET_BE_U_4(dp) / 4;
dp++;
} else
len = NFSX_V2FH / 4;
if (ND_TTEST_LEN(dp, len * sizeof(*dp))) {
nfs_printfh(ndo, dp, len);
return (dp + len);
} else
return NULL;
}
/*
* Print out a file name and return pointer to 32-bit word past it.
* If packet was truncated, return 0.
*/
static const uint32_t *
parsefn(netdissect_options *ndo,
const uint32_t *dp)
{
uint32_t len, rounded_len;
const u_char *cp;
/* Fetch big-endian string length */
len = GET_BE_U_4(dp);
dp++;
if (UINT_MAX - len < 3) {
ND_PRINT("[cannot pad to 32-bit boundaries]");
nd_print_invalid(ndo);
return NULL;
}
rounded_len = roundup2(len, 4);
ND_TCHECK_LEN(dp, rounded_len);
cp = (const u_char *)dp;
/* Update 32-bit pointer (NFS filenames padded to 32-bit boundaries) */
dp += rounded_len / sizeof(*dp);
ND_PRINT("\"");
if (nd_printn(ndo, cp, len, ndo->ndo_snapend)) {
ND_PRINT("\"");
goto trunc;
}
ND_PRINT("\"");
return (dp);
trunc:
return NULL;
}
/*
* Print out file handle and file name.
* Return pointer to 32-bit word past file name.
* If packet was truncated (or there was some other error), return 0.
*/
static const uint32_t *
parsefhn(netdissect_options *ndo,
const uint32_t *dp, int v3)
{
dp = parsefh(ndo, dp, v3);
if (dp == NULL)
return (NULL);
ND_PRINT(" ");
return (parsefn(ndo, dp));
}
void
nfsreq_noaddr_print(netdissect_options *ndo,
const u_char *bp, u_int length,
const u_char *bp2)
{
const struct sunrpc_msg *rp;
const uint32_t *dp;
nfs_type type;
int v3;
uint32_t proc;
uint32_t access_flags;
struct nfsv3_sattr sa3;
ndo->ndo_protocol = "nfs";
ND_PRINT("%u", length);
rp = (const struct sunrpc_msg *)bp;
if (!xid_map_enter(ndo, rp, bp2)) /* record proc number for later on */
goto trunc;
v3 = (GET_BE_U_4(&rp->rm_call.cb_vers) == NFS_VER3);
proc = GET_BE_U_4(&rp->rm_call.cb_proc);
if (!v3 && proc < NFS_NPROCS)
proc = nfsv3_procid[proc];
ND_PRINT(" %s", tok2str(nfsproc_str, "proc-%u", proc));
switch (proc) {
case NFSPROC_GETATTR:
case NFSPROC_SETATTR:
case NFSPROC_READLINK:
case NFSPROC_FSSTAT:
case NFSPROC_FSINFO:
case NFSPROC_PATHCONF:
dp = parsereq(ndo, rp, length);
if (dp == NULL)
goto trunc;
if (parsefh(ndo, dp, v3) == NULL)
goto trunc;
break;
case NFSPROC_LOOKUP:
case NFSPROC_CREATE:
case NFSPROC_MKDIR:
case NFSPROC_REMOVE:
case NFSPROC_RMDIR:
dp = parsereq(ndo, rp, length);
if (dp == NULL)
goto trunc;
if (parsefhn(ndo, dp, v3) == NULL)
goto trunc;
break;
case NFSPROC_ACCESS:
dp = parsereq(ndo, rp, length);
if (dp == NULL)
goto trunc;
dp = parsefh(ndo, dp, v3);
if (dp == NULL)
goto trunc;
access_flags = GET_BE_U_4(dp);
if (access_flags & ~NFSV3ACCESS_FULL) {
/* NFSV3ACCESS definitions aren't up to date */
ND_PRINT(" %04x", access_flags);
} else if ((access_flags & NFSV3ACCESS_FULL) == NFSV3ACCESS_FULL) {
ND_PRINT(" NFS_ACCESS_FULL");
} else {
char separator = ' ';
if (access_flags & NFSV3ACCESS_READ) {
ND_PRINT(" NFS_ACCESS_READ");
separator = '|';
}
if (access_flags & NFSV3ACCESS_LOOKUP) {
ND_PRINT("%cNFS_ACCESS_LOOKUP", separator);
separator = '|';
}
if (access_flags & NFSV3ACCESS_MODIFY) {
ND_PRINT("%cNFS_ACCESS_MODIFY", separator);
separator = '|';
}
if (access_flags & NFSV3ACCESS_EXTEND) {
ND_PRINT("%cNFS_ACCESS_EXTEND", separator);
separator = '|';
}
if (access_flags & NFSV3ACCESS_DELETE) {
ND_PRINT("%cNFS_ACCESS_DELETE", separator);
separator = '|';
}
if (access_flags & NFSV3ACCESS_EXECUTE)
ND_PRINT("%cNFS_ACCESS_EXECUTE", separator);
}
break;
case NFSPROC_READ:
dp = parsereq(ndo, rp, length);
if (dp == NULL)
goto trunc;
dp = parsefh(ndo, dp, v3);
if (dp == NULL)
goto trunc;
if (v3) {
ND_PRINT(" %u bytes @ %" PRIu64,
GET_BE_U_4(dp + 2),
GET_BE_U_8(dp));
} else {
ND_PRINT(" %u bytes @ %u",
GET_BE_U_4(dp + 1),
GET_BE_U_4(dp));
}
break;
case NFSPROC_WRITE:
dp = parsereq(ndo, rp, length);
if (dp == NULL)
goto trunc;
dp = parsefh(ndo, dp, v3);
if (dp == NULL)
goto trunc;
if (v3) {
ND_PRINT(" %u (%u) bytes @ %" PRIu64,
GET_BE_U_4(dp + 4),
GET_BE_U_4(dp + 2),
GET_BE_U_8(dp));
if (ndo->ndo_vflag) {
ND_PRINT(" <%s>",
tok2str(nfsv3_writemodes,
NULL, GET_BE_U_4(dp + 3)));
}
} else {
ND_PRINT(" %u (%u) bytes @ %u (%u)",
GET_BE_U_4(dp + 3),
GET_BE_U_4(dp + 2),
GET_BE_U_4(dp + 1),
GET_BE_U_4(dp));
}
break;
case NFSPROC_SYMLINK:
dp = parsereq(ndo, rp, length);
if (dp == NULL)
goto trunc;
dp = parsefhn(ndo, dp, v3);
if (dp == NULL)
goto trunc;
ND_PRINT(" ->");
if (v3 && (dp = parse_sattr3(ndo, dp, &sa3)) == NULL)
goto trunc;
if (parsefn(ndo, dp) == NULL)
goto trunc;
if (v3 && ndo->ndo_vflag)
print_sattr3(ndo, &sa3, ndo->ndo_vflag);
break;
case NFSPROC_MKNOD:
dp = parsereq(ndo, rp, length);
if (dp == NULL)
goto trunc;
dp = parsefhn(ndo, dp, v3);
if (dp == NULL)
goto trunc;
type = (nfs_type) GET_BE_U_4(dp);
dp++;
dp = parse_sattr3(ndo, dp, &sa3);
if (dp == NULL)
goto trunc;
ND_PRINT(" %s", tok2str(type2str, "unk-ft %u", type));
if (ndo->ndo_vflag && (type == NFCHR || type == NFBLK)) {
ND_PRINT(" %u/%u",
GET_BE_U_4(dp),
GET_BE_U_4(dp + 1));
dp += 2;
}
if (ndo->ndo_vflag)
print_sattr3(ndo, &sa3, ndo->ndo_vflag);
break;
case NFSPROC_RENAME:
dp = parsereq(ndo, rp, length);
if (dp == NULL)
goto trunc;
dp = parsefhn(ndo, dp, v3);
if (dp == NULL)
goto trunc;
ND_PRINT(" ->");
if (parsefhn(ndo, dp, v3) == NULL)
goto trunc;
break;
case NFSPROC_LINK:
dp = parsereq(ndo, rp, length);
if (dp == NULL)
goto trunc;
dp = parsefh(ndo, dp, v3);
if (dp == NULL)
goto trunc;
ND_PRINT(" ->");
if (parsefhn(ndo, dp, v3) == NULL)
goto trunc;
break;
case NFSPROC_READDIR:
dp = parsereq(ndo, rp, length);
if (dp == NULL)
goto trunc;
dp = parsefh(ndo, dp, v3);
if (dp == NULL)
goto trunc;
if (v3) {
/*
* We shouldn't really try to interpret the
* offset cookie here.
*/
ND_PRINT(" %u bytes @ %" PRId64,
GET_BE_U_4(dp + 4),
GET_BE_U_8(dp));
if (ndo->ndo_vflag) {
/*
* This displays the 8 bytes
* of the verifier in order,
* from the low-order byte
* to the high-order byte.
*/
ND_PRINT(" verf %08x%08x",
GET_BE_U_4(dp + 2),
GET_BE_U_4(dp + 3));
}
} else {
/*
* Print the offset as signed, since -1 is
* common, but offsets > 2^31 aren't.
*/
ND_PRINT(" %u bytes @ %u",
GET_BE_U_4(dp + 1),
GET_BE_U_4(dp));
}
break;
case NFSPROC_READDIRPLUS:
dp = parsereq(ndo, rp, length);
if (dp == NULL)
goto trunc;
dp = parsefh(ndo, dp, v3);
if (dp == NULL)
goto trunc;
/*
* We don't try to interpret the offset
* cookie here.
*/
ND_PRINT(" %u bytes @ %" PRId64,
GET_BE_U_4(dp + 4),
GET_BE_U_8(dp));
if (ndo->ndo_vflag) {
/*
* This displays the 8 bytes
* of the verifier in order,
* from the low-order byte
* to the high-order byte.
*/
ND_PRINT(" max %u verf %08x%08x",
GET_BE_U_4(dp + 5),
GET_BE_U_4(dp + 2),
GET_BE_U_4(dp + 3));
}
break;
case NFSPROC_COMMIT:
dp = parsereq(ndo, rp, length);
if (dp == NULL)
goto trunc;
dp = parsefh(ndo, dp, v3);
if (dp == NULL)
goto trunc;
ND_PRINT(" %u bytes @ %" PRIu64,
GET_BE_U_4(dp + 2),
GET_BE_U_8(dp));
break;
default:
break;
}
return;
trunc:
nd_print_trunc(ndo);
}
/*
* Print out an NFS file handle.
* We assume packet was not truncated before the end of the
* file handle pointed to by dp.
*
* Note: new version (using portable file-handle parser) doesn't produce
* generation number. It probably could be made to do that, with some
* additional hacking on the parser code.
*/
static void
nfs_printfh(netdissect_options *ndo,
const uint32_t *dp, const u_int len)
{
my_fsid fsid;
uint32_t ino;
const char *sfsname = NULL;
char *spacep;
if (ndo->ndo_uflag) {
u_int i;
char const *sep = "";
ND_PRINT(" fh[");
for (i=0; i<len; i++) {
/*
* This displays 4 bytes in big-endian byte
* order. That's as good a choice as little-
* endian, as there's no guarantee that the
* server is big-endian or little-endian or
* that the file handle contains 4-byte
* integral fields, and is better than "the
* byte order of the host running tcpdump", as
* the latter means that different hosts
* running tcpdump may show the same file
* handle in different ways.
*/
ND_PRINT("%s%x", sep, GET_BE_U_4(dp + i));
sep = ":";
}
ND_PRINT("]");
return;
}
Parse_fh(ndo, (const u_char *)dp, len, &fsid, &ino, NULL, &sfsname, 0);
if (sfsname) {
/* file system ID is ASCII, not numeric, for this server OS */
char temp[NFSX_V3FHMAX+1];
u_int stringlen;
/* Make sure string is null-terminated */
stringlen = len;
if (stringlen > NFSX_V3FHMAX)
stringlen = NFSX_V3FHMAX;
strncpy(temp, sfsname, stringlen);
temp[stringlen] = '\0';
/* Remove trailing spaces */
spacep = strchr(temp, ' ');
if (spacep)
*spacep = '\0';
- ND_PRINT(" fh %s/", temp);
+ ND_PRINT(" fh ");
+ fn_print_str(ndo, (const u_char *)temp);
+ ND_PRINT("/");
} else {
ND_PRINT(" fh %u,%u/",
fsid.Fsid_dev.Major, fsid.Fsid_dev.Minor);
}
- if(fsid.Fsid_dev.Minor == 257)
+ if(fsid.Fsid_dev.Minor == UINT_MAX && fsid.Fsid_dev.Major == UINT_MAX)
/* Print the undecoded handle */
- ND_PRINT("%s", fsid.Opaque_Handle);
+ fn_print_str(ndo, (const u_char *)fsid.Opaque_Handle);
else
ND_PRINT("%u", ino);
}
/*
* Maintain a small cache of recent client.XID.server/proc pairs, to allow
* us to match up replies with requests and thus to know how to parse
* the reply.
*/
struct xid_map_entry {
uint32_t xid; /* transaction ID (net order) */
int ipver; /* IP version (4 or 6) */
nd_ipv6 client; /* client IP address (net order) */
nd_ipv6 server; /* server IP address (net order) */
uint32_t proc; /* call proc number (host order) */
uint32_t vers; /* program version (host order) */
};
/*
* Map entries are kept in an array that we manage as a ring;
* new entries are always added at the tail of the ring. Initially,
* all the entries are zero and hence don't match anything.
*/
#define XIDMAPSIZE 64
static struct xid_map_entry xid_map[XIDMAPSIZE];
static int xid_map_next = 0;
static int xid_map_hint = 0;
static int
xid_map_enter(netdissect_options *ndo,
const struct sunrpc_msg *rp, const u_char *bp)
{
const struct ip *ip = NULL;
const struct ip6_hdr *ip6 = NULL;
struct xid_map_entry *xmep;
if (!ND_TTEST_4(rp->rm_call.cb_proc))
return (0);
switch (IP_V((const struct ip *)bp)) {
case 4:
ip = (const struct ip *)bp;
break;
case 6:
ip6 = (const struct ip6_hdr *)bp;
break;
default:
return (1);
}
xmep = &xid_map[xid_map_next];
if (++xid_map_next >= XIDMAPSIZE)
xid_map_next = 0;
UNALIGNED_MEMCPY(&xmep->xid, &rp->rm_xid, sizeof(xmep->xid));
if (ip) {
xmep->ipver = 4;
UNALIGNED_MEMCPY(&xmep->client, ip->ip_src,
sizeof(ip->ip_src));
UNALIGNED_MEMCPY(&xmep->server, ip->ip_dst,
sizeof(ip->ip_dst));
- }
- else if (ip6) {
+ } else if (ip6) {
xmep->ipver = 6;
UNALIGNED_MEMCPY(&xmep->client, ip6->ip6_src,
sizeof(ip6->ip6_src));
UNALIGNED_MEMCPY(&xmep->server, ip6->ip6_dst,
sizeof(ip6->ip6_dst));
}
xmep->proc = GET_BE_U_4(&rp->rm_call.cb_proc);
xmep->vers = GET_BE_U_4(&rp->rm_call.cb_vers);
return (1);
}
/*
* Returns 0 and puts NFSPROC_xxx in proc return and
* version in vers return, or returns -1 on failure
*/
static int
xid_map_find(netdissect_options *ndo, const struct sunrpc_msg *rp,
const u_char *bp, uint32_t *proc, uint32_t *vers)
{
int i;
struct xid_map_entry *xmep;
uint32_t xid;
const struct ip *ip = (const struct ip *)bp;
const struct ip6_hdr *ip6 = (const struct ip6_hdr *)bp;
int cmp;
UNALIGNED_MEMCPY(&xid, &rp->rm_xid, sizeof(xmep->xid));
/* Start searching from where we last left off */
i = xid_map_hint;
do {
xmep = &xid_map[i];
cmp = 1;
if (xmep->ipver != IP_V(ip) || xmep->xid != xid)
goto nextitem;
switch (xmep->ipver) {
case 4:
if (UNALIGNED_MEMCMP(ip->ip_src, &xmep->server,
sizeof(ip->ip_src)) != 0 ||
UNALIGNED_MEMCMP(ip->ip_dst, &xmep->client,
sizeof(ip->ip_dst)) != 0) {
cmp = 0;
}
break;
case 6:
if (UNALIGNED_MEMCMP(ip6->ip6_src, &xmep->server,
sizeof(ip6->ip6_src)) != 0 ||
UNALIGNED_MEMCMP(ip6->ip6_dst, &xmep->client,
sizeof(ip6->ip6_dst)) != 0) {
cmp = 0;
}
break;
default:
cmp = 0;
break;
}
if (cmp) {
/* match */
xid_map_hint = i;
*proc = xmep->proc;
*vers = xmep->vers;
return 0;
}
nextitem:
if (++i >= XIDMAPSIZE)
i = 0;
} while (i != xid_map_hint);
/* search failed */
return (-1);
}
/*
* Routines for parsing reply packets
*/
/*
* Return a pointer to the beginning of the actual results.
* If the packet was truncated, return 0.
*/
static const uint32_t *
parserep(netdissect_options *ndo,
const struct sunrpc_msg *rp, u_int length, int *nfserrp)
{
const uint32_t *dp;
u_int len;
enum sunrpc_accept_stat astat;
/*
* Portability note:
* Here we find the address of the ar_verf credentials.
* Originally, this calculation was
* dp = (uint32_t *)&rp->rm_reply.rp_acpt.ar_verf
* On the wire, the rp_acpt field starts immediately after
* the (32 bit) rp_stat field. However, rp_acpt (which is a
* "struct accepted_reply") contains a "struct opaque_auth",
* whose internal representation contains a pointer, so on a
* 64-bit machine the compiler inserts 32 bits of padding
* before rp->rm_reply.rp_acpt.ar_verf. So, we cannot use
* the internal representation to parse the on-the-wire
* representation. Instead, we skip past the rp_stat field,
* which is an "enum" and so occupies one 32-bit word.
*/
dp = ((const uint32_t *)&rp->rm_reply) + 1;
len = GET_BE_U_4(dp + 1);
if (len >= length)
return (NULL);
/*
* skip past the ar_verf credentials.
*/
dp += (len + (2*sizeof(uint32_t) + 3)) / sizeof(uint32_t);
/*
* now we can check the ar_stat field
*/
astat = (enum sunrpc_accept_stat) GET_BE_U_4(dp);
if (astat != SUNRPC_SUCCESS) {
ND_PRINT(" %s", tok2str(sunrpc_str, "ar_stat %u", astat));
*nfserrp = 1; /* suppress trunc string */
return (NULL);
}
/* successful return */
ND_TCHECK_LEN(dp, sizeof(astat));
return ((const uint32_t *) (sizeof(astat) + ((const char *)dp)));
trunc:
return (0);
}
static const uint32_t *
parsestatus(netdissect_options *ndo,
const uint32_t *dp, u_int *er, int *nfserrp)
{
u_int errnum;
errnum = GET_BE_U_4(dp);
if (er)
*er = errnum;
if (errnum != 0) {
if (!ndo->ndo_qflag)
ND_PRINT(" ERROR: %s",
tok2str(status2str, "unk %u", errnum));
*nfserrp = 1;
}
return (dp + 1);
}
static const uint32_t *
parsefattr(netdissect_options *ndo,
const uint32_t *dp, int verbose, int v3)
{
const struct nfs_fattr *fap;
fap = (const struct nfs_fattr *)dp;
ND_TCHECK_4(fap->fa_gid);
if (verbose) {
/*
* XXX - UIDs and GIDs are unsigned in NFS and in
* at least some UN*Xes, but we'll show them as
* signed because -2 has traditionally been the
* UID for "nobody", rather than 4294967294.
*/
ND_PRINT(" %s %o ids %d/%d",
tok2str(type2str, "unk-ft %u ",
GET_BE_U_4(fap->fa_type)),
GET_BE_U_4(fap->fa_mode),
GET_BE_S_4(fap->fa_uid),
GET_BE_S_4(fap->fa_gid));
if (v3) {
ND_PRINT(" sz %" PRIu64,
GET_BE_U_8(fap->fa3_size));
} else {
ND_PRINT(" sz %u", GET_BE_U_4(fap->fa2_size));
}
}
/* print lots more stuff */
if (verbose > 1) {
if (v3) {
ND_TCHECK_8(&fap->fa3_ctime);
ND_PRINT(" nlink %u rdev %u/%u",
GET_BE_U_4(fap->fa_nlink),
GET_BE_U_4(fap->fa3_rdev.specdata1),
GET_BE_U_4(fap->fa3_rdev.specdata2));
ND_PRINT(" fsid %" PRIx64,
GET_BE_U_8(fap->fa3_fsid));
ND_PRINT(" fileid %" PRIx64,
GET_BE_U_8(fap->fa3_fileid));
ND_PRINT(" a/m/ctime %u.%06u",
GET_BE_U_4(fap->fa3_atime.nfsv3_sec),
GET_BE_U_4(fap->fa3_atime.nfsv3_nsec));
ND_PRINT(" %u.%06u",
GET_BE_U_4(fap->fa3_mtime.nfsv3_sec),
GET_BE_U_4(fap->fa3_mtime.nfsv3_nsec));
ND_PRINT(" %u.%06u",
GET_BE_U_4(fap->fa3_ctime.nfsv3_sec),
GET_BE_U_4(fap->fa3_ctime.nfsv3_nsec));
} else {
ND_TCHECK_8(&fap->fa2_ctime);
ND_PRINT(" nlink %u rdev 0x%x fsid 0x%x nodeid 0x%x a/m/ctime",
GET_BE_U_4(fap->fa_nlink),
GET_BE_U_4(fap->fa2_rdev),
GET_BE_U_4(fap->fa2_fsid),
GET_BE_U_4(fap->fa2_fileid));
ND_PRINT(" %u.%06u",
GET_BE_U_4(fap->fa2_atime.nfsv2_sec),
GET_BE_U_4(fap->fa2_atime.nfsv2_usec));
ND_PRINT(" %u.%06u",
GET_BE_U_4(fap->fa2_mtime.nfsv2_sec),
GET_BE_U_4(fap->fa2_mtime.nfsv2_usec));
ND_PRINT(" %u.%06u",
GET_BE_U_4(fap->fa2_ctime.nfsv2_sec),
GET_BE_U_4(fap->fa2_ctime.nfsv2_usec));
}
}
return ((const uint32_t *)((const unsigned char *)dp +
(v3 ? NFSX_V3FATTR : NFSX_V2FATTR)));
trunc:
return (NULL);
}
static int
parseattrstat(netdissect_options *ndo,
const uint32_t *dp, int verbose, int v3, int *nfserrp)
{
u_int er;
dp = parsestatus(ndo, dp, &er, nfserrp);
if (dp == NULL)
return (0);
if (er)
return (1);
return (parsefattr(ndo, dp, verbose, v3) != NULL);
}
static int
parsediropres(netdissect_options *ndo,
const uint32_t *dp, int *nfserrp)
{
u_int er;
dp = parsestatus(ndo, dp, &er, nfserrp);
if (dp == NULL)
return (0);
if (er)
return (1);
dp = parsefh(ndo, dp, 0);
if (dp == NULL)
return (0);
return (parsefattr(ndo, dp, ndo->ndo_vflag, 0) != NULL);
}
static int
parselinkres(netdissect_options *ndo,
const uint32_t *dp, int v3, int *nfserrp)
{
u_int er;
dp = parsestatus(ndo, dp, &er, nfserrp);
if (dp == NULL)
return(0);
if (er)
return(1);
if (v3) {
dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag);
if (dp == NULL)
return (0);
}
ND_PRINT(" ");
return (parsefn(ndo, dp) != NULL);
}
static int
parsestatfs(netdissect_options *ndo,
const uint32_t *dp, int v3, int *nfserrp)
{
const struct nfs_statfs *sfsp;
u_int er;
dp = parsestatus(ndo, dp, &er, nfserrp);
if (dp == NULL)
return (0);
if (!v3 && er)
return (1);
if (ndo->ndo_qflag)
return(1);
if (v3) {
if (ndo->ndo_vflag)
ND_PRINT(" POST:");
dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag);
if (dp == NULL)
return (0);
}
ND_TCHECK_LEN(dp, (v3 ? NFSX_V3STATFS : NFSX_V2STATFS));
sfsp = (const struct nfs_statfs *)dp;
if (v3) {
ND_PRINT(" tbytes %" PRIu64 " fbytes %" PRIu64 " abytes %" PRIu64,
GET_BE_U_8(sfsp->sf_tbytes),
GET_BE_U_8(sfsp->sf_fbytes),
GET_BE_U_8(sfsp->sf_abytes));
if (ndo->ndo_vflag) {
ND_PRINT(" tfiles %" PRIu64 " ffiles %" PRIu64 " afiles %" PRIu64 " invar %u",
GET_BE_U_8(sfsp->sf_tfiles),
GET_BE_U_8(sfsp->sf_ffiles),
GET_BE_U_8(sfsp->sf_afiles),
GET_BE_U_4(sfsp->sf_invarsec));
}
} else {
ND_PRINT(" tsize %u bsize %u blocks %u bfree %u bavail %u",
GET_BE_U_4(sfsp->sf_tsize),
GET_BE_U_4(sfsp->sf_bsize),
GET_BE_U_4(sfsp->sf_blocks),
GET_BE_U_4(sfsp->sf_bfree),
GET_BE_U_4(sfsp->sf_bavail));
}
return (1);
trunc:
return (0);
}
static int
parserddires(netdissect_options *ndo,
const uint32_t *dp, int *nfserrp)
{
u_int er;
dp = parsestatus(ndo, dp, &er, nfserrp);
if (dp == NULL)
return (0);
if (er)
return (1);
if (ndo->ndo_qflag)
return (1);
ND_PRINT(" offset 0x%x size %u ",
GET_BE_U_4(dp), GET_BE_U_4(dp + 1));
if (GET_BE_U_4(dp + 2) != 0)
ND_PRINT(" eof");
return (1);
}
static const uint32_t *
parse_wcc_attr(netdissect_options *ndo,
const uint32_t *dp)
{
/* Our caller has already checked this */
ND_PRINT(" sz %" PRIu64, GET_BE_U_8(dp));
ND_PRINT(" mtime %u.%06u ctime %u.%06u",
GET_BE_U_4(dp + 2), GET_BE_U_4(dp + 3),
GET_BE_U_4(dp + 4), GET_BE_U_4(dp + 5));
return (dp + 6);
}
/*
* Pre operation attributes. Print only if vflag > 1.
*/
static const uint32_t *
parse_pre_op_attr(netdissect_options *ndo,
const uint32_t *dp, int verbose)
{
if (!GET_BE_U_4(dp))
return (dp + 1);
dp++;
ND_TCHECK_LEN(dp, 24);
if (verbose > 1) {
return parse_wcc_attr(ndo, dp);
} else {
/* If not verbose enough, just skip over wcc_attr */
return (dp + 6);
}
trunc:
return (NULL);
}
/*
* Post operation attributes are printed if vflag >= 1
*/
static const uint32_t *
parse_post_op_attr(netdissect_options *ndo,
const uint32_t *dp, int verbose)
{
if (!GET_BE_U_4(dp))
return (dp + 1);
dp++;
if (verbose) {
return parsefattr(ndo, dp, verbose, 1);
} else
return (dp + (NFSX_V3FATTR / sizeof (uint32_t)));
}
static const uint32_t *
parse_wcc_data(netdissect_options *ndo,
const uint32_t *dp, int verbose)
{
if (verbose > 1)
ND_PRINT(" PRE:");
dp = parse_pre_op_attr(ndo, dp, verbose);
if (dp == NULL)
return (0);
if (verbose)
ND_PRINT(" POST:");
return parse_post_op_attr(ndo, dp, verbose);
}
static const uint32_t *
parsecreateopres(netdissect_options *ndo,
const uint32_t *dp, int verbose, int *nfserrp)
{
u_int er;
dp = parsestatus(ndo, dp, &er, nfserrp);
if (dp == NULL)
return (0);
if (er)
dp = parse_wcc_data(ndo, dp, verbose);
else {
if (!GET_BE_U_4(dp))
return (dp + 1);
dp++;
dp = parsefh(ndo, dp, 1);
if (dp == NULL)
return (0);
if (verbose) {
dp = parse_post_op_attr(ndo, dp, verbose);
if (dp == NULL)
return (0);
if (ndo->ndo_vflag > 1) {
ND_PRINT(" dir attr:");
dp = parse_wcc_data(ndo, dp, verbose);
}
}
}
return (dp);
}
static const uint32_t *
parsewccres(netdissect_options *ndo,
const uint32_t *dp, int verbose, int *nfserrp)
{
u_int er;
dp = parsestatus(ndo, dp, &er, nfserrp);
if (dp == NULL)
return (0);
return parse_wcc_data(ndo, dp, verbose);
}
static const uint32_t *
parsev3rddirres(netdissect_options *ndo,
const uint32_t *dp, int verbose, int *nfserrp)
{
u_int er;
dp = parsestatus(ndo, dp, &er, nfserrp);
if (dp == NULL)
return (0);
if (ndo->ndo_vflag)
ND_PRINT(" POST:");
dp = parse_post_op_attr(ndo, dp, verbose);
if (dp == NULL)
return (0);
if (er)
return dp;
if (ndo->ndo_vflag) {
/*
* This displays the 8 bytes of the verifier in order,
* from the low-order byte to the high-order byte.
*/
ND_PRINT(" verf %08x%08x",
GET_BE_U_4(dp), GET_BE_U_4(dp + 1));
dp += 2;
}
return dp;
}
static int
parsefsinfo(netdissect_options *ndo,
const uint32_t *dp, int *nfserrp)
{
const struct nfsv3_fsinfo *sfp;
u_int er;
dp = parsestatus(ndo, dp, &er, nfserrp);
if (dp == NULL)
return (0);
if (ndo->ndo_vflag)
ND_PRINT(" POST:");
dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag);
if (dp == NULL)
return (0);
if (er)
return (1);
sfp = (const struct nfsv3_fsinfo *)dp;
ND_TCHECK_SIZE(sfp);
ND_PRINT(" rtmax %u rtpref %u wtmax %u wtpref %u dtpref %u",
GET_BE_U_4(sfp->fs_rtmax),
GET_BE_U_4(sfp->fs_rtpref),
GET_BE_U_4(sfp->fs_wtmax),
GET_BE_U_4(sfp->fs_wtpref),
GET_BE_U_4(sfp->fs_dtpref));
if (ndo->ndo_vflag) {
ND_PRINT(" rtmult %u wtmult %u maxfsz %" PRIu64,
GET_BE_U_4(sfp->fs_rtmult),
GET_BE_U_4(sfp->fs_wtmult),
GET_BE_U_8(sfp->fs_maxfilesize));
ND_PRINT(" delta %u.%06u ",
GET_BE_U_4(sfp->fs_timedelta.nfsv3_sec),
GET_BE_U_4(sfp->fs_timedelta.nfsv3_nsec));
}
return (1);
trunc:
return (0);
}
static int
parsepathconf(netdissect_options *ndo,
const uint32_t *dp, int *nfserrp)
{
u_int er;
const struct nfsv3_pathconf *spp;
dp = parsestatus(ndo, dp, &er, nfserrp);
if (dp == NULL)
return (0);
if (ndo->ndo_vflag)
ND_PRINT(" POST:");
dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag);
if (dp == NULL)
return (0);
if (er)
return (1);
spp = (const struct nfsv3_pathconf *)dp;
ND_TCHECK_SIZE(spp);
ND_PRINT(" linkmax %u namemax %u %s %s %s %s",
GET_BE_U_4(spp->pc_linkmax),
GET_BE_U_4(spp->pc_namemax),
GET_BE_U_4(spp->pc_notrunc) ? "notrunc" : "",
GET_BE_U_4(spp->pc_chownrestricted) ? "chownres" : "",
GET_BE_U_4(spp->pc_caseinsensitive) ? "igncase" : "",
GET_BE_U_4(spp->pc_casepreserving) ? "keepcase" : "");
return (1);
trunc:
return (0);
}
static void
interp_reply(netdissect_options *ndo,
const struct sunrpc_msg *rp, uint32_t proc, uint32_t vers,
int length)
{
const uint32_t *dp;
int v3;
u_int er;
int nfserr = 0;
v3 = (vers == NFS_VER3);
if (!v3 && proc < NFS_NPROCS)
proc = nfsv3_procid[proc];
ND_PRINT(" %s", tok2str(nfsproc_str, "proc-%u", proc));
switch (proc) {
case NFSPROC_GETATTR:
dp = parserep(ndo, rp, length, &nfserr);
if (dp == NULL)
goto trunc;
if (parseattrstat(ndo, dp, !ndo->ndo_qflag, v3, &nfserr) == 0)
goto trunc;
break;
case NFSPROC_SETATTR:
dp = parserep(ndo, rp, length, &nfserr);
if (dp == NULL)
goto trunc;
if (v3) {
- if (parsewccres(ndo, dp, ndo->ndo_vflag, &nfserr) == 0)
+ if (parsewccres(ndo, dp, ndo->ndo_vflag, &nfserr) == NULL)
goto trunc;
} else {
if (parseattrstat(ndo, dp, !ndo->ndo_qflag, 0, &nfserr) == 0)
goto trunc;
}
break;
case NFSPROC_LOOKUP:
dp = parserep(ndo, rp, length, &nfserr);
if (dp == NULL)
goto trunc;
if (v3) {
dp = parsestatus(ndo, dp, &er, &nfserr);
if (dp == NULL)
goto trunc;
if (er) {
if (ndo->ndo_vflag > 1) {
ND_PRINT(" post dattr:");
dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag);
if (dp == NULL)
goto trunc;
}
} else {
dp = parsefh(ndo, dp, v3);
if (dp == NULL)
goto trunc;
dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag);
if (dp == NULL)
goto trunc;
if (ndo->ndo_vflag > 1) {
ND_PRINT(" post dattr:");
dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag);
if (dp == NULL)
goto trunc;
}
}
} else {
if (parsediropres(ndo, dp, &nfserr) == 0)
goto trunc;
}
break;
case NFSPROC_ACCESS:
dp = parserep(ndo, rp, length, &nfserr);
if (dp == NULL)
goto trunc;
dp = parsestatus(ndo, dp, &er, &nfserr);
if (dp == NULL)
goto trunc;
if (ndo->ndo_vflag)
ND_PRINT(" attr:");
dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag);
if (dp == NULL)
goto trunc;
if (!er) {
ND_PRINT(" c %04x", GET_BE_U_4(dp));
}
break;
case NFSPROC_READLINK:
dp = parserep(ndo, rp, length, &nfserr);
if (dp == NULL)
goto trunc;
if (parselinkres(ndo, dp, v3, &nfserr) == 0)
goto trunc;
break;
case NFSPROC_READ:
dp = parserep(ndo, rp, length, &nfserr);
if (dp == NULL)
goto trunc;
if (v3) {
dp = parsestatus(ndo, dp, &er, &nfserr);
if (dp == NULL)
goto trunc;
dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag);
if (dp == NULL)
goto trunc;
if (!er) {
if (ndo->ndo_vflag) {
ND_PRINT(" %u bytes", GET_BE_U_4(dp));
if (GET_BE_U_4(dp + 1))
ND_PRINT(" EOF");
}
}
} else {
if (parseattrstat(ndo, dp, ndo->ndo_vflag, 0, &nfserr) == 0)
goto trunc;
}
break;
case NFSPROC_WRITE:
dp = parserep(ndo, rp, length, &nfserr);
if (dp == NULL)
goto trunc;
if (v3) {
dp = parsestatus(ndo, dp, &er, &nfserr);
if (dp == NULL)
goto trunc;
dp = parse_wcc_data(ndo, dp, ndo->ndo_vflag);
if (dp == NULL)
goto trunc;
if (!er) {
if (ndo->ndo_vflag) {
ND_PRINT(" %u bytes", GET_BE_U_4(dp));
if (ndo->ndo_vflag > 1) {
ND_PRINT(" <%s>",
tok2str(nfsv3_writemodes,
NULL, GET_BE_U_4(dp + 1)));
/* write-verf-cookie */
ND_PRINT(" verf %" PRIx64,
GET_BE_U_8(dp + 2));
}
}
}
return;
} else {
if (parseattrstat(ndo, dp, ndo->ndo_vflag, v3, &nfserr) == 0)
goto trunc;
}
break;
case NFSPROC_CREATE:
case NFSPROC_MKDIR:
dp = parserep(ndo, rp, length, &nfserr);
if (dp == NULL)
goto trunc;
if (v3) {
if (parsecreateopres(ndo, dp, ndo->ndo_vflag, &nfserr) == NULL)
goto trunc;
} else {
if (parsediropres(ndo, dp, &nfserr) == 0)
goto trunc;
}
break;
case NFSPROC_SYMLINK:
dp = parserep(ndo, rp, length, &nfserr);
if (dp == NULL)
goto trunc;
if (v3) {
if (parsecreateopres(ndo, dp, ndo->ndo_vflag, &nfserr) == NULL)
goto trunc;
} else {
if (parsestatus(ndo, dp, &er, &nfserr) == NULL)
goto trunc;
}
break;
case NFSPROC_MKNOD:
dp = parserep(ndo, rp, length, &nfserr);
if (dp == NULL)
goto trunc;
if (parsecreateopres(ndo, dp, ndo->ndo_vflag, &nfserr) == NULL)
goto trunc;
break;
case NFSPROC_REMOVE:
case NFSPROC_RMDIR:
dp = parserep(ndo, rp, length, &nfserr);
if (dp == NULL)
goto trunc;
if (v3) {
if (parsewccres(ndo, dp, ndo->ndo_vflag, &nfserr) == NULL)
goto trunc;
} else {
if (parsestatus(ndo, dp, &er, &nfserr) == NULL)
goto trunc;
}
break;
case NFSPROC_RENAME:
dp = parserep(ndo, rp, length, &nfserr);
if (dp == NULL)
goto trunc;
if (v3) {
dp = parsestatus(ndo, dp, &er, &nfserr);
if (dp == NULL)
goto trunc;
if (ndo->ndo_vflag) {
ND_PRINT(" from:");
dp = parse_wcc_data(ndo, dp, ndo->ndo_vflag);
if (dp == NULL)
goto trunc;
ND_PRINT(" to:");
dp = parse_wcc_data(ndo, dp, ndo->ndo_vflag);
if (dp == NULL)
goto trunc;
}
} else {
if (parsestatus(ndo, dp, &er, &nfserr) == NULL)
goto trunc;
}
break;
case NFSPROC_LINK:
dp = parserep(ndo, rp, length, &nfserr);
if (dp == NULL)
goto trunc;
if (v3) {
dp = parsestatus(ndo, dp, &er, &nfserr);
if (dp == NULL)
goto trunc;
if (ndo->ndo_vflag) {
ND_PRINT(" file POST:");
dp = parse_post_op_attr(ndo, dp, ndo->ndo_vflag);
if (dp == NULL)
goto trunc;
ND_PRINT(" dir:");
dp = parse_wcc_data(ndo, dp, ndo->ndo_vflag);
if (dp == NULL)
goto trunc;
}
return;
} else {
if (parsestatus(ndo, dp, &er, &nfserr) == NULL)
goto trunc;
}
break;
case NFSPROC_READDIR:
dp = parserep(ndo, rp, length, &nfserr);
if (dp == NULL)
goto trunc;
if (v3) {
if (parsev3rddirres(ndo, dp, ndo->ndo_vflag, &nfserr) == NULL)
goto trunc;
} else {
if (parserddires(ndo, dp, &nfserr) == 0)
goto trunc;
}
break;
case NFSPROC_READDIRPLUS:
dp = parserep(ndo, rp, length, &nfserr);
if (dp == NULL)
goto trunc;
if (parsev3rddirres(ndo, dp, ndo->ndo_vflag, &nfserr) == NULL)
goto trunc;
break;
case NFSPROC_FSSTAT:
dp = parserep(ndo, rp, length, &nfserr);
if (dp == NULL)
goto trunc;
if (parsestatfs(ndo, dp, v3, &nfserr) == 0)
goto trunc;
break;
case NFSPROC_FSINFO:
dp = parserep(ndo, rp, length, &nfserr);
if (dp == NULL)
goto trunc;
if (parsefsinfo(ndo, dp, &nfserr) == 0)
goto trunc;
break;
case NFSPROC_PATHCONF:
dp = parserep(ndo, rp, length, &nfserr);
if (dp == NULL)
goto trunc;
if (parsepathconf(ndo, dp, &nfserr) == 0)
goto trunc;
break;
case NFSPROC_COMMIT:
dp = parserep(ndo, rp, length, &nfserr);
if (dp == NULL)
goto trunc;
dp = parsewccres(ndo, dp, ndo->ndo_vflag, &nfserr);
if (dp == NULL)
goto trunc;
if (ndo->ndo_vflag > 1) {
/* write-verf-cookie */
ND_PRINT(" verf %" PRIx64, GET_BE_U_8(dp));
}
break;
default:
break;
}
return;
trunc:
if (!nfserr)
nd_print_trunc(ndo);
}
diff --git a/contrib/tcpdump/print-nsh.c b/contrib/tcpdump/print-nsh.c
index 12a63cd6370c..bf86a8bae4b9 100644
--- a/contrib/tcpdump/print-nsh.c
+++ b/contrib/tcpdump/print-nsh.c
@@ -1,264 +1,261 @@
/* Copyright (c) 2015, bugyo
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* \summary: Network Service Header (NSH) printer */
/* specification: RFC 8300 */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
static const struct tok nsh_flags [] = {
{ 0x2, "O" },
{ 0, NULL }
};
/*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |Ver|O|U| TTL | Length |U|U|U|U|MD Type| Next Protocol |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
#define NSH_BASE_HDR_LEN 4
#define NSH_VER(x) (((x) & 0xc0000000) >> 30)
#define NSH_FLAGS(x) (((x) & 0x30000000) >> 28)
#define NSH_TTL(x) (((x) & 0x0fc00000) >> 22)
#define NSH_LENGTH(x) (((x) & 0x003f0000) >> 16)
#define NSH_MD_TYPE(x) (((x) & 0x00000f00) >> 8)
#define NSH_NEXT_PROT(x) (((x) & 0x000000ff) >> 0)
#define NSH_SERVICE_PATH_HDR_LEN 4
#define NSH_HDR_WORD_SIZE 4U
#define MD_RSV 0x00
#define MD_TYPE1 0x01
#define MD_TYPE2 0x02
#define MD_EXP 0x0F
static const struct tok md_str[] = {
{ MD_RSV, "reserved" },
{ MD_TYPE1, "1" },
{ MD_TYPE2, "2" },
{ MD_EXP, "experimental" },
{ 0, NULL }
};
#define NP_IPV4 0x01
#define NP_IPV6 0x02
#define NP_ETH 0x03
#define NP_NSH 0x04
#define NP_MPLS 0x05
#define NP_EXP1 0xFE
#define NP_EXP2 0xFF
static const struct tok np_str[] = {
{ NP_IPV4, "IPv4" },
{ NP_IPV6, "IPv6" },
{ NP_ETH, "Ethernet" },
{ NP_NSH, "NSH" },
{ NP_MPLS, "MPLS" },
{ NP_EXP1, "Experiment 1" },
{ NP_EXP2, "Experiment 2" },
{ 0, NULL }
};
void
nsh_print(netdissect_options *ndo, const u_char *bp, u_int len)
{
uint32_t basehdr;
u_int ver, length, md_type;
uint8_t next_protocol;
u_char past_headers = 0;
u_int next_len;
ndo->ndo_protocol = "nsh";
/*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Base Header |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Service Path Header |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* ~ Context Header(s) ~
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/* print Base Header and Service Path Header */
if (len < NSH_BASE_HDR_LEN + NSH_SERVICE_PATH_HDR_LEN) {
ND_PRINT(" (packet length %u < %u)",
len, NSH_BASE_HDR_LEN + NSH_SERVICE_PATH_HDR_LEN);
goto invalid;
}
basehdr = GET_BE_U_4(bp);
bp += 4;
ver = NSH_VER(basehdr);
length = NSH_LENGTH(basehdr);
md_type = NSH_MD_TYPE(basehdr);
next_protocol = NSH_NEXT_PROT(basehdr);
ND_PRINT("NSH, ");
if (ndo->ndo_vflag > 1) {
ND_PRINT("ver %u, ", ver);
}
if (ver != 0)
return;
ND_PRINT("flags [%s], ",
bittok2str_nosep(nsh_flags, "none", NSH_FLAGS(basehdr)));
if (ndo->ndo_vflag > 2) {
ND_PRINT("TTL %u, ", NSH_TTL(basehdr));
ND_PRINT("length %u, ", length);
ND_PRINT("md type %s, ", tok2str(md_str, "unknown (0x%02x)", md_type));
}
if (ndo->ndo_vflag > 1) {
ND_PRINT("next-protocol %s, ",
tok2str(np_str, "unknown (0x%02x)", next_protocol));
}
/* Make sure we have all the headers */
if (len < length * NSH_HDR_WORD_SIZE) {
ND_PRINT(" (too many headers for packet length %u)", len);
goto invalid;
}
/*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Service Path Identifier (SPI) | Service Index |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*/
ND_PRINT("service-path-id 0x%06x, ", GET_BE_U_3(bp));
bp += 3;
ND_PRINT("service-index 0x%x", GET_U_1(bp));
bp += 1;
/*
* length includes the lengths of the Base and Service Path headers.
* That means it must be at least 2.
*/
if (length < 2) {
ND_PRINT(" (less than two headers)");
goto invalid;
}
/*
* Print, or skip, the Context Headers.
* (length - 2) is the length of those headers.
*/
if (ndo->ndo_vflag > 2) {
u_int n;
if (md_type == MD_TYPE1) {
if (length != 6) {
- ND_PRINT(" (invalid length for the MD type)");
+ ND_PRINT(" (length for the MD type)");
goto invalid;
}
for (n = 0; n < length - 2; n++) {
ND_PRINT("\n Context[%02u]: 0x%08x", n, GET_BE_U_4(bp));
bp += NSH_HDR_WORD_SIZE;
}
past_headers = 1;
- }
- else if (md_type == MD_TYPE2) {
+ } else if (md_type == MD_TYPE2) {
n = 0;
while (n < length - 2) {
uint16_t tlv_class;
uint8_t tlv_type, tlv_len, tlv_len_padded;
tlv_class = GET_BE_U_2(bp);
bp += 2;
tlv_type = GET_U_1(bp);
bp += 1;
tlv_len = GET_U_1(bp) & 0x7f;
bp += 1;
tlv_len_padded = roundup2(tlv_len, NSH_HDR_WORD_SIZE);
ND_PRINT("\n TLV Class %u, Type %u, Len %u",
tlv_class, tlv_type, tlv_len);
n += 1;
if (length - 2 < n + tlv_len_padded / NSH_HDR_WORD_SIZE) {
ND_PRINT(" (length too big)");
goto invalid;
}
if (tlv_len) {
const char *sep = "0x";
u_int vn;
ND_PRINT("\n Value: ");
for (vn = 0; vn < tlv_len; vn++) {
ND_PRINT("%s%02x", sep, GET_U_1(bp));
bp += 1;
sep = ":";
}
/* Cover any TLV padding. */
ND_TCHECK_LEN(bp, tlv_len_padded - tlv_len);
bp += tlv_len_padded - tlv_len;
n += tlv_len_padded / NSH_HDR_WORD_SIZE;
}
}
past_headers = 1;
}
}
if (! past_headers) {
ND_TCHECK_LEN(bp, (length - 2) * NSH_HDR_WORD_SIZE);
bp += (length - 2) * NSH_HDR_WORD_SIZE;
}
ND_PRINT(ndo->ndo_vflag ? "\n " : ": ");
/* print Next Protocol */
next_len = len - length * NSH_HDR_WORD_SIZE;
switch (next_protocol) {
case NP_IPV4:
ip_print(ndo, bp, next_len);
break;
case NP_IPV6:
ip6_print(ndo, bp, next_len);
break;
case NP_ETH:
ether_print(ndo, bp, next_len, ND_BYTES_AVAILABLE_AFTER(bp), NULL, NULL);
break;
default:
ND_PRINT("ERROR: unknown-next-protocol");
return;
}
return;
invalid:
nd_print_invalid(ndo);
}
diff --git a/contrib/tcpdump/print-ntp.c b/contrib/tcpdump/print-ntp.c
index 537975cc2e59..30bef73172e9 100644
--- a/contrib/tcpdump/print-ntp.c
+++ b/contrib/tcpdump/print-ntp.c
@@ -1,536 +1,532 @@
/*
* 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.
*
* By Jeffrey Mogul/DECWRL
* loosely based on print-bootp.c
*/
/* \summary: Network Time Protocol (NTP) printer */
/*
* specification:
*
* RFC 1119 - NTPv2
* RFC 1305 - NTPv3
* RFC 5905 - NTPv4
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
-#include <time.h>
-
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#include "ntp.h"
/*
* Based on ntp.h from the U of MD implementation
* This file is based on Version 2 of the NTP spec (RFC1119).
*/
/* rfc2030
* 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |LI | VN |Mode | Stratum | Poll | Precision |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Root Delay |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Root Dispersion |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Reference Identifier |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* | Reference Timestamp (64) |
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* | Originate Timestamp (64) |
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* | Receive Timestamp (64) |
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* | Transmit Timestamp (64) |
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Key Identifier (optional) (32) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* | |
* | Message Digest (optional) (128) |
* | |
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/* Length of the NTP data message with the mandatory fields ("the header")
* and without any optional fields (extension, Key Identifier,
* Message Digest).
*/
#define NTP_TIMEMSG_MINLEN 48U
struct ntp_time_data {
nd_uint8_t status; /* status of local clock and leap info */
nd_uint8_t stratum; /* Stratum level */
nd_int8_t ppoll; /* poll value */
nd_int8_t precision;
struct s_fixedpt root_delay;
struct s_fixedpt root_dispersion;
nd_uint32_t refid;
struct l_fixedpt ref_timestamp;
struct l_fixedpt org_timestamp;
struct l_fixedpt rec_timestamp;
struct l_fixedpt xmt_timestamp;
nd_uint32_t key_id;
nd_uint8_t message_digest[20];
};
/*
* Leap Second Codes (high order two bits)
*/
#define NO_WARNING 0x00 /* no warning */
#define PLUS_SEC 0x40 /* add a second (61 seconds) */
#define MINUS_SEC 0x80 /* minus a second (59 seconds) */
#define ALARM 0xc0 /* alarm condition (clock unsynchronized) */
/*
* Clock Status Bits that Encode Version
*/
#define NTPVERSION_1 0x08
#define VERSIONMASK 0x38
#define VERSIONSHIFT 3
#define LEAPMASK 0xc0
#define LEAPSHIFT 6
#ifdef MODEMASK
#undef MODEMASK /* Solaris sucks */
#endif
#define MODEMASK 0x07
#define MODESHIFT 0
/*
* Code values
*/
#define MODE_UNSPEC 0 /* unspecified */
#define MODE_SYM_ACT 1 /* symmetric active */
#define MODE_SYM_PAS 2 /* symmetric passive */
#define MODE_CLIENT 3 /* client */
#define MODE_SERVER 4 /* server */
#define MODE_BROADCAST 5 /* broadcast */
#define MODE_CONTROL 6 /* control message */
#define MODE_RES2 7 /* reserved */
/*
* Stratum Definitions
*/
#define UNSPECIFIED 0
#define PRIM_REF 1 /* radio clock */
#define INFO_QUERY 62 /* **** THIS implementation dependent **** */
#define INFO_REPLY 63 /* **** THIS implementation dependent **** */
static void p_sfix(netdissect_options *ndo, const struct s_fixedpt *);
static void p_ntp_delta(netdissect_options *, const struct l_fixedpt *, const struct l_fixedpt *);
static void p_poll(netdissect_options *, const int);
static const struct tok ntp_mode_values[] = {
{ MODE_UNSPEC, "unspecified" },
{ MODE_SYM_ACT, "symmetric active" },
{ MODE_SYM_PAS, "symmetric passive" },
{ MODE_CLIENT, "Client" },
{ MODE_SERVER, "Server" },
{ MODE_BROADCAST, "Broadcast" },
{ MODE_CONTROL, "Control Message" },
{ MODE_RES2, "Reserved" },
{ 0, NULL }
};
static const struct tok ntp_leapind_values[] = {
{ NO_WARNING, "" },
{ PLUS_SEC, "+1s" },
{ MINUS_SEC, "-1s" },
{ ALARM, "clock unsynchronized" },
{ 0, NULL }
};
static const struct tok ntp_stratum_values[] = {
{ UNSPECIFIED, "unspecified" },
{ PRIM_REF, "primary reference" },
{ 0, NULL }
};
/* draft-ietf-ntp-mode-6-cmds-02
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |LI | VN |Mode |R|E|M| OpCode | Sequence Number |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Status | Association ID |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Offset | Count |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* / Data (up to 468 bytes) /
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Padding (optional) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* / Authenticator (optional, 96 bytes) /
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* Figure 1: NTP Control Message Header
*/
/* Length of the NTP control message with the mandatory fields ("the header")
* and without any optional fields (Data, Padding, Authenticator).
*/
#define NTP_CTRLMSG_MINLEN 12U
struct ntp_control_data {
nd_uint8_t magic; /* LI, VN, Mode */
nd_uint8_t control; /* R, E, M, OpCode */
nd_uint16_t sequence; /* Sequence Number */
nd_uint16_t status; /* Status */
nd_uint16_t assoc; /* Association ID */
nd_uint16_t offset; /* Offset */
nd_uint16_t count; /* Count */
nd_uint8_t data[564]; /* Data, [Padding, [Authenticator]] */
};
/*
* Print NTP time requests and responses
*/
static void
ntp_time_print(netdissect_options *ndo,
const struct ntp_time_data *bp, u_int length)
{
uint8_t stratum;
if (length < NTP_TIMEMSG_MINLEN)
goto invalid;
stratum = GET_U_1(bp->stratum);
ND_PRINT(", Stratum %u (%s)",
stratum,
tok2str(ntp_stratum_values, (stratum >=2 && stratum<=15) ? "secondary reference" : "reserved", stratum));
ND_PRINT(", poll %d", GET_S_1(bp->ppoll));
p_poll(ndo, GET_S_1(bp->ppoll));
ND_PRINT(", precision %d", GET_S_1(bp->precision));
ND_TCHECK_SIZE(&bp->root_delay);
ND_PRINT("\n\tRoot Delay: ");
p_sfix(ndo, &bp->root_delay);
ND_TCHECK_SIZE(&bp->root_dispersion);
ND_PRINT(", Root dispersion: ");
p_sfix(ndo, &bp->root_dispersion);
ND_TCHECK_4(bp->refid);
ND_PRINT(", Reference-ID: ");
/* Interpretation depends on stratum */
switch (stratum) {
case UNSPECIFIED:
ND_PRINT("(unspec)");
break;
case PRIM_REF:
if (nd_printn(ndo, (const u_char *)&(bp->refid), 4, ndo->ndo_snapend))
goto trunc;
break;
case INFO_QUERY:
ND_PRINT("%s INFO_QUERY", GET_IPADDR_STRING(bp->refid));
/* this doesn't have more content */
return;
case INFO_REPLY:
ND_PRINT("%s INFO_REPLY", GET_IPADDR_STRING(bp->refid));
/* this is too complex to be worth printing */
return;
default:
/* In NTPv4 (RFC 5905) refid is an IPv4 address or first 32 bits of
MD5 sum of IPv6 address */
ND_PRINT("0x%08x", GET_BE_U_4(bp->refid));
break;
}
ND_TCHECK_SIZE(&bp->ref_timestamp);
ND_PRINT("\n\t Reference Timestamp: ");
p_ntp_time(ndo, &(bp->ref_timestamp));
ND_TCHECK_SIZE(&bp->org_timestamp);
ND_PRINT("\n\t Originator Timestamp: ");
p_ntp_time(ndo, &(bp->org_timestamp));
ND_TCHECK_SIZE(&bp->rec_timestamp);
ND_PRINT("\n\t Receive Timestamp: ");
p_ntp_time(ndo, &(bp->rec_timestamp));
ND_TCHECK_SIZE(&bp->xmt_timestamp);
ND_PRINT("\n\t Transmit Timestamp: ");
p_ntp_time(ndo, &(bp->xmt_timestamp));
ND_PRINT("\n\t Originator - Receive Timestamp: ");
p_ntp_delta(ndo, &(bp->org_timestamp), &(bp->rec_timestamp));
ND_PRINT("\n\t Originator - Transmit Timestamp: ");
p_ntp_delta(ndo, &(bp->org_timestamp), &(bp->xmt_timestamp));
/* FIXME: this code is not aware of any extension fields */
if (length == NTP_TIMEMSG_MINLEN + 4) { /* Optional: key-id (crypto-NAK) */
ND_PRINT("\n\tKey id: %u", GET_BE_U_4(bp->key_id));
} else if (length == NTP_TIMEMSG_MINLEN + 4 + 16) { /* Optional: key-id + 128-bit digest */
ND_PRINT("\n\tKey id: %u", GET_BE_U_4(bp->key_id));
ND_TCHECK_LEN(bp->message_digest, 16);
ND_PRINT("\n\tAuthentication: %08x%08x%08x%08x",
GET_BE_U_4(bp->message_digest),
GET_BE_U_4(bp->message_digest + 4),
GET_BE_U_4(bp->message_digest + 8),
GET_BE_U_4(bp->message_digest + 12));
} else if (length == NTP_TIMEMSG_MINLEN + 4 + 20) { /* Optional: key-id + 160-bit digest */
ND_PRINT("\n\tKey id: %u", GET_BE_U_4(bp->key_id));
ND_TCHECK_LEN(bp->message_digest, 20);
ND_PRINT("\n\tAuthentication: %08x%08x%08x%08x%08x",
GET_BE_U_4(bp->message_digest),
GET_BE_U_4(bp->message_digest + 4),
GET_BE_U_4(bp->message_digest + 8),
GET_BE_U_4(bp->message_digest + 12),
GET_BE_U_4(bp->message_digest + 16));
} else if (length > NTP_TIMEMSG_MINLEN) {
ND_PRINT("\n\t(%u more bytes after the header)", length - NTP_TIMEMSG_MINLEN);
}
return;
invalid:
nd_print_invalid(ndo);
ND_TCHECK_LEN(bp, length);
return;
trunc:
nd_print_trunc(ndo);
}
/*
* Print NTP control message requests and responses
*/
static void
ntp_control_print(netdissect_options *ndo,
const struct ntp_control_data *cd, u_int length)
{
uint8_t control, R, E, M, opcode;
uint16_t sequence, status, assoc, offset, count;
if (length < NTP_CTRLMSG_MINLEN)
goto invalid;
control = GET_U_1(cd->control);
R = (control & 0x80) != 0;
E = (control & 0x40) != 0;
M = (control & 0x20) != 0;
opcode = control & 0x1f;
ND_PRINT(", %s, %s, %s, OpCode=%u\n",
R ? "Response" : "Request", E ? "Error" : "OK",
M ? "More" : "Last", opcode);
sequence = GET_BE_U_2(cd->sequence);
ND_PRINT("\tSequence=%hu", sequence);
status = GET_BE_U_2(cd->status);
ND_PRINT(", Status=%#hx", status);
assoc = GET_BE_U_2(cd->assoc);
ND_PRINT(", Assoc.=%hu", assoc);
offset = GET_BE_U_2(cd->offset);
ND_PRINT(", Offset=%hu", offset);
count = GET_BE_U_2(cd->count);
ND_PRINT(", Count=%hu", count);
if (NTP_CTRLMSG_MINLEN + count > length)
goto invalid;
if (count != 0) {
ND_TCHECK_LEN(cd->data, count);
ND_PRINT("\n\tTO-BE-DONE: data not interpreted");
}
return;
invalid:
nd_print_invalid(ndo);
ND_TCHECK_LEN(cd, length);
return;
trunc:
nd_print_trunc(ndo);
}
union ntpdata {
struct ntp_time_data td;
struct ntp_control_data cd;
};
/*
* Print NTP requests, handling the common VN, LI, and Mode
*/
void
ntp_print(netdissect_options *ndo,
const u_char *cp, u_int length)
{
const union ntpdata *bp = (const union ntpdata *)cp;
u_int mode, version, leapind;
uint8_t status;
ndo->ndo_protocol = "ntp";
status = GET_U_1(bp->td.status);
version = (status & VERSIONMASK) >> VERSIONSHIFT;
ND_PRINT("NTPv%u", version);
mode = (status & MODEMASK) >> MODESHIFT;
if (!ndo->ndo_vflag) {
ND_PRINT(", %s, length %u",
tok2str(ntp_mode_values, "Unknown mode", mode),
length);
return;
}
ND_PRINT(", %s, length %u\n",
tok2str(ntp_mode_values, "Unknown mode", mode), length);
/* leapind = (status & LEAPMASK) >> LEAPSHIFT; */
leapind = (status & LEAPMASK);
ND_PRINT("\tLeap indicator: %s (%u)",
tok2str(ntp_leapind_values, "Unknown", leapind),
leapind);
switch (mode) {
case MODE_UNSPEC:
case MODE_SYM_ACT:
case MODE_SYM_PAS:
case MODE_CLIENT:
case MODE_SERVER:
case MODE_BROADCAST:
ntp_time_print(ndo, &bp->td, length);
break;
case MODE_CONTROL:
ntp_control_print(ndo, &bp->cd, length);
break;
default:
break; /* XXX: not implemented! */
}
}
static void
p_sfix(netdissect_options *ndo,
const struct s_fixedpt *sfp)
{
int i;
int f;
double ff;
i = GET_BE_U_2(sfp->int_part);
f = GET_BE_U_2(sfp->fraction);
ff = f / 65536.0; /* shift radix point by 16 bits */
f = (int)(ff * 1000000.0); /* Treat fraction as parts per million */
ND_PRINT("%d.%06d", i, f);
}
/* Prints time difference between *lfp and *olfp */
static void
p_ntp_delta(netdissect_options *ndo,
const struct l_fixedpt *olfp,
const struct l_fixedpt *lfp)
{
uint32_t u, uf;
uint32_t ou, ouf;
uint32_t i;
uint32_t f;
double ff;
int signbit;
u = GET_BE_U_4(lfp->int_part);
ou = GET_BE_U_4(olfp->int_part);
uf = GET_BE_U_4(lfp->fraction);
ouf = GET_BE_U_4(olfp->fraction);
if (ou == 0 && ouf == 0) {
p_ntp_time(ndo, lfp);
return;
}
if (u > ou) { /* new is definitely greater than old */
signbit = 0;
i = u - ou;
f = uf - ouf;
if (ouf > uf) /* must borrow from high-order bits */
i -= 1;
} else if (u < ou) { /* new is definitely less than old */
signbit = 1;
i = ou - u;
f = ouf - uf;
if (uf > ouf) /* must borrow from the high-order bits */
i -= 1;
} else { /* int_part is zero */
i = 0;
if (uf > ouf) {
signbit = 0;
f = uf - ouf;
} else {
signbit = 1;
f = ouf - uf;
}
}
ff = f;
if (ff < 0.0) /* some compilers are buggy */
ff += FMAXINT;
ff = ff / FMAXINT; /* shift radix point by 32 bits */
f = (uint32_t)(ff * 1000000000.0); /* treat fraction as parts per billion */
ND_PRINT("%s%u.%09u", signbit ? "-" : "+", i, f);
}
/* Prints polling interval in log2 as seconds or fraction of second */
static void
p_poll(netdissect_options *ndo,
const int poll_interval)
{
if (poll_interval <= -32 || poll_interval >= 32)
return;
if (poll_interval >= 0)
ND_PRINT(" (%us)", 1U << poll_interval);
else
ND_PRINT(" (1/%us)", 1U << -poll_interval);
}
diff --git a/contrib/tcpdump/print-null.c b/contrib/tcpdump/print-null.c
index a1b03f86aae6..037a35fd9678 100644
--- a/contrib/tcpdump/print-null.c
+++ b/contrib/tcpdump/print-null.c
@@ -1,138 +1,136 @@
/*
* Copyright (c) 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.
*/
/* \summary: BSD loopback device printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
#include "af.h"
/*
* The DLT_NULL packet header is 4 bytes long. It contains a host-byte-order
* 32-bit integer that specifies the family, e.g. AF_INET.
*
* Note here that "host" refers to the host on which the packets were
* captured; that isn't necessarily *this* host.
*
* The OpenBSD DLT_LOOP packet header is the same, except that the integer
* is in network byte order.
*/
#define NULL_HDRLEN 4
/*
* Byte-swap a 32-bit number.
* ("htonl()" or "ntohl()" won't work - we want to byte-swap even on
* big-endian platforms.)
*/
#define SWAPLONG(y) \
((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff))
static void
null_hdr_print(netdissect_options *ndo, uint32_t family, u_int length)
{
if (!ndo->ndo_qflag) {
ND_PRINT("AF %s (%u)",
tok2str(bsd_af_values,"Unknown",family),family);
} else {
ND_PRINT("%s",
tok2str(bsd_af_values,"Unknown AF %u",family));
}
ND_PRINT(", length %u: ", length);
}
/*
* This is the top level routine of the printer. 'p' points
* to the ether header of the packet, 'h->ts' is the timestamp,
* 'h->len' is the length of the packet off the wire, and 'h->caplen'
* is the number of bytes actually captured.
*/
void
null_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
{
u_int length = h->len;
u_int caplen = h->caplen;
uint32_t family;
ndo->ndo_protocol = "null";
ND_TCHECK_LEN(p, NULL_HDRLEN);
ndo->ndo_ll_hdr_len += NULL_HDRLEN;
family = GET_HE_U_4(p);
/*
* This isn't necessarily in our host byte order; if this is
* a DLT_LOOP capture, it's in network byte order, and if
* this is a DLT_NULL capture from a machine with the opposite
* byte-order, it's in the opposite byte order from ours.
*
* If the upper 16 bits aren't all zero, assume it's byte-swapped.
*/
if ((family & 0xFFFF0000) != 0)
family = SWAPLONG(family);
if (ndo->ndo_eflag)
null_hdr_print(ndo, family, length);
length -= NULL_HDRLEN;
caplen -= NULL_HDRLEN;
p += NULL_HDRLEN;
switch (family) {
case BSD_AFNUM_INET:
ip_print(ndo, p, length);
break;
case BSD_AFNUM_INET6_BSD:
case BSD_AFNUM_INET6_FREEBSD:
case BSD_AFNUM_INET6_DARWIN:
ip6_print(ndo, p, length);
break;
case BSD_AFNUM_ISO:
isoclns_print(ndo, p, length);
break;
case BSD_AFNUM_APPLETALK:
atalk_print(ndo, p, length);
break;
case BSD_AFNUM_IPX:
ipx_print(ndo, p, length);
break;
default:
/* unknown AF_ value */
if (!ndo->ndo_eflag)
null_hdr_print(ndo, family, length + NULL_HDRLEN);
if (!ndo->ndo_suppress_default_print)
ND_DEFAULTPRINT(p, caplen);
}
}
diff --git a/contrib/tcpdump/print-olsr.c b/contrib/tcpdump/print-olsr.c
index 8f049237167b..d83a960e1403 100644
--- a/contrib/tcpdump/print-olsr.c
+++ b/contrib/tcpdump/print-olsr.c
@@ -1,714 +1,706 @@
/*
* Copyright (c) 1998-2007 The TCPDUMP project
* Copyright (c) 2009 Florian Forster
*
* 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.
*
* Original code by Hannes Gredler <hannes@gredler.at>
* IPv6 additions by Florian Forster <octo at verplant.org>
*/
/* \summary: Optimized Link State Routing Protocol (OLSR) printer */
/* specification: RFC 3626 */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
/*
* RFC 3626 common header
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Packet Length | Packet Sequence Number |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Message Type | Vtime | Message Size |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Originator Address |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Time To Live | Hop Count | Message Sequence Number |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* : MESSAGE :
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Message Type | Vtime | Message Size |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Originator Address |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Time To Live | Hop Count | Message Sequence Number |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* : MESSAGE :
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* : :
*/
struct olsr_common {
nd_uint16_t packet_len;
nd_uint16_t packet_seq;
};
#define OLSR_HELLO_MSG 1 /* rfc3626 */
#define OLSR_TC_MSG 2 /* rfc3626 */
#define OLSR_MID_MSG 3 /* rfc3626 */
#define OLSR_HNA_MSG 4 /* rfc3626 */
#define OLSR_POWERINFO_MSG 128
#define OLSR_NAMESERVICE_MSG 130
#define OLSR_HELLO_LQ_MSG 201 /* LQ extensions olsr.org */
#define OLSR_TC_LQ_MSG 202 /* LQ extensions olsr.org */
static const struct tok olsr_msg_values[] = {
{ OLSR_HELLO_MSG, "Hello" },
{ OLSR_TC_MSG, "TC" },
{ OLSR_MID_MSG, "MID" },
{ OLSR_HNA_MSG, "HNA" },
{ OLSR_POWERINFO_MSG, "Powerinfo" },
{ OLSR_NAMESERVICE_MSG, "Nameservice" },
{ OLSR_HELLO_LQ_MSG, "Hello-LQ" },
{ OLSR_TC_LQ_MSG, "TC-LQ" },
{ 0, NULL}
};
struct olsr_msg4 {
nd_uint8_t msg_type;
nd_uint8_t vtime;
nd_uint16_t msg_len;
nd_ipv4 originator;
nd_uint8_t ttl;
nd_uint8_t hopcount;
nd_uint16_t msg_seq;
};
struct olsr_msg6 {
nd_uint8_t msg_type;
nd_uint8_t vtime;
nd_uint16_t msg_len;
nd_ipv6 originator;
nd_uint8_t ttl;
nd_uint8_t hopcount;
nd_uint16_t msg_seq;
};
struct olsr_hello {
nd_byte res[2];
nd_uint8_t htime;
nd_uint8_t will;
};
struct olsr_hello_link {
nd_uint8_t link_code;
nd_byte res;
nd_uint16_t len;
};
struct olsr_tc {
nd_uint16_t ans_seq;
nd_byte res[2];
};
struct olsr_hna4 {
nd_ipv4 network;
nd_ipv4 mask;
};
struct olsr_hna6 {
nd_ipv6 network;
nd_ipv6 mask;
};
/** gateway HNA flags */
enum gateway_hna_flags {
GW_HNA_FLAG_LINKSPEED = 1 << 0,
GW_HNA_FLAG_IPV4 = 1 << 1,
GW_HNA_FLAG_IPV4_NAT = 1 << 2,
GW_HNA_FLAG_IPV6 = 1 << 3,
GW_HNA_FLAG_IPV6PREFIX = 1 << 4
};
/** gateway HNA field byte offsets in the netmask field of the HNA */
enum gateway_hna_fields {
GW_HNA_PAD = 0,
GW_HNA_FLAGS = 1,
GW_HNA_UPLINK = 2,
GW_HNA_DOWNLINK = 3,
GW_HNA_V6PREFIXLEN = 4,
GW_HNA_V6PREFIX = 5
};
#define OLSR_EXTRACT_LINK_TYPE(link_code) (link_code & 0x3)
#define OLSR_EXTRACT_NEIGHBOR_TYPE(link_code) (link_code >> 2)
static const struct tok olsr_link_type_values[] = {
{ 0, "Unspecified" },
{ 1, "Asymmetric" },
{ 2, "Symmetric" },
{ 3, "Lost" },
{ 0, NULL}
};
static const struct tok olsr_neighbor_type_values[] = {
{ 0, "Not-Neighbor" },
{ 1, "Symmetric" },
{ 2, "Symmetric-MPR" },
{ 0, NULL}
};
struct olsr_lq_neighbor4 {
nd_ipv4 neighbor;
nd_uint8_t link_quality;
nd_uint8_t neighbor_link_quality;
nd_byte res[2];
};
struct olsr_lq_neighbor6 {
nd_ipv6 neighbor;
nd_uint8_t link_quality;
nd_uint8_t neighbor_link_quality;
nd_byte res[2];
};
#define MAX_SMARTGW_SPEED 320000000
/**
* Convert an encoded 1 byte transport value (5 bits mantissa, 3 bits exponent)
* to an uplink/downlink speed value
*
* @param value the encoded 1 byte transport value
* @return the uplink/downlink speed value (in kbit/s)
*/
static uint32_t deserialize_gw_speed(uint8_t value) {
uint32_t speed;
uint32_t exp;
if (!value) {
return 0;
}
if (value == UINT8_MAX) {
/* maximum value: also return maximum value */
return MAX_SMARTGW_SPEED;
}
speed = (value >> 3) + 1;
exp = value & 7;
while (exp != 0) {
speed *= 10;
exp--;
}
return speed;
}
/*
* macro to convert the 8-bit mantissa/exponent to a double float
* taken from olsr.org.
*/
#define VTIME_SCALE_FACTOR 0.0625
#define ME_TO_DOUBLE(me) \
(double)(VTIME_SCALE_FACTOR*(1+(double)(me>>4)/16)*(double)(1<<(me&0x0F)))
/*
* print a neighbor list with LQ extensions.
*/
static int
olsr_print_lq_neighbor4(netdissect_options *ndo,
const u_char *msg_data, u_int hello_len)
{
const struct olsr_lq_neighbor4 *lq_neighbor;
while (hello_len >= sizeof(struct olsr_lq_neighbor4)) {
lq_neighbor = (const struct olsr_lq_neighbor4 *)msg_data;
ND_TCHECK_SIZE(lq_neighbor);
ND_PRINT("\n\t neighbor %s, link-quality %.2f%%"
", neighbor-link-quality %.2f%%",
GET_IPADDR_STRING(lq_neighbor->neighbor),
((double) GET_U_1(lq_neighbor->link_quality)/2.55),
((double) GET_U_1(lq_neighbor->neighbor_link_quality)/2.55));
msg_data += sizeof(struct olsr_lq_neighbor4);
hello_len -= sizeof(struct olsr_lq_neighbor4);
}
return (0);
trunc:
return -1;
}
static int
olsr_print_lq_neighbor6(netdissect_options *ndo,
const u_char *msg_data, u_int hello_len)
{
const struct olsr_lq_neighbor6 *lq_neighbor;
while (hello_len >= sizeof(struct olsr_lq_neighbor6)) {
lq_neighbor = (const struct olsr_lq_neighbor6 *)msg_data;
ND_TCHECK_SIZE(lq_neighbor);
ND_PRINT("\n\t neighbor %s, link-quality %.2f%%"
", neighbor-link-quality %.2f%%",
GET_IP6ADDR_STRING(lq_neighbor->neighbor),
((double) GET_U_1(lq_neighbor->link_quality)/2.55),
((double) GET_U_1(lq_neighbor->neighbor_link_quality)/2.55));
msg_data += sizeof(struct olsr_lq_neighbor6);
hello_len -= sizeof(struct olsr_lq_neighbor6);
}
return (0);
trunc:
return -1;
}
/*
* print a neighbor list.
*/
static int
olsr_print_neighbor(netdissect_options *ndo,
const u_char *msg_data, u_int hello_len)
{
int neighbor;
ND_PRINT("\n\t neighbor\n\t\t");
neighbor = 1;
while (hello_len >= sizeof(nd_ipv4)) {
/* print 4 neighbors per line */
ND_PRINT("%s%s", GET_IPADDR_STRING(msg_data),
neighbor % 4 == 0 ? "\n\t\t" : " ");
msg_data += sizeof(nd_ipv4);
hello_len -= sizeof(nd_ipv4);
}
return (0);
}
void
olsr_print(netdissect_options *ndo,
const u_char *pptr, u_int length, int is_ipv6)
{
union {
const struct olsr_common *common;
const struct olsr_msg4 *msg4;
const struct olsr_msg6 *msg6;
const struct olsr_hello *hello;
const struct olsr_hello_link *hello_link;
const struct olsr_tc *tc;
const struct olsr_hna4 *hna;
} ptr;
u_int msg_type, msg_len, msg_tlen, hello_len;
uint16_t name_entry_type, name_entry_len;
u_int name_entry_padding;
uint8_t link_type, neighbor_type;
const u_char *tptr, *msg_data;
ndo->ndo_protocol = "olsr";
tptr = pptr;
nd_print_protocol_caps(ndo);
ND_PRINT("v%u", (is_ipv6) ? 6 : 4);
if (length < sizeof(struct olsr_common)) {
goto trunc;
}
ND_TCHECK_LEN(tptr, sizeof(struct olsr_common));
ptr.common = (const struct olsr_common *)tptr;
length = ND_MIN(length, GET_BE_U_2(ptr.common->packet_len));
ND_PRINT(", seq 0x%04x, length %u",
GET_BE_U_2(ptr.common->packet_seq),
length);
tptr += sizeof(struct olsr_common);
/*
* In non-verbose mode, just print version.
*/
if (ndo->ndo_vflag < 1) {
return;
}
while (tptr < (pptr+length)) {
union
{
const struct olsr_msg4 *v4;
const struct olsr_msg6 *v6;
} msgptr;
int msg_len_valid = 0;
- if (is_ipv6)
- {
+ if (is_ipv6) {
ND_TCHECK_LEN(tptr, sizeof(struct olsr_msg6));
msgptr.v6 = (const struct olsr_msg6 *) tptr;
msg_type = GET_U_1(msgptr.v6->msg_type);
msg_len = GET_BE_U_2(msgptr.v6->msg_len);
if ((msg_len >= sizeof (struct olsr_msg6))
&& (msg_len <= length))
msg_len_valid = 1;
/* infinite loop check */
if (msg_type == 0 || msg_len == 0) {
return;
}
ND_PRINT("\n\t%s Message (%#04x), originator %s, ttl %u, hop %u"
"\n\t vtime %.3fs, msg-seq 0x%04x, length %u%s",
tok2str(olsr_msg_values, "Unknown", msg_type),
msg_type, GET_IP6ADDR_STRING(msgptr.v6->originator),
GET_U_1(msgptr.v6->ttl),
GET_U_1(msgptr.v6->hopcount),
ME_TO_DOUBLE(GET_U_1(msgptr.v6->vtime)),
GET_BE_U_2(msgptr.v6->msg_seq),
msg_len, (msg_len_valid == 0) ? " (invalid)" : "");
if (!msg_len_valid) {
return;
}
msg_tlen = msg_len - sizeof(struct olsr_msg6);
msg_data = tptr + sizeof(struct olsr_msg6);
- }
- else /* (!is_ipv6) */
- {
+ } else { /* (!is_ipv6) */
ND_TCHECK_LEN(tptr, sizeof(struct olsr_msg4));
msgptr.v4 = (const struct olsr_msg4 *) tptr;
msg_type = GET_U_1(msgptr.v4->msg_type);
msg_len = GET_BE_U_2(msgptr.v4->msg_len);
if ((msg_len >= sizeof (struct olsr_msg4))
&& (msg_len <= length))
msg_len_valid = 1;
/* infinite loop check */
if (msg_type == 0 || msg_len == 0) {
return;
}
ND_PRINT("\n\t%s Message (%#04x), originator %s, ttl %u, hop %u"
"\n\t vtime %.3fs, msg-seq 0x%04x, length %u%s",
tok2str(olsr_msg_values, "Unknown", msg_type),
msg_type, GET_IPADDR_STRING(msgptr.v4->originator),
GET_U_1(msgptr.v4->ttl),
GET_U_1(msgptr.v4->hopcount),
ME_TO_DOUBLE(GET_U_1(msgptr.v4->vtime)),
GET_BE_U_2(msgptr.v4->msg_seq),
msg_len, (msg_len_valid == 0) ? " (invalid)" : "");
if (!msg_len_valid) {
return;
}
msg_tlen = msg_len - sizeof(struct olsr_msg4);
msg_data = tptr + sizeof(struct olsr_msg4);
}
switch (msg_type) {
case OLSR_HELLO_MSG:
case OLSR_HELLO_LQ_MSG:
if (msg_tlen < sizeof(struct olsr_hello))
goto trunc;
ND_TCHECK_LEN(msg_data, sizeof(struct olsr_hello));
ptr.hello = (const struct olsr_hello *)msg_data;
ND_PRINT("\n\t hello-time %.3fs, MPR willingness %u",
ME_TO_DOUBLE(GET_U_1(ptr.hello->htime)),
GET_U_1(ptr.hello->will));
msg_data += sizeof(struct olsr_hello);
msg_tlen -= sizeof(struct olsr_hello);
while (msg_tlen >= sizeof(struct olsr_hello_link)) {
int hello_len_valid = 0;
/*
* link-type.
*/
ND_TCHECK_LEN(msg_data, sizeof(struct olsr_hello_link));
ptr.hello_link = (const struct olsr_hello_link *)msg_data;
hello_len = GET_BE_U_2(ptr.hello_link->len);
link_type = OLSR_EXTRACT_LINK_TYPE(GET_U_1(ptr.hello_link->link_code));
neighbor_type = OLSR_EXTRACT_NEIGHBOR_TYPE(GET_U_1(ptr.hello_link->link_code));
if ((hello_len <= msg_tlen)
&& (hello_len >= sizeof(struct olsr_hello_link)))
hello_len_valid = 1;
ND_PRINT("\n\t link-type %s, neighbor-type %s, len %u%s",
tok2str(olsr_link_type_values, "Unknown", link_type),
tok2str(olsr_neighbor_type_values, "Unknown", neighbor_type),
hello_len,
(hello_len_valid == 0) ? " (invalid)" : "");
if (hello_len_valid == 0)
break;
msg_data += sizeof(struct olsr_hello_link);
msg_tlen -= sizeof(struct olsr_hello_link);
hello_len -= sizeof(struct olsr_hello_link);
ND_TCHECK_LEN(msg_data, hello_len);
if (msg_type == OLSR_HELLO_MSG) {
if (olsr_print_neighbor(ndo, msg_data, hello_len) == -1)
goto trunc;
} else {
if (is_ipv6) {
if (olsr_print_lq_neighbor6(ndo, msg_data, hello_len) == -1)
goto trunc;
} else {
if (olsr_print_lq_neighbor4(ndo, msg_data, hello_len) == -1)
goto trunc;
}
}
msg_data += hello_len;
msg_tlen -= hello_len;
}
break;
case OLSR_TC_MSG:
case OLSR_TC_LQ_MSG:
if (msg_tlen < sizeof(struct olsr_tc))
goto trunc;
ND_TCHECK_LEN(msg_data, sizeof(struct olsr_tc));
ptr.tc = (const struct olsr_tc *)msg_data;
ND_PRINT("\n\t advertised neighbor seq 0x%04x",
GET_BE_U_2(ptr.tc->ans_seq));
msg_data += sizeof(struct olsr_tc);
msg_tlen -= sizeof(struct olsr_tc);
if (msg_type == OLSR_TC_MSG) {
if (olsr_print_neighbor(ndo, msg_data, msg_tlen) == -1)
goto trunc;
} else {
if (is_ipv6) {
if (olsr_print_lq_neighbor6(ndo, msg_data, msg_tlen) == -1)
goto trunc;
} else {
if (olsr_print_lq_neighbor4(ndo, msg_data, msg_tlen) == -1)
goto trunc;
}
}
break;
case OLSR_MID_MSG:
{
u_int addr_size = (u_int)sizeof(nd_ipv4);
if (is_ipv6)
addr_size = (u_int)sizeof(nd_ipv6);
while (msg_tlen >= addr_size) {
ND_TCHECK_LEN(msg_data, addr_size);
ND_PRINT("\n\t interface address %s",
is_ipv6 ? GET_IP6ADDR_STRING(msg_data) :
GET_IPADDR_STRING(msg_data));
msg_data += addr_size;
msg_tlen -= addr_size;
}
break;
}
case OLSR_HNA_MSG:
- if (is_ipv6)
- {
+ if (is_ipv6) {
int i = 0;
ND_PRINT("\n\t Advertised networks (total %u)",
(unsigned int) (msg_tlen / sizeof(struct olsr_hna6)));
while (msg_tlen >= sizeof(struct olsr_hna6)) {
const struct olsr_hna6 *hna6;
ND_TCHECK_LEN(msg_data, sizeof(struct olsr_hna6));
hna6 = (const struct olsr_hna6 *)msg_data;
ND_PRINT("\n\t #%i: %s/%u",
i, GET_IP6ADDR_STRING(hna6->network),
mask62plen (hna6->mask));
msg_data += sizeof(struct olsr_hna6);
msg_tlen -= sizeof(struct olsr_hna6);
}
- }
- else
- {
+ } else {
int col = 0;
ND_PRINT("\n\t Advertised networks (total %u)",
(unsigned int) (msg_tlen / sizeof(struct olsr_hna4)));
while (msg_tlen >= sizeof(struct olsr_hna4)) {
ND_TCHECK_LEN(msg_data, sizeof(struct olsr_hna4));
ptr.hna = (const struct olsr_hna4 *)msg_data;
/* print 4 prefixes per line */
if (!ptr.hna->network[0] && !ptr.hna->network[1] &&
!ptr.hna->network[2] && !ptr.hna->network[3] &&
!ptr.hna->mask[GW_HNA_PAD] &&
ptr.hna->mask[GW_HNA_FLAGS]) {
/* smart gateway */
ND_PRINT("%sSmart-Gateway:%s%s%s%s%s %u/%u",
col == 0 ? "\n\t " : ", ", /* indent */
/* sgw */
/* LINKSPEED */
(ptr.hna->mask[GW_HNA_FLAGS] &
GW_HNA_FLAG_LINKSPEED) ? " LINKSPEED" : "",
/* IPV4 */
(ptr.hna->mask[GW_HNA_FLAGS] &
GW_HNA_FLAG_IPV4) ? " IPV4" : "",
/* IPV4-NAT */
(ptr.hna->mask[GW_HNA_FLAGS] &
GW_HNA_FLAG_IPV4_NAT) ? " IPV4-NAT" : "",
/* IPV6 */
(ptr.hna->mask[GW_HNA_FLAGS] &
GW_HNA_FLAG_IPV6) ? " IPV6" : "",
/* IPv6PREFIX */
(ptr.hna->mask[GW_HNA_FLAGS] &
GW_HNA_FLAG_IPV6PREFIX) ? " IPv6-PREFIX" : "",
/* uplink */
(ptr.hna->mask[GW_HNA_FLAGS] &
GW_HNA_FLAG_LINKSPEED) ?
deserialize_gw_speed(ptr.hna->mask[GW_HNA_UPLINK]) : 0,
/* downlink */
(ptr.hna->mask[GW_HNA_FLAGS] &
GW_HNA_FLAG_LINKSPEED) ?
deserialize_gw_speed(ptr.hna->mask[GW_HNA_DOWNLINK]) : 0
);
} else {
/* normal route */
ND_PRINT("%s%s/%u",
col == 0 ? "\n\t " : ", ",
GET_IPADDR_STRING(ptr.hna->network),
mask2plen(GET_BE_U_4(ptr.hna->mask)));
}
msg_data += sizeof(struct olsr_hna4);
msg_tlen -= sizeof(struct olsr_hna4);
col = (col + 1) % 4;
}
}
break;
case OLSR_NAMESERVICE_MSG:
{
u_int name_entries;
u_int addr_size;
int name_entries_valid;
u_int i;
if (msg_tlen < 4)
goto trunc;
name_entries = GET_BE_U_2(msg_data + 2);
addr_size = 4;
if (is_ipv6)
addr_size = 16;
name_entries_valid = 0;
if ((name_entries > 0)
&& ((name_entries * (4 + addr_size)) <= msg_tlen))
name_entries_valid = 1;
ND_PRINT("\n\t Version %u, Entries %u%s",
GET_BE_U_2(msg_data),
name_entries, (name_entries_valid == 0) ? " (invalid)" : "");
if (name_entries_valid == 0)
break;
msg_data += 4;
msg_tlen -= 4;
for (i = 0; i < name_entries; i++) {
int name_entry_len_valid = 0;
if (msg_tlen < 4)
break;
name_entry_type = GET_BE_U_2(msg_data);
name_entry_len = GET_BE_U_2(msg_data + 2);
msg_data += 4;
msg_tlen -= 4;
if ((name_entry_len > 0) && ((addr_size + name_entry_len) <= msg_tlen))
name_entry_len_valid = 1;
ND_PRINT("\n\t #%u: type %#06x, length %u%s",
(unsigned int) i, name_entry_type,
name_entry_len, (name_entry_len_valid == 0) ? " (invalid)" : "");
if (name_entry_len_valid == 0)
break;
/* 32-bit alignment */
name_entry_padding = 0;
if (name_entry_len%4 != 0)
name_entry_padding = 4-(name_entry_len%4);
if (msg_tlen < addr_size + name_entry_len + name_entry_padding)
goto trunc;
ND_TCHECK_LEN(msg_data,
addr_size + name_entry_len + name_entry_padding);
if (is_ipv6)
ND_PRINT(", address %s, name \"",
GET_IP6ADDR_STRING(msg_data));
else
ND_PRINT(", address %s, name \"",
GET_IPADDR_STRING(msg_data));
(void)nd_printn(ndo, msg_data + addr_size, name_entry_len, NULL);
ND_PRINT("\"");
msg_data += addr_size + name_entry_len + name_entry_padding;
msg_tlen -= addr_size + name_entry_len + name_entry_padding;
} /* for (i = 0; i < name_entries; i++) */
break;
} /* case OLSR_NAMESERVICE_MSG */
/*
* FIXME those are the defined messages that lack a decoder
* you are welcome to contribute code ;-)
*/
case OLSR_POWERINFO_MSG:
default:
print_unknown_data(ndo, msg_data, "\n\t ", msg_tlen);
break;
} /* switch (msg_type) */
tptr += msg_len;
} /* while (tptr < (pptr+length)) */
return;
trunc:
nd_print_trunc(ndo);
}
diff --git a/contrib/tcpdump/print-openflow-1.0.c b/contrib/tcpdump/print-openflow-1.0.c
index 1d7f2474875e..3ee1650da573 100644
--- a/contrib/tcpdump/print-openflow-1.0.c
+++ b/contrib/tcpdump/print-openflow-1.0.c
@@ -1,2298 +1,2279 @@
/*
* This module implements decoding of OpenFlow protocol version 1.0 (wire
* protocol 0x01). The decoder implements terse (default), detailed (-v) and
* full (-vv) output formats and, as much as each format implies, detects and
* tries to work around sizing anomalies inside the messages. The decoder marks
* up bogus values of selected message fields and decodes partially captured
* messages up to the snapshot end. It is based on the specification below:
*
* [OF10] https://www.opennetworking.org/wp-content/uploads/2013/04/openflow-spec-v1.0.0.pdf
*
* Most functions in this file take the following arguments:
* * cp -- the pointer to the first octet to decode
* * len -- the declared length of the structure to decode
* The convention is that a printer function returns iff the given structure is
* completely within the packet buffer; otherwise it processes the part that is
* within the buffer, sooner of later takes the "truncated packet" shortcut via
* longjmp() and never returns. With that in mind, the function may return
* without printing the structure completely if it is invalid or the ndo_vflag
* value is not high enough. This way the calling function can try to decode
* the next data item.
*
* Decoding of Ethernet frames nested in OFPT_PACKET_IN and OFPT_PACKET_OUT
* messages is done only when the verbosity level set by command-line argument
* is "-vvv" or higher. In that case the verbosity level is temporarily
* decremented by 3 during the nested frame decoding. For example, running
* tcpdump with "-vvvv" will do full decoding of OpenFlow and "-v" decoding of
* the nested frames.
*
* Partial decoding of Big Switch Networks vendor extensions is done after the
* oftest (OpenFlow Testing Framework) and Loxigen (library generator) source
* code.
*
*
* Copyright (c) 2013 The TCPDUMP project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* \summary: OpenFlow protocol version 1.0 printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
#include "addrtoname.h"
#include "ethertype.h"
#include "ipproto.h"
#include "oui.h"
#include "openflow.h"
#define OFPT_HELLO 0x00
#define OFPT_ERROR 0x01
#define OFPT_ECHO_REQUEST 0x02
#define OFPT_ECHO_REPLY 0x03
#define OFPT_VENDOR 0x04
#define OFPT_FEATURES_REQUEST 0x05
#define OFPT_FEATURES_REPLY 0x06
#define OFPT_GET_CONFIG_REQUEST 0x07
#define OFPT_GET_CONFIG_REPLY 0x08
#define OFPT_SET_CONFIG 0x09
#define OFPT_PACKET_IN 0x0a
#define OFPT_FLOW_REMOVED 0x0b
#define OFPT_PORT_STATUS 0x0c
#define OFPT_PACKET_OUT 0x0d
#define OFPT_FLOW_MOD 0x0e
#define OFPT_PORT_MOD 0x0f
#define OFPT_STATS_REQUEST 0x10
#define OFPT_STATS_REPLY 0x11
#define OFPT_BARRIER_REQUEST 0x12
#define OFPT_BARRIER_REPLY 0x13
#define OFPT_QUEUE_GET_CONFIG_REQUEST 0x14
#define OFPT_QUEUE_GET_CONFIG_REPLY 0x15
#define OFPT_MAX OFPT_QUEUE_GET_CONFIG_REPLY
#define OFPPC_PORT_DOWN (1U <<0)
#define OFPPC_NO_STP (1U <<1)
#define OFPPC_NO_RECV (1U <<2)
#define OFPPC_NO_RECV_STP (1U <<3)
#define OFPPC_NO_FLOOD (1U <<4)
#define OFPPC_NO_FWD (1U <<5)
#define OFPPC_NO_PACKET_IN (1U <<6)
static const struct tok ofppc_bm[] = {
{ OFPPC_PORT_DOWN, "PORT_DOWN" },
{ OFPPC_NO_STP, "NO_STP" },
{ OFPPC_NO_RECV, "NO_RECV" },
{ OFPPC_NO_RECV_STP, "NO_RECV_STP" },
{ OFPPC_NO_FLOOD, "NO_FLOOD" },
{ OFPPC_NO_FWD, "NO_FWD" },
{ OFPPC_NO_PACKET_IN, "NO_PACKET_IN" },
{ 0, NULL }
};
#define OFPPC_U (~(OFPPC_PORT_DOWN | OFPPC_NO_STP | OFPPC_NO_RECV | \
OFPPC_NO_RECV_STP | OFPPC_NO_FLOOD | OFPPC_NO_FWD | \
OFPPC_NO_PACKET_IN))
/*
* [OF10] lists all FPPS_ constants in one enum, but they mean a 1-bit bitmap
* in the least significant octet and a 2-bit code point in the next octet.
* Remember to mix or to separate these two parts as the context requires.
*/
#define OFPPS_LINK_DOWN (1U << 0) /* bitmap */
#define OFPPS_STP_LISTEN (0U << 8) /* code point */
#define OFPPS_STP_LEARN (1U << 8) /* code point */
#define OFPPS_STP_FORWARD (2U << 8) /* code point */
#define OFPPS_STP_BLOCK (3U << 8) /* code point */
#define OFPPS_STP_MASK (3U << 8) /* code point bitmask */
static const struct tok ofpps_stp_str[] = {
{ OFPPS_STP_LISTEN, "STP_LISTEN" },
{ OFPPS_STP_LEARN, "STP_LEARN" },
{ OFPPS_STP_FORWARD, "STP_FORWARD" },
{ OFPPS_STP_BLOCK, "STP_BLOCK" },
{ 0, NULL }
};
#define OFPPS_U (~(OFPPS_LINK_DOWN | OFPPS_STP_LISTEN | OFPPS_STP_LEARN | \
OFPPS_STP_FORWARD | OFPPS_STP_BLOCK))
#define OFPP_MAX 0xff00U
#define OFPP_IN_PORT 0xfff8U
#define OFPP_TABLE 0xfff9U
#define OFPP_NORMAL 0xfffaU
#define OFPP_FLOOD 0xfffbU
#define OFPP_ALL 0xfffcU
#define OFPP_CONTROLLER 0xfffdU
#define OFPP_LOCAL 0xfffeU
#define OFPP_NONE 0xffffU
static const struct tok ofpp_str[] = {
{ OFPP_MAX, "MAX" },
{ OFPP_IN_PORT, "IN_PORT" },
{ OFPP_TABLE, "TABLE" },
{ OFPP_NORMAL, "NORMAL" },
{ OFPP_FLOOD, "FLOOD" },
{ OFPP_ALL, "ALL" },
{ OFPP_CONTROLLER, "CONTROLLER" },
{ OFPP_LOCAL, "LOCAL" },
{ OFPP_NONE, "NONE" },
{ 0, NULL }
};
#define OFPPF_10MB_HD (1U << 0)
#define OFPPF_10MB_FD (1U << 1)
#define OFPPF_100MB_HD (1U << 2)
#define OFPPF_100MB_FD (1U << 3)
#define OFPPF_1GB_HD (1U << 4)
#define OFPPF_1GB_FD (1U << 5)
#define OFPPF_10GB_FD (1U << 6)
#define OFPPF_COPPER (1U << 7)
#define OFPPF_FIBER (1U << 8)
#define OFPPF_AUTONEG (1U << 9)
#define OFPPF_PAUSE (1U <<10)
#define OFPPF_PAUSE_ASYM (1U <<11)
static const struct tok ofppf_bm[] = {
{ OFPPF_10MB_HD, "10MB_HD" },
{ OFPPF_10MB_FD, "10MB_FD" },
{ OFPPF_100MB_HD, "100MB_HD" },
{ OFPPF_100MB_FD, "100MB_FD" },
{ OFPPF_1GB_HD, "1GB_HD" },
{ OFPPF_1GB_FD, "1GB_FD" },
{ OFPPF_10GB_FD, "10GB_FD" },
{ OFPPF_COPPER, "COPPER" },
{ OFPPF_FIBER, "FIBER" },
{ OFPPF_AUTONEG, "AUTONEG" },
{ OFPPF_PAUSE, "PAUSE" },
{ OFPPF_PAUSE_ASYM, "PAUSE_ASYM" },
{ 0, NULL }
};
#define OFPPF_U (~(OFPPF_10MB_HD | OFPPF_10MB_FD | OFPPF_100MB_HD | \
OFPPF_100MB_FD | OFPPF_1GB_HD | OFPPF_1GB_FD | \
OFPPF_10GB_FD | OFPPF_COPPER | OFPPF_FIBER | \
OFPPF_AUTONEG | OFPPF_PAUSE | OFPPF_PAUSE_ASYM))
#define OFPQT_NONE 0x0000
#define OFPQT_MIN_RATE 0x0001
static const struct tok ofpqt_str[] = {
{ OFPQT_NONE, "NONE" },
{ OFPQT_MIN_RATE, "MIN_RATE" },
{ 0, NULL }
};
#define OFPFW_IN_PORT (1U <<0)
#define OFPFW_DL_VLAN (1U <<1)
#define OFPFW_DL_SRC (1U <<2)
#define OFPFW_DL_DST (1U <<3)
#define OFPFW_DL_TYPE (1U <<4)
#define OFPFW_NW_PROTO (1U <<5)
#define OFPFW_TP_SRC (1U <<6)
#define OFPFW_TP_DST (1U <<7)
#define OFPFW_NW_SRC_SHIFT 8
#define OFPFW_NW_SRC_BITS 6
#define OFPFW_NW_SRC_MASK (((1U <<OFPFW_NW_SRC_BITS) - 1) << OFPFW_NW_SRC_SHIFT)
#define OFPFW_NW_DST_SHIFT 14
#define OFPFW_NW_DST_BITS 6
#define OFPFW_NW_DST_MASK (((1U <<OFPFW_NW_DST_BITS) - 1) << OFPFW_NW_DST_SHIFT)
#define OFPFW_DL_VLAN_PCP (1U <<20)
#define OFPFW_NW_TOS (1U <<21)
#define OFPFW_ALL ((1U <<22) - 1)
static const struct tok ofpfw_bm[] = {
{ OFPFW_IN_PORT, "IN_PORT" },
{ OFPFW_DL_VLAN, "DL_VLAN" },
{ OFPFW_DL_SRC, "DL_SRC" },
{ OFPFW_DL_DST, "DL_DST" },
{ OFPFW_DL_TYPE, "DL_TYPE" },
{ OFPFW_NW_PROTO, "NW_PROTO" },
{ OFPFW_TP_SRC, "TP_SRC" },
{ OFPFW_TP_DST, "TP_DST" },
{ OFPFW_DL_VLAN_PCP, "DL_VLAN_PCP" },
{ OFPFW_NW_TOS, "NW_TOS" },
{ 0, NULL }
};
/* The above array does not include bits 8~13 (OFPFW_NW_SRC_*) and 14~19
* (OFPFW_NW_DST_*), which are not a part of the bitmap and require decoding
* other than that of tok2str(). The macro below includes these bits such that
* they are not reported as bogus in the decoding. */
#define OFPFW_U (~(OFPFW_ALL))
#define OFPAT_OUTPUT 0x0000U
#define OFPAT_SET_VLAN_VID 0x0001U
#define OFPAT_SET_VLAN_PCP 0x0002U
#define OFPAT_STRIP_VLAN 0x0003U
#define OFPAT_SET_DL_SRC 0x0004U
#define OFPAT_SET_DL_DST 0x0005U
#define OFPAT_SET_NW_SRC 0x0006U
#define OFPAT_SET_NW_DST 0x0007U
#define OFPAT_SET_NW_TOS 0x0008U
#define OFPAT_SET_TP_SRC 0x0009U
#define OFPAT_SET_TP_DST 0x000aU
#define OFPAT_ENQUEUE 0x000bU
#define OFPAT_VENDOR 0xffffU
static const struct tok ofpat_str[] = {
{ OFPAT_OUTPUT, "OUTPUT" },
{ OFPAT_SET_VLAN_VID, "SET_VLAN_VID" },
{ OFPAT_SET_VLAN_PCP, "SET_VLAN_PCP" },
{ OFPAT_STRIP_VLAN, "STRIP_VLAN" },
{ OFPAT_SET_DL_SRC, "SET_DL_SRC" },
{ OFPAT_SET_DL_DST, "SET_DL_DST" },
{ OFPAT_SET_NW_SRC, "SET_NW_SRC" },
{ OFPAT_SET_NW_DST, "SET_NW_DST" },
{ OFPAT_SET_NW_TOS, "SET_NW_TOS" },
{ OFPAT_SET_TP_SRC, "SET_TP_SRC" },
{ OFPAT_SET_TP_DST, "SET_TP_DST" },
{ OFPAT_ENQUEUE, "ENQUEUE" },
{ OFPAT_VENDOR, "VENDOR" },
{ 0, NULL }
};
/* bit-shifted, w/o vendor action */
static const struct tok ofpat_bm[] = {
{ 1U <<OFPAT_OUTPUT, "OUTPUT" },
{ 1U <<OFPAT_SET_VLAN_VID, "SET_VLAN_VID" },
{ 1U <<OFPAT_SET_VLAN_PCP, "SET_VLAN_PCP" },
{ 1U <<OFPAT_STRIP_VLAN, "STRIP_VLAN" },
{ 1U <<OFPAT_SET_DL_SRC, "SET_DL_SRC" },
{ 1U <<OFPAT_SET_DL_DST, "SET_DL_DST" },
{ 1U <<OFPAT_SET_NW_SRC, "SET_NW_SRC" },
{ 1U <<OFPAT_SET_NW_DST, "SET_NW_DST" },
{ 1U <<OFPAT_SET_NW_TOS, "SET_NW_TOS" },
{ 1U <<OFPAT_SET_TP_SRC, "SET_TP_SRC" },
{ 1U <<OFPAT_SET_TP_DST, "SET_TP_DST" },
{ 1U <<OFPAT_ENQUEUE, "ENQUEUE" },
{ 0, NULL }
};
#define OFPAT_U (~(1U <<OFPAT_OUTPUT | 1U <<OFPAT_SET_VLAN_VID | \
1U <<OFPAT_SET_VLAN_PCP | 1U <<OFPAT_STRIP_VLAN | \
1U <<OFPAT_SET_DL_SRC | 1U <<OFPAT_SET_DL_DST | \
1U <<OFPAT_SET_NW_SRC | 1U <<OFPAT_SET_NW_DST | \
1U <<OFPAT_SET_NW_TOS | 1U <<OFPAT_SET_TP_SRC | \
1U <<OFPAT_SET_TP_DST | 1U <<OFPAT_ENQUEUE))
#define OFPC_FLOW_STATS (1U <<0)
#define OFPC_TABLE_STATS (1U <<1)
#define OFPC_PORT_STATS (1U <<2)
#define OFPC_STP (1U <<3)
#define OFPC_RESERVED (1U <<4)
#define OFPC_IP_REASM (1U <<5)
#define OFPC_QUEUE_STATS (1U <<6)
#define OFPC_ARP_MATCH_IP (1U <<7)
static const struct tok ofp_capabilities_bm[] = {
{ OFPC_FLOW_STATS, "FLOW_STATS" },
{ OFPC_TABLE_STATS, "TABLE_STATS" },
{ OFPC_PORT_STATS, "PORT_STATS" },
{ OFPC_STP, "STP" },
{ OFPC_RESERVED, "RESERVED" }, /* not in the mask below */
{ OFPC_IP_REASM, "IP_REASM" },
{ OFPC_QUEUE_STATS, "QUEUE_STATS" },
{ OFPC_ARP_MATCH_IP, "ARP_MATCH_IP" },
{ 0, NULL }
};
#define OFPCAP_U (~(OFPC_FLOW_STATS | OFPC_TABLE_STATS | OFPC_PORT_STATS | \
OFPC_STP | OFPC_IP_REASM | OFPC_QUEUE_STATS | \
OFPC_ARP_MATCH_IP))
#define OFPC_FRAG_NORMAL 0x0000U
#define OFPC_FRAG_DROP 0x0001U
#define OFPC_FRAG_REASM 0x0002U
-#define OFPC_FRAG_MASK 0x0003U
static const struct tok ofp_config_str[] = {
{ OFPC_FRAG_NORMAL, "FRAG_NORMAL" },
{ OFPC_FRAG_DROP, "FRAG_DROP" },
{ OFPC_FRAG_REASM, "FRAG_REASM" },
{ 0, NULL }
};
#define OFPFC_ADD 0x0000U
#define OFPFC_MODIFY 0x0001U
#define OFPFC_MODIFY_STRICT 0x0002U
#define OFPFC_DELETE 0x0003U
#define OFPFC_DELETE_STRICT 0x0004U
static const struct tok ofpfc_str[] = {
{ OFPFC_ADD, "ADD" },
{ OFPFC_MODIFY, "MODIFY" },
{ OFPFC_MODIFY_STRICT, "MODIFY_STRICT" },
{ OFPFC_DELETE, "DELETE" },
{ OFPFC_DELETE_STRICT, "DELETE_STRICT" },
{ 0, NULL }
};
static const struct tok bufferid_str[] = {
{ 0xffffffff, "NONE" },
{ 0, NULL }
};
#define OFPFF_SEND_FLOW_REM (1U <<0)
#define OFPFF_CHECK_OVERLAP (1U <<1)
#define OFPFF_EMERG (1U <<2)
static const struct tok ofpff_bm[] = {
{ OFPFF_SEND_FLOW_REM, "SEND_FLOW_REM" },
{ OFPFF_CHECK_OVERLAP, "CHECK_OVERLAP" },
{ OFPFF_EMERG, "EMERG" },
{ 0, NULL }
};
#define OFPFF_U (~(OFPFF_SEND_FLOW_REM | OFPFF_CHECK_OVERLAP | OFPFF_EMERG))
#define OFPST_DESC 0x0000U
#define OFPST_FLOW 0x0001U
#define OFPST_AGGREGATE 0x0002U
#define OFPST_TABLE 0x0003U
#define OFPST_PORT 0x0004U
#define OFPST_QUEUE 0x0005U
#define OFPST_VENDOR 0xffffU
static const struct tok ofpst_str[] = {
{ OFPST_DESC, "DESC" },
{ OFPST_FLOW, "FLOW" },
{ OFPST_AGGREGATE, "AGGREGATE" },
{ OFPST_TABLE, "TABLE" },
{ OFPST_PORT, "PORT" },
{ OFPST_QUEUE, "QUEUE" },
{ OFPST_VENDOR, "VENDOR" },
{ 0, NULL }
};
static const struct tok tableid_str[] = {
{ 0xfeU, "EMERG" },
{ 0xffU, "ALL" },
{ 0, NULL }
};
#define OFPQ_ALL 0xffffffffU
static const struct tok ofpq_str[] = {
{ OFPQ_ALL, "ALL" },
{ 0, NULL }
};
#define OFPSF_REPLY_MORE 0x0001U
static const struct tok ofpsf_reply_bm[] = {
{ OFPSF_REPLY_MORE, "MORE" },
{ 0, NULL }
};
#define OFPSF_REPLY_U (~(OFPSF_REPLY_MORE))
#define OFPR_NO_MATCH 0x00U
#define OFPR_ACTION 0x01U
static const struct tok ofpr_str[] = {
{ OFPR_NO_MATCH, "NO_MATCH" },
{ OFPR_ACTION, "ACTION" },
{ 0, NULL }
};
#define OFPRR_IDLE_TIMEOUT 0x00U
#define OFPRR_HARD_TIMEOUT 0x01U
#define OFPRR_DELETE 0x02U
static const struct tok ofprr_str[] = {
{ OFPRR_IDLE_TIMEOUT, "IDLE_TIMEOUT" },
{ OFPRR_HARD_TIMEOUT, "HARD_TIMEOUT" },
{ OFPRR_DELETE, "DELETE" },
{ 0, NULL }
};
#define OFPPR_ADD 0x00U
#define OFPPR_DELETE 0x01U
#define OFPPR_MODIFY 0x02U
static const struct tok ofppr_str[] = {
{ OFPPR_ADD, "ADD" },
{ OFPPR_DELETE, "DELETE" },
{ OFPPR_MODIFY, "MODIFY" },
{ 0, NULL }
};
#define OFPET_HELLO_FAILED 0x0000U
#define OFPET_BAD_REQUEST 0x0001U
#define OFPET_BAD_ACTION 0x0002U
#define OFPET_FLOW_MOD_FAILED 0x0003U
#define OFPET_PORT_MOD_FAILED 0x0004U
#define OFPET_QUEUE_OP_FAILED 0x0005U
static const struct tok ofpet_str[] = {
{ OFPET_HELLO_FAILED, "HELLO_FAILED" },
{ OFPET_BAD_REQUEST, "BAD_REQUEST" },
{ OFPET_BAD_ACTION, "BAD_ACTION" },
{ OFPET_FLOW_MOD_FAILED, "FLOW_MOD_FAILED" },
{ OFPET_PORT_MOD_FAILED, "PORT_MOD_FAILED" },
{ OFPET_QUEUE_OP_FAILED, "QUEUE_OP_FAILED" },
{ 0, NULL }
};
#define OFPHFC_INCOMPATIBLE 0x0000U
#define OFPHFC_EPERM 0x0001U
static const struct tok ofphfc_str[] = {
{ OFPHFC_INCOMPATIBLE, "INCOMPATIBLE" },
{ OFPHFC_EPERM, "EPERM" },
{ 0, NULL }
};
#define OFPBRC_BAD_VERSION 0x0000U
#define OFPBRC_BAD_TYPE 0x0001U
#define OFPBRC_BAD_STAT 0x0002U
#define OFPBRC_BAD_VENDOR 0x0003U
#define OFPBRC_BAD_SUBTYPE 0x0004U
#define OFPBRC_EPERM 0x0005U
#define OFPBRC_BAD_LEN 0x0006U
#define OFPBRC_BUFFER_EMPTY 0x0007U
#define OFPBRC_BUFFER_UNKNOWN 0x0008U
static const struct tok ofpbrc_str[] = {
{ OFPBRC_BAD_VERSION, "BAD_VERSION" },
{ OFPBRC_BAD_TYPE, "BAD_TYPE" },
{ OFPBRC_BAD_STAT, "BAD_STAT" },
{ OFPBRC_BAD_VENDOR, "BAD_VENDOR" },
{ OFPBRC_BAD_SUBTYPE, "BAD_SUBTYPE" },
{ OFPBRC_EPERM, "EPERM" },
{ OFPBRC_BAD_LEN, "BAD_LEN" },
{ OFPBRC_BUFFER_EMPTY, "BUFFER_EMPTY" },
{ OFPBRC_BUFFER_UNKNOWN, "BUFFER_UNKNOWN" },
{ 0, NULL }
};
#define OFPBAC_BAD_TYPE 0x0000U
#define OFPBAC_BAD_LEN 0x0001U
#define OFPBAC_BAD_VENDOR 0x0002U
#define OFPBAC_BAD_VENDOR_TYPE 0x0003U
#define OFPBAC_BAD_OUT_PORT 0x0004U
#define OFPBAC_BAD_ARGUMENT 0x0005U
#define OFPBAC_EPERM 0x0006U
#define OFPBAC_TOO_MANY 0x0007U
#define OFPBAC_BAD_QUEUE 0x0008U
static const struct tok ofpbac_str[] = {
{ OFPBAC_BAD_TYPE, "BAD_TYPE" },
{ OFPBAC_BAD_LEN, "BAD_LEN" },
{ OFPBAC_BAD_VENDOR, "BAD_VENDOR" },
{ OFPBAC_BAD_VENDOR_TYPE, "BAD_VENDOR_TYPE" },
{ OFPBAC_BAD_OUT_PORT, "BAD_OUT_PORT" },
{ OFPBAC_BAD_ARGUMENT, "BAD_ARGUMENT" },
{ OFPBAC_EPERM, "EPERM" },
{ OFPBAC_TOO_MANY, "TOO_MANY" },
{ OFPBAC_BAD_QUEUE, "BAD_QUEUE" },
{ 0, NULL }
};
#define OFPFMFC_ALL_TABLES_FULL 0x0000U
#define OFPFMFC_OVERLAP 0x0001U
#define OFPFMFC_EPERM 0x0002U
#define OFPFMFC_BAD_EMERG_TIMEOUT 0x0003U
#define OFPFMFC_BAD_COMMAND 0x0004U
#define OFPFMFC_UNSUPPORTED 0x0005U
static const struct tok ofpfmfc_str[] = {
{ OFPFMFC_ALL_TABLES_FULL, "ALL_TABLES_FULL" },
{ OFPFMFC_OVERLAP, "OVERLAP" },
{ OFPFMFC_EPERM, "EPERM" },
{ OFPFMFC_BAD_EMERG_TIMEOUT, "BAD_EMERG_TIMEOUT" },
{ OFPFMFC_BAD_COMMAND, "BAD_COMMAND" },
{ OFPFMFC_UNSUPPORTED, "UNSUPPORTED" },
{ 0, NULL }
};
#define OFPPMFC_BAD_PORT 0x0000U
#define OFPPMFC_BAD_HW_ADDR 0x0001U
static const struct tok ofppmfc_str[] = {
{ OFPPMFC_BAD_PORT, "BAD_PORT" },
{ OFPPMFC_BAD_HW_ADDR, "BAD_HW_ADDR" },
{ 0, NULL }
};
#define OFPQOFC_BAD_PORT 0x0000U
#define OFPQOFC_BAD_QUEUE 0x0001U
#define OFPQOFC_EPERM 0x0002U
static const struct tok ofpqofc_str[] = {
{ OFPQOFC_BAD_PORT, "BAD_PORT" },
{ OFPQOFC_BAD_QUEUE, "BAD_QUEUE" },
{ OFPQOFC_EPERM, "EPERM" },
{ 0, NULL }
};
static const struct uint_tokary of10_ofpet2tokary[] = {
{ OFPET_HELLO_FAILED, ofphfc_str },
{ OFPET_BAD_REQUEST, ofpbrc_str },
{ OFPET_BAD_ACTION, ofpbac_str },
{ OFPET_FLOW_MOD_FAILED, ofpfmfc_str },
{ OFPET_PORT_MOD_FAILED, ofppmfc_str },
{ OFPET_QUEUE_OP_FAILED, ofpqofc_str },
/* uint2tokary() does not use array termination. */
};
/* lengths (fixed or minimal) of particular message types, where not 0 */
#define OF_SWITCH_CONFIG_FIXLEN (12U - OF_HEADER_FIXLEN)
#define OF_FEATURES_REPLY_MINLEN (32U - OF_HEADER_FIXLEN)
#define OF_PORT_STATUS_FIXLEN (64U - OF_HEADER_FIXLEN)
#define OF_PORT_MOD_FIXLEN (32U - OF_HEADER_FIXLEN)
#define OF_PACKET_IN_MINLEN (20U - OF_HEADER_FIXLEN) /* with 2 mock octets */
#define OF_PACKET_OUT_MINLEN (16U - OF_HEADER_FIXLEN)
#define OF_FLOW_MOD_MINLEN (72U - OF_HEADER_FIXLEN)
#define OF_FLOW_REMOVED_FIXLEN (88U - OF_HEADER_FIXLEN)
#define OF_ERROR_MSG_MINLEN (12U - OF_HEADER_FIXLEN)
#define OF_STATS_REQUEST_MINLEN (12U - OF_HEADER_FIXLEN)
#define OF_STATS_REPLY_MINLEN (12U - OF_HEADER_FIXLEN)
#define OF_VENDOR_MINLEN (12U - OF_HEADER_FIXLEN)
#define OF_QUEUE_GET_CONFIG_REQUEST_FIXLEN (12U - OF_HEADER_FIXLEN)
#define OF_QUEUE_GET_CONFIG_REPLY_MINLEN (16U - OF_HEADER_FIXLEN)
/* lengths (fixed or minimal) of particular protocol structures */
#define OF_PHY_PORT_FIXLEN 48
#define OF_ACTION_MINLEN 8
#define OF_MATCH_FIXLEN 40
#define OF_DESC_STATS_REPLY_FIXLEN 1056
#define OF_FLOW_STATS_REQUEST_FIXLEN 44
#define OF_FLOW_STATS_REPLY_MINLEN 88
#define OF_AGGREGATE_STATS_REPLY_FIXLEN 24
#define OF_TABLE_STATS_REPLY_FIXLEN 64
#define OF_PORT_STATS_REQUEST_FIXLEN 8
#define OF_PORT_STATS_REPLY_FIXLEN 104
#define OF_QUEUE_PROP_MINLEN 8
#define OF_QUEUE_PROP_MIN_RATE_FIXLEN 16
#define OF_PACKET_QUEUE_MINLEN 8
#define OF_QUEUE_STATS_REQUEST_FIXLEN 8
#define OF_QUEUE_STATS_REPLY_FIXLEN 32
/* miscellaneous constants from [OF10] */
#define OFP_MAX_TABLE_NAME_LEN 32
#define OFP_MAX_PORT_NAME_LEN 16
#define DESC_STR_LEN 256
#define SERIAL_NUM_LEN 32
#define OFP_VLAN_NONE 0xffffU
/* vendor extensions */
#define BSN_SET_IP_MASK 0
#define BSN_GET_IP_MASK_REQUEST 1
#define BSN_GET_IP_MASK_REPLY 2
#define BSN_SET_MIRRORING 3
#define BSN_GET_MIRRORING_REQUEST 4
#define BSN_GET_MIRRORING_REPLY 5
#define BSN_SHELL_COMMAND 6
#define BSN_SHELL_OUTPUT 7
#define BSN_SHELL_STATUS 8
#define BSN_GET_INTERFACES_REQUEST 9
#define BSN_GET_INTERFACES_REPLY 10
#define BSN_SET_PKTIN_SUPPRESSION_REQUEST 11
#define BSN_SET_L2_TABLE_REQUEST 12
#define BSN_GET_L2_TABLE_REQUEST 13
#define BSN_GET_L2_TABLE_REPLY 14
#define BSN_VIRTUAL_PORT_CREATE_REQUEST 15
#define BSN_VIRTUAL_PORT_CREATE_REPLY 16
#define BSN_VIRTUAL_PORT_REMOVE_REQUEST 17
#define BSN_BW_ENABLE_SET_REQUEST 18
#define BSN_BW_ENABLE_GET_REQUEST 19
#define BSN_BW_ENABLE_GET_REPLY 20
#define BSN_BW_CLEAR_DATA_REQUEST 21
#define BSN_BW_CLEAR_DATA_REPLY 22
#define BSN_BW_ENABLE_SET_REPLY 23
#define BSN_SET_L2_TABLE_REPLY 24
#define BSN_SET_PKTIN_SUPPRESSION_REPLY 25
#define BSN_VIRTUAL_PORT_REMOVE_REPLY 26
#define BSN_HYBRID_GET_REQUEST 27
#define BSN_HYBRID_GET_REPLY 28
/* 29 */
/* 30 */
#define BSN_PDU_TX_REQUEST 31
#define BSN_PDU_TX_REPLY 32
#define BSN_PDU_RX_REQUEST 33
#define BSN_PDU_RX_REPLY 34
#define BSN_PDU_RX_TIMEOUT 35
static const struct tok bsn_subtype_str[] = {
{ BSN_SET_IP_MASK, "SET_IP_MASK" },
{ BSN_GET_IP_MASK_REQUEST, "GET_IP_MASK_REQUEST" },
{ BSN_GET_IP_MASK_REPLY, "GET_IP_MASK_REPLY" },
{ BSN_SET_MIRRORING, "SET_MIRRORING" },
{ BSN_GET_MIRRORING_REQUEST, "GET_MIRRORING_REQUEST" },
{ BSN_GET_MIRRORING_REPLY, "GET_MIRRORING_REPLY" },
{ BSN_SHELL_COMMAND, "SHELL_COMMAND" },
{ BSN_SHELL_OUTPUT, "SHELL_OUTPUT" },
{ BSN_SHELL_STATUS, "SHELL_STATUS" },
{ BSN_GET_INTERFACES_REQUEST, "GET_INTERFACES_REQUEST" },
{ BSN_GET_INTERFACES_REPLY, "GET_INTERFACES_REPLY" },
{ BSN_SET_PKTIN_SUPPRESSION_REQUEST, "SET_PKTIN_SUPPRESSION_REQUEST" },
{ BSN_SET_L2_TABLE_REQUEST, "SET_L2_TABLE_REQUEST" },
{ BSN_GET_L2_TABLE_REQUEST, "GET_L2_TABLE_REQUEST" },
{ BSN_GET_L2_TABLE_REPLY, "GET_L2_TABLE_REPLY" },
{ BSN_VIRTUAL_PORT_CREATE_REQUEST, "VIRTUAL_PORT_CREATE_REQUEST" },
{ BSN_VIRTUAL_PORT_CREATE_REPLY, "VIRTUAL_PORT_CREATE_REPLY" },
{ BSN_VIRTUAL_PORT_REMOVE_REQUEST, "VIRTUAL_PORT_REMOVE_REQUEST" },
{ BSN_BW_ENABLE_SET_REQUEST, "BW_ENABLE_SET_REQUEST" },
{ BSN_BW_ENABLE_GET_REQUEST, "BW_ENABLE_GET_REQUEST" },
{ BSN_BW_ENABLE_GET_REPLY, "BW_ENABLE_GET_REPLY" },
{ BSN_BW_CLEAR_DATA_REQUEST, "BW_CLEAR_DATA_REQUEST" },
{ BSN_BW_CLEAR_DATA_REPLY, "BW_CLEAR_DATA_REPLY" },
{ BSN_BW_ENABLE_SET_REPLY, "BW_ENABLE_SET_REPLY" },
{ BSN_SET_L2_TABLE_REPLY, "SET_L2_TABLE_REPLY" },
{ BSN_SET_PKTIN_SUPPRESSION_REPLY, "SET_PKTIN_SUPPRESSION_REPLY" },
{ BSN_VIRTUAL_PORT_REMOVE_REPLY, "VIRTUAL_PORT_REMOVE_REPLY" },
{ BSN_HYBRID_GET_REQUEST, "HYBRID_GET_REQUEST" },
{ BSN_HYBRID_GET_REPLY, "HYBRID_GET_REPLY" },
{ BSN_PDU_TX_REQUEST, "PDU_TX_REQUEST" },
{ BSN_PDU_TX_REPLY, "PDU_TX_REPLY" },
{ BSN_PDU_RX_REQUEST, "PDU_RX_REQUEST" },
{ BSN_PDU_RX_REPLY, "PDU_RX_REPLY" },
{ BSN_PDU_RX_TIMEOUT, "PDU_RX_TIMEOUT" },
{ 0, NULL }
};
#define BSN_ACTION_MIRROR 1
#define BSN_ACTION_SET_TUNNEL_DST 2
/* 3 */
#define BSN_ACTION_CHECKSUM 4
static const struct tok bsn_action_subtype_str[] = {
{ BSN_ACTION_MIRROR, "MIRROR" },
{ BSN_ACTION_SET_TUNNEL_DST, "SET_TUNNEL_DST" },
{ BSN_ACTION_CHECKSUM, "CHECKSUM" },
{ 0, NULL }
};
static const struct tok bsn_mirror_copy_stage_str[] = {
{ 0, "INGRESS" },
{ 1, "EGRESS" },
{ 0, NULL },
};
static const struct tok bsn_onoff_str[] = {
{ 0, "OFF" },
{ 1, "ON" },
{ 0, NULL },
};
static const char *
vlan_str(const uint16_t vid)
{
static char buf[sizeof("65535 (bogus)")];
if (vid == OFP_VLAN_NONE)
return "NONE";
snprintf(buf, sizeof(buf), "%u%s", vid,
(vid > 0 && vid < 0x0fff) ? "" : " (bogus)");
return buf;
}
static const char *
pcp_str(const uint8_t pcp)
{
static char buf[sizeof("255 (bogus)")];
snprintf(buf, sizeof(buf), "%u%s", pcp,
pcp <= 7 ? "" : " (bogus)");
return buf;
}
static void
of10_bsn_message_print(netdissect_options *ndo,
const u_char *cp, u_int len)
{
uint32_t subtype;
- if (len < 4)
- goto invalid;
+ ND_PRINT("\n\t");
+ ND_ICHECK_U(len, <, 4);
/* subtype */
subtype = GET_BE_U_4(cp);
OF_FWD(4);
- ND_PRINT("\n\t subtype %s", tok2str(bsn_subtype_str, "unknown (0x%08x)", subtype));
+ ND_PRINT(" subtype %s", tok2str(bsn_subtype_str, "unknown (0x%08x)", subtype));
switch (subtype) {
case BSN_GET_IP_MASK_REQUEST:
/*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +---------------+---------------+---------------+---------------+
* | subtype |
* +---------------+---------------+---------------+---------------+
* | index | pad |
* +---------------+---------------+---------------+---------------+
* | pad |
* +---------------+---------------+---------------+---------------+
*
*/
- if (len != 8)
- goto invalid;
+ ND_ICHECK_U(len, !=, 8);
/* index */
ND_PRINT(", index %u", GET_U_1(cp));
OF_FWD(1);
/* pad */
/* Always the last field, check bounds. */
ND_TCHECK_7(cp);
break;
case BSN_SET_IP_MASK:
case BSN_GET_IP_MASK_REPLY:
/*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +---------------+---------------+---------------+---------------+
* | subtype |
* +---------------+---------------+---------------+---------------+
* | index | pad |
* +---------------+---------------+---------------+---------------+
* | mask |
* +---------------+---------------+---------------+---------------+
*
*/
- if (len != 8)
- goto invalid;
+ ND_ICHECK_U(len, !=, 8);
/* index */
ND_PRINT(", index %u", GET_U_1(cp));
OF_FWD(1);
/* pad */
OF_FWD(3);
/* mask */
ND_PRINT(", mask %s", GET_IPADDR_STRING(cp));
break;
case BSN_SET_MIRRORING:
case BSN_GET_MIRRORING_REQUEST:
case BSN_GET_MIRRORING_REPLY:
/*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +---------------+---------------+---------------+---------------+
* | subtype |
* +---------------+---------------+---------------+---------------+
* | report m. p. | pad |
* +---------------+---------------+---------------+---------------+
*
*/
- if (len != 4)
- goto invalid;
+ ND_ICHECK_U(len, !=, 4);
/* report_mirror_ports */
ND_PRINT(", report_mirror_ports %s",
tok2str(bsn_onoff_str, "bogus (%u)", GET_U_1(cp)));
OF_FWD(1);
/* pad */
/* Always the last field, check bounds. */
ND_TCHECK_3(cp);
break;
case BSN_GET_INTERFACES_REQUEST:
case BSN_GET_L2_TABLE_REQUEST:
case BSN_BW_ENABLE_GET_REQUEST:
case BSN_BW_CLEAR_DATA_REQUEST:
case BSN_HYBRID_GET_REQUEST:
/*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +---------------+---------------+---------------+---------------+
* | subtype |
* +---------------+---------------+---------------+---------------+
*
*/
- if (len)
- goto invalid;
+ ND_ICHECK_U(len, !=, 0);
break;
case BSN_VIRTUAL_PORT_REMOVE_REQUEST:
/*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +---------------+---------------+---------------+---------------+
* | subtype |
* +---------------+---------------+---------------+---------------+
* | vport_no |
* +---------------+---------------+---------------+---------------+
*
*/
- if (len != 4)
- goto invalid;
+ ND_ICHECK_U(len, !=, 4);
/* vport_no */
ND_PRINT(", vport_no %u", GET_BE_U_4(cp));
break;
case BSN_SHELL_COMMAND:
/*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +---------------+---------------+---------------+---------------+
* | subtype |
* +---------------+---------------+---------------+---------------+
* | service |
* +---------------+---------------+---------------+---------------+
* | data ...
* +---------------+---------------+--------
*
*/
- if (len < 4)
- goto invalid;
+ ND_ICHECK_U(len, <, 4);
/* service */
ND_PRINT(", service %u", GET_BE_U_4(cp));
OF_FWD(4);
/* data */
ND_PRINT(", data '");
(void)nd_printn(ndo, cp, len, NULL);
ND_PRINT("'");
break;
case BSN_SHELL_OUTPUT:
/*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +---------------+---------------+---------------+---------------+
* | subtype |
* +---------------+---------------+---------------+---------------+
* | data ...
* +---------------+---------------+--------
*
*/
/* already checked that len >= 4 */
/* data */
ND_PRINT(", data '");
(void)nd_printn(ndo, cp, len, NULL);
ND_PRINT("'");
break;
case BSN_SHELL_STATUS:
/*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +---------------+---------------+---------------+---------------+
* | subtype |
* +---------------+---------------+---------------+---------------+
* | status |
* +---------------+---------------+---------------+---------------+
*
*/
- if (len != 4)
- goto invalid;
+ ND_ICHECK_U(len, !=, 4);
/* status */
ND_PRINT(", status 0x%08x", GET_BE_U_4(cp));
break;
default:
ND_TCHECK_LEN(cp, len);
}
return;
invalid: /* skip the undersized data */
nd_print_invalid(ndo);
ND_TCHECK_LEN(cp, len);
}
static void
of10_bsn_actions_print(netdissect_options *ndo,
const u_char *cp, u_int len)
{
uint32_t subtype, vlan_tag;
- if (len < 4)
- goto invalid;
+ ND_PRINT("\n\t ");
+ ND_ICHECK_U(len, <, 4);
/* subtype */
subtype = GET_BE_U_4(cp);
OF_FWD(4);
- ND_PRINT("\n\t subtype %s", tok2str(bsn_action_subtype_str, "unknown (0x%08x)", subtype));
+ ND_PRINT(" subtype %s", tok2str(bsn_action_subtype_str, "unknown (0x%08x)", subtype));
switch (subtype) {
case BSN_ACTION_MIRROR:
/*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +---------------+---------------+---------------+---------------+
* | subtype |
* +---------------+---------------+---------------+---------------+
* | dest_port |
* +---------------+---------------+---------------+---------------+
* | vlan_tag |
* +---------------+---------------+---------------+---------------+
* | copy_stage | pad |
* +---------------+---------------+---------------+---------------+
*
*/
- if (len != 12)
- goto invalid;
+ ND_ICHECK_U(len, !=, 12);
/* dest_port */
ND_PRINT(", dest_port %u", GET_BE_U_4(cp));
OF_FWD(4);
/* vlan_tag */
vlan_tag = GET_BE_U_4(cp);
OF_FWD(4);
switch (vlan_tag >> 16) {
case 0:
ND_PRINT(", vlan_tag none");
break;
case ETHERTYPE_8021Q:
ND_PRINT(", vlan_tag 802.1Q (%s)", ieee8021q_tci_string(vlan_tag & 0xffff));
break;
default:
ND_PRINT(", vlan_tag unknown (0x%04x)", vlan_tag >> 16);
}
/* copy_stage */
ND_PRINT(", copy_stage %s",
tok2str(bsn_mirror_copy_stage_str, "unknown (%u)", GET_U_1(cp)));
OF_FWD(1);
/* pad */
/* Always the last field, check bounds. */
ND_TCHECK_3(cp);
break;
default:
ND_TCHECK_LEN(cp, len);
}
return;
invalid:
nd_print_invalid(ndo);
ND_TCHECK_LEN(cp, len);
}
static void
of10_vendor_action_print(netdissect_options *ndo,
const u_char *cp, u_int len)
{
uint32_t vendor;
void (*decoder)(netdissect_options *, const u_char *, u_int);
- if (len < 4)
- goto invalid;
+ ND_ICHECK_U(len, <, 4);
/* vendor */
vendor = GET_BE_U_4(cp);
OF_FWD(4);
ND_PRINT(", vendor 0x%08x (%s)", vendor, of_vendor_name(vendor));
/* data */
decoder =
vendor == OUI_BSN ? of10_bsn_actions_print :
of_data_print;
decoder(ndo, cp, len);
return;
invalid: /* skip the undersized data */
nd_print_invalid(ndo);
ND_TCHECK_LEN(cp, len);
}
/* [OF10] Section 5.5.4 */
static void
of10_vendor_message_print(netdissect_options *ndo,
const u_char *cp, u_int len)
{
uint32_t vendor;
void (*decoder)(netdissect_options *, const u_char *, u_int);
/* vendor */
vendor = GET_BE_U_4(cp);
OF_FWD(4);
ND_PRINT(", vendor 0x%08x (%s)", vendor, of_vendor_name(vendor));
/* data */
decoder =
vendor == OUI_BSN ? of10_bsn_message_print :
of_data_print;
decoder(ndo, cp, len);
}
/* Vendor ID is mandatory, data is optional. */
static void
of10_vendor_data_print(netdissect_options *ndo,
const u_char *cp, u_int len)
{
uint32_t vendor;
- if (len < 4)
- goto invalid;
+ ND_ICHECK_U(len, <, 4);
/* vendor */
vendor = GET_BE_U_4(cp);
OF_FWD(4);
ND_PRINT(", vendor 0x%08x (%s)", vendor, of_vendor_name(vendor));
/* data */
of_data_print(ndo, cp, len);
return;
invalid: /* skip the undersized data */
nd_print_invalid(ndo);
ND_TCHECK_LEN(cp, len);
}
static void
of10_packet_data_print(netdissect_options *ndo,
const u_char *cp, const u_int len)
{
if (len == 0)
return;
/* data */
ND_PRINT("\n\t data (%u octets)", len);
if (ndo->ndo_vflag < 3) {
ND_TCHECK_LEN(cp, len);
return;
}
ndo->ndo_vflag -= 3;
ND_PRINT(", frame decoding below\n");
/*
* The encapsulated Ethernet frame is not necessarily the last
* data of this packet (i.e. there may be more OpenFlow messages
* after the current OFPT_PACKET_IN/OFPT_PACKET_OUT message, in
* which case the current (outer) packet's snapshot end is not
* what ether_print() needs to decode an Ethernet frame nested in
* the middle of a TCP payload.
*/
const u_char *snapend_save = ndo->ndo_snapend;
ndo->ndo_snapend = ND_MIN(cp + len, ndo->ndo_snapend);
ether_print(ndo, cp, len, ND_BYTES_AVAILABLE_AFTER(cp), NULL, NULL);
ndo->ndo_snapend = snapend_save;
ndo->ndo_vflag += 3;
}
/* [OF10] Section 5.2.1 */
static void
of10_phy_port_print(netdissect_options *ndo,
const u_char *cp)
{
uint32_t state;
/* port_no */
ND_PRINT("\n\t port_no %s",
tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
cp += 2;
/* hw_addr */
ND_PRINT(", hw_addr %s", GET_ETHERADDR_STRING(cp));
cp += MAC_ADDR_LEN;
/* name */
ND_PRINT(", name '");
nd_printjnp(ndo, cp, OFP_MAX_PORT_NAME_LEN);
ND_PRINT("'");
cp += OFP_MAX_PORT_NAME_LEN;
if (ndo->ndo_vflag < 2) {
ND_TCHECK_LEN(cp, 24);
return;
}
/* config */
ND_PRINT("\n\t config 0x%08x", GET_BE_U_4(cp));
of_bitmap_print(ndo, ofppc_bm, GET_BE_U_4(cp), OFPPC_U);
cp += 4;
/* state */
state = GET_BE_U_4(cp);
/*
* Decode the code point and the single bit separately, but
* format the result as a single sequence of comma-separated
* strings (see the comments at the OFPPS_ props).
*/
ND_PRINT("\n\t state 0x%08x (%s%s)%s", state,
tok2str(ofpps_stp_str, "", state & OFPPS_STP_MASK),
state & OFPPS_LINK_DOWN ? ", LINK_DOWN" : "",
state & OFPPS_U ? " (bogus)" : "");
cp += 4;
/* curr */
ND_PRINT("\n\t curr 0x%08x", GET_BE_U_4(cp));
of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
cp += 4;
/* advertised */
ND_PRINT("\n\t advertised 0x%08x", GET_BE_U_4(cp));
of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
cp += 4;
/* supported */
ND_PRINT("\n\t supported 0x%08x", GET_BE_U_4(cp));
of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
cp += 4;
/* peer */
ND_PRINT("\n\t peer 0x%08x", GET_BE_U_4(cp));
of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
}
/* [OF10] Section 5.2.2 */
static void
of10_queue_props_print(netdissect_options *ndo,
const u_char *cp, u_int len)
{
while (len) {
uint16_t property, plen;
u_char plen_bogus = 0, skip = 0;
- if (len < OF_QUEUE_PROP_MINLEN)
- goto invalid;
+ ND_PRINT("\n\t ");
+ ND_ICHECKMSG_U("remaining length", len, <, OF_QUEUE_PROP_MINLEN);
/* property */
property = GET_BE_U_2(cp);
OF_FWD(2);
- ND_PRINT("\n\t property %s", tok2str(ofpqt_str, "invalid (0x%04x)", property));
+ ND_PRINT(" property %s", tok2str(ofpqt_str, "invalid (0x%04x)", property));
/* len */
plen = GET_BE_U_2(cp);
OF_FWD(2);
ND_PRINT(", len %u", plen);
- if (plen < OF_QUEUE_PROP_MINLEN || plen > len + 4)
- goto invalid;
+ ND_ICHECKMSG_U("property length", plen, <, OF_QUEUE_PROP_MINLEN);
+ ND_ICHECKMSG_U("property length", plen, >, len + 4);
/* pad */
/* Sometimes the last field, check bounds. */
OF_CHK_FWD(4);
/* property-specific constraints and decoding */
switch (property) {
case OFPQT_NONE:
plen_bogus = plen != OF_QUEUE_PROP_MINLEN;
break;
case OFPQT_MIN_RATE:
plen_bogus = plen != OF_QUEUE_PROP_MIN_RATE_FIXLEN;
break;
default:
skip = 1;
}
if (plen_bogus) {
ND_PRINT(" (bogus)");
skip = 1;
}
if (skip) {
/*
* plen >= OF_QUEUE_PROP_MINLEN
* cp is OF_QUEUE_PROP_MINLEN bytes in
*/
OF_CHK_FWD(plen - OF_QUEUE_PROP_MINLEN);
continue;
}
if (property == OFPQT_MIN_RATE) { /* the only case of property decoding */
/* rate */
uint16_t rate = GET_BE_U_2(cp);
OF_FWD(2);
if (rate > 1000)
ND_PRINT(", rate disabled");
else
ND_PRINT(", rate %u.%u%%", rate / 10, rate % 10);
/* pad */
/* Sometimes the last field, check bounds. */
OF_CHK_FWD(6);
}
} /* while */
return;
invalid: /* skip the rest of queue properties */
nd_print_invalid(ndo);
ND_TCHECK_LEN(cp, len);
}
/* ibid */
static void
of10_queues_print(netdissect_options *ndo,
const u_char *cp, u_int len)
{
while (len) {
uint16_t desclen;
- if (len < OF_PACKET_QUEUE_MINLEN)
- goto invalid;
+ ND_PRINT("\n\t ");
+ ND_ICHECKMSG_U("remaining length", len, <, OF_PACKET_QUEUE_MINLEN);
/* queue_id */
- ND_PRINT("\n\t queue_id %u", GET_BE_U_4(cp));
+ ND_PRINT(" queue_id %u", GET_BE_U_4(cp));
OF_FWD(4);
/* len */
desclen = GET_BE_U_2(cp);
OF_FWD(2);
ND_PRINT(", len %u", desclen);
- if (desclen < OF_PACKET_QUEUE_MINLEN || desclen > len + 6)
- goto invalid;
+ ND_ICHECKMSG_U("prop. desc. length", desclen, <, OF_PACKET_QUEUE_MINLEN);
+ ND_ICHECKMSG_U("prop. desc. length", desclen, >, len + 6);
/* pad */
/* Sometimes the last field, check bounds. */
OF_CHK_FWD(2);
/* properties */
if (ndo->ndo_vflag >= 2)
of10_queue_props_print(ndo, cp, desclen - OF_PACKET_QUEUE_MINLEN);
else
ND_TCHECK_LEN(cp, desclen - OF_PACKET_QUEUE_MINLEN);
OF_FWD(desclen - OF_PACKET_QUEUE_MINLEN);
} /* while */
return;
invalid: /* skip the rest of queues */
nd_print_invalid(ndo);
ND_TCHECK_LEN(cp, len);
}
/* [OF10] Section 5.2.3 */
static void
of10_match_print(netdissect_options *ndo,
const char *pfx, const u_char *cp)
{
uint32_t wildcards;
uint16_t dl_type;
uint8_t nw_proto;
u_int nw_bits;
const char *field_name;
/* wildcards */
wildcards = GET_BE_U_4(cp);
if (wildcards & OFPFW_U)
ND_PRINT("%swildcards 0x%08x (bogus)", pfx, wildcards);
cp += 4;
/* in_port */
if (! (wildcards & OFPFW_IN_PORT))
ND_PRINT("%smatch in_port %s", pfx,
tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
cp += 2;
/* dl_src */
if (! (wildcards & OFPFW_DL_SRC))
ND_PRINT("%smatch dl_src %s", pfx, GET_ETHERADDR_STRING(cp));
cp += MAC_ADDR_LEN;
/* dl_dst */
if (! (wildcards & OFPFW_DL_DST))
ND_PRINT("%smatch dl_dst %s", pfx, GET_ETHERADDR_STRING(cp));
cp += MAC_ADDR_LEN;
/* dl_vlan */
if (! (wildcards & OFPFW_DL_VLAN))
ND_PRINT("%smatch dl_vlan %s", pfx, vlan_str(GET_BE_U_2(cp)));
cp += 2;
/* dl_vlan_pcp */
if (! (wildcards & OFPFW_DL_VLAN_PCP))
ND_PRINT("%smatch dl_vlan_pcp %s", pfx, pcp_str(GET_U_1(cp)));
cp += 1;
/* pad1 */
cp += 1;
/* dl_type */
dl_type = GET_BE_U_2(cp);
cp += 2;
if (! (wildcards & OFPFW_DL_TYPE))
ND_PRINT("%smatch dl_type 0x%04x", pfx, dl_type);
/* nw_tos */
if (! (wildcards & OFPFW_NW_TOS))
ND_PRINT("%smatch nw_tos 0x%02x", pfx, GET_U_1(cp));
cp += 1;
/* nw_proto */
nw_proto = GET_U_1(cp);
cp += 1;
if (! (wildcards & OFPFW_NW_PROTO)) {
field_name = ! (wildcards & OFPFW_DL_TYPE) && dl_type == ETHERTYPE_ARP
? "arp_opcode" : "nw_proto";
ND_PRINT("%smatch %s %u", pfx, field_name, nw_proto);
}
/* pad2 */
cp += 2;
/* nw_src */
nw_bits = (wildcards & OFPFW_NW_SRC_MASK) >> OFPFW_NW_SRC_SHIFT;
if (nw_bits < 32)
ND_PRINT("%smatch nw_src %s/%u", pfx, GET_IPADDR_STRING(cp), 32 - nw_bits);
cp += 4;
/* nw_dst */
nw_bits = (wildcards & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT;
if (nw_bits < 32)
ND_PRINT("%smatch nw_dst %s/%u", pfx, GET_IPADDR_STRING(cp), 32 - nw_bits);
cp += 4;
/* tp_src */
if (! (wildcards & OFPFW_TP_SRC)) {
field_name = ! (wildcards & OFPFW_DL_TYPE) && dl_type == ETHERTYPE_IP
&& ! (wildcards & OFPFW_NW_PROTO) && nw_proto == IPPROTO_ICMP
? "icmp_type" : "tp_src";
ND_PRINT("%smatch %s %u", pfx, field_name, GET_BE_U_2(cp));
}
cp += 2;
/* tp_dst */
/* The last unconditional check was at nw_proto, so have an "else" here. */
if (! (wildcards & OFPFW_TP_DST)) {
field_name = ! (wildcards & OFPFW_DL_TYPE) && dl_type == ETHERTYPE_IP
&& ! (wildcards & OFPFW_NW_PROTO) && nw_proto == IPPROTO_ICMP
? "icmp_code" : "tp_dst";
ND_PRINT("%smatch %s %u", pfx, field_name, GET_BE_U_2(cp));
- }
- else
+ } else
ND_TCHECK_2(cp);
}
/* [OF10] Section 5.2.4 */
static void
of10_actions_print(netdissect_options *ndo,
const char *pfx, const u_char *cp, u_int len)
{
while (len) {
uint16_t type, alen, output_port;
u_char alen_bogus = 0, skip = 0;
- if (len < OF_ACTION_MINLEN)
- goto invalid;
+ ND_PRINT("%saction", pfx);
+ ND_ICHECKMSG_U("remaining length", len, <, OF_ACTION_MINLEN);
/* type */
type = GET_BE_U_2(cp);
OF_FWD(2);
- ND_PRINT("%saction type %s", pfx, tok2str(ofpat_str, "invalid (0x%04x)", type));
+ ND_PRINT(" type %s", tok2str(ofpat_str, "invalid (0x%04x)", type));
/* length */
alen = GET_BE_U_2(cp);
OF_FWD(2);
ND_PRINT(", len %u", alen);
/*
* The 4-byte "pad" in the specification is not a field of the
* action header, but a placeholder to illustrate the 64-bit
* alignment requirement. Action type specific case blocks
* below fetch these 4 bytes.
*/
/* On action size underrun/overrun skip the rest of the action list. */
- if (alen < OF_ACTION_MINLEN || alen > len + 4)
- goto invalid;
+ ND_ICHECK_U(alen, <, OF_ACTION_MINLEN);
+ ND_ICHECK_U(alen, >, len + 4);
/*
* After validating the basic length constraint it will be safe
* to skip the current action if the action size is not valid
* for the type or the type is invalid.
*/
switch (type) {
case OFPAT_OUTPUT:
case OFPAT_SET_VLAN_VID:
case OFPAT_SET_VLAN_PCP:
case OFPAT_STRIP_VLAN:
case OFPAT_SET_NW_SRC:
case OFPAT_SET_NW_DST:
case OFPAT_SET_NW_TOS:
case OFPAT_SET_TP_SRC:
case OFPAT_SET_TP_DST:
alen_bogus = alen != 8;
break;
case OFPAT_SET_DL_SRC:
case OFPAT_SET_DL_DST:
case OFPAT_ENQUEUE:
alen_bogus = alen != 16;
break;
case OFPAT_VENDOR:
alen_bogus = alen % 8 != 0; /* already >= 8 so far */
break;
default:
skip = 1;
}
if (alen_bogus) {
ND_PRINT(" (bogus)");
skip = 1;
}
if (skip) {
/*
* alen >= OF_ACTION_MINLEN
* cp is 4 bytes in
*/
OF_CHK_FWD(alen - 4);
continue;
}
/* OK to decode the rest of the action structure */
switch (type) {
case OFPAT_OUTPUT:
/* port */
output_port = GET_BE_U_2(cp);
OF_FWD(2);
ND_PRINT(", port %s", tok2str(ofpp_str, "%u", output_port));
/* max_len */
if (output_port == OFPP_CONTROLLER)
ND_PRINT(", max_len %u", GET_BE_U_2(cp));
else
ND_TCHECK_2(cp);
OF_FWD(2);
break;
case OFPAT_SET_VLAN_VID:
/* vlan_vid */
ND_PRINT(", vlan_vid %s", vlan_str(GET_BE_U_2(cp)));
OF_FWD(2);
/* pad */
/* Sometimes the last field, check bounds. */
OF_CHK_FWD(2);
break;
case OFPAT_SET_VLAN_PCP:
/* vlan_pcp */
ND_PRINT(", vlan_pcp %s", pcp_str(GET_U_1(cp)));
OF_FWD(1);
/* pad */
/* Sometimes the last field, check bounds. */
OF_CHK_FWD(3);
break;
case OFPAT_SET_DL_SRC:
case OFPAT_SET_DL_DST:
/* dl_addr */
ND_PRINT(", dl_addr %s", GET_ETHERADDR_STRING(cp));
OF_FWD(MAC_ADDR_LEN);
/* pad */
/* Sometimes the last field, check bounds. */
OF_CHK_FWD(6);
break;
case OFPAT_SET_NW_SRC:
case OFPAT_SET_NW_DST:
/* nw_addr */
ND_PRINT(", nw_addr %s", GET_IPADDR_STRING(cp));
OF_FWD(4);
break;
case OFPAT_SET_NW_TOS:
/* nw_tos */
ND_PRINT(", nw_tos 0x%02x", GET_U_1(cp));
OF_FWD(1);
/* pad */
/* Sometimes the last field, check bounds. */
OF_CHK_FWD(3);
break;
case OFPAT_SET_TP_SRC:
case OFPAT_SET_TP_DST:
/* nw_tos */
ND_PRINT(", tp_port %u", GET_BE_U_2(cp));
OF_FWD(2);
/* pad */
/* Sometimes the last field, check bounds. */
OF_CHK_FWD(2);
break;
case OFPAT_ENQUEUE:
/* port */
ND_PRINT(", port %s",
tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
OF_FWD(2);
/* pad */
OF_FWD(6);
/* queue_id */
ND_PRINT(", queue_id %s",
tok2str(ofpq_str, "%u", GET_BE_U_4(cp)));
OF_FWD(4);
break;
case OFPAT_VENDOR:
of10_vendor_action_print(ndo, cp, alen - 4);
OF_FWD(alen - 4);
break;
case OFPAT_STRIP_VLAN:
/* pad */
/* Sometimes the last field, check bounds. */
OF_CHK_FWD(4);
break;
} /* switch */
} /* while */
return;
invalid: /* skip the rest of actions */
nd_print_invalid(ndo);
ND_TCHECK_LEN(cp, len);
}
/* [OF10] Section 5.3.1 */
static void
of10_features_reply_print(netdissect_options *ndo,
const u_char *cp, u_int len)
{
/* datapath_id */
ND_PRINT("\n\t dpid 0x%016" PRIx64, GET_BE_U_8(cp));
OF_FWD(8);
/* n_buffers */
ND_PRINT(", n_buffers %u", GET_BE_U_4(cp));
OF_FWD(4);
/* n_tables */
ND_PRINT(", n_tables %u", GET_U_1(cp));
OF_FWD(1);
/* pad */
OF_FWD(3);
/* capabilities */
ND_PRINT("\n\t capabilities 0x%08x", GET_BE_U_4(cp));
of_bitmap_print(ndo, ofp_capabilities_bm, GET_BE_U_4(cp), OFPCAP_U);
OF_FWD(4);
/* actions */
ND_PRINT("\n\t actions 0x%08x", GET_BE_U_4(cp));
of_bitmap_print(ndo, ofpat_bm, GET_BE_U_4(cp), OFPAT_U);
OF_FWD(4);
/* ports */
while (len) {
- if (len < OF_PHY_PORT_FIXLEN)
- goto invalid;
+ ND_ICHECKMSG_U("\n\t port def. length", len, <, OF_PHY_PORT_FIXLEN);
of10_phy_port_print(ndo, cp);
OF_FWD(OF_PHY_PORT_FIXLEN);
}
return;
invalid: /* skip the undersized trailing data */
nd_print_invalid(ndo);
ND_TCHECK_LEN(cp, len);
}
/* [OF10] Section 5.3.2 */
static void
of10_switch_config_msg_print(netdissect_options *ndo,
const u_char *cp, u_int len _U_)
{
/* flags */
ND_PRINT("\n\t flags %s",
tok2str(ofp_config_str, "invalid (0x%04x)", GET_BE_U_2(cp)));
cp += 2;
/* miss_send_len */
ND_PRINT(", miss_send_len %u", GET_BE_U_2(cp));
}
/* [OF10] Section 5.3.3 */
static void
of10_flow_mod_print(netdissect_options *ndo,
const u_char *cp, u_int len)
{
uint16_t command;
/* match */
of10_match_print(ndo, "\n\t ", cp);
OF_FWD(OF_MATCH_FIXLEN);
/* cookie */
ND_PRINT("\n\t cookie 0x%016" PRIx64, GET_BE_U_8(cp));
OF_FWD(8);
/* command */
command = GET_BE_U_2(cp);
ND_PRINT(", command %s", tok2str(ofpfc_str, "invalid (0x%04x)", command));
OF_FWD(2);
/* idle_timeout */
if (GET_BE_U_2(cp))
ND_PRINT(", idle_timeout %u", GET_BE_U_2(cp));
OF_FWD(2);
/* hard_timeout */
if (GET_BE_U_2(cp))
ND_PRINT(", hard_timeout %u", GET_BE_U_2(cp));
OF_FWD(2);
/* priority */
if (GET_BE_U_2(cp))
ND_PRINT(", priority %u", GET_BE_U_2(cp));
OF_FWD(2);
/* buffer_id */
if (command == OFPFC_ADD || command == OFPFC_MODIFY ||
command == OFPFC_MODIFY_STRICT)
ND_PRINT(", buffer_id %s",
tok2str(bufferid_str, "0x%08x", GET_BE_U_4(cp)));
OF_FWD(4);
/* out_port */
if (command == OFPFC_DELETE || command == OFPFC_DELETE_STRICT)
ND_PRINT(", out_port %s",
tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
OF_FWD(2);
/* flags */
ND_PRINT(", flags 0x%04x", GET_BE_U_2(cp));
of_bitmap_print(ndo, ofpff_bm, GET_BE_U_2(cp), OFPFF_U);
OF_FWD(2);
/* actions */
of10_actions_print(ndo, "\n\t ", cp, len);
}
/* ibid */
static void
of10_port_mod_print(netdissect_options *ndo,
const u_char *cp, u_int len _U_)
{
/* port_no */
ND_PRINT("\n\t port_no %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
cp += 2;
/* hw_addr */
ND_PRINT(", hw_addr %s", GET_ETHERADDR_STRING(cp));
cp += MAC_ADDR_LEN;
/* config */
- ND_PRINT("\n\t config 0x%08x", GET_BE_U_4(cp));
+ ND_PRINT("\n\t config 0x%08x", GET_BE_U_4(cp));
of_bitmap_print(ndo, ofppc_bm, GET_BE_U_4(cp), OFPPC_U);
cp += 4;
/* mask */
- ND_PRINT("\n\t mask 0x%08x", GET_BE_U_4(cp));
+ ND_PRINT("\n\t mask 0x%08x", GET_BE_U_4(cp));
of_bitmap_print(ndo, ofppc_bm, GET_BE_U_4(cp), OFPPC_U);
cp += 4;
/* advertise */
- ND_PRINT("\n\t advertise 0x%08x", GET_BE_U_4(cp));
+ ND_PRINT("\n\t advertise 0x%08x", GET_BE_U_4(cp));
of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
cp += 4;
/* pad */
/* Always the last field, check bounds. */
ND_TCHECK_4(cp);
}
/* [OF10] Section 5.3.4 */
static void
of10_queue_get_config_request_print(netdissect_options *ndo,
const u_char *cp, u_int len _U_)
{
/* port */
ND_PRINT("\n\t port %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
cp += 2;
/* pad */
/* Always the last field, check bounds. */
ND_TCHECK_2(cp);
}
/* ibid */
static void
of10_queue_get_config_reply_print(netdissect_options *ndo,
const u_char *cp, u_int len)
{
/* port */
ND_PRINT("\n\t port %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
OF_FWD(2);
/* pad */
/* Sometimes the last field, check bounds. */
OF_CHK_FWD(6);
/* queues */
of10_queues_print(ndo, cp, len);
}
/* [OF10] Section 5.3.5 */
static void
of10_stats_request_print(netdissect_options *ndo,
const u_char *cp, u_int len)
{
uint16_t type;
/* type */
type = GET_BE_U_2(cp);
OF_FWD(2);
ND_PRINT("\n\t type %s", tok2str(ofpst_str, "invalid (0x%04x)", type));
/* flags */
ND_PRINT(", flags 0x%04x", GET_BE_U_2(cp));
if (GET_BE_U_2(cp))
ND_PRINT(" (bogus)");
OF_FWD(2);
/* type-specific body of one of fixed lengths */
switch(type) {
case OFPST_DESC:
case OFPST_TABLE:
- if (len)
- goto invalid;
+ ND_ICHECK_U(len, !=, 0);
return;
case OFPST_FLOW:
case OFPST_AGGREGATE:
- if (len != OF_FLOW_STATS_REQUEST_FIXLEN)
- goto invalid;
+ ND_ICHECK_U(len, !=, OF_FLOW_STATS_REQUEST_FIXLEN);
/* match */
of10_match_print(ndo, "\n\t ", cp);
OF_FWD(OF_MATCH_FIXLEN);
/* table_id */
ND_PRINT("\n\t table_id %s",
tok2str(tableid_str, "%u", GET_U_1(cp)));
OF_FWD(1);
/* pad */
OF_FWD(1);
/* out_port */
ND_PRINT(", out_port %s",
tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
return;
case OFPST_PORT:
- if (len != OF_PORT_STATS_REQUEST_FIXLEN)
- goto invalid;
+ ND_ICHECK_U(len, !=, OF_PORT_STATS_REQUEST_FIXLEN);
/* port_no */
ND_PRINT("\n\t port_no %s",
tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
OF_FWD(2);
/* pad */
/* Always the last field, check bounds. */
OF_CHK_FWD(6);
return;
case OFPST_QUEUE:
- if (len != OF_QUEUE_STATS_REQUEST_FIXLEN)
- goto invalid;
+ ND_ICHECK_U(len, !=, OF_QUEUE_STATS_REQUEST_FIXLEN);
/* port_no */
ND_PRINT("\n\t port_no %s",
tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
OF_FWD(2);
/* pad */
OF_FWD(2);
/* queue_id */
ND_PRINT(", queue_id %s",
tok2str(ofpq_str, "%u", GET_BE_U_4(cp)));
return;
case OFPST_VENDOR:
of10_vendor_data_print(ndo, cp, len);
return;
}
return;
invalid: /* skip the message body */
nd_print_invalid(ndo);
ND_TCHECK_LEN(cp, len);
}
/* ibid */
static void
of10_desc_stats_reply_print(netdissect_options *ndo,
const u_char *cp, u_int len)
{
- if (len != OF_DESC_STATS_REPLY_FIXLEN)
- goto invalid;
+ ND_PRINT("\n\t ");
+ ND_ICHECK_U(len, !=, OF_DESC_STATS_REPLY_FIXLEN);
/* mfr_desc */
- ND_PRINT("\n\t mfr_desc '");
+ ND_PRINT(" mfr_desc '");
nd_printjnp(ndo, cp, DESC_STR_LEN);
ND_PRINT("'");
OF_FWD(DESC_STR_LEN);
/* hw_desc */
ND_PRINT("\n\t hw_desc '");
nd_printjnp(ndo, cp, DESC_STR_LEN);
ND_PRINT("'");
OF_FWD(DESC_STR_LEN);
/* sw_desc */
ND_PRINT("\n\t sw_desc '");
nd_printjnp(ndo, cp, DESC_STR_LEN);
ND_PRINT("'");
OF_FWD(DESC_STR_LEN);
/* serial_num */
ND_PRINT("\n\t serial_num '");
nd_printjnp(ndo, cp, SERIAL_NUM_LEN);
ND_PRINT("'");
OF_FWD(SERIAL_NUM_LEN);
/* dp_desc */
ND_PRINT("\n\t dp_desc '");
nd_printjnp(ndo, cp, DESC_STR_LEN);
ND_PRINT("'");
return;
invalid: /* skip the message body */
nd_print_invalid(ndo);
ND_TCHECK_LEN(cp, len);
}
/* ibid */
static void
of10_flow_stats_reply_print(netdissect_options *ndo,
const u_char *cp, u_int len)
{
while (len) {
uint16_t entry_len;
- if (len < OF_FLOW_STATS_REPLY_MINLEN)
- goto invalid;
+ ND_PRINT("\n\t");
+ ND_ICHECKMSG_U("remaining length", len, <, OF_FLOW_STATS_REPLY_MINLEN);
/* length */
entry_len = GET_BE_U_2(cp);
- ND_PRINT("\n\t length %u", entry_len);
- if (entry_len < OF_FLOW_STATS_REPLY_MINLEN || entry_len > len)
- goto invalid;
+ ND_PRINT(" length %u", entry_len);
+ ND_ICHECK_U(entry_len, <, OF_FLOW_STATS_REPLY_MINLEN);
+ ND_ICHECK_U(entry_len, >, len);
OF_FWD(2);
/* table_id */
ND_PRINT(", table_id %s",
tok2str(tableid_str, "%u", GET_U_1(cp)));
OF_FWD(1);
/* pad */
OF_FWD(1);
/* match */
of10_match_print(ndo, "\n\t ", cp);
OF_FWD(OF_MATCH_FIXLEN);
/* duration_sec */
ND_PRINT("\n\t duration_sec %u", GET_BE_U_4(cp));
OF_FWD(4);
/* duration_nsec */
ND_PRINT(", duration_nsec %u", GET_BE_U_4(cp));
OF_FWD(4);
/* priority */
ND_PRINT(", priority %u", GET_BE_U_2(cp));
OF_FWD(2);
/* idle_timeout */
ND_PRINT(", idle_timeout %u", GET_BE_U_2(cp));
OF_FWD(2);
/* hard_timeout */
ND_PRINT(", hard_timeout %u", GET_BE_U_2(cp));
OF_FWD(2);
/* pad2 */
OF_FWD(6);
/* cookie */
ND_PRINT(", cookie 0x%016" PRIx64, GET_BE_U_8(cp));
OF_FWD(8);
/* packet_count */
ND_PRINT(", packet_count %" PRIu64, GET_BE_U_8(cp));
OF_FWD(8);
/* byte_count */
ND_PRINT(", byte_count %" PRIu64, GET_BE_U_8(cp));
OF_FWD(8);
/* actions */
of10_actions_print(ndo, "\n\t ", cp, entry_len - OF_FLOW_STATS_REPLY_MINLEN);
OF_FWD(entry_len - OF_FLOW_STATS_REPLY_MINLEN);
} /* while */
return;
invalid: /* skip the rest of flow statistics entries */
nd_print_invalid(ndo);
ND_TCHECK_LEN(cp, len);
}
/* ibid */
static void
of10_aggregate_stats_reply_print(netdissect_options *ndo,
const u_char *cp, u_int len)
{
- if (len != OF_AGGREGATE_STATS_REPLY_FIXLEN)
- goto invalid;
+ ND_PRINT("\n\t");
+ ND_ICHECKMSG_U("remaining length", len, !=, OF_AGGREGATE_STATS_REPLY_FIXLEN);
/* packet_count */
- ND_PRINT("\n\t packet_count %" PRIu64, GET_BE_U_8(cp));
+ ND_PRINT(" packet_count %" PRIu64, GET_BE_U_8(cp));
OF_FWD(8);
/* byte_count */
ND_PRINT(", byte_count %" PRIu64, GET_BE_U_8(cp));
OF_FWD(8);
/* flow_count */
ND_PRINT(", flow_count %u", GET_BE_U_4(cp));
OF_FWD(4);
/* pad */
/* Always the last field, check bounds. */
ND_TCHECK_4(cp);
return;
invalid: /* skip the message body */
nd_print_invalid(ndo);
ND_TCHECK_LEN(cp, len);
}
/* ibid */
static void
of10_table_stats_reply_print(netdissect_options *ndo,
const u_char *cp, u_int len)
{
while (len) {
- if (len < OF_TABLE_STATS_REPLY_FIXLEN)
- goto invalid;
+ ND_PRINT("\n\t");
+ ND_ICHECKMSG_U("remaining length", len, <, OF_TABLE_STATS_REPLY_FIXLEN);
/* table_id */
- ND_PRINT("\n\t table_id %s",
+ ND_PRINT(" table_id %s",
tok2str(tableid_str, "%u", GET_U_1(cp)));
OF_FWD(1);
/* pad */
OF_FWD(3);
/* name */
ND_PRINT(", name '");
nd_printjnp(ndo, cp, OFP_MAX_TABLE_NAME_LEN);
ND_PRINT("'");
OF_FWD(OFP_MAX_TABLE_NAME_LEN);
/* wildcards */
ND_PRINT("\n\t wildcards 0x%08x", GET_BE_U_4(cp));
of_bitmap_print(ndo, ofpfw_bm, GET_BE_U_4(cp), OFPFW_U);
OF_FWD(4);
/* max_entries */
ND_PRINT("\n\t max_entries %u", GET_BE_U_4(cp));
OF_FWD(4);
/* active_count */
ND_PRINT(", active_count %u", GET_BE_U_4(cp));
OF_FWD(4);
/* lookup_count */
ND_PRINT(", lookup_count %" PRIu64, GET_BE_U_8(cp));
OF_FWD(8);
/* matched_count */
ND_PRINT(", matched_count %" PRIu64, GET_BE_U_8(cp));
OF_FWD(8);
} /* while */
return;
invalid: /* skip the undersized trailing data */
nd_print_invalid(ndo);
ND_TCHECK_LEN(cp, len);
}
/* ibid */
static void
of10_port_stats_reply_print(netdissect_options *ndo,
const u_char *cp, u_int len)
{
while (len) {
- if (len < OF_PORT_STATS_REPLY_FIXLEN)
- goto invalid;
+ ND_PRINT("\n\t ");
+ ND_ICHECKMSG_U("remaining length", len, <, OF_PORT_STATS_REPLY_FIXLEN);
/* port_no */
- ND_PRINT("\n\t port_no %s",
+ ND_PRINT(" port_no %s",
tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
OF_FWD(2);
if (ndo->ndo_vflag < 2) {
OF_CHK_FWD(OF_PORT_STATS_REPLY_FIXLEN - 2);
continue;
}
/* pad */
OF_FWD(6);
/* rx_packets */
ND_PRINT(", rx_packets %" PRIu64, GET_BE_U_8(cp));
OF_FWD(8);
/* tx_packets */
ND_PRINT(", tx_packets %" PRIu64, GET_BE_U_8(cp));
OF_FWD(8);
/* rx_bytes */
ND_PRINT(", rx_bytes %" PRIu64, GET_BE_U_8(cp));
OF_FWD(8);
/* tx_bytes */
ND_PRINT(", tx_bytes %" PRIu64, GET_BE_U_8(cp));
OF_FWD(8);
/* rx_dropped */
ND_PRINT(", rx_dropped %" PRIu64, GET_BE_U_8(cp));
OF_FWD(8);
/* tx_dropped */
ND_PRINT(", tx_dropped %" PRIu64, GET_BE_U_8(cp));
OF_FWD(8);
/* rx_errors */
ND_PRINT(", rx_errors %" PRIu64, GET_BE_U_8(cp));
OF_FWD(8);
/* tx_errors */
ND_PRINT(", tx_errors %" PRIu64, GET_BE_U_8(cp));
OF_FWD(8);
/* rx_frame_err */
ND_PRINT(", rx_frame_err %" PRIu64, GET_BE_U_8(cp));
OF_FWD(8);
/* rx_over_err */
ND_PRINT(", rx_over_err %" PRIu64, GET_BE_U_8(cp));
OF_FWD(8);
/* rx_crc_err */
ND_PRINT(", rx_crc_err %" PRIu64, GET_BE_U_8(cp));
OF_FWD(8);
/* collisions */
ND_PRINT(", collisions %" PRIu64, GET_BE_U_8(cp));
OF_FWD(8);
} /* while */
return;
invalid: /* skip the undersized trailing data */
nd_print_invalid(ndo);
ND_TCHECK_LEN(cp, len);
}
/* ibid */
static void
of10_queue_stats_reply_print(netdissect_options *ndo,
const u_char *cp, u_int len)
{
while (len) {
- if (len < OF_QUEUE_STATS_REPLY_FIXLEN)
- goto invalid;
+ ND_PRINT("\n\t ");
+ ND_ICHECKMSG_U("remaining length", len, <, OF_QUEUE_STATS_REPLY_FIXLEN);
/* port_no */
- ND_PRINT("\n\t port_no %s",
+ ND_PRINT(" port_no %s",
tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
OF_FWD(2);
/* pad */
OF_FWD(2);
/* queue_id */
ND_PRINT(", queue_id %u", GET_BE_U_4(cp));
OF_FWD(4);
/* tx_bytes */
ND_PRINT(", tx_bytes %" PRIu64, GET_BE_U_8(cp));
OF_FWD(8);
/* tx_packets */
ND_PRINT(", tx_packets %" PRIu64, GET_BE_U_8(cp));
OF_FWD(8);
/* tx_errors */
ND_PRINT(", tx_errors %" PRIu64, GET_BE_U_8(cp));
OF_FWD(8);
} /* while */
return;
invalid: /* skip the undersized trailing data */
nd_print_invalid(ndo);
ND_TCHECK_LEN(cp, len);
}
/* ibid */
static void
of10_stats_reply_print(netdissect_options *ndo,
const u_char *cp, u_int len)
{
uint16_t type;
/* type */
type = GET_BE_U_2(cp);
ND_PRINT("\n\t type %s", tok2str(ofpst_str, "invalid (0x%04x)", type));
OF_FWD(2);
/* flags */
ND_PRINT(", flags 0x%04x", GET_BE_U_2(cp));
of_bitmap_print(ndo, ofpsf_reply_bm, GET_BE_U_2(cp), OFPSF_REPLY_U);
OF_FWD(2);
if (ndo->ndo_vflag > 0) {
void (*decoder)(netdissect_options *, const u_char *, u_int) =
type == OFPST_DESC ? of10_desc_stats_reply_print :
type == OFPST_FLOW ? of10_flow_stats_reply_print :
type == OFPST_AGGREGATE ? of10_aggregate_stats_reply_print :
type == OFPST_TABLE ? of10_table_stats_reply_print :
type == OFPST_PORT ? of10_port_stats_reply_print :
type == OFPST_QUEUE ? of10_queue_stats_reply_print :
type == OFPST_VENDOR ? of10_vendor_data_print :
NULL;
if (decoder != NULL) {
decoder(ndo, cp, len);
return;
}
}
ND_TCHECK_LEN(cp, len);
}
/* [OF10] Section 5.3.6 */
static void
of10_packet_out_print(netdissect_options *ndo,
const u_char *cp, u_int len)
{
uint16_t actions_len;
/* buffer_id */
ND_PRINT("\n\t buffer_id 0x%08x", GET_BE_U_4(cp));
OF_FWD(4);
/* in_port */
ND_PRINT(", in_port %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
OF_FWD(2);
/* actions_len */
actions_len = GET_BE_U_2(cp);
+ ND_PRINT(", actions_len %u", actions_len);
OF_FWD(2);
- if (actions_len > len)
- goto invalid;
+ ND_ICHECK_U(actions_len, >, len);
/* actions */
of10_actions_print(ndo, "\n\t ", cp, actions_len);
OF_FWD(actions_len);
/* data */
of10_packet_data_print(ndo, cp, len);
return;
invalid: /* skip the rest of the message body */
nd_print_invalid(ndo);
ND_TCHECK_LEN(cp, len);
}
/* [OF10] Section 5.4.1 */
static void
of10_packet_in_print(netdissect_options *ndo,
const u_char *cp, u_int len)
{
/* buffer_id */
ND_PRINT("\n\t buffer_id %s",
tok2str(bufferid_str, "0x%08x", GET_BE_U_4(cp)));
OF_FWD(4);
/* total_len */
ND_PRINT(", total_len %u", GET_BE_U_2(cp));
OF_FWD(2);
/* in_port */
ND_PRINT(", in_port %s", tok2str(ofpp_str, "%u", GET_BE_U_2(cp)));
OF_FWD(2);
/* reason */
ND_PRINT(", reason %s",
tok2str(ofpr_str, "invalid (0x%02x)", GET_U_1(cp)));
OF_FWD(1);
/* pad */
/* Sometimes the last field, check bounds. */
OF_CHK_FWD(1);
/* data */
of10_packet_data_print(ndo, cp, len);
}
/* [OF10] Section 5.4.2 */
static void
of10_flow_removed_print(netdissect_options *ndo,
const u_char *cp, u_int len _U_)
{
/* match */
of10_match_print(ndo, "\n\t ", cp);
cp += OF_MATCH_FIXLEN;
/* cookie */
ND_PRINT("\n\t cookie 0x%016" PRIx64, GET_BE_U_8(cp));
cp += 8;
/* priority */
if (GET_BE_U_2(cp))
ND_PRINT(", priority %u", GET_BE_U_2(cp));
cp += 2;
/* reason */
ND_PRINT(", reason %s",
tok2str(ofprr_str, "unknown (0x%02x)", GET_U_1(cp)));
cp += 1;
/* pad */
cp += 1;
/* duration_sec */
ND_PRINT(", duration_sec %u", GET_BE_U_4(cp));
cp += 4;
/* duration_nsec */
ND_PRINT(", duration_nsec %u", GET_BE_U_4(cp));
cp += 4;
/* idle_timeout */
if (GET_BE_U_2(cp))
ND_PRINT(", idle_timeout %u", GET_BE_U_2(cp));
cp += 2;
/* pad2 */
cp += 2;
/* packet_count */
ND_PRINT(", packet_count %" PRIu64, GET_BE_U_8(cp));
cp += 8;
/* byte_count */
ND_PRINT(", byte_count %" PRIu64, GET_BE_U_8(cp));
}
/* [OF10] Section 5.4.3 */
static void
of10_port_status_print(netdissect_options *ndo,
const u_char *cp, u_int len _U_)
{
/* reason */
ND_PRINT("\n\t reason %s",
tok2str(ofppr_str, "invalid (0x%02x)", GET_U_1(cp)));
cp += 1;
/* pad */
/* No need to check bounds, more data follows. */
cp += 7;
/* desc */
of10_phy_port_print(ndo, cp);
}
/* [OF10] Section 5.4.4 */
static void
of10_error_print(netdissect_options *ndo,
const u_char *cp, u_int len)
{
uint16_t type, code;
const struct tok *code_str;
/* type */
type = GET_BE_U_2(cp);
OF_FWD(2);
ND_PRINT("\n\t type %s", tok2str(ofpet_str, "invalid (0x%04x)", type));
/* code */
code = GET_BE_U_2(cp);
OF_FWD(2);
code_str = uint2tokary(of10_ofpet2tokary, type);
if (code_str != NULL)
ND_PRINT(", code %s",
tok2str(code_str, "invalid (0x%04x)", code));
else
ND_PRINT(", code invalid (0x%04x)", code);
/* data */
of_data_print(ndo, cp, len);
}
static const struct of_msgtypeinfo of10_msgtypeinfo[OFPT_MAX + 1] = {
/*
* [OF10] Section 5.5.1
* Variable-size data.
*/
{
"HELLO", of_data_print,
REQ_MINLEN, 0
},
/*
* [OF10] Section 5.4.4
* A fixed-size message body and variable-size data.
*/
{
"ERROR", of10_error_print,
REQ_MINLEN, OF_ERROR_MSG_MINLEN
},
/*
* [OF10] Section 5.5.2
* Variable-size data.
*/
{
"ECHO_REQUEST", of_data_print,
REQ_MINLEN, 0
},
/*
* [OF10] Section 5.5.3
* Variable-size data.
*/
{
"ECHO_REPLY", of_data_print,
REQ_MINLEN, 0
},
/*
* [OF10] Section 5.5.4
* A fixed-size message body and variable-size data.
*/
{
"VENDOR", of10_vendor_message_print,
REQ_MINLEN, OF_VENDOR_MINLEN
},
/*
* [OF10] Section 5.3.1
* No message body.
*/
{
"FEATURES_REQUEST", NULL,
REQ_FIXLEN, 0
},
/*
* [OF10] Section 5.3.1
* A fixed-size message body and n * fixed-size data units.
*/
{
"FEATURES_REPLY", of10_features_reply_print,
REQ_MINLEN, OF_FEATURES_REPLY_MINLEN
},
/*
* [OF10] Section 5.3.2
* No message body.
*/
{
"GET_CONFIG_REQUEST", NULL,
REQ_FIXLEN, 0
},
/*
* [OF10] Section 5.3.2
* A fixed-size message body.
*/
{
"GET_CONFIG_REPLY", of10_switch_config_msg_print,
REQ_FIXLEN, OF_SWITCH_CONFIG_FIXLEN
},
/*
* [OF10] Section 5.3.2
* A fixed-size message body.
*/
{
"SET_CONFIG", of10_switch_config_msg_print,
REQ_FIXLEN, OF_SWITCH_CONFIG_FIXLEN
},
/*
* [OF10] Section 5.4.1
* A fixed-size message body and variable-size data.
* (The 2 mock octets count in OF_PACKET_IN_MINLEN only.)
*/
{
"PACKET_IN", of10_packet_in_print,
REQ_MINLEN, OF_PACKET_IN_MINLEN - 2
},
/*
* [OF10] Section 5.4.2
* A fixed-size message body.
*/
{
"FLOW_REMOVED", of10_flow_removed_print,
REQ_FIXLEN, OF_FLOW_REMOVED_FIXLEN
},
/*
* [OF10] Section 5.4.3
* A fixed-size message body.
*/
{
"PORT_STATUS", of10_port_status_print,
REQ_FIXLEN, OF_PORT_STATUS_FIXLEN
},
/*
* [OF10] Section 5.3.6
* A fixed-size message body, n * variable-size data units and
* variable-size data.
*/
{
"PACKET_OUT", of10_packet_out_print,
REQ_MINLEN, OF_PACKET_OUT_MINLEN
},
/*
* [OF10] Section 5.3.3
* A fixed-size message body and n * variable-size data units.
*/
{
"FLOW_MOD", of10_flow_mod_print,
REQ_MINLEN, OF_FLOW_MOD_MINLEN
},
/*
* [OF10] Section 5.3.3
* A fixed-size message body.
*/
{
"PORT_MOD", of10_port_mod_print,
REQ_FIXLEN, OF_PORT_MOD_FIXLEN
},
/*
* [OF10] Section 5.3.5
* A fixed-size message body and possibly more data of varying size
* and structure.
*/
{
"STATS_REQUEST", of10_stats_request_print,
REQ_MINLEN, OF_STATS_REQUEST_MINLEN
},
/*
* [OF10] Section 5.3.5
* A fixed-size message body and possibly more data of varying size
* and structure.
*/
{
"STATS_REPLY", of10_stats_reply_print,
REQ_MINLEN, OF_STATS_REPLY_MINLEN
},
/*
* [OF10] Section 5.3.7
* No message body.
*/
{
"BARRIER_REQUEST", NULL,
REQ_FIXLEN, 0
},
/*
* [OF10] Section 5.3.7
* No message body.
*/
{
"BARRIER_REPLY", NULL,
REQ_FIXLEN, 0
},
/*
* [OF10] Section 5.3.4
* A fixed-size message body.
*/
{
"QUEUE_GET_CONFIG_REQUEST", of10_queue_get_config_request_print,
REQ_FIXLEN, OF_QUEUE_GET_CONFIG_REQUEST_FIXLEN
},
/*
* [OF10] Section 5.3.4
* A fixed-size message body and n * variable-size data units.
*/
{
"QUEUE_GET_CONFIG_REPLY", of10_queue_get_config_reply_print,
REQ_MINLEN, OF_QUEUE_GET_CONFIG_REPLY_MINLEN
},
};
const struct of_msgtypeinfo *
of10_identify_msgtype(const uint8_t type)
{
return type <= OFPT_MAX ? &of10_msgtypeinfo[type] : NULL;
}
diff --git a/contrib/tcpdump/print-openflow-1.3.c b/contrib/tcpdump/print-openflow-1.3.c
index 9e76ba1b2935..935e573909f0 100644
--- a/contrib/tcpdump/print-openflow-1.3.c
+++ b/contrib/tcpdump/print-openflow-1.3.c
@@ -1,1209 +1,1206 @@
/*
* This module implements decoding of OpenFlow protocol version 1.3 (wire
* protocol 0x04). It is based on the implementation conventions explained in
* print-openflow-1.0.c.
*
* [OF13] https://www.opennetworking.org/wp-content/uploads/2014/10/openflow-switch-v1.3.5.pdf
*
* Copyright (c) 2020 The TCPDUMP project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* \summary: OpenFlow protocol version 1.3 printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
#include "addrtoname.h"
#include "openflow.h"
#define OFPT_HELLO 0U
#define OFPT_ERROR 1U
#define OFPT_ECHO_REQUEST 2U
#define OFPT_ECHO_REPLY 3U
#define OFPT_EXPERIMENTER 4U
#define OFPT_FEATURES_REQUEST 5U
#define OFPT_FEATURES_REPLY 6U
#define OFPT_GET_CONFIG_REQUEST 7U
#define OFPT_GET_CONFIG_REPLY 8U
#define OFPT_SET_CONFIG 9U
#define OFPT_PACKET_IN 10U
#define OFPT_FLOW_REMOVED 11U
#define OFPT_PORT_STATUS 12U
#define OFPT_PACKET_OUT 13U
#define OFPT_FLOW_MOD 14U
#define OFPT_GROUP_MOD 15U
#define OFPT_PORT_MOD 16U
#define OFPT_TABLE_MOD 17U
#define OFPT_MULTIPART_REQUEST 18U
#define OFPT_MULTIPART_REPLY 19U
#define OFPT_BARRIER_REQUEST 20U
#define OFPT_BARRIER_REPLY 21U
#define OFPT_QUEUE_GET_CONFIG_REQUEST 22U
#define OFPT_QUEUE_GET_CONFIG_REPLY 23U
#define OFPT_ROLE_REQUEST 24U
#define OFPT_ROLE_REPLY 25U
#define OFPT_GET_ASYNC_REQUEST 26U
#define OFPT_GET_ASYNC_REPLY 27U
#define OFPT_SET_ASYNC 28U
#define OFPT_METER_MOD 29U
#define OFPT_MAX OFPT_METER_MOD
#define OFPC_FLOW_STATS (1U <<0)
#define OFPC_TABLE_STATS (1U <<1)
#define OFPC_PORT_STATS (1U <<2)
#define OFPC_GROUP_STATS (1U <<3)
#define OFPC_IP_REASM (1U <<5)
#define OFPC_QUEUE_STATS (1U <<6)
#define OFPC_PORT_BLOCKED (1U <<8)
static const struct tok ofp_capabilities_bm[] = {
{ OFPC_FLOW_STATS, "FLOW_STATS" },
{ OFPC_TABLE_STATS, "TABLE_STATS" },
{ OFPC_PORT_STATS, "PORT_STATS" },
{ OFPC_GROUP_STATS, "GROUP_STATS" },
{ OFPC_IP_REASM, "IP_REASM" },
{ OFPC_QUEUE_STATS, "QUEUE_STATS" },
{ OFPC_PORT_BLOCKED, "PORT_BLOCKED" },
{ 0, NULL }
};
#define OFPCAP_U (~(OFPC_FLOW_STATS | OFPC_TABLE_STATS | OFPC_PORT_STATS | \
OFPC_GROUP_STATS | OFPC_IP_REASM | OFPC_QUEUE_STATS | \
OFPC_PORT_BLOCKED))
#define OFPC_FRAG_NORMAL 0U
#define OFPC_FRAG_DROP 1U
#define OFPC_FRAG_REASM 2U
static const struct tok ofp_config_str[] = {
{ OFPC_FRAG_NORMAL, "FRAG_NORMAL" },
{ OFPC_FRAG_DROP, "FRAG_DROP" },
{ OFPC_FRAG_REASM, "FRAG_REASM" },
{ 0, NULL }
};
#define OFPTT_MAX 0xfeU
#define OFPTT_ALL 0xffU
static const struct tok ofptt_str[] = {
{ OFPTT_MAX, "MAX" },
{ OFPTT_ALL, "ALL" },
{ 0, NULL },
};
#define OFPCML_MAX 0xffe5U
#define OFPCML_NO_BUFFER 0xffffU
static const struct tok ofpcml_str[] = {
{ OFPCML_MAX, "MAX" },
{ OFPCML_NO_BUFFER, "NO_BUFFER" },
{ 0, NULL }
};
#define OFPPC_PORT_DOWN (1U <<0)
#define OFPPC_NO_RECV (1U <<2)
#define OFPPC_NO_FWD (1U <<5)
#define OFPPC_NO_PACKET_IN (1U <<6)
static const struct tok ofppc_bm[] = {
{ OFPPC_PORT_DOWN, "PORT_DOWN" },
{ OFPPC_NO_RECV, "NO_RECV" },
{ OFPPC_NO_FWD, "NO_FWD" },
{ OFPPC_NO_PACKET_IN, "NO_PACKET_IN" },
{ 0, NULL }
};
#define OFPPC_U (~(OFPPC_PORT_DOWN | OFPPC_NO_RECV | OFPPC_NO_FWD | \
OFPPC_NO_PACKET_IN))
#define OFPPS_LINK_DOWN (1U << 0)
#define OFPPS_BLOCKED (1U << 1)
#define OFPPS_LIVE (1U << 2)
static const struct tok ofpps_bm[] = {
{ OFPPS_LINK_DOWN, "LINK_DOWN" },
{ OFPPS_BLOCKED, "BLOCKED" },
{ OFPPS_LIVE, "LIVE" },
{ 0, NULL }
};
#define OFPPS_U (~(OFPPS_LINK_DOWN | OFPPS_BLOCKED | OFPPS_LIVE))
#define OFPPF_10MB_HD (1U << 0)
#define OFPPF_10MB_FD (1U << 1)
#define OFPPF_100MB_HD (1U << 2)
#define OFPPF_100MB_FD (1U << 3)
#define OFPPF_1GB_HD (1U << 4)
#define OFPPF_1GB_FD (1U << 5)
#define OFPPF_10GB_FD (1U << 6)
#define OFPPF_40GB_FD (1U << 7)
#define OFPPF_100GB_FD (1U << 8)
#define OFPPF_1TB_FD (1U << 9)
#define OFPPF_OTHER (1U << 10)
#define OFPPF_COPPER (1U << 11)
#define OFPPF_FIBER (1U << 12)
#define OFPPF_AUTONEG (1U << 13)
#define OFPPF_PAUSE (1U << 14)
#define OFPPF_PAUSE_ASYM (1U << 15)
static const struct tok ofppf_bm[] = {
{ OFPPF_10MB_HD, "10MB_HD" },
{ OFPPF_10MB_FD, "10MB_FD" },
{ OFPPF_100MB_HD, "100MB_HD" },
{ OFPPF_100MB_FD, "100MB_FD" },
{ OFPPF_1GB_HD, "1GB_HD" },
{ OFPPF_1GB_FD, "1GB_FD" },
{ OFPPF_10GB_FD, "10GB_FD" },
{ OFPPF_40GB_FD, "40GB_FD" },
{ OFPPF_100GB_FD, "100GB_FD" },
{ OFPPF_1TB_FD, "1TB_FD" },
{ OFPPF_OTHER, "OTHER" },
{ OFPPF_COPPER, "COPPER" },
{ OFPPF_FIBER, "FIBER" },
{ OFPPF_AUTONEG, "AUTONEG" },
{ OFPPF_PAUSE, "PAUSE" },
{ OFPPF_PAUSE_ASYM, "PAUSE_ASYM" },
{ 0, NULL }
};
#define OFPPF_U (~(OFPPF_10MB_HD | OFPPF_10MB_FD | OFPPF_100MB_HD | \
OFPPF_100MB_FD | OFPPF_1GB_HD | OFPPF_1GB_FD | \
OFPPF_10GB_FD | OFPPF_40GB_FD | OFPPF_100GB_FD | \
OFPPF_1TB_FD | OFPPF_OTHER | OFPPF_COPPER | OFPPF_FIBER | \
OFPPF_AUTONEG | OFPPF_PAUSE | OFPPF_PAUSE_ASYM))
#define OFPHET_VERSIONBITMAP 1U
static const struct tok ofphet_str[] = {
{ OFPHET_VERSIONBITMAP, "VERSIONBITMAP" },
{ 0, NULL }
};
#define OFPP_MAX 0xffffff00U
#define OFPP_IN_PORT 0xfffffff8U
#define OFPP_TABLE 0xfffffff9U
#define OFPP_NORMAL 0xfffffffaU
#define OFPP_FLOOD 0xfffffffbU
#define OFPP_ALL 0xfffffffcU
#define OFPP_CONTROLLER 0xfffffffdU
#define OFPP_LOCAL 0xfffffffeU
#define OFPP_ANY 0xffffffffU
static const struct tok ofpp_str[] = {
{ OFPP_MAX, "MAX" },
{ OFPP_IN_PORT, "IN_PORT" },
{ OFPP_TABLE, "TABLE" },
{ OFPP_NORMAL, "NORMAL" },
{ OFPP_FLOOD, "FLOOD" },
{ OFPP_ALL, "ALL" },
{ OFPP_CONTROLLER, "CONTROLLER" },
{ OFPP_LOCAL, "LOCAL" },
{ OFPP_ANY, "ANY" },
{ 0, NULL }
};
#define OFPCR_ROLE_NOCHANGE 0U
#define OFPCR_ROLE_EQUAL 1U
#define OFPCR_ROLE_MASTER 2U
#define OFPCR_ROLE_SLAVE 3U
static const struct tok ofpcr_str[] = {
{ OFPCR_ROLE_NOCHANGE, "NOCHANGE" },
{ OFPCR_ROLE_EQUAL, "EQUAL" },
{ OFPCR_ROLE_MASTER, "MASTER" },
{ OFPCR_ROLE_SLAVE, "SLAVE" },
{ 0, NULL }
};
#define OF_BIT_VER_1_0 (1U << (OF_VER_1_0 - 1))
#define OF_BIT_VER_1_1 (1U << (OF_VER_1_1 - 1))
#define OF_BIT_VER_1_2 (1U << (OF_VER_1_2 - 1))
#define OF_BIT_VER_1_3 (1U << (OF_VER_1_3 - 1))
#define OF_BIT_VER_1_4 (1U << (OF_VER_1_4 - 1))
#define OF_BIT_VER_1_5 (1U << (OF_VER_1_5 - 1))
static const struct tok ofverbm_str[] = {
{ OF_BIT_VER_1_0, "1.0" },
{ OF_BIT_VER_1_1, "1.1" },
{ OF_BIT_VER_1_2, "1.2" },
{ OF_BIT_VER_1_3, "1.3" },
{ OF_BIT_VER_1_4, "1.4" },
{ OF_BIT_VER_1_5, "1.5" },
{ 0, NULL }
};
#define OF_BIT_VER_U (~(OF_BIT_VER_1_0 | OF_BIT_VER_1_1 | OF_BIT_VER_1_2 | \
OF_BIT_VER_1_3 | OF_BIT_VER_1_4 | OF_BIT_VER_1_5))
#define OFPR_NO_MATCH 0U
#define OFPR_ACTION 1U
#define OFPR_INVALID_TTL 2U
#if 0 /* for OFPT_PACKET_IN */
static const struct tok ofpr_str[] = {
{ OFPR_NO_MATCH, "NO_MATCH" },
{ OFPR_ACTION, "ACTION" },
{ OFPR_INVALID_TTL, "OFPR_INVALID_TTL" },
{ 0, NULL }
};
#endif
#define ASYNC_OFPR_NO_MATCH (1U << OFPR_NO_MATCH )
#define ASYNC_OFPR_ACTION (1U << OFPR_ACTION )
#define ASYNC_OFPR_INVALID_TTL (1U << OFPR_INVALID_TTL)
static const struct tok async_ofpr_bm[] = {
{ ASYNC_OFPR_NO_MATCH, "NO_MATCH" },
{ ASYNC_OFPR_ACTION, "ACTION" },
{ ASYNC_OFPR_INVALID_TTL, "INVALID_TTL" },
{ 0, NULL }
};
#define ASYNC_OFPR_U (~(ASYNC_OFPR_NO_MATCH | ASYNC_OFPR_ACTION | \
ASYNC_OFPR_INVALID_TTL))
#define OFPPR_ADD 0U
#define OFPPR_DELETE 1U
#define OFPPR_MODIFY 2U
static const struct tok ofppr_str[] = {
{ OFPPR_ADD, "ADD" },
{ OFPPR_DELETE, "DELETE" },
{ OFPPR_MODIFY, "MODIFY" },
{ 0, NULL }
};
#define ASYNC_OFPPR_ADD (1U << OFPPR_ADD )
#define ASYNC_OFPPR_DELETE (1U << OFPPR_DELETE)
#define ASYNC_OFPPR_MODIFY (1U << OFPPR_MODIFY)
static const struct tok async_ofppr_bm[] = {
{ ASYNC_OFPPR_ADD, "ADD" },
{ ASYNC_OFPPR_DELETE, "DELETE" },
{ ASYNC_OFPPR_MODIFY, "MODIFY" },
{ 0, NULL }
};
#define ASYNC_OFPPR_U (~(ASYNC_OFPPR_ADD | ASYNC_OFPPR_DELETE | \
ASYNC_OFPPR_MODIFY))
#define OFPET_HELLO_FAILED 0U
#define OFPET_BAD_REQUEST 1U
#define OFPET_BAD_ACTION 2U
#define OFPET_BAD_INSTRUCTION 3U
#define OFPET_BAD_MATCH 4U
#define OFPET_FLOW_MOD_FAILED 5U
#define OFPET_GROUP_MOD_FAILED 6U
#define OFPET_PORT_MOD_FAILED 7U
#define OFPET_TABLE_MOD_FAILED 8U
#define OFPET_QUEUE_OP_FAILED 9U
#define OFPET_SWITCH_CONFIG_FAILED 10U
#define OFPET_ROLE_REQUEST_FAILED 11U
#define OFPET_METER_MOD_FAILED 12U
#define OFPET_TABLE_FEATURES_FAILED 13U
#define OFPET_EXPERIMENTER 0xffffU /* a special case */
static const struct tok ofpet_str[] = {
{ OFPET_HELLO_FAILED, "HELLO_FAILED" },
{ OFPET_BAD_REQUEST, "BAD_REQUEST" },
{ OFPET_BAD_ACTION, "BAD_ACTION" },
{ OFPET_BAD_INSTRUCTION, "BAD_INSTRUCTION" },
{ OFPET_BAD_MATCH, "BAD_MATCH" },
{ OFPET_FLOW_MOD_FAILED, "FLOW_MOD_FAILED" },
{ OFPET_GROUP_MOD_FAILED, "GROUP_MOD_FAILED" },
{ OFPET_PORT_MOD_FAILED, "PORT_MOD_FAILED" },
{ OFPET_TABLE_MOD_FAILED, "TABLE_MOD_FAILED" },
{ OFPET_QUEUE_OP_FAILED, "QUEUE_OP_FAILED" },
{ OFPET_SWITCH_CONFIG_FAILED, "SWITCH_CONFIG_FAILED" },
{ OFPET_ROLE_REQUEST_FAILED, "ROLE_REQUEST_FAILED" },
{ OFPET_METER_MOD_FAILED, "METER_MOD_FAILED" },
{ OFPET_TABLE_FEATURES_FAILED, "TABLE_FEATURES_FAILED" },
{ OFPET_EXPERIMENTER, "EXPERIMENTER" },
{ 0, NULL }
};
#define OFPHFC_INCOMPATIBLE 0U
#define OFPHFC_EPERM 1U
static const struct tok ofphfc_str[] = {
{ OFPHFC_INCOMPATIBLE, "INCOMPATIBLE" },
{ OFPHFC_EPERM, "EPERM" },
{ 0, NULL }
};
#define OFPBRC_BAD_VERSION 0U
#define OFPBRC_BAD_TYPE 1U
#define OFPBRC_BAD_MULTIPART 2U
#define OFPBRC_BAD_EXPERIMENTER 3U
#define OFPBRC_BAD_EXP_TYPE 4U
#define OFPBRC_EPERM 5U
#define OFPBRC_BAD_LEN 6U
#define OFPBRC_BUFFER_EMPTY 7U
#define OFPBRC_BUFFER_UNKNOWN 8U
#define OFPBRC_BAD_TABLE_ID 9U
#define OFPBRC_IS_SLAVE 10U
#define OFPBRC_BAD_PORT 11U
#define OFPBRC_BAD_PACKET 12U
#define OFPBRC_MULTIPART_BUFFER_OVERFLOW 13U
static const struct tok ofpbrc_str[] = {
{ OFPBRC_BAD_VERSION, "BAD_VERSION" },
{ OFPBRC_BAD_TYPE, "BAD_TYPE" },
{ OFPBRC_BAD_MULTIPART, "BAD_MULTIPART" },
{ OFPBRC_BAD_EXPERIMENTER, "BAD_EXPERIMENTER" },
{ OFPBRC_BAD_EXP_TYPE, "BAD_EXP_TYPE" },
{ OFPBRC_EPERM, "EPERM" },
{ OFPBRC_BAD_LEN, "BAD_LEN" },
{ OFPBRC_BUFFER_EMPTY, "BUFFER_EMPTY" },
{ OFPBRC_BUFFER_UNKNOWN, "BUFFER_UNKNOWN" },
{ OFPBRC_BAD_TABLE_ID, "BAD_TABLE_ID" },
{ OFPBRC_IS_SLAVE, "IS_SLAVE" },
{ OFPBRC_BAD_PORT, "BAD_PORT" },
{ OFPBRC_BAD_PACKET, "BAD_PACKET" },
{ OFPBRC_MULTIPART_BUFFER_OVERFLOW, "MULTIPART_BUFFER_OVERFLOW" },
{ 0, NULL }
};
#define OFPBAC_BAD_TYPE 0U
#define OFPBAC_BAD_LEN 1U
#define OFPBAC_BAD_EXPERIMENTER 2U
#define OFPBAC_BAD_EXP_TYPE 3U
#define OFPBAC_BAD_OUT_PORT 4U
#define OFPBAC_BAD_ARGUMENT 5U
#define OFPBAC_EPERM 6U
#define OFPBAC_TOO_MANY 7U
#define OFPBAC_BAD_QUEUE 8U
#define OFPBAC_BAD_OUT_GROUP 9U
#define OFPBAC_MATCH_INCONSISTENT 10U
#define OFPBAC_UNSUPPORTED_ORDER 11U
#define OFPBAC_BAD_TAG 12U
#define OFPBAC_BAD_SET_TYPE 13U
#define OFPBAC_BAD_SET_LEN 14U
#define OFPBAC_BAD_SET_ARGUMENT 15U
static const struct tok ofpbac_str[] = {
{ OFPBAC_BAD_TYPE, "BAD_TYPE" },
{ OFPBAC_BAD_LEN, "BAD_LEN" },
{ OFPBAC_BAD_EXPERIMENTER, "BAD_EXPERIMENTER" },
{ OFPBAC_BAD_EXP_TYPE, "BAD_EXP_TYPE" },
{ OFPBAC_BAD_OUT_PORT, "BAD_OUT_PORT" },
{ OFPBAC_BAD_ARGUMENT, "BAD_ARGUMENT" },
{ OFPBAC_EPERM, "EPERM" },
{ OFPBAC_TOO_MANY, "TOO_MANY" },
{ OFPBAC_BAD_QUEUE, "BAD_QUEUE" },
{ OFPBAC_BAD_OUT_GROUP, "BAD_OUT_GROUP" },
{ OFPBAC_MATCH_INCONSISTENT, "MATCH_INCONSISTENT" },
{ OFPBAC_UNSUPPORTED_ORDER, "UNSUPPORTED_ORDER" },
{ OFPBAC_BAD_TAG, "BAD_TAG" },
{ OFPBAC_BAD_SET_TYPE, "BAD_SET_TYPE" },
{ OFPBAC_BAD_SET_LEN, "BAD_SET_LEN" },
{ OFPBAC_BAD_SET_ARGUMENT, "BAD_SET_ARGUMENT" },
{ 0, NULL }
};
#define OFPBIC_UNKNOWN_INST 0U
#define OFPBIC_UNSUP_INST 1U
#define OFPBIC_BAD_TABLE_ID 2U
#define OFPBIC_UNSUP_METADATA 3U
#define OFPBIC_UNSUP_METADATA_MASK 4U
#define OFPBIC_BAD_EXPERIMENTER 5U
#define OFPBIC_BAD_EXP_TYPE 6U
#define OFPBIC_BAD_LEN 7U
#define OFPBIC_EPERM 8U
static const struct tok ofpbic_str[] = {
{ OFPBIC_UNKNOWN_INST, "UNKNOWN_INST" },
{ OFPBIC_UNSUP_INST, "UNSUP_INST" },
{ OFPBIC_BAD_TABLE_ID, "BAD_TABLE_ID" },
{ OFPBIC_UNSUP_METADATA, "UNSUP_METADATA" },
{ OFPBIC_UNSUP_METADATA_MASK, "UNSUP_METADATA_MASK" },
{ OFPBIC_BAD_EXPERIMENTER, "BAD_EXPERIMENTER" },
{ OFPBIC_BAD_EXP_TYPE, "BAD_EXP_TYPE" },
{ OFPBIC_BAD_LEN, "BAD_LEN" },
{ OFPBIC_EPERM, "EPERM" },
{ 0, NULL }
};
#define OFPBMC_BAD_TYPE 0U
#define OFPBMC_BAD_LEN 1U
#define OFPBMC_BAD_TAG 2U
#define OFPBMC_BAD_DL_ADDR_MASK 3U
#define OFPBMC_BAD_NW_ADDR_MASK 4U
#define OFPBMC_BAD_WILDCARDS 5U
#define OFPBMC_BAD_FIELD 6U
#define OFPBMC_BAD_VALUE 7U
#define OFPBMC_BAD_MASK 8U
#define OFPBMC_BAD_PREREQ 9U
#define OFPBMC_DUP_FIELD 10U
#define OFPBMC_EPERM 11U
static const struct tok ofpbmc_str[] = {
{ OFPBMC_BAD_TYPE, "BAD_TYPE" },
{ OFPBMC_BAD_LEN, "BAD_LEN" },
{ OFPBMC_BAD_TAG, "BAD_TAG" },
{ OFPBMC_BAD_DL_ADDR_MASK, "BAD_DL_ADDR_MASK" },
{ OFPBMC_BAD_NW_ADDR_MASK, "BAD_NW_ADDR_MASK" },
{ OFPBMC_BAD_WILDCARDS, "BAD_WILDCARDS" },
{ OFPBMC_BAD_FIELD, "BAD_FIELD" },
{ OFPBMC_BAD_VALUE, "BAD_VALUE" },
{ OFPBMC_BAD_MASK, "BAD_MASK" },
{ OFPBMC_BAD_PREREQ, "BAD_PREREQ" },
{ OFPBMC_DUP_FIELD, "DUP_FIELD" },
{ OFPBMC_EPERM, "EPERM" },
{ 0, NULL }
};
#define OFPFMFC_UNKNOWN 0U
#define OFPFMFC_TABLE_FULL 1U
#define OFPFMFC_BAD_TABLE_ID 2U
#define OFPFMFC_OVERLAP 3U
#define OFPFMFC_EPERM 4U
#define OFPFMFC_BAD_TIMEOUT 5U
#define OFPFMFC_BAD_COMMAND 6U
#define OFPFMFC_BAD_FLAGS 7U
static const struct tok ofpfmfc_str[] = {
{ OFPFMFC_UNKNOWN, "UNKNOWN" },
{ OFPFMFC_TABLE_FULL, "TABLE_FULL" },
{ OFPFMFC_BAD_TABLE_ID, "BAD_TABLE_ID" },
{ OFPFMFC_OVERLAP, "OVERLAP" },
{ OFPFMFC_EPERM, "EPERM" },
{ OFPFMFC_BAD_TIMEOUT, "BAD_TIMEOUT" },
{ OFPFMFC_BAD_COMMAND, "BAD_COMMAND" },
{ OFPFMFC_BAD_FLAGS, "BAD_FLAGS" },
{ 0, NULL }
};
#define OFPGMFC_GROUP_EXISTS 0U
#define OFPGMFC_INVALID_GROUP 1U
#define OFPGMFC_WEIGHT_UNSUPPORTED 2U
#define OFPGMFC_OUT_OF_GROUPS 3U
#define OFPGMFC_OUT_OF_BUCKETS 4U
#define OFPGMFC_CHAINING_UNSUPPORTED 5U
#define OFPGMFC_WATCH_UNSUPPORTED 6U
#define OFPGMFC_LOOP 7U
#define OFPGMFC_UNKNOWN_GROUP 8U
#define OFPGMFC_CHAINED_GROUP 9U
#define OFPGMFC_BAD_TYPE 10U
#define OFPGMFC_BAD_COMMAND 11U
#define OFPGMFC_BAD_BUCKET 12U
#define OFPGMFC_BAD_MATCH 13U
#define OFPGMFC_EPERM 14U
static const struct tok ofpgmfc_str[] = {
{ OFPGMFC_GROUP_EXISTS, "GROUP_EXISTS" },
{ OFPGMFC_INVALID_GROUP, "INVALID_GROUP" },
{ OFPGMFC_WEIGHT_UNSUPPORTED, "WEIGHT_UNSUPPORTED" },
{ OFPGMFC_OUT_OF_GROUPS, "OUT_OF_GROUPS" },
{ OFPGMFC_OUT_OF_BUCKETS, "OUT_OF_BUCKETS" },
{ OFPGMFC_CHAINING_UNSUPPORTED, "CHAINING_UNSUPPORTED" },
{ OFPGMFC_WATCH_UNSUPPORTED, "WATCH_UNSUPPORTED" },
{ OFPGMFC_LOOP, "LOOP" },
{ OFPGMFC_UNKNOWN_GROUP, "UNKNOWN_GROUP" },
{ OFPGMFC_CHAINED_GROUP, "CHAINED_GROUP" },
{ OFPGMFC_BAD_TYPE, "BAD_TYPE" },
{ OFPGMFC_BAD_COMMAND, "BAD_COMMAND" },
{ OFPGMFC_BAD_BUCKET, "BAD_BUCKET" },
{ OFPGMFC_BAD_MATCH, "BAD_MATCH" },
{ OFPGMFC_EPERM, "EPERM" },
{ 0, NULL }
};
#define OFPPMFC_BAD_PORT 0U
#define OFPPMFC_BAD_HW_ADDR 1U
#define OFPPMFC_BAD_CONFIG 2U
#define OFPPMFC_BAD_ADVERTISE 3U
#define OFPPMFC_EPERM 4U
static const struct tok ofppmfc_str[] = {
{ OFPPMFC_BAD_PORT, "BAD_PORT" },
{ OFPPMFC_BAD_HW_ADDR, "BAD_HW_ADDR" },
{ OFPPMFC_BAD_CONFIG, "BAD_CONFIG" },
{ OFPPMFC_BAD_ADVERTISE, "BAD_ADVERTISE" },
{ OFPPMFC_EPERM, "EPERM" },
{ 0, NULL }
};
#define OFPTMFC_BAD_TABLE 0U
#define OFPTMFC_BAD_CONFIG 1U
#define OFPTMFC_EPERM 2U
static const struct tok ofptmfc_str[] = {
{ OFPTMFC_BAD_TABLE, "BAD_TABLE" },
{ OFPTMFC_BAD_CONFIG, "BAD_CONFIG" },
{ OFPTMFC_EPERM, "EPERM" },
{ 0, NULL }
};
#define OFPQOFC_BAD_PORT 0U
#define OFPQOFC_BAD_QUEUE 1U
#define OFPQOFC_EPERM 2U
static const struct tok ofpqofc_str[] = {
{ OFPQOFC_BAD_PORT, "BAD_PORT" },
{ OFPQOFC_BAD_QUEUE, "BAD_QUEUE" },
{ OFPQOFC_EPERM, "EPERM" },
{ 0, NULL }
};
#define OFPSCFC_BAD_FLAGS 0U
#define OFPSCFC_BAD_LEN 1U
#define OFPSCFC_EPERM 2U
static const struct tok ofpscfc_str[] = {
{ OFPSCFC_BAD_FLAGS, "BAD_FLAGS" },
{ OFPSCFC_BAD_LEN, "BAD_LEN" },
{ OFPSCFC_EPERM, "EPERM" },
{ 0, NULL }
};
#define OFPRRFC_STALE 0U
#define OFPRRFC_UNSUP 1U
#define OFPRRFC_BAD_ROLE 2U
static const struct tok ofprrfc_str[] = {
{ OFPRRFC_STALE, "STALE" },
{ OFPRRFC_UNSUP, "UNSUP" },
{ OFPRRFC_BAD_ROLE, "BAD_ROLE" },
{ 0, NULL }
};
#define OFPMMFC_UNKNOWN 0U
#define OFPMMFC_METER_EXISTS 1U
#define OFPMMFC_INVALID_METER 2U
#define OFPMMFC_UNKNOWN_METER 3U
#define OFPMMFC_BAD_COMMAND 4U
#define OFPMMFC_BAD_FLAGS 5U
#define OFPMMFC_BAD_RATE 6U
#define OFPMMFC_BAD_BURST 7U
#define OFPMMFC_BAD_BAND 8U
#define OFPMMFC_BAD_BAND_VALUE 9U
#define OFPMMFC_OUT_OF_METERS 10U
#define OFPMMFC_OUT_OF_BANDS 11U
static const struct tok ofpmmfc_str[] = {
{ OFPMMFC_UNKNOWN, "UNKNOWN" },
{ OFPMMFC_METER_EXISTS, "METER_EXISTS" },
{ OFPMMFC_INVALID_METER, "INVALID_METER" },
{ OFPMMFC_UNKNOWN_METER, "UNKNOWN_METER" },
{ OFPMMFC_BAD_COMMAND, "BAD_COMMAND" },
{ OFPMMFC_BAD_FLAGS, "BAD_FLAGS" },
{ OFPMMFC_BAD_RATE, "BAD_RATE" },
{ OFPMMFC_BAD_BURST, "BAD_BURST" },
{ OFPMMFC_BAD_BAND, "BAD_BAND" },
{ OFPMMFC_BAD_BAND_VALUE, "BAD_BAND_VALUE" },
{ OFPMMFC_OUT_OF_METERS, "OUT_OF_METERS" },
{ OFPMMFC_OUT_OF_BANDS, "OUT_OF_BANDS" },
{ 0, NULL }
};
#define OFPTFFC_BAD_TABLE 0U
#define OFPTFFC_BAD_METADATA 1U
#define OFPTFFC_BAD_TYPE 2U
#define OFPTFFC_BAD_LEN 3U
#define OFPTFFC_BAD_ARGUMENT 4U
#define OFPTFFC_EPERM 5U
static const struct tok ofptffc_str[] = {
{ OFPTFFC_BAD_TABLE, "BAD_TABLE" },
{ OFPTFFC_BAD_METADATA, "BAD_METADATA" },
{ OFPTFFC_BAD_TYPE, "BAD_TYPE" },
{ OFPTFFC_BAD_LEN, "BAD_LEN" },
{ OFPTFFC_BAD_ARGUMENT, "BAD_ARGUMENT" },
{ OFPTFFC_EPERM, "EPERM" },
{ 0, NULL }
};
static const struct uint_tokary of13_ofpet2tokary[] = {
{ OFPET_HELLO_FAILED, ofphfc_str },
{ OFPET_BAD_REQUEST, ofpbrc_str },
{ OFPET_BAD_ACTION, ofpbac_str },
{ OFPET_BAD_INSTRUCTION, ofpbic_str },
{ OFPET_BAD_MATCH, ofpbmc_str },
{ OFPET_FLOW_MOD_FAILED, ofpfmfc_str },
{ OFPET_GROUP_MOD_FAILED, ofpgmfc_str },
{ OFPET_PORT_MOD_FAILED, ofppmfc_str },
{ OFPET_TABLE_MOD_FAILED, ofptmfc_str },
{ OFPET_QUEUE_OP_FAILED, ofpqofc_str },
{ OFPET_SWITCH_CONFIG_FAILED, ofpscfc_str },
{ OFPET_ROLE_REQUEST_FAILED, ofprrfc_str },
{ OFPET_METER_MOD_FAILED, ofpmmfc_str },
{ OFPET_TABLE_FEATURES_FAILED, ofptffc_str },
{ OFPET_EXPERIMENTER, NULL }, /* defines no codes */
/* uint2tokary() does not use array termination. */
};
/* lengths (fixed or minimal) of particular message types, where not 0 */
#define OF_ERROR_MSG_MINLEN (12U - OF_HEADER_FIXLEN)
#define OF_FEATURES_REPLY_FIXLEN (32U - OF_HEADER_FIXLEN)
#define OF_PORT_MOD_FIXLEN (40U - OF_HEADER_FIXLEN)
#define OF_SWITCH_CONFIG_MSG_FIXLEN (12U - OF_HEADER_FIXLEN)
#define OF_TABLE_MOD_FIXLEN (16U - OF_HEADER_FIXLEN)
#define OF_QUEUE_GET_CONFIG_REQUEST_FIXLEN (16U - OF_HEADER_FIXLEN)
#define OF_ROLE_MSG_FIXLEN (24U - OF_HEADER_FIXLEN)
#define OF_ASYNC_MSG_FIXLEN (32U - OF_HEADER_FIXLEN)
#define OF_PORT_STATUS_FIXLEN (80U - OF_HEADER_FIXLEN)
#define OF_EXPERIMENTER_MSG_MINLEN (16U - OF_HEADER_FIXLEN)
/* lengths (fixed or minimal) of particular protocol structures */
#define OF_HELLO_ELEM_MINSIZE 4U
/* miscellaneous constants from [OF13] */
#define OFP_MAX_PORT_NAME_LEN 16U
/* [OF13] Section 7.2.1 */
static void
of13_port_print(netdissect_options *ndo,
const u_char *cp)
{
/* port_no */
ND_PRINT("\n\t port_no %s",
tok2str(ofpp_str, "%u", GET_BE_U_4(cp)));
cp += 4;
/* pad */
cp += 4;
/* hw_addr */
ND_PRINT(", hw_addr %s", GET_ETHERADDR_STRING(cp));
cp += MAC_ADDR_LEN;
/* pad2 */
cp += 2;
/* name */
ND_PRINT(", name '");
nd_printjnp(ndo, cp, OFP_MAX_PORT_NAME_LEN);
ND_PRINT("'");
cp += OFP_MAX_PORT_NAME_LEN;
if (ndo->ndo_vflag < 2) {
ND_TCHECK_LEN(cp, 32);
return;
}
/* config */
ND_PRINT("\n\t config 0x%08x", GET_BE_U_4(cp));
of_bitmap_print(ndo, ofppc_bm, GET_BE_U_4(cp), OFPPC_U);
cp += 4;
/* state */
ND_PRINT("\n\t state 0x%08x", GET_BE_U_4(cp));
- of_bitmap_print(ndo, ofpps_bm, GET_BE_U_4(cp), OFPPS_U);;
+ of_bitmap_print(ndo, ofpps_bm, GET_BE_U_4(cp), OFPPS_U);
cp += 4;
/* curr */
ND_PRINT("\n\t curr 0x%08x", GET_BE_U_4(cp));
of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
cp += 4;
/* advertised */
ND_PRINT("\n\t advertised 0x%08x", GET_BE_U_4(cp));
of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
cp += 4;
/* supported */
ND_PRINT("\n\t supported 0x%08x", GET_BE_U_4(cp));
of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
cp += 4;
/* peer */
ND_PRINT("\n\t peer 0x%08x", GET_BE_U_4(cp));
of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
cp += 4;
/* curr_speed */
ND_PRINT("\n\t curr_speed %ukbps", GET_BE_U_4(cp));
cp += 4;
/* max_speed */
ND_PRINT("\n\t max_speed %ukbps", GET_BE_U_4(cp));
}
/* [OF13] Section 7.3.1 */
static void
of13_features_reply_print(netdissect_options *ndo,
const u_char *cp, u_int len _U_)
{
/* datapath_id */
ND_PRINT("\n\t dpid 0x%016" PRIx64, GET_BE_U_8(cp));
cp += 8;
/* n_buffers */
ND_PRINT(", n_buffers %u", GET_BE_U_4(cp));
cp += 4;
/* n_tables */
ND_PRINT(", n_tables %u", GET_U_1(cp));
cp += 1;
/* auxiliary_id */
ND_PRINT(", auxiliary_id %u", GET_U_1(cp));
cp += 1;
/* pad */
cp += 2;
/* capabilities */
ND_PRINT("\n\t capabilities 0x%08x", GET_BE_U_4(cp));
of_bitmap_print(ndo, ofp_capabilities_bm, GET_BE_U_4(cp), OFPCAP_U);
cp += 4;
/* reserved */
ND_TCHECK_4(cp);
}
/* [OF13] Section 7.3.2 */
static void
of13_switch_config_msg_print(netdissect_options *ndo,
const u_char *cp, u_int len _U_)
{
/* flags */
ND_PRINT("\n\t flags %s",
tok2str(ofp_config_str, "invalid (0x%04x)", GET_BE_U_2(cp)));
cp += 2;
/* miss_send_len */
ND_PRINT(", miss_send_len %s",
tok2str(ofpcml_str, "%u", GET_BE_U_2(cp)));
}
/* [OF13] Section 7.3.3 */
static void
of13_table_mod_print(netdissect_options *ndo,
const u_char *cp, u_int len _U_)
{
/* table_id */
ND_PRINT("\n\t table_id %s", tok2str(ofptt_str, "%u", GET_U_1(cp)));
cp += 1;
/* pad */
cp += 3;
/* config */
ND_PRINT(", config 0x%08x", GET_BE_U_4(cp));
}
/* [OF13] Section 7.3.9 */
static void
of13_role_msg_print(netdissect_options *ndo,
const u_char *cp, u_int len _U_)
{
/* role */
ND_PRINT("\n\t role %s",
tok2str(ofpcr_str, "invalid (0x%08x)", GET_BE_U_4(cp)));
cp += 4;
/* pad */
cp += 4;
/* generation_id */
ND_PRINT(", generation_id 0x%016" PRIx64, GET_BE_U_8(cp));
}
/* [OF13] Section 7.3.10 */
static void
of13_async_msg_print(netdissect_options *ndo,
const u_char *cp, u_int len _U_)
{
/* packet_in_mask[0] */
ND_PRINT("\n\t packet_in_mask[EM] 0x%08x", GET_BE_U_4(cp));
of_bitmap_print(ndo, async_ofpr_bm, GET_BE_U_4(cp), ASYNC_OFPR_U);
cp += 4;
/* packet_in_mask[1] */
ND_PRINT("\n\t packet_in_mask[S] 0x%08x", GET_BE_U_4(cp));
of_bitmap_print(ndo, async_ofpr_bm, GET_BE_U_4(cp), ASYNC_OFPR_U);
cp += 4;
/* port_status_mask[0] */
ND_PRINT("\n\t port_status_mask[EM] 0x%08x", GET_BE_U_4(cp));
of_bitmap_print(ndo, async_ofppr_bm, GET_BE_U_4(cp), ASYNC_OFPPR_U);
cp += 4;
/* port_status_mask[1] */
ND_PRINT("\n\t port_status_mask[S] 0x%08x", GET_BE_U_4(cp));
of_bitmap_print(ndo, async_ofppr_bm, GET_BE_U_4(cp), ASYNC_OFPPR_U);
cp += 4;
/* flow_removed_mask[0] */
ND_PRINT("\n\t flow_removed_mask[EM] 0x%08x", GET_BE_U_4(cp));
of_bitmap_print(ndo, async_ofppr_bm, GET_BE_U_4(cp), ASYNC_OFPPR_U);
cp += 4;
/* flow_removed_mask[1] */
ND_PRINT("\n\t flow_removed_mask[S] 0x%08x", GET_BE_U_4(cp));
of_bitmap_print(ndo, async_ofppr_bm, GET_BE_U_4(cp), ASYNC_OFPPR_U);
}
/* [OF13] Section 7.3.4.3 */
static void
of13_port_mod_print(netdissect_options *ndo,
const u_char *cp, u_int len _U_)
{
/* port_no */
ND_PRINT("\n\t port_no %s", tok2str(ofpp_str, "%u", GET_BE_U_4(cp)));
cp += 4;
/* pad */
cp += 4;
/* hw_addr */
ND_PRINT(", hw_addr %s", GET_ETHERADDR_STRING(cp));
cp += MAC_ADDR_LEN;
/* pad2 */
cp += 2;
/* config */
ND_PRINT("\n\t config 0x%08x", GET_BE_U_4(cp));
of_bitmap_print(ndo, ofppc_bm, GET_BE_U_4(cp), OFPPC_U);
cp += 4;
/* mask */
ND_PRINT("\n\t mask 0x%08x", GET_BE_U_4(cp));
of_bitmap_print(ndo, ofppc_bm, GET_BE_U_4(cp), OFPPC_U);
cp += 4;
/* advertise */
ND_PRINT("\n\t advertise 0x%08x", GET_BE_U_4(cp));
of_bitmap_print(ndo, ofppf_bm, GET_BE_U_4(cp), OFPPF_U);
cp += 4;
/* pad3 */
/* Always the last field, check bounds. */
ND_TCHECK_4(cp);
}
/* [OF13] Section 7.4.3 */
static void
of13_port_status_print(netdissect_options *ndo,
const u_char *cp, u_int len _U_)
{
/* reason */
ND_PRINT("\n\t reason %s",
tok2str(ofppr_str, "invalid (0x02x)", GET_U_1(cp)));
cp += 1;
/* pad */
cp += 7;
/* desc */
of13_port_print(ndo, cp);
}
/* [OF13] Section 7.5.1 */
static void
of13_hello_elements_print(netdissect_options *ndo,
const u_char *cp, u_int len)
{
while (len) {
uint16_t type, bmlen;
- if (len < OF_HELLO_ELEM_MINSIZE)
- goto invalid;
+ ND_PRINT("\n\t");
+ ND_ICHECKMSG_U("remaining length", len, <, OF_HELLO_ELEM_MINSIZE);
/* type */
type = GET_BE_U_2(cp);
OF_FWD(2);
- ND_PRINT("\n\t type %s",
+ ND_PRINT(" type %s",
tok2str(ofphet_str, "unknown (0x%04x)", type));
/* length */
bmlen = GET_BE_U_2(cp);
OF_FWD(2);
ND_PRINT(", length %u", bmlen);
/* cp is OF_HELLO_ELEM_MINSIZE bytes in */
- if (bmlen < OF_HELLO_ELEM_MINSIZE ||
- bmlen > OF_HELLO_ELEM_MINSIZE + len)
- goto invalid;
+ ND_ICHECKMSG_U("bitmap length", bmlen, <, OF_HELLO_ELEM_MINSIZE);
+ ND_ICHECKMSG_U("bitmap length", bmlen, >, OF_HELLO_ELEM_MINSIZE + len);
switch (type) {
case OFPHET_VERSIONBITMAP:
/*
* The specification obviously overprovisions the space
* for version bitmaps in this element ("ofp versions
* 32 to 63 are encoded in the second bitmap and so
* on"). Keep this code simple for now and recognize
* only a single bitmap with no padding.
*/
if (bmlen == OF_HELLO_ELEM_MINSIZE + 4) {
uint32_t bitmap = GET_BE_U_4(cp);
ND_PRINT(", bitmap 0x%08x", bitmap);
of_bitmap_print(ndo, ofverbm_str, bitmap,
OF_BIT_VER_U);
} else {
ND_PRINT(" (bogus)");
ND_TCHECK_LEN(cp, bmlen - OF_HELLO_ELEM_MINSIZE);
}
break;
default:
ND_TCHECK_LEN(cp, bmlen - OF_HELLO_ELEM_MINSIZE);
}
OF_FWD(bmlen - OF_HELLO_ELEM_MINSIZE);
}
return;
invalid:
nd_print_invalid(ndo);
ND_TCHECK_LEN(cp, len);
}
/* [OF13] Section 7.5.4 */
static void
of13_experimenter_message_print(netdissect_options *ndo,
const u_char *cp, u_int len)
{
uint32_t experimenter;
/* experimenter */
experimenter = GET_BE_U_4(cp);
OF_FWD(4);
ND_PRINT("\n\t experimenter 0x%08x (%s)", experimenter,
of_vendor_name(experimenter));
/* exp_type */
ND_PRINT(", exp_type 0x%08x", GET_BE_U_4(cp));
OF_FWD(4);
/* data */
of_data_print(ndo, cp, len);
}
/* [OF13] Section 7.3.6 */
static void
of13_queue_get_config_request_print(netdissect_options *ndo,
const u_char *cp, u_int len _U_)
{
/* port */
ND_PRINT("\n\t port %s", tok2str(ofpp_str, "%u", GET_BE_U_4(cp)));
cp += 4;
/* pad */
/* Always the last field, check bounds. */
ND_TCHECK_4(cp);
}
/* [OF13] Section 7.4.4 */
static void
of13_error_print(netdissect_options *ndo,
const u_char *cp, u_int len)
{
uint16_t type, code;
const struct tok *code_str;
/* type */
type = GET_BE_U_2(cp);
OF_FWD(2);
ND_PRINT("\n\t type %s", tok2str(ofpet_str, "invalid (0x%04x)", type));
/* code */
code = GET_BE_U_2(cp);
OF_FWD(2);
code_str = uint2tokary(of13_ofpet2tokary, type);
if (code_str != NULL)
ND_PRINT(", code %s",
tok2str(code_str, "invalid (0x%04x)", code));
else
ND_PRINT(", code invalid (0x%04x)", code);
/* data */
of_data_print(ndo, cp, len);
}
static const struct of_msgtypeinfo of13_msgtypeinfo[OFPT_MAX + 1] = {
/*
* [OF13] Section 7.5.1
* n * variable-size data units.
*/
{
"HELLO", of13_hello_elements_print,
REQ_MINLEN, 0
},
/*
* [OF13] Section 7.4.4
* A fixed-size message body and variable-size data.
*/
{
"ERROR", of13_error_print,
REQ_MINLEN, OF_ERROR_MSG_MINLEN
},
/*
* [OF13] Section 7.5.2
* Variable-size data.
*/
{
"ECHO_REQUEST", of_data_print,
REQ_MINLEN, 0
},
/*
* [OF13] Section 7.5.3
* Variable-size data.
*/
{
"ECHO_REPLY", of_data_print,
REQ_MINLEN, 0
},
/*
* [OF13] Section 7.5.4
* A fixed-size message body and variable-size data.
*/
{
"EXPERIMENTER", of13_experimenter_message_print,
REQ_MINLEN, OF_EXPERIMENTER_MSG_MINLEN
},
/*
* [OF13] Section 7.3.1
* No message body.
*/
{
"FEATURES_REQUEST", NULL,
REQ_FIXLEN, 0
},
/*
* [OF13] Section 7.3.1
* A fixed-size message body.
*/
{
"FEATURES_REPLY", of13_features_reply_print,
REQ_FIXLEN, OF_FEATURES_REPLY_FIXLEN
},
/*
* [OF13] Section 7.3.2
* No message body.
*/
{
"GET_CONFIG_REQUEST", NULL,
REQ_FIXLEN, 0
},
/*
* [OF13] Section 7.3.2
* A fixed-size message body.
*/
{
"GET_CONFIG_REPLY", of13_switch_config_msg_print,
REQ_FIXLEN, OF_SWITCH_CONFIG_MSG_FIXLEN
},
/*
* [OF13] Section 7.3.2
* A fixed-size message body.
*/
{
"SET_CONFIG", of13_switch_config_msg_print,
REQ_FIXLEN, OF_SWITCH_CONFIG_MSG_FIXLEN
},
/*
* [OF13] Section 7.4.1
* (to be done)
*/
{
"PACKET_IN", NULL,
REQ_NONE, 0
},
/*
* [OF13] Section 7.4.2
* (to be done)
*/
{
"FLOW_REMOVED", NULL,
REQ_NONE, 0
},
/*
* [OF13] Section 7.4.3
* A fixed-size message body.
*/
{
"PORT_STATUS", of13_port_status_print,
REQ_FIXLEN, OF_PORT_STATUS_FIXLEN
},
/*
* [OF13] Section 7.3.7
* (to be done)
*/
{
"PACKET_OUT", NULL,
REQ_NONE, 0
},
/*
* [OF13] Section 7.3.4.1
* (to be done)
*/
{
"FLOW_MOD", NULL,
REQ_NONE, 0
},
/*
* [OF13] Section 7.3.4.2
* (to be done)
*/
{
"GROUP_MOD", NULL,
REQ_NONE, 0
},
/*
* [OF13] Section 7.3.4.3
* A fixed-size message body.
*/
{
"PORT_MOD", of13_port_mod_print,
REQ_FIXLEN, OF_PORT_MOD_FIXLEN
},
/*
* [OF13] Section 7.3.3
* A fixed-size message body.
*/
{
"TABLE_MOD", of13_table_mod_print,
REQ_FIXLEN, OF_TABLE_MOD_FIXLEN
},
/*
* [OF13] Section 7.3.5
* (to be done)
*/
{
"MULTIPART_REQUEST", NULL,
REQ_NONE, 0
},
/*
* [OF13] Section 7.3.5
* (to be done)
*/
{
"MULTIPART_REPLY", NULL,
REQ_NONE, 0
},
/*
* [OF13] Section 7.3.8
* No message body.
*/
{
"BARRIER_REQUEST", NULL,
REQ_FIXLEN, 0
},
/*
* [OF13] Section 7.3.8
* No message body.
*/
{
"BARRIER_REPLY", NULL,
REQ_FIXLEN, 0
},
/*
* [OF13] Section 7.3.6
* A fixed-size message body.
*/
{
"QUEUE_GET_CONFIG_REQUEST", of13_queue_get_config_request_print,
REQ_FIXLEN, OF_QUEUE_GET_CONFIG_REQUEST_FIXLEN
},
/*
* [OF13] Section 7.3.6
* (to be done)
*/
{
"QUEUE_GET_CONFIG_REPLY", NULL,
REQ_NONE, 0
},
/*
* [OF13] Section 7.3.9
* A fixed-size message body.
*/
{
"ROLE_REQUEST", of13_role_msg_print,
REQ_FIXLEN, OF_ROLE_MSG_FIXLEN
},
/*
* [OF13] Section 7.3.9
* A fixed-size message body.
*/
{
"ROLE_REPLY", of13_role_msg_print,
REQ_FIXLEN, OF_ROLE_MSG_FIXLEN
},
/*
* [OF13] Section 7.3.10
* No message body.
*/
{
"GET_ASYNC_REQUEST", NULL,
REQ_FIXLEN, 0
},
/*
* [OF13] Section 7.3.10
* A fixed-size message body.
*/
{
"GET_ASYNC_REPLY", of13_async_msg_print,
REQ_FIXLEN, OF_ASYNC_MSG_FIXLEN
},
/*
* [OF13] Section 7.3.10
* A fixed-size message body.
*/
{
"SET_ASYNC", of13_async_msg_print,
REQ_FIXLEN, OF_ASYNC_MSG_FIXLEN
},
/*
* [OF13] Section 7.3.4.4
* (to be done)
*/
{
"METER_MOD", NULL,
REQ_NONE, 0
},
};
const struct of_msgtypeinfo *
of13_identify_msgtype(const uint8_t type)
{
return type <= OFPT_MAX ? &of13_msgtypeinfo[type] : NULL;
}
diff --git a/contrib/tcpdump/print-openflow.c b/contrib/tcpdump/print-openflow.c
index 6024a215a133..82eeda0c7267 100644
--- a/contrib/tcpdump/print-openflow.c
+++ b/contrib/tcpdump/print-openflow.c
@@ -1,228 +1,226 @@
/*
* This module implements printing of the very basic (version-independent)
* OpenFlow header and iteration over OpenFlow messages. It is intended for
* dispatching of version-specific OpenFlow message decoding.
*
*
* Copyright (c) 2013 The TCPDUMP project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* \summary: version-independent OpenFlow printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
#include "openflow.h"
#include "oui.h"
static const struct tok ofver_str[] = {
{ OF_VER_1_0, "1.0" },
{ OF_VER_1_1, "1.1" },
{ OF_VER_1_2, "1.2" },
{ OF_VER_1_3, "1.3" },
{ OF_VER_1_4, "1.4" },
{ OF_VER_1_5, "1.5" },
{ 0, NULL }
};
const struct tok onf_exp_str[] = {
{ ONF_EXP_ONF, "ONF Extensions" },
{ ONF_EXP_BUTE, "Budapest University of Technology and Economics" },
{ ONF_EXP_NOVIFLOW, "NoviFlow" },
{ ONF_EXP_L3, "L3+ Extensions, Vendor Neutral" },
{ ONF_EXP_L4L7, "L4-L7 Extensions" },
{ ONF_EXP_WMOB, "Wireless and Mobility Extensions" },
{ ONF_EXP_FABS, "Forwarding Abstractions Extensions" },
{ ONF_EXP_OTRANS, "Optical Transport Extensions" },
{ ONF_EXP_NBLNCTU, "Network Benchmarking Lab, NCTU" },
{ ONF_EXP_MPCE, "Mobile Packet Core Extensions" },
{ ONF_EXP_MPLSTPSPTN, "MPLS-TP OpenFlow Extensions for SPTN" },
{ 0, NULL }
};
const char *
of_vendor_name(const uint32_t vendor)
{
const struct tok *table = (vendor & 0xff000000) == 0 ? oui_values : onf_exp_str;
return tok2str(table, "unknown", vendor);
}
void
of_bitmap_print(netdissect_options *ndo,
const struct tok *t, const uint32_t v, const uint32_t u)
{
/* Assigned bits? */
if (v & ~u)
ND_PRINT(" (%s)", bittok2str(t, "", v));
/* Unassigned bits? */
if (v & u)
ND_PRINT(" (bogus)");
}
void
of_data_print(netdissect_options *ndo,
const u_char *cp, const u_int len)
{
if (len == 0)
return;
/* data */
ND_PRINT("\n\t data (%u octets)", len);
if (ndo->ndo_vflag >= 2)
hex_and_ascii_print(ndo, "\n\t ", cp, len);
else
ND_TCHECK_LEN(cp, len);
}
static void
of_message_print(netdissect_options *ndo,
const u_char *cp, uint16_t len,
const struct of_msgtypeinfo *mti)
{
/*
* Here "cp" and "len" stand for the message part beyond the common
* OpenFlow 1.0 header, if any.
*
* Most message types are longer than just the header, and the length
* constraints may be complex. When possible, validate the constraint
* completely here (REQ_FIXLEN), otherwise check that the message is
* long enough to begin the decoding (REQ_MINLEN) and have the
* type-specific function do any remaining validation.
*/
if (!mti)
goto tcheck_remainder;
if ((mti->req_what == REQ_FIXLEN && len != mti->req_value) ||
(mti->req_what == REQ_MINLEN && len < mti->req_value))
goto invalid;
if (!ndo->ndo_vflag || !mti->decoder)
goto tcheck_remainder;
mti->decoder(ndo, cp, len);
return;
invalid:
nd_print_invalid(ndo);
tcheck_remainder:
ND_TCHECK_LEN(cp, len);
}
/* Print a TCP segment worth of OpenFlow messages presuming the segment begins
* on a message boundary. */
void
openflow_print(netdissect_options *ndo, const u_char *cp, u_int len)
{
ndo->ndo_protocol = "openflow";
ND_PRINT(": OpenFlow");
while (len) {
/* Print a single OpenFlow message. */
uint8_t version, type;
uint16_t length;
const struct of_msgtypeinfo *mti;
/* version */
version = GET_U_1(cp);
OF_FWD(1);
ND_PRINT("\n\tversion %s",
tok2str(ofver_str, "unknown (0x%02x)", version));
/* type */
if (len < 1)
goto partial_header;
type = GET_U_1(cp);
OF_FWD(1);
mti =
version == OF_VER_1_0 ? of10_identify_msgtype(type) :
version == OF_VER_1_3 ? of13_identify_msgtype(type) :
NULL;
if (mti && mti->name)
ND_PRINT(", type %s", mti->name);
else
ND_PRINT(", type unknown (0x%02x)", type);
/* length */
if (len < 2)
goto partial_header;
length = GET_BE_U_2(cp);
OF_FWD(2);
ND_PRINT(", length %u%s", length,
length < OF_HEADER_FIXLEN ? " (too short!)" : "");
/* xid */
if (len < 4)
goto partial_header;
ND_PRINT(", xid 0x%08x", GET_BE_U_4(cp));
OF_FWD(4);
/*
* When a TCP packet can contain several protocol messages,
* and at the same time a protocol message can span several
* TCP packets, decoding an incomplete message at the end of
* a TCP packet requires attention to detail in this loop.
*
* Message length includes the header length and a message
* always includes the basic header. A message length underrun
* fails decoding of the rest of the current packet. At the
* same time, try decoding as much of the current message as
* possible even when it does not end within the current TCP
* segment.
*
* Specifically, to try to process the message body in this
* iteration do NOT require the header "length" to be small
* enough for the full declared OpenFlow message to fit into
* the remainder of the declared TCP segment, same as the full
* declared TCP segment is not required to fit into the
* captured packet buffer.
*
* But DO require the same at the end of this iteration to
* decrement "len" and to proceed to the next iteration.
* (Ideally the declared TCP payload end will be at or after
* the captured packet buffer end, but stay safe even when
* that's somehow not the case.)
*/
if (length < OF_HEADER_FIXLEN)
goto invalid;
of_message_print(ndo, cp, length - OF_HEADER_FIXLEN, mti);
if (length - OF_HEADER_FIXLEN > len)
break;
OF_FWD(length - OF_HEADER_FIXLEN);
} /* while (len) */
return;
partial_header:
ND_PRINT(" (end of TCP payload)");
ND_TCHECK_LEN(cp, len);
return;
invalid: /* fail the current packet */
nd_print_invalid(ndo);
ND_TCHECK_LEN(cp, len);
}
diff --git a/contrib/tcpdump/print-ospf.c b/contrib/tcpdump/print-ospf.c
index e6bebed374f8..eae546d9c296 100644
--- a/contrib/tcpdump/print-ospf.c
+++ b/contrib/tcpdump/print-ospf.c
@@ -1,1178 +1,1182 @@
/*
* Copyright (c) 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.
*
* OSPF support contributed by Jeffrey Honig (jch@mitchell.cit.cornell.edu)
*/
/* \summary: Open Shortest Path First (OSPF) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#include "gmpls.h"
#include "ospf.h"
static const struct tok ospf_option_values[] = {
{ OSPF_OPTION_MT, "MultiTopology" }, /* draft-ietf-ospf-mt-09 */
{ OSPF_OPTION_E, "External" },
{ OSPF_OPTION_MC, "Multicast" },
{ OSPF_OPTION_NP, "NSSA" },
{ OSPF_OPTION_L, "LLS" },
{ OSPF_OPTION_DC, "Demand Circuit" },
{ OSPF_OPTION_O, "Opaque" },
{ OSPF_OPTION_DN, "Up/Down" },
{ 0, NULL }
};
static const struct tok ospf_authtype_values[] = {
{ OSPF_AUTH_NONE, "none" },
{ OSPF_AUTH_SIMPLE, "simple" },
{ OSPF_AUTH_MD5, "MD5" },
{ 0, NULL }
};
static const struct tok ospf_rla_flag_values[] = {
{ RLA_FLAG_B, "ABR" },
{ RLA_FLAG_E, "ASBR" },
{ RLA_FLAG_V, "Virtual" },
{ RLA_FLAG_W, "Wildcard" },
{ RLA_FLAG_NT, "Nt" },
{ RLA_FLAG_H, "Host" },
{ 0, NULL }
};
static const struct tok type2str[] = {
{ OSPF_TYPE_HELLO, "Hello" },
{ OSPF_TYPE_DD, "Database Description" },
{ OSPF_TYPE_LS_REQ, "LS-Request" },
{ OSPF_TYPE_LS_UPDATE, "LS-Update" },
{ OSPF_TYPE_LS_ACK, "LS-Ack" },
{ 0, NULL }
};
static const struct tok lsa_values[] = {
{ LS_TYPE_ROUTER, "Router" },
{ LS_TYPE_NETWORK, "Network" },
{ LS_TYPE_SUM_IP, "Summary" },
{ LS_TYPE_SUM_ABR, "ASBR Summary" },
{ LS_TYPE_ASE, "External" },
{ LS_TYPE_GROUP, "Multicast Group" },
{ LS_TYPE_NSSA, "NSSA" },
{ LS_TYPE_OPAQUE_LL, "Link Local Opaque" },
{ LS_TYPE_OPAQUE_AL, "Area Local Opaque" },
{ LS_TYPE_OPAQUE_DW, "Domain Wide Opaque" },
{ 0, NULL }
};
static const struct tok ospf_dd_flag_values[] = {
{ OSPF_DB_INIT, "Init" },
{ OSPF_DB_MORE, "More" },
{ OSPF_DB_MASTER, "Master" },
{ OSPF_DB_RESYNC, "OOBResync" },
{ 0, NULL }
};
static const struct tok lsa_opaque_values[] = {
{ LS_OPAQUE_TYPE_TE, "Traffic Engineering" },
{ LS_OPAQUE_TYPE_GRACE, "Graceful restart" },
{ LS_OPAQUE_TYPE_RI, "Router Information" },
{ 0, NULL }
};
static const struct tok lsa_opaque_te_tlv_values[] = {
{ LS_OPAQUE_TE_TLV_ROUTER, "Router Address" },
{ LS_OPAQUE_TE_TLV_LINK, "Link" },
{ 0, NULL }
};
static const struct tok lsa_opaque_te_link_tlv_subtlv_values[] = {
{ LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE, "Link Type" },
{ LS_OPAQUE_TE_LINK_SUBTLV_LINK_ID, "Link ID" },
{ LS_OPAQUE_TE_LINK_SUBTLV_LOCAL_IP, "Local Interface IP address" },
{ LS_OPAQUE_TE_LINK_SUBTLV_REMOTE_IP, "Remote Interface IP address" },
{ LS_OPAQUE_TE_LINK_SUBTLV_TE_METRIC, "Traffic Engineering Metric" },
{ LS_OPAQUE_TE_LINK_SUBTLV_MAX_BW, "Maximum Bandwidth" },
{ LS_OPAQUE_TE_LINK_SUBTLV_MAX_RES_BW, "Maximum Reservable Bandwidth" },
{ LS_OPAQUE_TE_LINK_SUBTLV_UNRES_BW, "Unreserved Bandwidth" },
{ LS_OPAQUE_TE_LINK_SUBTLV_ADMIN_GROUP, "Administrative Group" },
{ LS_OPAQUE_TE_LINK_SUBTLV_LINK_LOCAL_REMOTE_ID, "Link Local/Remote Identifier" },
{ LS_OPAQUE_TE_LINK_SUBTLV_LINK_PROTECTION_TYPE, "Link Protection Type" },
{ LS_OPAQUE_TE_LINK_SUBTLV_INTF_SW_CAP_DESCR, "Interface Switching Capability" },
{ LS_OPAQUE_TE_LINK_SUBTLV_SHARED_RISK_GROUP, "Shared Risk Link Group" },
{ LS_OPAQUE_TE_LINK_SUBTLV_BW_CONSTRAINTS, "Bandwidth Constraints" },
{ 0, NULL }
};
static const struct tok lsa_opaque_grace_tlv_values[] = {
{ LS_OPAQUE_GRACE_TLV_PERIOD, "Grace Period" },
{ LS_OPAQUE_GRACE_TLV_REASON, "Graceful restart Reason" },
{ LS_OPAQUE_GRACE_TLV_INT_ADDRESS, "IPv4 interface address" },
{ 0, NULL }
};
static const struct tok lsa_opaque_grace_tlv_reason_values[] = {
{ LS_OPAQUE_GRACE_TLV_REASON_UNKNOWN, "Unknown" },
{ LS_OPAQUE_GRACE_TLV_REASON_SW_RESTART, "Software Restart" },
{ LS_OPAQUE_GRACE_TLV_REASON_SW_UPGRADE, "Software Reload/Upgrade" },
{ LS_OPAQUE_GRACE_TLV_REASON_CP_SWITCH, "Control Processor Switch" },
{ 0, NULL }
};
static const struct tok lsa_opaque_te_tlv_link_type_sub_tlv_values[] = {
{ LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE_PTP, "Point-to-point" },
{ LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE_MA, "Multi-Access" },
{ 0, NULL }
};
static const struct tok lsa_opaque_ri_tlv_values[] = {
{ LS_OPAQUE_RI_TLV_CAP, "Router Capabilities" },
{ 0, NULL }
};
static const struct tok lsa_opaque_ri_tlv_cap_values[] = {
{ 1, "Reserved" },
{ 2, "Reserved" },
{ 4, "Reserved" },
{ 8, "Reserved" },
{ 16, "graceful restart capable" },
{ 32, "graceful restart helper" },
{ 64, "Stub router support" },
{ 128, "Traffic engineering" },
{ 256, "p2p over LAN" },
{ 512, "path computation server" },
{ 0, NULL }
};
static const struct tok ospf_lls_tlv_values[] = {
{ OSPF_LLS_EO, "Extended Options" },
{ OSPF_LLS_MD5, "MD5 Authentication" },
{ 0, NULL }
};
static const struct tok ospf_lls_eo_options[] = {
{ OSPF_LLS_EO_LR, "LSDB resync" },
{ OSPF_LLS_EO_RS, "Restart" },
{ 0, NULL }
};
int
ospf_grace_lsa_print(netdissect_options *ndo,
const u_char *tptr, u_int ls_length)
{
u_int tlv_type, tlv_length;
while (ls_length > 0) {
ND_TCHECK_4(tptr);
if (ls_length < 4) {
ND_PRINT("\n\t Remaining LS length %u < 4", ls_length);
return -1;
}
tlv_type = GET_BE_U_2(tptr);
tlv_length = GET_BE_U_2(tptr + 2);
tptr+=4;
ls_length-=4;
ND_PRINT("\n\t %s TLV (%u), length %u, value: ",
tok2str(lsa_opaque_grace_tlv_values,"unknown",tlv_type),
tlv_type,
tlv_length);
if (tlv_length > ls_length) {
ND_PRINT("\n\t Bogus length %u > %u", tlv_length,
ls_length);
return -1;
}
/* Infinite loop protection. */
if (tlv_type == 0 || tlv_length ==0) {
return -1;
}
ND_TCHECK_LEN(tptr, tlv_length);
switch(tlv_type) {
case LS_OPAQUE_GRACE_TLV_PERIOD:
if (tlv_length != 4) {
ND_PRINT("\n\t Bogus length %u != 4", tlv_length);
return -1;
}
ND_PRINT("%us", GET_BE_U_4(tptr));
break;
case LS_OPAQUE_GRACE_TLV_REASON:
if (tlv_length != 1) {
ND_PRINT("\n\t Bogus length %u != 1", tlv_length);
return -1;
}
ND_PRINT("%s (%u)",
tok2str(lsa_opaque_grace_tlv_reason_values, "Unknown", GET_U_1(tptr)),
GET_U_1(tptr));
break;
case LS_OPAQUE_GRACE_TLV_INT_ADDRESS:
if (tlv_length != 4) {
ND_PRINT("\n\t Bogus length %u != 4", tlv_length);
return -1;
}
ND_PRINT("%s", GET_IPADDR_STRING(tptr));
break;
default:
if (ndo->ndo_vflag <= 1) {
if (!print_unknown_data(ndo, tptr, "\n\t ", tlv_length))
return -1;
}
break;
}
/* in OSPF everything has to be 32-bit aligned, including TLVs */
if (tlv_length%4 != 0)
tlv_length+=4-(tlv_length%4);
ls_length-=tlv_length;
tptr+=tlv_length;
}
return 0;
trunc:
return -1;
}
int
ospf_te_lsa_print(netdissect_options *ndo,
const u_char *tptr, u_int ls_length)
{
u_int tlv_type, tlv_length, subtlv_type, subtlv_length;
u_int priority_level, te_class, count_srlg;
union { /* int to float conversion buffer for several subTLVs */
float f;
uint32_t i;
} bw;
while (ls_length != 0) {
ND_TCHECK_4(tptr);
if (ls_length < 4) {
ND_PRINT("\n\t Remaining LS length %u < 4", ls_length);
return -1;
}
tlv_type = GET_BE_U_2(tptr);
tlv_length = GET_BE_U_2(tptr + 2);
tptr+=4;
ls_length-=4;
ND_PRINT("\n\t %s TLV (%u), length: %u",
tok2str(lsa_opaque_te_tlv_values,"unknown",tlv_type),
tlv_type,
tlv_length);
if (tlv_length > ls_length) {
ND_PRINT("\n\t Bogus length %u > %u", tlv_length,
ls_length);
return -1;
}
/* Infinite loop protection. */
if (tlv_type == 0 || tlv_length ==0) {
return -1;
}
switch(tlv_type) {
case LS_OPAQUE_TE_TLV_LINK:
while (tlv_length != 0) {
if (tlv_length < 4) {
ND_PRINT("\n\t Remaining TLV length %u < 4",
tlv_length);
return -1;
}
subtlv_type = GET_BE_U_2(tptr);
subtlv_length = GET_BE_U_2(tptr + 2);
tptr+=4;
tlv_length-=4;
/* Infinite loop protection */
if (subtlv_type == 0 || subtlv_length == 0)
goto invalid;
ND_PRINT("\n\t %s subTLV (%u), length: %u",
tok2str(lsa_opaque_te_link_tlv_subtlv_values,"unknown",subtlv_type),
subtlv_type,
subtlv_length);
if (tlv_length < subtlv_length) {
ND_PRINT("\n\t Remaining TLV length %u < %u",
tlv_length + 4, subtlv_length + 4);
return -1;
}
ND_TCHECK_LEN(tptr, subtlv_length);
switch(subtlv_type) {
case LS_OPAQUE_TE_LINK_SUBTLV_ADMIN_GROUP:
if (subtlv_length != 4) {
ND_PRINT(" != 4");
goto invalid;
}
ND_PRINT(", 0x%08x", GET_BE_U_4(tptr));
break;
case LS_OPAQUE_TE_LINK_SUBTLV_LINK_ID:
case LS_OPAQUE_TE_LINK_SUBTLV_LINK_LOCAL_REMOTE_ID:
if (subtlv_length != 4 && subtlv_length != 8) {
ND_PRINT(" != 4 && != 8");
goto invalid;
}
ND_PRINT(", %s (0x%08x)",
GET_IPADDR_STRING(tptr),
GET_BE_U_4(tptr));
if (subtlv_length == 8) /* rfc4203 */
ND_PRINT(", %s (0x%08x)",
GET_IPADDR_STRING(tptr+4),
GET_BE_U_4(tptr + 4));
break;
case LS_OPAQUE_TE_LINK_SUBTLV_LOCAL_IP:
case LS_OPAQUE_TE_LINK_SUBTLV_REMOTE_IP:
if (subtlv_length != 4) {
ND_PRINT(" != 4");
goto invalid;
}
ND_PRINT(", %s", GET_IPADDR_STRING(tptr));
break;
case LS_OPAQUE_TE_LINK_SUBTLV_MAX_BW:
case LS_OPAQUE_TE_LINK_SUBTLV_MAX_RES_BW:
if (subtlv_length != 4) {
ND_PRINT(" != 4");
goto invalid;
}
bw.i = GET_BE_U_4(tptr);
ND_PRINT(", %.3f Mbps", bw.f * 8 / 1000000);
break;
case LS_OPAQUE_TE_LINK_SUBTLV_UNRES_BW:
if (subtlv_length != 32) {
ND_PRINT(" != 32");
goto invalid;
}
for (te_class = 0; te_class < 8; te_class++) {
bw.i = GET_BE_U_4(tptr + te_class * 4);
ND_PRINT("\n\t\tTE-Class %u: %.3f Mbps",
te_class,
bw.f * 8 / 1000000);
}
break;
case LS_OPAQUE_TE_LINK_SUBTLV_BW_CONSTRAINTS:
if (subtlv_length < 4) {
ND_PRINT(" < 4");
goto invalid;
}
/* BC Model Id (1 octet) + Reserved (3 octets) */
ND_PRINT("\n\t\tBandwidth Constraints Model ID: %s (%u)",
tok2str(diffserv_te_bc_values, "unknown", GET_U_1(tptr)),
GET_U_1(tptr));
if (subtlv_length % 4 != 0) {
ND_PRINT("\n\t\tlength %u != N x 4", subtlv_length);
goto invalid;
}
if (subtlv_length > 36) {
ND_PRINT("\n\t\tlength %u > 36", subtlv_length);
goto invalid;
}
/* decode BCs until the subTLV ends */
for (te_class = 0; te_class < (subtlv_length-4)/4; te_class++) {
bw.i = GET_BE_U_4(tptr + 4 + te_class * 4);
ND_PRINT("\n\t\t Bandwidth constraint CT%u: %.3f Mbps",
te_class,
bw.f * 8 / 1000000);
}
break;
case LS_OPAQUE_TE_LINK_SUBTLV_TE_METRIC:
if (subtlv_length != 4) {
ND_PRINT(" != 4");
goto invalid;
}
ND_PRINT(", Metric %u", GET_BE_U_4(tptr));
break;
case LS_OPAQUE_TE_LINK_SUBTLV_LINK_PROTECTION_TYPE:
/* Protection Cap (1 octet) + Reserved ((3 octets) */
if (subtlv_length != 4) {
ND_PRINT(" != 4");
goto invalid;
}
ND_PRINT(", %s",
bittok2str(gmpls_link_prot_values, "none", GET_U_1(tptr)));
break;
case LS_OPAQUE_TE_LINK_SUBTLV_INTF_SW_CAP_DESCR:
if (subtlv_length < 36) {
ND_PRINT(" < 36");
goto invalid;
}
/* Switching Cap (1 octet) + Encoding (1) + Reserved (2) */
ND_PRINT("\n\t\tInterface Switching Capability: %s",
tok2str(gmpls_switch_cap_values, "Unknown", GET_U_1((tptr))));
ND_PRINT("\n\t\tLSP Encoding: %s\n\t\tMax LSP Bandwidth:",
tok2str(gmpls_encoding_values, "Unknown", GET_U_1((tptr + 1))));
for (priority_level = 0; priority_level < 8; priority_level++) {
bw.i = GET_BE_U_4(tptr + 4 + (priority_level * 4));
ND_PRINT("\n\t\t priority level %u: %.3f Mbps",
priority_level,
bw.f * 8 / 1000000);
}
break;
case LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE:
if (subtlv_length != 1) {
ND_PRINT(" != 1");
goto invalid;
}
ND_PRINT(", %s (%u)",
tok2str(lsa_opaque_te_tlv_link_type_sub_tlv_values,"unknown",GET_U_1(tptr)),
GET_U_1(tptr));
break;
case LS_OPAQUE_TE_LINK_SUBTLV_SHARED_RISK_GROUP:
if (subtlv_length % 4 != 0) {
ND_PRINT(" != N x 4");
goto invalid;
}
count_srlg = subtlv_length / 4;
if (count_srlg != 0)
ND_PRINT("\n\t\t Shared risk group: ");
while (count_srlg > 0) {
bw.i = GET_BE_U_4(tptr);
ND_PRINT("%u", bw.i);
tptr+=4;
count_srlg--;
if (count_srlg > 0)
ND_PRINT(", ");
}
break;
default:
if (ndo->ndo_vflag <= 1) {
if (!print_unknown_data(ndo, tptr, "\n\t\t", subtlv_length))
return -1;
}
break;
}
/* in OSPF everything has to be 32-bit aligned, including subTLVs */
if (subtlv_length%4 != 0)
subtlv_length+=4-(subtlv_length%4);
if (tlv_length < subtlv_length) {
ND_PRINT("\n\t Remaining TLV length %u < %u",
tlv_length + 4, subtlv_length + 4);
return -1;
}
tlv_length-=subtlv_length;
tptr+=subtlv_length;
}
break;
case LS_OPAQUE_TE_TLV_ROUTER:
if (tlv_length < 4) {
ND_PRINT("\n\t TLV length %u < 4", tlv_length);
return -1;
}
ND_PRINT(", %s", GET_IPADDR_STRING(tptr));
break;
default:
if (ndo->ndo_vflag <= 1) {
if (!print_unknown_data(ndo, tptr, "\n\t ", tlv_length))
return -1;
}
break;
}
/* in OSPF everything has to be 32-bit aligned, including TLVs */
if (tlv_length%4 != 0)
tlv_length+=4-(tlv_length%4);
if (tlv_length > ls_length) {
ND_PRINT("\n\t Bogus padded length %u > %u", tlv_length,
ls_length);
return -1;
}
ls_length-=tlv_length;
tptr+=tlv_length;
}
return 0;
trunc:
return -1;
invalid:
nd_print_invalid(ndo);
return -1;
}
static int
ospf_print_lshdr(netdissect_options *ndo,
const struct lsa_hdr *lshp)
{
u_int ls_type;
u_int ls_length;
ls_length = GET_BE_U_2(lshp->ls_length);
if (ls_length < sizeof(struct lsa_hdr)) {
ND_PRINT("\n\t Bogus length %u < header (%zu)", ls_length,
sizeof(struct lsa_hdr));
return(-1);
}
ND_PRINT("\n\t Advertising Router %s, seq 0x%08x, age %us, length %zu",
GET_IPADDR_STRING(lshp->ls_router),
GET_BE_U_4(lshp->ls_seq),
GET_BE_U_2(lshp->ls_age),
ls_length - sizeof(struct lsa_hdr));
ls_type = GET_U_1(lshp->ls_type);
switch (ls_type) {
/* the LSA header for opaque LSAs was slightly changed */
case LS_TYPE_OPAQUE_LL:
case LS_TYPE_OPAQUE_AL:
case LS_TYPE_OPAQUE_DW:
ND_PRINT("\n\t %s LSA (%u), Opaque-Type %s LSA (%u), Opaque-ID %u",
tok2str(lsa_values,"unknown",ls_type),
ls_type,
tok2str(lsa_opaque_values,
"unknown",
GET_U_1(lshp->un_lsa_id.opaque_field.opaque_type)),
GET_U_1(lshp->un_lsa_id.opaque_field.opaque_type),
GET_BE_U_3(lshp->un_lsa_id.opaque_field.opaque_id)
);
break;
/* all other LSA types use regular style LSA headers */
default:
ND_PRINT("\n\t %s LSA (%u), LSA-ID: %s",
tok2str(lsa_values,"unknown",ls_type),
ls_type,
GET_IPADDR_STRING(lshp->un_lsa_id.lsa_id));
break;
}
ND_PRINT("\n\t Options: [%s]",
bittok2str(ospf_option_values, "none", GET_U_1(lshp->ls_options)));
return (ls_length);
}
/* draft-ietf-ospf-mt-09 */
static const struct tok ospf_topology_values[] = {
{ 0, "default" },
{ 1, "multicast" },
{ 2, "management" },
{ 0, NULL }
};
/*
* Print all the per-topology metrics.
*/
static void
ospf_print_tos_metrics(netdissect_options *ndo,
const union un_tos *tos)
{
u_int metric_count;
u_int toscount;
u_int tos_type;
toscount = GET_U_1(tos->link.link_tos_count)+1;
metric_count = 0;
/*
* All but the first metric contain a valid topology id.
*/
while (toscount != 0) {
tos_type = GET_U_1(tos->metrics.tos_type);
ND_PRINT("\n\t\ttopology %s (%u), metric %u",
tok2str(ospf_topology_values, "Unknown",
metric_count ? tos_type : 0),
metric_count ? tos_type : 0,
GET_BE_U_2(tos->metrics.tos_metric));
metric_count++;
tos++;
toscount--;
}
}
/*
* Print a single link state advertisement. If truncated or if LSA length
* field is less than the length of the LSA header, return NULl, else
* return pointer to data past end of LSA.
*/
static const uint8_t *
ospf_print_lsa(netdissect_options *ndo,
const struct lsa *lsap)
{
const uint8_t *ls_end;
const struct rlalink *rlp;
const nd_ipv4 *ap;
const struct aslametric *almp;
const struct mcla *mcp;
const uint8_t *lp;
u_int tlv_type, tlv_length, rla_count, topology;
int ospf_print_lshdr_ret;
u_int ls_length;
const uint8_t *tptr;
tptr = (const uint8_t *)lsap->lsa_un.un_unknown; /* squelch compiler warnings */
ospf_print_lshdr_ret = ospf_print_lshdr(ndo, &lsap->ls_hdr);
if (ospf_print_lshdr_ret < 0)
return(NULL);
ls_length = (u_int)ospf_print_lshdr_ret;
ls_end = (const uint8_t *)lsap + ls_length;
/*
* ospf_print_lshdr() returns -1 if the length is too short,
* so we know ls_length is >= sizeof(struct lsa_hdr).
*/
ls_length -= sizeof(struct lsa_hdr);
switch (GET_U_1(lsap->ls_hdr.ls_type)) {
case LS_TYPE_ROUTER:
ND_PRINT("\n\t Router LSA Options: [%s]",
bittok2str(ospf_rla_flag_values, "none", GET_U_1(lsap->lsa_un.un_rla.rla_flags)));
rla_count = GET_BE_U_2(lsap->lsa_un.un_rla.rla_count);
ND_TCHECK_SIZE(lsap->lsa_un.un_rla.rla_link);
rlp = lsap->lsa_un.un_rla.rla_link;
for (u_int i = rla_count; i != 0; i--) {
ND_TCHECK_SIZE(rlp);
switch (GET_U_1(rlp->un_tos.link.link_type)) {
case RLA_TYPE_VIRTUAL:
ND_PRINT("\n\t Virtual Link: Neighbor Router-ID: %s, Interface Address: %s",
GET_IPADDR_STRING(rlp->link_id),
GET_IPADDR_STRING(rlp->link_data));
break;
case RLA_TYPE_ROUTER:
ND_PRINT("\n\t Neighbor Router-ID: %s, Interface Address: %s",
GET_IPADDR_STRING(rlp->link_id),
GET_IPADDR_STRING(rlp->link_data));
break;
case RLA_TYPE_TRANSIT:
ND_PRINT("\n\t Neighbor Network-ID: %s, Interface Address: %s",
GET_IPADDR_STRING(rlp->link_id),
GET_IPADDR_STRING(rlp->link_data));
break;
case RLA_TYPE_STUB:
ND_PRINT("\n\t Stub Network: %s, Mask: %s",
GET_IPADDR_STRING(rlp->link_id),
GET_IPADDR_STRING(rlp->link_data));
break;
default:
ND_PRINT("\n\t Unknown Router Link Type (%u)",
GET_U_1(rlp->un_tos.link.link_type));
return (ls_end);
}
ospf_print_tos_metrics(ndo, &rlp->un_tos);
rlp = (const struct rlalink *)((const u_char *)(rlp + 1) +
(GET_U_1(rlp->un_tos.link.link_tos_count) * sizeof(union un_tos)));
}
break;
case LS_TYPE_NETWORK:
ND_PRINT("\n\t Mask %s\n\t Connected Routers:",
GET_IPADDR_STRING(lsap->lsa_un.un_nla.nla_mask));
ap = lsap->lsa_un.un_nla.nla_router;
while ((const u_char *)ap < ls_end) {
ND_PRINT("\n\t %s", GET_IPADDR_STRING(ap));
++ap;
}
break;
case LS_TYPE_SUM_IP:
ND_TCHECK_4(lsap->lsa_un.un_nla.nla_mask);
ND_PRINT("\n\t Mask %s",
GET_IPADDR_STRING(lsap->lsa_un.un_sla.sla_mask));
ND_TCHECK_SIZE(lsap->lsa_un.un_sla.sla_tosmetric);
lp = (const uint8_t *)lsap->lsa_un.un_sla.sla_tosmetric;
while (lp < ls_end) {
uint32_t ul;
ul = GET_BE_U_4(lp);
topology = (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS;
ND_PRINT("\n\t\ttopology %s (%u) metric %u",
tok2str(ospf_topology_values, "Unknown", topology),
topology,
ul & SLA_MASK_METRIC);
lp += 4;
}
break;
case LS_TYPE_SUM_ABR:
ND_TCHECK_SIZE(lsap->lsa_un.un_sla.sla_tosmetric);
lp = (const uint8_t *)lsap->lsa_un.un_sla.sla_tosmetric;
while (lp < ls_end) {
uint32_t ul;
ul = GET_BE_U_4(lp);
topology = (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS;
ND_PRINT("\n\t\ttopology %s (%u) metric %u",
tok2str(ospf_topology_values, "Unknown", topology),
topology,
ul & SLA_MASK_METRIC);
lp += 4;
}
break;
case LS_TYPE_ASE:
case LS_TYPE_NSSA: /* fall through - those LSAs share the same format */
ND_TCHECK_4(lsap->lsa_un.un_nla.nla_mask);
ND_PRINT("\n\t Mask %s",
GET_IPADDR_STRING(lsap->lsa_un.un_asla.asla_mask));
ND_TCHECK_SIZE(lsap->lsa_un.un_sla.sla_tosmetric);
almp = lsap->lsa_un.un_asla.asla_metric;
while ((const u_char *)almp < ls_end) {
uint32_t ul;
ul = GET_BE_U_4(almp->asla_tosmetric);
topology = ((ul & ASLA_MASK_TOS) >> ASLA_SHIFT_TOS);
ND_PRINT("\n\t\ttopology %s (%u), type %u, metric",
tok2str(ospf_topology_values, "Unknown", topology),
topology,
(ul & ASLA_FLAG_EXTERNAL) ? 2 : 1);
if ((ul & ASLA_MASK_METRIC) == 0xffffff)
ND_PRINT(" infinite");
else
ND_PRINT(" %u", (ul & ASLA_MASK_METRIC));
if (GET_IPV4_TO_NETWORK_ORDER(almp->asla_forward) != 0) {
ND_PRINT(", forward %s", GET_IPADDR_STRING(almp->asla_forward));
}
if (GET_IPV4_TO_NETWORK_ORDER(almp->asla_tag) != 0) {
ND_PRINT(", tag %s", GET_IPADDR_STRING(almp->asla_tag));
}
++almp;
}
break;
case LS_TYPE_GROUP:
/* Multicast extensions as of 23 July 1991 */
mcp = lsap->lsa_un.un_mcla;
while ((const u_char *)mcp < ls_end) {
switch (GET_BE_U_4(mcp->mcla_vtype)) {
case MCLA_VERTEX_ROUTER:
ND_PRINT("\n\t Router Router-ID %s",
GET_IPADDR_STRING(mcp->mcla_vid));
break;
case MCLA_VERTEX_NETWORK:
ND_PRINT("\n\t Network Designated Router %s",
GET_IPADDR_STRING(mcp->mcla_vid));
break;
default:
ND_PRINT("\n\t unknown VertexType (%u)",
GET_BE_U_4(mcp->mcla_vtype));
break;
}
++mcp;
}
break;
case LS_TYPE_OPAQUE_LL: /* fall through */
case LS_TYPE_OPAQUE_AL:
case LS_TYPE_OPAQUE_DW:
switch (GET_U_1(lsap->ls_hdr.un_lsa_id.opaque_field.opaque_type)) {
case LS_OPAQUE_TYPE_RI:
tptr = (const uint8_t *)(lsap->lsa_un.un_ri_tlv);
u_int ls_length_remaining = ls_length;
while (ls_length_remaining != 0) {
ND_TCHECK_4(tptr);
if (ls_length_remaining < 4) {
ND_PRINT("\n\t Remaining LS length %u < 4", ls_length_remaining);
return(ls_end);
}
tlv_type = GET_BE_U_2(tptr);
tlv_length = GET_BE_U_2(tptr + 2);
tptr+=4;
ls_length_remaining-=4;
ND_PRINT("\n\t %s TLV (%u), length: %u, value: ",
tok2str(lsa_opaque_ri_tlv_values,"unknown",tlv_type),
tlv_type,
tlv_length);
if (tlv_length > ls_length_remaining) {
ND_PRINT("\n\t Bogus length %u > remaining LS length %u", tlv_length,
ls_length_remaining);
return(ls_end);
}
ND_TCHECK_LEN(tptr, tlv_length);
switch(tlv_type) {
case LS_OPAQUE_RI_TLV_CAP:
if (tlv_length != 4) {
ND_PRINT("\n\t Bogus length %u != 4", tlv_length);
return(ls_end);
}
ND_PRINT("Capabilities: %s",
bittok2str(lsa_opaque_ri_tlv_cap_values, "Unknown", GET_BE_U_4(tptr)));
break;
default:
if (ndo->ndo_vflag <= 1) {
if (!print_unknown_data(ndo, tptr, "\n\t ", tlv_length))
return(ls_end);
}
break;
}
+
+ /* in OSPF everything has to be 32-bit aligned, including TLVs */
+ if (tlv_length % 4) {
+ tlv_length += (4 - (tlv_length % 4));
+ }
tptr+=tlv_length;
ls_length_remaining-=tlv_length;
}
break;
case LS_OPAQUE_TYPE_GRACE:
if (ospf_grace_lsa_print(ndo, (const u_char *)(lsap->lsa_un.un_grace_tlv),
ls_length) == -1) {
return(ls_end);
}
break;
case LS_OPAQUE_TYPE_TE:
if (ospf_te_lsa_print(ndo, (const u_char *)(lsap->lsa_un.un_te_lsa_tlv),
ls_length) == -1) {
return(ls_end);
}
break;
default:
if (ndo->ndo_vflag <= 1) {
if (!print_unknown_data(ndo, (const uint8_t *)lsap->lsa_un.un_unknown,
"\n\t ", ls_length))
return(ls_end);
}
break;
}
}
/* do we want to see an additionally hexdump ? */
if (ndo->ndo_vflag> 1)
if (!print_unknown_data(ndo, (const uint8_t *)lsap->lsa_un.un_unknown,
"\n\t ", ls_length)) {
return(ls_end);
}
return (ls_end);
trunc:
return (NULL);
}
static void
ospf_decode_lls(netdissect_options *ndo,
const struct ospfhdr *op, u_int length)
{
const u_char *dptr;
const u_char *dataend;
u_int length2;
uint16_t lls_type, lls_len;
uint32_t lls_flags;
switch (GET_U_1(op->ospf_type)) {
case OSPF_TYPE_HELLO:
if (!(GET_U_1(op->ospf_hello.hello_options) & OSPF_OPTION_L))
return;
break;
case OSPF_TYPE_DD:
if (!(GET_U_1(op->ospf_db.db_options) & OSPF_OPTION_L))
return;
break;
default:
return;
}
/* dig deeper if LLS data is available; see RFC4813 */
length2 = GET_BE_U_2(op->ospf_len);
dptr = (const u_char *)op + length2;
dataend = (const u_char *)op + length;
if (GET_BE_U_2(op->ospf_authtype) == OSPF_AUTH_MD5) {
dptr = dptr + GET_U_1(op->ospf_authdata + 3);
length2 += GET_U_1(op->ospf_authdata + 3);
}
if (length2 >= length) {
ND_PRINT("\n\t[LLS truncated]");
return;
}
ND_PRINT("\n\t LLS: checksum: 0x%04x", (u_int) GET_BE_U_2(dptr));
dptr += 2;
length2 = GET_BE_U_2(dptr);
ND_PRINT(", length: %u", length2);
dptr += 2;
while (dptr < dataend) {
lls_type = GET_BE_U_2(dptr);
ND_PRINT("\n\t %s (%u)",
tok2str(ospf_lls_tlv_values,"Unknown TLV",lls_type),
lls_type);
dptr += 2;
lls_len = GET_BE_U_2(dptr);
ND_PRINT(", length: %u", lls_len);
dptr += 2;
switch (lls_type) {
case OSPF_LLS_EO:
if (lls_len != 4) {
ND_PRINT(" [should be 4]");
lls_len = 4;
}
lls_flags = GET_BE_U_4(dptr);
ND_PRINT("\n\t Options: 0x%08x [%s]", lls_flags,
bittok2str(ospf_lls_eo_options, "?", lls_flags));
break;
case OSPF_LLS_MD5:
if (lls_len != 20) {
ND_PRINT(" [should be 20]");
lls_len = 20;
}
ND_PRINT("\n\t Sequence number: 0x%08x", GET_BE_U_4(dptr));
break;
}
dptr += lls_len;
}
}
static int
ospf_decode_v2(netdissect_options *ndo,
const struct ospfhdr *op, const u_char *dataend)
{
const nd_ipv4 *ap;
const struct lsr *lsrp;
const struct lsa_hdr *lshp;
const struct lsa *lsap;
uint32_t lsa_count,lsa_count_max;
switch (GET_U_1(op->ospf_type)) {
case OSPF_TYPE_HELLO:
ND_PRINT("\n\tOptions [%s]",
bittok2str(ospf_option_values,"none",GET_U_1(op->ospf_hello.hello_options)));
ND_PRINT("\n\t Hello Timer %us, Dead Timer %us, Mask %s, Priority %u",
GET_BE_U_2(op->ospf_hello.hello_helloint),
GET_BE_U_4(op->ospf_hello.hello_deadint),
GET_IPADDR_STRING(op->ospf_hello.hello_mask),
GET_U_1(op->ospf_hello.hello_priority));
if (GET_IPV4_TO_NETWORK_ORDER(op->ospf_hello.hello_dr) != 0)
ND_PRINT("\n\t Designated Router %s",
GET_IPADDR_STRING(op->ospf_hello.hello_dr));
if (GET_IPV4_TO_NETWORK_ORDER(op->ospf_hello.hello_bdr) != 0)
ND_PRINT(", Backup Designated Router %s",
GET_IPADDR_STRING(op->ospf_hello.hello_bdr));
ap = op->ospf_hello.hello_neighbor;
if ((const u_char *)ap < dataend)
ND_PRINT("\n\t Neighbor List:");
while ((const u_char *)ap < dataend) {
ND_PRINT("\n\t %s", GET_IPADDR_STRING(ap));
++ap;
}
break; /* HELLO */
case OSPF_TYPE_DD:
ND_PRINT("\n\tOptions [%s]",
bittok2str(ospf_option_values, "none", GET_U_1(op->ospf_db.db_options)));
ND_PRINT(", DD Flags [%s]",
bittok2str(ospf_dd_flag_values, "none", GET_U_1(op->ospf_db.db_flags)));
if (GET_BE_U_2(op->ospf_db.db_ifmtu)) {
ND_PRINT(", MTU: %u",
GET_BE_U_2(op->ospf_db.db_ifmtu));
}
ND_PRINT(", Sequence: 0x%08x", GET_BE_U_4(op->ospf_db.db_seq));
/* Print all the LS adv's */
lshp = op->ospf_db.db_lshdr;
while (((const u_char *)lshp < dataend) && ospf_print_lshdr(ndo, lshp) != -1) {
++lshp;
}
break;
case OSPF_TYPE_LS_REQ:
lsrp = op->ospf_lsr;
while ((const u_char *)lsrp < dataend) {
ND_TCHECK_SIZE(lsrp);
ND_PRINT("\n\t Advertising Router: %s, %s LSA (%u)",
GET_IPADDR_STRING(lsrp->ls_router),
tok2str(lsa_values,"unknown",GET_BE_U_4(lsrp->ls_type)),
GET_BE_U_4(lsrp->ls_type));
switch (GET_BE_U_4(lsrp->ls_type)) {
/* the LSA header for opaque LSAs was slightly changed */
case LS_TYPE_OPAQUE_LL:
case LS_TYPE_OPAQUE_AL:
case LS_TYPE_OPAQUE_DW:
ND_PRINT(", Opaque-Type: %s LSA (%u), Opaque-ID: %u",
tok2str(lsa_opaque_values, "unknown",GET_U_1(lsrp->un_ls_stateid.opaque_field.opaque_type)),
GET_U_1(lsrp->un_ls_stateid.opaque_field.opaque_type),
GET_BE_U_3(lsrp->un_ls_stateid.opaque_field.opaque_id));
break;
default:
ND_PRINT(", LSA-ID: %s",
GET_IPADDR_STRING(lsrp->un_ls_stateid.ls_stateid));
break;
}
++lsrp;
}
break;
case OSPF_TYPE_LS_UPDATE:
lsap = op->ospf_lsu.lsu_lsa;
lsa_count_max = GET_BE_U_4(op->ospf_lsu.lsu_count);
ND_PRINT(", %u LSA%s", lsa_count_max, PLURAL_SUFFIX(lsa_count_max));
for (lsa_count=1;lsa_count <= lsa_count_max;lsa_count++) {
ND_PRINT("\n\t LSA #%u", lsa_count);
lsap = (const struct lsa *)ospf_print_lsa(ndo, lsap);
if (lsap == NULL)
goto trunc;
}
break;
case OSPF_TYPE_LS_ACK:
lshp = op->ospf_lsa.lsa_lshdr;
- while (ospf_print_lshdr(ndo, lshp) != -1) {
+ while ((const u_char *)lshp < dataend) {
+ ospf_print_lshdr(ndo, lshp);
++lshp;
}
break;
default:
break;
}
return (0);
trunc:
return (1);
}
void
ospf_print(netdissect_options *ndo,
const u_char *bp, u_int length,
const u_char *bp2 _U_)
{
const struct ospfhdr *op;
const u_char *dataend;
const char *cp;
ndo->ndo_protocol = "ospf2";
op = (const struct ospfhdr *)bp;
/* XXX Before we do anything else, strip off the MD5 trailer */
if (GET_BE_U_2(op->ospf_authtype) == OSPF_AUTH_MD5) {
length -= OSPF_AUTH_MD5_LEN;
ndo->ndo_snapend -= OSPF_AUTH_MD5_LEN;
}
/* If the type is valid translate it, or just print the type */
/* value. If it's not valid, say so and return */
cp = tok2str(type2str, "unknown LS-type %u", GET_U_1(op->ospf_type));
ND_PRINT("OSPFv%u, %s, length %u", GET_U_1(op->ospf_version), cp,
length);
if (*cp == 'u')
return;
if (!ndo->ndo_vflag) { /* non verbose - so lets bail out here */
return;
}
if (length != GET_BE_U_2(op->ospf_len)) {
ND_PRINT(" [len %u]", GET_BE_U_2(op->ospf_len));
}
if (length > GET_BE_U_2(op->ospf_len)) {
dataend = bp + GET_BE_U_2(op->ospf_len);
} else {
dataend = bp + length;
}
ND_PRINT("\n\tRouter-ID %s", GET_IPADDR_STRING(op->ospf_routerid));
if (GET_IPV4_TO_NETWORK_ORDER(op->ospf_areaid) != 0)
ND_PRINT(", Area %s", GET_IPADDR_STRING(op->ospf_areaid));
else
ND_PRINT(", Backbone Area");
if (ndo->ndo_vflag) {
/* Print authentication data (should we really do this?) */
ND_TCHECK_LEN(op->ospf_authdata, sizeof(op->ospf_authdata));
ND_PRINT(", Authentication Type: %s (%u)",
tok2str(ospf_authtype_values, "unknown", GET_BE_U_2(op->ospf_authtype)),
GET_BE_U_2(op->ospf_authtype));
switch (GET_BE_U_2(op->ospf_authtype)) {
case OSPF_AUTH_NONE:
break;
case OSPF_AUTH_SIMPLE:
ND_PRINT("\n\tSimple text password: ");
nd_printjnp(ndo, op->ospf_authdata, OSPF_AUTH_SIMPLE_LEN);
break;
case OSPF_AUTH_MD5:
ND_PRINT("\n\tKey-ID: %u, Auth-Length: %u, Crypto Sequence Number: 0x%08x",
GET_U_1(op->ospf_authdata + 2),
GET_U_1(op->ospf_authdata + 3),
GET_BE_U_4((op->ospf_authdata) + 4));
break;
default:
return;
}
}
/* Do rest according to version. */
switch (GET_U_1(op->ospf_version)) {
case 2:
/* ospf version 2 */
if (ospf_decode_v2(ndo, op, dataend))
goto trunc;
if (length > GET_BE_U_2(op->ospf_len))
ospf_decode_lls(ndo, op, length);
break;
default:
ND_PRINT(" ospf [version %u]", GET_U_1(op->ospf_version));
break;
} /* end switch on version */
return;
trunc:
nd_trunc_longjmp(ndo);
}
diff --git a/contrib/tcpdump/print-ospf6.c b/contrib/tcpdump/print-ospf6.c
index 49167954e20c..3a227c3e12c2 100644
--- a/contrib/tcpdump/print-ospf6.c
+++ b/contrib/tcpdump/print-ospf6.c
@@ -1,1002 +1,1009 @@
/*
* Copyright (c) 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.
*
* OSPF support contributed by Jeffrey Honig (jch@mitchell.cit.cornell.edu)
*/
/* \summary: IPv6 Open Shortest Path First (OSPFv3) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <string.h>
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#include "ospf.h"
#define OSPF_TYPE_HELLO 1 /* Hello */
#define OSPF_TYPE_DD 2 /* Database Description */
#define OSPF_TYPE_LS_REQ 3 /* Link State Request */
#define OSPF_TYPE_LS_UPDATE 4 /* Link State Update */
#define OSPF_TYPE_LS_ACK 5 /* Link State Ack */
/* Options *_options */
#define OSPF6_OPTION_V6 0x01 /* V6 bit: A bit for peeping tom */
#define OSPF6_OPTION_E 0x02 /* E bit: External routes advertised */
#define OSPF6_OPTION_MC 0x04 /* MC bit: Multicast capable */
#define OSPF6_OPTION_N 0x08 /* N bit: For type-7 LSA */
#define OSPF6_OPTION_R 0x10 /* R bit: Router bit */
#define OSPF6_OPTION_DC 0x20 /* DC bit: Demand circuits */
/* The field is actually 24-bit (RFC5340 Section A.2). */
#define OSPF6_OPTION_AF 0x0100 /* AF bit: Multiple address families */
#define OSPF6_OPTION_L 0x0200 /* L bit: Link-local signaling (LLS) */
#define OSPF6_OPTION_AT 0x0400 /* AT bit: Authentication trailer */
/* db_flags */
#define OSPF6_DB_INIT 0x04 /* */
#define OSPF6_DB_MORE 0x02
#define OSPF6_DB_MASTER 0x01
#define OSPF6_DB_M6 0x10 /* IPv6 MTU */
/* ls_type */
#define LS_TYPE_ROUTER 1 /* router link */
#define LS_TYPE_NETWORK 2 /* network link */
#define LS_TYPE_INTER_AP 3 /* Inter-Area-Prefix */
#define LS_TYPE_INTER_AR 4 /* Inter-Area-Router */
#define LS_TYPE_ASE 5 /* ASE */
#define LS_TYPE_GROUP 6 /* Group membership */
#define LS_TYPE_NSSA 7 /* NSSA */
#define LS_TYPE_LINK 8 /* Link LSA */
#define LS_TYPE_INTRA_AP 9 /* Intra-Area-Prefix */
#define LS_TYPE_INTRA_ATE 10 /* Intra-Area-TE */
#define LS_TYPE_GRACE 11 /* Grace LSA */
#define LS_TYPE_RI 12 /* Router information */
#define LS_TYPE_INTER_ASTE 13 /* Inter-AS-TE */
#define LS_TYPE_L1VPN 14 /* L1VPN */
#define LS_TYPE_MASK 0x1fff
#define LS_SCOPE_LINKLOCAL 0x0000
#define LS_SCOPE_AREA 0x2000
#define LS_SCOPE_AS 0x4000
#define LS_SCOPE_MASK 0x6000
#define LS_SCOPE_U 0x8000
/* rla_link.link_type */
#define RLA_TYPE_ROUTER 1 /* point-to-point to another router */
#define RLA_TYPE_TRANSIT 2 /* connection to transit network */
#define RLA_TYPE_VIRTUAL 4 /* virtual link */
/* rla_flags */
#define RLA_FLAG_B 0x01
#define RLA_FLAG_E 0x02
#define RLA_FLAG_V 0x04
#define RLA_FLAG_W 0x08
#define RLA_FLAG_Nt 0x10
/* lsa_prefix options */
#define LSA_PREFIX_OPT_NU 0x01
#define LSA_PREFIX_OPT_LA 0x02
#define LSA_PREFIX_OPT_MC 0x04
#define LSA_PREFIX_OPT_P 0x08
#define LSA_PREFIX_OPT_DN 0x10
#define LSA_PREFIX_OPT_N 0x20
/* sla_tosmetric breakdown */
#define SLA_MASK_TOS 0x7f000000
#define SLA_MASK_METRIC 0x00ffffff
#define SLA_SHIFT_TOS 24
/* asla_metric */
#define ASLA_FLAG_FWDADDR 0x02000000
#define ASLA_FLAG_ROUTETAG 0x01000000
#define ASLA_MASK_METRIC 0x00ffffff
/* RFC6506 Section 4.1 */
#define OSPF6_AT_HDRLEN 16U
#define OSPF6_AUTH_TYPE_HMAC 0x0001
typedef nd_uint32_t rtrid_t;
/* link state advertisement header */
struct lsa6_hdr {
nd_uint16_t ls_age;
nd_uint16_t ls_type;
rtrid_t ls_stateid;
rtrid_t ls_router;
nd_uint32_t ls_seq;
nd_uint16_t ls_chksum;
nd_uint16_t ls_length;
};
/* Length of an IPv6 address, in bytes. */
#define IPV6_ADDR_LEN_BYTES (128/8)
struct lsa6_prefix {
nd_uint8_t lsa_p_len;
nd_uint8_t lsa_p_opt;
nd_uint16_t lsa_p_metric;
nd_byte lsa_p_prefix[IPV6_ADDR_LEN_BYTES]; /* maximum length */
};
/* link state advertisement */
struct lsa6 {
struct lsa6_hdr ls_hdr;
/* Link state types */
union {
/* Router links advertisements */
struct {
union {
nd_uint8_t flg;
nd_uint32_t opt;
} rla_flgandopt;
#define rla_flags rla_flgandopt.flg
#define rla_options rla_flgandopt.opt
struct rlalink6 {
nd_uint8_t link_type;
nd_byte link_zero;
nd_uint16_t link_metric;
nd_uint32_t link_ifid;
nd_uint32_t link_nifid;
rtrid_t link_nrtid;
} rla_link[1]; /* may repeat */
} un_rla;
/* Network links advertisements */
struct {
nd_uint32_t nla_options;
rtrid_t nla_router[1]; /* may repeat */
} un_nla;
/* Inter Area Prefix LSA */
struct {
nd_uint32_t inter_ap_metric;
struct lsa6_prefix inter_ap_prefix[1];
} un_inter_ap;
/* AS external links advertisements */
struct {
nd_uint32_t asla_metric;
struct lsa6_prefix asla_prefix[1];
/* some optional fields follow */
} un_asla;
#if 0
/* Summary links advertisements */
struct {
nd_ipv4 sla_mask;
nd_uint32_t sla_tosmetric[1]; /* may repeat */
} un_sla;
/* Multicast group membership */
struct mcla {
nd_uint32_t mcla_vtype;
nd_ipv4 mcla_vid;
} un_mcla[1];
#endif
/* Type 7 LSA */
/* Link LSA */
struct llsa {
union {
nd_uint8_t pri;
nd_uint32_t opt;
} llsa_priandopt;
#define llsa_priority llsa_priandopt.pri
#define llsa_options llsa_priandopt.opt
nd_ipv6 llsa_lladdr;
nd_uint32_t llsa_nprefix;
struct lsa6_prefix llsa_prefix[1];
} un_llsa;
/* Intra-Area-Prefix */
struct {
nd_uint16_t intra_ap_nprefix;
nd_uint16_t intra_ap_lstype;
rtrid_t intra_ap_lsid;
rtrid_t intra_ap_rtid;
struct lsa6_prefix intra_ap_prefix[1];
} un_intra_ap;
} lsa_un;
};
/*
* the main header
*/
struct ospf6hdr {
nd_uint8_t ospf6_version;
nd_uint8_t ospf6_type;
nd_uint16_t ospf6_len;
rtrid_t ospf6_routerid;
rtrid_t ospf6_areaid;
nd_uint16_t ospf6_chksum;
nd_uint8_t ospf6_instanceid;
nd_uint8_t ospf6_rsvd;
};
/*
* The OSPF6 header length is 16 bytes, regardless of how your compiler
* might choose to pad the above structure.
*/
#define OSPF6HDR_LEN 16
/* Hello packet */
struct hello6 {
nd_uint32_t hello_ifid;
union {
nd_uint8_t pri;
nd_uint32_t opt;
} hello_priandopt;
#define hello_priority hello_priandopt.pri
#define hello_options hello_priandopt.opt
nd_uint16_t hello_helloint;
nd_uint16_t hello_deadint;
rtrid_t hello_dr;
rtrid_t hello_bdr;
rtrid_t hello_neighbor[1]; /* may repeat */
};
/* Database Description packet */
struct dd6 {
nd_uint32_t db_options;
nd_uint16_t db_mtu;
nd_uint8_t db_mbz;
nd_uint8_t db_flags;
nd_uint32_t db_seq;
struct lsa6_hdr db_lshdr[1]; /* may repeat */
};
/* Link State Request */
struct lsr6 {
nd_uint16_t ls_mbz;
nd_uint16_t ls_type;
rtrid_t ls_stateid;
rtrid_t ls_router;
};
/* Link State Update */
struct lsu6 {
nd_uint32_t lsu_count;
struct lsa6 lsu_lsa[1]; /* may repeat */
};
static const struct tok ospf6_option_values[] = {
{ OSPF6_OPTION_V6, "V6" },
{ OSPF6_OPTION_E, "External" },
{ OSPF6_OPTION_MC, "Deprecated" },
{ OSPF6_OPTION_N, "NSSA" },
{ OSPF6_OPTION_R, "Router" },
{ OSPF6_OPTION_DC, "Demand Circuit" },
{ OSPF6_OPTION_AF, "AFs Support" },
{ OSPF6_OPTION_L, "LLS" },
{ OSPF6_OPTION_AT, "Authentication Trailer" },
{ 0, NULL }
};
static const struct tok ospf6_rla_flag_values[] = {
{ RLA_FLAG_B, "ABR" },
{ RLA_FLAG_E, "External" },
{ RLA_FLAG_V, "Virtual-Link Endpoint" },
{ RLA_FLAG_W, "Deprecated" },
{ RLA_FLAG_Nt, "NSSA Translator" },
{ 0, NULL }
};
static const struct tok ospf6_asla_flag_values[] = {
{ ASLA_FLAG_EXTERNAL, "External Type 2" },
{ ASLA_FLAG_FWDADDR, "Forwarding" },
{ ASLA_FLAG_ROUTETAG, "Tag" },
{ 0, NULL }
};
static const struct tok ospf6_type_values[] = {
{ OSPF_TYPE_HELLO, "Hello" },
{ OSPF_TYPE_DD, "Database Description" },
{ OSPF_TYPE_LS_REQ, "LS-Request" },
{ OSPF_TYPE_LS_UPDATE, "LS-Update" },
{ OSPF_TYPE_LS_ACK, "LS-Ack" },
{ 0, NULL }
};
static const struct tok ospf6_lsa_values[] = {
{ LS_TYPE_ROUTER, "Router" },
{ LS_TYPE_NETWORK, "Network" },
{ LS_TYPE_INTER_AP, "Inter-Area Prefix" },
{ LS_TYPE_INTER_AR, "Inter-Area Router" },
{ LS_TYPE_ASE, "External" },
{ LS_TYPE_GROUP, "Deprecated" },
{ LS_TYPE_NSSA, "NSSA" },
{ LS_TYPE_LINK, "Link" },
{ LS_TYPE_INTRA_AP, "Intra-Area Prefix" },
{ LS_TYPE_INTRA_ATE, "Intra-Area TE" },
{ LS_TYPE_GRACE, "Grace" },
{ LS_TYPE_RI, "Router Information" },
{ LS_TYPE_INTER_ASTE, "Inter-AS-TE" },
{ LS_TYPE_L1VPN, "Layer 1 VPN" },
{ 0, NULL }
};
static const struct tok ospf6_ls_scope_values[] = {
{ LS_SCOPE_LINKLOCAL, "Link Local" },
{ LS_SCOPE_AREA, "Area Local" },
{ LS_SCOPE_AS, "Domain Wide" },
{ 0, NULL }
};
static const struct tok ospf6_dd_flag_values[] = {
{ OSPF6_DB_INIT, "Init" },
{ OSPF6_DB_MORE, "More" },
{ OSPF6_DB_MASTER, "Master" },
{ OSPF6_DB_M6, "IPv6 MTU" },
{ 0, NULL }
};
static const struct tok ospf6_lsa_prefix_option_values[] = {
{ LSA_PREFIX_OPT_NU, "No Unicast" },
{ LSA_PREFIX_OPT_LA, "Local address" },
{ LSA_PREFIX_OPT_MC, "Deprecated" },
{ LSA_PREFIX_OPT_P, "Propagate" },
{ LSA_PREFIX_OPT_DN, "Down" },
{ LSA_PREFIX_OPT_N, "N-bit" },
{ 0, NULL }
};
static const struct tok ospf6_auth_type_str[] = {
{ OSPF6_AUTH_TYPE_HMAC, "HMAC" },
{ 0, NULL }
};
static void
ospf6_print_ls_type(netdissect_options *ndo,
u_int ls_type, const rtrid_t *ls_stateid)
{
ND_PRINT("\n\t %s LSA (%u), %s Scope%s, LSA-ID %s",
tok2str(ospf6_lsa_values, "Unknown", ls_type & LS_TYPE_MASK),
ls_type & LS_TYPE_MASK,
tok2str(ospf6_ls_scope_values, "Unknown", ls_type & LS_SCOPE_MASK),
ls_type &0x8000 ? ", transitive" : "", /* U-bit */
GET_IPADDR_STRING(ls_stateid));
}
static int
ospf6_print_lshdr(netdissect_options *ndo,
const struct lsa6_hdr *lshp, const u_char *dataend)
{
+ u_int ls_length;
+
if ((const u_char *)(lshp + 1) > dataend)
goto trunc;
+ ls_length = GET_BE_U_2(lshp->ls_length);
+ if (ls_length < sizeof(struct lsa_hdr)) {
+ ND_PRINT("\n\t Bogus length %u < header (%zu)", ls_length,
+ sizeof(struct lsa_hdr));
+ goto trunc;
+ }
+
ND_PRINT("\n\t Advertising Router %s, seq 0x%08x, age %us, length %zu",
GET_IPADDR_STRING(lshp->ls_router),
GET_BE_U_4(lshp->ls_seq),
GET_BE_U_2(lshp->ls_age),
- GET_BE_U_2(lshp->ls_length)-sizeof(struct lsa6_hdr));
+ ls_length-sizeof(struct lsa6_hdr));
ospf6_print_ls_type(ndo, GET_BE_U_2(lshp->ls_type),
&lshp->ls_stateid);
return (0);
trunc:
return (1);
}
static int
ospf6_print_lsaprefix(netdissect_options *ndo,
const uint8_t *tptr, u_int lsa_length)
{
const struct lsa6_prefix *lsapp = (const struct lsa6_prefix *)tptr;
u_int wordlen;
nd_ipv6 prefix;
if (lsa_length < sizeof (*lsapp) - IPV6_ADDR_LEN_BYTES)
goto trunc;
lsa_length -= sizeof (*lsapp) - IPV6_ADDR_LEN_BYTES;
ND_TCHECK_LEN(lsapp, sizeof(*lsapp) - IPV6_ADDR_LEN_BYTES);
wordlen = (GET_U_1(lsapp->lsa_p_len) + 31) / 32;
if (wordlen * 4 > sizeof(nd_ipv6)) {
ND_PRINT(" bogus prefixlen /%u", GET_U_1(lsapp->lsa_p_len));
goto trunc;
}
if (lsa_length < wordlen * 4)
goto trunc;
lsa_length -= wordlen * 4;
memset(prefix, 0, sizeof(prefix));
GET_CPY_BYTES(prefix, lsapp->lsa_p_prefix, wordlen * 4);
ND_PRINT("\n\t\t%s/%u", ip6addr_string(ndo, prefix), /* local buffer, not packet data; don't use GET_IP6ADDR_STRING() */
GET_U_1(lsapp->lsa_p_len));
if (GET_U_1(lsapp->lsa_p_opt)) {
ND_PRINT(", Options [%s]",
bittok2str(ospf6_lsa_prefix_option_values,
"none", GET_U_1(lsapp->lsa_p_opt)));
}
ND_PRINT(", metric %u", GET_BE_U_2(lsapp->lsa_p_metric));
return sizeof(*lsapp) - IPV6_ADDR_LEN_BYTES + wordlen * 4;
trunc:
return -1;
}
/*
* Print a single link state advertisement. If truncated return 1, else 0.
*/
static int
ospf6_print_lsa(netdissect_options *ndo,
const struct lsa6 *lsap, const u_char *dataend)
{
const struct rlalink6 *rlp;
#if 0
const struct tos_metric *tosp;
#endif
const rtrid_t *ap;
#if 0
const struct aslametric *almp;
const struct mcla *mcp;
#endif
const struct llsa *llsap;
const struct lsa6_prefix *lsapp;
#if 0
const uint32_t *lp;
#endif
u_int prefixes;
int bytelen;
u_int length, lsa_length;
uint32_t flags32;
const uint8_t *tptr;
if (ospf6_print_lshdr(ndo, &lsap->ls_hdr, dataend))
return (1);
length = GET_BE_U_2(lsap->ls_hdr.ls_length);
/*
* The LSA length includes the length of the header;
* it must have a value that's at least that length.
* If it does, find the length of what follows the
* header.
*/
if (length < sizeof(struct lsa6_hdr) || (const u_char *)lsap + length > dataend)
return (1);
lsa_length = length - sizeof(struct lsa6_hdr);
tptr = (const uint8_t *)lsap+sizeof(struct lsa6_hdr);
switch (GET_BE_U_2(lsap->ls_hdr.ls_type)) {
case LS_TYPE_ROUTER | LS_SCOPE_AREA:
if (lsa_length < sizeof (lsap->lsa_un.un_rla.rla_options))
return (1);
lsa_length -= sizeof (lsap->lsa_un.un_rla.rla_options);
ND_PRINT("\n\t Options [%s]",
bittok2str(ospf6_option_values, "none",
GET_BE_U_4(lsap->lsa_un.un_rla.rla_options)));
ND_PRINT(", RLA-Flags [%s]",
bittok2str(ospf6_rla_flag_values, "none",
GET_U_1(lsap->lsa_un.un_rla.rla_flags)));
rlp = lsap->lsa_un.un_rla.rla_link;
while (lsa_length != 0) {
if (lsa_length < sizeof (*rlp))
return (1);
lsa_length -= sizeof (*rlp);
ND_TCHECK_SIZE(rlp);
switch (GET_U_1(rlp->link_type)) {
case RLA_TYPE_VIRTUAL:
ND_PRINT("\n\t Virtual Link: Neighbor Router-ID %s"
"\n\t Neighbor Interface-ID %s, Interface %s",
GET_IPADDR_STRING(rlp->link_nrtid),
GET_IPADDR_STRING(rlp->link_nifid),
GET_IPADDR_STRING(rlp->link_ifid));
break;
case RLA_TYPE_ROUTER:
ND_PRINT("\n\t Neighbor Router-ID %s"
"\n\t Neighbor Interface-ID %s, Interface %s",
GET_IPADDR_STRING(rlp->link_nrtid),
GET_IPADDR_STRING(rlp->link_nifid),
GET_IPADDR_STRING(rlp->link_ifid));
break;
case RLA_TYPE_TRANSIT:
ND_PRINT("\n\t Neighbor Network-ID %s"
"\n\t Neighbor Interface-ID %s, Interface %s",
GET_IPADDR_STRING(rlp->link_nrtid),
GET_IPADDR_STRING(rlp->link_nifid),
GET_IPADDR_STRING(rlp->link_ifid));
break;
default:
ND_PRINT("\n\t Unknown Router Links Type 0x%02x",
GET_U_1(rlp->link_type));
return (0);
}
ND_PRINT(", metric %u", GET_BE_U_2(rlp->link_metric));
rlp++;
}
break;
case LS_TYPE_NETWORK | LS_SCOPE_AREA:
if (lsa_length < sizeof (lsap->lsa_un.un_nla.nla_options))
return (1);
lsa_length -= sizeof (lsap->lsa_un.un_nla.nla_options);
ND_PRINT("\n\t Options [%s]",
bittok2str(ospf6_option_values, "none",
GET_BE_U_4(lsap->lsa_un.un_nla.nla_options)));
ND_PRINT("\n\t Connected Routers:");
ap = lsap->lsa_un.un_nla.nla_router;
while (lsa_length != 0) {
if (lsa_length < sizeof (*ap))
return (1);
lsa_length -= sizeof (*ap);
ND_PRINT("\n\t\t%s", GET_IPADDR_STRING(ap));
++ap;
}
break;
case LS_TYPE_INTER_AP | LS_SCOPE_AREA:
if (lsa_length < sizeof (lsap->lsa_un.un_inter_ap.inter_ap_metric))
return (1);
lsa_length -= sizeof (lsap->lsa_un.un_inter_ap.inter_ap_metric);
ND_PRINT(", metric %u",
GET_BE_U_4(lsap->lsa_un.un_inter_ap.inter_ap_metric) & SLA_MASK_METRIC);
tptr = (const uint8_t *)lsap->lsa_un.un_inter_ap.inter_ap_prefix;
while (lsa_length != 0) {
bytelen = ospf6_print_lsaprefix(ndo, tptr, lsa_length);
if (bytelen < 0)
goto trunc;
/*
* ospf6_print_lsaprefix() will return -1 if
* the length is too high, so this will not
* underflow.
*/
lsa_length -= bytelen;
tptr += bytelen;
}
break;
case LS_TYPE_ASE | LS_SCOPE_AS:
if (lsa_length < sizeof (lsap->lsa_un.un_asla.asla_metric))
return (1);
lsa_length -= sizeof (lsap->lsa_un.un_asla.asla_metric);
flags32 = GET_BE_U_4(lsap->lsa_un.un_asla.asla_metric);
ND_PRINT("\n\t Flags [%s]",
bittok2str(ospf6_asla_flag_values, "none", flags32));
ND_PRINT(" metric %u",
GET_BE_U_4(lsap->lsa_un.un_asla.asla_metric) &
ASLA_MASK_METRIC);
tptr = (const uint8_t *)lsap->lsa_un.un_asla.asla_prefix;
lsapp = (const struct lsa6_prefix *)tptr;
bytelen = ospf6_print_lsaprefix(ndo, tptr, lsa_length);
if (bytelen < 0)
goto trunc;
/*
* ospf6_print_lsaprefix() will return -1 if
* the length is too high, so this will not
* underflow.
*/
lsa_length -= bytelen;
tptr += bytelen;
if ((flags32 & ASLA_FLAG_FWDADDR) != 0) {
if (lsa_length < sizeof (nd_ipv6))
return (1);
lsa_length -= sizeof (nd_ipv6);
ND_PRINT(" forward %s",
GET_IP6ADDR_STRING(tptr));
tptr += sizeof(nd_ipv6);
}
if ((flags32 & ASLA_FLAG_ROUTETAG) != 0) {
if (lsa_length < sizeof (uint32_t))
return (1);
lsa_length -= sizeof (uint32_t);
ND_PRINT(" tag %s",
GET_IPADDR_STRING(tptr));
tptr += sizeof(uint32_t);
}
if (GET_U_1(lsapp->lsa_p_metric)) {
if (lsa_length < sizeof (uint32_t))
return (1);
lsa_length -= sizeof (uint32_t);
ND_PRINT(" RefLSID: %s",
GET_IPADDR_STRING(tptr));
tptr += sizeof(uint32_t);
}
break;
case LS_TYPE_LINK:
/* Link LSA */
llsap = &lsap->lsa_un.un_llsa;
if (lsa_length < sizeof (llsap->llsa_priandopt))
return (1);
lsa_length -= sizeof (llsap->llsa_priandopt);
ND_TCHECK_SIZE(&llsap->llsa_priandopt);
ND_PRINT("\n\t Options [%s]",
bittok2str(ospf6_option_values, "none",
GET_BE_U_4(llsap->llsa_options)));
if (lsa_length < sizeof (llsap->llsa_lladdr) + sizeof (llsap->llsa_nprefix))
return (1);
lsa_length -= sizeof (llsap->llsa_lladdr) + sizeof (llsap->llsa_nprefix);
prefixes = GET_BE_U_4(llsap->llsa_nprefix);
ND_PRINT("\n\t Priority %u, Link-local address %s, Prefixes %u:",
GET_U_1(llsap->llsa_priority),
GET_IP6ADDR_STRING(llsap->llsa_lladdr),
prefixes);
tptr = (const uint8_t *)llsap->llsa_prefix;
while (prefixes > 0) {
bytelen = ospf6_print_lsaprefix(ndo, tptr, lsa_length);
if (bytelen < 0)
goto trunc;
prefixes--;
/*
* ospf6_print_lsaprefix() will return -1 if
* the length is too high, so this will not
* underflow.
*/
lsa_length -= bytelen;
tptr += bytelen;
}
break;
case LS_TYPE_INTRA_AP | LS_SCOPE_AREA:
/* Intra-Area-Prefix LSA */
if (lsa_length < sizeof (lsap->lsa_un.un_intra_ap.intra_ap_rtid))
return (1);
lsa_length -= sizeof (lsap->lsa_un.un_intra_ap.intra_ap_rtid);
ND_TCHECK_4(lsap->lsa_un.un_intra_ap.intra_ap_rtid);
ospf6_print_ls_type(ndo,
GET_BE_U_2(lsap->lsa_un.un_intra_ap.intra_ap_lstype),
&lsap->lsa_un.un_intra_ap.intra_ap_lsid);
if (lsa_length < sizeof (lsap->lsa_un.un_intra_ap.intra_ap_nprefix))
return (1);
lsa_length -= sizeof (lsap->lsa_un.un_intra_ap.intra_ap_nprefix);
prefixes = GET_BE_U_2(lsap->lsa_un.un_intra_ap.intra_ap_nprefix);
ND_PRINT("\n\t Prefixes %u:", prefixes);
tptr = (const uint8_t *)lsap->lsa_un.un_intra_ap.intra_ap_prefix;
while (prefixes > 0) {
bytelen = ospf6_print_lsaprefix(ndo, tptr, lsa_length);
if (bytelen < 0)
goto trunc;
prefixes--;
/*
* ospf6_print_lsaprefix() will return -1 if
* the length is too high, so this will not
* underflow.
*/
lsa_length -= bytelen;
tptr += bytelen;
}
break;
case LS_TYPE_GRACE | LS_SCOPE_LINKLOCAL:
if (ospf_grace_lsa_print(ndo, tptr, lsa_length) == -1) {
return 1;
}
break;
case LS_TYPE_INTRA_ATE | LS_SCOPE_LINKLOCAL:
if (ospf_te_lsa_print(ndo, tptr, lsa_length) == -1) {
return 1;
}
break;
default:
if(!print_unknown_data(ndo,tptr,
"\n\t ",
lsa_length)) {
return (1);
}
break;
}
return (0);
trunc:
return (1);
}
static int
ospf6_decode_v3(netdissect_options *ndo,
const struct ospf6hdr *op,
const u_char *dataend)
{
const rtrid_t *ap;
const struct lsr6 *lsrp;
const struct lsa6_hdr *lshp;
const struct lsa6 *lsap;
- int i;
+ uint32_t i;
switch (GET_U_1(op->ospf6_type)) {
case OSPF_TYPE_HELLO: {
const struct hello6 *hellop = (const struct hello6 *)((const uint8_t *)op + OSPF6HDR_LEN);
ND_PRINT("\n\tOptions [%s]",
bittok2str(ospf6_option_values, "none",
GET_BE_U_4(hellop->hello_options)));
ND_PRINT("\n\t Hello Timer %us, Dead Timer %us, Interface-ID %s, Priority %u",
GET_BE_U_2(hellop->hello_helloint),
GET_BE_U_2(hellop->hello_deadint),
GET_IPADDR_STRING(hellop->hello_ifid),
GET_U_1(hellop->hello_priority));
if (GET_BE_U_4(hellop->hello_dr) != 0)
ND_PRINT("\n\t Designated Router %s",
GET_IPADDR_STRING(hellop->hello_dr));
if (GET_BE_U_4(hellop->hello_bdr) != 0)
ND_PRINT(", Backup Designated Router %s",
GET_IPADDR_STRING(hellop->hello_bdr));
if (ndo->ndo_vflag > 1) {
ND_PRINT("\n\t Neighbor List:");
ap = hellop->hello_neighbor;
while ((const u_char *)ap < dataend) {
ND_PRINT("\n\t %s", GET_IPADDR_STRING(ap));
++ap;
}
}
break; /* HELLO */
}
case OSPF_TYPE_DD: {
const struct dd6 *ddp = (const struct dd6 *)((const uint8_t *)op + OSPF6HDR_LEN);
ND_PRINT("\n\tOptions [%s]",
bittok2str(ospf6_option_values, "none",
GET_BE_U_4(ddp->db_options)));
ND_PRINT(", DD Flags [%s]",
bittok2str(ospf6_dd_flag_values,"none",GET_U_1(ddp->db_flags)));
ND_PRINT(", MTU %u, DD-Sequence 0x%08x",
GET_BE_U_2(ddp->db_mtu),
GET_BE_U_4(ddp->db_seq));
if (ndo->ndo_vflag > 1) {
/* Print all the LS adv's */
lshp = ddp->db_lshdr;
while ((const u_char *)lshp < dataend) {
if (ospf6_print_lshdr(ndo, lshp++, dataend))
goto trunc;
}
}
break;
}
case OSPF_TYPE_LS_REQ:
if (ndo->ndo_vflag > 1) {
lsrp = (const struct lsr6 *)((const uint8_t *)op + OSPF6HDR_LEN);
while ((const u_char *)lsrp < dataend) {
ND_TCHECK_SIZE(lsrp);
ND_PRINT("\n\t Advertising Router %s",
GET_IPADDR_STRING(lsrp->ls_router));
ospf6_print_ls_type(ndo,
GET_BE_U_2(lsrp->ls_type),
&lsrp->ls_stateid);
++lsrp;
}
}
break;
case OSPF_TYPE_LS_UPDATE:
if (ndo->ndo_vflag > 1) {
const struct lsu6 *lsup = (const struct lsu6 *)((const uint8_t *)op + OSPF6HDR_LEN);
i = GET_BE_U_4(lsup->lsu_count);
lsap = lsup->lsu_lsa;
while ((const u_char *)lsap < dataend && i--) {
if (ospf6_print_lsa(ndo, lsap, dataend))
goto trunc;
lsap = (const struct lsa6 *)((const u_char *)lsap +
GET_BE_U_2(lsap->ls_hdr.ls_length));
}
}
break;
case OSPF_TYPE_LS_ACK:
if (ndo->ndo_vflag > 1) {
lshp = (const struct lsa6_hdr *)((const uint8_t *)op + OSPF6HDR_LEN);
while ((const u_char *)lshp < dataend) {
if (ospf6_print_lshdr(ndo, lshp++, dataend))
goto trunc;
}
}
break;
default:
break;
}
return (0);
trunc:
return (1);
}
/* RFC5613 Section 2.2 (w/o the TLVs) */
static int
ospf6_print_lls(netdissect_options *ndo,
const u_char *cp, const u_int len)
{
uint16_t llsdatalen;
if (len == 0)
return 0;
if (len < OSPF_LLS_HDRLEN)
goto trunc;
/* Checksum */
ND_PRINT("\n\tLLS Checksum 0x%04x", GET_BE_U_2(cp));
cp += 2;
/* LLS Data Length */
llsdatalen = GET_BE_U_2(cp);
ND_PRINT(", Data Length %u", llsdatalen);
if (llsdatalen < OSPF_LLS_HDRLEN || llsdatalen > len)
goto trunc;
cp += 2;
/* LLS TLVs */
ND_TCHECK_LEN(cp, llsdatalen - OSPF_LLS_HDRLEN);
/* FIXME: code in print-ospf.c can be reused to decode the TLVs */
return llsdatalen;
trunc:
return -1;
}
/* RFC6506 Section 4.1 */
static int
ospf6_decode_at(netdissect_options *ndo,
const u_char *cp, const u_int len)
{
uint16_t authdatalen;
if (len == 0)
return 0;
if (len < OSPF6_AT_HDRLEN)
goto trunc;
/* Authentication Type */
ND_PRINT("\n\tAuthentication Type %s",
tok2str(ospf6_auth_type_str, "unknown (0x%04x)", GET_BE_U_2(cp)));
cp += 2;
/* Auth Data Len */
authdatalen = GET_BE_U_2(cp);
ND_PRINT(", Length %u", authdatalen);
if (authdatalen < OSPF6_AT_HDRLEN || authdatalen > len)
goto trunc;
cp += 2;
/* Reserved */
cp += 2;
/* Security Association ID */
ND_PRINT(", SAID %u", GET_BE_U_2(cp));
cp += 2;
/* Cryptographic Sequence Number (High-Order 32 Bits) */
ND_PRINT(", CSN 0x%08x", GET_BE_U_4(cp));
cp += 4;
/* Cryptographic Sequence Number (Low-Order 32 Bits) */
ND_PRINT(":%08x", GET_BE_U_4(cp));
cp += 4;
/* Authentication Data */
ND_TCHECK_LEN(cp, authdatalen - OSPF6_AT_HDRLEN);
if (ndo->ndo_vflag > 1)
print_unknown_data(ndo,cp, "\n\tAuthentication Data ", authdatalen - OSPF6_AT_HDRLEN);
return 0;
trunc:
return 1;
}
/* The trailing data may include LLS and/or AT data (in this specific order).
* LLS data may be present only in Hello and DBDesc packets with the L-bit set.
* AT data may be present in Hello and DBDesc packets with the AT-bit set or in
* any other packet type, thus decode the AT data regardless of the AT-bit.
*/
static int
ospf6_decode_v3_trailer(netdissect_options *ndo,
const struct ospf6hdr *op, const u_char *cp, const unsigned len)
{
uint8_t type;
int llslen = 0;
int lls_hello = 0;
int lls_dd = 0;
type = GET_U_1(op->ospf6_type);
if (type == OSPF_TYPE_HELLO) {
const struct hello6 *hellop = (const struct hello6 *)((const uint8_t *)op + OSPF6HDR_LEN);
if (GET_BE_U_4(hellop->hello_options) & OSPF6_OPTION_L)
lls_hello = 1;
} else if (type == OSPF_TYPE_DD) {
const struct dd6 *ddp = (const struct dd6 *)((const uint8_t *)op + OSPF6HDR_LEN);
if (GET_BE_U_4(ddp->db_options) & OSPF6_OPTION_L)
lls_dd = 1;
}
if ((lls_hello || lls_dd) && (llslen = ospf6_print_lls(ndo, cp, len)) < 0)
goto trunc;
return ospf6_decode_at(ndo, cp + llslen, len - llslen);
trunc:
return 1;
}
void
ospf6_print(netdissect_options *ndo,
const u_char *bp, u_int length)
{
const struct ospf6hdr *op;
const u_char *dataend;
const char *cp;
uint16_t datalen;
ndo->ndo_protocol = "ospf3";
op = (const struct ospf6hdr *)bp;
/* If the type is valid translate it, or just print the type */
/* value. If it's not valid, say so and return */
cp = tok2str(ospf6_type_values, "unknown packet type (%u)",
GET_U_1(op->ospf6_type));
ND_PRINT("OSPFv%u, %s, length %u", GET_U_1(op->ospf6_version), cp,
length);
if (*cp == 'u') {
return;
}
if(!ndo->ndo_vflag) { /* non verbose - so lets bail out here */
return;
}
/* OSPFv3 data always comes first and optional trailing data may follow. */
datalen = GET_BE_U_2(op->ospf6_len);
if (datalen > length) {
ND_PRINT(" [len %u]", datalen);
return;
}
dataend = bp + datalen;
ND_PRINT("\n\tRouter-ID %s", GET_IPADDR_STRING(op->ospf6_routerid));
if (GET_BE_U_4(op->ospf6_areaid) != 0)
ND_PRINT(", Area %s", GET_IPADDR_STRING(op->ospf6_areaid));
else
ND_PRINT(", Backbone Area");
if (GET_U_1(op->ospf6_instanceid))
ND_PRINT(", Instance %u", GET_U_1(op->ospf6_instanceid));
/* Do rest according to version. */
switch (GET_U_1(op->ospf6_version)) {
case 3:
/* ospf version 3 */
if (ospf6_decode_v3(ndo, op, dataend) ||
ospf6_decode_v3_trailer(ndo, op, dataend, length - datalen))
goto trunc;
break;
} /* end switch on version */
return;
trunc:
nd_print_trunc(ndo);
}
diff --git a/contrib/tcpdump/print-otv.c b/contrib/tcpdump/print-otv.c
index a0fe9d0eb5b3..1303740009a0 100644
--- a/contrib/tcpdump/print-otv.c
+++ b/contrib/tcpdump/print-otv.c
@@ -1,76 +1,74 @@
/*
* 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.
*
* Original code by Francesco Fondelli (francesco dot fondelli, gmail dot com)
*/
/* \summary: Overlay Transport Virtualization (OTV) printer */
/* specification: draft-hasmit-otv-04 */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
#define OTV_HDR_LEN 8
/*
* OTV header, draft-hasmit-otv-04
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |R|R|R|R|I|R|R|R| Overlay ID |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Instance ID | Reserved |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
void
otv_print(netdissect_options *ndo, const u_char *bp, u_int len)
{
uint8_t flags;
ndo->ndo_protocol = "otv";
ND_PRINT("OTV, ");
if (len < OTV_HDR_LEN) {
ND_PRINT("[length %u < %u]", len, OTV_HDR_LEN);
goto invalid;
}
flags = GET_U_1(bp);
ND_PRINT("flags [%s] (0x%02x), ", flags & 0x08 ? "I" : ".", flags);
bp += 1;
ND_PRINT("overlay %u, ", GET_BE_U_3(bp));
bp += 3;
ND_PRINT("instance %u\n", GET_BE_U_3(bp));
bp += 3;
/* Reserved */
ND_TCHECK_1(bp);
bp += 1;
ether_print(ndo, bp, len - OTV_HDR_LEN, ND_BYTES_AVAILABLE_AFTER(bp), NULL, NULL);
return;
invalid:
nd_print_invalid(ndo);
ND_TCHECK_LEN(bp, len);
}
diff --git a/contrib/tcpdump/print-pflog.c b/contrib/tcpdump/print-pflog.c
index 23956524cbaf..71bf01f07555 100644
--- a/contrib/tcpdump/print-pflog.c
+++ b/contrib/tcpdump/print-pflog.c
@@ -1,216 +1,214 @@
/*
* Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996
* 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.
*/
/* \summary: *BSD/Darwin packet filter log file printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "extract.h"
#include "af.h"
#include "pflog.h"
static const struct tok pf_reasons[] = {
{ PFRES_MATCH, "0(match)" },
{ PFRES_BADOFF, "1(bad-offset)" },
{ PFRES_FRAG, "2(fragment)" },
- { PFRES_NORM, "3(short)" },
+ { PFRES_SHORT, "3(short)" },
{ PFRES_NORM, "4(normalize)" },
{ PFRES_MEMORY, "5(memory)" },
{ PFRES_TS, "6(bad-timestamp)" },
{ PFRES_CONGEST, "7(congestion)" },
{ PFRES_IPOPTIONS, "8(ip-option)" },
{ PFRES_PROTCKSUM, "9(proto-cksum)" },
{ PFRES_BADSTATE, "10(state-mismatch)" },
{ PFRES_STATEINS, "11(state-insert)" },
{ PFRES_MAXSTATES, "12(state-limit)" },
{ PFRES_SRCLIMIT, "13(src-limit)" },
{ PFRES_SYNPROXY, "14(synproxy)" },
#if defined(__FreeBSD__)
{ PFRES_MAPFAILED, "15(map-failed)" },
#elif defined(__NetBSD__)
{ PFRES_STATELOCKED, "15(state-locked)" },
#elif defined(__OpenBSD__)
{ PFRES_TRANSLATE, "15(translate)" },
{ PFRES_NOROUTE, "16(no-route)" },
#elif defined(__APPLE__)
{ PFRES_DUMMYNET, "15(dummynet)" },
#endif
{ 0, NULL }
};
static const struct tok pf_actions[] = {
{ PF_PASS, "pass" },
{ PF_DROP, "block" },
{ PF_SCRUB, "scrub" },
{ PF_NOSCRUB, "scrub" },
{ PF_NAT, "nat" },
{ PF_NONAT, "nonat" },
{ PF_BINAT, "binat" },
{ PF_NOBINAT, "nobinat" },
{ PF_RDR, "rdr" },
{ PF_NORDR, "nordr" },
{ PF_SYNPROXY_DROP, "synproxy-drop" },
#if defined(__FreeBSD__)
{ PF_DEFER, "defer" },
{ PF_MATCH, "match" },
#elif defined(__OpenBSD__)
{ PF_DEFER, "defer" },
{ PF_MATCH, "match" },
{ PF_DIVERT, "divert" },
{ PF_RT, "rt" },
{ PF_AFRT, "afrt" },
#elif defined(__APPLE__)
{ PF_DUMMYNET, "dummynet" },
{ PF_NODUMMYNET, "nodummynet" },
{ PF_NAT64, "nat64" },
{ PF_NONAT64, "nonat64" },
#endif
{ 0, NULL }
};
static const struct tok pf_directions[] = {
{ PF_INOUT, "in/out" },
{ PF_IN, "in" },
{ PF_OUT, "out" },
#if defined(__OpenBSD__)
{ PF_FWD, "fwd" },
#endif
{ 0, NULL }
};
static void
pflog_print(netdissect_options *ndo, const struct pfloghdr *hdr)
{
uint32_t rulenr, subrulenr, ridentifier;
ndo->ndo_protocol = "pflog";
- rulenr = GET_BE_U_4(&hdr->rulenr);
- subrulenr = GET_BE_U_4(&hdr->subrulenr);
- ridentifier = GET_BE_U_4(&hdr->ridentifier);
+ rulenr = GET_BE_U_4(hdr->rulenr);
+ subrulenr = GET_BE_U_4(hdr->subrulenr);
+ ridentifier = GET_BE_U_4(hdr->ridentifier);
if (subrulenr == (uint32_t)-1)
ND_PRINT("rule %u/", rulenr);
else {
ND_PRINT("rule %u.", rulenr);
nd_printjnp(ndo, (const u_char*)hdr->ruleset, PFLOG_RULESET_NAME_SIZE);
ND_PRINT(".%u/", subrulenr);
}
- ND_PRINT("%s", tok2str(pf_reasons, "unkn(%u)", hdr->reason));
+ ND_PRINT("%s", tok2str(pf_reasons, "unkn(%u)", GET_U_1(hdr->reason)));
- if (hdr->uid != UID_MAX)
- ND_PRINT(" [uid %u]", (unsigned)hdr->uid);
+ if (GET_HE_U_4(hdr->uid) != UID_MAX)
+ ND_PRINT(" [uid %u]", GET_HE_U_4(hdr->uid));
if (ridentifier != 0)
ND_PRINT(" [ridentifier %u]", ridentifier);
ND_PRINT(": %s %s on ",
- tok2str(pf_actions, "unkn(%u)", GET_U_1(&hdr->action)),
- tok2str(pf_directions, "unkn(%u)", GET_U_1(&hdr->dir)));
+ tok2str(pf_actions, "unkn(%u)", GET_U_1(hdr->action)),
+ tok2str(pf_directions, "unkn(%u)", GET_U_1(hdr->dir)));
nd_printjnp(ndo, (const u_char*)hdr->ifname, PFLOG_IFNAMSIZ);
ND_PRINT(": ");
}
void
pflog_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h,
const u_char *p)
{
u_int length = h->len;
u_int hdrlen;
u_int caplen = h->caplen;
const struct pfloghdr *hdr;
uint8_t af;
ndo->ndo_protocol = "pflog";
/* check length */
if (caplen < sizeof(uint8_t)) {
nd_print_trunc(ndo);
ndo->ndo_ll_hdr_len += h->caplen;
return;
}
-#define MIN_PFLOG_HDRLEN 45
hdr = (const struct pfloghdr *)p;
- if (GET_U_1(&hdr->length) < MIN_PFLOG_HDRLEN) {
+ hdrlen = GET_U_1(hdr->length);
+ if (hdrlen < MIN_PFLOG_HDRLEN) {
ND_PRINT("[pflog: invalid header length!]");
- ndo->ndo_ll_hdr_len += GET_U_1(&hdr->length); /* XXX: not really */
+ ndo->ndo_ll_hdr_len += hdrlen; /* XXX: not really */
return;
}
- hdrlen = roundup2(hdr->length, 4);
+ hdrlen = roundup2(hdrlen, 4);
if (caplen < hdrlen) {
nd_print_trunc(ndo);
ndo->ndo_ll_hdr_len += hdrlen; /* XXX: true? */
return;
}
/* print what we know */
ND_TCHECK_SIZE(hdr);
if (ndo->ndo_eflag)
pflog_print(ndo, hdr);
/* skip to the real packet */
- af = GET_U_1(&hdr->af);
+ af = GET_U_1(hdr->af);
length -= hdrlen;
caplen -= hdrlen;
p += hdrlen;
switch (af) {
/*
* If there's a system that doesn't use the AF_INET
* from 4.2BSD, feel free to add its value to af.h
* and use it here.
*
* Hopefully, there isn't.
*/
case BSD_AFNUM_INET:
ip_print(ndo, p, length);
break;
/*
* Try all AF_INET6 values for all systems with pflog,
* including Darwin.
*/
case BSD_AFNUM_INET6_BSD:
case BSD_AFNUM_INET6_FREEBSD:
case BSD_AFNUM_INET6_DARWIN:
ip6_print(ndo, p, length);
break;
default:
/* address family not handled, print raw packet */
if (!ndo->ndo_eflag)
pflog_print(ndo, hdr);
if (!ndo->ndo_suppress_default_print)
ND_DEFAULTPRINT(p, caplen);
}
ndo->ndo_ll_hdr_len += hdrlen;
return;
trunc:
nd_print_trunc(ndo);
ndo->ndo_ll_hdr_len += hdrlen;
}
diff --git a/contrib/tcpdump/print-pgm.c b/contrib/tcpdump/print-pgm.c
index ccb0b46afef9..6cffb52eabe6 100644
--- a/contrib/tcpdump/print-pgm.c
+++ b/contrib/tcpdump/print-pgm.c
@@ -1,829 +1,827 @@
/*
* 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.
*
* Original code by Andy Heffernan (ahh@juniper.net)
*/
/* \summary: Pragmatic General Multicast (PGM) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "extract.h"
#include "addrtoname.h"
#include "addrtostr.h"
#include "ip.h"
#include "ip6.h"
#include "ipproto.h"
#include "af.h"
/*
* PGM header (RFC 3208)
*/
struct pgm_header {
nd_uint16_t pgm_sport;
nd_uint16_t pgm_dport;
nd_uint8_t pgm_type;
nd_uint8_t pgm_options;
nd_uint16_t pgm_sum;
nd_byte pgm_gsid[6];
nd_uint16_t pgm_length;
};
struct pgm_spm {
nd_uint32_t pgms_seq;
nd_uint32_t pgms_trailseq;
nd_uint32_t pgms_leadseq;
nd_uint16_t pgms_nla_afi;
nd_uint16_t pgms_reserved;
/* ... uint8_t pgms_nla[0]; */
/* ... options */
};
struct pgm_nak {
nd_uint32_t pgmn_seq;
nd_uint16_t pgmn_source_afi;
nd_uint16_t pgmn_reserved;
/* ... uint8_t pgmn_source[0]; */
/* ... uint16_t pgmn_group_afi */
/* ... uint16_t pgmn_reserved2; */
/* ... uint8_t pgmn_group[0]; */
/* ... options */
};
struct pgm_ack {
nd_uint32_t pgma_rx_max_seq;
nd_uint32_t pgma_bitmap;
/* ... options */
};
struct pgm_poll {
nd_uint32_t pgmp_seq;
nd_uint16_t pgmp_round;
nd_uint16_t pgmp_subtype;
nd_uint16_t pgmp_nla_afi;
nd_uint16_t pgmp_reserved;
/* ... uint8_t pgmp_nla[0]; */
/* ... options */
};
struct pgm_polr {
nd_uint32_t pgmp_seq;
nd_uint16_t pgmp_round;
nd_uint16_t pgmp_reserved;
/* ... options */
};
struct pgm_data {
nd_uint32_t pgmd_seq;
nd_uint32_t pgmd_trailseq;
/* ... options */
};
typedef enum _pgm_type {
PGM_SPM = 0, /* source path message */
PGM_POLL = 1, /* POLL Request */
PGM_POLR = 2, /* POLL Response */
PGM_ODATA = 4, /* original data */
PGM_RDATA = 5, /* repair data */
PGM_NAK = 8, /* NAK */
PGM_NULLNAK = 9, /* Null NAK */
PGM_NCF = 10, /* NAK Confirmation */
PGM_ACK = 11, /* ACK for congestion control */
PGM_SPMR = 12, /* SPM request */
PGM_MAX = 255
} pgm_type;
#define PGM_OPT_BIT_PRESENT 0x01
#define PGM_OPT_BIT_NETWORK 0x02
#define PGM_OPT_BIT_VAR_PKTLEN 0x40
#define PGM_OPT_BIT_PARITY 0x80
#define PGM_OPT_LENGTH 0x00
#define PGM_OPT_FRAGMENT 0x01
#define PGM_OPT_NAK_LIST 0x02
#define PGM_OPT_JOIN 0x03
#define PGM_OPT_NAK_BO_IVL 0x04
#define PGM_OPT_NAK_BO_RNG 0x05
#define PGM_OPT_REDIRECT 0x07
#define PGM_OPT_PARITY_PRM 0x08
#define PGM_OPT_PARITY_GRP 0x09
#define PGM_OPT_CURR_TGSIZE 0x0A
#define PGM_OPT_NBR_UNREACH 0x0B
#define PGM_OPT_PATH_NLA 0x0C
#define PGM_OPT_SYN 0x0D
#define PGM_OPT_FIN 0x0E
#define PGM_OPT_RST 0x0F
#define PGM_OPT_CR 0x10
#define PGM_OPT_CRQST 0x11
#define PGM_OPT_PGMCC_DATA 0x12
#define PGM_OPT_PGMCC_FEEDBACK 0x13
#define PGM_OPT_MASK 0x7f
#define PGM_OPT_END 0x80 /* end of options marker */
#define PGM_MIN_OPT_LEN 4
void
pgm_print(netdissect_options *ndo,
const u_char *bp, u_int length,
const u_char *bp2)
{
const struct pgm_header *pgm;
const struct ip *ip;
uint8_t pgm_type_val;
uint16_t sport, dport;
u_int nla_afnum;
char nla_buf[INET6_ADDRSTRLEN];
const struct ip6_hdr *ip6;
uint8_t opt_type, opt_len;
uint32_t seq, opts_len, len, offset;
ndo->ndo_protocol = "pgm";
pgm = (const struct pgm_header *)bp;
ip = (const struct ip *)bp2;
if (IP_V(ip) == 6)
ip6 = (const struct ip6_hdr *)bp2;
else
ip6 = NULL;
if (!ND_TTEST_2(pgm->pgm_dport)) {
if (ip6) {
ND_PRINT("%s > %s:",
GET_IP6ADDR_STRING(ip6->ip6_src),
GET_IP6ADDR_STRING(ip6->ip6_dst));
} else {
ND_PRINT("%s > %s:",
GET_IPADDR_STRING(ip->ip_src),
GET_IPADDR_STRING(ip->ip_dst));
}
nd_print_trunc(ndo);
return;
}
sport = GET_BE_U_2(pgm->pgm_sport);
dport = GET_BE_U_2(pgm->pgm_dport);
if (ip6) {
if (GET_U_1(ip6->ip6_nxt) == IPPROTO_PGM) {
ND_PRINT("%s.%s > %s.%s: ",
GET_IP6ADDR_STRING(ip6->ip6_src),
tcpport_string(ndo, sport),
GET_IP6ADDR_STRING(ip6->ip6_dst),
tcpport_string(ndo, dport));
} else {
ND_PRINT("%s > %s: ",
tcpport_string(ndo, sport), tcpport_string(ndo, dport));
}
} else {
if (GET_U_1(ip->ip_p) == IPPROTO_PGM) {
ND_PRINT("%s.%s > %s.%s: ",
GET_IPADDR_STRING(ip->ip_src),
tcpport_string(ndo, sport),
GET_IPADDR_STRING(ip->ip_dst),
tcpport_string(ndo, dport));
} else {
ND_PRINT("%s > %s: ",
tcpport_string(ndo, sport), tcpport_string(ndo, dport));
}
}
ND_TCHECK_SIZE(pgm);
ND_PRINT("PGM, length %u", GET_BE_U_2(pgm->pgm_length));
if (!ndo->ndo_vflag)
return;
pgm_type_val = GET_U_1(pgm->pgm_type);
ND_PRINT(" 0x%02x%02x%02x%02x%02x%02x ",
pgm->pgm_gsid[0],
pgm->pgm_gsid[1],
pgm->pgm_gsid[2],
pgm->pgm_gsid[3],
pgm->pgm_gsid[4],
pgm->pgm_gsid[5]);
switch (pgm_type_val) {
case PGM_SPM: {
const struct pgm_spm *spm;
spm = (const struct pgm_spm *)(pgm + 1);
ND_TCHECK_SIZE(spm);
bp = (const u_char *) (spm + 1);
switch (GET_BE_U_2(spm->pgms_nla_afi)) {
case AFNUM_INET:
ND_TCHECK_LEN(bp, sizeof(nd_ipv4));
addrtostr(bp, nla_buf, sizeof(nla_buf));
bp += sizeof(nd_ipv4);
break;
case AFNUM_INET6:
ND_TCHECK_LEN(bp, sizeof(nd_ipv6));
addrtostr6(bp, nla_buf, sizeof(nla_buf));
bp += sizeof(nd_ipv6);
break;
default:
goto trunc;
break;
}
ND_PRINT("SPM seq %u trail %u lead %u nla %s",
GET_BE_U_4(spm->pgms_seq),
GET_BE_U_4(spm->pgms_trailseq),
GET_BE_U_4(spm->pgms_leadseq),
nla_buf);
break;
}
case PGM_POLL: {
const struct pgm_poll *pgm_poll;
uint32_t ivl, rnd, mask;
pgm_poll = (const struct pgm_poll *)(pgm + 1);
ND_TCHECK_SIZE(pgm_poll);
bp = (const u_char *) (pgm_poll + 1);
switch (GET_BE_U_2(pgm_poll->pgmp_nla_afi)) {
case AFNUM_INET:
ND_TCHECK_LEN(bp, sizeof(nd_ipv4));
addrtostr(bp, nla_buf, sizeof(nla_buf));
bp += sizeof(nd_ipv4);
break;
case AFNUM_INET6:
ND_TCHECK_LEN(bp, sizeof(nd_ipv6));
addrtostr6(bp, nla_buf, sizeof(nla_buf));
bp += sizeof(nd_ipv6);
break;
default:
goto trunc;
break;
}
ivl = GET_BE_U_4(bp);
bp += sizeof(uint32_t);
rnd = GET_BE_U_4(bp);
bp += sizeof(uint32_t);
mask = GET_BE_U_4(bp);
bp += sizeof(uint32_t);
ND_PRINT("POLL seq %u round %u nla %s ivl %u rnd 0x%08x "
"mask 0x%08x", GET_BE_U_4(pgm_poll->pgmp_seq),
GET_BE_U_2(pgm_poll->pgmp_round), nla_buf, ivl, rnd,
mask);
break;
}
case PGM_POLR: {
const struct pgm_polr *polr_msg;
polr_msg = (const struct pgm_polr *)(pgm + 1);
ND_TCHECK_SIZE(polr_msg);
ND_PRINT("POLR seq %u round %u",
GET_BE_U_4(polr_msg->pgmp_seq),
GET_BE_U_2(polr_msg->pgmp_round));
bp = (const u_char *) (polr_msg + 1);
break;
}
case PGM_ODATA: {
const struct pgm_data *odata;
odata = (const struct pgm_data *)(pgm + 1);
ND_TCHECK_SIZE(odata);
ND_PRINT("ODATA trail %u seq %u",
GET_BE_U_4(odata->pgmd_trailseq),
GET_BE_U_4(odata->pgmd_seq));
bp = (const u_char *) (odata + 1);
break;
}
case PGM_RDATA: {
const struct pgm_data *rdata;
rdata = (const struct pgm_data *)(pgm + 1);
ND_TCHECK_SIZE(rdata);
ND_PRINT("RDATA trail %u seq %u",
GET_BE_U_4(rdata->pgmd_trailseq),
GET_BE_U_4(rdata->pgmd_seq));
bp = (const u_char *) (rdata + 1);
break;
}
case PGM_NAK:
case PGM_NULLNAK:
case PGM_NCF: {
const struct pgm_nak *nak;
char source_buf[INET6_ADDRSTRLEN], group_buf[INET6_ADDRSTRLEN];
nak = (const struct pgm_nak *)(pgm + 1);
ND_TCHECK_SIZE(nak);
bp = (const u_char *) (nak + 1);
/*
* Skip past the source, saving info along the way
* and stopping if we don't have enough.
*/
switch (GET_BE_U_2(nak->pgmn_source_afi)) {
case AFNUM_INET:
ND_TCHECK_LEN(bp, sizeof(nd_ipv4));
addrtostr(bp, source_buf, sizeof(source_buf));
bp += sizeof(nd_ipv4);
break;
case AFNUM_INET6:
ND_TCHECK_LEN(bp, sizeof(nd_ipv6));
addrtostr6(bp, source_buf, sizeof(source_buf));
bp += sizeof(nd_ipv6);
break;
default:
goto trunc;
break;
}
/*
* Skip past the group, saving info along the way
* and stopping if we don't have enough.
*/
bp += (2 * sizeof(uint16_t));
switch (GET_BE_U_2(bp)) {
case AFNUM_INET:
ND_TCHECK_LEN(bp, sizeof(nd_ipv4));
addrtostr(bp, group_buf, sizeof(group_buf));
bp += sizeof(nd_ipv4);
break;
case AFNUM_INET6:
ND_TCHECK_LEN(bp, sizeof(nd_ipv6));
addrtostr6(bp, group_buf, sizeof(group_buf));
bp += sizeof(nd_ipv6);
break;
default:
goto trunc;
break;
}
/*
* Options decoding can go here.
*/
switch (pgm_type_val) {
case PGM_NAK:
ND_PRINT("NAK ");
break;
case PGM_NULLNAK:
ND_PRINT("NNAK ");
break;
case PGM_NCF:
ND_PRINT("NCF ");
break;
default:
break;
}
ND_PRINT("(%s -> %s), seq %u",
source_buf, group_buf, GET_BE_U_4(nak->pgmn_seq));
break;
}
case PGM_ACK: {
const struct pgm_ack *ack;
ack = (const struct pgm_ack *)(pgm + 1);
ND_TCHECK_SIZE(ack);
ND_PRINT("ACK seq %u",
GET_BE_U_4(ack->pgma_rx_max_seq));
bp = (const u_char *) (ack + 1);
break;
}
case PGM_SPMR:
ND_PRINT("SPMR");
break;
default:
ND_PRINT("UNKNOWN type 0x%02x", pgm_type_val);
break;
}
if (GET_U_1(pgm->pgm_options) & PGM_OPT_BIT_PRESENT) {
/*
* make sure there's enough for the first option header
*/
ND_TCHECK_LEN(bp, PGM_MIN_OPT_LEN);
/*
* That option header MUST be an OPT_LENGTH option
* (see the first paragraph of section 9.1 in RFC 3208).
*/
opt_type = GET_U_1(bp);
bp++;
if ((opt_type & PGM_OPT_MASK) != PGM_OPT_LENGTH) {
ND_PRINT("[First option bad, should be PGM_OPT_LENGTH, is %u]", opt_type & PGM_OPT_MASK);
return;
}
opt_len = GET_U_1(bp);
bp++;
if (opt_len != 4) {
ND_PRINT("[Bad OPT_LENGTH option, length %u != 4]", opt_len);
return;
}
opts_len = GET_BE_U_2(bp);
bp += sizeof(uint16_t);
if (opts_len < 4) {
ND_PRINT("[Bad total option length %u < 4]", opts_len);
return;
}
ND_PRINT(" OPTS LEN %u", opts_len);
opts_len -= 4;
while (opts_len) {
if (opts_len < PGM_MIN_OPT_LEN) {
ND_PRINT("[Total option length leaves no room for final option]");
return;
}
opt_type = GET_U_1(bp);
bp++;
opt_len = GET_U_1(bp);
bp++;
if (opt_len < PGM_MIN_OPT_LEN) {
ND_PRINT("[Bad option, length %u < %u]", opt_len,
PGM_MIN_OPT_LEN);
break;
}
if (opts_len < opt_len) {
ND_PRINT("[Total option length leaves no room for final option]");
return;
}
ND_TCHECK_LEN(bp, opt_len - 2);
switch (opt_type & PGM_OPT_MASK) {
case PGM_OPT_LENGTH:
#define PGM_OPT_LENGTH_LEN (2+2)
if (opt_len != PGM_OPT_LENGTH_LEN) {
ND_PRINT("[Bad OPT_LENGTH option, length %u != %u]",
opt_len, PGM_OPT_LENGTH_LEN);
return;
}
ND_PRINT(" OPTS LEN (extra?) %u", GET_BE_U_2(bp));
bp += 2;
opts_len -= PGM_OPT_LENGTH_LEN;
break;
case PGM_OPT_FRAGMENT:
#define PGM_OPT_FRAGMENT_LEN (2+2+4+4+4)
if (opt_len != PGM_OPT_FRAGMENT_LEN) {
ND_PRINT("[Bad OPT_FRAGMENT option, length %u != %u]",
opt_len, PGM_OPT_FRAGMENT_LEN);
return;
}
bp += 2;
seq = GET_BE_U_4(bp);
bp += 4;
offset = GET_BE_U_4(bp);
bp += 4;
len = GET_BE_U_4(bp);
bp += 4;
ND_PRINT(" FRAG seq %u off %u len %u", seq, offset, len);
opts_len -= PGM_OPT_FRAGMENT_LEN;
break;
case PGM_OPT_NAK_LIST:
bp += 2;
opt_len -= 4; /* option header */
ND_PRINT(" NAK LIST");
while (opt_len) {
if (opt_len < 4) {
ND_PRINT("[Option length not a multiple of 4]");
return;
}
ND_PRINT(" %u", GET_BE_U_4(bp));
bp += 4;
opt_len -= 4;
opts_len -= 4;
}
break;
case PGM_OPT_JOIN:
#define PGM_OPT_JOIN_LEN (2+2+4)
if (opt_len != PGM_OPT_JOIN_LEN) {
ND_PRINT("[Bad OPT_JOIN option, length %u != %u]",
opt_len, PGM_OPT_JOIN_LEN);
return;
}
bp += 2;
seq = GET_BE_U_4(bp);
bp += 4;
ND_PRINT(" JOIN %u", seq);
opts_len -= PGM_OPT_JOIN_LEN;
break;
case PGM_OPT_NAK_BO_IVL:
#define PGM_OPT_NAK_BO_IVL_LEN (2+2+4+4)
if (opt_len != PGM_OPT_NAK_BO_IVL_LEN) {
ND_PRINT("[Bad OPT_NAK_BO_IVL option, length %u != %u]",
opt_len, PGM_OPT_NAK_BO_IVL_LEN);
return;
}
bp += 2;
offset = GET_BE_U_4(bp);
bp += 4;
seq = GET_BE_U_4(bp);
bp += 4;
ND_PRINT(" BACKOFF ivl %u ivlseq %u", offset, seq);
opts_len -= PGM_OPT_NAK_BO_IVL_LEN;
break;
case PGM_OPT_NAK_BO_RNG:
#define PGM_OPT_NAK_BO_RNG_LEN (2+2+4+4)
if (opt_len != PGM_OPT_NAK_BO_RNG_LEN) {
ND_PRINT("[Bad OPT_NAK_BO_RNG option, length %u != %u]",
opt_len, PGM_OPT_NAK_BO_RNG_LEN);
return;
}
bp += 2;
offset = GET_BE_U_4(bp);
bp += 4;
seq = GET_BE_U_4(bp);
bp += 4;
ND_PRINT(" BACKOFF max %u min %u", offset, seq);
opts_len -= PGM_OPT_NAK_BO_RNG_LEN;
break;
case PGM_OPT_REDIRECT:
#define PGM_OPT_REDIRECT_FIXED_LEN (2+2+2+2)
if (opt_len < PGM_OPT_REDIRECT_FIXED_LEN) {
ND_PRINT("[Bad OPT_REDIRECT option, length %u < %u]",
opt_len, PGM_OPT_REDIRECT_FIXED_LEN);
return;
}
bp += 2;
nla_afnum = GET_BE_U_2(bp);
bp += 2+2;
switch (nla_afnum) {
case AFNUM_INET:
if (opt_len != PGM_OPT_REDIRECT_FIXED_LEN + sizeof(nd_ipv4)) {
ND_PRINT("[Bad OPT_REDIRECT option, length %u != %u + address size]",
opt_len, PGM_OPT_REDIRECT_FIXED_LEN);
return;
}
ND_TCHECK_LEN(bp, sizeof(nd_ipv4));
addrtostr(bp, nla_buf, sizeof(nla_buf));
bp += sizeof(nd_ipv4);
opts_len -= PGM_OPT_REDIRECT_FIXED_LEN + sizeof(nd_ipv4);
break;
case AFNUM_INET6:
if (opt_len != PGM_OPT_REDIRECT_FIXED_LEN + sizeof(nd_ipv6)) {
ND_PRINT("[Bad OPT_REDIRECT option, length %u != %u + address size]",
opt_len, PGM_OPT_REDIRECT_FIXED_LEN);
return;
}
ND_TCHECK_LEN(bp, sizeof(nd_ipv6));
addrtostr6(bp, nla_buf, sizeof(nla_buf));
bp += sizeof(nd_ipv6);
opts_len -= PGM_OPT_REDIRECT_FIXED_LEN + sizeof(nd_ipv6);
break;
default:
goto trunc;
break;
}
ND_PRINT(" REDIRECT %s", nla_buf);
break;
case PGM_OPT_PARITY_PRM:
#define PGM_OPT_PARITY_PRM_LEN (2+2+4)
if (opt_len != PGM_OPT_PARITY_PRM_LEN) {
ND_PRINT("[Bad OPT_PARITY_PRM option, length %u != %u]",
opt_len, PGM_OPT_PARITY_PRM_LEN);
return;
}
bp += 2;
len = GET_BE_U_4(bp);
bp += 4;
ND_PRINT(" PARITY MAXTGS %u", len);
opts_len -= PGM_OPT_PARITY_PRM_LEN;
break;
case PGM_OPT_PARITY_GRP:
#define PGM_OPT_PARITY_GRP_LEN (2+2+4)
if (opt_len != PGM_OPT_PARITY_GRP_LEN) {
ND_PRINT("[Bad OPT_PARITY_GRP option, length %u != %u]",
opt_len, PGM_OPT_PARITY_GRP_LEN);
return;
}
bp += 2;
seq = GET_BE_U_4(bp);
bp += 4;
ND_PRINT(" PARITY GROUP %u", seq);
opts_len -= PGM_OPT_PARITY_GRP_LEN;
break;
case PGM_OPT_CURR_TGSIZE:
#define PGM_OPT_CURR_TGSIZE_LEN (2+2+4)
if (opt_len != PGM_OPT_CURR_TGSIZE_LEN) {
ND_PRINT("[Bad OPT_CURR_TGSIZE option, length %u != %u]",
opt_len, PGM_OPT_CURR_TGSIZE_LEN);
return;
}
bp += 2;
len = GET_BE_U_4(bp);
bp += 4;
ND_PRINT(" PARITY ATGS %u", len);
opts_len -= PGM_OPT_CURR_TGSIZE_LEN;
break;
case PGM_OPT_NBR_UNREACH:
#define PGM_OPT_NBR_UNREACH_LEN (2+2)
if (opt_len != PGM_OPT_NBR_UNREACH_LEN) {
ND_PRINT("[Bad OPT_NBR_UNREACH option, length %u != %u]",
opt_len, PGM_OPT_NBR_UNREACH_LEN);
return;
}
bp += 2;
ND_PRINT(" NBR_UNREACH");
opts_len -= PGM_OPT_NBR_UNREACH_LEN;
break;
case PGM_OPT_PATH_NLA:
ND_PRINT(" PATH_NLA [%u]", opt_len);
bp += opt_len;
opts_len -= opt_len;
break;
case PGM_OPT_SYN:
#define PGM_OPT_SYN_LEN (2+2)
if (opt_len != PGM_OPT_SYN_LEN) {
ND_PRINT("[Bad OPT_SYN option, length %u != %u]",
opt_len, PGM_OPT_SYN_LEN);
return;
}
bp += 2;
ND_PRINT(" SYN");
opts_len -= PGM_OPT_SYN_LEN;
break;
case PGM_OPT_FIN:
#define PGM_OPT_FIN_LEN (2+2)
if (opt_len != PGM_OPT_FIN_LEN) {
ND_PRINT("[Bad OPT_FIN option, length %u != %u]",
opt_len, PGM_OPT_FIN_LEN);
return;
}
bp += 2;
ND_PRINT(" FIN");
opts_len -= PGM_OPT_FIN_LEN;
break;
case PGM_OPT_RST:
#define PGM_OPT_RST_LEN (2+2)
if (opt_len != PGM_OPT_RST_LEN) {
ND_PRINT("[Bad OPT_RST option, length %u != %u]",
opt_len, PGM_OPT_RST_LEN);
return;
}
bp += 2;
ND_PRINT(" RST");
opts_len -= PGM_OPT_RST_LEN;
break;
case PGM_OPT_CR:
ND_PRINT(" CR");
bp += opt_len;
opts_len -= opt_len;
break;
case PGM_OPT_CRQST:
#define PGM_OPT_CRQST_LEN (2+2)
if (opt_len != PGM_OPT_CRQST_LEN) {
ND_PRINT("[Bad OPT_CRQST option, length %u != %u]",
opt_len, PGM_OPT_CRQST_LEN);
return;
}
bp += 2;
ND_PRINT(" CRQST");
opts_len -= PGM_OPT_CRQST_LEN;
break;
case PGM_OPT_PGMCC_DATA:
#define PGM_OPT_PGMCC_DATA_FIXED_LEN (2+2+4+2+2)
if (opt_len < PGM_OPT_PGMCC_DATA_FIXED_LEN) {
ND_PRINT("[Bad OPT_PGMCC_DATA option, length %u < %u]",
opt_len, PGM_OPT_PGMCC_DATA_FIXED_LEN);
return;
}
bp += 2;
offset = GET_BE_U_4(bp);
bp += 4;
nla_afnum = GET_BE_U_2(bp);
bp += 2+2;
switch (nla_afnum) {
case AFNUM_INET:
if (opt_len != PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(nd_ipv4)) {
ND_PRINT("[Bad OPT_PGMCC_DATA option, length %u != %u + address size]",
opt_len, PGM_OPT_PGMCC_DATA_FIXED_LEN);
return;
}
ND_TCHECK_LEN(bp, sizeof(nd_ipv4));
addrtostr(bp, nla_buf, sizeof(nla_buf));
bp += sizeof(nd_ipv4);
opts_len -= PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(nd_ipv4);
break;
case AFNUM_INET6:
if (opt_len != PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(nd_ipv6)) {
ND_PRINT("[Bad OPT_PGMCC_DATA option, length %u != %u + address size]",
opt_len, PGM_OPT_PGMCC_DATA_FIXED_LEN);
return;
}
ND_TCHECK_LEN(bp, sizeof(nd_ipv6));
addrtostr6(bp, nla_buf, sizeof(nla_buf));
bp += sizeof(nd_ipv6);
opts_len -= PGM_OPT_PGMCC_DATA_FIXED_LEN + sizeof(nd_ipv6);
break;
default:
goto trunc;
break;
}
ND_PRINT(" PGMCC DATA %u %s", offset, nla_buf);
break;
case PGM_OPT_PGMCC_FEEDBACK:
#define PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN (2+2+4+2+2)
if (opt_len < PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN) {
ND_PRINT("[Bad PGM_OPT_PGMCC_FEEDBACK option, length %u < %u]",
opt_len, PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN);
return;
}
bp += 2;
offset = GET_BE_U_4(bp);
bp += 4;
nla_afnum = GET_BE_U_2(bp);
bp += 2+2;
switch (nla_afnum) {
case AFNUM_INET:
if (opt_len != PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(nd_ipv4)) {
ND_PRINT("[Bad OPT_PGMCC_FEEDBACK option, length %u != %u + address size]",
opt_len, PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN);
return;
}
ND_TCHECK_LEN(bp, sizeof(nd_ipv4));
addrtostr(bp, nla_buf, sizeof(nla_buf));
bp += sizeof(nd_ipv4);
opts_len -= PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(nd_ipv4);
break;
case AFNUM_INET6:
if (opt_len != PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(nd_ipv6)) {
ND_PRINT("[Bad OPT_PGMCC_FEEDBACK option, length %u != %u + address size]",
opt_len, PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN);
return;
}
ND_TCHECK_LEN(bp, sizeof(nd_ipv6));
addrtostr6(bp, nla_buf, sizeof(nla_buf));
bp += sizeof(nd_ipv6);
opts_len -= PGM_OPT_PGMCC_FEEDBACK_FIXED_LEN + sizeof(nd_ipv6);
break;
default:
goto trunc;
break;
}
ND_PRINT(" PGMCC FEEDBACK %u %s", offset, nla_buf);
break;
default:
ND_PRINT(" OPT_%02X [%u] ", opt_type, opt_len);
bp += opt_len;
opts_len -= opt_len;
break;
}
if (opt_type & PGM_OPT_END)
break;
}
}
ND_PRINT(" [%u]", length);
if (ndo->ndo_packettype == PT_PGM_ZMTP1 &&
(pgm_type_val == PGM_ODATA || pgm_type_val == PGM_RDATA))
zmtp1_datagram_print(ndo, bp,
GET_BE_U_2(pgm->pgm_length));
return;
trunc:
nd_print_trunc(ndo);
}
diff --git a/contrib/tcpdump/print-pim.c b/contrib/tcpdump/print-pim.c
index f2db8c768165..30dfaa838e4f 100644
--- a/contrib/tcpdump/print-pim.c
+++ b/contrib/tcpdump/print-pim.c
@@ -1,1234 +1,1230 @@
/*
* Copyright (c) 1995, 1996
* 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.
*/
/* \summary: Protocol Independent Multicast (PIM) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#include "ip.h"
#include "ip6.h"
#include "ipproto.h"
#define PIMV1_TYPE_QUERY 0
#define PIMV1_TYPE_REGISTER 1
#define PIMV1_TYPE_REGISTER_STOP 2
#define PIMV1_TYPE_JOIN_PRUNE 3
#define PIMV1_TYPE_RP_REACHABILITY 4
#define PIMV1_TYPE_ASSERT 5
#define PIMV1_TYPE_GRAFT 6
#define PIMV1_TYPE_GRAFT_ACK 7
static const struct tok pimv1_type_str[] = {
{ PIMV1_TYPE_QUERY, "Query" },
{ PIMV1_TYPE_REGISTER, "Register" },
{ PIMV1_TYPE_REGISTER_STOP, "Register-Stop" },
{ PIMV1_TYPE_JOIN_PRUNE, "Join/Prune" },
{ PIMV1_TYPE_RP_REACHABILITY, "RP-reachable" },
{ PIMV1_TYPE_ASSERT, "Assert" },
{ PIMV1_TYPE_GRAFT, "Graft" },
{ PIMV1_TYPE_GRAFT_ACK, "Graft-ACK" },
{ 0, NULL }
};
#define PIMV2_TYPE_HELLO 0
#define PIMV2_TYPE_REGISTER 1
#define PIMV2_TYPE_REGISTER_STOP 2
#define PIMV2_TYPE_JOIN_PRUNE 3
#define PIMV2_TYPE_BOOTSTRAP 4
#define PIMV2_TYPE_ASSERT 5
#define PIMV2_TYPE_GRAFT 6
#define PIMV2_TYPE_GRAFT_ACK 7
#define PIMV2_TYPE_CANDIDATE_RP 8
#define PIMV2_TYPE_PRUNE_REFRESH 9
#define PIMV2_TYPE_DF_ELECTION 10
#define PIMV2_TYPE_ECMP_REDIRECT 11
static const struct tok pimv2_type_values[] = {
{ PIMV2_TYPE_HELLO, "Hello" },
{ PIMV2_TYPE_REGISTER, "Register" },
{ PIMV2_TYPE_REGISTER_STOP, "Register Stop" },
{ PIMV2_TYPE_JOIN_PRUNE, "Join / Prune" },
{ PIMV2_TYPE_BOOTSTRAP, "Bootstrap" },
{ PIMV2_TYPE_ASSERT, "Assert" },
{ PIMV2_TYPE_GRAFT, "Graft" },
{ PIMV2_TYPE_GRAFT_ACK, "Graft Acknowledgement" },
{ PIMV2_TYPE_CANDIDATE_RP, "Candidate RP Advertisement" },
{ PIMV2_TYPE_PRUNE_REFRESH, "Prune Refresh" },
{ PIMV2_TYPE_DF_ELECTION, "DF Election" },
{ PIMV2_TYPE_ECMP_REDIRECT, "ECMP Redirect" },
{ 0, NULL}
};
#define PIMV2_HELLO_OPTION_HOLDTIME 1
#define PIMV2_HELLO_OPTION_LANPRUNEDELAY 2
#define PIMV2_HELLO_OPTION_DR_PRIORITY_OLD 18
#define PIMV2_HELLO_OPTION_DR_PRIORITY 19
#define PIMV2_HELLO_OPTION_GENID 20
#define PIMV2_HELLO_OPTION_REFRESH_CAP 21
#define PIMV2_HELLO_OPTION_BIDIR_CAP 22
#define PIMV2_HELLO_OPTION_ADDRESS_LIST 24
#define PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD 65001
static const struct tok pimv2_hello_option_values[] = {
{ PIMV2_HELLO_OPTION_HOLDTIME, "Hold Time" },
{ PIMV2_HELLO_OPTION_LANPRUNEDELAY, "LAN Prune Delay" },
{ PIMV2_HELLO_OPTION_DR_PRIORITY_OLD, "DR Priority (Old)" },
{ PIMV2_HELLO_OPTION_DR_PRIORITY, "DR Priority" },
{ PIMV2_HELLO_OPTION_GENID, "Generation ID" },
{ PIMV2_HELLO_OPTION_REFRESH_CAP, "State Refresh Capability" },
{ PIMV2_HELLO_OPTION_BIDIR_CAP, "Bi-Directional Capability" },
{ PIMV2_HELLO_OPTION_ADDRESS_LIST, "Address List" },
{ PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD, "Address List (Old)" },
{ 0, NULL}
};
#define PIMV2_REGISTER_FLAG_LEN 4
#define PIMV2_REGISTER_FLAG_BORDER 0x80000000
#define PIMV2_REGISTER_FLAG_NULL 0x40000000
static const struct tok pimv2_register_flag_values[] = {
{ PIMV2_REGISTER_FLAG_BORDER, "Border" },
{ PIMV2_REGISTER_FLAG_NULL, "Null" },
{ 0, NULL}
};
#define PIMV2_DF_ELECTION_OFFER 1
#define PIMV2_DF_ELECTION_WINNER 2
#define PIMV2_DF_ELECTION_BACKOFF 3
#define PIMV2_DF_ELECTION_PASS 4
static const struct tok pimv2_df_election_flag_values[] = {
{ PIMV2_DF_ELECTION_OFFER, "Offer" },
{ PIMV2_DF_ELECTION_WINNER, "Winner" },
{ PIMV2_DF_ELECTION_BACKOFF, "Backoff" },
{ PIMV2_DF_ELECTION_PASS, "Pass" },
{ 0, NULL}
};
#define PIMV2_DF_ELECTION_PASS_BACKOFF_STR(x) ( \
x == PIMV2_DF_ELECTION_BACKOFF ? "offer" : "new winner" )
/*
* XXX: We consider a case where IPv6 is not ready yet for portability,
* but PIM dependent definitions should be independent of IPv6...
*/
struct pim {
nd_uint8_t pim_typever;
/* upper 4bit: PIM version number; 2 for PIMv2 */
/* lower 4bit: the PIM message type, currently they are:
* Hello, Register, Register-Stop, Join/Prune,
* Bootstrap, Assert, Graft (PIM-DM only),
* Graft-Ack (PIM-DM only), C-RP-Adv
*/
#define PIM_VER(x) (((x) & 0xf0) >> 4)
#define PIM_TYPE(x) ((x) & 0x0f)
nd_uint8_t pim_rsv; /* Reserved in v1, subtype+address length in v2 */
#define PIM_SUBTYPE(x) (((x) & 0xf0) >> 4)
nd_uint16_t pim_cksum; /* IP style check sum */
};
static void pimv2_print(netdissect_options *, const u_char *bp, u_int len, const u_char *);
static void
pimv1_join_prune_print(netdissect_options *ndo,
const u_char *bp, u_int len)
{
u_int ngroups, njoin, nprune;
u_int njp;
/* If it's a single group and a single source, use 1-line output. */
if (ND_TTEST_LEN(bp, 30) && GET_U_1(bp + 11) == 1 &&
((njoin = GET_BE_U_2(bp + 20)) + GET_BE_U_2(bp + 22)) == 1) {
u_int hold;
ND_PRINT(" RPF %s ", GET_IPADDR_STRING(bp));
hold = GET_BE_U_2(bp + 6);
if (hold != 180) {
ND_PRINT("Hold ");
unsigned_relts_print(ndo, hold);
}
ND_PRINT("%s (%s/%u, %s", njoin ? "Join" : "Prune",
GET_IPADDR_STRING(bp + 26), GET_U_1(bp + 25) & 0x3f,
GET_IPADDR_STRING(bp + 12));
if (GET_BE_U_4(bp + 16) != 0xffffffff)
ND_PRINT("/%s", GET_IPADDR_STRING(bp + 16));
ND_PRINT(") %s%s %s",
(GET_U_1(bp + 24) & 0x01) ? "Sparse" : "Dense",
(GET_U_1(bp + 25) & 0x80) ? " WC" : "",
(GET_U_1(bp + 25) & 0x40) ? "RP" : "SPT");
return;
}
if (len < sizeof(nd_ipv4))
goto trunc;
if (ndo->ndo_vflag > 1)
ND_PRINT("\n");
ND_PRINT(" Upstream Nbr: %s", GET_IPADDR_STRING(bp));
bp += 4;
len -= 4;
if (len < 4)
goto trunc;
if (ndo->ndo_vflag > 1)
ND_PRINT("\n");
ND_PRINT(" Hold time: ");
unsigned_relts_print(ndo, GET_BE_U_2(bp + 2));
if (ndo->ndo_vflag < 2)
return;
bp += 4;
len -= 4;
if (len < 4)
goto trunc;
ngroups = GET_U_1(bp + 3);
bp += 4;
len -= 4;
while (ngroups != 0) {
/*
* XXX - does the address have length "addrlen" and the
* mask length "maddrlen"?
*/
if (len < 4)
goto trunc;
ND_PRINT("\n\tGroup: %s", GET_IPADDR_STRING(bp));
bp += 4;
len -= 4;
if (len < 4)
goto trunc;
if (GET_BE_U_4(bp) != 0xffffffff)
ND_PRINT("/%s", GET_IPADDR_STRING(bp));
bp += 4;
len -= 4;
if (len < 4)
goto trunc;
njoin = GET_BE_U_2(bp);
nprune = GET_BE_U_2(bp + 2);
ND_PRINT(" joined: %u pruned: %u", njoin, nprune);
bp += 4;
len -= 4;
for (njp = 0; njp < (njoin + nprune); njp++) {
const char *type;
if (njp < njoin)
type = "Join ";
else
type = "Prune";
if (len < 6)
goto trunc;
ND_PRINT("\n\t%s %s%s%s%s/%u", type,
(GET_U_1(bp) & 0x01) ? "Sparse " : "Dense ",
(GET_U_1(bp + 1) & 0x80) ? "WC " : "",
(GET_U_1(bp + 1) & 0x40) ? "RP " : "SPT ",
GET_IPADDR_STRING(bp + 2),
GET_U_1(bp + 1) & 0x3f);
bp += 6;
len -= 6;
}
ngroups--;
}
return;
trunc:
nd_print_trunc(ndo);
}
void
pimv1_print(netdissect_options *ndo,
const u_char *bp, u_int len)
{
u_char type;
ndo->ndo_protocol = "pimv1";
type = GET_U_1(bp + 1);
ND_PRINT(" %s", tok2str(pimv1_type_str, "[type %u]", type));
switch (type) {
case PIMV1_TYPE_QUERY:
if (ND_TTEST_1(bp + 8)) {
switch (GET_U_1(bp + 8) >> 4) {
case 0:
ND_PRINT(" Dense-mode");
break;
case 1:
ND_PRINT(" Sparse-mode");
break;
case 2:
ND_PRINT(" Sparse-Dense-mode");
break;
default:
ND_PRINT(" mode-%u", GET_U_1(bp + 8) >> 4);
break;
}
}
if (ndo->ndo_vflag) {
ND_PRINT(" (Hold-time ");
unsigned_relts_print(ndo, GET_BE_U_2(bp + 10));
ND_PRINT(")");
}
break;
case PIMV1_TYPE_REGISTER:
ND_TCHECK_LEN(bp + 8, 20); /* ip header */
ND_PRINT(" for %s > %s", GET_IPADDR_STRING(bp + 20),
GET_IPADDR_STRING(bp + 24));
break;
case PIMV1_TYPE_REGISTER_STOP:
ND_PRINT(" for %s > %s", GET_IPADDR_STRING(bp + 8),
GET_IPADDR_STRING(bp + 12));
break;
case PIMV1_TYPE_RP_REACHABILITY:
if (ndo->ndo_vflag) {
ND_PRINT(" group %s", GET_IPADDR_STRING(bp + 8));
if (GET_BE_U_4(bp + 12) != 0xffffffff)
ND_PRINT("/%s", GET_IPADDR_STRING(bp + 12));
ND_PRINT(" RP %s hold ", GET_IPADDR_STRING(bp + 16));
unsigned_relts_print(ndo, GET_BE_U_2(bp + 22));
}
break;
case PIMV1_TYPE_ASSERT:
ND_PRINT(" for %s > %s", GET_IPADDR_STRING(bp + 16),
GET_IPADDR_STRING(bp + 8));
if (GET_BE_U_4(bp + 12) != 0xffffffff)
ND_PRINT("/%s", GET_IPADDR_STRING(bp + 12));
ND_PRINT(" %s pref %u metric %u",
(GET_U_1(bp + 20) & 0x80) ? "RP-tree" : "SPT",
GET_BE_U_4(bp + 20) & 0x7fffffff,
GET_BE_U_4(bp + 24));
break;
case PIMV1_TYPE_JOIN_PRUNE:
case PIMV1_TYPE_GRAFT:
case PIMV1_TYPE_GRAFT_ACK:
if (ndo->ndo_vflag) {
if (len < 8)
goto trunc;
pimv1_join_prune_print(ndo, bp + 8, len - 8);
}
break;
}
if ((GET_U_1(bp + 4) >> 4) != 1)
ND_PRINT(" [v%u]", GET_U_1(bp + 4) >> 4);
return;
trunc:
nd_print_trunc(ndo);
}
/*
* auto-RP is a cisco protocol, documented at
* ftp://ftpeng.cisco.com/ipmulticast/specs/pim-autorp-spec01.txt
*
* This implements version 1+, dated Sept 9, 1998.
*/
void
cisco_autorp_print(netdissect_options *ndo,
const u_char *bp, u_int len)
{
u_int type;
u_int numrps;
u_int hold;
ndo->ndo_protocol = "cisco_autorp";
if (len < 8)
goto trunc;
ND_PRINT(" auto-rp ");
type = GET_U_1(bp);
switch (type) {
case 0x11:
ND_PRINT("candidate-advert");
break;
case 0x12:
ND_PRINT("mapping");
break;
default:
ND_PRINT("type-0x%02x", type);
break;
}
numrps = GET_U_1(bp + 1);
ND_PRINT(" Hold ");
hold = GET_BE_U_2(bp + 2);
if (hold)
unsigned_relts_print(ndo, GET_BE_U_2(bp + 2));
else
ND_PRINT("FOREVER");
/* Next 4 bytes are reserved. */
bp += 8; len -= 8;
/*XXX skip unless -v? */
/*
* Rest of packet:
* numrps entries of the form:
* 32 bits: RP
* 6 bits: reserved
* 2 bits: PIM version supported, bit 0 is "supports v1", 1 is "v2".
* 8 bits: # of entries for this RP
* each entry: 7 bits: reserved, 1 bit: negative,
* 8 bits: mask 32 bits: source
* lather, rinse, repeat.
*/
while (numrps != 0) {
u_int nentries;
char s;
if (len < 4)
goto trunc;
ND_PRINT(" RP %s", GET_IPADDR_STRING(bp));
bp += 4;
len -= 4;
if (len < 1)
goto trunc;
switch (GET_U_1(bp) & 0x3) {
case 0: ND_PRINT(" PIMv?");
break;
case 1: ND_PRINT(" PIMv1");
break;
case 2: ND_PRINT(" PIMv2");
break;
case 3: ND_PRINT(" PIMv1+2");
break;
}
if (GET_U_1(bp) & 0xfc)
ND_PRINT(" [rsvd=0x%02x]", GET_U_1(bp) & 0xfc);
bp += 1;
len -= 1;
if (len < 1)
goto trunc;
nentries = GET_U_1(bp);
bp += 1;
len -= 1;
s = ' ';
while (nentries != 0) {
if (len < 6)
goto trunc;
ND_PRINT("%c%s%s/%u", s, GET_U_1(bp) & 1 ? "!" : "",
GET_IPADDR_STRING(bp + 2), GET_U_1(bp + 1));
if (GET_U_1(bp) & 0x02) {
ND_PRINT(" bidir");
}
if (GET_U_1(bp) & 0xfc) {
ND_PRINT("[rsvd=0x%02x]", GET_U_1(bp) & 0xfc);
}
s = ',';
bp += 6; len -= 6;
nentries--;
}
numrps--;
}
return;
trunc:
nd_print_trunc(ndo);
}
void
pim_print(netdissect_options *ndo,
const u_char *bp, u_int len, const u_char *bp2)
{
const struct pim *pim = (const struct pim *)bp;
uint8_t pim_typever;
ndo->ndo_protocol = "pim";
pim_typever = GET_U_1(pim->pim_typever);
switch (PIM_VER(pim_typever)) {
case 2:
if (!ndo->ndo_vflag) {
ND_PRINT("PIMv%u, %s, length %u",
PIM_VER(pim_typever),
tok2str(pimv2_type_values,"Unknown Type",PIM_TYPE(pim_typever)),
len);
return;
} else {
ND_PRINT("PIMv%u, length %u\n\t%s",
PIM_VER(pim_typever),
len,
tok2str(pimv2_type_values,"Unknown Type",PIM_TYPE(pim_typever)));
pimv2_print(ndo, bp, len, bp2);
}
break;
default:
ND_PRINT("PIMv%u, length %u",
PIM_VER(pim_typever),
len);
break;
}
}
/*
* PIMv2 uses encoded address representations.
*
* The last PIM-SM I-D before RFC2117 was published specified the
* following representation for unicast addresses. However, RFC2117
* specified no encoding for unicast addresses with the unicast
* address length specified in the header. Therefore, we have to
* guess which encoding is being used (Cisco's PIMv2 implementation
* uses the non-RFC encoding). RFC2117 turns a previously "Reserved"
* field into a 'unicast-address-length-in-bytes' field. We guess
* that it's the draft encoding if this reserved field is zero.
*
* RFC2362 goes back to the encoded format, and calls the addr length
* field "reserved" again.
*
* The first byte is the address family, from:
*
* 0 Reserved
* 1 IP (IP version 4)
* 2 IP6 (IP version 6)
* 3 NSAP
* 4 HDLC (8-bit multidrop)
* 5 BBN 1822
* 6 802 (includes all 802 media plus Ethernet "canonical format")
* 7 E.163
* 8 E.164 (SMDS, Frame Relay, ATM)
* 9 F.69 (Telex)
* 10 X.121 (X.25, Frame Relay)
* 11 IPX
* 12 Appletalk
* 13 Decnet IV
* 14 Banyan Vines
* 15 E.164 with NSAP format subaddress
*
* In addition, the second byte is an "Encoding". 0 is the default
* encoding for the address family, and no other encodings are currently
* specified.
*
*/
enum pimv2_addrtype {
pimv2_unicast, pimv2_group, pimv2_source
};
/* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Addr Family | Encoding Type | Unicast Address |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+++++++
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Addr Family | Encoding Type | Reserved | Mask Len |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Group multicast Address |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Addr Family | Encoding Type | Rsrvd |S|W|R| Mask Len |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Source Address |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
static int
pimv2_addr_print(netdissect_options *ndo,
const u_char *bp, u_int len, enum pimv2_addrtype at,
u_int addr_len, int silent)
{
u_int af;
int hdrlen;
if (addr_len == 0) {
if (len < 2)
goto trunc;
switch (GET_U_1(bp)) {
case 1:
af = AF_INET;
addr_len = (u_int)sizeof(nd_ipv4);
break;
case 2:
af = AF_INET6;
addr_len = (u_int)sizeof(nd_ipv6);
break;
default:
return -1;
}
if (GET_U_1(bp + 1) != 0)
return -1;
hdrlen = 2;
} else {
switch (addr_len) {
case sizeof(nd_ipv4):
af = AF_INET;
break;
case sizeof(nd_ipv6):
af = AF_INET6;
break;
default:
return -1;
break;
}
hdrlen = 0;
}
bp += hdrlen;
len -= hdrlen;
switch (at) {
case pimv2_unicast:
if (len < addr_len)
goto trunc;
ND_TCHECK_LEN(bp, addr_len);
if (af == AF_INET) {
if (!silent)
ND_PRINT("%s", GET_IPADDR_STRING(bp));
- }
- else if (af == AF_INET6) {
+ } else if (af == AF_INET6) {
if (!silent)
ND_PRINT("%s", GET_IP6ADDR_STRING(bp));
}
return hdrlen + addr_len;
case pimv2_group:
case pimv2_source:
if (len < addr_len + 2)
goto trunc;
ND_TCHECK_LEN(bp, addr_len + 2);
if (af == AF_INET) {
if (!silent) {
ND_PRINT("%s", GET_IPADDR_STRING(bp + 2));
if (GET_U_1(bp + 1) != 32)
ND_PRINT("/%u", GET_U_1(bp + 1));
}
- }
- else if (af == AF_INET6) {
+ } else if (af == AF_INET6) {
if (!silent) {
ND_PRINT("%s", GET_IP6ADDR_STRING(bp + 2));
if (GET_U_1(bp + 1) != 128)
ND_PRINT("/%u", GET_U_1(bp + 1));
}
}
if (GET_U_1(bp) && !silent) {
if (at == pimv2_group) {
ND_PRINT("(0x%02x)", GET_U_1(bp));
} else {
ND_PRINT("(%s%s%s",
GET_U_1(bp) & 0x04 ? "S" : "",
GET_U_1(bp) & 0x02 ? "W" : "",
GET_U_1(bp) & 0x01 ? "R" : "");
if (GET_U_1(bp) & 0xf8) {
ND_PRINT("+0x%02x",
GET_U_1(bp) & 0xf8);
}
ND_PRINT(")");
}
}
return hdrlen + 2 + addr_len;
default:
return -1;
}
trunc:
return -1;
}
enum checksum_status {
CORRECT,
INCORRECT,
UNVERIFIED
};
static enum checksum_status
pimv2_check_checksum(netdissect_options *ndo, const u_char *bp,
const u_char *bp2, u_int len)
{
const struct ip *ip;
u_int cksum;
if (!ND_TTEST_LEN(bp, len)) {
/* We don't have all the data. */
return (UNVERIFIED);
}
ip = (const struct ip *)bp2;
if (IP_V(ip) == 4) {
struct cksum_vec vec[1];
vec[0].ptr = bp;
vec[0].len = len;
cksum = in_cksum(vec, 1);
return (cksum ? INCORRECT : CORRECT);
} else if (IP_V(ip) == 6) {
const struct ip6_hdr *ip6;
ip6 = (const struct ip6_hdr *)bp2;
cksum = nextproto6_cksum(ndo, ip6, bp, len, len, IPPROTO_PIM);
return (cksum ? INCORRECT : CORRECT);
} else {
return (UNVERIFIED);
}
}
static void
pimv2_print(netdissect_options *ndo,
const u_char *bp, u_int len, const u_char *bp2)
{
const struct pim *pim = (const struct pim *)bp;
int advance;
int subtype;
enum checksum_status cksum_status;
u_int pim_typever;
u_int pimv2_addr_len;
ndo->ndo_protocol = "pimv2";
if (len < 2) {
ND_PRINT("[length %u < 2]", len);
nd_print_invalid(ndo);
return;
}
pim_typever = GET_U_1(pim->pim_typever);
/* RFC5015 allocates the high 4 bits of pim_rsv for "subtype". */
pimv2_addr_len = GET_U_1(pim->pim_rsv) & 0x0f;
if (pimv2_addr_len != 0)
ND_PRINT(", RFC2117-encoding");
if (len < 4) {
ND_PRINT("[length %u < 4]", len);
nd_print_invalid(ndo);
return;
}
ND_PRINT(", cksum 0x%04x ", GET_BE_U_2(pim->pim_cksum));
if (GET_BE_U_2(pim->pim_cksum) == 0) {
ND_PRINT("(unverified)");
} else {
if (PIM_TYPE(pim_typever) == PIMV2_TYPE_REGISTER) {
/*
* The checksum only covers the packet header,
* not the encapsulated packet.
*/
cksum_status = pimv2_check_checksum(ndo, bp, bp2, 8);
if (cksum_status == INCORRECT) {
/*
* To quote RFC 4601, "For interoperability
* reasons, a message carrying a checksum
* calculated over the entire PIM Register
* message should also be accepted."
*/
cksum_status = pimv2_check_checksum(ndo, bp, bp2, len);
}
} else {
/*
* The checksum covers the entire packet.
*/
cksum_status = pimv2_check_checksum(ndo, bp, bp2, len);
}
switch (cksum_status) {
case CORRECT:
ND_PRINT("(correct)");
break;
case INCORRECT:
ND_PRINT("(incorrect)");
break;
case UNVERIFIED:
ND_PRINT("(unverified)");
break;
}
}
bp += 4;
len -= 4;
switch (PIM_TYPE(pim_typever)) {
case PIMV2_TYPE_HELLO:
{
uint16_t otype, olen;
while (len > 0) {
if (len < 4)
goto trunc;
otype = GET_BE_U_2(bp);
olen = GET_BE_U_2(bp + 2);
ND_PRINT("\n\t %s Option (%u), length %u, Value: ",
tok2str(pimv2_hello_option_values, "Unknown", otype),
otype,
olen);
bp += 4;
len -= 4;
if (len < olen)
goto trunc;
ND_TCHECK_LEN(bp, olen);
switch (otype) {
case PIMV2_HELLO_OPTION_HOLDTIME:
if (olen != 2) {
ND_PRINT("[option length %u != 2]", olen);
nd_print_invalid(ndo);
return;
} else {
unsigned_relts_print(ndo,
GET_BE_U_2(bp));
}
break;
case PIMV2_HELLO_OPTION_LANPRUNEDELAY:
if (olen != 4) {
ND_PRINT("[option length %u != 4]", olen);
nd_print_invalid(ndo);
return;
} else {
char t_bit;
uint16_t lan_delay, override_interval;
lan_delay = GET_BE_U_2(bp);
override_interval = GET_BE_U_2(bp + 2);
t_bit = (lan_delay & 0x8000)? 1 : 0;
lan_delay &= ~0x8000;
ND_PRINT("\n\t T-bit=%u, LAN delay %ums, Override interval %ums",
t_bit, lan_delay, override_interval);
}
break;
case PIMV2_HELLO_OPTION_DR_PRIORITY_OLD:
case PIMV2_HELLO_OPTION_DR_PRIORITY:
switch (olen) {
case 0:
ND_PRINT("Bi-Directional Capability (Old)");
break;
case 4:
ND_PRINT("%u", GET_BE_U_4(bp));
break;
default:
ND_PRINT("[option length %u != 4]", olen);
nd_print_invalid(ndo);
return;
break;
}
break;
case PIMV2_HELLO_OPTION_GENID:
if (olen != 4) {
ND_PRINT("[option length %u != 4]", olen);
nd_print_invalid(ndo);
return;
} else {
ND_PRINT("0x%08x", GET_BE_U_4(bp));
}
break;
case PIMV2_HELLO_OPTION_REFRESH_CAP:
if (olen != 4) {
ND_PRINT("[option length %u != 4]", olen);
nd_print_invalid(ndo);
return;
} else {
ND_PRINT("v%u", GET_U_1(bp));
if (GET_U_1(bp + 1) != 0) {
ND_PRINT(", interval ");
unsigned_relts_print(ndo,
GET_U_1(bp + 1));
}
if (GET_BE_U_2(bp + 2) != 0) {
ND_PRINT(" ?0x%04x?",
GET_BE_U_2(bp + 2));
}
}
break;
case PIMV2_HELLO_OPTION_BIDIR_CAP:
break;
case PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD:
case PIMV2_HELLO_OPTION_ADDRESS_LIST:
if (ndo->ndo_vflag > 1) {
const u_char *ptr = bp;
u_int plen = len;
while (ptr < (bp+olen)) {
ND_PRINT("\n\t ");
advance = pimv2_addr_print(ndo, ptr, plen, pimv2_unicast, pimv2_addr_len, 0);
if (advance < 0)
goto trunc;
ptr += advance;
plen -= advance;
}
}
break;
default:
if (ndo->ndo_vflag <= 1)
print_unknown_data(ndo, bp, "\n\t ", olen);
break;
}
/* do we want to see an additionally hexdump ? */
if (ndo->ndo_vflag> 1)
print_unknown_data(ndo, bp, "\n\t ", olen);
bp += olen;
len -= olen;
}
break;
}
case PIMV2_TYPE_REGISTER:
{
const struct ip *ip;
if (len < 4)
goto trunc;
ND_TCHECK_LEN(bp, PIMV2_REGISTER_FLAG_LEN);
ND_PRINT(", Flags [ %s ]\n\t",
tok2str(pimv2_register_flag_values,
"none",
GET_BE_U_4(bp)));
bp += 4; len -= 4;
/* encapsulated multicast packet */
if (len == 0)
goto trunc;
ip = (const struct ip *)bp;
switch (IP_V(ip)) {
case 0: /* Null header */
ND_PRINT("IP-Null-header %s > %s",
GET_IPADDR_STRING(ip->ip_src),
GET_IPADDR_STRING(ip->ip_dst));
break;
case 4: /* IPv4 */
ip_print(ndo, bp, len);
break;
case 6: /* IPv6 */
ip6_print(ndo, bp, len);
break;
default:
ND_PRINT("IP ver %u", IP_V(ip));
break;
}
break;
}
case PIMV2_TYPE_REGISTER_STOP:
ND_PRINT(" group=");
if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_group, pimv2_addr_len, 0)) < 0)
goto trunc;
bp += advance; len -= advance;
ND_PRINT(" source=");
if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0)
goto trunc;
bp += advance; len -= advance;
break;
case PIMV2_TYPE_JOIN_PRUNE:
case PIMV2_TYPE_GRAFT:
case PIMV2_TYPE_GRAFT_ACK:
/*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |PIM Ver| Type | Addr length | Checksum |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Unicast-Upstream Neighbor Address |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Reserved | Num groups | Holdtime |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Encoded-Multicast Group Address-1 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Number of Joined Sources | Number of Pruned Sources |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Encoded-Joined Source Address-1 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | . |
* | . |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Encoded-Joined Source Address-n |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Encoded-Pruned Source Address-1 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | . |
* | . |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Encoded-Pruned Source Address-n |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | . |
* | . |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Encoded-Multicast Group Address-n |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
{
uint8_t ngroup;
uint16_t holdtime;
uint16_t njoin;
uint16_t nprune;
u_int i, j;
if (PIM_TYPE(pim_typever) != 7) { /*not for Graft-ACK*/
ND_PRINT(", upstream-neighbor: ");
if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0)
goto trunc;
bp += advance; len -= advance;
}
if (len < 4)
goto trunc;
ND_TCHECK_4(bp);
ngroup = GET_U_1(bp + 1);
holdtime = GET_BE_U_2(bp + 2);
ND_PRINT("\n\t %u group(s)", ngroup);
if (PIM_TYPE(pim_typever) != 7) { /*not for Graft-ACK*/
ND_PRINT(", holdtime: ");
if (holdtime == 0xffff)
ND_PRINT("infinite");
else
unsigned_relts_print(ndo, holdtime);
}
bp += 4; len -= 4;
for (i = 0; i < ngroup; i++) {
ND_PRINT("\n\t group #%u: ", i+1);
if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_group, pimv2_addr_len, 0)) < 0)
goto trunc;
bp += advance; len -= advance;
if (len < 4)
goto trunc;
ND_TCHECK_4(bp);
njoin = GET_BE_U_2(bp);
nprune = GET_BE_U_2(bp + 2);
ND_PRINT(", joined sources: %u, pruned sources: %u", njoin, nprune);
bp += 4; len -= 4;
for (j = 0; j < njoin; j++) {
ND_PRINT("\n\t joined source #%u: ", j+1);
if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_source, pimv2_addr_len, 0)) < 0)
goto trunc;
bp += advance; len -= advance;
}
for (j = 0; j < nprune; j++) {
ND_PRINT("\n\t pruned source #%u: ", j+1);
if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_source, pimv2_addr_len, 0)) < 0)
goto trunc;
bp += advance; len -= advance;
}
}
break;
}
case PIMV2_TYPE_BOOTSTRAP:
{
u_int i, j, frpcnt;
/* Fragment Tag, Hash Mask len, and BSR-priority */
if (len < 2)
goto trunc;
ND_PRINT(" tag=%x", GET_BE_U_2(bp));
bp += 2;
len -= 2;
if (len < 1)
goto trunc;
ND_PRINT(" hashmlen=%u", GET_U_1(bp));
if (len < 2)
goto trunc;
ND_TCHECK_1(bp + 2);
ND_PRINT(" BSRprio=%u", GET_U_1(bp + 1));
bp += 2;
len -= 2;
/* Encoded-Unicast-BSR-Address */
ND_PRINT(" BSR=");
if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0)
goto trunc;
bp += advance;
len -= advance;
for (i = 0; len > 0; i++) {
/* Encoded-Group Address */
ND_PRINT(" (group%u: ", i);
if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_group, pimv2_addr_len, 0)) < 0)
goto trunc;
bp += advance;
len -= advance;
/* RP-Count, Frag RP-Cnt, and rsvd */
if (len < 1)
goto trunc;
ND_PRINT(" RPcnt=%u", GET_U_1(bp));
if (len < 2)
goto trunc;
frpcnt = GET_U_1(bp + 1);
ND_PRINT(" FRPcnt=%u", frpcnt);
if (len < 4)
goto trunc;
bp += 4;
len -= 4;
for (j = 0; j < frpcnt && len > 0; j++) {
/* each RP info */
ND_PRINT(" RP%u=", j);
if ((advance = pimv2_addr_print(ndo, bp, len,
pimv2_unicast,
pimv2_addr_len,
0)) < 0)
goto trunc;
bp += advance;
len -= advance;
if (len < 2)
goto trunc;
ND_PRINT(",holdtime=");
unsigned_relts_print(ndo,
GET_BE_U_2(bp));
if (len < 3)
goto trunc;
ND_PRINT(",prio=%u", GET_U_1(bp + 2));
if (len < 4)
goto trunc;
bp += 4;
len -= 4;
}
ND_PRINT(")");
}
break;
}
case PIMV2_TYPE_ASSERT:
ND_PRINT(" group=");
if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_group, pimv2_addr_len, 0)) < 0)
goto trunc;
bp += advance; len -= advance;
ND_PRINT(" src=");
if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0)
goto trunc;
bp += advance; len -= advance;
if (len < 8)
goto trunc;
ND_TCHECK_8(bp);
if (GET_U_1(bp) & 0x80)
ND_PRINT(" RPT");
ND_PRINT(" pref=%u", GET_BE_U_4(bp) & 0x7fffffff);
ND_PRINT(" metric=%u", GET_BE_U_4(bp + 4));
break;
case PIMV2_TYPE_CANDIDATE_RP:
{
u_int i, pfxcnt;
/* Prefix-Cnt, Priority, and Holdtime */
if (len < 1)
goto trunc;
ND_PRINT(" prefix-cnt=%u", GET_U_1(bp));
pfxcnt = GET_U_1(bp);
if (len < 2)
goto trunc;
ND_PRINT(" prio=%u", GET_U_1(bp + 1));
if (len < 4)
goto trunc;
ND_PRINT(" holdtime=");
unsigned_relts_print(ndo, GET_BE_U_2(bp + 2));
bp += 4;
len -= 4;
/* Encoded-Unicast-RP-Address */
ND_PRINT(" RP=");
if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0)
goto trunc;
bp += advance;
len -= advance;
/* Encoded-Group Addresses */
for (i = 0; i < pfxcnt && len > 0; i++) {
ND_PRINT(" Group%u=", i);
if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_group, pimv2_addr_len, 0)) < 0)
goto trunc;
bp += advance;
len -= advance;
}
break;
}
case PIMV2_TYPE_PRUNE_REFRESH:
ND_PRINT(" src=");
if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0)
goto trunc;
bp += advance;
len -= advance;
ND_PRINT(" grp=");
if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_group, pimv2_addr_len, 0)) < 0)
goto trunc;
bp += advance;
len -= advance;
ND_PRINT(" forwarder=");
if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0)
goto trunc;
bp += advance;
len -= advance;
if (len < 2)
goto trunc;
ND_PRINT(" TUNR ");
unsigned_relts_print(ndo, GET_BE_U_2(bp));
break;
case PIMV2_TYPE_DF_ELECTION:
subtype = PIM_SUBTYPE(GET_U_1(pim->pim_rsv));
ND_PRINT("\n\t %s,", tok2str( pimv2_df_election_flag_values,
"Unknown", subtype) );
ND_PRINT(" rpa=");
if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0) {
goto trunc;
}
bp += advance;
len -= advance;
ND_PRINT(" sender pref=%u", GET_BE_U_4(bp) );
ND_PRINT(" sender metric=%u", GET_BE_U_4(bp + 4));
bp += 8;
len -= 8;
switch (subtype) {
case PIMV2_DF_ELECTION_BACKOFF:
case PIMV2_DF_ELECTION_PASS:
ND_PRINT("\n\t %s addr=", PIMV2_DF_ELECTION_PASS_BACKOFF_STR(subtype));
if ((advance = pimv2_addr_print(ndo, bp, len, pimv2_unicast, pimv2_addr_len, 0)) < 0) {
goto trunc;
}
bp += advance;
len -= advance;
ND_PRINT(" %s pref=%u", PIMV2_DF_ELECTION_PASS_BACKOFF_STR(subtype), GET_BE_U_4(bp) );
ND_PRINT(" %s metric=%u", PIMV2_DF_ELECTION_PASS_BACKOFF_STR(subtype), GET_BE_U_4(bp + 4));
bp += 8;
len -= 8;
if (subtype == PIMV2_DF_ELECTION_BACKOFF) {
ND_PRINT(" interval %dms", GET_BE_U_2(bp));
}
break;
default:
break;
}
break;
default:
ND_PRINT(" [type %u]", PIM_TYPE(pim_typever));
break;
}
return;
trunc:
nd_print_trunc(ndo);
}
diff --git a/contrib/tcpdump/print-pktap.c b/contrib/tcpdump/print-pktap.c
index 05ce5f997824..d1c391d5ce1b 100644
--- a/contrib/tcpdump/print-pktap.c
+++ b/contrib/tcpdump/print-pktap.c
@@ -1,177 +1,175 @@
/*
* 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.
*/
/* \summary: Apple's DLT_PKTAP printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
#ifdef DLT_PKTAP
/*
* XXX - these are little-endian in the captures I've seen, but Apple
* no longer make any big-endian machines (Macs use x86, iOS machines
* use ARM and run it little-endian), so that might be by definition
* or they might be host-endian.
*
* If a big-endian PKTAP file ever shows up, and it comes from a
* big-endian machine, presumably these are host-endian, and we need
* to just fetch the fields directly in tcpdump but byte-swap them
* to host byte order in libpcap.
*/
typedef struct pktap_header {
nd_uint32_t pkt_len; /* length of pktap header */
nd_uint32_t pkt_rectype; /* type of record */
nd_uint32_t pkt_dlt; /* DLT type of this packet */
char pkt_ifname[24]; /* interface name */
nd_uint32_t pkt_flags;
nd_uint32_t pkt_pfamily; /* "protocol family" */
nd_uint32_t pkt_llhdrlen; /* link-layer header length? */
nd_uint32_t pkt_lltrlrlen; /* link-layer trailer length? */
nd_uint32_t pkt_pid; /* process ID */
char pkt_cmdname[20]; /* command name */
nd_uint32_t pkt_svc_class; /* "service class" */
nd_uint16_t pkt_iftype; /* "interface type" */
nd_uint16_t pkt_ifunit; /* unit number of interface? */
nd_uint32_t pkt_epid; /* "effective process ID" */
char pkt_ecmdname[20]; /* "effective command name" */
} pktap_header_t;
/*
* Record types.
*/
#define PKT_REC_NONE 0 /* nothing follows the header */
#define PKT_REC_PACKET 1 /* a packet follows the header */
static void
pktap_header_print(netdissect_options *ndo, const u_char *bp, u_int length)
{
const pktap_header_t *hdr;
uint32_t dlt, hdrlen;
const char *dltname;
hdr = (const pktap_header_t *)bp;
dlt = GET_LE_U_4(hdr->pkt_dlt);
hdrlen = GET_LE_U_4(hdr->pkt_len);
dltname = pcap_datalink_val_to_name(dlt);
if (!ndo->ndo_qflag) {
ND_PRINT("DLT %s (%u) len %u",
(dltname != NULL ? dltname : "UNKNOWN"), dlt, hdrlen);
} else {
ND_PRINT("%s", (dltname != NULL ? dltname : "UNKNOWN"));
}
ND_PRINT(", length %u: ", length);
}
/*
* This is the top level routine of the printer. 'p' points
* to the ether header of the packet, 'h->ts' is the timestamp,
* 'h->len' is the length of the packet off the wire, and 'h->caplen'
* is the number of bytes actually captured.
*/
void
pktap_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h, const u_char *p)
{
uint32_t dlt, hdrlen, rectype;
u_int caplen = h->caplen;
u_int length = h->len;
if_printer printer;
const pktap_header_t *hdr;
struct pcap_pkthdr nhdr;
ndo->ndo_protocol = "pktap";
if (length < sizeof(pktap_header_t)) {
ND_PRINT(" (packet too short, %u < %zu)",
length, sizeof(pktap_header_t));
goto invalid;
}
hdr = (const pktap_header_t *)p;
dlt = GET_LE_U_4(hdr->pkt_dlt);
hdrlen = GET_LE_U_4(hdr->pkt_len);
if (hdrlen < sizeof(pktap_header_t)) {
/*
* Claimed header length < structure length.
* XXX - does this just mean some fields aren't
* being supplied, or is it truly an error (i.e.,
* is the length supplied so that the header can
* be expanded in the future)?
*/
ND_PRINT(" (pkt_len too small, %u < %zu)",
hdrlen, sizeof(pktap_header_t));
goto invalid;
}
if (hdrlen > length) {
ND_PRINT(" (pkt_len too big, %u > %u)",
hdrlen, length);
goto invalid;
}
ND_TCHECK_LEN(p, hdrlen);
if (ndo->ndo_eflag)
pktap_header_print(ndo, p, length);
length -= hdrlen;
caplen -= hdrlen;
p += hdrlen;
rectype = GET_LE_U_4(hdr->pkt_rectype);
switch (rectype) {
case PKT_REC_NONE:
ND_PRINT("no data");
break;
case PKT_REC_PACKET:
printer = lookup_printer(dlt);
if (printer != NULL) {
nhdr = *h;
nhdr.caplen = caplen;
nhdr.len = length;
printer(ndo, &nhdr, p);
hdrlen += ndo->ndo_ll_hdr_len;
} else {
if (!ndo->ndo_eflag)
pktap_header_print(ndo, (const u_char *)hdr,
length + hdrlen);
if (!ndo->ndo_suppress_default_print)
ND_DEFAULTPRINT(p, caplen);
}
break;
}
ndo->ndo_ll_hdr_len += hdrlen;
return;
invalid:
nd_print_invalid(ndo);
}
#endif /* DLT_PKTAP */
diff --git a/contrib/tcpdump/print-ppi.c b/contrib/tcpdump/print-ppi.c
index 774edfbaf8ce..0795f276ac0a 100644
--- a/contrib/tcpdump/print-ppi.c
+++ b/contrib/tcpdump/print-ppi.c
@@ -1,131 +1,129 @@
/*
* Oracle
*/
/* \summary: Per-Packet Information (DLT_PPI) printer */
/* Specification:
* Per-Packet Information Header Specification - Version 1.0.7
* https://web.archive.org/web/20160328114748/http://www.cacetech.com/documents/PPI%20Header%20format%201.0.7.pdf
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "extract.h"
typedef struct ppi_header {
nd_uint8_t ppi_ver; /* Version. Currently 0 */
nd_uint8_t ppi_flags; /* Flags. */
nd_uint16_t ppi_len; /* Length of entire message, including
* this header and TLV payload. */
nd_uint32_t ppi_dlt; /* Data Link Type of the captured
* packet data. */
} ppi_header_t;
#define PPI_HDRLEN 8
#ifdef DLT_PPI
static void
ppi_header_print(netdissect_options *ndo, const u_char *bp, u_int length)
{
const ppi_header_t *hdr;
uint16_t len;
uint32_t dlt;
const char *dltname;
hdr = (const ppi_header_t *)bp;
len = GET_LE_U_2(hdr->ppi_len);
dlt = GET_LE_U_4(hdr->ppi_dlt);
dltname = pcap_datalink_val_to_name(dlt);
if (!ndo->ndo_qflag) {
ND_PRINT("V.%u DLT %s (%u) len %u", GET_U_1(hdr->ppi_ver),
(dltname != NULL ? dltname : "UNKNOWN"), dlt,
len);
} else {
ND_PRINT("%s", (dltname != NULL ? dltname : "UNKNOWN"));
}
ND_PRINT(", length %u: ", length);
}
/*
* This is the top level routine of the printer. 'p' points
* to the ether header of the packet, 'h->ts' is the timestamp,
* 'h->len' is the length of the packet off the wire, and 'h->caplen'
* is the number of bytes actually captured.
*/
void
ppi_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h, const u_char *p)
{
if_printer printer;
const ppi_header_t *hdr;
u_int caplen = h->caplen;
u_int length = h->len;
uint16_t len;
uint32_t dlt;
uint32_t hdrlen;
struct pcap_pkthdr nhdr;
ndo->ndo_protocol = "ppi";
if (caplen < sizeof(ppi_header_t)) {
nd_print_trunc(ndo);
ndo->ndo_ll_hdr_len += caplen;
return;
}
hdr = (const ppi_header_t *)p;
len = GET_LE_U_2(hdr->ppi_len);
if (len < sizeof(ppi_header_t) || len > 65532) {
/* It MUST be between 8 and 65,532 inclusive (spec 3.1.3) */
ND_PRINT(" [length %u < %zu or > 65532]", len,
sizeof(ppi_header_t));
nd_print_invalid(ndo);
ndo->ndo_ll_hdr_len += caplen;
return;
}
if (caplen < len) {
/*
* If we don't have the entire PPI header, don't
* bother.
*/
nd_print_trunc(ndo);
ndo->ndo_ll_hdr_len += caplen;
return;
}
dlt = GET_LE_U_4(hdr->ppi_dlt);
if (ndo->ndo_eflag)
ppi_header_print(ndo, p, length);
length -= len;
caplen -= len;
p += len;
printer = lookup_printer(dlt);
if (printer != NULL) {
nhdr = *h;
nhdr.caplen = caplen;
nhdr.len = length;
printer(ndo, &nhdr, p);
hdrlen = ndo->ndo_ll_hdr_len;
} else {
if (!ndo->ndo_eflag)
ppi_header_print(ndo, (const u_char *)hdr, length + len);
if (!ndo->ndo_suppress_default_print)
ND_DEFAULTPRINT(p, caplen);
hdrlen = 0;
}
ndo->ndo_ll_hdr_len += len + hdrlen;
}
#endif /* DLT_PPI */
diff --git a/contrib/tcpdump/print-ppp.c b/contrib/tcpdump/print-ppp.c
index e5ae0646ebae..ccce71539790 100644
--- a/contrib/tcpdump/print-ppp.c
+++ b/contrib/tcpdump/print-ppp.c
@@ -1,1900 +1,1899 @@
/*
* 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.
*
* Extensively modified by Motonori Shindo (mshindo@mshindo.net) for more
* complete PPP support.
*/
/* \summary: Point to Point Protocol (PPP) printer */
/*
* TODO:
* o resolve XXX as much as possible
* o MP support
* o BAP support
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
+#include <stdlib.h>
+
#ifdef __bsdi__
#include <net/slcompress.h>
#include <net/if_ppp.h>
#endif
#include <stdlib.h>
#include "netdissect.h"
#include "extract.h"
#include "addrtoname.h"
#include "ppp.h"
#include "chdlc.h"
#include "ethertype.h"
#include "oui.h"
#include "netdissect-alloc.h"
/*
* The following constants are defined by IANA. Please refer to
* https://www.isi.edu/in-notes/iana/assignments/ppp-numbers
* for the up-to-date information.
*/
/* Protocol Codes defined in ppp.h */
static const struct tok ppptype2str[] = {
{ PPP_IP, "IP" },
{ PPP_OSI, "OSI" },
{ PPP_NS, "NS" },
{ PPP_DECNET, "DECNET" },
{ PPP_APPLE, "APPLE" },
{ PPP_IPX, "IPX" },
{ PPP_VJC, "VJC IP" },
{ PPP_VJNC, "VJNC IP" },
{ PPP_BRPDU, "BRPDU" },
{ PPP_STII, "STII" },
{ PPP_VINES, "VINES" },
{ PPP_MPLS_UCAST, "MPLS" },
{ PPP_MPLS_MCAST, "MPLS" },
{ PPP_COMP, "Compressed"},
{ PPP_ML, "MLPPP"},
{ PPP_IPV6, "IP6"},
{ PPP_HELLO, "HELLO" },
{ PPP_LUXCOM, "LUXCOM" },
{ PPP_SNS, "SNS" },
{ PPP_IPCP, "IPCP" },
{ PPP_OSICP, "OSICP" },
{ PPP_NSCP, "NSCP" },
{ PPP_DECNETCP, "DECNETCP" },
{ PPP_APPLECP, "APPLECP" },
{ PPP_IPXCP, "IPXCP" },
{ PPP_STIICP, "STIICP" },
{ PPP_VINESCP, "VINESCP" },
{ PPP_IPV6CP, "IP6CP" },
{ PPP_MPLSCP, "MPLSCP" },
{ PPP_LCP, "LCP" },
{ PPP_PAP, "PAP" },
{ PPP_LQM, "LQM" },
{ PPP_CHAP, "CHAP" },
{ PPP_EAP, "EAP" },
{ PPP_SPAP, "SPAP" },
{ PPP_SPAP_OLD, "Old-SPAP" },
{ PPP_BACP, "BACP" },
{ PPP_BAP, "BAP" },
{ PPP_MPCP, "MLPPP-CP" },
{ PPP_CCP, "CCP" },
{ 0, NULL }
};
/* Control Protocols (LCP/IPCP/CCP etc.) Codes defined in RFC 1661 */
#define CPCODES_VEXT 0 /* Vendor-Specific (RFC2153) */
#define CPCODES_CONF_REQ 1 /* Configure-Request */
#define CPCODES_CONF_ACK 2 /* Configure-Ack */
#define CPCODES_CONF_NAK 3 /* Configure-Nak */
#define CPCODES_CONF_REJ 4 /* Configure-Reject */
#define CPCODES_TERM_REQ 5 /* Terminate-Request */
#define CPCODES_TERM_ACK 6 /* Terminate-Ack */
#define CPCODES_CODE_REJ 7 /* Code-Reject */
#define CPCODES_PROT_REJ 8 /* Protocol-Reject (LCP only) */
#define CPCODES_ECHO_REQ 9 /* Echo-Request (LCP only) */
#define CPCODES_ECHO_RPL 10 /* Echo-Reply (LCP only) */
#define CPCODES_DISC_REQ 11 /* Discard-Request (LCP only) */
#define CPCODES_ID 12 /* Identification (LCP only) RFC1570 */
#define CPCODES_TIME_REM 13 /* Time-Remaining (LCP only) RFC1570 */
#define CPCODES_RESET_REQ 14 /* Reset-Request (CCP only) RFC1962 */
#define CPCODES_RESET_REP 15 /* Reset-Reply (CCP only) */
static const struct tok cpcodes[] = {
{CPCODES_VEXT, "Vendor-Extension"}, /* RFC2153 */
{CPCODES_CONF_REQ, "Conf-Request"},
{CPCODES_CONF_ACK, "Conf-Ack"},
{CPCODES_CONF_NAK, "Conf-Nack"},
{CPCODES_CONF_REJ, "Conf-Reject"},
{CPCODES_TERM_REQ, "Term-Request"},
{CPCODES_TERM_ACK, "Term-Ack"},
{CPCODES_CODE_REJ, "Code-Reject"},
{CPCODES_PROT_REJ, "Prot-Reject"},
{CPCODES_ECHO_REQ, "Echo-Request"},
{CPCODES_ECHO_RPL, "Echo-Reply"},
{CPCODES_DISC_REQ, "Disc-Req"},
{CPCODES_ID, "Ident"}, /* RFC1570 */
{CPCODES_TIME_REM, "Time-Rem"}, /* RFC1570 */
{CPCODES_RESET_REQ, "Reset-Req"}, /* RFC1962 */
{CPCODES_RESET_REP, "Reset-Ack"}, /* RFC1962 */
{0, NULL}
};
/* LCP Config Options */
#define LCPOPT_VEXT 0
#define LCPOPT_MRU 1
#define LCPOPT_ACCM 2
#define LCPOPT_AP 3
#define LCPOPT_QP 4
#define LCPOPT_MN 5
#define LCPOPT_DEP6 6
#define LCPOPT_PFC 7
#define LCPOPT_ACFC 8
#define LCPOPT_FCSALT 9
#define LCPOPT_SDP 10
#define LCPOPT_NUMMODE 11
#define LCPOPT_DEP12 12
#define LCPOPT_CBACK 13
#define LCPOPT_DEP14 14
#define LCPOPT_DEP15 15
#define LCPOPT_DEP16 16
#define LCPOPT_MLMRRU 17
#define LCPOPT_MLSSNHF 18
#define LCPOPT_MLED 19
#define LCPOPT_PROP 20
#define LCPOPT_DCEID 21
#define LCPOPT_MPP 22
#define LCPOPT_LD 23
#define LCPOPT_LCPAOPT 24
#define LCPOPT_COBS 25
#define LCPOPT_PE 26
#define LCPOPT_MLHF 27
#define LCPOPT_I18N 28
#define LCPOPT_SDLOS 29
#define LCPOPT_PPPMUX 30
static const char *lcpconfopts[] = {
"Vend-Ext", /* (0) */
"MRU", /* (1) */
"ACCM", /* (2) */
"Auth-Prot", /* (3) */
"Qual-Prot", /* (4) */
"Magic-Num", /* (5) */
"deprecated(6)", /* used to be a Quality Protocol */
"PFC", /* (7) */
"ACFC", /* (8) */
"FCS-Alt", /* (9) */
"SDP", /* (10) */
"Num-Mode", /* (11) */
"deprecated(12)", /* used to be a Multi-Link-Procedure*/
"Call-Back", /* (13) */
"deprecated(14)", /* used to be a Connect-Time */
- "deprecated(15)", /* used to be a Compund-Frames */
+ "deprecated(15)", /* used to be a Compound-Frames */
"deprecated(16)", /* used to be a Nominal-Data-Encap */
"MRRU", /* (17) */
"12-Bit seq #", /* (18) */
"End-Disc", /* (19) */
"Proprietary", /* (20) */
"DCE-Id", /* (21) */
"MP+", /* (22) */
"Link-Disc", /* (23) */
"LCP-Auth-Opt", /* (24) */
"COBS", /* (25) */
"Prefix-elision", /* (26) */
"Multilink-header-Form",/* (27) */
"I18N", /* (28) */
"SDL-over-SONET/SDH", /* (29) */
"PPP-Muxing", /* (30) */
};
#define NUM_LCPOPTS (sizeof(lcpconfopts) / sizeof(lcpconfopts[0]))
/* ECP - to be supported */
/* CCP Config Options */
#define CCPOPT_OUI 0 /* RFC1962 */
#define CCPOPT_PRED1 1 /* RFC1962 */
#define CCPOPT_PRED2 2 /* RFC1962 */
#define CCPOPT_PJUMP 3 /* RFC1962 */
/* 4-15 unassigned */
#define CCPOPT_HPPPC 16 /* RFC1962 */
#define CCPOPT_STACLZS 17 /* RFC1974 */
#define CCPOPT_MPPC 18 /* RFC2118 */
#define CCPOPT_GFZA 19 /* RFC1962 */
#define CCPOPT_V42BIS 20 /* RFC1962 */
#define CCPOPT_BSDCOMP 21 /* RFC1977 */
/* 22 unassigned */
#define CCPOPT_LZSDCP 23 /* RFC1967 */
#define CCPOPT_MVRCA 24 /* RFC1975 */
#define CCPOPT_DEC 25 /* RFC1976 */
#define CCPOPT_DEFLATE 26 /* RFC1979 */
/* 27-254 unassigned */
#define CCPOPT_RESV 255 /* RFC1962 */
static const struct tok ccpconfopts_values[] = {
{ CCPOPT_OUI, "OUI" },
{ CCPOPT_PRED1, "Pred-1" },
{ CCPOPT_PRED2, "Pred-2" },
{ CCPOPT_PJUMP, "Puddle" },
{ CCPOPT_HPPPC, "HP-PPC" },
{ CCPOPT_STACLZS, "Stac-LZS" },
{ CCPOPT_MPPC, "MPPC" },
{ CCPOPT_GFZA, "Gand-FZA" },
{ CCPOPT_V42BIS, "V.42bis" },
{ CCPOPT_BSDCOMP, "BSD-Comp" },
{ CCPOPT_LZSDCP, "LZS-DCP" },
{ CCPOPT_MVRCA, "MVRCA" },
{ CCPOPT_DEC, "DEC" },
{ CCPOPT_DEFLATE, "Deflate" },
{ CCPOPT_RESV, "Reserved"},
{0, NULL}
};
/* BACP Config Options */
#define BACPOPT_FPEER 1 /* RFC2125 */
static const struct tok bacconfopts_values[] = {
{ BACPOPT_FPEER, "Favored-Peer" },
{0, NULL}
};
/* SDCP - to be supported */
/* IPCP Config Options */
#define IPCPOPT_2ADDR 1 /* RFC1172, RFC1332 (deprecated) */
#define IPCPOPT_IPCOMP 2 /* RFC1332 */
#define IPCPOPT_ADDR 3 /* RFC1332 */
#define IPCPOPT_MOBILE4 4 /* RFC2290 */
#define IPCPOPT_PRIDNS 129 /* RFC1877 */
#define IPCPOPT_PRINBNS 130 /* RFC1877 */
#define IPCPOPT_SECDNS 131 /* RFC1877 */
#define IPCPOPT_SECNBNS 132 /* RFC1877 */
static const struct tok ipcpopt_values[] = {
{ IPCPOPT_2ADDR, "IP-Addrs" },
{ IPCPOPT_IPCOMP, "IP-Comp" },
{ IPCPOPT_ADDR, "IP-Addr" },
{ IPCPOPT_MOBILE4, "Home-Addr" },
{ IPCPOPT_PRIDNS, "Pri-DNS" },
{ IPCPOPT_PRINBNS, "Pri-NBNS" },
{ IPCPOPT_SECDNS, "Sec-DNS" },
{ IPCPOPT_SECNBNS, "Sec-NBNS" },
{ 0, NULL }
};
#define IPCPOPT_IPCOMP_HDRCOMP 0x61 /* rfc3544 */
#define IPCPOPT_IPCOMP_MINLEN 14
static const struct tok ipcpopt_compproto_values[] = {
{ PPP_VJC, "VJ-Comp" },
{ IPCPOPT_IPCOMP_HDRCOMP, "IP Header Compression" },
{ 0, NULL }
};
static const struct tok ipcpopt_compproto_subopt_values[] = {
{ 1, "RTP-Compression" },
{ 2, "Enhanced RTP-Compression" },
{ 0, NULL }
};
/* IP6CP Config Options */
#define IP6CP_IFID 1
static const struct tok ip6cpopt_values[] = {
{ IP6CP_IFID, "Interface-ID" },
{ 0, NULL }
};
/* ATCP - to be supported */
/* OSINLCP - to be supported */
/* BVCP - to be supported */
/* BCP - to be supported */
/* IPXCP - to be supported */
/* MPLSCP - to be supported */
/* Auth Algorithms */
/* 0-4 Reserved (RFC1994) */
#define AUTHALG_CHAPMD5 5 /* RFC1994 */
#define AUTHALG_MSCHAP1 128 /* RFC2433 */
#define AUTHALG_MSCHAP2 129 /* RFC2795 */
static const struct tok authalg_values[] = {
{ AUTHALG_CHAPMD5, "MD5" },
{ AUTHALG_MSCHAP1, "MS-CHAPv1" },
{ AUTHALG_MSCHAP2, "MS-CHAPv2" },
{ 0, NULL }
};
/* FCS Alternatives - to be supported */
/* Multilink Endpoint Discriminator (RFC1717) */
#define MEDCLASS_NULL 0 /* Null Class */
#define MEDCLASS_LOCAL 1 /* Locally Assigned */
#define MEDCLASS_IPV4 2 /* Internet Protocol (IPv4) */
#define MEDCLASS_MAC 3 /* IEEE 802.1 global MAC address */
#define MEDCLASS_MNB 4 /* PPP Magic Number Block */
#define MEDCLASS_PSNDN 5 /* Public Switched Network Director Number */
/* PPP LCP Callback */
#define CALLBACK_AUTH 0 /* Location determined by user auth */
#define CALLBACK_DSTR 1 /* Dialing string */
#define CALLBACK_LID 2 /* Location identifier */
#define CALLBACK_E164 3 /* E.164 number */
#define CALLBACK_X500 4 /* X.500 distinguished name */
#define CALLBACK_CBCP 6 /* Location is determined during CBCP nego */
static const struct tok ppp_callback_values[] = {
{ CALLBACK_AUTH, "UserAuth" },
{ CALLBACK_DSTR, "DialString" },
{ CALLBACK_LID, "LocalID" },
{ CALLBACK_E164, "E.164" },
{ CALLBACK_X500, "X.500" },
{ CALLBACK_CBCP, "CBCP" },
{ 0, NULL }
};
/* CHAP */
#define CHAP_CHAL 1
#define CHAP_RESP 2
#define CHAP_SUCC 3
#define CHAP_FAIL 4
static const struct tok chapcode_values[] = {
{ CHAP_CHAL, "Challenge" },
{ CHAP_RESP, "Response" },
{ CHAP_SUCC, "Success" },
{ CHAP_FAIL, "Fail" },
{ 0, NULL}
};
/* PAP */
#define PAP_AREQ 1
#define PAP_AACK 2
#define PAP_ANAK 3
static const struct tok papcode_values[] = {
{ PAP_AREQ, "Auth-Req" },
{ PAP_AACK, "Auth-ACK" },
{ PAP_ANAK, "Auth-NACK" },
{ 0, NULL }
};
/* BAP */
#define BAP_CALLREQ 1
#define BAP_CALLRES 2
#define BAP_CBREQ 3
#define BAP_CBRES 4
#define BAP_LDQREQ 5
#define BAP_LDQRES 6
#define BAP_CSIND 7
#define BAP_CSRES 8
static u_int print_lcp_config_options(netdissect_options *, const u_char *p, u_int);
static u_int print_ipcp_config_options(netdissect_options *, const u_char *p, u_int);
static u_int print_ip6cp_config_options(netdissect_options *, const u_char *p, u_int);
static u_int print_ccp_config_options(netdissect_options *, const u_char *p, u_int);
static u_int print_bacp_config_options(netdissect_options *, const u_char *p, u_int);
static void handle_ppp(netdissect_options *, u_int proto, const u_char *p, u_int length);
/* generic Control Protocol (e.g. LCP, IPCP, CCP, etc.) handler */
static void
handle_ctrl_proto(netdissect_options *ndo,
u_int proto, const u_char *pptr, u_int length)
{
const char *typestr;
u_int code, len;
u_int (*pfunc)(netdissect_options *, const u_char *, u_int);
u_int tlen, advance;
const u_char *tptr;
tptr=pptr;
typestr = tok2str(ppptype2str, "unknown ctrl-proto (0x%04x)", proto);
ND_PRINT("%s, ", typestr);
if (length < 4) /* FIXME weak boundary checking */
goto trunc;
ND_TCHECK_2(tptr);
code = GET_U_1(tptr);
tptr++;
ND_PRINT("%s (0x%02x), id %u, length %u",
tok2str(cpcodes, "Unknown Opcode",code),
code,
GET_U_1(tptr), /* ID */
length + 2);
tptr++;
if (!ndo->ndo_vflag)
return;
len = GET_BE_U_2(tptr);
tptr += 2;
if (len < 4) {
ND_PRINT("\n\tencoded length %u (< 4))", len);
return;
}
if (len > length) {
ND_PRINT("\n\tencoded length %u (> packet length %u))", len, length);
return;
}
length = len;
ND_PRINT("\n\tencoded length %u (=Option(s) length %u)", len, len - 4);
if (length == 4)
return; /* there may be a NULL confreq etc. */
if (ndo->ndo_vflag > 1)
print_unknown_data(ndo, pptr - 2, "\n\t", 6);
switch (code) {
case CPCODES_VEXT:
if (length < 11)
break;
ND_PRINT("\n\t Magic-Num 0x%08x", GET_BE_U_4(tptr));
tptr += 4;
ND_PRINT(" Vendor: %s (%u)",
tok2str(oui_values,"Unknown",GET_BE_U_3(tptr)),
GET_BE_U_3(tptr));
/* XXX: need to decode Kind and Value(s)? */
break;
case CPCODES_CONF_REQ:
case CPCODES_CONF_ACK:
case CPCODES_CONF_NAK:
case CPCODES_CONF_REJ:
tlen = len - 4; /* Code(1), Identifier(1) and Length(2) */
do {
switch (proto) {
case PPP_LCP:
pfunc = print_lcp_config_options;
break;
case PPP_IPCP:
pfunc = print_ipcp_config_options;
break;
case PPP_IPV6CP:
pfunc = print_ip6cp_config_options;
break;
case PPP_CCP:
pfunc = print_ccp_config_options;
break;
case PPP_BACP:
pfunc = print_bacp_config_options;
break;
default:
/*
* No print routine for the options for
* this protocol.
*/
pfunc = NULL;
break;
}
if (pfunc == NULL) /* catch the above null pointer if unknown CP */
break;
if ((advance = (*pfunc)(ndo, tptr, len)) == 0)
break;
if (tlen < advance) {
ND_PRINT(" [remaining options length %u < %u]",
tlen, advance);
nd_print_invalid(ndo);
break;
}
tlen -= advance;
tptr += advance;
} while (tlen != 0);
break;
case CPCODES_TERM_REQ:
case CPCODES_TERM_ACK:
/* XXX: need to decode Data? */
break;
case CPCODES_CODE_REJ:
/* XXX: need to decode Rejected-Packet? */
break;
case CPCODES_PROT_REJ:
if (length < 6)
break;
ND_PRINT("\n\t Rejected %s Protocol (0x%04x)",
tok2str(ppptype2str,"unknown", GET_BE_U_2(tptr)),
GET_BE_U_2(tptr));
/* XXX: need to decode Rejected-Information? - hexdump for now */
if (len > 6) {
ND_PRINT("\n\t Rejected Packet");
print_unknown_data(ndo, tptr + 2, "\n\t ", len - 2);
}
break;
case CPCODES_ECHO_REQ:
case CPCODES_ECHO_RPL:
case CPCODES_DISC_REQ:
if (length < 8)
break;
ND_PRINT("\n\t Magic-Num 0x%08x", GET_BE_U_4(tptr));
/* XXX: need to decode Data? - hexdump for now */
if (len > 8) {
ND_PRINT("\n\t -----trailing data-----");
ND_TCHECK_LEN(tptr + 4, len - 8);
print_unknown_data(ndo, tptr + 4, "\n\t ", len - 8);
}
break;
case CPCODES_ID:
if (length < 8)
break;
ND_PRINT("\n\t Magic-Num 0x%08x", GET_BE_U_4(tptr));
/* RFC 1661 says this is intended to be human readable */
if (len > 8) {
ND_PRINT("\n\t Message\n\t ");
if (nd_printn(ndo, tptr + 4, len - 4, ndo->ndo_snapend))
goto trunc;
}
break;
case CPCODES_TIME_REM:
if (length < 12)
break;
ND_PRINT("\n\t Magic-Num 0x%08x", GET_BE_U_4(tptr));
ND_PRINT(", Seconds-Remaining %us", GET_BE_U_4(tptr + 4));
/* XXX: need to decode Message? */
break;
default:
/* XXX this is dirty but we do not get the
* original pointer passed to the begin
* the PPP packet */
if (ndo->ndo_vflag <= 1)
print_unknown_data(ndo, pptr - 2, "\n\t ", length + 2);
break;
}
return;
trunc:
ND_PRINT("[|%s]", typestr);
}
/* LCP config options */
static u_int
print_lcp_config_options(netdissect_options *ndo,
const u_char *p, u_int length)
{
u_int opt, len;
if (length < 2)
return 0;
ND_TCHECK_2(p);
opt = GET_U_1(p);
len = GET_U_1(p + 1);
if (length < len)
return 0;
if (len < 2) {
if (opt < NUM_LCPOPTS)
ND_PRINT("\n\t %s Option (0x%02x), length %u (length bogus, should be >= 2)",
lcpconfopts[opt], opt, len);
else
ND_PRINT("\n\tunknown LCP option 0x%02x", opt);
return 0;
}
if (opt < NUM_LCPOPTS)
ND_PRINT("\n\t %s Option (0x%02x), length %u", lcpconfopts[opt], opt, len);
else {
ND_PRINT("\n\tunknown LCP option 0x%02x", opt);
return len;
}
switch (opt) {
case LCPOPT_VEXT:
if (len < 6) {
ND_PRINT(" (length bogus, should be >= 6)");
return len;
}
ND_PRINT(": Vendor: %s (%u)",
tok2str(oui_values,"Unknown",GET_BE_U_3(p + 2)),
GET_BE_U_3(p + 2));
#if 0
ND_PRINT(", kind: 0x%02x", GET_U_1(p + 5));
ND_PRINT(", Value: 0x");
for (i = 0; i < len - 6; i++) {
ND_PRINT("%02x", GET_U_1(p + 6 + i));
}
#endif
break;
case LCPOPT_MRU:
if (len != 4) {
ND_PRINT(" (length bogus, should be = 4)");
return len;
}
ND_PRINT(": %u", GET_BE_U_2(p + 2));
break;
case LCPOPT_ACCM:
if (len != 6) {
ND_PRINT(" (length bogus, should be = 6)");
return len;
}
ND_PRINT(": 0x%08x", GET_BE_U_4(p + 2));
break;
case LCPOPT_AP:
if (len < 4) {
ND_PRINT(" (length bogus, should be >= 4)");
return len;
}
ND_PRINT(": %s",
tok2str(ppptype2str, "Unknown Auth Proto (0x04x)", GET_BE_U_2(p + 2)));
switch (GET_BE_U_2(p + 2)) {
case PPP_CHAP:
ND_PRINT(", %s",
tok2str(authalg_values, "Unknown Auth Alg %u", GET_U_1(p + 4)));
break;
case PPP_PAP: /* fall through */
case PPP_EAP:
case PPP_SPAP:
case PPP_SPAP_OLD:
break;
default:
print_unknown_data(ndo, p, "\n\t", len);
}
break;
case LCPOPT_QP:
if (len < 4) {
ND_PRINT(" (length bogus, should be >= 4)");
return 0;
}
if (GET_BE_U_2(p + 2) == PPP_LQM)
ND_PRINT(": LQR");
else
ND_PRINT(": unknown");
break;
case LCPOPT_MN:
if (len != 6) {
ND_PRINT(" (length bogus, should be = 6)");
return 0;
}
ND_PRINT(": 0x%08x", GET_BE_U_4(p + 2));
break;
case LCPOPT_PFC:
break;
case LCPOPT_ACFC:
break;
case LCPOPT_LD:
if (len != 4) {
ND_PRINT(" (length bogus, should be = 4)");
return 0;
}
ND_PRINT(": 0x%04x", GET_BE_U_2(p + 2));
break;
case LCPOPT_CBACK:
if (len < 3) {
ND_PRINT(" (length bogus, should be >= 3)");
return 0;
}
- ND_PRINT(": ");
ND_PRINT(": Callback Operation %s (%u)",
tok2str(ppp_callback_values, "Unknown", GET_U_1(p + 2)),
GET_U_1(p + 2));
break;
case LCPOPT_MLMRRU:
if (len != 4) {
ND_PRINT(" (length bogus, should be = 4)");
return 0;
}
ND_PRINT(": %u", GET_BE_U_2(p + 2));
break;
case LCPOPT_MLED:
if (len < 3) {
ND_PRINT(" (length bogus, should be >= 3)");
return 0;
}
switch (GET_U_1(p + 2)) { /* class */
case MEDCLASS_NULL:
ND_PRINT(": Null");
break;
case MEDCLASS_LOCAL:
ND_PRINT(": Local"); /* XXX */
break;
case MEDCLASS_IPV4:
if (len != 7) {
ND_PRINT(" (length bogus, should be = 7)");
return 0;
}
ND_PRINT(": IPv4 %s", GET_IPADDR_STRING(p + 3));
break;
case MEDCLASS_MAC:
if (len != 9) {
ND_PRINT(" (length bogus, should be = 9)");
return 0;
}
ND_PRINT(": MAC %s", GET_ETHERADDR_STRING(p + 3));
break;
case MEDCLASS_MNB:
ND_PRINT(": Magic-Num-Block"); /* XXX */
break;
case MEDCLASS_PSNDN:
ND_PRINT(": PSNDN"); /* XXX */
break;
default:
ND_PRINT(": Unknown class %u", GET_U_1(p + 2));
break;
}
break;
/* XXX: to be supported */
#if 0
case LCPOPT_DEP6:
case LCPOPT_FCSALT:
case LCPOPT_SDP:
case LCPOPT_NUMMODE:
case LCPOPT_DEP12:
case LCPOPT_DEP14:
case LCPOPT_DEP15:
case LCPOPT_DEP16:
case LCPOPT_MLSSNHF:
case LCPOPT_PROP:
case LCPOPT_DCEID:
case LCPOPT_MPP:
case LCPOPT_LCPAOPT:
case LCPOPT_COBS:
case LCPOPT_PE:
case LCPOPT_MLHF:
case LCPOPT_I18N:
case LCPOPT_SDLOS:
case LCPOPT_PPPMUX:
break;
#endif
default:
/*
* Unknown option; dump it as raw bytes now if we're
* not going to do so below.
*/
if (ndo->ndo_vflag < 2)
print_unknown_data(ndo, p + 2, "\n\t ", len - 2);
break;
}
if (ndo->ndo_vflag > 1)
print_unknown_data(ndo, p + 2, "\n\t ", len - 2); /* exclude TLV header */
return len;
trunc:
ND_PRINT("[|lcp]");
return 0;
}
/* ML-PPP*/
static const struct tok ppp_ml_flag_values[] = {
{ 0x80, "begin" },
{ 0x40, "end" },
{ 0, NULL }
};
static void
handle_mlppp(netdissect_options *ndo,
const u_char *p, u_int length)
{
if (!ndo->ndo_eflag)
ND_PRINT("MLPPP, ");
if (length < 2) {
ND_PRINT("[|mlppp]");
return;
}
if (!ND_TTEST_2(p)) {
ND_PRINT("[|mlppp]");
return;
}
ND_PRINT("seq 0x%03x, Flags [%s], length %u",
(GET_BE_U_2(p))&0x0fff,
/* only support 12-Bit sequence space for now */
bittok2str(ppp_ml_flag_values, "none", GET_U_1(p) & 0xc0),
length);
}
/* CHAP */
static void
handle_chap(netdissect_options *ndo,
const u_char *p, u_int length)
{
u_int code, len;
u_int val_size, name_size, msg_size;
const u_char *p0;
u_int i;
p0 = p;
if (length < 1) {
ND_PRINT("[|chap]");
return;
} else if (length < 4) {
ND_PRINT("[|chap 0x%02x]", GET_U_1(p));
return;
}
code = GET_U_1(p);
ND_PRINT("CHAP, %s (0x%02x)",
tok2str(chapcode_values,"unknown",code),
code);
p++;
ND_PRINT(", id %u", GET_U_1(p)); /* ID */
p++;
len = GET_BE_U_2(p);
p += 2;
/*
* Note that this is a generic CHAP decoding routine. Since we
* don't know which flavor of CHAP (i.e. CHAP-MD5, MS-CHAPv1,
* MS-CHAPv2) is used at this point, we can't decode packet
* specifically to each algorithms. Instead, we simply decode
- * the GCD (Gratest Common Denominator) for all algorithms.
+ * the GCD (Greatest Common Denominator) for all algorithms.
*/
switch (code) {
case CHAP_CHAL:
case CHAP_RESP:
if (length - (p - p0) < 1)
return;
val_size = GET_U_1(p); /* value size */
p++;
if (length - (p - p0) < val_size)
return;
ND_PRINT(", Value ");
for (i = 0; i < val_size; i++) {
ND_PRINT("%02x", GET_U_1(p));
p++;
}
name_size = len - (u_int)(p - p0);
ND_PRINT(", Name ");
for (i = 0; i < name_size; i++) {
fn_print_char(ndo, GET_U_1(p));
p++;
}
break;
case CHAP_SUCC:
case CHAP_FAIL:
msg_size = len - (u_int)(p - p0);
ND_PRINT(", Msg ");
for (i = 0; i< msg_size; i++) {
fn_print_char(ndo, GET_U_1(p));
p++;
}
break;
}
}
/* PAP (see RFC 1334) */
static void
handle_pap(netdissect_options *ndo,
const u_char *p, u_int length)
{
u_int code, len;
u_int peerid_len, passwd_len, msg_len;
const u_char *p0;
u_int i;
p0 = p;
if (length < 1) {
ND_PRINT("[|pap]");
return;
} else if (length < 4) {
ND_PRINT("[|pap 0x%02x]", GET_U_1(p));
return;
}
code = GET_U_1(p);
ND_PRINT("PAP, %s (0x%02x)",
tok2str(papcode_values, "unknown", code),
code);
p++;
ND_PRINT(", id %u", GET_U_1(p)); /* ID */
p++;
len = GET_BE_U_2(p);
p += 2;
if (len > length) {
ND_PRINT(", length %u > packet size", len);
return;
}
length = len;
if (length < (size_t)(p - p0)) {
ND_PRINT(", length %u < PAP header length", length);
return;
}
switch (code) {
case PAP_AREQ:
/* A valid Authenticate-Request is 6 or more octets long. */
if (len < 6)
goto trunc;
if (length - (p - p0) < 1)
return;
peerid_len = GET_U_1(p); /* Peer-ID Length */
p++;
if (length - (p - p0) < peerid_len)
return;
ND_PRINT(", Peer ");
for (i = 0; i < peerid_len; i++) {
fn_print_char(ndo, GET_U_1(p));
p++;
}
if (length - (p - p0) < 1)
return;
passwd_len = GET_U_1(p); /* Password Length */
p++;
if (length - (p - p0) < passwd_len)
return;
ND_PRINT(", Name ");
for (i = 0; i < passwd_len; i++) {
fn_print_char(ndo, GET_U_1(p));
p++;
}
break;
case PAP_AACK:
case PAP_ANAK:
/* Although some implementations ignore truncation at
* this point and at least one generates a truncated
* packet, RFC 1334 section 2.2.2 clearly states that
* both AACK and ANAK are at least 5 bytes long.
*/
if (len < 5)
goto trunc;
if (length - (p - p0) < 1)
return;
msg_len = GET_U_1(p); /* Msg-Length */
p++;
if (length - (p - p0) < msg_len)
return;
ND_PRINT(", Msg ");
for (i = 0; i< msg_len; i++) {
fn_print_char(ndo, GET_U_1(p));
p++;
}
break;
}
return;
trunc:
ND_PRINT("[|pap]");
}
/* BAP */
static void
handle_bap(netdissect_options *ndo _U_,
const u_char *p _U_, u_int length _U_)
{
/* XXX: to be supported!! */
}
/* IPCP config options */
static u_int
print_ipcp_config_options(netdissect_options *ndo,
const u_char *p, u_int length)
{
u_int opt, len;
u_int compproto, ipcomp_subopttotallen, ipcomp_subopt, ipcomp_suboptlen;
if (length < 2)
return 0;
ND_TCHECK_2(p);
opt = GET_U_1(p);
len = GET_U_1(p + 1);
if (length < len)
return 0;
if (len < 2) {
ND_PRINT("\n\t %s Option (0x%02x), length %u (length bogus, should be >= 2)",
tok2str(ipcpopt_values,"unknown",opt),
opt,
len);
return 0;
}
ND_PRINT("\n\t %s Option (0x%02x), length %u",
tok2str(ipcpopt_values,"unknown",opt),
opt,
len);
switch (opt) {
case IPCPOPT_2ADDR: /* deprecated */
if (len != 10) {
ND_PRINT(" (length bogus, should be = 10)");
return len;
}
ND_PRINT(": src %s, dst %s",
GET_IPADDR_STRING(p + 2),
GET_IPADDR_STRING(p + 6));
break;
case IPCPOPT_IPCOMP:
if (len < 4) {
ND_PRINT(" (length bogus, should be >= 4)");
return 0;
}
compproto = GET_BE_U_2(p + 2);
ND_PRINT(": %s (0x%02x):",
tok2str(ipcpopt_compproto_values, "Unknown", compproto),
compproto);
switch (compproto) {
case PPP_VJC:
/* XXX: VJ-Comp parameters should be decoded */
break;
case IPCPOPT_IPCOMP_HDRCOMP:
if (len < IPCPOPT_IPCOMP_MINLEN) {
ND_PRINT(" (length bogus, should be >= %u)",
IPCPOPT_IPCOMP_MINLEN);
return 0;
}
ND_TCHECK_LEN(p + 2, IPCPOPT_IPCOMP_MINLEN);
ND_PRINT("\n\t TCP Space %u, non-TCP Space %u"
", maxPeriod %u, maxTime %u, maxHdr %u",
GET_BE_U_2(p + 4),
GET_BE_U_2(p + 6),
GET_BE_U_2(p + 8),
GET_BE_U_2(p + 10),
GET_BE_U_2(p + 12));
/* suboptions present ? */
if (len > IPCPOPT_IPCOMP_MINLEN) {
ipcomp_subopttotallen = len - IPCPOPT_IPCOMP_MINLEN;
p += IPCPOPT_IPCOMP_MINLEN;
ND_PRINT("\n\t Suboptions, length %u", ipcomp_subopttotallen);
while (ipcomp_subopttotallen >= 2) {
ND_TCHECK_2(p);
ipcomp_subopt = GET_U_1(p);
ipcomp_suboptlen = GET_U_1(p + 1);
/* sanity check */
if (ipcomp_subopt == 0 ||
ipcomp_suboptlen == 0 )
break;
/* XXX: just display the suboptions for now */
ND_PRINT("\n\t\t%s Suboption #%u, length %u",
tok2str(ipcpopt_compproto_subopt_values,
"Unknown",
ipcomp_subopt),
ipcomp_subopt,
ipcomp_suboptlen);
if (ipcomp_subopttotallen < ipcomp_suboptlen) {
ND_PRINT(" [remaining suboptions length %u < %u]",
ipcomp_subopttotallen, ipcomp_suboptlen);
nd_print_invalid(ndo);
break;
}
ipcomp_subopttotallen -= ipcomp_suboptlen;
p += ipcomp_suboptlen;
}
}
break;
default:
break;
}
break;
case IPCPOPT_ADDR: /* those options share the same format - fall through */
case IPCPOPT_MOBILE4:
case IPCPOPT_PRIDNS:
case IPCPOPT_PRINBNS:
case IPCPOPT_SECDNS:
case IPCPOPT_SECNBNS:
if (len != 6) {
ND_PRINT(" (length bogus, should be = 6)");
return 0;
}
ND_PRINT(": %s", GET_IPADDR_STRING(p + 2));
break;
default:
/*
* Unknown option; dump it as raw bytes now if we're
* not going to do so below.
*/
if (ndo->ndo_vflag < 2)
print_unknown_data(ndo, p + 2, "\n\t ", len - 2);
break;
}
- if (ndo->ndo_vflag > 1)
+ if (ndo->ndo_vflag > 1 && ND_TTEST_LEN(p + 2, len - 2))
print_unknown_data(ndo, p + 2, "\n\t ", len - 2); /* exclude TLV header */
return len;
trunc:
ND_PRINT("[|ipcp]");
return 0;
}
/* IP6CP config options */
static u_int
print_ip6cp_config_options(netdissect_options *ndo,
const u_char *p, u_int length)
{
u_int opt, len;
if (length < 2)
return 0;
ND_TCHECK_2(p);
opt = GET_U_1(p);
len = GET_U_1(p + 1);
if (length < len)
return 0;
if (len < 2) {
ND_PRINT("\n\t %s Option (0x%02x), length %u (length bogus, should be >= 2)",
tok2str(ip6cpopt_values,"unknown",opt),
opt,
len);
return 0;
}
ND_PRINT("\n\t %s Option (0x%02x), length %u",
tok2str(ip6cpopt_values,"unknown",opt),
opt,
len);
switch (opt) {
case IP6CP_IFID:
if (len != 10) {
ND_PRINT(" (length bogus, should be = 10)");
return len;
}
ND_TCHECK_8(p + 2);
ND_PRINT(": %04x:%04x:%04x:%04x",
GET_BE_U_2(p + 2),
GET_BE_U_2(p + 4),
GET_BE_U_2(p + 6),
GET_BE_U_2(p + 8));
break;
default:
/*
* Unknown option; dump it as raw bytes now if we're
* not going to do so below.
*/
if (ndo->ndo_vflag < 2)
print_unknown_data(ndo, p + 2, "\n\t ", len - 2);
break;
}
if (ndo->ndo_vflag > 1)
print_unknown_data(ndo, p + 2, "\n\t ", len - 2); /* exclude TLV header */
return len;
trunc:
ND_PRINT("[|ip6cp]");
return 0;
}
/* CCP config options */
static u_int
print_ccp_config_options(netdissect_options *ndo,
const u_char *p, u_int length)
{
u_int opt, len;
if (length < 2)
return 0;
ND_TCHECK_2(p);
opt = GET_U_1(p);
len = GET_U_1(p + 1);
if (length < len)
return 0;
if (len < 2) {
ND_PRINT("\n\t %s Option (0x%02x), length %u (length bogus, should be >= 2)",
tok2str(ccpconfopts_values, "Unknown", opt),
opt,
len);
return 0;
}
ND_PRINT("\n\t %s Option (0x%02x), length %u",
tok2str(ccpconfopts_values, "Unknown", opt),
opt,
len);
switch (opt) {
case CCPOPT_BSDCOMP:
if (len < 3) {
ND_PRINT(" (length bogus, should be >= 3)");
return len;
}
ND_PRINT(": Version: %u, Dictionary Bits: %u",
GET_U_1(p + 2) >> 5,
GET_U_1(p + 2) & 0x1f);
break;
case CCPOPT_MVRCA:
if (len < 4) {
ND_PRINT(" (length bogus, should be >= 4)");
return len;
}
ND_PRINT(": Features: %u, PxP: %s, History: %u, #CTX-ID: %u",
(GET_U_1(p + 2) & 0xc0) >> 6,
(GET_U_1(p + 2) & 0x20) ? "Enabled" : "Disabled",
GET_U_1(p + 2) & 0x1f,
GET_U_1(p + 3));
break;
case CCPOPT_DEFLATE:
if (len < 4) {
ND_PRINT(" (length bogus, should be >= 4)");
return len;
}
ND_PRINT(": Window: %uK, Method: %s (0x%x), MBZ: %u, CHK: %u",
(GET_U_1(p + 2) & 0xf0) >> 4,
((GET_U_1(p + 2) & 0x0f) == 8) ? "zlib" : "unknown",
GET_U_1(p + 2) & 0x0f,
(GET_U_1(p + 3) & 0xfc) >> 2,
GET_U_1(p + 3) & 0x03);
break;
/* XXX: to be supported */
#if 0
case CCPOPT_OUI:
case CCPOPT_PRED1:
case CCPOPT_PRED2:
case CCPOPT_PJUMP:
case CCPOPT_HPPPC:
case CCPOPT_STACLZS:
case CCPOPT_MPPC:
case CCPOPT_GFZA:
case CCPOPT_V42BIS:
case CCPOPT_LZSDCP:
case CCPOPT_DEC:
case CCPOPT_RESV:
break;
#endif
default:
/*
* Unknown option; dump it as raw bytes now if we're
* not going to do so below.
*/
if (ndo->ndo_vflag < 2)
print_unknown_data(ndo, p + 2, "\n\t ", len - 2);
break;
}
if (ndo->ndo_vflag > 1)
print_unknown_data(ndo, p + 2, "\n\t ", len - 2); /* exclude TLV header */
return len;
trunc:
ND_PRINT("[|ccp]");
return 0;
}
/* BACP config options */
static u_int
print_bacp_config_options(netdissect_options *ndo,
const u_char *p, u_int length)
{
u_int opt, len;
if (length < 2)
return 0;
ND_TCHECK_2(p);
opt = GET_U_1(p);
len = GET_U_1(p + 1);
if (length < len)
return 0;
if (len < 2) {
ND_PRINT("\n\t %s Option (0x%02x), length %u (length bogus, should be >= 2)",
tok2str(bacconfopts_values, "Unknown", opt),
opt,
len);
return 0;
}
ND_PRINT("\n\t %s Option (0x%02x), length %u",
tok2str(bacconfopts_values, "Unknown", opt),
opt,
len);
switch (opt) {
case BACPOPT_FPEER:
if (len != 6) {
ND_PRINT(" (length bogus, should be = 6)");
return len;
}
ND_PRINT(": Magic-Num 0x%08x", GET_BE_U_4(p + 2));
break;
default:
/*
* Unknown option; dump it as raw bytes now if we're
* not going to do so below.
*/
if (ndo->ndo_vflag < 2)
print_unknown_data(ndo, p + 2, "\n\t ", len - 2);
break;
}
if (ndo->ndo_vflag > 1)
print_unknown_data(ndo, p + 2, "\n\t ", len - 2); /* exclude TLV header */
return len;
trunc:
ND_PRINT("[|bacp]");
return 0;
}
/*
* Un-escape RFC 1662 PPP in HDLC-like framing, with octet escapes.
* The length argument is the on-the-wire length, not the captured
* length; we can only un-escape the captured part.
*/
static void
ppp_hdlc(netdissect_options *ndo,
const u_char *p, u_int length)
{
u_int caplen = ND_BYTES_AVAILABLE_AFTER(p);
u_char *b, *t, c;
const u_char *s;
u_int i, proto;
if (caplen == 0)
return;
if (length == 0)
return;
b = (u_char *)malloc(caplen);
if (b == NULL) {
(*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC,
"%s: malloc", __func__);
}
/*
* Unescape all the data into a temporary, private, buffer.
* Do this so that we don't overwrite the original packet
* contents.
*/
for (s = p, t = b, i = caplen; i != 0; i--) {
c = GET_U_1(s);
s++;
if (c == 0x7d) {
if (i <= 1)
break;
i--;
c = GET_U_1(s) ^ 0x20;
s++;
}
*t++ = c;
}
/*
* Switch to the output buffer for dissection, and save it
* on the buffer stack so it can be freed; our caller must
* pop it when done.
*/
if (!nd_push_buffer(ndo, b, b, (u_int)(t - b))) {
free(b);
(*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC,
"%s: can't push buffer on buffer stack", __func__);
}
length = ND_BYTES_AVAILABLE_AFTER(b);
/* now lets guess about the payload codepoint format */
if (length < 1)
goto trunc;
proto = GET_U_1(b); /* start with a one-octet codepoint guess */
switch (proto) {
case PPP_IP:
ip_print(ndo, b + 1, length - 1);
goto cleanup;
case PPP_IPV6:
ip6_print(ndo, b + 1, length - 1);
goto cleanup;
default: /* no luck - try next guess */
break;
}
if (length < 2)
goto trunc;
proto = GET_BE_U_2(b); /* next guess - load two octets */
switch (proto) {
case (PPP_ADDRESS << 8 | PPP_CONTROL): /* looks like a PPP frame */
if (length < 4)
goto trunc;
proto = GET_BE_U_2(b + 2); /* load the PPP proto-id */
if ((proto & 0xff00) == 0x7e00)
ND_PRINT("(protocol 0x%04x invalid)", proto);
else
handle_ppp(ndo, proto, b + 4, length - 4);
break;
default: /* last guess - proto must be a PPP proto-id */
if ((proto & 0xff00) == 0x7e00)
ND_PRINT("(protocol 0x%04x invalid)", proto);
else
handle_ppp(ndo, proto, b + 2, length - 2);
break;
}
cleanup:
nd_pop_packet_info(ndo);
return;
trunc:
nd_pop_packet_info(ndo);
nd_print_trunc(ndo);
}
/* PPP */
static void
handle_ppp(netdissect_options *ndo,
u_int proto, const u_char *p, u_int length)
{
if ((proto & 0xff00) == 0x7e00) { /* is this an escape code ? */
ppp_hdlc(ndo, p - 1, length);
return;
}
switch (proto) {
case PPP_LCP: /* fall through */
case PPP_IPCP:
case PPP_OSICP:
case PPP_MPLSCP:
case PPP_IPV6CP:
case PPP_CCP:
case PPP_BACP:
handle_ctrl_proto(ndo, proto, p, length);
break;
case PPP_ML:
handle_mlppp(ndo, p, length);
break;
case PPP_CHAP:
handle_chap(ndo, p, length);
break;
case PPP_PAP:
handle_pap(ndo, p, length);
break;
case PPP_BAP: /* XXX: not yet completed */
handle_bap(ndo, p, length);
break;
case ETHERTYPE_IP: /*XXX*/
case PPP_VJNC:
case PPP_IP:
ip_print(ndo, p, length);
break;
case ETHERTYPE_IPV6: /*XXX*/
case PPP_IPV6:
ip6_print(ndo, p, length);
break;
case ETHERTYPE_IPX: /*XXX*/
case PPP_IPX:
ipx_print(ndo, p, length);
break;
case PPP_OSI:
isoclns_print(ndo, p, length);
break;
case PPP_MPLS_UCAST:
case PPP_MPLS_MCAST:
mpls_print(ndo, p, length);
break;
case PPP_COMP:
ND_PRINT("compressed PPP data");
break;
default:
ND_PRINT("%s ", tok2str(ppptype2str, "unknown PPP protocol (0x%04x)", proto));
print_unknown_data(ndo, p, "\n\t", length);
break;
}
}
/* Standard PPP printer */
u_int
ppp_print(netdissect_options *ndo,
const u_char *p, u_int length)
{
u_int proto,ppp_header;
u_int olen = length; /* _o_riginal length */
u_int hdr_len = 0;
ndo->ndo_protocol = "ppp";
/*
* Here, we assume that p points to the Address and Control
* field (if they present).
*/
if (length < 2)
goto trunc;
ppp_header = GET_BE_U_2(p);
switch(ppp_header) {
case (PPP_PPPD_IN << 8 | PPP_CONTROL):
if (ndo->ndo_eflag) ND_PRINT("In ");
p += 2;
length -= 2;
hdr_len += 2;
break;
case (PPP_PPPD_OUT << 8 | PPP_CONTROL):
if (ndo->ndo_eflag) ND_PRINT("Out ");
p += 2;
length -= 2;
hdr_len += 2;
break;
case (PPP_ADDRESS << 8 | PPP_CONTROL):
p += 2; /* ACFC not used */
length -= 2;
hdr_len += 2;
break;
default:
break;
}
if (length < 2)
goto trunc;
if (GET_U_1(p) % 2) {
proto = GET_U_1(p); /* PFC is used */
p++;
length--;
hdr_len++;
} else {
proto = GET_BE_U_2(p);
p += 2;
length -= 2;
hdr_len += 2;
}
if (ndo->ndo_eflag) {
const char *typestr;
typestr = tok2str(ppptype2str, "unknown", proto);
ND_PRINT("%s (0x%04x), length %u",
typestr,
proto,
olen);
if (*typestr == 'u') /* "unknown" */
return hdr_len;
ND_PRINT(": ");
}
handle_ppp(ndo, proto, p, length);
return (hdr_len);
trunc:
nd_print_trunc(ndo);
return (0);
}
/* PPP I/F printer */
void
ppp_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h, const u_char *p)
{
u_int length = h->len;
u_int caplen = h->caplen;
ndo->ndo_protocol = "ppp";
if (caplen < PPP_HDRLEN) {
nd_print_trunc(ndo);
ndo->ndo_ll_hdr_len += caplen;
return;
}
ndo->ndo_ll_hdr_len += PPP_HDRLEN;
#if 0
/*
* XXX: seems to assume that there are 2 octets prepended to an
* actual PPP frame. The 1st octet looks like Input/Output flag
* while 2nd octet is unknown, at least to me
* (mshindo@mshindo.net).
*
* That was what the original tcpdump code did.
*
* FreeBSD's "if_ppp.c" *does* set the first octet to 1 for outbound
* packets and 0 for inbound packets - but only if the
* protocol field has the 0x8000 bit set (i.e., it's a network
* control protocol); it does so before running the packet through
* "bpf_filter" to see if it should be discarded, and to see
* if we should update the time we sent the most recent packet...
*
* ...but it puts the original address field back after doing
* so.
*
* NetBSD's "if_ppp.c" doesn't set the first octet in that fashion.
*
* I don't know if any PPP implementation handed up to a BPF
* device packets with the first octet being 1 for outbound and
* 0 for inbound packets, so I (guy@alum.mit.edu) don't know
* whether that ever needs to be checked or not.
*
* Note that NetBSD has a DLT_PPP_SERIAL, which it uses for PPP,
* and its tcpdump appears to assume that the frame always
* begins with an address field and a control field, and that
* the address field might be 0x0f or 0x8f, for Cisco
* point-to-point with HDLC framing as per section 4.3.1 of RFC
* 1547, as well as 0xff, for PPP in HDLC-like framing as per
* RFC 1662.
*
* (Is the Cisco framing in question what DLT_C_HDLC, in
* BSD/OS, is?)
*/
if (ndo->ndo_eflag)
ND_PRINT("%c %4d %02x ", GET_U_1(p) ? 'O' : 'I',
length, GET_U_1(p + 1));
#endif
ppp_print(ndo, p, length);
}
/*
* PPP I/F printer to use if we know that RFC 1662-style PPP in HDLC-like
* framing, or Cisco PPP with HDLC framing as per section 4.3.1 of RFC 1547,
* is being used (i.e., we don't check for PPP_ADDRESS and PPP_CONTROL,
* discard them *if* those are the first two octets, and parse the remaining
* packet as a PPP packet, as "ppp_print()" does).
*
* This handles, for example, DLT_PPP_SERIAL in NetBSD.
*/
void
ppp_hdlc_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h, const u_char *p)
{
u_int length = h->len;
u_int caplen = h->caplen;
u_int proto;
u_int hdrlen = 0;
ndo->ndo_protocol = "ppp_hdlc";
if (caplen < 2) {
nd_print_trunc(ndo);
ndo->ndo_ll_hdr_len += caplen;
return;
}
switch (GET_U_1(p)) {
case PPP_ADDRESS:
if (caplen < 4) {
nd_print_trunc(ndo);
ndo->ndo_ll_hdr_len += caplen;
return;
}
if (ndo->ndo_eflag)
ND_PRINT("%02x %02x %u ", GET_U_1(p),
GET_U_1(p + 1), length);
p += 2;
length -= 2;
hdrlen += 2;
proto = GET_BE_U_2(p);
p += 2;
length -= 2;
hdrlen += 2;
ND_PRINT("%s: ", tok2str(ppptype2str, "unknown PPP protocol (0x%04x)", proto));
handle_ppp(ndo, proto, p, length);
break;
case CHDLC_UNICAST:
case CHDLC_BCAST:
chdlc_if_print(ndo, h, p);
return;
default:
if (caplen < 4) {
nd_print_trunc(ndo);
ndo->ndo_ll_hdr_len += caplen;
return;
}
if (ndo->ndo_eflag)
ND_PRINT("%02x %02x %u ", GET_U_1(p),
GET_U_1(p + 1), length);
p += 2;
hdrlen += 2;
/*
* XXX - NetBSD's "ppp_netbsd_serial_if_print()" treats
* the next two octets as an Ethernet type; does that
* ever happen?
*/
ND_PRINT("unknown addr %02x; ctrl %02x", GET_U_1(p),
GET_U_1(p + 1));
break;
}
ndo->ndo_ll_hdr_len += hdrlen;
}
#define PPP_BSDI_HDRLEN 24
/* BSD/OS specific PPP printer */
void
ppp_bsdos_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h _U_, const u_char *p _U_)
{
u_int hdrlength;
#ifdef __bsdi__
u_int length = h->len;
u_int caplen = h->caplen;
uint16_t ptype;
uint8_t llhl;
const u_char *q;
u_int i;
ndo->ndo_protocol = "ppp_bsdos";
if (caplen < PPP_BSDI_HDRLEN) {
nd_print_trunc(ndo);
ndo->ndo_ll_hdr_len += caplen;
return;
}
hdrlength = 0;
#if 0
if (GET_U_1(p) == PPP_ADDRESS &&
GET_U_1(p + 1) == PPP_CONTROL) {
if (ndo->ndo_eflag)
ND_PRINT("%02x %02x ", GET_U_1(p),
GET_U_1(p + 1));
p += 2;
hdrlength = 2;
}
if (ndo->ndo_eflag)
ND_PRINT("%u ", length);
/* Retrieve the protocol type */
if (GET_U_1(p) & 01) {
/* Compressed protocol field */
ptype = GET_U_1(p);
if (ndo->ndo_eflag)
ND_PRINT("%02x ", ptype);
p++;
hdrlength += 1;
} else {
/* Un-compressed protocol field */
ptype = GET_BE_U_2(p);
if (ndo->ndo_eflag)
ND_PRINT("%04x ", ptype);
p += 2;
hdrlength += 2;
}
#else
ptype = 0; /*XXX*/
if (ndo->ndo_eflag)
ND_PRINT("%c ", GET_U_1(p + SLC_DIR) ? 'O' : 'I');
llhl = GET_U_1(p + SLC_LLHL);
if (llhl) {
/* link level header */
struct ppp_header *ph;
q = p + SLC_BPFHDRLEN;
ph = (struct ppp_header *)q;
if (ph->phdr_addr == PPP_ADDRESS
&& ph->phdr_ctl == PPP_CONTROL) {
if (ndo->ndo_eflag)
ND_PRINT("%02x %02x ", GET_U_1(q),
GET_U_1(q + 1));
ptype = GET_BE_U_2(&ph->phdr_type);
if (ndo->ndo_eflag && (ptype == PPP_VJC || ptype == PPP_VJNC)) {
ND_PRINT("%s ", tok2str(ppptype2str,
"proto-#%u", ptype));
}
} else {
if (ndo->ndo_eflag) {
ND_PRINT("LLH=[");
for (i = 0; i < llhl; i++)
ND_PRINT("%02x", GET_U_1(q + i));
ND_PRINT("] ");
}
}
}
if (ndo->ndo_eflag)
ND_PRINT("%u ", length);
if (GET_U_1(p + SLC_CHL)) {
q = p + SLC_BPFHDRLEN + llhl;
switch (ptype) {
case PPP_VJC:
ptype = vjc_print(ndo, q, ptype);
hdrlength = PPP_BSDI_HDRLEN;
p += hdrlength;
switch (ptype) {
case PPP_IP:
ip_print(ndo, p, length);
break;
case PPP_IPV6:
ip6_print(ndo, p, length);
break;
case PPP_MPLS_UCAST:
case PPP_MPLS_MCAST:
mpls_print(ndo, p, length);
break;
}
goto printx;
case PPP_VJNC:
ptype = vjc_print(ndo, q, ptype);
hdrlength = PPP_BSDI_HDRLEN;
p += hdrlength;
switch (ptype) {
case PPP_IP:
ip_print(ndo, p, length);
break;
case PPP_IPV6:
ip6_print(ndo, p, length);
break;
case PPP_MPLS_UCAST:
case PPP_MPLS_MCAST:
mpls_print(ndo, p, length);
break;
}
goto printx;
default:
if (ndo->ndo_eflag) {
ND_PRINT("CH=[");
for (i = 0; i < llhl; i++)
ND_PRINT("%02x",
GET_U_1(q + i));
ND_PRINT("] ");
}
break;
}
}
hdrlength = PPP_BSDI_HDRLEN;
#endif
length -= hdrlength;
p += hdrlength;
switch (ptype) {
case PPP_IP:
ip_print(p, length);
break;
case PPP_IPV6:
ip6_print(ndo, p, length);
break;
case PPP_MPLS_UCAST:
case PPP_MPLS_MCAST:
mpls_print(ndo, p, length);
break;
default:
ND_PRINT("%s ", tok2str(ppptype2str, "unknown PPP protocol (0x%04x)", ptype));
}
printx:
#else /* __bsdi */
hdrlength = 0;
#endif /* __bsdi__ */
ndo->ndo_ll_hdr_len += hdrlength;
}
diff --git a/contrib/tcpdump/print-pppoe.c b/contrib/tcpdump/print-pppoe.c
index 65518dff16d9..9649b15ffe3a 100644
--- a/contrib/tcpdump/print-pppoe.c
+++ b/contrib/tcpdump/print-pppoe.c
@@ -1,206 +1,204 @@
/*
* Copyright (c) 1988, 1989, 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.
*
* Original code by Greg Stark <gsstark@mit.edu>
*/
/* \summary: PPP-over-Ethernet (PPPoE) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect-ctype.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
/* Codes */
enum {
PPPOE_PADI = 0x09,
PPPOE_PADO = 0x07,
PPPOE_PADR = 0x19,
PPPOE_PADS = 0x65,
PPPOE_PADT = 0xa7
};
static const struct tok pppoecode2str[] = {
{ PPPOE_PADI, "PADI" },
{ PPPOE_PADO, "PADO" },
{ PPPOE_PADR, "PADR" },
{ PPPOE_PADS, "PADS" },
{ PPPOE_PADT, "PADT" },
{ 0, "" }, /* PPP Data */
{ 0, NULL }
};
/* Tags */
enum {
PPPOE_EOL = 0,
PPPOE_SERVICE_NAME = 0x0101,
PPPOE_AC_NAME = 0x0102,
PPPOE_HOST_UNIQ = 0x0103,
PPPOE_AC_COOKIE = 0x0104,
PPPOE_VENDOR = 0x0105,
PPPOE_RELAY_SID = 0x0110,
PPPOE_MAX_PAYLOAD = 0x0120,
PPPOE_SERVICE_NAME_ERROR = 0x0201,
PPPOE_AC_SYSTEM_ERROR = 0x0202,
PPPOE_GENERIC_ERROR = 0x0203
};
static const struct tok pppoetag2str[] = {
{ PPPOE_EOL, "EOL" },
{ PPPOE_SERVICE_NAME, "Service-Name" },
{ PPPOE_AC_NAME, "AC-Name" },
{ PPPOE_HOST_UNIQ, "Host-Uniq" },
{ PPPOE_AC_COOKIE, "AC-Cookie" },
{ PPPOE_VENDOR, "Vendor-Specific" },
{ PPPOE_RELAY_SID, "Relay-Session-ID" },
{ PPPOE_MAX_PAYLOAD, "PPP-Max-Payload" },
{ PPPOE_SERVICE_NAME_ERROR, "Service-Name-Error" },
{ PPPOE_AC_SYSTEM_ERROR, "AC-System-Error" },
{ PPPOE_GENERIC_ERROR, "Generic-Error" },
{ 0, NULL }
};
#define PPPOE_HDRLEN 6
#define MAXTAGPRINT 80
void
pppoe_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
{
ndo->ndo_protocol = "pppoe";
ndo->ndo_ll_hdr_len += pppoe_print(ndo, p, h->len);
}
u_int
pppoe_print(netdissect_options *ndo, const u_char *bp, u_int length)
{
uint16_t pppoe_ver, pppoe_type, pppoe_code, pppoe_sessionid;
u_int pppoe_length;
const u_char *pppoe_packet, *pppoe_payload;
ndo->ndo_protocol = "pppoe";
if (length < PPPOE_HDRLEN) {
ND_PRINT(" (length %u < %u)", length, PPPOE_HDRLEN);
goto invalid;
}
length -= PPPOE_HDRLEN;
pppoe_packet = bp;
ND_TCHECK_LEN(pppoe_packet, PPPOE_HDRLEN);
pppoe_ver = (GET_U_1(pppoe_packet) & 0xF0) >> 4;
pppoe_type = (GET_U_1(pppoe_packet) & 0x0F);
pppoe_code = GET_U_1(pppoe_packet + 1);
pppoe_sessionid = GET_BE_U_2(pppoe_packet + 2);
pppoe_length = GET_BE_U_2(pppoe_packet + 4);
pppoe_payload = pppoe_packet + PPPOE_HDRLEN;
if (pppoe_ver != 1) {
ND_PRINT(" [ver %u]",pppoe_ver);
}
if (pppoe_type != 1) {
ND_PRINT(" [type %u]",pppoe_type);
}
ND_PRINT("PPPoE %s", tok2str(pppoecode2str, "PAD-%x", pppoe_code));
if (pppoe_code == PPPOE_PADI && pppoe_length > 1484 - PPPOE_HDRLEN) {
ND_PRINT(" [len %u!]",pppoe_length);
}
if (pppoe_length > length) {
ND_PRINT(" [len %u > %u!]", pppoe_length, length);
pppoe_length = length;
}
if (pppoe_sessionid) {
ND_PRINT(" [ses 0x%x]", pppoe_sessionid);
}
if (pppoe_code) {
/* PPP session packets don't contain tags */
u_short tag_type = 0xffff, tag_len;
const u_char *p = pppoe_payload;
/*
* loop invariant:
* p points to current tag,
* tag_type is previous tag or 0xffff for first iteration
*/
while (tag_type && p < pppoe_payload + pppoe_length) {
tag_type = GET_BE_U_2(p);
tag_len = GET_BE_U_2(p + 2);
p += 4;
/* p points to tag_value */
if (tag_len) {
unsigned ascii_count = 0, garbage_count = 0;
const u_char *v;
char tag_str[MAXTAGPRINT];
unsigned tag_str_len = 0;
/* TODO print UTF-8 decoded text */
ND_TCHECK_LEN(p, tag_len);
for (v = p; v < p + tag_len && tag_str_len < MAXTAGPRINT-1; v++)
if (ND_ASCII_ISPRINT(GET_U_1(v))) {
tag_str[tag_str_len++] = GET_U_1(v);
ascii_count++;
} else {
tag_str[tag_str_len++] = '.';
garbage_count++;
}
tag_str[tag_str_len] = 0;
if (ascii_count > garbage_count) {
ND_PRINT(" [%s \"%*.*s\"]",
tok2str(pppoetag2str, "TAG-0x%x", tag_type),
(int)tag_str_len,
(int)tag_str_len,
tag_str);
} else {
/* Print hex, not fast to abuse printf but this doesn't get used much */
ND_PRINT(" [%s 0x", tok2str(pppoetag2str, "TAG-0x%x", tag_type));
for (v=p; v<p+tag_len; v++) {
ND_PRINT("%02X", GET_U_1(v));
}
ND_PRINT("]");
}
} else
ND_PRINT(" [%s]", tok2str(pppoetag2str,
"TAG-0x%x", tag_type));
p += tag_len;
/* p points to next tag */
}
return PPPOE_HDRLEN;
} else {
/* PPPoE data */
ND_PRINT(" ");
return (PPPOE_HDRLEN + ppp_print(ndo, pppoe_payload, pppoe_length));
}
/* NOTREACHED */
invalid:
nd_print_invalid(ndo);
return 0;
}
diff --git a/contrib/tcpdump/print-pptp.c b/contrib/tcpdump/print-pptp.c
index e8e328bbe3da..8666e505bbc7 100644
--- a/contrib/tcpdump/print-pptp.c
+++ b/contrib/tcpdump/print-pptp.c
@@ -1,871 +1,869 @@
/*
* Copyright (c) 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.
*
* PPTP support contributed by Motonori Shindo (mshindo@mshindo.net)
*/
/* \summary: Point-to-Point Tunnelling Protocol (PPTP) printer */
/* specification: RFC 2637 */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "extract.h"
#define PPTP_MSG_TYPE_CTRL 1 /* Control Message */
#define PPTP_MSG_TYPE_MGMT 2 /* Management Message (currently not used */
#define PPTP_MAGIC_COOKIE 0x1a2b3c4d /* for sanity check */
#define PPTP_CTRL_MSG_TYPE_SCCRQ 1
#define PPTP_CTRL_MSG_TYPE_SCCRP 2
#define PPTP_CTRL_MSG_TYPE_StopCCRQ 3
#define PPTP_CTRL_MSG_TYPE_StopCCRP 4
#define PPTP_CTRL_MSG_TYPE_ECHORQ 5
#define PPTP_CTRL_MSG_TYPE_ECHORP 6
#define PPTP_CTRL_MSG_TYPE_OCRQ 7
#define PPTP_CTRL_MSG_TYPE_OCRP 8
#define PPTP_CTRL_MSG_TYPE_ICRQ 9
#define PPTP_CTRL_MSG_TYPE_ICRP 10
#define PPTP_CTRL_MSG_TYPE_ICCN 11
#define PPTP_CTRL_MSG_TYPE_CCRQ 12
#define PPTP_CTRL_MSG_TYPE_CDN 13
#define PPTP_CTRL_MSG_TYPE_WEN 14
#define PPTP_CTRL_MSG_TYPE_SLI 15
#define PPTP_FRAMING_CAP_ASYNC_MASK 0x00000001 /* Asynchronous */
#define PPTP_FRAMING_CAP_SYNC_MASK 0x00000002 /* Synchronous */
#define PPTP_BEARER_CAP_ANALOG_MASK 0x00000001 /* Analog */
#define PPTP_BEARER_CAP_DIGITAL_MASK 0x00000002 /* Digital */
static const char *pptp_message_type_string[] = {
"NOT_DEFINED", /* 0 Not defined in the RFC2637 */
"SCCRQ", /* 1 Start-Control-Connection-Request */
"SCCRP", /* 2 Start-Control-Connection-Reply */
"StopCCRQ", /* 3 Stop-Control-Connection-Request */
"StopCCRP", /* 4 Stop-Control-Connection-Reply */
"ECHORQ", /* 5 Echo Request */
"ECHORP", /* 6 Echo Reply */
"OCRQ", /* 7 Outgoing-Call-Request */
"OCRP", /* 8 Outgoing-Call-Reply */
"ICRQ", /* 9 Incoming-Call-Request */
"ICRP", /* 10 Incoming-Call-Reply */
"ICCN", /* 11 Incoming-Call-Connected */
"CCRQ", /* 12 Call-Clear-Request */
"CDN", /* 13 Call-Disconnect-Notify */
"WEN", /* 14 WAN-Error-Notify */
"SLI" /* 15 Set-Link-Info */
#define PPTP_MAX_MSGTYPE_INDEX 16
};
/* common for all PPTP control messages */
struct pptp_hdr {
nd_uint16_t length;
nd_uint16_t msg_type;
nd_uint32_t magic_cookie;
nd_uint16_t ctrl_msg_type;
nd_uint16_t reserved0;
};
struct pptp_msg_sccrq {
nd_uint16_t proto_ver;
nd_uint16_t reserved1;
nd_uint32_t framing_cap;
nd_uint32_t bearer_cap;
nd_uint16_t max_channel;
nd_uint16_t firm_rev;
nd_byte hostname[64];
nd_byte vendor[64];
};
struct pptp_msg_sccrp {
nd_uint16_t proto_ver;
nd_uint8_t result_code;
nd_uint8_t err_code;
nd_uint32_t framing_cap;
nd_uint32_t bearer_cap;
nd_uint16_t max_channel;
nd_uint16_t firm_rev;
nd_byte hostname[64];
nd_byte vendor[64];
};
struct pptp_msg_stopccrq {
nd_uint8_t reason;
nd_uint8_t reserved1;
nd_uint16_t reserved2;
};
struct pptp_msg_stopccrp {
nd_uint8_t result_code;
nd_uint8_t err_code;
nd_uint16_t reserved1;
};
struct pptp_msg_echorq {
nd_uint32_t id;
};
struct pptp_msg_echorp {
nd_uint32_t id;
nd_uint8_t result_code;
nd_uint8_t err_code;
nd_uint16_t reserved1;
};
struct pptp_msg_ocrq {
nd_uint16_t call_id;
nd_uint16_t call_ser;
nd_uint32_t min_bps;
nd_uint32_t max_bps;
nd_uint32_t bearer_type;
nd_uint32_t framing_type;
nd_uint16_t recv_winsiz;
nd_uint16_t pkt_proc_delay;
nd_uint16_t phone_no_len;
nd_uint16_t reserved1;
nd_byte phone_no[64];
nd_byte subaddr[64];
};
struct pptp_msg_ocrp {
nd_uint16_t call_id;
nd_uint16_t peer_call_id;
nd_uint8_t result_code;
nd_uint8_t err_code;
nd_uint16_t cause_code;
nd_uint32_t conn_speed;
nd_uint16_t recv_winsiz;
nd_uint16_t pkt_proc_delay;
nd_uint32_t phy_chan_id;
};
struct pptp_msg_icrq {
nd_uint16_t call_id;
nd_uint16_t call_ser;
nd_uint32_t bearer_type;
nd_uint32_t phy_chan_id;
nd_uint16_t dialed_no_len;
nd_uint16_t dialing_no_len;
nd_byte dialed_no[64]; /* DNIS */
nd_byte dialing_no[64]; /* CLID */
nd_byte subaddr[64];
};
struct pptp_msg_icrp {
nd_uint16_t call_id;
nd_uint16_t peer_call_id;
nd_uint8_t result_code;
nd_uint8_t err_code;
nd_uint16_t recv_winsiz;
nd_uint16_t pkt_proc_delay;
nd_uint16_t reserved1;
};
struct pptp_msg_iccn {
nd_uint16_t peer_call_id;
nd_uint16_t reserved1;
nd_uint32_t conn_speed;
nd_uint16_t recv_winsiz;
nd_uint16_t pkt_proc_delay;
nd_uint32_t framing_type;
};
struct pptp_msg_ccrq {
nd_uint16_t call_id;
nd_uint16_t reserved1;
};
struct pptp_msg_cdn {
nd_uint16_t call_id;
nd_uint8_t result_code;
nd_uint8_t err_code;
nd_uint16_t cause_code;
nd_uint16_t reserved1;
nd_byte call_stats[128];
};
struct pptp_msg_wen {
nd_uint16_t peer_call_id;
nd_uint16_t reserved1;
nd_uint32_t crc_err;
nd_uint32_t framing_err;
nd_uint32_t hardware_overrun;
nd_uint32_t buffer_overrun;
nd_uint32_t timeout_err;
nd_uint32_t align_err;
};
struct pptp_msg_sli {
nd_uint16_t peer_call_id;
nd_uint16_t reserved1;
nd_uint32_t send_accm;
nd_uint32_t recv_accm;
};
/* attributes that appear more than once in above messages:
Number of
occurrence attributes
--------------------------------------
2 uint32_t bearer_cap;
2 uint32_t bearer_type;
6 uint16_t call_id;
2 uint16_t call_ser;
2 uint16_t cause_code;
2 uint32_t conn_speed;
6 uint8_t err_code;
2 uint16_t firm_rev;
2 uint32_t framing_cap;
2 uint32_t framing_type;
2 u_char hostname[64];
2 uint32_t id;
2 uint16_t max_channel;
5 uint16_t peer_call_id;
2 uint32_t phy_chan_id;
4 uint16_t pkt_proc_delay;
2 uint16_t proto_ver;
4 uint16_t recv_winsiz;
2 uint8_t reserved1;
9 uint16_t reserved1;
6 uint8_t result_code;
2 u_char subaddr[64];
2 u_char vendor[64];
so I will prepare print out functions for these attributes (except for
reserved*).
*/
#define PRINT_RESERVED_IF_NOT_ZERO_1(reserved) \
if (GET_U_1(reserved)) \
ND_PRINT(" [ERROR: reserved=%u must be zero]", \
GET_U_1(reserved));
#define PRINT_RESERVED_IF_NOT_ZERO_2(reserved) \
if (GET_BE_U_2(reserved)) \
ND_PRINT(" [ERROR: reserved=%u must be zero]", \
GET_BE_U_2(reserved));
/******************************************/
/* Attribute-specific print out functions */
/******************************************/
static void
pptp_bearer_cap_print(netdissect_options *ndo,
const nd_uint32_t bearer_cap)
{
ND_PRINT(" BEARER_CAP(%s%s)",
GET_BE_U_4(bearer_cap) & PPTP_BEARER_CAP_DIGITAL_MASK ? "D" : "",
GET_BE_U_4(bearer_cap) & PPTP_BEARER_CAP_ANALOG_MASK ? "A" : "");
}
static const struct tok pptp_btype_str[] = {
{ 1, "A" }, /* Analog */
{ 2, "D" }, /* Digital */
{ 3, "Any" },
{ 0, NULL }
};
static void
pptp_bearer_type_print(netdissect_options *ndo,
const nd_uint32_t bearer_type)
{
ND_PRINT(" BEARER_TYPE(%s)",
tok2str(pptp_btype_str, "?", GET_BE_U_4(bearer_type)));
}
static void
pptp_call_id_print(netdissect_options *ndo,
const nd_uint16_t call_id)
{
ND_PRINT(" CALL_ID(%u)", GET_BE_U_2(call_id));
}
static void
pptp_call_ser_print(netdissect_options *ndo,
const nd_uint16_t call_ser)
{
ND_PRINT(" CALL_SER_NUM(%u)", GET_BE_U_2(call_ser));
}
static void
pptp_cause_code_print(netdissect_options *ndo,
const nd_uint16_t cause_code)
{
ND_PRINT(" CAUSE_CODE(%u)", GET_BE_U_2(cause_code));
}
static void
pptp_conn_speed_print(netdissect_options *ndo,
const nd_uint32_t conn_speed)
{
ND_PRINT(" CONN_SPEED(%u)", GET_BE_U_4(conn_speed));
}
static const struct tok pptp_errcode_str[] = {
{ 0, "None" },
{ 1, "Not-Connected" },
{ 2, "Bad-Format" },
{ 3, "Bad-Value" },
{ 4, "No-Resource" },
{ 5, "Bad-Call-ID" },
{ 6, "PAC-Error" },
{ 0, NULL }
};
static void
pptp_err_code_print(netdissect_options *ndo,
const nd_uint8_t err_code)
{
ND_PRINT(" ERR_CODE(%u", GET_U_1(err_code));
if (ndo->ndo_vflag) {
ND_PRINT(":%s",
tok2str(pptp_errcode_str, "?", GET_U_1(err_code)));
}
ND_PRINT(")");
}
static void
pptp_firm_rev_print(netdissect_options *ndo,
const nd_uint16_t firm_rev)
{
ND_PRINT(" FIRM_REV(%u)", GET_BE_U_2(firm_rev));
}
static void
pptp_framing_cap_print(netdissect_options *ndo,
const nd_uint32_t framing_cap)
{
ND_PRINT(" FRAME_CAP(");
if (GET_BE_U_4(framing_cap) & PPTP_FRAMING_CAP_ASYNC_MASK) {
ND_PRINT("A"); /* Async */
}
if (GET_BE_U_4(framing_cap) & PPTP_FRAMING_CAP_SYNC_MASK) {
ND_PRINT("S"); /* Sync */
}
ND_PRINT(")");
}
static const struct tok pptp_ftype_str[] = {
{ 1, "A" }, /* Async */
{ 2, "S" }, /* Sync */
{ 3, "E" }, /* Either */
{ 0, NULL }
};
static void
pptp_framing_type_print(netdissect_options *ndo,
const nd_uint32_t framing_type)
{
ND_PRINT(" FRAME_TYPE(%s)",
tok2str(pptp_ftype_str, "?", GET_BE_U_4(framing_type)));
}
static void
pptp_hostname_print(netdissect_options *ndo,
const u_char *hostname)
{
ND_PRINT(" HOSTNAME(");
nd_printjnp(ndo, hostname, 64);
ND_PRINT(")");
}
static void
pptp_id_print(netdissect_options *ndo,
const nd_uint32_t id)
{
ND_PRINT(" ID(%u)", GET_BE_U_4(id));
}
static void
pptp_max_channel_print(netdissect_options *ndo,
const nd_uint16_t max_channel)
{
ND_PRINT(" MAX_CHAN(%u)", GET_BE_U_2(max_channel));
}
static void
pptp_peer_call_id_print(netdissect_options *ndo,
const nd_uint16_t peer_call_id)
{
ND_PRINT(" PEER_CALL_ID(%u)", GET_BE_U_2(peer_call_id));
}
static void
pptp_phy_chan_id_print(netdissect_options *ndo,
const nd_uint32_t phy_chan_id)
{
ND_PRINT(" PHY_CHAN_ID(%u)", GET_BE_U_4(phy_chan_id));
}
static void
pptp_pkt_proc_delay_print(netdissect_options *ndo,
const nd_uint16_t pkt_proc_delay)
{
ND_PRINT(" PROC_DELAY(%u)", GET_BE_U_2(pkt_proc_delay));
}
static void
pptp_proto_ver_print(netdissect_options *ndo,
const nd_uint16_t proto_ver)
{
ND_PRINT(" PROTO_VER(%u.%u)", /* Version.Revision */
GET_BE_U_2(proto_ver) >> 8,
GET_BE_U_2(proto_ver) & 0xff);
}
static void
pptp_recv_winsiz_print(netdissect_options *ndo,
const nd_uint16_t recv_winsiz)
{
ND_PRINT(" RECV_WIN(%u)", GET_BE_U_2(recv_winsiz));
}
static const struct tok pptp_scrrp_str[] = {
{ 1, "Successful channel establishment" },
{ 2, "General error" },
{ 3, "Command channel already exists" },
{ 4, "Requester is not authorized to establish a command channel" },
{ 5, "The protocol version of the requester is not supported" },
{ 0, NULL }
};
static const struct tok pptp_echorp_str[] = {
{ 1, "OK" },
{ 2, "General Error" },
{ 0, NULL }
};
static const struct tok pptp_ocrp_str[] = {
{ 1, "Connected" },
{ 2, "General Error" },
{ 3, "No Carrier" },
{ 4, "Busy" },
{ 5, "No Dial Tone" },
{ 6, "Time-out" },
{ 7, "Do Not Accept" },
{ 0, NULL }
};
static const struct tok pptp_icrp_str[] = {
{ 1, "Connect" },
{ 2, "General Error" },
{ 3, "Do Not Accept" },
{ 0, NULL }
};
static const struct tok pptp_cdn_str[] = {
{ 1, "Lost Carrier" },
{ 2, "General Error" },
{ 3, "Admin Shutdown" },
{ 4, "Request" },
{ 0, NULL }
};
static void
pptp_result_code_print(netdissect_options *ndo,
const nd_uint8_t result_code, int ctrl_msg_type)
{
ND_PRINT(" RESULT_CODE(%u", GET_U_1(result_code));
if (ndo->ndo_vflag) {
const struct tok *dict =
ctrl_msg_type == PPTP_CTRL_MSG_TYPE_SCCRP ? pptp_scrrp_str :
ctrl_msg_type == PPTP_CTRL_MSG_TYPE_StopCCRP ? pptp_echorp_str :
ctrl_msg_type == PPTP_CTRL_MSG_TYPE_ECHORP ? pptp_echorp_str :
ctrl_msg_type == PPTP_CTRL_MSG_TYPE_OCRP ? pptp_ocrp_str :
ctrl_msg_type == PPTP_CTRL_MSG_TYPE_ICRP ? pptp_icrp_str :
ctrl_msg_type == PPTP_CTRL_MSG_TYPE_CDN ? pptp_cdn_str :
NULL; /* assertion error */
if (dict != NULL)
ND_PRINT(":%s",
tok2str(dict, "?", GET_U_1(result_code)));
}
ND_PRINT(")");
}
static void
pptp_subaddr_print(netdissect_options *ndo,
const u_char *subaddr)
{
ND_PRINT(" SUB_ADDR(");
nd_printjnp(ndo, subaddr, 64);
ND_PRINT(")");
}
static void
pptp_vendor_print(netdissect_options *ndo,
const u_char *vendor)
{
ND_PRINT(" VENDOR(");
nd_printjnp(ndo, vendor, 64);
ND_PRINT(")");
}
/************************************/
/* PPTP message print out functions */
/************************************/
static void
pptp_sccrq_print(netdissect_options *ndo,
const u_char *dat)
{
const struct pptp_msg_sccrq *ptr = (const struct pptp_msg_sccrq *)dat;
pptp_proto_ver_print(ndo, ptr->proto_ver);
PRINT_RESERVED_IF_NOT_ZERO_2(ptr->reserved1);
pptp_framing_cap_print(ndo, ptr->framing_cap);
pptp_bearer_cap_print(ndo, ptr->bearer_cap);
pptp_max_channel_print(ndo, ptr->max_channel);
pptp_firm_rev_print(ndo, ptr->firm_rev);
pptp_hostname_print(ndo, ptr->hostname);
pptp_vendor_print(ndo, ptr->vendor);
}
static void
pptp_sccrp_print(netdissect_options *ndo,
const u_char *dat)
{
const struct pptp_msg_sccrp *ptr = (const struct pptp_msg_sccrp *)dat;
pptp_proto_ver_print(ndo, ptr->proto_ver);
pptp_result_code_print(ndo, ptr->result_code, PPTP_CTRL_MSG_TYPE_SCCRP);
pptp_err_code_print(ndo, ptr->err_code);
pptp_framing_cap_print(ndo, ptr->framing_cap);
pptp_bearer_cap_print(ndo, ptr->bearer_cap);
pptp_max_channel_print(ndo, ptr->max_channel);
pptp_firm_rev_print(ndo, ptr->firm_rev);
pptp_hostname_print(ndo, ptr->hostname);
pptp_vendor_print(ndo, ptr->vendor);
}
static void
pptp_stopccrq_print(netdissect_options *ndo,
const u_char *dat)
{
const struct pptp_msg_stopccrq *ptr = (const struct pptp_msg_stopccrq *)dat;
ND_PRINT(" REASON(%u", GET_U_1(ptr->reason));
if (ndo->ndo_vflag) {
switch (GET_U_1(ptr->reason)) {
case 1:
ND_PRINT(":None");
break;
case 2:
ND_PRINT(":Stop-Protocol");
break;
case 3:
ND_PRINT(":Stop-Local-Shutdown");
break;
default:
ND_PRINT(":?");
break;
}
}
ND_PRINT(")");
PRINT_RESERVED_IF_NOT_ZERO_1(ptr->reserved1);
PRINT_RESERVED_IF_NOT_ZERO_2(ptr->reserved2);
}
static void
pptp_stopccrp_print(netdissect_options *ndo,
const u_char *dat)
{
const struct pptp_msg_stopccrp *ptr = (const struct pptp_msg_stopccrp *)dat;
pptp_result_code_print(ndo, ptr->result_code, PPTP_CTRL_MSG_TYPE_StopCCRP);
pptp_err_code_print(ndo, ptr->err_code);
PRINT_RESERVED_IF_NOT_ZERO_2(ptr->reserved1);
}
static void
pptp_echorq_print(netdissect_options *ndo,
const u_char *dat)
{
const struct pptp_msg_echorq *ptr = (const struct pptp_msg_echorq *)dat;
pptp_id_print(ndo, ptr->id);
}
static void
pptp_echorp_print(netdissect_options *ndo,
const u_char *dat)
{
const struct pptp_msg_echorp *ptr = (const struct pptp_msg_echorp *)dat;
pptp_id_print(ndo, ptr->id);
pptp_result_code_print(ndo, ptr->result_code, PPTP_CTRL_MSG_TYPE_ECHORP);
pptp_err_code_print(ndo, ptr->err_code);
PRINT_RESERVED_IF_NOT_ZERO_2(ptr->reserved1);
}
static void
pptp_ocrq_print(netdissect_options *ndo,
const u_char *dat)
{
const struct pptp_msg_ocrq *ptr = (const struct pptp_msg_ocrq *)dat;
pptp_call_id_print(ndo, ptr->call_id);
pptp_call_ser_print(ndo, ptr->call_ser);
ND_PRINT(" MIN_BPS(%u)", GET_BE_U_4(ptr->min_bps));
ND_PRINT(" MAX_BPS(%u)", GET_BE_U_4(ptr->max_bps));
pptp_bearer_type_print(ndo, ptr->bearer_type);
pptp_framing_type_print(ndo, ptr->framing_type);
pptp_recv_winsiz_print(ndo, ptr->recv_winsiz);
pptp_pkt_proc_delay_print(ndo, ptr->pkt_proc_delay);
ND_PRINT(" PHONE_NO_LEN(%u)", GET_BE_U_2(ptr->phone_no_len));
PRINT_RESERVED_IF_NOT_ZERO_2(ptr->reserved1);
ND_PRINT(" PHONE_NO(");
nd_printjnp(ndo, ptr->phone_no,
ND_MIN(64, GET_BE_U_2(ptr->phone_no_len)));
ND_PRINT(")");
pptp_subaddr_print(ndo, ptr->subaddr);
}
static void
pptp_ocrp_print(netdissect_options *ndo,
const u_char *dat)
{
const struct pptp_msg_ocrp *ptr = (const struct pptp_msg_ocrp *)dat;
pptp_call_id_print(ndo, ptr->call_id);
pptp_peer_call_id_print(ndo, ptr->peer_call_id);
pptp_result_code_print(ndo, ptr->result_code, PPTP_CTRL_MSG_TYPE_OCRP);
pptp_err_code_print(ndo, ptr->err_code);
pptp_cause_code_print(ndo, ptr->cause_code);
pptp_conn_speed_print(ndo, ptr->conn_speed);
pptp_recv_winsiz_print(ndo, ptr->recv_winsiz);
pptp_pkt_proc_delay_print(ndo, ptr->pkt_proc_delay);
pptp_phy_chan_id_print(ndo, ptr->phy_chan_id);
}
static void
pptp_icrq_print(netdissect_options *ndo,
const u_char *dat)
{
const struct pptp_msg_icrq *ptr = (const struct pptp_msg_icrq *)dat;
pptp_call_id_print(ndo, ptr->call_id);
pptp_call_ser_print(ndo, ptr->call_ser);
pptp_bearer_type_print(ndo, ptr->bearer_type);
pptp_phy_chan_id_print(ndo, ptr->phy_chan_id);
ND_PRINT(" DIALED_NO_LEN(%u)", GET_BE_U_2(ptr->dialed_no_len));
ND_PRINT(" DIALING_NO_LEN(%u)", GET_BE_U_2(ptr->dialing_no_len));
ND_PRINT(" DIALED_NO(");
nd_printjnp(ndo, ptr->dialed_no,
ND_MIN(64, GET_BE_U_2(ptr->dialed_no_len)));
ND_PRINT(")");
ND_PRINT(" DIALING_NO(");
nd_printjnp(ndo, ptr->dialing_no,
ND_MIN(64, GET_BE_U_2(ptr->dialing_no_len)));
ND_PRINT(")");
pptp_subaddr_print(ndo, ptr->subaddr);
}
static void
pptp_icrp_print(netdissect_options *ndo,
const u_char *dat)
{
const struct pptp_msg_icrp *ptr = (const struct pptp_msg_icrp *)dat;
pptp_call_id_print(ndo, ptr->call_id);
pptp_peer_call_id_print(ndo, ptr->peer_call_id);
pptp_result_code_print(ndo, ptr->result_code, PPTP_CTRL_MSG_TYPE_ICRP);
pptp_err_code_print(ndo, ptr->err_code);
pptp_recv_winsiz_print(ndo, ptr->recv_winsiz);
pptp_pkt_proc_delay_print(ndo, ptr->pkt_proc_delay);
PRINT_RESERVED_IF_NOT_ZERO_2(ptr->reserved1);
}
static void
pptp_iccn_print(netdissect_options *ndo,
const u_char *dat)
{
const struct pptp_msg_iccn *ptr = (const struct pptp_msg_iccn *)dat;
pptp_peer_call_id_print(ndo, ptr->peer_call_id);
PRINT_RESERVED_IF_NOT_ZERO_2(ptr->reserved1);
pptp_conn_speed_print(ndo, ptr->conn_speed);
pptp_recv_winsiz_print(ndo, ptr->recv_winsiz);
pptp_pkt_proc_delay_print(ndo, ptr->pkt_proc_delay);
pptp_framing_type_print(ndo, ptr->framing_type);
}
static void
pptp_ccrq_print(netdissect_options *ndo,
const u_char *dat)
{
const struct pptp_msg_ccrq *ptr = (const struct pptp_msg_ccrq *)dat;
pptp_call_id_print(ndo, ptr->call_id);
PRINT_RESERVED_IF_NOT_ZERO_2(ptr->reserved1);
}
static void
pptp_cdn_print(netdissect_options *ndo,
const u_char *dat)
{
const struct pptp_msg_cdn *ptr = (const struct pptp_msg_cdn *)dat;
pptp_call_id_print(ndo, ptr->call_id);
pptp_result_code_print(ndo, ptr->result_code, PPTP_CTRL_MSG_TYPE_CDN);
pptp_err_code_print(ndo, ptr->err_code);
pptp_cause_code_print(ndo, ptr->cause_code);
PRINT_RESERVED_IF_NOT_ZERO_2(ptr->reserved1);
ND_PRINT(" CALL_STATS(");
nd_printjnp(ndo, ptr->call_stats, 128);
ND_PRINT(")");
}
static void
pptp_wen_print(netdissect_options *ndo,
const u_char *dat)
{
const struct pptp_msg_wen *ptr = (const struct pptp_msg_wen *)dat;
pptp_peer_call_id_print(ndo, ptr->peer_call_id);
PRINT_RESERVED_IF_NOT_ZERO_2(ptr->reserved1);
ND_PRINT(" CRC_ERR(%u)", GET_BE_U_4(ptr->crc_err));
ND_PRINT(" FRAMING_ERR(%u)", GET_BE_U_4(ptr->framing_err));
ND_PRINT(" HARDWARE_OVERRUN(%u)", GET_BE_U_4(ptr->hardware_overrun));
ND_PRINT(" BUFFER_OVERRUN(%u)", GET_BE_U_4(ptr->buffer_overrun));
ND_PRINT(" TIMEOUT_ERR(%u)", GET_BE_U_4(ptr->timeout_err));
ND_PRINT(" ALIGN_ERR(%u)", GET_BE_U_4(ptr->align_err));
}
static void
pptp_sli_print(netdissect_options *ndo,
const u_char *dat)
{
const struct pptp_msg_sli *ptr = (const struct pptp_msg_sli *)dat;
pptp_peer_call_id_print(ndo, ptr->peer_call_id);
PRINT_RESERVED_IF_NOT_ZERO_2(ptr->reserved1);
ND_PRINT(" SEND_ACCM(0x%08x)", GET_BE_U_4(ptr->send_accm));
ND_PRINT(" RECV_ACCM(0x%08x)", GET_BE_U_4(ptr->recv_accm));
}
void
pptp_print(netdissect_options *ndo,
const u_char *dat)
{
const struct pptp_hdr *hdr;
uint32_t mc;
uint16_t ctrl_msg_type;
ndo->ndo_protocol = "pptp";
ND_PRINT(": ");
nd_print_protocol(ndo);
hdr = (const struct pptp_hdr *)dat;
if (ndo->ndo_vflag) {
ND_PRINT(" Length=%u", GET_BE_U_2(hdr->length));
}
if (ndo->ndo_vflag) {
switch(GET_BE_U_2(hdr->msg_type)) {
case PPTP_MSG_TYPE_CTRL:
ND_PRINT(" CTRL-MSG");
break;
case PPTP_MSG_TYPE_MGMT:
ND_PRINT(" MGMT-MSG");
break;
default:
ND_PRINT(" UNKNOWN-MSG-TYPE");
break;
}
}
mc = GET_BE_U_4(hdr->magic_cookie);
if (mc != PPTP_MAGIC_COOKIE) {
ND_PRINT(" UNEXPECTED Magic-Cookie!!(%08x)", mc);
}
if (ndo->ndo_vflag || mc != PPTP_MAGIC_COOKIE) {
ND_PRINT(" Magic-Cookie=%08x", mc);
}
ctrl_msg_type = GET_BE_U_2(hdr->ctrl_msg_type);
if (ctrl_msg_type < PPTP_MAX_MSGTYPE_INDEX) {
ND_PRINT(" CTRL_MSGTYPE=%s",
pptp_message_type_string[ctrl_msg_type]);
} else {
ND_PRINT(" UNKNOWN_CTRL_MSGTYPE(%u)", ctrl_msg_type);
}
PRINT_RESERVED_IF_NOT_ZERO_2(hdr->reserved0);
dat += 12;
switch(ctrl_msg_type) {
case PPTP_CTRL_MSG_TYPE_SCCRQ:
pptp_sccrq_print(ndo, dat);
break;
case PPTP_CTRL_MSG_TYPE_SCCRP:
pptp_sccrp_print(ndo, dat);
break;
case PPTP_CTRL_MSG_TYPE_StopCCRQ:
pptp_stopccrq_print(ndo, dat);
break;
case PPTP_CTRL_MSG_TYPE_StopCCRP:
pptp_stopccrp_print(ndo, dat);
break;
case PPTP_CTRL_MSG_TYPE_ECHORQ:
pptp_echorq_print(ndo, dat);
break;
case PPTP_CTRL_MSG_TYPE_ECHORP:
pptp_echorp_print(ndo, dat);
break;
case PPTP_CTRL_MSG_TYPE_OCRQ:
pptp_ocrq_print(ndo, dat);
break;
case PPTP_CTRL_MSG_TYPE_OCRP:
pptp_ocrp_print(ndo, dat);
break;
case PPTP_CTRL_MSG_TYPE_ICRQ:
pptp_icrq_print(ndo, dat);
break;
case PPTP_CTRL_MSG_TYPE_ICRP:
pptp_icrp_print(ndo, dat);
break;
case PPTP_CTRL_MSG_TYPE_ICCN:
pptp_iccn_print(ndo, dat);
break;
case PPTP_CTRL_MSG_TYPE_CCRQ:
pptp_ccrq_print(ndo, dat);
break;
case PPTP_CTRL_MSG_TYPE_CDN:
pptp_cdn_print(ndo, dat);
break;
case PPTP_CTRL_MSG_TYPE_WEN:
pptp_wen_print(ndo, dat);
break;
case PPTP_CTRL_MSG_TYPE_SLI:
pptp_sli_print(ndo, dat);
break;
default:
/* do nothing */
break;
}
}
diff --git a/contrib/tcpdump/print-ptp.c b/contrib/tcpdump/print-ptp.c
index a1c09c03ccef..09180110a818 100644
--- a/contrib/tcpdump/print-ptp.c
+++ b/contrib/tcpdump/print-ptp.c
@@ -1,634 +1,645 @@
/*
* 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.
*
* Original code by Partha S. Ghosh (psglinux dot gmail dot com)
*/
/* \summary: Precision Time Protocol (PTP) printer */
/* specification: https://standards.ieee.org/findstds/standard/1588-2008.html*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "extract.h"
/*
* PTP header
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | R | |msgtype| version | Msg Len |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | domain No | rsvd1 | flag Field |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Correction NS |
* + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | | Correction Sub NS |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Reserved2 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Clock Identity |
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Port Identity | Sequence ID |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | control | log msg int |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* 0 1 2 3
*
* Announce Message (msg type=0xB)
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
* | Seconds |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Nano Seconds |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Origin Cur UTC Offset | Reserved | GM Prio 1 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |GM Clock Class | GM Clock Accu | GM Clock Variance |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | GM Prio 2 | |
* +-+-+-+-+-+-+-+-+ +
* | GM Clock Identity |
* + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | | Steps Removed | Time Source |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* 0 1 2 3
*
* Sync Message (msg type=0x0)
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
* | Seconds |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Nano Seconds |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* Delay Request Message (msg type=0x1)
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
* | Origin Time Stamp Seconds |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Nano Seconds |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* Followup Message (msg type=0x8)
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
* | Precise Origin Time Stamp Seconds |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Nano Seconds |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* Delay Resp Message (msg type=0x9)
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
* | Seconds |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Nano Seconds |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Port Identity |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* PDelay Request Message (msg type=0x2)
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
* | Origin Time Stamp Seconds |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Origin Time Stamp Nano Seconds |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Port Identity |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* PDelay Response Message (msg type=0x3)
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
* | Request receipt Time Stamp Seconds |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Nano Seconds |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Requesting Port Identity |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* PDelay Resp Follow up Message (msg type=0xA)
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
* | Response Origin Time Stamp Seconds |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Nano Seconds |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Requesting Port Identity |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
- * Signalling Message (msg type=0xC)
+ * Signaling Message (msg type=0xC)
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Requesting Port Identity |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* Management Message (msg type=0xD)
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Requesting Port Identity |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |Start Bndry Hps| Boundary Hops | flags | Reserved |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*/
/* Values from IEEE1588-2008: 13.3.2.2 messageType (Enumeration4) */
#define M_SYNC 0x0
#define M_DELAY_REQ 0x1
#define M_PDELAY_REQ 0x2
#define M_PDELAY_RESP 0x3
#define M_FOLLOW_UP 0x8
#define M_DELAY_RESP 0x9
#define M_PDELAY_RESP_FOLLOW_UP 0xA
#define M_ANNOUNCE 0xB
-#define M_SIGNALLING 0xC
+#define M_SIGNALING 0xC
#define M_MANAGEMENT 0xD
static const struct tok ptp_msg_type[] = {
{ M_SYNC, "sync msg"},
{ M_DELAY_REQ, "delay req msg"},
{ M_PDELAY_REQ, "peer delay req msg"},
{ M_PDELAY_RESP, "peer delay resp msg"},
{ M_FOLLOW_UP, "follow up msg"},
{ M_DELAY_RESP, "delay resp msg"},
{ M_PDELAY_RESP_FOLLOW_UP, "pdelay resp fup msg"},
{ M_ANNOUNCE, "announce msg"},
- { M_SIGNALLING, "signalling msg"},
+ { M_SIGNALING, "signaling msg"},
{ M_MANAGEMENT, "management msg"},
{ 0, NULL}
};
/* Values from IEEE1588-2008: 13.3.2.10 controlField (UInteger8) */
/*
* The use of this field by the receiver is deprecated.
* NOTE-This field is provided for compatibility with hardware designed
* to conform to version 1 of this standard.
*/
#define C_SYNC 0x0
#define C_DELAY_REQ 0x1
#define C_FOLLOW_UP 0x2
#define C_DELAY_RESP 0x3
#define C_MANAGEMENT 0x4
#define C_OTHER 0x5
static const struct tok ptp_control_field[] = {
{ C_SYNC, "Sync"},
{ C_DELAY_REQ, "Delay_Req"},
{ C_FOLLOW_UP, "Follow_Up"},
{ C_DELAY_RESP, "Delay_Resp"},
{ C_MANAGEMENT, "Management"},
{ C_OTHER, "Other"},
{ 0, NULL}
};
#define PTP_TRUE 1
#define PTP_FALSE !PTP_TRUE
#define PTP_HDR_LEN 0x22
/* mask based on the first byte */
-#define PTP_VERS_MASK 0xFF
-#define PTP_V1_COMPAT 0x10
+#define PTP_MAJOR_VERS_MASK 0x0F
+#define PTP_MINOR_VERS_MASK 0xF0
+#define PTP_MAJOR_SDO_ID_MASK 0xF0
#define PTP_MSG_TYPE_MASK 0x0F
/*mask based 2byte */
#define PTP_DOMAIN_MASK 0xFF00
#define PTP_RSVD1_MASK 0xFF
#define PTP_CONTROL_MASK 0xFF
#define PTP_LOGMSG_MASK 0xFF
/* mask based on the flags 2 bytes */
#define PTP_L161_MASK 0x1
#define PTP_L1_59_MASK 0x2
#define PTP_UTC_REASONABLE_MASK 0x4
#define PTP_TIMESCALE_MASK 0x8
#define PTP_TIME_TRACABLE_MASK 0x10
#define PTP_FREQUENCY_TRACABLE_MASK 0x20
#define PTP_ALTERNATE_MASTER_MASK 0x100
#define PTP_TWO_STEP_MASK 0x200
#define PTP_UNICAST_MASK 0x400
#define PTP_PROFILE_SPEC_1_MASK 0x1000
#define PTP_PROFILE_SPEC_2_MASK 0x2000
#define PTP_SECURITY_MASK 0x4000
#define PTP_FLAGS_UNKNOWN_MASK 0x18C0
static const struct tok ptp_flag_values[] = {
{ PTP_L161_MASK, "l1 61"},
{ PTP_L1_59_MASK, "l1 59"},
{ PTP_UTC_REASONABLE_MASK, "utc reasonable"},
{ PTP_TIMESCALE_MASK, "timescale"},
{ PTP_TIME_TRACABLE_MASK, "time tracable"},
{ PTP_FREQUENCY_TRACABLE_MASK, "frequency tracable"},
{ PTP_ALTERNATE_MASTER_MASK, "alternate master"},
{ PTP_TWO_STEP_MASK, "two step"},
{ PTP_UNICAST_MASK, "unicast"},
{ PTP_PROFILE_SPEC_1_MASK, "profile specific 1"},
{ PTP_PROFILE_SPEC_2_MASK, "profile specific 2"},
{ PTP_SECURITY_MASK, "security mask"},
{ PTP_FLAGS_UNKNOWN_MASK, "unknown"},
{0, NULL}
};
static const char *p_porigin_ts = "preciseOriginTimeStamp";
static const char *p_origin_ts = "originTimeStamp";
static const char *p_recv_ts = "receiveTimeStamp";
#define PTP_VER_1 0x1
#define PTP_VER_2 0x2
#define PTP_UCHAR_LEN sizeof(uint8_t)
#define PTP_UINT16_LEN sizeof(uint16_t)
#define PTP_UINT32_LEN sizeof(uint32_t)
#define PTP_6BYTES_LEN sizeof(uint32_t)+sizeof(uint16_t)
#define PTP_UINT64_LEN sizeof(uint64_t)
static void ptp_print_1(netdissect_options *ndo);
static void ptp_print_2(netdissect_options *ndo, const u_char *bp, u_int len);
static void ptp_print_timestamp(netdissect_options *ndo, const u_char *bp, u_int *len, const char *stype);
static void ptp_print_timestamp_identity(netdissect_options *ndo, const u_char *bp, u_int *len, const char *ttype);
static void ptp_print_announce_msg(netdissect_options *ndo, const u_char *bp, u_int *len);
static void ptp_print_port_id(netdissect_options *ndo, const u_char *bp, u_int *len);
static void ptp_print_mgmt_msg(netdissect_options *ndo, const u_char *bp, u_int *len);
static void
print_field(netdissect_options *ndo, const char *st, uint32_t flen,
const u_char *bp, u_int *len, uint8_t hex)
{
uint8_t u8_val;
uint16_t u16_val;
uint32_t u32_val;
uint64_t u64_val;
switch(flen) {
case PTP_UCHAR_LEN:
u8_val = GET_U_1(bp);
ND_PRINT(", %s", st);
if (hex)
ND_PRINT(" 0x%x", u8_val);
else
ND_PRINT(" %u", u8_val);
*len -= 1; bp += 1;
break;
case PTP_UINT16_LEN:
u16_val = GET_BE_U_2(bp);
ND_PRINT(", %s", st);
if (hex)
ND_PRINT(" 0x%x", u16_val);
else
ND_PRINT(" %u", u16_val);
*len -= 2; bp += 2;
break;
case PTP_UINT32_LEN:
u32_val = GET_BE_U_4(bp);
ND_PRINT(", %s", st);
if (hex)
ND_PRINT(" 0x%x", u32_val);
else
ND_PRINT(" %u", u32_val);
*len -= 4; bp += 4;
break;
case PTP_UINT64_LEN:
u64_val = GET_BE_U_8(bp);
ND_PRINT(", %s", st);
if (hex)
ND_PRINT(" 0x%"PRIx64, u64_val);
else
ND_PRINT(" 0x%"PRIu64, u64_val);
*len -= 8; bp += 8;
break;
default:
break;
}
}
static void
ptp_print_1(netdissect_options *ndo)
{
ND_PRINT(" (not implemented)");
}
static void
ptp_print_2(netdissect_options *ndo, const u_char *bp, u_int length)
{
u_int len = length;
uint16_t msg_len, flags, port_id, seq_id;
- uint8_t foct, domain_no, msg_type, v1_compat, rsvd1, lm_int, control;
+ uint8_t foct, domain_no, msg_type, major_sdo_id, rsvd1, lm_int, control;
uint64_t ns_corr;
uint16_t sns_corr;
uint32_t rsvd2;
uint64_t clk_id;
foct = GET_U_1(bp);
- v1_compat = foct & PTP_V1_COMPAT;
- ND_PRINT(", v1 compat : %s", v1_compat?"yes":"no");
+ major_sdo_id = (foct & PTP_MAJOR_SDO_ID_MASK) >> 4;
+ ND_PRINT(", majorSdoId : 0x%x", major_sdo_id);
msg_type = foct & PTP_MSG_TYPE_MASK;
ND_PRINT(", msg type : %s", tok2str(ptp_msg_type, "Reserved", msg_type));
/* msg length */
len -= 2; bp += 2; msg_len = GET_BE_U_2(bp); ND_PRINT(", length : %u", msg_len);
/* domain */
len -= 2; bp += 2; domain_no = (GET_BE_U_2(bp) & PTP_DOMAIN_MASK) >> 8; ND_PRINT(", domain : %u", domain_no);
/* rsvd 1*/
rsvd1 = GET_BE_U_2(bp) & PTP_RSVD1_MASK;
ND_PRINT(", reserved1 : %u", rsvd1);
/* flags */
len -= 2; bp += 2; flags = GET_BE_U_2(bp); ND_PRINT(", Flags [%s]", bittok2str(ptp_flag_values, "none", flags));
/* correction NS (48 bits) */
len -= 2; bp += 2; ns_corr = GET_BE_U_6(bp); ND_PRINT(", NS correction : %"PRIu64, ns_corr);
/* correction sub NS (16 bits) */
len -= 6; bp += 6; sns_corr = GET_BE_U_2(bp); ND_PRINT(", sub NS correction : %u", sns_corr);
/* Reserved 2 */
len -= 2; bp += 2; rsvd2 = GET_BE_U_4(bp); ND_PRINT(", reserved2 : %u", rsvd2);
/* clock identity */
len -= 4; bp += 4; clk_id = GET_BE_U_8(bp); ND_PRINT(", clock identity : 0x%"PRIx64, clk_id);
/* port identity */
len -= 8; bp += 8; port_id = GET_BE_U_2(bp); ND_PRINT(", port id : %u", port_id);
/* sequence ID */
len -= 2; bp += 2; seq_id = GET_BE_U_2(bp); ND_PRINT(", seq id : %u", seq_id);
/* control */
len -= 2; bp += 2; control = GET_U_1(bp) ;
ND_PRINT(", control : %u (%s)", control, tok2str(ptp_control_field, "Reserved", control));
/* log message interval */
lm_int = GET_BE_U_2(bp) & PTP_LOGMSG_MASK; ND_PRINT(", log message interval : %u", lm_int); len -= 2; bp += 2;
switch(msg_type) {
case M_SYNC:
ptp_print_timestamp(ndo, bp, &len, p_origin_ts);
break;
case M_DELAY_REQ:
ptp_print_timestamp(ndo, bp, &len, p_origin_ts);
break;
case M_PDELAY_REQ:
ptp_print_timestamp_identity(ndo, bp, &len, p_porigin_ts);
break;
case M_PDELAY_RESP:
ptp_print_timestamp_identity(ndo, bp, &len, p_recv_ts);
break;
case M_FOLLOW_UP:
ptp_print_timestamp(ndo, bp, &len, p_porigin_ts);
break;
case M_DELAY_RESP:
ptp_print_timestamp_identity(ndo, bp, &len, p_recv_ts);
break;
case M_PDELAY_RESP_FOLLOW_UP:
ptp_print_timestamp_identity(ndo, bp, &len, p_porigin_ts);
break;
case M_ANNOUNCE:
ptp_print_announce_msg(ndo, bp, &len);
break;
- case M_SIGNALLING:
+ case M_SIGNALING:
ptp_print_port_id(ndo, bp, &len);
break;
case M_MANAGEMENT:
ptp_print_mgmt_msg(ndo, bp, &len);
break;
default:
break;
}
}
/*
* PTP general message
*/
void
ptp_print(netdissect_options *ndo, const u_char *bp, u_int length)
{
- u_int vers;
-
+ u_int major_vers;
+ u_int minor_vers;
+
+ /* In 1588-2019, a minorVersionPTP field has been created in the common PTP
+ * message header, from a previously reserved field. Implementations
+ * compatible to the 2019 edition shall indicate a versionPTP field value
+ * of 2 and minorVersionPTP field value of 1, indicating that this is PTP
+ * version 2.1.
+ */
ndo->ndo_protocol = "ptp";
- ND_LCHECK_U(length, PTP_HDR_LEN);
- vers = GET_BE_U_2(bp) & PTP_VERS_MASK;
- ND_PRINT("PTPv%u",vers);
- switch(vers) {
+ ND_ICHECK_U(length, <, PTP_HDR_LEN);
+ major_vers = GET_BE_U_2(bp) & PTP_MAJOR_VERS_MASK;
+ minor_vers = (GET_BE_U_2(bp) & PTP_MINOR_VERS_MASK) >> 4;
+ if (minor_vers)
+ ND_PRINT("PTPv%u.%u", major_vers, minor_vers);
+ else
+ ND_PRINT("PTPv%u", major_vers);
+
+ switch(major_vers) {
case PTP_VER_1:
ptp_print_1(ndo);
break;
case PTP_VER_2:
ptp_print_2(ndo, bp, length);
break;
default:
//ND_PRINT("ERROR: unknown-version\n");
break;
}
return;
invalid:
nd_print_invalid(ndo);
}
static void
ptp_print_timestamp(netdissect_options *ndo, const u_char *bp, u_int *len, const char *stype)
{
uint64_t secs;
uint32_t nsecs;
ND_PRINT(", %s :", stype);
/* sec time stamp 6 bytes */
secs = GET_BE_U_6(bp);
ND_PRINT(" %"PRIu64" seconds,", secs);
*len -= 6;
bp += 6;
/* NS time stamp 4 bytes */
nsecs = GET_BE_U_4(bp);
ND_PRINT(" %u nanoseconds", nsecs);
*len -= 4;
bp += 4;
}
static void
ptp_print_timestamp_identity(netdissect_options *ndo,
const u_char *bp, u_int *len, const char *ttype)
{
uint64_t secs;
uint32_t nsecs;
uint16_t port_id;
uint64_t port_identity;
ND_PRINT(", %s :", ttype);
/* sec time stamp 6 bytes */
secs = GET_BE_U_6(bp);
ND_PRINT(" %"PRIu64" seconds,", secs);
*len -= 6;
bp += 6;
/* NS time stamp 4 bytes */
nsecs = GET_BE_U_4(bp);
ND_PRINT(" %u nanoseconds", nsecs);
*len -= 4;
bp += 4;
/* port identity*/
port_identity = GET_BE_U_8(bp);
ND_PRINT(", port identity : 0x%"PRIx64, port_identity);
*len -= 8;
bp += 8;
/* port id */
port_id = GET_BE_U_2(bp);
ND_PRINT(", port id : %u", port_id);
*len -= 2;
bp += 2;
}
static void
ptp_print_announce_msg(netdissect_options *ndo, const u_char *bp, u_int *len)
{
uint8_t rsvd, gm_prio_1, gm_prio_2, gm_clk_cls, gm_clk_acc, time_src;
uint16_t origin_cur_utc, gm_clk_var, steps_removed;
uint64_t gm_clock_id;
uint64_t secs;
uint32_t nsecs;
ND_PRINT(", %s :", p_origin_ts);
/* sec time stamp 6 bytes */
secs = GET_BE_U_6(bp);
ND_PRINT(" %"PRIu64" seconds", secs);
*len -= 6;
bp += 6;
/* NS time stamp 4 bytes */
nsecs = GET_BE_U_4(bp);
ND_PRINT(" %u nanoseconds", nsecs);
*len -= 4;
bp += 4;
/* origin cur utc */
origin_cur_utc = GET_BE_U_2(bp);
ND_PRINT(", origin cur utc :%u", origin_cur_utc);
*len -= 2;
bp += 2;
/* rsvd */
rsvd = GET_U_1(bp);
ND_PRINT(", rsvd : %u", rsvd);
*len -= 1;
bp += 1;
/* gm prio */
gm_prio_1 = GET_U_1(bp);
ND_PRINT(", gm priority_1 : %u", gm_prio_1);
*len -= 1;
bp += 1;
/* GM clock class */
gm_clk_cls = GET_U_1(bp);
ND_PRINT(", gm clock class : %u", gm_clk_cls);
*len -= 1;
bp += 1;
/* GM clock accuracy */
gm_clk_acc = GET_U_1(bp);
ND_PRINT(", gm clock accuracy : %u", gm_clk_acc);
*len -= 1;
bp += 1;
/* GM clock variance */
gm_clk_var = GET_BE_U_2(bp);
ND_PRINT(", gm clock variance : %u", gm_clk_var);
*len -= 2;
bp += 2;
/* GM Prio 2 */
gm_prio_2 = GET_U_1(bp);
ND_PRINT(", gm priority_2 : %u", gm_prio_2);
*len -= 1;
bp += 1;
/* GM Clock Identity */
gm_clock_id = GET_BE_U_8(bp);
ND_PRINT(", gm clock id : 0x%"PRIx64, gm_clock_id);
*len -= 8;
bp += 8;
/* steps removed */
steps_removed = GET_BE_U_2(bp);
ND_PRINT(", steps removed : %u", steps_removed);
*len -= 2;
bp += 2;
/* Time source */
time_src = GET_U_1(bp);
ND_PRINT(", time source : 0x%x", time_src);
*len -= 1;
bp += 1;
}
static void
ptp_print_port_id(netdissect_options *ndo, const u_char *bp, u_int *len)
{
uint16_t port_id;
uint64_t port_identity;
/* port identity*/
port_identity = GET_BE_U_8(bp);
ND_PRINT(", port identity : 0x%"PRIx64, port_identity);
*len -= 8;
bp += 8;
/* port id */
port_id = GET_BE_U_2(bp);
ND_PRINT(", port id : %u", port_id);
*len -= 2;
bp += 2;
}
static void
ptp_print_mgmt_msg(netdissect_options *ndo, const u_char *bp, u_int *len)
{
ptp_print_port_id(ndo, bp, len);
print_field(ndo, ", start boundary hops ", PTP_UCHAR_LEN, bp, len, PTP_FALSE);
print_field(ndo, ", boundary hops ", PTP_UCHAR_LEN, bp, len, PTP_FALSE);
print_field(ndo, ", flags ", PTP_UCHAR_LEN, bp, len, PTP_TRUE);
print_field(ndo, ", reserved ", PTP_UCHAR_LEN, bp, len, PTP_TRUE);
}
diff --git a/contrib/tcpdump/print-radius.c b/contrib/tcpdump/print-radius.c
index 57d7e507e345..1b3c0f727073 100644
--- a/contrib/tcpdump/print-radius.c
+++ b/contrib/tcpdump/print-radius.c
@@ -1,1504 +1,1465 @@
/*
* Copyright (C) 2000 Alfredo Andres Omella. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. The names of the authors may not 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.
*/
/* \summary: Radius protocol printer */
/*
* Radius printer routines as specified on:
*
* RFC 2865:
* "Remote Authentication Dial In User Service (RADIUS)"
*
* RFC 2866:
* "RADIUS Accounting"
*
* RFC 2867:
* "RADIUS Accounting Modifications for Tunnel Protocol Support"
*
* RFC 2868:
* "RADIUS Attributes for Tunnel Protocol Support"
*
* RFC 2869:
* "RADIUS Extensions"
*
* RFC 3162:
* "RADIUS and IPv6"
*
* RFC 3580:
* "IEEE 802.1X Remote Authentication Dial In User Service (RADIUS)"
* "Usage Guidelines"
*
* RFC 4072:
* "Diameter Extensible Authentication Protocol (EAP) Application"
*
* RFC 4675:
* "RADIUS Attributes for Virtual LAN and Priority Support"
*
* RFC 4818:
* "RADIUS Delegated-IPv6-Prefix Attribute"
*
* RFC 4849:
* "RADIUS Filter Rule Attribute"
*
* RFC 5090:
* "RADIUS Extension for Digest Authentication"
*
* RFC 5176:
* "Dynamic Authorization Extensions to RADIUS"
*
* RFC 5447:
* "Diameter Mobile IPv6"
*
* RFC 5580:
* "Carrying Location Objects in RADIUS and Diameter"
*
* RFC 6572:
* "RADIUS Support for Proxy Mobile IPv6"
*
* RFC 7155:
* "Diameter Network Access Server Application"
*
* Alfredo Andres Omella (aandres@s21sec.com) v0.1 2000/09/15
*
* TODO: Among other things to print ok MacIntosh and Vendor values
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <string.h>
#include "netdissect-ctype.h"
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#include "oui.h"
#include "ntp.h"
#define TAM_SIZE(x) (sizeof(x)/sizeof(x[0]) )
#define PRINT_HEX(bytes_len, ptr_data) \
while(bytes_len) \
{ \
ND_PRINT("%02X", GET_U_1(ptr_data)); \
ptr_data++; \
bytes_len--; \
}
/* Radius packet codes */
/* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-27 */
-#define RADCMD_ACCESS_REQ 1 /* Access-Request */
-#define RADCMD_ACCESS_ACC 2 /* Access-Accept */
-#define RADCMD_ACCESS_REJ 3 /* Access-Reject */
-#define RADCMD_ACCOUN_REQ 4 /* Accounting-Request */
-#define RADCMD_ACCOUN_RES 5 /* Accounting-Response */
-#define RADCMD_ACCESS_CHA 11 /* Access-Challenge */
-#define RADCMD_STATUS_SER 12 /* Status-Server */
-#define RADCMD_STATUS_CLI 13 /* Status-Client */
-#define RADCMD_DISCON_REQ 40 /* Disconnect-Request */
-#define RADCMD_DISCON_ACK 41 /* Disconnect-ACK */
-#define RADCMD_DISCON_NAK 42 /* Disconnect-NAK */
-#define RADCMD_COA_REQ 43 /* CoA-Request */
-#define RADCMD_COA_ACK 44 /* CoA-ACK */
-#define RADCMD_COA_NAK 45 /* CoA-NAK */
-#define RADCMD_RESERVED 255 /* Reserved */
+#define RADCMD_ACCESS_REQ 1 /* Access-Request */
+#define RADCMD_ACCESS_ACC 2 /* Access-Accept */
+#define RADCMD_ACCESS_REJ 3 /* Access-Reject */
+#define RADCMD_ACCOUNT_REQ 4 /* Accounting-Request */
+#define RADCMD_ACCOUNT_RES 5 /* Accounting-Response */
+#define RADCMD_ACCESS_CHA 11 /* Access-Challenge */
+#define RADCMD_STATUS_SER 12 /* Status-Server */
+#define RADCMD_STATUS_CLI 13 /* Status-Client */
+#define RADCMD_DISCON_REQ 40 /* Disconnect-Request */
+#define RADCMD_DISCON_ACK 41 /* Disconnect-ACK */
+#define RADCMD_DISCON_NAK 42 /* Disconnect-NAK */
+#define RADCMD_COA_REQ 43 /* CoA-Request */
+#define RADCMD_COA_ACK 44 /* CoA-ACK */
+#define RADCMD_COA_NAK 45 /* CoA-NAK */
+#define RADCMD_RESERVED 255 /* Reserved */
static const struct tok radius_command_values[] = {
- { RADCMD_ACCESS_REQ, "Access-Request" },
- { RADCMD_ACCESS_ACC, "Access-Accept" },
- { RADCMD_ACCESS_REJ, "Access-Reject" },
- { RADCMD_ACCOUN_REQ, "Accounting-Request" },
- { RADCMD_ACCOUN_RES, "Accounting-Response" },
- { RADCMD_ACCESS_CHA, "Access-Challenge" },
- { RADCMD_STATUS_SER, "Status-Server" },
- { RADCMD_STATUS_CLI, "Status-Client" },
- { RADCMD_DISCON_REQ, "Disconnect-Request" },
- { RADCMD_DISCON_ACK, "Disconnect-ACK" },
- { RADCMD_DISCON_NAK, "Disconnect-NAK" },
- { RADCMD_COA_REQ, "CoA-Request" },
- { RADCMD_COA_ACK, "CoA-ACK" },
- { RADCMD_COA_NAK, "CoA-NAK" },
- { RADCMD_RESERVED, "Reserved" },
+ { RADCMD_ACCESS_REQ, "Access-Request" },
+ { RADCMD_ACCESS_ACC, "Access-Accept" },
+ { RADCMD_ACCESS_REJ, "Access-Reject" },
+ { RADCMD_ACCOUNT_REQ, "Accounting-Request" },
+ { RADCMD_ACCOUNT_RES, "Accounting-Response" },
+ { RADCMD_ACCESS_CHA, "Access-Challenge" },
+ { RADCMD_STATUS_SER, "Status-Server" },
+ { RADCMD_STATUS_CLI, "Status-Client" },
+ { RADCMD_DISCON_REQ, "Disconnect-Request" },
+ { RADCMD_DISCON_ACK, "Disconnect-ACK" },
+ { RADCMD_DISCON_NAK, "Disconnect-NAK" },
+ { RADCMD_COA_REQ, "CoA-Request" },
+ { RADCMD_COA_ACK, "CoA-ACK" },
+ { RADCMD_COA_NAK, "CoA-NAK" },
+ { RADCMD_RESERVED, "Reserved" },
{ 0, NULL}
};
/********************************/
/* Begin Radius Attribute types */
/********************************/
#define SERV_TYPE 6
#define FRM_IPADDR 8
#define LOG_IPHOST 14
#define LOG_SERVICE 15
#define FRM_IPX 23
#define SESSION_TIMEOUT 27
#define IDLE_TIMEOUT 28
#define FRM_ATALK_LINK 37
#define FRM_ATALK_NETWORK 38
#define ACCT_DELAY 41
#define ACCT_SESSION_TIME 46
#define EGRESS_VLAN_ID 56
#define EGRESS_VLAN_NAME 58
#define TUNNEL_TYPE 64
#define TUNNEL_MEDIUM 65
#define TUNNEL_CLIENT_END 66
#define TUNNEL_SERVER_END 67
#define TUNNEL_PASS 69
#define ARAP_PASS 70
#define ARAP_FEATURES 71
#define EAP_MESSAGE 79
#define TUNNEL_PRIV_GROUP 81
#define TUNNEL_ASSIGN_ID 82
#define TUNNEL_PREFERENCE 83
#define ARAP_CHALLENGE_RESP 84
#define ACCT_INT_INTERVAL 85
#define TUNNEL_CLIENT_AUTH 90
#define TUNNEL_SERVER_AUTH 91
#define ERROR_CAUSE 101
/********************************/
/* End Radius Attribute types */
/********************************/
#define RFC4675_TAGGED 0x31
#define RFC4675_UNTAGGED 0x32
static const struct tok rfc4675_tagged[] = {
{ RFC4675_TAGGED, "Tagged" },
{ RFC4675_UNTAGGED, "Untagged" },
{ 0, NULL}
};
static void print_attr_string(netdissect_options *, const u_char *, u_int, u_short );
static void print_attr_num(netdissect_options *, const u_char *, u_int, u_short );
static void print_vendor_attr(netdissect_options *, const u_char *, u_int, u_short );
static void print_attr_address(netdissect_options *, const u_char *, u_int, u_short);
static void print_attr_address6(netdissect_options *, const u_char *, u_int, u_short);
static void print_attr_netmask6(netdissect_options *, const u_char *, u_int, u_short);
static void print_attr_mip6_home_link_prefix(netdissect_options *, const u_char *, u_int, u_short);
static void print_attr_operator_name(netdissect_options *, const u_char *, u_int, u_short);
static void print_attr_location_information(netdissect_options *, const u_char *, u_int, u_short);
static void print_attr_location_data(netdissect_options *, const u_char *, u_int, u_short);
static void print_basic_location_policy_rules(netdissect_options *, const u_char *, u_int, u_short);
static void print_attr_time(netdissect_options *, const u_char *, u_int, u_short);
-static void print_attr_vector64(netdissect_options *, register const u_char *, u_int, u_short);
+static void print_attr_vector64(netdissect_options *, const u_char *, u_int, u_short);
static void print_attr_strange(netdissect_options *, const u_char *, u_int, u_short);
struct radius_hdr { nd_uint8_t code; /* Radius packet code */
nd_uint8_t id; /* Radius packet id */
nd_uint16_t len; /* Radius total length */
nd_byte auth[16]; /* Authenticator */
};
#define MIN_RADIUS_LEN 20
struct radius_attr { nd_uint8_t type; /* Attribute type */
nd_uint8_t len; /* Attribute length */
};
/* Service-Type Attribute standard values */
/* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-4 */
static const char *serv_type[]={ NULL,
"Login",
"Framed",
"Callback Login",
"Callback Framed",
"Outbound",
"Administrative",
"NAS Prompt",
"Authenticate Only",
"Callback NAS Prompt",
/* ^ [0, 9] ^ */
"Call Check",
"Callback Administrative",
"Voice",
"Fax",
"Modem Relay",
"IAPP-Register",
"IAPP-AP-Check",
"Authorize Only",
"Framed-Management",
"Additional-Authorization",
/* ^ [10, 19] ^ */
};
/* Framed-Protocol Attribute standard values */
/* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-5 */
static const char *frm_proto[]={ NULL,
"PPP",
"SLIP",
"ARAP",
"Gandalf proprietary",
"Xylogics IPX/SLIP",
"X.75 Synchronous",
"GPRS PDP Context",
};
/* Framed-Routing Attribute standard values */
/* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-6 */
static const char *frm_routing[]={ "None",
"Send",
"Listen",
"Send&Listen",
};
/* Framed-Compression Attribute standard values */
/* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-7 */
static const char *frm_comp[]={ "None",
"VJ TCP/IP",
"IPX",
"Stac-LZS",
};
/* Login-Service Attribute standard values */
/* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-8 */
static const char *login_serv[]={ "Telnet",
"Rlogin",
"TCP Clear",
"PortMaster(proprietary)",
"LAT",
"X.25-PAD",
"X.25-T3POS",
"Unassigned",
"TCP Clear Quiet",
};
/* Termination-Action Attribute standard values */
/* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-9 */
static const char *term_action[]={ "Default",
"RADIUS-Request",
};
/* Ingress-Filters Attribute standard values */
static const char *ingress_filters[]={ NULL,
"Enabled",
"Disabled",
};
/* NAS-Port-Type Attribute standard values */
/* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-13 */
static const char *nas_port_type[]={ "Async",
"Sync",
"ISDN Sync",
"ISDN Async V.120",
"ISDN Async V.110",
"Virtual",
"PIAFS",
"HDLC Clear Channel",
"X.25",
"X.75",
/* ^ [0, 9] ^ */
"G.3 Fax",
"SDSL",
"ADSL-CAP",
"ADSL-DMT",
"ISDN-DSL",
"Ethernet",
"xDSL",
"Cable",
"Wireless - Other",
"Wireless - IEEE 802.11",
/* ^ [10, 19] ^ */
"Token-Ring",
"FDDI",
"Wireless - CDMA200",
"Wireless - UMTS",
"Wireless - 1X-EV",
"IAPP",
"FTTP",
"Wireless - IEEE 802.16",
"Wireless - IEEE 802.20",
"Wireless - IEEE 802.22",
/* ^ [20, 29] ^ */
"PPPoA",
"PPPoEoA",
"PPPoEoE",
"PPPoEoVLAN",
"PPPoEoQinQ",
"xPON",
"Wireless - XGP",
"WiMAX Pre-Release 8 IWK Function",
"WIMAX-WIFI-IWK",
"WIMAX-SFF",
/* ^ [30, 39] ^ */
"WIMAX-HA-LMA",
"WIMAX-DHCP",
"WIMAX-LBS",
"WIMAX-WVS",
};
/* Acct-Status-Type Accounting Attribute standard values */
/* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-10 */
static const char *acct_status[]={ NULL,
"Start",
"Stop",
"Interim-Update",
"Unassigned",
"Unassigned",
"Unassigned",
"Accounting-On",
"Accounting-Off",
"Tunnel-Start",
/* ^ [0, 9] ^ */
"Tunnel-Stop",
"Tunnel-Reject",
"Tunnel-Link-Start",
"Tunnel-Link-Stop",
"Tunnel-Link-Reject",
"Failed",
};
/* Acct-Authentic Accounting Attribute standard values */
/* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-11 */
static const char *acct_auth[]={ NULL,
"RADIUS",
"Local",
"Remote",
"Diameter",
};
/* Acct-Terminate-Cause Accounting Attribute standard values */
/* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-12 */
static const char *acct_term[]={ NULL,
"User Request",
"Lost Carrier",
"Lost Service",
"Idle Timeout",
"Session Timeout",
"Admin Reset",
"Admin Reboot",
"Port Error",
"NAS Error",
/* ^ [0, 9] ^ */
"NAS Request",
"NAS Reboot",
"Port Unneeded",
"Port Preempted",
"Port Suspended",
"Service Unavailable",
"Callback",
"User Error",
"Host Request",
"Supplicant Restart",
/* ^ [10, 19] ^ */
"Reauthentication Failure",
"Port Reinitialized",
"Port Administratively Disabled",
"Lost Power",
};
/* Tunnel-Type Attribute standard values */
/* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-14 */
static const char *tunnel_type[]={ NULL,
"PPTP",
"L2F",
"L2TP",
"ATMP",
"VTP",
"AH",
"IP-IP",
"MIN-IP-IP",
"ESP",
/* ^ [0, 9] ^ */
"GRE",
"DVS",
"IP-in-IP Tunneling",
"VLAN",
};
/* Tunnel-Medium-Type Attribute standard values */
/* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-15 */
static const char *tunnel_medium[]={ NULL,
"IPv4",
"IPv6",
"NSAP",
"HDLC",
"BBN 1822",
"802",
"E.163",
"E.164",
"F.69",
/* ^ [0, 9] ^ */
"X.121",
"IPX",
"Appletalk",
"Decnet IV",
"Banyan Vines",
"E.164 with NSAP subaddress",
};
/* ARAP-Zone-Access Attribute standard values */
/* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-16 */
static const char *arap_zone[]={ NULL,
"Only access to dfl zone",
"Use zone filter inc.",
"Not used",
"Use zone filter exc.",
};
/* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-17 */
static const char *prompt[]={ "No Echo",
"Echo",
};
/* Error-Cause standard values */
/* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-18 */
#define ERROR_CAUSE_RESIDUAL_CONTEXT_REMOVED 201
#define ERROR_CAUSE_INVALID_EAP_PACKET 202
#define ERROR_CAUSE_UNSUPPORTED_ATTRIBUTE 401
#define ERROR_CAUSE_MISSING_ATTRIBUTE 402
#define ERROR_CAUSE_NAS_IDENTIFICATION_MISMATCH 403
#define ERROR_CAUSE_INVALID_REQUEST 404
#define ERROR_CAUSE_UNSUPPORTED_SERVICE 405
#define ERROR_CAUSE_UNSUPPORTED_EXTENSION 406
#define ERROR_CAUSE_INVALID_ATTRIBUTE_VALUE 407
#define ERROR_CAUSE_ADMINISTRATIVELY_PROHIBITED 501
#define ERROR_CAUSE_PROXY_REQUEST_NOT_ROUTABLE 502
#define ERROR_CAUSE_SESSION_CONTEXT_NOT_FOUND 503
#define ERROR_CAUSE_SESSION_CONTEXT_NOT_REMOVABLE 504
#define ERROR_CAUSE_PROXY_PROCESSING_ERROR 505
#define ERROR_CAUSE_RESOURCES_UNAVAILABLE 506
#define ERROR_CAUSE_REQUEST_INITIATED 507
#define ERROR_CAUSE_MULTIPLE_SESSION_SELECTION_UNSUPPORTED 508
#define ERROR_CAUSE_LOCATION_INFO_REQUIRED 509
static const struct tok errorcausetype[] = {
{ ERROR_CAUSE_RESIDUAL_CONTEXT_REMOVED, "Residual Session Context Removed" },
{ ERROR_CAUSE_INVALID_EAP_PACKET, "Invalid EAP Packet (Ignored)" },
{ ERROR_CAUSE_UNSUPPORTED_ATTRIBUTE, "Unsupported Attribute" },
{ ERROR_CAUSE_MISSING_ATTRIBUTE, "Missing Attribute" },
{ ERROR_CAUSE_NAS_IDENTIFICATION_MISMATCH, "NAS Identification Mismatch" },
{ ERROR_CAUSE_INVALID_REQUEST, "Invalid Request" },
{ ERROR_CAUSE_UNSUPPORTED_SERVICE, "Unsupported Service" },
{ ERROR_CAUSE_UNSUPPORTED_EXTENSION, "Unsupported Extension" },
{ ERROR_CAUSE_INVALID_ATTRIBUTE_VALUE, "Invalid Attribute Value" },
{ ERROR_CAUSE_ADMINISTRATIVELY_PROHIBITED, "Administratively Prohibited" },
{ ERROR_CAUSE_PROXY_REQUEST_NOT_ROUTABLE, "Request Not Routable (Proxy)" },
{ ERROR_CAUSE_SESSION_CONTEXT_NOT_FOUND, "Session Context Not Found" },
{ ERROR_CAUSE_SESSION_CONTEXT_NOT_REMOVABLE, "Session Context Not Removable" },
{ ERROR_CAUSE_PROXY_PROCESSING_ERROR, "Other Proxy Processing Error" },
{ ERROR_CAUSE_RESOURCES_UNAVAILABLE, "Resources Unavailable" },
{ ERROR_CAUSE_REQUEST_INITIATED, "Request Initiated" },
{ ERROR_CAUSE_MULTIPLE_SESSION_SELECTION_UNSUPPORTED, "Multiple Session Selection Unsupported" },
{ ERROR_CAUSE_LOCATION_INFO_REQUIRED, "Location Info Required" },
{ 0, NULL }
};
/* MIP6-Feature-Vector standard values */
/* https://www.iana.org/assignments/aaa-parameters/aaa-parameters.xhtml */
#define MIP6_INTEGRATED 0x0000000000000001
#define LOCAL_HOME_AGENT_ASSIGNMENT 0x0000000000000002
#define PMIP6_SUPPORTED 0x0000010000000000
#define IP4_HOA_SUPPORTED 0x0000020000000000
#define LOCAL_MAG_ROUTING_SUPPORTED 0x0000040000000000
#define ASSIGN_LOCAL_IP 0x0000080000000000
#define MIP4_SUPPORTED 0x0000100000000000
#define OPTIMIZED_IDLE_MODE_MOBILITY 0x0000200000000000
#define GTPv2_SUPPORTED 0x0000400000000000
#define IP4_TRANSPORT_SUPPORTED 0x0000800000000000
#define IP4_HOA_ONLY_SUPPORTED 0x0001000000000000
#define INTER_MAG_ROUTING_SUPPORTED 0x0002000000000000
static const struct mip6_feature_vector {
uint64_t v;
const char *s;
} mip6_feature_vector[] = {
{ MIP6_INTEGRATED, "MIP6_INTEGRATED" },
{ LOCAL_HOME_AGENT_ASSIGNMENT, "LOCAL_HOME_AGENT_ASSIGNMENT" },
{ PMIP6_SUPPORTED, "PMIP6_SUPPORTED" },
{ IP4_HOA_SUPPORTED, "IP4_HOA_SUPPORTED" },
{ LOCAL_MAG_ROUTING_SUPPORTED, "LOCAL_MAG_ROUTING_SUPPORTED" },
{ ASSIGN_LOCAL_IP, "ASSIGN_LOCAL_IP" },
{ MIP4_SUPPORTED, "MIP4_SUPPORTED" },
{ OPTIMIZED_IDLE_MODE_MOBILITY, "OPTIMIZED_IDLE_MODE_MOBILITY" },
{ GTPv2_SUPPORTED, "GTPv2_SUPPORTED" },
{ IP4_TRANSPORT_SUPPORTED, "IP4_TRANSPORT_SUPPORTED" },
{ IP4_HOA_ONLY_SUPPORTED, "IP4_HOA_ONLY_SUPPORTED" },
{ INTER_MAG_ROUTING_SUPPORTED, "INTER_MAG_ROUTING_SUPPORTED" },
};
/* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-19 */
#define OPERATOR_NAME_TADIG 0x30
#define OPERATOR_NAME_REALM 0x31
#define OPERATOR_NAME_E212 0x32
#define OPERATOR_NAME_ICC 0x33
static const struct tok operator_name_vector[] = {
{ OPERATOR_NAME_TADIG, "TADIG" },
{ OPERATOR_NAME_REALM, "REALM" },
{ OPERATOR_NAME_E212, "E212" },
{ OPERATOR_NAME_ICC, "ICC" },
{ 0, NULL }
};
/* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-20 */
#define LOCATION_INFORMATION_CODE_CIVIC 0
#define LOCATION_INFORMATION_CODE_GEOSPATIAL 1
static const struct tok location_information_code_vector[] = {
{ LOCATION_INFORMATION_CODE_CIVIC , "Civic" },
{ LOCATION_INFORMATION_CODE_GEOSPATIAL, "Geospatial" },
{ 0, NULL }
};
/* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-21 */
#define LOCATION_INFORMATION_ENTITY_USER 0
#define LOCATION_INFORMATION_ENTITY_RADIUS 1
static const struct tok location_information_entity_vector[] = {
{ LOCATION_INFORMATION_ENTITY_USER, "User" },
{ LOCATION_INFORMATION_ENTITY_RADIUS, "RADIUS" },
{ 0, NULL }
};
/* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-22 */
static const struct tok blpr_bm[] = {
{ 0x0001, "MBZ-15" },
{ 0x0002, "MBZ-14" },
{ 0x0004, "MBZ-13" },
{ 0x0008, "MBZ-12" },
{ 0x0010, "MBZ-11" },
{ 0x0020, "MBZ-10" },
{ 0x0040, "MBZ-9" },
{ 0x0080, "MBZ-8" },
{ 0x0100, "MBZ-7" },
{ 0x0200, "MBZ-6" },
{ 0x0400, "MBZ-5" },
{ 0x0800, "MBZ-4" },
{ 0x1000, "MBZ-3" },
{ 0x2000, "MBZ-2" },
{ 0x4000, "MBZ-1" },
{ 0x8000, "Retransmission Allowed" },
{ 0, NULL }
};
/* https://www.iana.org/assignments/radius-types/radius-types.xhtml#radius-types-2 */
static const struct attrtype {
const char *name; /* Attribute name */
const char **subtypes; /* Standard Values (if any) */
u_char siz_subtypes; /* Size of total standard values */
u_char first_subtype; /* First standard value is 0 or 1 */
void (*print_func)(netdissect_options *, const u_char *, u_int, u_short);
} attr_type[]=
{
{ NULL, NULL, 0, 0, NULL },
{ "User-Name", NULL, 0, 0, print_attr_string },
{ "User-Password", NULL, 0, 0, NULL },
{ "CHAP-Password", NULL, 0, 0, NULL },
{ "NAS-IP-Address", NULL, 0, 0, print_attr_address },
{ "NAS-Port", NULL, 0, 0, print_attr_num },
{ "Service-Type", serv_type, TAM_SIZE(serv_type)-1, 1, print_attr_num },
{ "Framed-Protocol", frm_proto, TAM_SIZE(frm_proto)-1, 1, print_attr_num },
{ "Framed-IP-Address", NULL, 0, 0, print_attr_address },
{ "Framed-IP-Netmask", NULL, 0, 0, print_attr_address },
/* ^ [0, 9] ^ */
{ "Framed-Routing", frm_routing, TAM_SIZE(frm_routing), 0, print_attr_num },
{ "Filter-Id", NULL, 0, 0, print_attr_string },
{ "Framed-MTU", NULL, 0, 0, print_attr_num },
{ "Framed-Compression", frm_comp, TAM_SIZE(frm_comp), 0, print_attr_num },
{ "Login-IP-Host", NULL, 0, 0, print_attr_address },
{ "Login-Service", login_serv, TAM_SIZE(login_serv), 0, print_attr_num },
{ "Login-TCP-Port", NULL, 0, 0, print_attr_num },
{ "Unassigned", NULL, 0, 0, NULL }, /*17*/
{ "Reply-Message", NULL, 0, 0, print_attr_string },
{ "Callback-Number", NULL, 0, 0, print_attr_string },
/* ^ [10, 19] ^ */
{ "Callback-Id", NULL, 0, 0, print_attr_string },
{ "Unassigned", NULL, 0, 0, NULL }, /*21*/
{ "Framed-Route", NULL, 0, 0, print_attr_string },
{ "Framed-IPX-Network", NULL, 0, 0, print_attr_num },
{ "State", NULL, 0, 0, print_attr_string },
{ "Class", NULL, 0, 0, print_attr_string },
{ "Vendor-Specific", NULL, 0, 0, print_vendor_attr },
{ "Session-Timeout", NULL, 0, 0, print_attr_num },
{ "Idle-Timeout", NULL, 0, 0, print_attr_num },
{ "Termination-Action", term_action, TAM_SIZE(term_action), 0, print_attr_num },
/* ^ [20, 29] ^ */
{ "Called-Station-Id", NULL, 0, 0, print_attr_string },
{ "Calling-Station-Id", NULL, 0, 0, print_attr_string },
{ "NAS-Identifier", NULL, 0, 0, print_attr_string },
{ "Proxy-State", NULL, 0, 0, print_attr_string },
{ "Login-LAT-Service", NULL, 0, 0, print_attr_string },
{ "Login-LAT-Node", NULL, 0, 0, print_attr_string },
{ "Login-LAT-Group", NULL, 0, 0, print_attr_string },
{ "Framed-AppleTalk-Link", NULL, 0, 0, print_attr_num },
{ "Framed-AppleTalk-Network", NULL, 0, 0, print_attr_num },
{ "Framed-AppleTalk-Zone", NULL, 0, 0, print_attr_string },
/* ^ [30, 39] ^ */
{ "Acct-Status-Type", acct_status, TAM_SIZE(acct_status)-1, 1, print_attr_num },
{ "Acct-Delay-Time", NULL, 0, 0, print_attr_num },
{ "Acct-Input-Octets", NULL, 0, 0, print_attr_num },
{ "Acct-Output-Octets", NULL, 0, 0, print_attr_num },
{ "Acct-Session-Id", NULL, 0, 0, print_attr_string },
{ "Acct-Authentic", acct_auth, TAM_SIZE(acct_auth)-1, 1, print_attr_num },
{ "Acct-Session-Time", NULL, 0, 0, print_attr_num },
{ "Acct-Input-Packets", NULL, 0, 0, print_attr_num },
{ "Acct-Output-Packets", NULL, 0, 0, print_attr_num },
{ "Acct-Terminate-Cause", acct_term, TAM_SIZE(acct_term)-1, 1, print_attr_num },
/* ^ [40, 49] ^ */
{ "Acct-Multi-Session-Id", NULL, 0, 0, print_attr_string },
{ "Acct-Link-Count", NULL, 0, 0, print_attr_num },
{ "Acct-Input-Gigawords", NULL, 0, 0, print_attr_num },
{ "Acct-Output-Gigawords", NULL, 0, 0, print_attr_num },
{ "Unassigned", NULL, 0, 0, NULL }, /*54*/
{ "Event-Timestamp", NULL, 0, 0, print_attr_time },
{ "Egress-VLANID", NULL, 0, 0, print_attr_num },
{ "Ingress-Filters", ingress_filters, TAM_SIZE(ingress_filters)-1, 1, print_attr_num },
{ "Egress-VLAN-Name", NULL, 0, 0, print_attr_string },
{ "User-Priority-Table", NULL, 0, 0, NULL },
/* ^ [50, 59] ^ */
{ "CHAP-Challenge", NULL, 0, 0, print_attr_string },
{ "NAS-Port-Type", nas_port_type, TAM_SIZE(nas_port_type), 0, print_attr_num },
{ "Port-Limit", NULL, 0, 0, print_attr_num },
{ "Login-LAT-Port", NULL, 0, 0, print_attr_string }, /*63*/
{ "Tunnel-Type", tunnel_type, TAM_SIZE(tunnel_type)-1, 1, print_attr_num },
{ "Tunnel-Medium-Type", tunnel_medium, TAM_SIZE(tunnel_medium)-1, 1, print_attr_num },
{ "Tunnel-Client-Endpoint", NULL, 0, 0, print_attr_string },
{ "Tunnel-Server-Endpoint", NULL, 0, 0, print_attr_string },
{ "Acct-Tunnel-Connection", NULL, 0, 0, print_attr_string },
{ "Tunnel-Password", NULL, 0, 0, print_attr_string },
/* ^ [60, 69] ^ */
{ "ARAP-Password", NULL, 0, 0, print_attr_strange },
{ "ARAP-Features", NULL, 0, 0, print_attr_strange },
{ "ARAP-Zone-Access", arap_zone, TAM_SIZE(arap_zone)-1, 1, print_attr_num }, /*72*/
{ "ARAP-Security", NULL, 0, 0, print_attr_string },
{ "ARAP-Security-Data", NULL, 0, 0, print_attr_string },
{ "Password-Retry", NULL, 0, 0, print_attr_num },
{ "Prompt", prompt, TAM_SIZE(prompt), 0, print_attr_num },
{ "Connect-Info", NULL, 0, 0, print_attr_string },
{ "Configuration-Token", NULL, 0, 0, print_attr_string },
{ "EAP-Message", NULL, 0, 0, print_attr_string },
/* ^ [70, 79] ^ */
{ "Message-Authenticator", NULL, 0, 0, print_attr_string }, /*80*/
{ "Tunnel-Private-Group-ID", NULL, 0, 0, print_attr_string },
{ "Tunnel-Assignment-ID", NULL, 0, 0, print_attr_string },
{ "Tunnel-Preference", NULL, 0, 0, print_attr_num },
{ "ARAP-Challenge-Response", NULL, 0, 0, print_attr_strange },
{ "Acct-Interim-Interval", NULL, 0, 0, print_attr_num },
{ "Acct-Tunnel-Packets-Lost", NULL, 0, 0, print_attr_num }, /*86*/
{ "NAS-Port-Id", NULL, 0, 0, print_attr_string },
{ "Framed-Pool", NULL, 0, 0, print_attr_string },
{ "CUI", NULL, 0, 0, print_attr_string },
/* ^ [80, 89] ^ */
{ "Tunnel-Client-Auth-ID", NULL, 0, 0, print_attr_string },
{ "Tunnel-Server-Auth-ID", NULL, 0, 0, print_attr_string },
{ "NAS-Filter-Rule", NULL, 0, 0, print_attr_string },
{ "Unassigned", NULL, 0, 0, NULL }, /*93*/
{ "Originating-Line-Info", NULL, 0, 0, NULL },
{ "NAS-IPv6-Address", NULL, 0, 0, print_attr_address6 },
{ "Framed-Interface-ID", NULL, 0, 0, NULL },
{ "Framed-IPv6-Prefix", NULL, 0, 0, print_attr_netmask6 },
{ "Login-IPv6-Host", NULL, 0, 0, print_attr_address6 },
{ "Framed-IPv6-Route", NULL, 0, 0, print_attr_string },
/* ^ [90, 99] ^ */
{ "Framed-IPv6-Pool", NULL, 0, 0, print_attr_string },
{ "Error-Cause", NULL, 0, 0, print_attr_strange },
{ "EAP-Key-Name", NULL, 0, 0, NULL },
{ "Digest-Response", NULL, 0, 0, print_attr_string },
{ "Digest-Realm", NULL, 0, 0, print_attr_string },
{ "Digest-Nonce", NULL, 0, 0, print_attr_string },
{ "Digest-Response-Auth", NULL, 0, 0, print_attr_string },
{ "Digest-Nextnonce", NULL, 0, 0, print_attr_string },
{ "Digest-Method", NULL, 0, 0, print_attr_string },
{ "Digest-URI", NULL, 0, 0, print_attr_string },
/* ^ [100, 109] ^ */
{ "Digest-Qop", NULL, 0, 0, print_attr_string },
{ "Digest-Algorithm", NULL, 0, 0, print_attr_string },
{ "Digest-Entity-Body-Hash", NULL, 0, 0, print_attr_string },
{ "Digest-CNonce", NULL, 0, 0, print_attr_string },
{ "Digest-Nonce-Count", NULL, 0, 0, print_attr_string },
{ "Digest-Username", NULL, 0, 0, print_attr_string },
{ "Digest-Opaque", NULL, 0, 0, print_attr_string },
{ "Digest-Auth-Param", NULL, 0, 0, print_attr_string },
{ "Digest-AKA-Auts", NULL, 0, 0, print_attr_string },
{ "Digest-Domain", NULL, 0, 0, print_attr_string },
/* ^ [110, 119] ^ */
{ "Digest-Stale", NULL, 0, 0, print_attr_string },
{ "Digest-HA1", NULL, 0, 0, print_attr_string },
{ "SIP-AOR", NULL, 0, 0, print_attr_string },
{ "Delegated-IPv6-Prefix", NULL, 0, 0, print_attr_netmask6 },
{ "MIP6-Feature-Vector", NULL, 0, 0, print_attr_vector64 },
{ "MIP6-Home-Link-Prefix", NULL, 0, 0, print_attr_mip6_home_link_prefix },
{ "Operator-Name", NULL, 0, 0, print_attr_operator_name },
{ "Location-Information", NULL, 0, 0, print_attr_location_information },
{ "Location-Data", NULL, 0, 0, print_attr_location_data },
{ "Basic-Location-Policy-Rules", NULL, 0, 0, print_basic_location_policy_rules }
/* ^ [120, 129] ^ */
};
/*****************************/
/* Print an attribute string */
/* value pointed by 'data' */
/* and 'length' size. */
/*****************************/
/* Returns nothing. */
/*****************************/
static void
print_attr_string(netdissect_options *ndo,
const u_char *data, u_int length, u_short attr_code)
{
u_int i;
ND_TCHECK_LEN(data, length);
- switch(attr_code)
- {
+ switch(attr_code) {
case TUNNEL_PASS:
if (length < 3)
goto trunc;
if (GET_U_1(data) && (GET_U_1(data) <= 0x1F))
ND_PRINT("Tag[%u] ", GET_U_1(data));
else
ND_PRINT("Tag[Unused] ");
data++;
length--;
ND_PRINT("Salt %u ", GET_BE_U_2(data));
data+=2;
length-=2;
break;
case TUNNEL_CLIENT_END:
case TUNNEL_SERVER_END:
case TUNNEL_PRIV_GROUP:
case TUNNEL_ASSIGN_ID:
case TUNNEL_CLIENT_AUTH:
case TUNNEL_SERVER_AUTH:
- if (GET_U_1(data) <= 0x1F)
- {
+ if (GET_U_1(data) <= 0x1F) {
if (length < 1)
goto trunc;
if (GET_U_1(data))
ND_PRINT("Tag[%u] ", GET_U_1(data));
else
ND_PRINT("Tag[Unused] ");
data++;
length--;
}
break;
case EGRESS_VLAN_NAME:
if (length < 1)
goto trunc;
ND_PRINT("%s (0x%02x) ",
tok2str(rfc4675_tagged,"Unknown tag",GET_U_1(data)),
GET_U_1(data));
data++;
length--;
break;
case EAP_MESSAGE:
if (length < 1)
goto trunc;
eap_print(ndo, data, length);
return;
}
for (i=0; i < length && GET_U_1(data); i++, data++)
ND_PRINT("%c", ND_ASCII_ISPRINT(GET_U_1(data)) ? GET_U_1(data) : '.');
return;
trunc:
nd_print_trunc(ndo);
}
/*
* print vendor specific attributes
*/
static void
print_vendor_attr(netdissect_options *ndo,
const u_char *data, u_int length, u_short attr_code _U_)
{
u_int idx;
u_int vendor_id;
u_int vendor_type;
u_int vendor_length;
if (length < 4)
goto trunc;
vendor_id = GET_BE_U_4(data);
data+=4;
length-=4;
ND_PRINT("Vendor: %s (%u)",
tok2str(smi_values,"Unknown",vendor_id),
vendor_id);
while (length >= 2) {
vendor_type = GET_U_1(data);
vendor_length = GET_U_1(data + 1);
- if (vendor_length < 2)
- {
+ if (vendor_length < 2) {
ND_PRINT("\n\t Vendor Attribute: %u, Length: %u (bogus, must be >= 2)",
vendor_type,
vendor_length);
return;
}
- if (vendor_length > length)
- {
+ if (vendor_length > length) {
ND_PRINT("\n\t Vendor Attribute: %u, Length: %u (bogus, goes past end of vendor-specific attribute)",
vendor_type,
vendor_length);
return;
}
data+=2;
vendor_length-=2;
length-=2;
ND_TCHECK_LEN(data, vendor_length);
ND_PRINT("\n\t Vendor Attribute: %u, Length: %u, Value: ",
vendor_type,
vendor_length);
for (idx = 0; idx < vendor_length ; idx++, data++)
ND_PRINT("%c", ND_ASCII_ISPRINT(GET_U_1(data)) ? GET_U_1(data) : '.');
length-=vendor_length;
}
return;
trunc:
nd_print_trunc(ndo);
}
/******************************/
/* Print an attribute numeric */
/* value pointed by 'data' */
/* and 'length' size. */
/******************************/
/* Returns nothing. */
/******************************/
static void
print_attr_num(netdissect_options *ndo,
const u_char *data, u_int length, u_short attr_code)
{
uint32_t timeout;
- if (length != 4)
- {
+ if (length != 4) {
ND_PRINT("ERROR: length %u != 4", length);
return;
}
/* This attribute has standard values */
- if (attr_type[attr_code].siz_subtypes)
- {
+ if (attr_type[attr_code].siz_subtypes) {
static const char **table;
uint32_t data_value;
table = attr_type[attr_code].subtypes;
- if ( (attr_code == TUNNEL_TYPE) || (attr_code == TUNNEL_MEDIUM) )
- {
+ if ( (attr_code == TUNNEL_TYPE) || (attr_code == TUNNEL_MEDIUM) ) {
if (!GET_U_1(data))
ND_PRINT("Tag[Unused] ");
else
ND_PRINT("Tag[%u] ", GET_U_1(data));
data++;
data_value = GET_BE_U_3(data);
- }
- else
- {
+ } else {
data_value = GET_BE_U_4(data);
}
if ( data_value <= (uint32_t)(attr_type[attr_code].siz_subtypes - 1 +
attr_type[attr_code].first_subtype) &&
data_value >= attr_type[attr_code].first_subtype )
ND_PRINT("%s", table[data_value]);
else
ND_PRINT("#%u", data_value);
- }
- else
- {
+ } else {
switch(attr_code) /* Be aware of special cases... */
{
case FRM_IPX:
if (GET_BE_U_4(data) == 0xFFFFFFFE )
ND_PRINT("NAS Select");
else
ND_PRINT("%u", GET_BE_U_4(data));
break;
case SESSION_TIMEOUT:
case IDLE_TIMEOUT:
case ACCT_DELAY:
case ACCT_SESSION_TIME:
case ACCT_INT_INTERVAL:
timeout = GET_BE_U_4(data);
if ( timeout < 60 )
ND_PRINT("%02d secs", timeout);
- else
- {
+ else {
if ( timeout < 3600 )
ND_PRINT("%02d:%02d min",
timeout / 60, timeout % 60);
else
ND_PRINT("%02d:%02d:%02d hours",
timeout / 3600, (timeout % 3600) / 60,
timeout % 60);
}
break;
case FRM_ATALK_LINK:
if (GET_BE_U_4(data))
ND_PRINT("%u", GET_BE_U_4(data));
else
ND_PRINT("Unnumbered");
break;
case FRM_ATALK_NETWORK:
if (GET_BE_U_4(data))
ND_PRINT("%u", GET_BE_U_4(data));
else
ND_PRINT("NAS assigned");
break;
case TUNNEL_PREFERENCE:
if (GET_U_1(data))
ND_PRINT("Tag[%u] ", GET_U_1(data));
else
ND_PRINT("Tag[Unused] ");
data++;
ND_PRINT("%u", GET_BE_U_3(data));
break;
case EGRESS_VLAN_ID:
ND_PRINT("%s (0x%02x) ",
tok2str(rfc4675_tagged,"Unknown tag",GET_U_1(data)),
GET_U_1(data));
data++;
ND_PRINT("%u", GET_BE_U_3(data));
break;
default:
ND_PRINT("%u", GET_BE_U_4(data));
break;
} /* switch */
} /* if-else */
}
/*****************************/
/* Print an attribute IPv4 */
/* address value pointed by */
/* 'data' and 'length' size. */
/*****************************/
/* Returns nothing. */
/*****************************/
static void
print_attr_address(netdissect_options *ndo,
const u_char *data, u_int length, u_short attr_code)
{
- if (length != 4)
- {
+ if (length != 4) {
ND_PRINT("ERROR: length %u != 4", length);
return;
}
- switch(attr_code)
- {
+ switch(attr_code) {
case FRM_IPADDR:
case LOG_IPHOST:
if (GET_BE_U_4(data) == 0xFFFFFFFF )
ND_PRINT("User Selected");
else
if (GET_BE_U_4(data) == 0xFFFFFFFE )
ND_PRINT("NAS Select");
else
ND_PRINT("%s",GET_IPADDR_STRING(data));
break;
default:
ND_PRINT("%s", GET_IPADDR_STRING(data));
break;
}
}
/*****************************/
/* Print an attribute IPv6 */
/* address value pointed by */
/* 'data' and 'length' size. */
/*****************************/
/* Returns nothing. */
/*****************************/
static void
print_attr_address6(netdissect_options *ndo,
const u_char *data, u_int length, u_short attr_code _U_)
{
- if (length != 16)
- {
+ if (length != 16) {
ND_PRINT("ERROR: length %u != 16", length);
return;
}
ND_PRINT("%s", GET_IP6ADDR_STRING(data));
}
static void
print_attr_netmask6(netdissect_options *ndo,
const u_char *data, u_int length, u_short attr_code _U_)
{
u_char data2[16];
- if (length < 2 || length > 18)
- {
+ if (length < 2 || length > 18) {
ND_PRINT("ERROR: length %u not in range (2..18)", length);
return;
}
ND_TCHECK_LEN(data, length);
- if (GET_U_1(data + 1) > 128)
- {
+ if (GET_U_1(data + 1) > 128) {
ND_PRINT("ERROR: netmask %u not in range (0..128)", GET_U_1(data + 1));
return;
}
memset(data2, 0, sizeof(data2));
if (length > 2)
memcpy(data2, data+2, length-2);
ND_PRINT("%s/%u", ip6addr_string(ndo, data2), GET_U_1(data + 1)); /* local buffer, not packet data; don't use GET_IP6ADDR_STRING() */
if (GET_U_1(data + 1) > 8 * (length - 2))
ND_PRINT(" (inconsistent prefix length)");
return;
trunc:
nd_print_trunc(ndo);
}
static void
print_attr_mip6_home_link_prefix(netdissect_options *ndo,
const u_char *data, u_int length, u_short attr_code _U_)
{
- if (length != 17)
- {
+ if (length != 17) {
ND_PRINT("ERROR: length %u != 17", length);
return;
}
ND_TCHECK_LEN(data, length);
- if (GET_U_1(data) > 128)
- {
+ if (GET_U_1(data) > 128) {
ND_PRINT("ERROR: netmask %u not in range (0..128)", GET_U_1(data));
return;
}
ND_PRINT("%s/%u", GET_IP6ADDR_STRING(data + 1), GET_U_1(data));
return;
trunc:
nd_print_trunc(ndo);
}
static void
print_attr_operator_name(netdissect_options *ndo,
const u_char *data, u_int length, u_short attr_code _U_)
{
u_int namespace_value;
ND_TCHECK_LEN(data, length);
- if (length < 2)
- {
+ if (length < 2) {
ND_PRINT("ERROR: length %u < 2", length);
return;
}
namespace_value = GET_U_1(data);
data++;
ND_PRINT("[%s] ", tok2str(operator_name_vector, "unknown namespace %u", namespace_value));
(void)nd_printn(ndo, data, length - 1, NULL);
return;
trunc:
nd_print_trunc(ndo);
}
static void
print_attr_location_information(netdissect_options *ndo,
const u_char *data, u_int length, u_short attr_code _U_)
{
uint16_t index;
uint8_t code, entity;
ND_TCHECK_LEN(data, length);
- if (length < 21)
- {
+ if (length < 21) {
ND_PRINT("ERROR: length %u < 21", length);
return;
}
index = GET_BE_U_2(data);
data += 2;
code = GET_U_1(data);
data++;
entity = GET_U_1(data);
data++;
ND_PRINT("index %u, code %s, entity %s, ",
index,
tok2str(location_information_code_vector, "Unknown (%u)", code),
tok2str(location_information_entity_vector, "Unknown (%u)", entity)
);
ND_PRINT("sighting time ");
p_ntp_time(ndo, (const struct l_fixedpt *)data);
ND_PRINT(", ");
data += 8;
ND_PRINT("time to live ");
p_ntp_time(ndo, (const struct l_fixedpt *)data);
ND_PRINT(", ");
data += 8;
ND_PRINT("method \"");
(void)nd_printn(ndo, data, length - 20, NULL);
ND_PRINT("\"");
return;
trunc:
nd_print_trunc(ndo);
}
static void
print_attr_location_data(netdissect_options *ndo,
const u_char *data, u_int length, u_short attr_code _U_)
{
uint16_t index;
ND_TCHECK_LEN(data, length);
- if (length < 3)
- {
+ if (length < 3) {
ND_PRINT("ERROR: length %u < 3", length);
return;
}
index = GET_BE_U_2(data);
data += 2;
ND_PRINT("index %u, location", index);
/* The Location field of the String field of the Location-Data attribute
* can have two completely different structures depending on the value of
* the Code field of a Location-Info attribute, which supposedly precedes
* the current attribute. Unfortunately, this choice of encoding makes it
* non-trivial to decode the Location field without preserving some state
* between the attributes.
*/
hex_and_ascii_print(ndo, "\n\t ", data, length - 2);
return;
trunc:
nd_print_trunc(ndo);
}
static void
print_basic_location_policy_rules(netdissect_options *ndo,
const u_char *data, u_int length, u_short attr_code _U_)
{
uint16_t flags;
ND_TCHECK_LEN(data, length);
- if (length < 10)
- {
+ if (length < 10) {
ND_PRINT("ERROR: length %u < 10", length);
return;
}
flags = GET_BE_U_2(data);
data += 2;
ND_PRINT("flags [%s], ", bittok2str(blpr_bm, "none", flags));
ND_PRINT("retention expires ");
p_ntp_time(ndo, (const struct l_fixedpt *)data);
data += 8;
if (length > 10) {
ND_PRINT(", note well \"");
(void)nd_printn(ndo, data, length - 10, NULL);
ND_PRINT("\"");
}
return;
trunc:
nd_print_trunc(ndo);
}
/*************************************/
/* Print an attribute of 'secs since */
/* January 1, 1970 00:00 UTC' value */
/* pointed by 'data' and 'length' */
/* size. */
/*************************************/
/* Returns nothing. */
/*************************************/
static void
print_attr_time(netdissect_options *ndo,
const u_char *data, u_int length, u_short attr_code _U_)
{
time_t attr_time;
char string[26];
- if (length != 4)
- {
+ if (length != 4) {
ND_PRINT("ERROR: length %u != 4", length);
return;
}
attr_time = GET_BE_U_4(data);
strlcpy(string, ctime(&attr_time), sizeof(string));
/* Get rid of the newline */
string[24] = '\0';
ND_PRINT("%.24s", string);
}
static void
print_attr_vector64(netdissect_options *ndo,
- register const u_char *data, u_int length, u_short attr_code _U_)
+ const u_char *data, u_int length, u_short attr_code _U_)
{
uint64_t data_value, i;
const char *sep = "";
- if (length != 8)
- {
+ if (length != 8) {
ND_PRINT("ERROR: length %u != 8", length);
return;
}
ND_PRINT("[");
data_value = GET_BE_U_8(data);
/* Print the 64-bit field in a format similar to bittok2str(), less
* flagging any unknown bits. This way it should be easier to replace
* the custom code with a library function later.
*/
for (i = 0; i < TAM_SIZE(mip6_feature_vector); i++) {
if (data_value & mip6_feature_vector[i].v) {
ND_PRINT("%s%s", sep, mip6_feature_vector[i].s);
sep = ", ";
}
}
ND_PRINT("]");
}
/***********************************/
/* Print an attribute of 'strange' */
/* data format pointed by 'data' */
/* and 'length' size. */
/***********************************/
/* Returns nothing. */
/***********************************/
static void
print_attr_strange(netdissect_options *ndo,
const u_char *data, u_int length, u_short attr_code)
{
u_short len_data;
u_int error_cause_value;
- switch(attr_code)
- {
+ switch(attr_code) {
case ARAP_PASS:
- if (length != 16)
- {
+ if (length != 16) {
ND_PRINT("ERROR: length %u != 16", length);
return;
}
ND_PRINT("User_challenge (");
len_data = 8;
PRINT_HEX(len_data, data);
ND_PRINT(") User_resp(");
len_data = 8;
PRINT_HEX(len_data, data);
ND_PRINT(")");
break;
case ARAP_FEATURES:
- if (length != 14)
- {
+ if (length != 14) {
ND_PRINT("ERROR: length %u != 14", length);
return;
}
if (GET_U_1(data))
ND_PRINT("User can change password");
else
ND_PRINT("User cannot change password");
data++;
ND_PRINT(", Min password length: %u", GET_U_1(data));
data++;
ND_PRINT(", created at: ");
len_data = 4;
PRINT_HEX(len_data, data);
ND_PRINT(", expires in: ");
len_data = 4;
PRINT_HEX(len_data, data);
ND_PRINT(", Current Time: ");
len_data = 4;
PRINT_HEX(len_data, data);
break;
case ARAP_CHALLENGE_RESP:
- if (length < 8)
- {
+ if (length < 8) {
ND_PRINT("ERROR: length %u != 8", length);
return;
}
len_data = 8;
PRINT_HEX(len_data, data);
break;
case ERROR_CAUSE:
- if (length != 4)
- {
+ if (length != 4) {
ND_PRINT("Error: length %u != 4", length);
return;
}
error_cause_value = GET_BE_U_4(data);
ND_PRINT("Error cause %u: %s", error_cause_value, tok2str(errorcausetype, "Error-Cause %u not known", error_cause_value));
break;
}
return;
}
static void
radius_attrs_print(netdissect_options *ndo,
const u_char *attr, u_int length)
{
const struct radius_attr *rad_attr = (const struct radius_attr *)attr;
const char *attr_string;
uint8_t type, len;
- while (length > 0)
- {
+ while (length > 0) {
if (length < 2)
goto trunc;
ND_TCHECK_SIZE(rad_attr);
type = GET_U_1(rad_attr->type);
len = GET_U_1(rad_attr->len);
if (type != 0 && type < TAM_SIZE(attr_type))
attr_string = attr_type[type].name;
else
attr_string = "Unknown";
ND_PRINT("\n\t %s Attribute (%u), length: %u",
attr_string,
type,
len);
- if (len < 2)
- {
+ if (len < 2) {
ND_PRINT(" (bogus, must be >= 2)");
return;
}
- if (len > length)
- {
+ if (len > length) {
ND_PRINT(" (bogus, goes past end of packet)");
return;
}
ND_PRINT(", Value: ");
- if (type < TAM_SIZE(attr_type))
- {
- if (len > 2)
- {
+ if (type < TAM_SIZE(attr_type)) {
+ if (len > 2) {
if ( attr_type[type].print_func )
(*attr_type[type].print_func)(
ndo, ((const u_char *)(rad_attr+1)),
len - 2, type);
}
}
/* do we also want to see a hex dump ? */
if (ndo->ndo_vflag> 1)
print_unknown_data(ndo, (const u_char *)rad_attr+2, "\n\t ", (len)-2);
length-=(len);
rad_attr = (const struct radius_attr *)( ((const char *)(rad_attr))+len);
}
return;
trunc:
nd_print_trunc(ndo);
}
void
radius_print(netdissect_options *ndo,
const u_char *dat, u_int length)
{
const struct radius_hdr *rad;
u_int len, auth_idx;
ndo->ndo_protocol = "radius";
ND_TCHECK_LEN(dat, MIN_RADIUS_LEN);
rad = (const struct radius_hdr *)dat;
len = GET_BE_U_2(rad->len);
- if (len < MIN_RADIUS_LEN)
- {
+ if (len < MIN_RADIUS_LEN) {
nd_print_trunc(ndo);
return;
}
if (len > length)
len = length;
if (ndo->ndo_vflag < 1) {
ND_PRINT("RADIUS, %s (%u), id: 0x%02x length: %u",
tok2str(radius_command_values,"Unknown Command",GET_U_1(rad->code)),
GET_U_1(rad->code),
GET_U_1(rad->id),
len);
return;
- }
- else {
+ } else {
ND_PRINT("RADIUS, length: %u\n\t%s (%u), id: 0x%02x, Authenticator: ",
len,
tok2str(radius_command_values,"Unknown Command",GET_U_1(rad->code)),
GET_U_1(rad->code),
GET_U_1(rad->id));
for(auth_idx=0; auth_idx < 16; auth_idx++)
ND_PRINT("%02x", rad->auth[auth_idx]);
}
if (len > MIN_RADIUS_LEN)
radius_attrs_print(ndo, dat + MIN_RADIUS_LEN, len - MIN_RADIUS_LEN);
return;
trunc:
nd_print_trunc(ndo);
}
diff --git a/contrib/tcpdump/print-raw.c b/contrib/tcpdump/print-raw.c
index 9c6558fede02..d0edd2ece948 100644
--- a/contrib/tcpdump/print-raw.c
+++ b/contrib/tcpdump/print-raw.c
@@ -1,45 +1,43 @@
/*
* Copyright (c) 1996
* 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.
*/
/* \summary: Raw IP printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
/*
* The DLT_RAW packet has no header. It contains a raw IP packet.
*/
void
raw_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
{
ndo->ndo_protocol = "raw";
ndo->ndo_ll_hdr_len += 0;
if (ndo->ndo_eflag)
ND_PRINT("ip: ");
ipN_print(ndo, p, h->len);
}
diff --git a/contrib/tcpdump/print-realtek.c b/contrib/tcpdump/print-realtek.c
index 3105bf7f86af..f32086509497 100644
--- a/contrib/tcpdump/print-realtek.c
+++ b/contrib/tcpdump/print-realtek.c
@@ -1,248 +1,246 @@
/*
* Copyright (c) 2007 - Andrey "nording" Chernyak <andrew@nording.ru>
*
* 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.
*
* Format and print Realtek Remote Control Protocol (RRCP), Realtek
* Loop Detection Protocol (RLDP), and Realtek Echo Protocol (REP) packets,
* as well as tag formats used by some Realtek switch chips to supply
* tag information to a host CPU for a switch.
*/
/* \summary: printer for various Realtek protocols */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#define RTL_PROTOCOL_OFFSET 0 /* Protocol and possibly other data - 1 byte */
#define RTL_PROTOCOL_RRCP 0x01 /* RRCP */
#define RTL_PROTOCOL_REP 0x02 /* REP */
#define RTL_PROTOCOL_RLDP 0x03 /* RLDP */
#define RTL_PROTOCOL_RLDP2 0x23 /* also RLDP */
#define RTL_PROTOCOL_XXX_DSA 0x04 /* DSA protocol for some chip(s) */
/*
* Values for the upper 4 bits of the protocol field, for
* protocols where the lower 4 bits contain protocol data.
*
* See section 8.10 "CPU Tag Function" of
*
* http://realtek.info/pdf/rtl8306sd%28m%29_datasheet_1.1.pdf
*
* for the RTL8306 DSA protocol tag format.
*/
#define RTL_PROTOCOL_8306_DSA 0x90 /* RTL8306 DSA protocol */
#define RTL_PROTOCOL_8366RB_DSA 0xA0 /* RTL8366RB DSA protocol */
#define RRCP_OPCODE_ISREPLY_OFFSET 1 /* opcode and isreply flag - 1 byte */
#define RRCP_OPCODE_MASK 0x7F /* 0x00 = hello, 0x01 = get, 0x02 = set */
#define RRCP_ISREPLY 0x80 /* 0 = request to switch, 0x80 = reply from switch */
#define RRCP_OPCODE_HELLO 0x00
#define RRCP_OPCODE_GET_CONFIGURATION 0x01
#define RRCP_OPCODE_SET_CONFIGURATION 0x02
#define RRCP_AUTHKEY_OFFSET 2 /* authorization key - 2 bytes, 0x2379 by default */
/* most packets */
#define RRCP_REG_ADDR_OFFSET 4 /* register address - 2 bytes */
#define RRCP_REG_DATA_OFFSET 6 /* register data - 4 bytes */
#define RRCP_COOKIE1_OFFSET 10 /* 4 bytes */
#define RRCP_COOKIE2_OFFSET 14 /* 4 bytes */
/* hello reply packets */
#define RRCP_DOWNLINK_PORT_OFFSET 4 /* 1 byte */
#define RRCP_UPLINK_PORT_OFFSET 5 /* 1 byte */
#define RRCP_UPLINK_MAC_OFFSET 6 /* 6 byte MAC address */
#define RRCP_CHIP_ID_OFFSET 12 /* 2 bytes */
#define RRCP_VENDOR_ID_OFFSET 14 /* 4 bytes */
static const struct tok opcode_values[] = {
{ RRCP_OPCODE_HELLO, "hello" },
{ RRCP_OPCODE_GET_CONFIGURATION, "get" },
{ RRCP_OPCODE_SET_CONFIGURATION, "set" },
{ 0, NULL }
};
/*
* Print RRCP packets.
*
* See, for example, section 8.20 "Realtek Remote Control Protocol" of
*
* http://realtek.info/pdf/rtl8324.pdf
*
* and section 7.22 "Realtek Remote Control Protocol" of
*
* http://realtek.info/pdf/rtl8326.pdf
*
* and this page on the OpenRRCP Wiki:
*
* http://openrrcp.org.ru/wiki/rrcp_protocol
*
* for information on RRCP.
*/
static void
rrcp_print(netdissect_options *ndo,
const u_char *cp)
{
uint8_t rrcp_opcode;
ndo->ndo_protocol = "rrcp";
rrcp_opcode = GET_U_1((cp + RRCP_OPCODE_ISREPLY_OFFSET)) & RRCP_OPCODE_MASK;
ND_PRINT("RRCP %s: %s",
((GET_U_1(cp + RRCP_OPCODE_ISREPLY_OFFSET)) & RRCP_ISREPLY) ? "reply" : "query",
tok2str(opcode_values,"unknown opcode (0x%02x)",rrcp_opcode));
if (rrcp_opcode==RRCP_OPCODE_GET_CONFIGURATION ||
rrcp_opcode==RRCP_OPCODE_SET_CONFIGURATION){
ND_PRINT(" addr=0x%04x, data=0x%08x",
GET_LE_U_2(cp + RRCP_REG_ADDR_OFFSET),
GET_LE_U_4(cp + RRCP_REG_DATA_OFFSET));
}
ND_PRINT(", auth=0x%04x",
GET_BE_U_2(cp + RRCP_AUTHKEY_OFFSET));
if (rrcp_opcode==RRCP_OPCODE_HELLO &&
((GET_U_1(cp + RRCP_OPCODE_ISREPLY_OFFSET)) & RRCP_ISREPLY)){
ND_PRINT(" downlink_port=%u, uplink_port=%u, uplink_mac=%s, vendor_id=%08x ,chip_id=%04x ",
GET_U_1(cp + RRCP_DOWNLINK_PORT_OFFSET),
GET_U_1(cp + RRCP_UPLINK_PORT_OFFSET),
GET_ETHERADDR_STRING(cp + RRCP_UPLINK_MAC_OFFSET),
GET_BE_U_4(cp + RRCP_VENDOR_ID_OFFSET),
GET_BE_U_2(cp + RRCP_CHIP_ID_OFFSET));
}else if (rrcp_opcode==RRCP_OPCODE_GET_CONFIGURATION ||
rrcp_opcode==RRCP_OPCODE_SET_CONFIGURATION){
ND_PRINT(", cookie=0x%08x%08x ",
GET_BE_U_4(cp + RRCP_COOKIE2_OFFSET),
GET_BE_U_4(cp + RRCP_COOKIE1_OFFSET));
}
}
/*
* Print Realtek packets.
*
* See, for example, section 8.22 "Realtek Echo Protocol" of
*
* http://realtek.info/pdf/rtl8324.pdf
*
* and section 7.24 "Realtek Echo Protocol" of
*
* http://realtek.info/pdf/rtl8326.pdf
*
* for information on REP.
*
* See section 8.21 "Network Loop Connection Fault Detection" of
*
* http://realtek.info/pdf/rtl8324.pdf
*
* and section 7.23 "Network Loop Connection Fault Detection" of
*
* http://realtek.info/pdf/rtl8326.pdf
*
* for information on RLDP.
*
* See also section 7.3.8 "Loop Detection" of
*
* http://www.ibselectronics.com/ibsstore/datasheet/RTL8306E-CG.pdf
*
* (revision 1.1 of the RTL8306E-CG datasheet), which describes a loop
* detection protocol for which the payload has a 16-bit (presumably
* big-endian) field containing the value 0x0300, followed by what is
* presumably a 16-bit big-endian field the upper 12 bits of which are 0
* and the lower 4 bits of which are a TTL value, followed by zeroes to
* pad the packet out to the minimum Ethernet packet size.
*
* See also section 7.3.13 "Loop Detection" of
*
* http://realtek.info/pdf/rtl8305sb.pdf
*
* (revision 1.3 of the RTL8305SB datasheet), which describes a similar
* loop detection protocol that lacks the TTL field - all the bytes
* after 0x0300 are zero.
*
* See also section 7.3.7 "Loop Detection" of
*
* https://datasheet.lcsc.com/lcsc/1810221720_Realtek-Semicon-RTL8305NB-CG_C52146.pdf
*
* (revision 1.0 of the RTL8305NB-CT datasheet), which describes a loop
* detection protocol similar to the one from the RTL8306E-CG datasheet,
* except that the first value is 0x2300, not 0x0300.
*
* And, on top of all that, I've seen packets where the first octet of
* the packet is 0x23, and that's followed by 6 unknown octets (a MAC
* address of some sort? It differs from packet to packet in a capture),
* followed by the MAC address that appears in the source address in the
* Ethernet header (possibly the originator, in case the packet is forwarded,
* in which case the forwarded packets won't have the source address from
* the Ethernet header there), followed by unknown stuff (0x0d followed by
* zeroes for all such packets in one capture, 0x01 followed by zeroes for
* all such packets in another capture, 0x07 followed by 0x20's for all
* such packets in yet another capture). The OpenRRCP issue at
* https://github.com/illarionov/OpenRRCP/issues/3 shows a capture
* similar to the last of those, but with 0x02 instead of 0x07. Or is that
* just crap in the buffer in which the chip constructed the packet, left
* over from something else?
*/
void
rtl_print(netdissect_options *ndo,
const u_char *cp,
u_int length _U_,
const struct lladdr_info *src,
const struct lladdr_info *dst)
{
uint8_t rtl_proto;
ndo->ndo_protocol = "rtl";
if (src != NULL && dst != NULL) {
ND_PRINT("%s > %s, ",
(src->addr_string)(ndo, src->addr),
(dst->addr_string)(ndo, dst->addr));
}
rtl_proto = GET_U_1(cp + RTL_PROTOCOL_OFFSET);
if (rtl_proto == RTL_PROTOCOL_RRCP)
rrcp_print(ndo, cp);
else if (rtl_proto == RTL_PROTOCOL_REP) {
/*
* REP packets have no payload.
*/
ND_PRINT("REP");
} else if (rtl_proto == RTL_PROTOCOL_RLDP ||
rtl_proto == RTL_PROTOCOL_RLDP2) {
/*
* RLDP packets have no payload.
* (XXX - except when they do? See above.)
*/
ND_PRINT("RLDP");
} else if (rtl_proto == RTL_PROTOCOL_XXX_DSA)
ND_PRINT("Realtek 8-byte DSA tag");
else if ((rtl_proto & 0xF0) == RTL_PROTOCOL_8306_DSA)
ND_PRINT("Realtek RTL8306 4-byte DSA tag");
else if ((rtl_proto & 0xF0) == RTL_PROTOCOL_8366RB_DSA)
ND_PRINT("Realtek RTL8366RB 4-byte DSA tag");
else
ND_PRINT("Realtek unknown type 0x%02x", rtl_proto);
}
diff --git a/contrib/tcpdump/print-resp.c b/contrib/tcpdump/print-resp.c
index 37a386e3122c..8f0a5380d311 100644
--- a/contrib/tcpdump/print-resp.c
+++ b/contrib/tcpdump/print-resp.c
@@ -1,534 +1,532 @@
/*
* Copyright (c) 2015 The TCPDUMP project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Initial contribution by Andrew Darqui (andrew.darqui@gmail.com).
*/
/* \summary: REdis Serialization Protocol (RESP) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include <limits.h>
#include "extract.h"
/*
* For information regarding RESP, see: https://redis.io/topics/protocol
*/
#define RESP_SIMPLE_STRING '+'
#define RESP_ERROR '-'
#define RESP_INTEGER ':'
#define RESP_BULK_STRING '$'
#define RESP_ARRAY '*'
#define resp_print_empty(ndo) ND_PRINT(" empty")
#define resp_print_null(ndo) ND_PRINT(" null")
#define resp_print_length_too_large(ndo) ND_PRINT(" length too large")
#define resp_print_length_negative(ndo) ND_PRINT(" length negative and not -1")
#define resp_print_invalid(ndo) ND_PRINT(" invalid")
static int resp_parse(netdissect_options *, const u_char *, int);
static int resp_print_string_error_integer(netdissect_options *, const u_char *, int);
static int resp_print_simple_string(netdissect_options *, const u_char *, int);
static int resp_print_integer(netdissect_options *, const u_char *, int);
static int resp_print_error(netdissect_options *, const u_char *, int);
static int resp_print_bulk_string(netdissect_options *, const u_char *, int);
static int resp_print_bulk_array(netdissect_options *, const u_char *, int);
static int resp_print_inline(netdissect_options *, const u_char *, int);
static int resp_get_length(netdissect_options *, const u_char *, int, const u_char **);
#define LCHECK2(_tot_len, _len) \
{ \
if (_tot_len < _len) \
goto trunc; \
}
#define LCHECK(_tot_len) LCHECK2(_tot_len, 1)
/*
* FIND_CRLF:
* Attempts to move our 'ptr' forward until a \r\n is found,
* while also making sure we don't exceed the buffer '_len'
* or go past the end of the captured data.
* If we exceed or go past the end of the captured data,
* jump to trunc.
*/
#define FIND_CRLF(_ptr, _len) \
for (;;) { \
LCHECK2(_len, 2); \
ND_TCHECK_2(_ptr); \
if (GET_U_1(_ptr) == '\r' && \
GET_U_1(_ptr+1) == '\n') \
break; \
_ptr++; \
_len--; \
}
/*
* CONSUME_CRLF
* Consume a CRLF that we've just found.
*/
#define CONSUME_CRLF(_ptr, _len) \
_ptr += 2; \
_len -= 2;
/*
* FIND_CR_OR_LF
* Attempts to move our '_ptr' forward until a \r or \n is found,
* while also making sure we don't exceed the buffer '_len'
* or go past the end of the captured data.
* If we exceed or go past the end of the captured data,
* jump to trunc.
*/
#define FIND_CR_OR_LF(_ptr, _len) \
for (;;) { \
LCHECK(_len); \
if (GET_U_1(_ptr) == '\r' || \
GET_U_1(_ptr) == '\n') \
break; \
_ptr++; \
_len--; \
}
/*
* CONSUME_CR_OR_LF
* Consume all consecutive \r and \n bytes.
* If we exceed '_len' or go past the end of the captured data,
* jump to trunc.
*/
#define CONSUME_CR_OR_LF(_ptr, _len) \
{ \
int _found_cr_or_lf = 0; \
for (;;) { \
/* \
* Have we hit the end of data? \
*/ \
if (_len == 0 || !ND_TTEST_1(_ptr)) {\
/* \
* Yes. Have we seen a \r \
* or \n? \
*/ \
if (_found_cr_or_lf) { \
/* \
* Yes. Just stop. \
*/ \
break; \
} \
/* \
* No. We ran out of packet. \
*/ \
goto trunc; \
} \
if (GET_U_1(_ptr) != '\r' && \
GET_U_1(_ptr) != '\n') \
break; \
_found_cr_or_lf = 1; \
_ptr++; \
_len--; \
} \
}
/*
* SKIP_OPCODE
* Skip over the opcode character.
* The opcode has already been fetched, so we know it's there, and don't
* need to do any checks.
*/
#define SKIP_OPCODE(_ptr, _tot_len) \
_ptr++; \
_tot_len--;
/*
* GET_LENGTH
* Get a bulk string or array length.
*/
#define GET_LENGTH(_ndo, _tot_len, _ptr, _len) \
{ \
const u_char *_endp; \
_len = resp_get_length(_ndo, _ptr, _tot_len, &_endp); \
_tot_len -= (_endp - _ptr); \
_ptr = _endp; \
}
/*
* TEST_RET_LEN
* If ret_len is < 0, jump to the trunc tag which returns (-1)
* and 'bubbles up' to printing tstr. Otherwise, return ret_len.
*/
#define TEST_RET_LEN(rl) \
if (rl < 0) { goto trunc; } else { return rl; }
/*
* TEST_RET_LEN_NORETURN
* If ret_len is < 0, jump to the trunc tag which returns (-1)
* and 'bubbles up' to printing tstr. Otherwise, continue onward.
*/
#define TEST_RET_LEN_NORETURN(rl) \
if (rl < 0) { goto trunc; }
/*
* RESP_PRINT_SEGMENT
* Prints a segment in the form of: ' "<stuff>"\n"
* Assumes the data has already been verified as present.
*/
#define RESP_PRINT_SEGMENT(_ndo, _bp, _len) \
ND_PRINT(" \""); \
if (nd_printn(_ndo, _bp, _len, _ndo->ndo_snapend)) \
goto trunc; \
fn_print_char(_ndo, '"');
void
resp_print(netdissect_options *ndo, const u_char *bp, u_int length)
{
int ret_len = 0;
ndo->ndo_protocol = "resp";
ND_PRINT(": RESP");
while (length > 0) {
/*
* This block supports redis pipelining.
* For example, multiple operations can be pipelined within the same string:
* "*2\r\n\$4\r\nINCR\r\n\$1\r\nz\r\n*2\r\n\$4\r\nINCR\r\n\$1\r\nz\r\n*2\r\n\$4\r\nINCR\r\n\$1\r\nz\r\n"
* or
* "PING\r\nPING\r\nPING\r\n"
* In order to handle this case, we must try and parse 'bp' until
* 'length' bytes have been processed or we reach a trunc condition.
*/
ret_len = resp_parse(ndo, bp, length);
TEST_RET_LEN_NORETURN(ret_len);
bp += ret_len;
length -= ret_len;
}
return;
trunc:
nd_print_trunc(ndo);
}
static int
resp_parse(netdissect_options *ndo, const u_char *bp, int length)
{
u_char op;
int ret_len;
LCHECK2(length, 1);
op = GET_U_1(bp);
/* bp now points to the op, so these routines must skip it */
switch(op) {
case RESP_SIMPLE_STRING: ret_len = resp_print_simple_string(ndo, bp, length); break;
case RESP_INTEGER: ret_len = resp_print_integer(ndo, bp, length); break;
case RESP_ERROR: ret_len = resp_print_error(ndo, bp, length); break;
case RESP_BULK_STRING: ret_len = resp_print_bulk_string(ndo, bp, length); break;
case RESP_ARRAY: ret_len = resp_print_bulk_array(ndo, bp, length); break;
default: ret_len = resp_print_inline(ndo, bp, length); break;
}
/*
* This gives up with a "truncated" indicator for all errors,
* including invalid packet errors; that's what we want, as
* we have to give up on further parsing in that case.
*/
TEST_RET_LEN(ret_len);
trunc:
return (-1);
}
static int
resp_print_simple_string(netdissect_options *ndo, const u_char *bp, int length) {
return resp_print_string_error_integer(ndo, bp, length);
}
static int
resp_print_integer(netdissect_options *ndo, const u_char *bp, int length) {
return resp_print_string_error_integer(ndo, bp, length);
}
static int
resp_print_error(netdissect_options *ndo, const u_char *bp, int length) {
return resp_print_string_error_integer(ndo, bp, length);
}
static int
resp_print_string_error_integer(netdissect_options *ndo, const u_char *bp, int length) {
int length_cur = length, len, ret_len;
const u_char *bp_ptr;
/* bp points to the op; skip it */
SKIP_OPCODE(bp, length_cur);
bp_ptr = bp;
/*
* bp now prints past the (+-;) opcode, so it's pointing to the first
* character of the string (which could be numeric).
* +OK\r\n
* -ERR ...\r\n
* :02912309\r\n
*
* Find the \r\n with FIND_CRLF().
*/
FIND_CRLF(bp_ptr, length_cur);
/*
* bp_ptr points to the \r\n, so bp_ptr - bp is the length of text
* preceding the \r\n. That includes the opcode, so don't print
* that.
*/
- len = ND_BYTES_BETWEEN(bp_ptr, bp);
+ len = ND_BYTES_BETWEEN(bp, bp_ptr);
RESP_PRINT_SEGMENT(ndo, bp, len);
ret_len = 1 /*<opcode>*/ + len /*<string>*/ + 2 /*<CRLF>*/;
TEST_RET_LEN(ret_len);
trunc:
return (-1);
}
static int
resp_print_bulk_string(netdissect_options *ndo, const u_char *bp, int length) {
int length_cur = length, string_len;
/* bp points to the op; skip it */
SKIP_OPCODE(bp, length_cur);
/* <length>\r\n */
GET_LENGTH(ndo, length_cur, bp, string_len);
if (string_len >= 0) {
/* Byte string of length string_len, starting at bp */
if (string_len == 0)
resp_print_empty(ndo);
else {
LCHECK2(length_cur, string_len);
ND_TCHECK_LEN(bp, string_len);
RESP_PRINT_SEGMENT(ndo, bp, string_len);
bp += string_len;
length_cur -= string_len;
}
/*
* Find the \r\n at the end of the string and skip past it.
* XXX - report an error if the \r\n isn't immediately after
* the item?
*/
FIND_CRLF(bp, length_cur);
CONSUME_CRLF(bp, length_cur);
} else {
/* null, truncated, or invalid for some reason */
switch(string_len) {
case (-1): resp_print_null(ndo); break;
case (-2): goto trunc;
case (-3): resp_print_length_too_large(ndo); break;
case (-4): resp_print_length_negative(ndo); break;
default: resp_print_invalid(ndo); break;
}
}
return (length - length_cur);
trunc:
return (-1);
}
static int
resp_print_bulk_array(netdissect_options *ndo, const u_char *bp, int length) {
u_int length_cur = length;
int array_len, i, ret_len;
/* bp points to the op; skip it */
SKIP_OPCODE(bp, length_cur);
/* <array_length>\r\n */
GET_LENGTH(ndo, length_cur, bp, array_len);
if (array_len > 0) {
/* non empty array */
for (i = 0; i < array_len; i++) {
ret_len = resp_parse(ndo, bp, length_cur);
TEST_RET_LEN_NORETURN(ret_len);
bp += ret_len;
length_cur -= ret_len;
}
} else {
/* empty, null, truncated, or invalid */
switch(array_len) {
case 0: resp_print_empty(ndo); break;
case (-1): resp_print_null(ndo); break;
case (-2): goto trunc;
case (-3): resp_print_length_too_large(ndo); break;
case (-4): resp_print_length_negative(ndo); break;
default: resp_print_invalid(ndo); break;
}
}
return (length - length_cur);
trunc:
return (-1);
}
static int
resp_print_inline(netdissect_options *ndo, const u_char *bp, int length) {
int length_cur = length;
int len;
const u_char *bp_ptr;
/*
* Inline commands are simply 'strings' followed by \r or \n or both.
* Redis will do its best to split/parse these strings.
* This feature of redis is implemented to support the ability of
* command parsing from telnet/nc sessions etc.
*
* <string><\r||\n||\r\n...>
*/
/*
* Skip forward past any leading \r, \n, or \r\n.
*/
CONSUME_CR_OR_LF(bp, length_cur);
bp_ptr = bp;
/*
* Scan forward looking for \r or \n.
*/
FIND_CR_OR_LF(bp_ptr, length_cur);
/*
* Found it; bp_ptr points to the \r or \n, so bp_ptr - bp is the
* Length of the line text that precedes it. Print it.
*/
- len = ND_BYTES_BETWEEN(bp_ptr, bp);
+ len = ND_BYTES_BETWEEN(bp, bp_ptr);
RESP_PRINT_SEGMENT(ndo, bp, len);
/*
* Skip forward past the \r, \n, or \r\n.
*/
CONSUME_CR_OR_LF(bp_ptr, length_cur);
/*
* Return the number of bytes we processed.
*/
return (length - length_cur);
trunc:
return (-1);
}
static int
resp_get_length(netdissect_options *ndo, const u_char *bp, int len, const u_char **endp)
{
int result;
u_char c;
int saw_digit;
int neg;
int too_large;
if (len == 0)
goto trunc;
too_large = 0;
neg = 0;
if (GET_U_1(bp) == '-') {
neg = 1;
bp++;
len--;
}
result = 0;
saw_digit = 0;
for (;;) {
if (len == 0)
goto trunc;
c = GET_U_1(bp);
if (!(c >= '0' && c <= '9')) {
if (!saw_digit) {
bp++;
goto invalid;
}
break;
}
c -= '0';
if (result > (INT_MAX / 10)) {
/* This will overflow an int when we multiply it by 10. */
too_large = 1;
} else {
result *= 10;
if (result == ((INT_MAX / 10) * 10) && c > (INT_MAX % 10)) {
/* This will overflow an int when we add c */
too_large = 1;
} else
result += c;
}
bp++;
len--;
saw_digit = 1;
}
/*
* OK, we found a non-digit character. It should be a \r, followed
* by a \n.
*/
if (GET_U_1(bp) != '\r') {
bp++;
goto invalid;
}
bp++;
len--;
if (len == 0)
goto trunc;
if (GET_U_1(bp) != '\n') {
bp++;
goto invalid;
}
bp++;
len--;
*endp = bp;
if (neg) {
/* -1 means "null", anything else is invalid */
if (too_large || result != 1)
return (-4);
result = -1;
}
return (too_large ? -3 : result);
trunc:
*endp = bp;
return (-2);
invalid:
*endp = bp;
return (-5);
}
diff --git a/contrib/tcpdump/print-rip.c b/contrib/tcpdump/print-rip.c
index fca534fb100b..aac3e4598983 100644
--- a/contrib/tcpdump/print-rip.c
+++ b/contrib/tcpdump/print-rip.c
@@ -1,422 +1,416 @@
/*
* Copyright (c) 1989, 1990, 1991, 1993, 1994, 1996
* 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.
*/
/* \summary: Routing Information Protocol (RIP) printer */
/* specification: RFC 1058, RFC 2453, RFC 4822 */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#include "af.h"
/*
* RFC 1058 and RFC 2453 header of packet.
*
* 0 1 2 3 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Command (1) | Version (1) | unused |
* +---------------+---------------+-------------------------------+
*/
struct rip {
nd_uint8_t rip_cmd; /* request/response */
nd_uint8_t rip_vers; /* protocol version # */
nd_byte unused[2]; /* unused */
};
#define RIPCMD_REQUEST 1 /* want info */
#define RIPCMD_RESPONSE 2 /* responding to request */
#define RIPCMD_TRACEON 3 /* turn tracing on */
#define RIPCMD_TRACEOFF 4 /* turn it off */
-#define RIPCMD_POLL 5 /* want info from everybody */
-#define RIPCMD_POLLENTRY 6 /* poll for entry */
+/* 5 is reserved */
+#define RIPCMD_TRIGREQ 6
+#define RIPCMD_TRIGRESP 7
+#define RIPCMD_TRIGACK 8
+#define RIPCMD_UPDREQ 9
+#define RIPCMD_UPDRESP 10
+#define RIPCMD_UPDACK 11
static const struct tok rip_cmd_values[] = {
{ RIPCMD_REQUEST, "Request" },
{ RIPCMD_RESPONSE, "Response" },
{ RIPCMD_TRACEON, "Trace on" },
{ RIPCMD_TRACEOFF, "Trace off" },
- { RIPCMD_POLL, "Poll" },
- { RIPCMD_POLLENTRY, "Poll Entry" },
+ { RIPCMD_TRIGREQ, "Triggered Request" },
+ { RIPCMD_TRIGRESP, "Triggered Response" },
+ { RIPCMD_TRIGACK, "Triggered Acknowledgement" },
+ { RIPCMD_UPDREQ, "Update Request" },
+ { RIPCMD_UPDRESP, "Update Response" },
+ { RIPCMD_UPDACK, "Update Acknowledge" },
{ 0, NULL}
};
#define RIP_AUTHLEN 16
#define RIP_ROUTELEN 20
/*
* First 4 bytes of all RIPv1/RIPv2 entries.
*/
struct rip_entry_header {
nd_uint16_t rip_family;
nd_uint16_t rip_tag;
};
/*
* RFC 1058 entry.
*
* 0 1 2 3 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Address Family Identifier (2) | must be zero (2) |
* +-------------------------------+-------------------------------+
* | IP Address (4) |
* +---------------------------------------------------------------+
* | must be zero (4) |
* +---------------------------------------------------------------+
* | must be zero (4) |
* +---------------------------------------------------------------+
* | Metric (4) |
* +---------------------------------------------------------------+
*/
struct rip_netinfo_v1 {
nd_uint16_t rip_family;
nd_byte rip_mbz1[2];
nd_ipv4 rip_dest;
nd_byte rip_mbz2[4];
nd_byte rip_mbz3[4];
nd_uint32_t rip_metric; /* cost of route */
};
/*
* RFC 2453 route entry
*
* 0 1 2 3 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Address Family Identifier (2) | Route Tag (2) |
* +-------------------------------+-------------------------------+
* | IP Address (4) |
* +---------------------------------------------------------------+
* | Subnet Mask (4) |
* +---------------------------------------------------------------+
* | Next Hop (4) |
* +---------------------------------------------------------------+
* | Metric (4) |
* +---------------------------------------------------------------+
*
*/
struct rip_netinfo_v2 {
nd_uint16_t rip_family;
nd_uint16_t rip_tag;
nd_ipv4 rip_dest;
nd_uint32_t rip_dest_mask;
nd_ipv4 rip_router;
nd_uint32_t rip_metric; /* cost of route */
};
/*
* RFC 2453 authentication entry
*
* 0 1 2 3 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 0xFFFF | Authentication Type (2) |
* +-------------------------------+-------------------------------+
* - Authentication (16) -
* +---------------------------------------------------------------+
*/
struct rip_auth_v2 {
nd_uint16_t rip_family;
nd_uint16_t rip_tag;
nd_byte rip_auth[16];
};
/*
* RFC 4822 Cryptographic Authentication entry.
*
* 0 1 2 3 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | RIPv2 Packet Length | Key ID | Auth Data Len |
* +---------------+---------------+---------------+---------------+
* | Sequence Number (non-decreasing) |
* +---------------+---------------+---------------+---------------+
* | reserved must be zero |
* +---------------+---------------+---------------+---------------+
* | reserved must be zero |
* +---------------+---------------+---------------+---------------+
*/
struct rip_auth_crypto_v2 {
nd_uint16_t rip_packet_len;
nd_uint8_t rip_key_id;
nd_uint8_t rip_auth_data_len;
nd_uint32_t rip_seq_num;
nd_byte rip_mbz1[4];
nd_byte rip_mbz2[4];
};
static unsigned
rip_entry_print_v1(netdissect_options *ndo, const u_char *p,
unsigned remaining)
{
const struct rip_entry_header *eh = (const struct rip_entry_header *)p;
u_short family;
const struct rip_netinfo_v1 *ni = (const struct rip_netinfo_v1 *)p;
/* RFC 1058 */
if (remaining < RIP_ROUTELEN)
return (0);
ND_TCHECK_SIZE(ni);
family = GET_BE_U_2(ni->rip_family);
if (family != BSD_AFNUM_INET && family != 0) {
ND_PRINT("\n\t AFI %s, ", tok2str(bsd_af_values, "Unknown (%u)", family));
print_unknown_data(ndo, p + sizeof(*eh), "\n\t ", RIP_ROUTELEN - sizeof(*eh));
return (RIP_ROUTELEN);
}
if (GET_BE_U_2(ni->rip_mbz1) ||
GET_BE_U_4(ni->rip_mbz2) ||
GET_BE_U_4(ni->rip_mbz3)) {
/* MBZ fields not zero */
print_unknown_data(ndo, p, "\n\t ", RIP_ROUTELEN);
return (RIP_ROUTELEN);
}
if (family == 0) {
ND_PRINT("\n\t AFI 0, %s, metric: %u",
GET_IPADDR_STRING(ni->rip_dest),
GET_BE_U_4(ni->rip_metric));
return (RIP_ROUTELEN);
} /* BSD_AFNUM_INET */
ND_PRINT("\n\t %s, metric: %u",
GET_IPADDR_STRING(ni->rip_dest),
GET_BE_U_4(ni->rip_metric));
return (RIP_ROUTELEN);
trunc:
return 0;
}
static unsigned
rip_entry_print_v2(netdissect_options *ndo, const u_char *p,
unsigned remaining)
{
const struct rip_entry_header *eh = (const struct rip_entry_header *)p;
u_short family;
const struct rip_netinfo_v2 *ni;
if (remaining < sizeof(*eh))
return (0);
ND_TCHECK_SIZE(eh);
family = GET_BE_U_2(eh->rip_family);
if (family == 0xFFFF) { /* variable-sized authentication structures */
uint16_t auth_type = GET_BE_U_2(eh->rip_tag);
p += sizeof(*eh);
remaining -= sizeof(*eh);
if (auth_type == 2) {
ND_PRINT("\n\t Simple Text Authentication data: ");
nd_printjnp(ndo, p, RIP_AUTHLEN);
} else if (auth_type == 3) {
const struct rip_auth_crypto_v2 *ch;
ch = (const struct rip_auth_crypto_v2 *)p;
ND_TCHECK_SIZE(ch);
if (remaining < sizeof(*ch))
return (0);
ND_PRINT("\n\t Auth header:");
ND_PRINT(" Packet Len %u,",
GET_BE_U_2(ch->rip_packet_len));
ND_PRINT(" Key-ID %u,", GET_U_1(ch->rip_key_id));
ND_PRINT(" Auth Data Len %u,",
GET_U_1(ch->rip_auth_data_len));
ND_PRINT(" SeqNo %u,", GET_BE_U_4(ch->rip_seq_num));
ND_PRINT(" MBZ %u,", GET_BE_U_4(ch->rip_mbz1));
ND_PRINT(" MBZ %u", GET_BE_U_4(ch->rip_mbz2));
} else if (auth_type == 1) {
ND_PRINT("\n\t Auth trailer:");
print_unknown_data(ndo, p, "\n\t ", remaining);
return (sizeof(*eh) + remaining); /* AT spans till the packet end */
} else {
ND_PRINT("\n\t Unknown (%u) Authentication data:",
auth_type);
print_unknown_data(ndo, p, "\n\t ", remaining);
return (sizeof(*eh) + remaining); /* we don't know how long this is, so we go to the packet end */
}
} else if (family != BSD_AFNUM_INET && family != 0) {
ND_PRINT("\n\t AFI %s", tok2str(bsd_af_values, "Unknown (%u)", family));
print_unknown_data(ndo, p + sizeof(*eh), "\n\t ", RIP_ROUTELEN - sizeof(*eh));
} else { /* BSD_AFNUM_INET or AFI 0 */
ni = (const struct rip_netinfo_v2 *)p;
ND_TCHECK_SIZE(ni);
if (remaining < sizeof(*ni))
return (0);
ND_PRINT("\n\t AFI %s, %15s/%-2d, tag 0x%04x, metric: %u, next-hop: ",
tok2str(bsd_af_values, "%u", family),
GET_IPADDR_STRING(ni->rip_dest),
mask2plen(GET_BE_U_4(ni->rip_dest_mask)),
GET_BE_U_2(ni->rip_tag),
GET_BE_U_4(ni->rip_metric));
if (GET_BE_U_4(ni->rip_router))
ND_PRINT("%s", GET_IPADDR_STRING(ni->rip_router));
else
ND_PRINT("self");
}
return (RIP_ROUTELEN);
trunc:
return 0;
}
void
rip_print(netdissect_options *ndo,
const u_char *dat, u_int length)
{
const struct rip *rp;
uint8_t vers, cmd;
const u_char *p;
u_int len, routecount;
unsigned entry_size;
ndo->ndo_protocol = "rip";
if (ndo->ndo_snapend < dat) {
nd_print_trunc(ndo);
return;
}
len = ND_BYTES_AVAILABLE_AFTER(dat);
if (len > length)
len = length;
if (len < sizeof(*rp)) {
nd_print_trunc(ndo);
return;
}
len -= sizeof(*rp);
rp = (const struct rip *)dat;
ND_TCHECK_SIZE(rp);
vers = GET_U_1(rp->rip_vers);
ND_PRINT("%sRIPv%u",
(ndo->ndo_vflag >= 1) ? "\n\t" : "",
vers);
- if (vers == 0) {
- /*
- * RFC 1058.
- *
- * XXX - RFC 1058 says
- *
- * 0 Datagrams whose version number is zero are to be ignored.
- * These are from a previous version of the protocol, whose
- * packet format was machine-specific.
- *
- * so perhaps we should just dump the packet, in hex.
- */
- print_unknown_data(ndo, (const uint8_t *)&rp->rip_cmd, "\n\t", length);
- return;
- }
-
/* dump version and lets see if we know the commands name*/
cmd = GET_U_1(rp->rip_cmd);
ND_PRINT(", %s, length: %u",
tok2str(rip_cmd_values, "unknown command (%u)", cmd),
length);
if (ndo->ndo_vflag < 1)
return;
switch (cmd) {
case RIPCMD_REQUEST:
case RIPCMD_RESPONSE:
switch (vers) {
case 1:
routecount = length / RIP_ROUTELEN;
ND_PRINT(", routes: %u", routecount);
p = (const u_char *)(rp + 1);
while (len != 0) {
entry_size = rip_entry_print_v1(ndo, p, len);
if (entry_size == 0) {
/* Error */
nd_print_trunc(ndo);
break;
}
if (len < entry_size) {
ND_PRINT(" [remaining entries length %u < %u]",
len, entry_size);
nd_print_invalid(ndo);
break;
}
p += entry_size;
len -= entry_size;
}
break;
case 2:
routecount = length / RIP_ROUTELEN;
ND_PRINT(", routes: %u or less", routecount);
p = (const u_char *)(rp + 1);
while (len != 0) {
entry_size = rip_entry_print_v2(ndo, p, len);
if (entry_size == 0) {
/* Error */
nd_print_trunc(ndo);
break;
}
if (len < entry_size) {
ND_PRINT(" [remaining entries length %u < %u]",
len, entry_size);
nd_print_invalid(ndo);
break;
}
p += entry_size;
len -= entry_size;
}
break;
default:
ND_PRINT(", unknown version");
break;
}
break;
+ case RIPCMD_TRACEON:
case RIPCMD_TRACEOFF:
- case RIPCMD_POLL:
- case RIPCMD_POLLENTRY:
+ case RIPCMD_TRIGREQ:
+ case RIPCMD_TRIGRESP:
+ case RIPCMD_TRIGACK:
+ case RIPCMD_UPDREQ:
+ case RIPCMD_UPDRESP:
+ case RIPCMD_UPDACK:
break;
- case RIPCMD_TRACEON:
- /* fall through */
default:
if (ndo->ndo_vflag <= 1) {
if (!print_unknown_data(ndo, (const uint8_t *)rp, "\n\t", length))
return;
}
break;
}
/* do we want to see an additionally hexdump ? */
if (ndo->ndo_vflag> 1) {
if (!print_unknown_data(ndo, (const uint8_t *)rp, "\n\t", length))
return;
}
trunc:
return;
}
diff --git a/contrib/tcpdump/print-ripng.c b/contrib/tcpdump/print-ripng.c
index 94ebf1bc4c4e..c6955cb8ef14 100644
--- a/contrib/tcpdump/print-ripng.c
+++ b/contrib/tcpdump/print-ripng.c
@@ -1,184 +1,182 @@
/*
* Copyright (c) 1989, 1990, 1991, 1993, 1994
* 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.
*/
/* \summary: IPv6 Routing Information Protocol (RIPng) printer */
/* specification: RFC 2080 */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
/*
* Copyright (C) 1995, 1996, 1997 and 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project 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 BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#define RIP6_VERSION 1
#define RIP6_REQUEST 1
#define RIP6_RESPONSE 2
struct netinfo6 {
nd_ipv6 rip6_dest;
nd_uint16_t rip6_tag;
nd_uint8_t rip6_plen;
nd_uint8_t rip6_metric;
};
struct rip6 {
nd_uint8_t rip6_cmd;
nd_uint8_t rip6_vers;
nd_byte rip6_res1[2];
struct netinfo6 rip6_nets[1];
};
#define HOPCNT_INFINITY6 16
static int ND_IN6_IS_ADDR_UNSPECIFIED(const nd_ipv6 *addr)
{
static const nd_ipv6 in6addr_any_val = { 0 }; /* :: */
return (memcmp(addr, &in6addr_any_val, sizeof(*addr)) == 0);
}
static void
rip6_entry_print(netdissect_options *ndo,
const struct netinfo6 *ni, const u_int print_metric)
{
uint16_t tag;
uint8_t metric;
ND_PRINT("%s/%u", GET_IP6ADDR_STRING(ni->rip6_dest),
GET_U_1(ni->rip6_plen));
tag = GET_BE_U_2(ni->rip6_tag);
if (tag)
ND_PRINT(" [%u]", tag);
metric = GET_U_1(ni->rip6_metric);
if (metric && print_metric)
ND_PRINT(" (%u)", metric);
}
void
ripng_print(netdissect_options *ndo, const u_char *dat, unsigned int length)
{
const struct rip6 *rp = (const struct rip6 *)dat;
uint8_t cmd, vers;
const struct netinfo6 *ni;
unsigned int length_left;
u_int j;
ndo->ndo_protocol = "ripng";
vers = GET_U_1(rp->rip6_vers);
if (vers != RIP6_VERSION) {
nd_print_protocol(ndo);
ND_PRINT(" [version %u, must be %u]", vers, RIP6_VERSION);
goto invalid;
}
cmd = GET_U_1(rp->rip6_cmd);
switch (cmd) {
case RIP6_REQUEST:
length_left = length;
if (length_left < (sizeof(struct rip6) - sizeof(struct netinfo6)))
goto invalid;
length_left -= (sizeof(struct rip6) - sizeof(struct netinfo6));
j = length_left / sizeof(*ni);
if (j == 1) {
if (GET_U_1(rp->rip6_nets->rip6_metric) == HOPCNT_INFINITY6
&& ND_IN6_IS_ADDR_UNSPECIFIED(&rp->rip6_nets->rip6_dest)) {
ND_PRINT(" ripng-req dump");
break;
}
}
if (j * sizeof(*ni) != length_left)
ND_PRINT(" ripng-req %u[%u]:", j, length);
else
ND_PRINT(" ripng-req %u:", j);
for (ni = rp->rip6_nets; length_left >= sizeof(*ni);
length_left -= sizeof(*ni), ++ni) {
if (ndo->ndo_vflag > 1)
ND_PRINT("\n\t");
else
ND_PRINT(" ");
rip6_entry_print(ndo, ni, FALSE);
}
if (length_left != 0)
goto invalid;
break;
case RIP6_RESPONSE:
length_left = length;
if (length_left < (sizeof(struct rip6) - sizeof(struct netinfo6)))
goto invalid;
length_left -= (sizeof(struct rip6) - sizeof(struct netinfo6));
j = length_left / sizeof(*ni);
if (j * sizeof(*ni) != length_left)
ND_PRINT(" ripng-resp %u[%u]:", j, length);
else
ND_PRINT(" ripng-resp %u:", j);
for (ni = rp->rip6_nets; length_left >= sizeof(*ni);
length_left -= sizeof(*ni), ++ni) {
if (ndo->ndo_vflag > 1)
ND_PRINT("\n\t");
else
ND_PRINT(" ");
rip6_entry_print(ndo, ni, TRUE);
}
if (length_left != 0)
goto invalid;
break;
default:
ND_PRINT(" ripng-%u ?? %u", cmd, length);
goto invalid;
}
return;
invalid:
nd_print_invalid(ndo);
}
diff --git a/contrib/tcpdump/print-rpki-rtr.c b/contrib/tcpdump/print-rpki-rtr.c
index 36be3998a326..7d8d9a1d74a1 100644
--- a/contrib/tcpdump/print-rpki-rtr.c
+++ b/contrib/tcpdump/print-rpki-rtr.c
@@ -1,391 +1,385 @@
/*
* Copyright (c) 1998-2011 The TCPDUMP project
*
* 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.
*
* Original code by Hannes Gredler (hannes@gredler.at)
*/
/* \summary: Resource Public Key Infrastructure (RPKI) to Router Protocol printer */
/* specification: RFC 6810 */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
#include "addrtoname.h"
/*
* RPKI/Router PDU header
*
* Here's what the PDU header looks like.
* The length does include the version and length fields.
*/
typedef struct rpki_rtr_pdu_ {
nd_uint8_t version; /* Version number */
nd_uint8_t pdu_type; /* PDU type */
union {
nd_uint16_t session_id; /* Session id */
nd_uint16_t error_code; /* Error code */
} u;
nd_uint32_t length;
} rpki_rtr_pdu;
/*
* IPv4 Prefix PDU.
*/
typedef struct rpki_rtr_pdu_ipv4_prefix_ {
rpki_rtr_pdu pdu_header;
nd_uint8_t flags;
nd_uint8_t prefix_length;
nd_uint8_t max_length;
nd_uint8_t zero;
nd_ipv4 prefix;
nd_uint32_t as;
} rpki_rtr_pdu_ipv4_prefix;
/*
* IPv6 Prefix PDU.
*/
typedef struct rpki_rtr_pdu_ipv6_prefix_ {
rpki_rtr_pdu pdu_header;
nd_uint8_t flags;
nd_uint8_t prefix_length;
nd_uint8_t max_length;
nd_uint8_t zero;
nd_ipv6 prefix;
nd_uint32_t as;
} rpki_rtr_pdu_ipv6_prefix;
/*
* Error report PDU.
*/
typedef struct rpki_rtr_pdu_error_report_ {
rpki_rtr_pdu pdu_header;
nd_uint32_t encapsulated_pdu_length; /* Encapsulated PDU length */
/* Copy of Erroneous PDU (variable, optional) */
/* Length of Error Text (4 octets in network byte order) */
/* Arbitrary Text of Error Diagnostic Message (variable, optional) */
} rpki_rtr_pdu_error_report;
/*
* PDU type codes
*/
#define RPKI_RTR_SERIAL_NOTIFY_PDU 0
#define RPKI_RTR_SERIAL_QUERY_PDU 1
#define RPKI_RTR_RESET_QUERY_PDU 2
#define RPKI_RTR_CACHE_RESPONSE_PDU 3
#define RPKI_RTR_IPV4_PREFIX_PDU 4
#define RPKI_RTR_IPV6_PREFIX_PDU 6
#define RPKI_RTR_END_OF_DATA_PDU 7
#define RPKI_RTR_CACHE_RESET_PDU 8
#define RPKI_RTR_ERROR_REPORT_PDU 10
static const struct tok rpki_rtr_pdu_values[] = {
{ RPKI_RTR_SERIAL_NOTIFY_PDU, "Serial Notify" },
{ RPKI_RTR_SERIAL_QUERY_PDU, "Serial Query" },
{ RPKI_RTR_RESET_QUERY_PDU, "Reset Query" },
{ RPKI_RTR_CACHE_RESPONSE_PDU, "Cache Response" },
{ RPKI_RTR_IPV4_PREFIX_PDU, "IPV4 Prefix" },
{ RPKI_RTR_IPV6_PREFIX_PDU, "IPV6 Prefix" },
{ RPKI_RTR_END_OF_DATA_PDU, "End of Data" },
{ RPKI_RTR_CACHE_RESET_PDU, "Cache Reset" },
{ RPKI_RTR_ERROR_REPORT_PDU, "Error Report" },
{ 0, NULL}
};
static const struct tok rpki_rtr_error_codes[] = {
{ 0, "Corrupt Data" },
{ 1, "Internal Error" },
{ 2, "No Data Available" },
{ 3, "Invalid Request" },
{ 4, "Unsupported Protocol Version" },
{ 5, "Unsupported PDU Type" },
{ 6, "Withdrawal of Unknown Record" },
{ 7, "Duplicate Announcement Received" },
{ 0, NULL}
};
/*
* Build a indentation string for a given indentation level.
* XXX this should be really in util.c
*/
static char *
indent_string (u_int indent)
{
static char buf[20];
u_int idx;
idx = 0;
buf[idx] = '\0';
/*
* Does the static buffer fit ?
*/
if (sizeof(buf) < ((indent/8) + (indent %8) + 2)) {
return buf;
}
/*
* Heading newline.
*/
buf[idx] = '\n';
idx++;
while (indent >= 8) {
buf[idx] = '\t';
idx++;
indent -= 8;
}
while (indent > 0) {
buf[idx] = ' ';
idx++;
indent--;
}
/*
* Trailing zero.
*/
buf[idx] = '\0';
return buf;
}
/*
* Print a single PDU.
*/
static u_int
rpki_rtr_pdu_print(netdissect_options *ndo, const u_char *tptr, const u_int len,
const u_char recurse, const u_int indent)
{
const rpki_rtr_pdu *pdu_header;
u_int pdu_type, pdu_len, hexdump;
const u_char *msg;
+ uint8_t pdu_ver;
- /* Protocol Version */
- if (GET_U_1(tptr) != 0) {
+ if (len < sizeof(rpki_rtr_pdu)) {
+ ND_PRINT("(%u bytes is too few to decode)", len);
+ goto invalid;
+ }
+ pdu_header = (const rpki_rtr_pdu *)tptr;
+ pdu_ver = GET_U_1(pdu_header->version);
+ if (pdu_ver != 0) {
/* Skip the rest of the input buffer because even if this is
* a well-formed PDU of a future RPKI-Router protocol version
* followed by a well-formed PDU of RPKI-Router protocol
* version 0, there is no way to know exactly how to skip the
* current PDU.
*/
- ND_PRINT("%sRPKI-RTRv%u (unknown)", indent_string(8), GET_U_1(tptr));
+ ND_PRINT("%sRPKI-RTRv%u (unknown)", indent_string(8), pdu_ver);
return len;
}
- if (len < sizeof(rpki_rtr_pdu)) {
- ND_PRINT("(%u bytes is too few to decode)", len);
- goto invalid;
- }
- ND_TCHECK_LEN(tptr, sizeof(rpki_rtr_pdu));
- pdu_header = (const rpki_rtr_pdu *)tptr;
pdu_type = GET_U_1(pdu_header->pdu_type);
pdu_len = GET_BE_U_4(pdu_header->length);
/* Do not check bounds with pdu_len yet, do it in the case blocks
* below to make it possible to decode at least the beginning of
* a truncated Error Report PDU or a truncated encapsulated PDU.
*/
hexdump = FALSE;
ND_PRINT("%sRPKI-RTRv%u, %s PDU (%u), length: %u",
indent_string(8),
- GET_U_1(pdu_header->version),
+ pdu_ver,
tok2str(rpki_rtr_pdu_values, "Unknown", pdu_type),
pdu_type, pdu_len);
if (pdu_len < sizeof(rpki_rtr_pdu) || pdu_len > len)
goto invalid;
switch (pdu_type) {
/*
* The following PDUs share the message format.
*/
case RPKI_RTR_SERIAL_NOTIFY_PDU:
case RPKI_RTR_SERIAL_QUERY_PDU:
case RPKI_RTR_END_OF_DATA_PDU:
if (pdu_len != sizeof(rpki_rtr_pdu) + 4)
goto invalid;
msg = (const u_char *)(pdu_header + 1);
ND_PRINT("%sSession ID: 0x%04x, Serial: %u",
indent_string(indent+2),
GET_BE_U_2(pdu_header->u.session_id),
GET_BE_U_4(msg));
break;
/*
* The following PDUs share the message format.
*/
case RPKI_RTR_RESET_QUERY_PDU:
case RPKI_RTR_CACHE_RESET_PDU:
if (pdu_len != sizeof(rpki_rtr_pdu))
goto invalid;
/* no additional boundary to check */
/*
* Zero payload PDUs.
*/
break;
case RPKI_RTR_CACHE_RESPONSE_PDU:
if (pdu_len != sizeof(rpki_rtr_pdu))
goto invalid;
/* no additional boundary to check */
ND_PRINT("%sSession ID: 0x%04x",
indent_string(indent+2),
GET_BE_U_2(pdu_header->u.session_id));
break;
case RPKI_RTR_IPV4_PREFIX_PDU:
{
const rpki_rtr_pdu_ipv4_prefix *pdu;
if (pdu_len != sizeof(rpki_rtr_pdu_ipv4_prefix))
goto invalid;
pdu = (const rpki_rtr_pdu_ipv4_prefix *)tptr;
ND_PRINT("%sIPv4 Prefix %s/%u-%u, origin-as %u, flags 0x%02x",
indent_string(indent+2),
GET_IPADDR_STRING(pdu->prefix),
GET_U_1(pdu->prefix_length), GET_U_1(pdu->max_length),
GET_BE_U_4(pdu->as), GET_U_1(pdu->flags));
}
break;
case RPKI_RTR_IPV6_PREFIX_PDU:
{
const rpki_rtr_pdu_ipv6_prefix *pdu;
if (pdu_len != sizeof(rpki_rtr_pdu_ipv6_prefix))
goto invalid;
pdu = (const rpki_rtr_pdu_ipv6_prefix *)tptr;
ND_PRINT("%sIPv6 Prefix %s/%u-%u, origin-as %u, flags 0x%02x",
indent_string(indent+2),
GET_IP6ADDR_STRING(pdu->prefix),
GET_U_1(pdu->prefix_length), GET_U_1(pdu->max_length),
GET_BE_U_4(pdu->as), GET_U_1(pdu->flags));
}
break;
case RPKI_RTR_ERROR_REPORT_PDU:
{
const rpki_rtr_pdu_error_report *pdu;
u_int encapsulated_pdu_length, text_length, tlen, error_code;
tlen = sizeof(rpki_rtr_pdu);
/* Do not test for the "Length of Error Text" data element yet. */
if (pdu_len < tlen + 4)
goto invalid;
- ND_TCHECK_LEN(tptr, tlen + 4);
- /* Safe up to and including the "Length of Encapsulated PDU"
- * data element, more data elements may be present.
- */
pdu = (const rpki_rtr_pdu_error_report *)tptr;
encapsulated_pdu_length = GET_BE_U_4(pdu->encapsulated_pdu_length);
tlen += 4;
+ /* Safe up to and including the "Length of Encapsulated PDU"
+ * data element, more data elements may be present.
+ */
error_code = GET_BE_U_2(pdu->pdu_header.u.error_code);
ND_PRINT("%sError code: %s (%u), Encapsulated PDU length: %u",
indent_string(indent+2),
tok2str(rpki_rtr_error_codes, "Unknown", error_code),
error_code, encapsulated_pdu_length);
if (encapsulated_pdu_length) {
/* Section 5.10 of RFC 6810 says:
* "An Error Report PDU MUST NOT be sent for an Error Report PDU."
*
* However, as far as the protocol encoding goes Error Report PDUs can
* happen to be nested in each other, however many times, in which case
* the decoder should still print such semantically incorrect PDUs.
*
* That said, "the Erroneous PDU field MAY be truncated" (ibid), thus
* to keep things simple this implementation decodes only the two
* outermost layers of PDUs and makes bounds checks in the outer and
* the inner PDU independently.
*/
if (pdu_len < tlen + encapsulated_pdu_length)
goto invalid;
if (! recurse) {
ND_TCHECK_LEN(tptr, tlen + encapsulated_pdu_length);
- }
- else {
+ } else {
ND_PRINT("%s-----encapsulated PDU-----", indent_string(indent+4));
rpki_rtr_pdu_print(ndo, tptr + tlen,
encapsulated_pdu_length, 0, indent + 2);
}
tlen += encapsulated_pdu_length;
}
if (pdu_len < tlen + 4)
goto invalid;
- ND_TCHECK_LEN(tptr, tlen + 4);
- /* Safe up to and including the "Length of Error Text" data element,
- * one more data element may be present.
- */
-
/*
* Extract, trail-zero and print the Error message.
*/
text_length = GET_BE_U_4(tptr + tlen);
tlen += 4;
+ /* Safe up to and including the "Length of Error Text" data element,
+ * one more data element may be present.
+ */
if (text_length) {
if (pdu_len < tlen + text_length)
goto invalid;
/* nd_printn() makes the bounds check */
ND_PRINT("%sError text: ", indent_string(indent+2));
(void)nd_printn(ndo, tptr + tlen, text_length, NULL);
}
}
break;
default:
ND_TCHECK_LEN(tptr, pdu_len);
/*
* Unknown data, please hexdump.
*/
hexdump = TRUE;
}
/* do we also want to see a hex dump ? */
if (ndo->ndo_vflag > 1 || (ndo->ndo_vflag && hexdump)) {
print_unknown_data(ndo,tptr,"\n\t ", pdu_len);
}
return pdu_len;
invalid:
nd_print_invalid(ndo);
ND_TCHECK_LEN(tptr, len);
return len;
}
void
rpki_rtr_print(netdissect_options *ndo, const u_char *pptr, u_int len)
{
ndo->ndo_protocol = "rpki_rtr";
if (!ndo->ndo_vflag) {
ND_PRINT(", RPKI-RTR");
return;
}
while (len) {
u_int pdu_len = rpki_rtr_pdu_print(ndo, pptr, len, 1, 8);
len -= pdu_len;
pptr += pdu_len;
}
}
diff --git a/contrib/tcpdump/print-rsvp.c b/contrib/tcpdump/print-rsvp.c
index 23b6d5a77386..9226c84e61ce 100644
--- a/contrib/tcpdump/print-rsvp.c
+++ b/contrib/tcpdump/print-rsvp.c
@@ -1,2069 +1,2067 @@
/*
* Copyright (c) 1998-2007 The TCPDUMP project
*
* 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.
*
* Original code by Hannes Gredler (hannes@gredler.at)
*/
/* \summary: Resource ReSerVation Protocol (RSVP) printer */
/* specification: RFC 2205 */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "extract.h"
#include "addrtoname.h"
#include "ethertype.h"
#include "gmpls.h"
#include "af.h"
#include "signature.h"
/*
* RFC 2205 common header
*
* 0 1 2 3
* +-------------+-------------+-------------+-------------+
* | Vers | Flags| Msg Type | RSVP Checksum |
* +-------------+-------------+-------------+-------------+
* | Send_TTL | (Reserved) | RSVP Length |
* +-------------+-------------+-------------+-------------+
*
*/
struct rsvp_common_header {
nd_uint8_t version_flags;
nd_uint8_t msg_type;
nd_uint16_t checksum;
nd_uint8_t ttl;
nd_byte reserved[1];
nd_uint16_t length;
};
/*
* RFC2205 object header
*
*
* 0 1 2 3
* +-------------+-------------+-------------+-------------+
* | Length (bytes) | Class-Num | C-Type |
* +-------------+-------------+-------------+-------------+
* | |
* // (Object contents) //
* | |
* +-------------+-------------+-------------+-------------+
*/
struct rsvp_object_header {
nd_uint16_t length;
nd_uint8_t class_num;
nd_uint8_t ctype;
};
#define RSVP_VERSION 1
#define RSVP_EXTRACT_VERSION(x) (((x)&0xf0)>>4)
#define RSVP_EXTRACT_FLAGS(x) ((x)&0x0f)
#define RSVP_MSGTYPE_PATH 1
#define RSVP_MSGTYPE_RESV 2
#define RSVP_MSGTYPE_PATHERR 3
#define RSVP_MSGTYPE_RESVERR 4
#define RSVP_MSGTYPE_PATHTEAR 5
#define RSVP_MSGTYPE_RESVTEAR 6
#define RSVP_MSGTYPE_RESVCONF 7
#define RSVP_MSGTYPE_BUNDLE 12
#define RSVP_MSGTYPE_ACK 13
#define RSVP_MSGTYPE_HELLO_OLD 14 /* ancient Hellos */
#define RSVP_MSGTYPE_SREFRESH 15
#define RSVP_MSGTYPE_HELLO 20
static const struct tok rsvp_msg_type_values[] = {
{ RSVP_MSGTYPE_PATH, "Path" },
{ RSVP_MSGTYPE_RESV, "Resv" },
{ RSVP_MSGTYPE_PATHERR, "PathErr" },
{ RSVP_MSGTYPE_RESVERR, "ResvErr" },
{ RSVP_MSGTYPE_PATHTEAR, "PathTear" },
{ RSVP_MSGTYPE_RESVTEAR, "ResvTear" },
{ RSVP_MSGTYPE_RESVCONF, "ResvConf" },
{ RSVP_MSGTYPE_BUNDLE, "Bundle" },
{ RSVP_MSGTYPE_ACK, "Acknowledgement" },
{ RSVP_MSGTYPE_HELLO_OLD, "Hello (Old)" },
{ RSVP_MSGTYPE_SREFRESH, "Refresh" },
{ RSVP_MSGTYPE_HELLO, "Hello" },
{ 0, NULL}
};
static const struct tok rsvp_header_flag_values[] = {
{ 0x01, "Refresh reduction capable" }, /* rfc2961 */
{ 0, NULL}
};
static const struct tok rsvp_obj_capability_flag_values[] = {
{ 0x0004, "RecoveryPath Transmit Enabled" },
{ 0x0002, "RecoveryPath Desired" },
{ 0x0001, "RecoveryPath Srefresh Capable" },
{ 0, NULL}
};
#define RSVP_OBJ_SESSION 1 /* rfc2205 */
#define RSVP_OBJ_RSVP_HOP 3 /* rfc2205, rfc3473 */
#define RSVP_OBJ_INTEGRITY 4 /* rfc2747 */
#define RSVP_OBJ_TIME_VALUES 5 /* rfc2205 */
#define RSVP_OBJ_ERROR_SPEC 6
#define RSVP_OBJ_SCOPE 7
#define RSVP_OBJ_STYLE 8 /* rfc2205 */
#define RSVP_OBJ_FLOWSPEC 9 /* rfc2215 */
#define RSVP_OBJ_FILTERSPEC 10 /* rfc2215 */
#define RSVP_OBJ_SENDER_TEMPLATE 11
#define RSVP_OBJ_SENDER_TSPEC 12 /* rfc2215 */
#define RSVP_OBJ_ADSPEC 13 /* rfc2215 */
#define RSVP_OBJ_POLICY_DATA 14
#define RSVP_OBJ_CONFIRM 15 /* rfc2205 */
#define RSVP_OBJ_LABEL 16 /* rfc3209 */
#define RSVP_OBJ_LABEL_REQ 19 /* rfc3209 */
#define RSVP_OBJ_ERO 20 /* rfc3209 */
#define RSVP_OBJ_RRO 21 /* rfc3209 */
#define RSVP_OBJ_HELLO 22 /* rfc3209 */
#define RSVP_OBJ_MESSAGE_ID 23 /* rfc2961 */
#define RSVP_OBJ_MESSAGE_ID_ACK 24 /* rfc2961 */
#define RSVP_OBJ_MESSAGE_ID_LIST 25 /* rfc2961 */
#define RSVP_OBJ_RECOVERY_LABEL 34 /* rfc3473 */
#define RSVP_OBJ_UPSTREAM_LABEL 35 /* rfc3473 */
#define RSVP_OBJ_LABEL_SET 36 /* rfc3473 */
#define RSVP_OBJ_PROTECTION 37 /* rfc3473 */
#define RSVP_OBJ_S2L 50 /* rfc4875 */
#define RSVP_OBJ_DETOUR 63 /* rfc4090 */
#define RSVP_OBJ_CLASSTYPE 66 /* rfc4124 */
#define RSVP_OBJ_CLASSTYPE_OLD 125 /* draft-ietf-tewg-diff-te-proto-07 */
#define RSVP_OBJ_SUGGESTED_LABEL 129 /* rfc3473 */
#define RSVP_OBJ_ACCEPT_LABEL_SET 130 /* rfc3473 */
#define RSVP_OBJ_RESTART_CAPABILITY 131 /* rfc3473 */
#define RSVP_OBJ_CAPABILITY 134 /* rfc5063 */
#define RSVP_OBJ_NOTIFY_REQ 195 /* rfc3473 */
#define RSVP_OBJ_ADMIN_STATUS 196 /* rfc3473 */
#define RSVP_OBJ_PROPERTIES 204 /* juniper proprietary */
#define RSVP_OBJ_FASTREROUTE 205 /* rfc4090 */
#define RSVP_OBJ_SESSION_ATTRIBUTE 207 /* rfc3209 */
#define RSVP_OBJ_GENERALIZED_UNI 229 /* OIF RSVP extensions UNI 1.0 Signaling, Rel. 2 */
#define RSVP_OBJ_CALL_ID 230 /* rfc3474 */
#define RSVP_OBJ_CALL_OPS 236 /* rfc3474 */
static const struct tok rsvp_obj_values[] = {
{ RSVP_OBJ_SESSION, "Session" },
{ RSVP_OBJ_RSVP_HOP, "RSVP Hop" },
{ RSVP_OBJ_INTEGRITY, "Integrity" },
{ RSVP_OBJ_TIME_VALUES, "Time Values" },
{ RSVP_OBJ_ERROR_SPEC, "Error Spec" },
{ RSVP_OBJ_SCOPE, "Scope" },
{ RSVP_OBJ_STYLE, "Style" },
{ RSVP_OBJ_FLOWSPEC, "Flowspec" },
{ RSVP_OBJ_FILTERSPEC, "FilterSpec" },
{ RSVP_OBJ_SENDER_TEMPLATE, "Sender Template" },
{ RSVP_OBJ_SENDER_TSPEC, "Sender TSpec" },
{ RSVP_OBJ_ADSPEC, "Adspec" },
{ RSVP_OBJ_POLICY_DATA, "Policy Data" },
{ RSVP_OBJ_CONFIRM, "Confirm" },
{ RSVP_OBJ_LABEL, "Label" },
{ RSVP_OBJ_LABEL_REQ, "Label Request" },
{ RSVP_OBJ_ERO, "ERO" },
{ RSVP_OBJ_RRO, "RRO" },
{ RSVP_OBJ_HELLO, "Hello" },
{ RSVP_OBJ_MESSAGE_ID, "Message ID" },
{ RSVP_OBJ_MESSAGE_ID_ACK, "Message ID Ack" },
{ RSVP_OBJ_MESSAGE_ID_LIST, "Message ID List" },
{ RSVP_OBJ_RECOVERY_LABEL, "Recovery Label" },
{ RSVP_OBJ_UPSTREAM_LABEL, "Upstream Label" },
{ RSVP_OBJ_LABEL_SET, "Label Set" },
{ RSVP_OBJ_ACCEPT_LABEL_SET, "Acceptable Label Set" },
{ RSVP_OBJ_DETOUR, "Detour" },
{ RSVP_OBJ_CLASSTYPE, "Class Type" },
{ RSVP_OBJ_CLASSTYPE_OLD, "Class Type (old)" },
{ RSVP_OBJ_SUGGESTED_LABEL, "Suggested Label" },
{ RSVP_OBJ_PROPERTIES, "Properties" },
{ RSVP_OBJ_FASTREROUTE, "Fast Re-Route" },
{ RSVP_OBJ_SESSION_ATTRIBUTE, "Session Attribute" },
{ RSVP_OBJ_GENERALIZED_UNI, "Generalized UNI" },
{ RSVP_OBJ_CALL_ID, "Call-ID" },
{ RSVP_OBJ_CALL_OPS, "Call Capability" },
{ RSVP_OBJ_RESTART_CAPABILITY, "Restart Capability" },
{ RSVP_OBJ_CAPABILITY, "Capability" },
{ RSVP_OBJ_NOTIFY_REQ, "Notify Request" },
{ RSVP_OBJ_PROTECTION, "Protection" },
{ RSVP_OBJ_ADMIN_STATUS, "Administrative Status" },
{ RSVP_OBJ_S2L, "Sub-LSP to LSP" },
{ 0, NULL}
};
#define RSVP_CTYPE_IPV4 1
#define RSVP_CTYPE_IPV6 2
#define RSVP_CTYPE_TUNNEL_IPV4 7
#define RSVP_CTYPE_TUNNEL_IPV6 8
#define RSVP_CTYPE_UNI_IPV4 11 /* OIF RSVP extensions UNI 1.0 Signaling Rel. 2 */
#define RSVP_CTYPE_1 1
#define RSVP_CTYPE_2 2
#define RSVP_CTYPE_3 3
#define RSVP_CTYPE_4 4
#define RSVP_CTYPE_12 12
#define RSVP_CTYPE_13 13
#define RSVP_CTYPE_14 14
/*
* the ctypes are not globally unique so for
* translating it to strings we build a table based
* on objects offsetted by the ctype
*/
static const struct tok rsvp_ctype_values[] = {
{ 256*RSVP_OBJ_RSVP_HOP+RSVP_CTYPE_IPV4, "IPv4" },
{ 256*RSVP_OBJ_RSVP_HOP+RSVP_CTYPE_IPV6, "IPv6" },
{ 256*RSVP_OBJ_RSVP_HOP+RSVP_CTYPE_3, "IPv4 plus opt. TLVs" },
{ 256*RSVP_OBJ_RSVP_HOP+RSVP_CTYPE_4, "IPv6 plus opt. TLVs" },
{ 256*RSVP_OBJ_NOTIFY_REQ+RSVP_CTYPE_IPV4, "IPv4" },
{ 256*RSVP_OBJ_NOTIFY_REQ+RSVP_CTYPE_IPV6, "IPv6" },
{ 256*RSVP_OBJ_CONFIRM+RSVP_CTYPE_IPV4, "IPv4" },
{ 256*RSVP_OBJ_CONFIRM+RSVP_CTYPE_IPV6, "IPv6" },
{ 256*RSVP_OBJ_TIME_VALUES+RSVP_CTYPE_1, "1" },
{ 256*RSVP_OBJ_FLOWSPEC+RSVP_CTYPE_1, "obsolete" },
{ 256*RSVP_OBJ_FLOWSPEC+RSVP_CTYPE_2, "IntServ" },
{ 256*RSVP_OBJ_SENDER_TSPEC+RSVP_CTYPE_2, "IntServ" },
{ 256*RSVP_OBJ_ADSPEC+RSVP_CTYPE_2, "IntServ" },
{ 256*RSVP_OBJ_FILTERSPEC+RSVP_CTYPE_IPV4, "IPv4" },
{ 256*RSVP_OBJ_FILTERSPEC+RSVP_CTYPE_IPV6, "IPv6" },
{ 256*RSVP_OBJ_FILTERSPEC+RSVP_CTYPE_3, "IPv6 Flow-label" },
{ 256*RSVP_OBJ_FILTERSPEC+RSVP_CTYPE_TUNNEL_IPV4, "Tunnel IPv4" },
{ 256*RSVP_OBJ_FILTERSPEC+RSVP_CTYPE_12, "IPv4 P2MP LSP Tunnel" },
{ 256*RSVP_OBJ_FILTERSPEC+RSVP_CTYPE_13, "IPv6 P2MP LSP Tunnel" },
{ 256*RSVP_OBJ_SESSION+RSVP_CTYPE_IPV4, "IPv4" },
{ 256*RSVP_OBJ_SESSION+RSVP_CTYPE_IPV6, "IPv6" },
{ 256*RSVP_OBJ_SESSION+RSVP_CTYPE_TUNNEL_IPV4, "Tunnel IPv4" },
{ 256*RSVP_OBJ_SESSION+RSVP_CTYPE_UNI_IPV4, "UNI IPv4" },
{ 256*RSVP_OBJ_SESSION+RSVP_CTYPE_13, "IPv4 P2MP LSP Tunnel" },
{ 256*RSVP_OBJ_SESSION+RSVP_CTYPE_14, "IPv6 P2MP LSP Tunnel" },
{ 256*RSVP_OBJ_SENDER_TEMPLATE+RSVP_CTYPE_IPV4, "IPv4" },
{ 256*RSVP_OBJ_SENDER_TEMPLATE+RSVP_CTYPE_IPV6, "IPv6" },
{ 256*RSVP_OBJ_SENDER_TEMPLATE+RSVP_CTYPE_TUNNEL_IPV4, "Tunnel IPv4" },
{ 256*RSVP_OBJ_SENDER_TEMPLATE+RSVP_CTYPE_12, "IPv4 P2MP LSP Tunnel" },
{ 256*RSVP_OBJ_SENDER_TEMPLATE+RSVP_CTYPE_13, "IPv6 P2MP LSP Tunnel" },
{ 256*RSVP_OBJ_MESSAGE_ID+RSVP_CTYPE_1, "1" },
{ 256*RSVP_OBJ_MESSAGE_ID_ACK+RSVP_CTYPE_1, "Message id ack" },
{ 256*RSVP_OBJ_MESSAGE_ID_ACK+RSVP_CTYPE_2, "Message id nack" },
{ 256*RSVP_OBJ_MESSAGE_ID_LIST+RSVP_CTYPE_1, "1" },
{ 256*RSVP_OBJ_STYLE+RSVP_CTYPE_1, "1" },
{ 256*RSVP_OBJ_HELLO+RSVP_CTYPE_1, "Hello Request" },
{ 256*RSVP_OBJ_HELLO+RSVP_CTYPE_2, "Hello Ack" },
{ 256*RSVP_OBJ_LABEL_REQ+RSVP_CTYPE_1, "without label range" },
{ 256*RSVP_OBJ_LABEL_REQ+RSVP_CTYPE_2, "with ATM label range" },
{ 256*RSVP_OBJ_LABEL_REQ+RSVP_CTYPE_3, "with FR label range" },
{ 256*RSVP_OBJ_LABEL_REQ+RSVP_CTYPE_4, "Generalized Label" },
{ 256*RSVP_OBJ_LABEL+RSVP_CTYPE_1, "Label" },
{ 256*RSVP_OBJ_LABEL+RSVP_CTYPE_2, "Generalized Label" },
{ 256*RSVP_OBJ_LABEL+RSVP_CTYPE_3, "Waveband Switching" },
{ 256*RSVP_OBJ_SUGGESTED_LABEL+RSVP_CTYPE_1, "Label" },
{ 256*RSVP_OBJ_SUGGESTED_LABEL+RSVP_CTYPE_2, "Generalized Label" },
{ 256*RSVP_OBJ_SUGGESTED_LABEL+RSVP_CTYPE_3, "Waveband Switching" },
{ 256*RSVP_OBJ_UPSTREAM_LABEL+RSVP_CTYPE_1, "Label" },
{ 256*RSVP_OBJ_UPSTREAM_LABEL+RSVP_CTYPE_2, "Generalized Label" },
{ 256*RSVP_OBJ_UPSTREAM_LABEL+RSVP_CTYPE_3, "Waveband Switching" },
{ 256*RSVP_OBJ_RECOVERY_LABEL+RSVP_CTYPE_1, "Label" },
{ 256*RSVP_OBJ_RECOVERY_LABEL+RSVP_CTYPE_2, "Generalized Label" },
{ 256*RSVP_OBJ_RECOVERY_LABEL+RSVP_CTYPE_3, "Waveband Switching" },
{ 256*RSVP_OBJ_ERO+RSVP_CTYPE_IPV4, "IPv4" },
{ 256*RSVP_OBJ_RRO+RSVP_CTYPE_IPV4, "IPv4" },
{ 256*RSVP_OBJ_ERROR_SPEC+RSVP_CTYPE_IPV4, "IPv4" },
{ 256*RSVP_OBJ_ERROR_SPEC+RSVP_CTYPE_IPV6, "IPv6" },
{ 256*RSVP_OBJ_ERROR_SPEC+RSVP_CTYPE_3, "IPv4 plus opt. TLVs" },
{ 256*RSVP_OBJ_ERROR_SPEC+RSVP_CTYPE_4, "IPv6 plus opt. TLVs" },
{ 256*RSVP_OBJ_RESTART_CAPABILITY+RSVP_CTYPE_1, "IPv4" },
{ 256*RSVP_OBJ_CAPABILITY+RSVP_CTYPE_1, "1" },
{ 256*RSVP_OBJ_SESSION_ATTRIBUTE+RSVP_CTYPE_TUNNEL_IPV4, "Tunnel IPv4" },
{ 256*RSVP_OBJ_FASTREROUTE+RSVP_CTYPE_TUNNEL_IPV4, "Tunnel IPv4" }, /* old style*/
{ 256*RSVP_OBJ_FASTREROUTE+RSVP_CTYPE_1, "1" }, /* new style */
{ 256*RSVP_OBJ_DETOUR+RSVP_CTYPE_TUNNEL_IPV4, "Tunnel IPv4" },
{ 256*RSVP_OBJ_PROPERTIES+RSVP_CTYPE_1, "1" },
{ 256*RSVP_OBJ_ADMIN_STATUS+RSVP_CTYPE_1, "1" },
{ 256*RSVP_OBJ_CLASSTYPE+RSVP_CTYPE_1, "1" },
{ 256*RSVP_OBJ_CLASSTYPE_OLD+RSVP_CTYPE_1, "1" },
{ 256*RSVP_OBJ_LABEL_SET+RSVP_CTYPE_1, "1" },
{ 256*RSVP_OBJ_GENERALIZED_UNI+RSVP_CTYPE_1, "1" },
{ 256*RSVP_OBJ_S2L+RSVP_CTYPE_IPV4, "IPv4 sub-LSP" },
{ 256*RSVP_OBJ_S2L+RSVP_CTYPE_IPV6, "IPv6 sub-LSP" },
{ 0, NULL}
};
/*
* XXX - this assumes a 16-byte digest, which is true for HMAC-MD5, but
* isn't necessarily the case for other hash algorithms.
*
* Unless I've missed something, there's nothing in RFC 2747 to indicate
* the hash algorithm being used, so it's presumably something set up
* out-of-band, or negotiated by other RSVP objects.
*/
struct rsvp_obj_integrity_t {
uint8_t flags;
uint8_t res;
uint8_t key_id[6];
uint8_t sequence[8];
uint8_t digest[16];
};
static const struct tok rsvp_obj_integrity_flag_values[] = {
{ 0x80, "Handshake" },
{ 0, NULL}
};
struct rsvp_obj_frr_t {
uint8_t setup_prio;
uint8_t hold_prio;
uint8_t hop_limit;
uint8_t flags;
uint8_t bandwidth[4];
uint8_t include_any[4];
uint8_t exclude_any[4];
uint8_t include_all[4];
};
#define RSVP_OBJ_XRO_MASK_SUBOBJ(x) ((x)&0x7f)
#define RSVP_OBJ_XRO_MASK_LOOSE(x) ((x)&0x80)
#define RSVP_OBJ_CAPABILITY_FLAGS_MASK 0x7U
#define RSVP_OBJ_XRO_RES 0
#define RSVP_OBJ_XRO_IPV4 1
#define RSVP_OBJ_XRO_IPV6 2
#define RSVP_OBJ_XRO_LABEL 3
#define RSVP_OBJ_XRO_ASN 32
#define RSVP_OBJ_XRO_MPLS 64
static const struct tok rsvp_obj_xro_values[] = {
{ RSVP_OBJ_XRO_RES, "Reserved" },
{ RSVP_OBJ_XRO_IPV4, "IPv4 prefix" },
{ RSVP_OBJ_XRO_IPV6, "IPv6 prefix" },
{ RSVP_OBJ_XRO_LABEL, "Label" },
{ RSVP_OBJ_XRO_ASN, "Autonomous system number" },
{ RSVP_OBJ_XRO_MPLS, "MPLS label switched path termination" },
{ 0, NULL}
};
/* RFC4090 */
static const struct tok rsvp_obj_rro_flag_values[] = {
{ 0x01, "Local protection available" },
{ 0x02, "Local protection in use" },
{ 0x04, "Bandwidth protection" },
{ 0x08, "Node protection" },
{ 0, NULL}
};
/* RFC3209 */
static const struct tok rsvp_obj_rro_label_flag_values[] = {
{ 0x01, "Global" },
{ 0, NULL}
};
static const struct tok rsvp_resstyle_values[] = {
{ 17, "Wildcard Filter" },
{ 10, "Fixed Filter" },
{ 18, "Shared Explicit" },
{ 0, NULL}
};
#define RSVP_OBJ_INTSERV_GUARANTEED_SERV 2
#define RSVP_OBJ_INTSERV_CONTROLLED_LOAD 5
static const struct tok rsvp_intserv_service_type_values[] = {
{ 1, "Default/Global Information" },
{ RSVP_OBJ_INTSERV_GUARANTEED_SERV, "Guaranteed Service" },
{ RSVP_OBJ_INTSERV_CONTROLLED_LOAD, "Controlled Load" },
{ 0, NULL}
};
static const struct tok rsvp_intserv_parameter_id_values[] = {
{ 4, "IS hop cnt" },
{ 6, "Path b/w estimate" },
{ 8, "Minimum path latency" },
{ 10, "Composed MTU" },
{ 127, "Token Bucket TSpec" },
{ 130, "Guaranteed Service RSpec" },
{ 133, "End-to-end composed value for C" },
{ 134, "End-to-end composed value for D" },
{ 135, "Since-last-reshaping point composed C" },
{ 136, "Since-last-reshaping point composed D" },
{ 0, NULL}
};
static const struct tok rsvp_session_attribute_flag_values[] = {
{ 0x01, "Local Protection" },
{ 0x02, "Label Recording" },
{ 0x04, "SE Style" },
{ 0x08, "Bandwidth protection" }, /* RFC4090 */
{ 0x10, "Node protection" }, /* RFC4090 */
{ 0, NULL}
};
static const struct tok rsvp_obj_prop_tlv_values[] = {
{ 0x01, "Cos" },
{ 0x02, "Metric 1" },
{ 0x04, "Metric 2" },
{ 0x08, "CCC Status" },
{ 0x10, "Path Type" },
{ 0, NULL}
};
#define RSVP_OBJ_ERROR_SPEC_CODE_ROUTING 24
#define RSVP_OBJ_ERROR_SPEC_CODE_NOTIFY 25
#define RSVP_OBJ_ERROR_SPEC_CODE_DIFFSERV_TE 28
#define RSVP_OBJ_ERROR_SPEC_CODE_DIFFSERV_TE_OLD 125
static const struct tok rsvp_obj_error_code_values[] = {
{ RSVP_OBJ_ERROR_SPEC_CODE_ROUTING, "Routing Problem" },
{ RSVP_OBJ_ERROR_SPEC_CODE_NOTIFY, "Notify Error" },
{ RSVP_OBJ_ERROR_SPEC_CODE_DIFFSERV_TE, "Diffserv TE Error" },
{ RSVP_OBJ_ERROR_SPEC_CODE_DIFFSERV_TE_OLD, "Diffserv TE Error (Old)" },
{ 0, NULL}
};
static const struct tok rsvp_obj_error_code_routing_values[] = {
{ 1, "Bad EXPLICIT_ROUTE object" },
{ 2, "Bad strict node" },
{ 3, "Bad loose node" },
{ 4, "Bad initial subobject" },
{ 5, "No route available toward destination" },
{ 6, "Unacceptable label value" },
{ 7, "RRO indicated routing loops" },
{ 8, "non-RSVP-capable router in the path" },
{ 9, "MPLS label allocation failure" },
{ 10, "Unsupported L3PID" },
{ 0, NULL}
};
static const struct tok rsvp_obj_error_code_diffserv_te_values[] = {
{ 1, "Unexpected CT object" },
{ 2, "Unsupported CT" },
{ 3, "Invalid CT value" },
{ 4, "CT/setup priority do not form a configured TE-Class" },
{ 5, "CT/holding priority do not form a configured TE-Class" },
{ 6, "CT/setup priority and CT/holding priority do not form a configured TE-Class" },
{ 7, "Inconsistency between signaled PSC and signaled CT" },
{ 8, "Inconsistency between signaled PHBs and signaled CT" },
{ 0, NULL}
};
/* rfc3473 / rfc 3471 */
static const struct tok rsvp_obj_admin_status_flag_values[] = {
{ 0x80000000, "Reflect" },
{ 0x00000004, "Testing" },
{ 0x00000002, "Admin-down" },
{ 0x00000001, "Delete-in-progress" },
{ 0, NULL}
};
/* label set actions - rfc3471 */
#define LABEL_SET_INCLUSIVE_LIST 0
#define LABEL_SET_EXCLUSIVE_LIST 1
#define LABEL_SET_INCLUSIVE_RANGE 2
#define LABEL_SET_EXCLUSIVE_RANGE 3
static const struct tok rsvp_obj_label_set_action_values[] = {
{ LABEL_SET_INCLUSIVE_LIST, "Inclusive list" },
{ LABEL_SET_EXCLUSIVE_LIST, "Exclusive list" },
{ LABEL_SET_INCLUSIVE_RANGE, "Inclusive range" },
{ LABEL_SET_EXCLUSIVE_RANGE, "Exclusive range" },
{ 0, NULL}
};
/* OIF RSVP extensions UNI 1.0 Signaling, release 2 */
#define RSVP_GEN_UNI_SUBOBJ_SOURCE_TNA_ADDRESS 1
#define RSVP_GEN_UNI_SUBOBJ_DESTINATION_TNA_ADDRESS 2
#define RSVP_GEN_UNI_SUBOBJ_DIVERSITY 3
#define RSVP_GEN_UNI_SUBOBJ_EGRESS_LABEL 4
#define RSVP_GEN_UNI_SUBOBJ_SERVICE_LEVEL 5
static const struct tok rsvp_obj_generalized_uni_values[] = {
{ RSVP_GEN_UNI_SUBOBJ_SOURCE_TNA_ADDRESS, "Source TNA address" },
{ RSVP_GEN_UNI_SUBOBJ_DESTINATION_TNA_ADDRESS, "Destination TNA address" },
{ RSVP_GEN_UNI_SUBOBJ_DIVERSITY, "Diversity" },
{ RSVP_GEN_UNI_SUBOBJ_EGRESS_LABEL, "Egress label" },
{ RSVP_GEN_UNI_SUBOBJ_SERVICE_LEVEL, "Service level" },
{ 0, NULL}
};
/*
* this is a dissector for all the intserv defined
* specs as defined per rfc2215
* it is called from various rsvp objects;
* returns the amount of bytes being processed
*/
static u_int
rsvp_intserv_print(netdissect_options *ndo,
const u_char *tptr, u_int obj_tlen)
{
u_int parameter_id,parameter_length;
union {
float f;
uint32_t i;
} bw;
if (obj_tlen < 4)
return 0;
parameter_id = GET_U_1(tptr);
parameter_length = GET_BE_U_2(tptr + 2)<<2; /* convert wordcount to bytecount */
ND_PRINT("\n\t Parameter ID: %s (%u), length: %u, Flags: [0x%02x]",
tok2str(rsvp_intserv_parameter_id_values,"unknown",parameter_id),
parameter_id,
parameter_length,
GET_U_1(tptr + 1));
if (obj_tlen < parameter_length+4)
return 0;
switch(parameter_id) { /* parameter_id */
case 4:
/*
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 4 (e) | (f) | 1 (g) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | IS hop cnt (32-bit unsigned integer) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
if (parameter_length == 4) {
ND_PRINT("\n\t\tIS hop count: %u", GET_BE_U_4(tptr + 4));
}
break;
case 6:
/*
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 6 (h) | (i) | 1 (j) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Path b/w estimate (32-bit IEEE floating point number) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
if (parameter_length == 4) {
bw.i = GET_BE_U_4(tptr + 4);
ND_PRINT("\n\t\tPath b/w estimate: %.10g Mbps", bw.f / 125000);
}
break;
case 8:
/*
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 8 (k) | (l) | 1 (m) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Minimum path latency (32-bit integer) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
if (parameter_length == 4) {
ND_PRINT("\n\t\tMinimum path latency: ");
if (GET_BE_U_4(tptr + 4) == 0xffffffff)
ND_PRINT("don't care");
else
ND_PRINT("%u", GET_BE_U_4(tptr + 4));
}
break;
case 10:
/*
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 10 (n) | (o) | 1 (p) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Composed MTU (32-bit unsigned integer) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
if (parameter_length == 4) {
ND_PRINT("\n\t\tComposed MTU: %u bytes", GET_BE_U_4(tptr + 4));
}
break;
case 127:
/*
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 127 (e) | 0 (f) | 5 (g) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Token Bucket Rate [r] (32-bit IEEE floating point number) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Token Bucket Size [b] (32-bit IEEE floating point number) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Peak Data Rate [p] (32-bit IEEE floating point number) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Minimum Policed Unit [m] (32-bit integer) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Maximum Packet Size [M] (32-bit integer) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
if (parameter_length == 20) {
ND_TCHECK_LEN(tptr + 4, 20);
bw.i = GET_BE_U_4(tptr + 4);
ND_PRINT("\n\t\tToken Bucket Rate: %.10g Mbps", bw.f / 125000);
bw.i = GET_BE_U_4(tptr + 8);
ND_PRINT("\n\t\tToken Bucket Size: %.10g bytes", bw.f);
bw.i = GET_BE_U_4(tptr + 12);
ND_PRINT("\n\t\tPeak Data Rate: %.10g Mbps", bw.f / 125000);
ND_PRINT("\n\t\tMinimum Policed Unit: %u bytes",
GET_BE_U_4(tptr + 16));
ND_PRINT("\n\t\tMaximum Packet Size: %u bytes",
GET_BE_U_4(tptr + 20));
}
break;
case 130:
/*
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 130 (h) | 0 (i) | 2 (j) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Rate [R] (32-bit IEEE floating point number) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Slack Term [S] (32-bit integer) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
if (parameter_length == 8) {
ND_TCHECK_8(tptr + 4);
bw.i = GET_BE_U_4(tptr + 4);
ND_PRINT("\n\t\tRate: %.10g Mbps", bw.f / 125000);
ND_PRINT("\n\t\tSlack Term: %u", GET_BE_U_4(tptr + 8));
}
break;
case 133:
case 134:
case 135:
case 136:
if (parameter_length == 4) {
ND_PRINT("\n\t\tValue: %u", GET_BE_U_4(tptr + 4));
}
break;
default:
if (ndo->ndo_vflag <= 1)
print_unknown_data(ndo, tptr + 4, "\n\t\t", parameter_length);
}
return (parameter_length+4); /* header length 4 bytes */
trunc:
nd_print_trunc(ndo);
return 0;
}
/*
* Clear checksum prior to signature verification.
*/
static void
rsvp_clear_checksum(void *header)
{
struct rsvp_common_header *rsvp_com_header = (struct rsvp_common_header *) header;
rsvp_com_header->checksum[0] = 0;
rsvp_com_header->checksum[1] = 0;
}
static int
rsvp_obj_print(netdissect_options *ndo,
const u_char *pptr, u_int plen, const u_char *tptr,
const char *indent, u_int tlen,
const struct rsvp_common_header *rsvp_com_header)
{
const struct rsvp_object_header *rsvp_obj_header;
const u_char *obj_tptr;
union {
const struct rsvp_obj_integrity_t *rsvp_obj_integrity;
const struct rsvp_obj_frr_t *rsvp_obj_frr;
} obj_ptr;
u_short rsvp_obj_len,rsvp_obj_ctype,rsvp_obj_class_num;
u_int obj_tlen,intserv_serv_tlen;
int hexdump;
u_int processed,padbytes,error_code,error_value,i,sigcheck;
union {
float f;
uint32_t i;
} bw;
u_int namelen;
u_int action, subchannel;
while(tlen>=sizeof(struct rsvp_object_header)) {
/* did we capture enough for fully decoding the object header ? */
ND_TCHECK_LEN(tptr, sizeof(struct rsvp_object_header));
rsvp_obj_header = (const struct rsvp_object_header *)tptr;
rsvp_obj_len=GET_BE_U_2(rsvp_obj_header->length);
rsvp_obj_ctype=GET_U_1(rsvp_obj_header->ctype);
if(rsvp_obj_len % 4) {
ND_PRINT("%sERROR: object header size %u not a multiple of 4", indent, rsvp_obj_len);
return -1;
}
if(rsvp_obj_len < sizeof(struct rsvp_object_header)) {
ND_PRINT("%sERROR: object header too short %u < %zu", indent, rsvp_obj_len,
sizeof(struct rsvp_object_header));
return -1;
}
rsvp_obj_class_num = GET_U_1(rsvp_obj_header->class_num);
ND_PRINT("%s%s Object (%u) Flags: [%s",
indent,
tok2str(rsvp_obj_values,
"Unknown",
rsvp_obj_class_num),
rsvp_obj_class_num,
(rsvp_obj_class_num & 0x80) ?
((rsvp_obj_class_num & 0x40) ? "ignore and forward" :
"ignore silently") :
"reject");
ND_PRINT(" if unknown], Class-Type: %s (%u), length: %u",
tok2str(rsvp_ctype_values,
"Unknown",
(rsvp_obj_class_num<<8)+rsvp_obj_ctype),
rsvp_obj_ctype,
rsvp_obj_len);
if(tlen < rsvp_obj_len) {
ND_PRINT("%sERROR: object goes past end of objects TLV", indent);
return -1;
}
obj_tptr=tptr+sizeof(struct rsvp_object_header);
obj_tlen=rsvp_obj_len-sizeof(struct rsvp_object_header);
/* did we capture enough for fully decoding the object ? */
ND_TCHECK_LEN(tptr, rsvp_obj_len);
hexdump=FALSE;
switch(rsvp_obj_class_num) {
case RSVP_OBJ_SESSION:
switch(rsvp_obj_ctype) {
case RSVP_CTYPE_IPV4:
if (obj_tlen < 8)
goto obj_tooshort;
ND_PRINT("%s IPv4 DestAddress: %s, Protocol ID: 0x%02x",
indent,
GET_IPADDR_STRING(obj_tptr),
GET_U_1(obj_tptr + sizeof(nd_ipv4)));
ND_PRINT("%s Flags: [0x%02x], DestPort %u",
indent,
GET_U_1((obj_tptr + 5)),
GET_BE_U_2(obj_tptr + 6));
obj_tlen-=8;
obj_tptr+=8;
break;
case RSVP_CTYPE_IPV6:
if (obj_tlen < 20)
goto obj_tooshort;
ND_PRINT("%s IPv6 DestAddress: %s, Protocol ID: 0x%02x",
indent,
GET_IP6ADDR_STRING(obj_tptr),
GET_U_1(obj_tptr + sizeof(nd_ipv6)));
ND_PRINT("%s Flags: [0x%02x], DestPort %u",
indent,
GET_U_1((obj_tptr + sizeof(nd_ipv6) + 1)),
GET_BE_U_2(obj_tptr + sizeof(nd_ipv6) + 2));
obj_tlen-=20;
obj_tptr+=20;
break;
case RSVP_CTYPE_TUNNEL_IPV6:
if (obj_tlen < 36)
goto obj_tooshort;
ND_PRINT("%s IPv6 Tunnel EndPoint: %s, Tunnel ID: 0x%04x, Extended Tunnel ID: %s",
indent,
GET_IP6ADDR_STRING(obj_tptr),
GET_BE_U_2(obj_tptr + 18),
GET_IP6ADDR_STRING(obj_tptr + 20));
obj_tlen-=36;
obj_tptr+=36;
break;
case RSVP_CTYPE_14: /* IPv6 p2mp LSP Tunnel */
if (obj_tlen < 26)
goto obj_tooshort;
ND_PRINT("%s IPv6 P2MP LSP ID: 0x%08x, Tunnel ID: 0x%04x, Extended Tunnel ID: %s",
indent,
GET_BE_U_4(obj_tptr),
GET_BE_U_2(obj_tptr + 6),
GET_IP6ADDR_STRING(obj_tptr + 8));
obj_tlen-=26;
obj_tptr+=26;
break;
case RSVP_CTYPE_13: /* IPv4 p2mp LSP Tunnel */
if (obj_tlen < 12)
goto obj_tooshort;
ND_PRINT("%s IPv4 P2MP LSP ID: %s, Tunnel ID: 0x%04x, Extended Tunnel ID: %s",
indent,
GET_IPADDR_STRING(obj_tptr),
GET_BE_U_2(obj_tptr + 6),
GET_IPADDR_STRING(obj_tptr + 8));
obj_tlen-=12;
obj_tptr+=12;
break;
case RSVP_CTYPE_TUNNEL_IPV4:
case RSVP_CTYPE_UNI_IPV4:
if (obj_tlen < 12)
goto obj_tooshort;
ND_PRINT("%s IPv4 Tunnel EndPoint: %s, Tunnel ID: 0x%04x, Extended Tunnel ID: %s",
indent,
GET_IPADDR_STRING(obj_tptr),
GET_BE_U_2(obj_tptr + 6),
GET_IPADDR_STRING(obj_tptr + 8));
obj_tlen-=12;
obj_tptr+=12;
break;
default:
hexdump=TRUE;
}
break;
case RSVP_OBJ_CONFIRM:
switch(rsvp_obj_ctype) {
case RSVP_CTYPE_IPV4:
if (obj_tlen < sizeof(nd_ipv4))
goto obj_tooshort;
ND_PRINT("%s IPv4 Receiver Address: %s",
indent,
GET_IPADDR_STRING(obj_tptr));
obj_tlen-=sizeof(nd_ipv4);
obj_tptr+=sizeof(nd_ipv4);
break;
case RSVP_CTYPE_IPV6:
if (obj_tlen < sizeof(nd_ipv6))
goto obj_tooshort;
ND_PRINT("%s IPv6 Receiver Address: %s",
indent,
GET_IP6ADDR_STRING(obj_tptr));
obj_tlen-=sizeof(nd_ipv6);
obj_tptr+=sizeof(nd_ipv6);
break;
default:
hexdump=TRUE;
}
break;
case RSVP_OBJ_NOTIFY_REQ:
switch(rsvp_obj_ctype) {
case RSVP_CTYPE_IPV4:
if (obj_tlen < sizeof(nd_ipv4))
goto obj_tooshort;
ND_PRINT("%s IPv4 Notify Node Address: %s",
indent,
GET_IPADDR_STRING(obj_tptr));
obj_tlen-=sizeof(nd_ipv4);
obj_tptr+=sizeof(nd_ipv4);
break;
case RSVP_CTYPE_IPV6:
if (obj_tlen < sizeof(nd_ipv6))
goto obj_tooshort;
ND_PRINT("%s IPv6 Notify Node Address: %s",
indent,
GET_IP6ADDR_STRING(obj_tptr));
obj_tlen-=sizeof(nd_ipv6);
obj_tptr+=sizeof(nd_ipv6);
break;
default:
hexdump=TRUE;
}
break;
case RSVP_OBJ_SUGGESTED_LABEL: /* fall through */
case RSVP_OBJ_UPSTREAM_LABEL: /* fall through */
case RSVP_OBJ_RECOVERY_LABEL: /* fall through */
case RSVP_OBJ_LABEL:
switch(rsvp_obj_ctype) {
case RSVP_CTYPE_1:
while(obj_tlen >= 4 ) {
ND_PRINT("%s Label: %u", indent, GET_BE_U_4(obj_tptr));
obj_tlen-=4;
obj_tptr+=4;
}
break;
case RSVP_CTYPE_2:
if (obj_tlen < 4)
goto obj_tooshort;
ND_PRINT("%s Generalized Label: %u",
indent,
GET_BE_U_4(obj_tptr));
obj_tlen-=4;
obj_tptr+=4;
break;
case RSVP_CTYPE_3:
if (obj_tlen < 12)
goto obj_tooshort;
ND_PRINT("%s Waveband ID: %u%s Start Label: %u, Stop Label: %u",
indent,
GET_BE_U_4(obj_tptr),
indent,
GET_BE_U_4(obj_tptr + 4),
GET_BE_U_4(obj_tptr + 8));
obj_tlen-=12;
obj_tptr+=12;
break;
default:
hexdump=TRUE;
}
break;
case RSVP_OBJ_STYLE:
switch(rsvp_obj_ctype) {
case RSVP_CTYPE_1:
if (obj_tlen < 4)
goto obj_tooshort;
ND_PRINT("%s Reservation Style: %s, Flags: [0x%02x]",
indent,
tok2str(rsvp_resstyle_values,
"Unknown",
GET_BE_U_3(obj_tptr + 1)),
GET_U_1(obj_tptr));
obj_tlen-=4;
obj_tptr+=4;
break;
default:
hexdump=TRUE;
}
break;
case RSVP_OBJ_SENDER_TEMPLATE:
switch(rsvp_obj_ctype) {
case RSVP_CTYPE_IPV4:
if (obj_tlen < 8)
goto obj_tooshort;
ND_PRINT("%s Source Address: %s, Source Port: %u",
indent,
GET_IPADDR_STRING(obj_tptr),
GET_BE_U_2(obj_tptr + 6));
obj_tlen-=8;
obj_tptr+=8;
break;
case RSVP_CTYPE_IPV6:
if (obj_tlen < 20)
goto obj_tooshort;
ND_PRINT("%s Source Address: %s, Source Port: %u",
indent,
GET_IP6ADDR_STRING(obj_tptr),
GET_BE_U_2(obj_tptr + 18));
obj_tlen-=20;
obj_tptr+=20;
break;
case RSVP_CTYPE_13: /* IPv6 p2mp LSP tunnel */
if (obj_tlen < 40)
goto obj_tooshort;
ND_PRINT("%s IPv6 Tunnel Sender Address: %s, LSP ID: 0x%04x"
"%s Sub-Group Originator ID: %s, Sub-Group ID: 0x%04x",
indent,
GET_IP6ADDR_STRING(obj_tptr),
GET_BE_U_2(obj_tptr + 18),
indent,
GET_IP6ADDR_STRING(obj_tptr+20),
GET_BE_U_2(obj_tptr + 38));
obj_tlen-=40;
obj_tptr+=40;
break;
case RSVP_CTYPE_TUNNEL_IPV4:
if (obj_tlen < 8)
goto obj_tooshort;
ND_PRINT("%s IPv4 Tunnel Sender Address: %s, LSP-ID: 0x%04x",
indent,
GET_IPADDR_STRING(obj_tptr),
GET_BE_U_2(obj_tptr + 6));
obj_tlen-=8;
obj_tptr+=8;
break;
case RSVP_CTYPE_12: /* IPv4 p2mp LSP tunnel */
if (obj_tlen < 16)
goto obj_tooshort;
ND_PRINT("%s IPv4 Tunnel Sender Address: %s, LSP ID: 0x%04x"
"%s Sub-Group Originator ID: %s, Sub-Group ID: 0x%04x",
indent,
GET_IPADDR_STRING(obj_tptr),
GET_BE_U_2(obj_tptr + 6),
indent,
GET_IPADDR_STRING(obj_tptr+8),
GET_BE_U_2(obj_tptr + 12));
obj_tlen-=16;
obj_tptr+=16;
break;
default:
hexdump=TRUE;
}
break;
case RSVP_OBJ_LABEL_REQ:
switch(rsvp_obj_ctype) {
case RSVP_CTYPE_1:
while(obj_tlen >= 4 ) {
ND_PRINT("%s L3 Protocol ID: %s",
indent,
tok2str(ethertype_values,
"Unknown Protocol (0x%04x)",
GET_BE_U_2(obj_tptr + 2)));
obj_tlen-=4;
obj_tptr+=4;
}
break;
case RSVP_CTYPE_2:
if (obj_tlen < 12)
goto obj_tooshort;
ND_PRINT("%s L3 Protocol ID: %s",
indent,
tok2str(ethertype_values,
"Unknown Protocol (0x%04x)",
GET_BE_U_2(obj_tptr + 2)));
ND_PRINT(",%s merge capability",
((GET_U_1(obj_tptr + 4)) & 0x80) ? "no" : "" );
ND_PRINT("%s Minimum VPI/VCI: %u/%u",
indent,
(GET_BE_U_2(obj_tptr + 4))&0xfff,
(GET_BE_U_2(obj_tptr + 6)) & 0xfff);
ND_PRINT("%s Maximum VPI/VCI: %u/%u",
indent,
(GET_BE_U_2(obj_tptr + 8))&0xfff,
(GET_BE_U_2(obj_tptr + 10)) & 0xfff);
obj_tlen-=12;
obj_tptr+=12;
break;
case RSVP_CTYPE_3:
if (obj_tlen < 12)
goto obj_tooshort;
ND_PRINT("%s L3 Protocol ID: %s",
indent,
tok2str(ethertype_values,
"Unknown Protocol (0x%04x)",
GET_BE_U_2(obj_tptr + 2)));
ND_PRINT("%s Minimum/Maximum DLCI: %u/%u, %s%s bit DLCI",
indent,
(GET_BE_U_4(obj_tptr + 4))&0x7fffff,
(GET_BE_U_4(obj_tptr + 8))&0x7fffff,
(((GET_BE_U_2(obj_tptr + 4)>>7)&3) == 0 ) ? "10" : "",
(((GET_BE_U_2(obj_tptr + 4) >> 7) & 3) == 2 ) ? "23" : "");
obj_tlen-=12;
obj_tptr+=12;
break;
case RSVP_CTYPE_4:
if (obj_tlen < 4)
goto obj_tooshort;
ND_PRINT("%s LSP Encoding Type: %s (%u)",
indent,
tok2str(gmpls_encoding_values,
"Unknown",
GET_U_1(obj_tptr)),
GET_U_1(obj_tptr));
ND_PRINT("%s Switching Type: %s (%u), Payload ID: %s (0x%04x)",
indent,
tok2str(gmpls_switch_cap_values,
"Unknown",
GET_U_1((obj_tptr + 1))),
GET_U_1(obj_tptr + 1),
tok2str(gmpls_payload_values,
"Unknown",
GET_BE_U_2(obj_tptr + 2)),
GET_BE_U_2(obj_tptr + 2));
obj_tlen-=4;
obj_tptr+=4;
break;
default:
hexdump=TRUE;
}
break;
case RSVP_OBJ_RRO:
case RSVP_OBJ_ERO:
switch(rsvp_obj_ctype) {
case RSVP_CTYPE_IPV4:
while(obj_tlen >= 4 ) {
u_char length;
ND_TCHECK_4(obj_tptr);
length = GET_U_1(obj_tptr + 1);
ND_PRINT("%s Subobject Type: %s, length %u",
indent,
tok2str(rsvp_obj_xro_values,
"Unknown %u",
RSVP_OBJ_XRO_MASK_SUBOBJ(GET_U_1(obj_tptr))),
length);
if (obj_tlen < length) {
ND_PRINT("%s ERROR: ERO subobject length > object length", indent);
break;
}
if (length == 0) { /* prevent infinite loops */
ND_PRINT("%s ERROR: zero length ERO subtype", indent);
break;
}
switch(RSVP_OBJ_XRO_MASK_SUBOBJ(GET_U_1(obj_tptr))) {
u_char prefix_length;
case RSVP_OBJ_XRO_IPV4:
if (length != 8) {
ND_PRINT(" ERROR: length != 8");
goto invalid;
}
ND_TCHECK_8(obj_tptr);
prefix_length = GET_U_1(obj_tptr + 6);
if (prefix_length != 32) {
ND_PRINT(" ERROR: Prefix length %u != 32",
prefix_length);
goto invalid;
}
ND_PRINT(", %s, %s/%u, Flags: [%s]",
RSVP_OBJ_XRO_MASK_LOOSE(GET_U_1(obj_tptr)) ? "Loose" : "Strict",
GET_IPADDR_STRING(obj_tptr+2),
GET_U_1((obj_tptr + 6)),
bittok2str(rsvp_obj_rro_flag_values,
"none",
GET_U_1((obj_tptr + 7)))); /* rfc3209 says that this field is rsvd. */
break;
case RSVP_OBJ_XRO_LABEL:
if (length != 8) {
ND_PRINT(" ERROR: length != 8");
goto invalid;
}
ND_TCHECK_8(obj_tptr);
ND_PRINT(", Flags: [%s] (%#x), Class-Type: %s (%u), %u",
bittok2str(rsvp_obj_rro_label_flag_values,
"none",
GET_U_1((obj_tptr + 2))),
GET_U_1(obj_tptr + 2),
tok2str(rsvp_ctype_values,
"Unknown",
GET_U_1((obj_tptr + 3)) + (256 * RSVP_OBJ_RRO)),
GET_U_1((obj_tptr + 3)),
GET_BE_U_4(obj_tptr + 4));
}
obj_tlen-=length;
obj_tptr+=length;
}
break;
default:
hexdump=TRUE;
}
break;
case RSVP_OBJ_HELLO:
switch(rsvp_obj_ctype) {
case RSVP_CTYPE_1:
case RSVP_CTYPE_2:
if (obj_tlen < 8)
goto obj_tooshort;
ND_PRINT("%s Source Instance: 0x%08x, Destination Instance: 0x%08x",
indent,
GET_BE_U_4(obj_tptr),
GET_BE_U_4(obj_tptr + 4));
obj_tlen-=8;
obj_tptr+=8;
break;
default:
hexdump=TRUE;
}
break;
case RSVP_OBJ_RESTART_CAPABILITY:
switch(rsvp_obj_ctype) {
case RSVP_CTYPE_1:
if (obj_tlen < 8)
goto obj_tooshort;
ND_PRINT("%s Restart Time: %ums, Recovery Time: %ums",
indent,
GET_BE_U_4(obj_tptr),
GET_BE_U_4(obj_tptr + 4));
obj_tlen-=8;
obj_tptr+=8;
break;
default:
hexdump=TRUE;
}
break;
case RSVP_OBJ_CAPABILITY:
switch(rsvp_obj_ctype) {
case RSVP_CTYPE_1:
if (obj_tlen < 4)
goto obj_tooshort;
uint32_t unused_and_flags = GET_BE_U_4(obj_tptr);
if (unused_and_flags & ~RSVP_OBJ_CAPABILITY_FLAGS_MASK)
ND_PRINT("%s [reserved=0x%08x must be zero]", indent,
unused_and_flags & ~RSVP_OBJ_CAPABILITY_FLAGS_MASK);
ND_PRINT("%s Flags: [%s]",
indent,
bittok2str(rsvp_obj_capability_flag_values,
"none",
(unused_and_flags & RSVP_OBJ_CAPABILITY_FLAGS_MASK)));
obj_tlen-=4;
obj_tptr+=4;
break;
default:
hexdump=TRUE;
}
break;
case RSVP_OBJ_SESSION_ATTRIBUTE:
switch(rsvp_obj_ctype) {
case RSVP_CTYPE_TUNNEL_IPV4:
if (obj_tlen < 4)
goto obj_tooshort;
namelen = GET_U_1(obj_tptr + 3);
if (obj_tlen < 4+namelen)
goto obj_tooshort;
ND_PRINT("%s Session Name: ", indent);
for (i = 0; i < namelen; i++)
fn_print_char(ndo, GET_U_1(obj_tptr + 4 + i));
ND_PRINT("%s Setup Priority: %u, Holding Priority: %u, Flags: [%s] (%#x)",
indent,
GET_U_1(obj_tptr),
GET_U_1(obj_tptr + 1),
bittok2str(rsvp_session_attribute_flag_values,
"none",
GET_U_1((obj_tptr + 2))),
GET_U_1(obj_tptr + 2));
obj_tlen-=4+namelen;
obj_tptr+=4+namelen;
break;
default:
hexdump=TRUE;
}
break;
case RSVP_OBJ_GENERALIZED_UNI:
switch(rsvp_obj_ctype) {
u_int subobj_type,af,subobj_len,total_subobj_len;
case RSVP_CTYPE_1:
if (obj_tlen < 4)
goto obj_tooshort;
/* read variable length subobjects */
total_subobj_len = obj_tlen;
while(total_subobj_len > 0) {
/* If RFC 3476 Section 3.1 defined that a sub-object of the
* GENERALIZED_UNI RSVP object must have the Length field as
* a multiple of 4, instead of the check below it would be
* better to test total_subobj_len only once before the loop.
* So long as it does not define it and this while loop does
* not implement such a requirement, let's accept that within
* each iteration subobj_len may happen to be a multiple of 1
* and test it and total_subobj_len respectively.
*/
if (total_subobj_len < 4)
goto invalid;
subobj_len = GET_BE_U_2(obj_tptr);
subobj_type = (GET_BE_U_2(obj_tptr + 2))>>8;
af = (GET_BE_U_2(obj_tptr + 2))&0x00FF;
ND_PRINT("%s Subobject Type: %s (%u), AF: %s (%u), length: %u",
indent,
tok2str(rsvp_obj_generalized_uni_values, "Unknown", subobj_type),
subobj_type,
tok2str(af_values, "Unknown", af), af,
subobj_len);
/* In addition to what is explained above, the same spec does not
* explicitly say that the same Length field includes the 4-octet
* sub-object header, but as long as this while loop implements it
* as it does include, let's keep the check below consistent with
* the rest of the code.
*
* XXX - RFC 3476 Section 3.1 says "The contents of these
* sub-objects are described in [8]", where [8] is
* UNI 1.0 Signaling Specification, The Optical
* Internetworking Forum. The URL they give for that
* document is
*
* http://www.oiforum.com/public/UNI_1.0_ia.html
*
* but that doesn't work; the new URL appears to be
*
* https://web.archive.org/web/20160401194747/http://www.oiforum.com/public/documents/OIF-UNI-01.0.pdf
*
* and *that* document, in section 12.5.2.3
* "GENERALIZED_UNI Object (Class-Num=11bbbbbb (TBA))",
* says nothing about the length field in general, but
* some of the examples it gives in subsections have
* length field values that clearly includes the length
* of the sub-object header as well as the length of the
* value.
*/
if(subobj_len < 4 || subobj_len > total_subobj_len ||
obj_tlen < subobj_len)
goto invalid;
switch(subobj_type) {
case RSVP_GEN_UNI_SUBOBJ_SOURCE_TNA_ADDRESS:
case RSVP_GEN_UNI_SUBOBJ_DESTINATION_TNA_ADDRESS:
switch(af) {
case AFNUM_INET:
if (subobj_len < 8)
goto subobj_tooshort;
ND_PRINT("%s UNI IPv4 TNA address: %s",
indent, GET_IPADDR_STRING(obj_tptr + 4));
break;
case AFNUM_INET6:
if (subobj_len < 20)
goto subobj_tooshort;
ND_PRINT("%s UNI IPv6 TNA address: %s",
indent, GET_IP6ADDR_STRING(obj_tptr + 4));
break;
case AFNUM_NSAP:
if (subobj_len) {
/* unless we have a TLV parser lets just hexdump */
hexdump=TRUE;
}
break;
}
break;
case RSVP_GEN_UNI_SUBOBJ_DIVERSITY:
if (subobj_len > 4) {
/* unless we have a TLV parser lets just hexdump */
hexdump=TRUE;
}
break;
case RSVP_GEN_UNI_SUBOBJ_EGRESS_LABEL:
if (subobj_len < 16) {
goto subobj_tooshort;
}
ND_PRINT("%s U-bit: %x, Label type: %u, Logical port id: %u, Label: %u",
indent,
((GET_BE_U_4(obj_tptr + 4))>>31),
((GET_BE_U_4(obj_tptr + 4))&0xFF),
GET_BE_U_4(obj_tptr + 8),
GET_BE_U_4(obj_tptr + 12));
break;
case RSVP_GEN_UNI_SUBOBJ_SERVICE_LEVEL:
if (subobj_len < 8) {
goto subobj_tooshort;
}
ND_PRINT("%s Service level: %u",
indent, (GET_BE_U_4(obj_tptr + 4)) >> 24);
break;
default:
hexdump=TRUE;
break;
}
total_subobj_len-=subobj_len;
obj_tptr+=subobj_len;
obj_tlen+=subobj_len;
}
break;
default:
hexdump=TRUE;
}
break;
case RSVP_OBJ_RSVP_HOP:
switch(rsvp_obj_ctype) {
case RSVP_CTYPE_3: /* fall through - FIXME add TLV parser */
case RSVP_CTYPE_IPV4:
if (obj_tlen < 8)
goto obj_tooshort;
ND_PRINT("%s Previous/Next Interface: %s, Logical Interface Handle: 0x%08x",
indent,
GET_IPADDR_STRING(obj_tptr),
GET_BE_U_4(obj_tptr + 4));
obj_tlen-=8;
obj_tptr+=8;
if (obj_tlen)
hexdump=TRUE; /* unless we have a TLV parser lets just hexdump */
break;
case RSVP_CTYPE_4: /* fall through - FIXME add TLV parser */
case RSVP_CTYPE_IPV6:
if (obj_tlen < 20)
goto obj_tooshort;
ND_PRINT("%s Previous/Next Interface: %s, Logical Interface Handle: 0x%08x",
indent,
GET_IP6ADDR_STRING(obj_tptr),
GET_BE_U_4(obj_tptr + 16));
obj_tlen-=20;
obj_tptr+=20;
hexdump=TRUE; /* unless we have a TLV parser lets just hexdump */
break;
default:
hexdump=TRUE;
}
break;
case RSVP_OBJ_TIME_VALUES:
switch(rsvp_obj_ctype) {
case RSVP_CTYPE_1:
if (obj_tlen < 4)
goto obj_tooshort;
ND_PRINT("%s Refresh Period: %ums",
indent,
GET_BE_U_4(obj_tptr));
obj_tlen-=4;
obj_tptr+=4;
break;
default:
hexdump=TRUE;
}
break;
/* those three objects do share the same semantics */
case RSVP_OBJ_SENDER_TSPEC:
case RSVP_OBJ_ADSPEC:
case RSVP_OBJ_FLOWSPEC:
switch(rsvp_obj_ctype) {
case RSVP_CTYPE_2:
if (obj_tlen < 4)
goto obj_tooshort;
ND_PRINT("%s Msg-Version: %u, length: %u",
indent,
(GET_U_1(obj_tptr) & 0xf0) >> 4,
GET_BE_U_2(obj_tptr + 2) << 2);
obj_tptr+=4; /* get to the start of the service header */
obj_tlen-=4;
while (obj_tlen >= 4) {
intserv_serv_tlen=GET_BE_U_2(obj_tptr + 2)<<2;
ND_PRINT("%s Service Type: %s (%u), break bit %sset, Service length: %u",
indent,
tok2str(rsvp_intserv_service_type_values,"unknown",GET_U_1((obj_tptr))),
GET_U_1(obj_tptr),
(GET_U_1(obj_tptr + 1)&0x80) ? "" : "not ",
intserv_serv_tlen);
obj_tptr+=4; /* get to the start of the parameter list */
obj_tlen-=4;
while (intserv_serv_tlen>=4) {
processed = rsvp_intserv_print(ndo, obj_tptr, obj_tlen);
if (processed == 0)
break;
obj_tlen-=processed;
intserv_serv_tlen-=processed;
obj_tptr+=processed;
}
}
break;
default:
hexdump=TRUE;
}
break;
case RSVP_OBJ_FILTERSPEC:
switch(rsvp_obj_ctype) {
case RSVP_CTYPE_IPV4:
if (obj_tlen < 8)
goto obj_tooshort;
ND_PRINT("%s Source Address: %s, Source Port: %u",
indent,
GET_IPADDR_STRING(obj_tptr),
GET_BE_U_2(obj_tptr + 6));
obj_tlen-=8;
obj_tptr+=8;
break;
case RSVP_CTYPE_IPV6:
if (obj_tlen < 20)
goto obj_tooshort;
ND_PRINT("%s Source Address: %s, Source Port: %u",
indent,
GET_IP6ADDR_STRING(obj_tptr),
GET_BE_U_2(obj_tptr + 18));
obj_tlen-=20;
obj_tptr+=20;
break;
case RSVP_CTYPE_3:
if (obj_tlen < 20)
goto obj_tooshort;
ND_PRINT("%s Source Address: %s, Flow Label: %u",
indent,
GET_IP6ADDR_STRING(obj_tptr),
GET_BE_U_3(obj_tptr + 17));
obj_tlen-=20;
obj_tptr+=20;
break;
case RSVP_CTYPE_TUNNEL_IPV6:
if (obj_tlen < 20)
goto obj_tooshort;
ND_PRINT("%s Source Address: %s, LSP-ID: 0x%04x",
indent,
GET_IPADDR_STRING(obj_tptr),
GET_BE_U_2(obj_tptr + 18));
obj_tlen-=20;
obj_tptr+=20;
break;
case RSVP_CTYPE_13: /* IPv6 p2mp LSP tunnel */
if (obj_tlen < 40)
goto obj_tooshort;
ND_PRINT("%s IPv6 Tunnel Sender Address: %s, LSP ID: 0x%04x"
"%s Sub-Group Originator ID: %s, Sub-Group ID: 0x%04x",
indent,
GET_IP6ADDR_STRING(obj_tptr),
GET_BE_U_2(obj_tptr + 18),
indent,
GET_IP6ADDR_STRING(obj_tptr+20),
GET_BE_U_2(obj_tptr + 38));
obj_tlen-=40;
obj_tptr+=40;
break;
case RSVP_CTYPE_TUNNEL_IPV4:
if (obj_tlen < 8)
goto obj_tooshort;
ND_PRINT("%s Source Address: %s, LSP-ID: 0x%04x",
indent,
GET_IPADDR_STRING(obj_tptr),
GET_BE_U_2(obj_tptr + 6));
obj_tlen-=8;
obj_tptr+=8;
break;
case RSVP_CTYPE_12: /* IPv4 p2mp LSP tunnel */
if (obj_tlen < 16)
goto obj_tooshort;
ND_PRINT("%s IPv4 Tunnel Sender Address: %s, LSP ID: 0x%04x"
"%s Sub-Group Originator ID: %s, Sub-Group ID: 0x%04x",
indent,
GET_IPADDR_STRING(obj_tptr),
GET_BE_U_2(obj_tptr + 6),
indent,
GET_IPADDR_STRING(obj_tptr+8),
GET_BE_U_2(obj_tptr + 12));
obj_tlen-=16;
obj_tptr+=16;
break;
default:
hexdump=TRUE;
}
break;
case RSVP_OBJ_FASTREROUTE:
/* the differences between c-type 1 and 7 are minor */
obj_ptr.rsvp_obj_frr = (const struct rsvp_obj_frr_t *)obj_tptr;
switch(rsvp_obj_ctype) {
case RSVP_CTYPE_1: /* new style */
if (obj_tlen < sizeof(struct rsvp_obj_frr_t))
goto obj_tooshort;
bw.i = GET_BE_U_4(obj_ptr.rsvp_obj_frr->bandwidth);
ND_PRINT("%s Setup Priority: %u, Holding Priority: %u, Hop-limit: %u, Bandwidth: %.10g Mbps",
indent,
obj_ptr.rsvp_obj_frr->setup_prio,
obj_ptr.rsvp_obj_frr->hold_prio,
obj_ptr.rsvp_obj_frr->hop_limit,
bw.f * 8 / 1000000);
ND_PRINT("%s Include-any: 0x%08x, Exclude-any: 0x%08x, Include-all: 0x%08x",
indent,
GET_BE_U_4(obj_ptr.rsvp_obj_frr->include_any),
GET_BE_U_4(obj_ptr.rsvp_obj_frr->exclude_any),
GET_BE_U_4(obj_ptr.rsvp_obj_frr->include_all));
obj_tlen-=sizeof(struct rsvp_obj_frr_t);
obj_tptr+=sizeof(struct rsvp_obj_frr_t);
break;
case RSVP_CTYPE_TUNNEL_IPV4: /* old style */
if (obj_tlen < 16)
goto obj_tooshort;
bw.i = GET_BE_U_4(obj_ptr.rsvp_obj_frr->bandwidth);
ND_PRINT("%s Setup Priority: %u, Holding Priority: %u, Hop-limit: %u, Bandwidth: %.10g Mbps",
indent,
obj_ptr.rsvp_obj_frr->setup_prio,
obj_ptr.rsvp_obj_frr->hold_prio,
obj_ptr.rsvp_obj_frr->hop_limit,
bw.f * 8 / 1000000);
ND_PRINT("%s Include Colors: 0x%08x, Exclude Colors: 0x%08x",
indent,
GET_BE_U_4(obj_ptr.rsvp_obj_frr->include_any),
GET_BE_U_4(obj_ptr.rsvp_obj_frr->exclude_any));
obj_tlen-=16;
obj_tptr+=16;
break;
default:
hexdump=TRUE;
}
break;
case RSVP_OBJ_DETOUR:
switch(rsvp_obj_ctype) {
case RSVP_CTYPE_TUNNEL_IPV4:
while(obj_tlen >= 8) {
ND_PRINT("%s PLR-ID: %s, Avoid-Node-ID: %s",
indent,
GET_IPADDR_STRING(obj_tptr),
GET_IPADDR_STRING(obj_tptr + 4));
obj_tlen-=8;
obj_tptr+=8;
}
break;
default:
hexdump=TRUE;
}
break;
case RSVP_OBJ_CLASSTYPE:
case RSVP_OBJ_CLASSTYPE_OLD: /* fall through */
switch(rsvp_obj_ctype) {
case RSVP_CTYPE_1:
if (obj_tlen < 4)
goto obj_tooshort;
ND_PRINT("%s CT: %u",
indent,
GET_BE_U_4(obj_tptr) & 0x7);
obj_tlen-=4;
obj_tptr+=4;
break;
default:
hexdump=TRUE;
}
break;
case RSVP_OBJ_ERROR_SPEC:
switch(rsvp_obj_ctype) {
case RSVP_CTYPE_3: /* fall through - FIXME add TLV parser */
case RSVP_CTYPE_IPV4:
if (obj_tlen < 8)
goto obj_tooshort;
error_code=GET_U_1(obj_tptr + 5);
error_value=GET_BE_U_2(obj_tptr + 6);
ND_PRINT("%s Error Node Address: %s, Flags: [0x%02x]%s Error Code: %s (%u)",
indent,
GET_IPADDR_STRING(obj_tptr),
GET_U_1(obj_tptr + 4),
indent,
tok2str(rsvp_obj_error_code_values,"unknown",error_code),
error_code);
switch (error_code) {
case RSVP_OBJ_ERROR_SPEC_CODE_ROUTING:
ND_PRINT(", Error Value: %s (%u)",
tok2str(rsvp_obj_error_code_routing_values,"unknown",error_value),
error_value);
break;
case RSVP_OBJ_ERROR_SPEC_CODE_DIFFSERV_TE: /* fall through */
case RSVP_OBJ_ERROR_SPEC_CODE_DIFFSERV_TE_OLD:
ND_PRINT(", Error Value: %s (%u)",
tok2str(rsvp_obj_error_code_diffserv_te_values,"unknown",error_value),
error_value);
break;
default:
ND_PRINT(", Unknown Error Value (%u)", error_value);
break;
}
obj_tlen-=8;
obj_tptr+=8;
break;
case RSVP_CTYPE_4: /* fall through - FIXME add TLV parser */
case RSVP_CTYPE_IPV6:
if (obj_tlen < 20)
goto obj_tooshort;
error_code=GET_U_1(obj_tptr + 17);
error_value=GET_BE_U_2(obj_tptr + 18);
ND_PRINT("%s Error Node Address: %s, Flags: [0x%02x]%s Error Code: %s (%u)",
indent,
GET_IP6ADDR_STRING(obj_tptr),
GET_U_1(obj_tptr + 16),
indent,
tok2str(rsvp_obj_error_code_values,"unknown",error_code),
error_code);
switch (error_code) {
case RSVP_OBJ_ERROR_SPEC_CODE_ROUTING:
ND_PRINT(", Error Value: %s (%u)",
tok2str(rsvp_obj_error_code_routing_values,"unknown",error_value),
error_value);
break;
default:
break;
}
obj_tlen-=20;
obj_tptr+=20;
break;
default:
hexdump=TRUE;
}
break;
case RSVP_OBJ_PROPERTIES:
switch(rsvp_obj_ctype) {
case RSVP_CTYPE_1:
if (obj_tlen < 4)
goto obj_tooshort;
padbytes = GET_BE_U_2(obj_tptr + 2);
ND_PRINT("%s TLV count: %u, padding bytes: %u",
indent,
GET_BE_U_2(obj_tptr),
padbytes);
obj_tlen-=4;
obj_tptr+=4;
/* loop through as long there is anything longer than the TLV header (2) */
while(obj_tlen >= 2 + padbytes) {
ND_PRINT("%s %s TLV (0x%02x), length: %u", /* length includes header */
indent,
tok2str(rsvp_obj_prop_tlv_values,"unknown",GET_U_1(obj_tptr)),
GET_U_1(obj_tptr),
GET_U_1(obj_tptr + 1));
if (obj_tlen < GET_U_1(obj_tptr + 1))
goto obj_tooshort;
if (GET_U_1(obj_tptr + 1) < 2) {
ND_PRINT("%sERROR: property TLV is too short", indent);
return -1;
}
print_unknown_data(ndo, obj_tptr + 2, "\n\t\t",
GET_U_1(obj_tptr + 1) - 2);
obj_tlen-=GET_U_1(obj_tptr + 1);
obj_tptr+=GET_U_1(obj_tptr + 1);
}
break;
default:
hexdump=TRUE;
}
break;
case RSVP_OBJ_MESSAGE_ID: /* fall through */
case RSVP_OBJ_MESSAGE_ID_ACK: /* fall through */
case RSVP_OBJ_MESSAGE_ID_LIST:
switch(rsvp_obj_ctype) {
case RSVP_CTYPE_1:
case RSVP_CTYPE_2:
if (obj_tlen < 4)
goto obj_tooshort;
ND_PRINT("%s Flags [0x%02x], epoch: %u",
indent,
GET_U_1(obj_tptr),
GET_BE_U_3(obj_tptr + 1));
obj_tlen-=4;
obj_tptr+=4;
/* loop through as long there are no messages left */
while(obj_tlen >= 4) {
ND_PRINT("%s Message-ID 0x%08x (%u)",
indent,
GET_BE_U_4(obj_tptr),
GET_BE_U_4(obj_tptr));
obj_tlen-=4;
obj_tptr+=4;
}
break;
default:
hexdump=TRUE;
}
break;
case RSVP_OBJ_INTEGRITY:
switch(rsvp_obj_ctype) {
case RSVP_CTYPE_1:
if (obj_tlen < sizeof(struct rsvp_obj_integrity_t))
goto obj_tooshort;
obj_ptr.rsvp_obj_integrity = (const struct rsvp_obj_integrity_t *)obj_tptr;
ND_PRINT("%s Key-ID 0x%04x%08x, Sequence 0x%08x%08x, Flags [%s]",
indent,
GET_BE_U_2(obj_ptr.rsvp_obj_integrity->key_id),
GET_BE_U_4(obj_ptr.rsvp_obj_integrity->key_id + 2),
GET_BE_U_4(obj_ptr.rsvp_obj_integrity->sequence),
GET_BE_U_4(obj_ptr.rsvp_obj_integrity->sequence + 4),
bittok2str(rsvp_obj_integrity_flag_values,
"none",
obj_ptr.rsvp_obj_integrity->flags));
ND_PRINT("%s MD5-sum 0x%08x%08x%08x%08x ",
indent,
GET_BE_U_4(obj_ptr.rsvp_obj_integrity->digest),
GET_BE_U_4(obj_ptr.rsvp_obj_integrity->digest + 4),
GET_BE_U_4(obj_ptr.rsvp_obj_integrity->digest + 8),
GET_BE_U_4(obj_ptr.rsvp_obj_integrity->digest + 12));
sigcheck = signature_verify(ndo, pptr, plen,
obj_ptr.rsvp_obj_integrity->digest,
rsvp_clear_checksum,
rsvp_com_header);
ND_PRINT(" (%s)", tok2str(signature_check_values, "Unknown", sigcheck));
obj_tlen+=sizeof(struct rsvp_obj_integrity_t);
obj_tptr+=sizeof(struct rsvp_obj_integrity_t);
break;
default:
hexdump=TRUE;
}
break;
case RSVP_OBJ_ADMIN_STATUS:
switch(rsvp_obj_ctype) {
case RSVP_CTYPE_1:
if (obj_tlen < 4)
goto obj_tooshort;
ND_PRINT("%s Flags [%s]", indent,
bittok2str(rsvp_obj_admin_status_flag_values, "none",
GET_BE_U_4(obj_tptr)));
obj_tlen-=4;
obj_tptr+=4;
break;
default:
hexdump=TRUE;
}
break;
case RSVP_OBJ_LABEL_SET:
switch(rsvp_obj_ctype) {
case RSVP_CTYPE_1:
if (obj_tlen < 4)
goto obj_tooshort;
action = (GET_BE_U_2(obj_tptr)>>8);
ND_PRINT("%s Action: %s (%u), Label type: %u", indent,
tok2str(rsvp_obj_label_set_action_values, "Unknown", action),
action, (GET_BE_U_4(obj_tptr) & 0x7F));
switch (action) {
case LABEL_SET_INCLUSIVE_RANGE:
case LABEL_SET_EXCLUSIVE_RANGE: /* fall through */
/* only a couple of subchannels are expected */
if (obj_tlen < 12)
goto obj_tooshort;
ND_PRINT("%s Start range: %u, End range: %u", indent,
GET_BE_U_4(obj_tptr + 4),
GET_BE_U_4(obj_tptr + 8));
obj_tlen-=12;
obj_tptr+=12;
break;
default:
obj_tlen-=4;
obj_tptr+=4;
subchannel = 1;
while(obj_tlen >= 4 ) {
ND_PRINT("%s Subchannel #%u: %u", indent, subchannel,
GET_BE_U_4(obj_tptr));
obj_tptr+=4;
obj_tlen-=4;
subchannel++;
}
break;
}
break;
default:
hexdump=TRUE;
}
break;
case RSVP_OBJ_S2L:
switch (rsvp_obj_ctype) {
case RSVP_CTYPE_IPV4:
if (obj_tlen < 4)
goto obj_tooshort;
ND_PRINT("%s Sub-LSP destination address: %s",
indent, GET_IPADDR_STRING(obj_tptr));
obj_tlen-=4;
obj_tptr+=4;
break;
case RSVP_CTYPE_IPV6:
if (obj_tlen < 16)
goto obj_tooshort;
ND_PRINT("%s Sub-LSP destination address: %s",
indent, GET_IP6ADDR_STRING(obj_tptr));
obj_tlen-=16;
obj_tptr+=16;
break;
default:
hexdump=TRUE;
}
break;
/*
* FIXME those are the defined objects that lack a decoder
* you are welcome to contribute code ;-)
*/
case RSVP_OBJ_SCOPE:
case RSVP_OBJ_POLICY_DATA:
case RSVP_OBJ_ACCEPT_LABEL_SET:
case RSVP_OBJ_PROTECTION:
default:
if (ndo->ndo_vflag <= 1)
print_unknown_data(ndo, obj_tptr, "\n\t ", obj_tlen); /* FIXME indentation */
break;
}
/* do we also want to see a hex dump ? */
if (ndo->ndo_vflag > 1 || hexdump == TRUE)
print_unknown_data(ndo, tptr + sizeof(struct rsvp_object_header), "\n\t ", /* FIXME indentation */
rsvp_obj_len - sizeof(struct rsvp_object_header));
tptr+=rsvp_obj_len;
tlen-=rsvp_obj_len;
}
return 0;
subobj_tooshort:
ND_PRINT("%sERROR: sub-object is too short", indent);
return -1;
obj_tooshort:
ND_PRINT("%sERROR: object is too short", indent);
return -1;
invalid:
nd_print_invalid(ndo);
return -1;
trunc:
nd_print_trunc(ndo);
return -1;
}
void
rsvp_print(netdissect_options *ndo,
const u_char *pptr, u_int len)
{
const struct rsvp_common_header *rsvp_com_header;
uint8_t version_flags, msg_type;
const u_char *tptr;
u_short plen, tlen;
ndo->ndo_protocol = "rsvp";
tptr=pptr;
rsvp_com_header = (const struct rsvp_common_header *)pptr;
ND_TCHECK_SIZE(rsvp_com_header);
version_flags = GET_U_1(rsvp_com_header->version_flags);
/*
* Sanity checking of the header.
*/
if (RSVP_EXTRACT_VERSION(version_flags) != RSVP_VERSION) {
ND_PRINT("ERROR: RSVP version %u packet not supported",
RSVP_EXTRACT_VERSION(version_flags));
return;
}
msg_type = GET_U_1(rsvp_com_header->msg_type);
/* in non-verbose mode just lets print the basic Message Type*/
if (ndo->ndo_vflag < 1) {
ND_PRINT("RSVPv%u %s Message, length: %u",
RSVP_EXTRACT_VERSION(version_flags),
tok2str(rsvp_msg_type_values, "unknown (%u)",msg_type),
len);
return;
}
/* ok they seem to want to know everything - lets fully decode it */
plen = tlen = GET_BE_U_2(rsvp_com_header->length);
ND_PRINT("\n\tRSVPv%u %s Message (%u), Flags: [%s], length: %u, ttl: %u, checksum: 0x%04x",
RSVP_EXTRACT_VERSION(version_flags),
tok2str(rsvp_msg_type_values, "unknown, type: %u",msg_type),
msg_type,
bittok2str(rsvp_header_flag_values,"none",RSVP_EXTRACT_FLAGS(version_flags)),
tlen,
GET_U_1(rsvp_com_header->ttl),
GET_BE_U_2(rsvp_com_header->checksum));
if (tlen < sizeof(struct rsvp_common_header)) {
ND_PRINT("ERROR: common header too short %u < %zu", tlen,
sizeof(struct rsvp_common_header));
return;
}
tptr+=sizeof(struct rsvp_common_header);
tlen-=sizeof(struct rsvp_common_header);
switch(msg_type) {
case RSVP_MSGTYPE_BUNDLE:
/*
* Process each submessage in the bundle message.
* Bundle messages may not contain bundle submessages, so we don't
* need to handle bundle submessages specially.
*/
while(tlen > 0) {
const u_char *subpptr=tptr, *subtptr;
u_short subplen, subtlen;
subtptr=subpptr;
rsvp_com_header = (const struct rsvp_common_header *)subpptr;
ND_TCHECK_SIZE(rsvp_com_header);
version_flags = GET_U_1(rsvp_com_header->version_flags);
/*
* Sanity checking of the header.
*/
if (RSVP_EXTRACT_VERSION(version_flags) != RSVP_VERSION) {
ND_PRINT("ERROR: RSVP version %u packet not supported",
RSVP_EXTRACT_VERSION(version_flags));
return;
}
subplen = subtlen = GET_BE_U_2(rsvp_com_header->length);
msg_type = GET_U_1(rsvp_com_header->msg_type);
ND_PRINT("\n\t RSVPv%u %s Message (%u), Flags: [%s], length: %u, ttl: %u, checksum: 0x%04x",
RSVP_EXTRACT_VERSION(version_flags),
tok2str(rsvp_msg_type_values, "unknown, type: %u",msg_type),
msg_type,
bittok2str(rsvp_header_flag_values,"none",RSVP_EXTRACT_FLAGS(version_flags)),
subtlen,
GET_U_1(rsvp_com_header->ttl),
GET_BE_U_2(rsvp_com_header->checksum));
if (subtlen < sizeof(struct rsvp_common_header)) {
ND_PRINT("ERROR: common header too short %u < %zu", subtlen,
sizeof(struct rsvp_common_header));
return;
}
if (tlen < subtlen) {
ND_PRINT("ERROR: common header too large %u > %u", subtlen,
tlen);
return;
}
subtptr+=sizeof(struct rsvp_common_header);
subtlen-=sizeof(struct rsvp_common_header);
/*
* Print all objects in the submessage.
*/
if (rsvp_obj_print(ndo, subpptr, subplen, subtptr, "\n\t ", subtlen, rsvp_com_header) == -1)
return;
tptr+=subtlen+sizeof(struct rsvp_common_header);
tlen-=subtlen+sizeof(struct rsvp_common_header);
}
break;
case RSVP_MSGTYPE_PATH:
case RSVP_MSGTYPE_RESV:
case RSVP_MSGTYPE_PATHERR:
case RSVP_MSGTYPE_RESVERR:
case RSVP_MSGTYPE_PATHTEAR:
case RSVP_MSGTYPE_RESVTEAR:
case RSVP_MSGTYPE_RESVCONF:
case RSVP_MSGTYPE_HELLO_OLD:
case RSVP_MSGTYPE_HELLO:
case RSVP_MSGTYPE_ACK:
case RSVP_MSGTYPE_SREFRESH:
/*
* Print all objects in the message.
*/
if (rsvp_obj_print(ndo, pptr, plen, tptr, "\n\t ", tlen, rsvp_com_header) == -1)
return;
break;
default:
print_unknown_data(ndo, tptr, "\n\t ", tlen);
break;
}
return;
trunc:
nd_print_trunc(ndo);
}
diff --git a/contrib/tcpdump/print-rt6.c b/contrib/tcpdump/print-rt6.c
index 096a96286c95..6019cd798eec 100644
--- a/contrib/tcpdump/print-rt6.c
+++ b/contrib/tcpdump/print-rt6.c
@@ -1,115 +1,113 @@
/*
* Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994
* 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.
*/
/* \summary: IPv6 routing header printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#include "ip6.h"
int
rt6_print(netdissect_options *ndo, const u_char *bp, const u_char *bp2 _U_)
{
const struct ip6_rthdr *dp;
const struct ip6_rthdr0 *dp0;
const struct ip6_srh *srh;
u_int i, len, type;
const u_char *p;
ndo->ndo_protocol = "rt6";
nd_print_protocol_caps(ndo);
dp = (const struct ip6_rthdr *)bp;
len = GET_U_1(dp->ip6r_len);
ND_PRINT(" (len=%u", len); /*)*/
type = GET_U_1(dp->ip6r_type);
ND_PRINT(", type=%u", type);
if (type == IPV6_RTHDR_TYPE_0)
ND_PRINT(" [Deprecated]");
ND_PRINT(", segleft=%u", GET_U_1(dp->ip6r_segleft));
switch (type) {
case IPV6_RTHDR_TYPE_0:
case IPV6_RTHDR_TYPE_2: /* Mobile IPv6 ID-20 */
dp0 = (const struct ip6_rthdr0 *)dp;
if (GET_BE_U_4(dp0->ip6r0_reserved) || ndo->ndo_vflag) {
ND_PRINT(", rsv=0x%0x",
GET_BE_U_4(dp0->ip6r0_reserved));
}
if (len % 2 == 1) {
- ND_PRINT(" (invalid length %u)", len);
+ ND_PRINT(" [length %u]", len);
goto invalid;
}
len >>= 1;
p = (const u_char *) dp0->ip6r0_addr;
for (i = 0; i < len; i++) {
ND_PRINT(", [%u]%s", i, GET_IP6ADDR_STRING(p));
p += 16;
}
/*(*/
ND_PRINT(") ");
return((GET_U_1(dp0->ip6r0_len) + 1) << 3);
break;
case IPV6_RTHDR_TYPE_4:
srh = (const struct ip6_srh *)dp;
ND_PRINT(", last-entry=%u", GET_U_1(srh->srh_last_ent));
if (GET_U_1(srh->srh_flags) || ndo->ndo_vflag) {
ND_PRINT(", flags=0x%0x",
GET_U_1(srh->srh_flags));
}
ND_PRINT(", tag=%x", GET_BE_U_2(srh->srh_tag));
if (len % 2 == 1) {
ND_PRINT(" (invalid length %u)", len);
goto invalid;
}
len >>= 1;
p = (const u_char *) srh->srh_segments;
for (i = 0; i < len; i++) {
ND_PRINT(", [%u]%s", i, GET_IP6ADDR_STRING(p));
p += 16;
}
/*(*/
ND_PRINT(") ");
return((GET_U_1(srh->srh_len) + 1) << 3);
break;
default:
ND_PRINT(" (unknown type)");
goto invalid;
}
invalid:
nd_print_invalid(ndo);
return -1;
}
diff --git a/contrib/tcpdump/print-rtsp.c b/contrib/tcpdump/print-rtsp.c
index 626a5ed9c89c..f240a90f99c1 100644
--- a/contrib/tcpdump/print-rtsp.c
+++ b/contrib/tcpdump/print-rtsp.c
@@ -1,44 +1,42 @@
/*
* 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.
*/
/* \summary: Real Time Streaming Protocol (RTSP) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
static const char *rtspcmds[] = {
"DESCRIBE",
"ANNOUNCE",
"GET_PARAMETER",
"OPTIONS",
"PAUSE",
"PLAY",
"RECORD",
"REDIRECT",
"SETUP",
"SET_PARAMETER",
"TEARDOWN",
NULL
};
void
rtsp_print(netdissect_options *ndo, const u_char *pptr, u_int len)
{
ndo->ndo_protocol = "rtsp";
txtproto_print(ndo, pptr, len, rtspcmds, RESP_CODE_SECOND_TOKEN);
}
diff --git a/contrib/tcpdump/print-rx.c b/contrib/tcpdump/print-rx.c
index 0a1a8d12d40d..3641a4c79e53 100644
--- a/contrib/tcpdump/print-rx.c
+++ b/contrib/tcpdump/print-rx.c
@@ -1,2842 +1,2840 @@
/*
* Copyright: (c) 2000 United States Government as represented by the
* Secretary of the Navy. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. The names of the authors may not 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.
*/
/* \summary: AFS RX printer */
/*
* This code unmangles RX packets. RX is the mutant form of RPC that AFS
* uses to communicate between clients and servers.
*
* In this code, I mainly concern myself with decoding the AFS calls, not
* with the guts of RX, per se.
*
* Bah. If I never look at rx_packet.h again, it will be too soon.
*
* Ken Hornstein <kenh@cmf.nrl.navy.mil>
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include <stdio.h>
#include <string.h>
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#include "ip.h"
#define FS_RX_PORT 7000
#define CB_RX_PORT 7001
#define PROT_RX_PORT 7002
#define VLDB_RX_PORT 7003
#define KAUTH_RX_PORT 7004
#define VOL_RX_PORT 7005
#define ERROR_RX_PORT 7006 /* Doesn't seem to be used */
#define BOS_RX_PORT 7007
#define AFSOPAQUEMAX 1024
#define AFSNAMEMAX 256 /* Must be >= PRNAMEMAX + 1, VLNAMEMAX + 1, and 32 + 1 */
#define PRNAMEMAX 64
#define VLNAMEMAX 65
#define KANAMEMAX 64
#define BOSNAMEMAX 256
#define USERNAMEMAX 1024 /* AFSOPAQUEMAX was used for this; does it need to be this big? */
#define PRSFS_READ 1 /* Read files */
#define PRSFS_WRITE 2 /* Write files */
#define PRSFS_INSERT 4 /* Insert files into a directory */
#define PRSFS_LOOKUP 8 /* Lookup files into a directory */
#define PRSFS_DELETE 16 /* Delete files */
#define PRSFS_LOCK 32 /* Lock files */
#define PRSFS_ADMINISTER 64 /* Change ACL's */
struct rx_header {
nd_uint32_t epoch;
nd_uint32_t cid;
nd_uint32_t callNumber;
nd_uint32_t seq;
nd_uint32_t serial;
nd_uint8_t type;
#define RX_PACKET_TYPE_DATA 1
#define RX_PACKET_TYPE_ACK 2
#define RX_PACKET_TYPE_BUSY 3
#define RX_PACKET_TYPE_ABORT 4
#define RX_PACKET_TYPE_ACKALL 5
#define RX_PACKET_TYPE_CHALLENGE 6
#define RX_PACKET_TYPE_RESPONSE 7
#define RX_PACKET_TYPE_DEBUG 8
#define RX_PACKET_TYPE_PARAMS 9
#define RX_PACKET_TYPE_VERSION 13
nd_uint8_t flags;
#define RX_CLIENT_INITIATED 1
#define RX_REQUEST_ACK 2
#define RX_LAST_PACKET 4
#define RX_MORE_PACKETS 8
#define RX_FREE_PACKET 16
#define RX_SLOW_START_OK 32
#define RX_JUMBO_PACKET 32
nd_uint8_t userStatus;
nd_uint8_t securityIndex;
nd_uint16_t spare; /* How clever: even though the AFS */
nd_uint16_t serviceId; /* header files indicate that the */
}; /* serviceId is first, it's really */
/* encoded _after_ the spare field */
/* I wasted a day figuring that out! */
#define NUM_RX_FLAGS 7
#define RX_MAXACKS 255
struct rx_ackPacket {
nd_uint16_t bufferSpace; /* Number of packet buffers available */
nd_uint16_t maxSkew; /* Max diff between ack'd packet and */
/* highest packet received */
nd_uint32_t firstPacket; /* The first packet in ack list */
nd_uint32_t previousPacket; /* Previous packet recv'd (obsolete) */
nd_uint32_t serial; /* # of packet that prompted the ack */
nd_uint8_t reason; /* Reason for acknowledgement */
nd_uint8_t nAcks; /* Number of acknowledgements */
/* Followed by nAcks acknowledgments */
#if 0
uint8_t acks[RX_MAXACKS]; /* Up to RX_MAXACKS acknowledgements */
#endif
};
/*
* Values for the acks array
*/
#define RX_ACK_TYPE_NACK 0 /* Don't have this packet */
#define RX_ACK_TYPE_ACK 1 /* I have this packet */
static const struct tok rx_types[] = {
{ RX_PACKET_TYPE_DATA, "data" },
{ RX_PACKET_TYPE_ACK, "ack" },
{ RX_PACKET_TYPE_BUSY, "busy" },
{ RX_PACKET_TYPE_ABORT, "abort" },
{ RX_PACKET_TYPE_ACKALL, "ackall" },
{ RX_PACKET_TYPE_CHALLENGE, "challenge" },
{ RX_PACKET_TYPE_RESPONSE, "response" },
{ RX_PACKET_TYPE_DEBUG, "debug" },
{ RX_PACKET_TYPE_PARAMS, "params" },
{ RX_PACKET_TYPE_VERSION, "version" },
{ 0, NULL },
};
static const struct double_tok {
uint32_t flag; /* Rx flag */
uint32_t packetType; /* Packet type */
const char *s; /* Flag string */
} rx_flags[] = {
{ RX_CLIENT_INITIATED, 0, "client-init" },
{ RX_REQUEST_ACK, 0, "req-ack" },
{ RX_LAST_PACKET, 0, "last-pckt" },
{ RX_MORE_PACKETS, 0, "more-pckts" },
{ RX_FREE_PACKET, 0, "free-pckt" },
{ RX_SLOW_START_OK, RX_PACKET_TYPE_ACK, "slow-start" },
{ RX_JUMBO_PACKET, RX_PACKET_TYPE_DATA, "jumbogram" }
};
static const struct tok fs_req[] = {
{ 130, "fetch-data" },
{ 131, "fetch-acl" },
{ 132, "fetch-status" },
{ 133, "store-data" },
{ 134, "store-acl" },
{ 135, "store-status" },
{ 136, "remove-file" },
{ 137, "create-file" },
{ 138, "rename" },
{ 139, "symlink" },
{ 140, "link" },
{ 141, "makedir" },
{ 142, "rmdir" },
{ 143, "oldsetlock" },
{ 144, "oldextlock" },
{ 145, "oldrellock" },
{ 146, "get-stats" },
{ 147, "give-cbs" },
{ 148, "get-vlinfo" },
{ 149, "get-vlstats" },
{ 150, "set-vlstats" },
{ 151, "get-rootvl" },
{ 152, "check-token" },
{ 153, "get-time" },
{ 154, "nget-vlinfo" },
{ 155, "bulk-stat" },
{ 156, "setlock" },
{ 157, "extlock" },
{ 158, "rellock" },
{ 159, "xstat-ver" },
{ 160, "get-xstat" },
{ 161, "dfs-lookup" },
{ 162, "dfs-flushcps" },
{ 163, "dfs-symlink" },
{ 220, "residency" },
{ 65536, "inline-bulk-status" },
{ 65537, "fetch-data-64" },
{ 65538, "store-data-64" },
{ 65539, "give-up-all-cbs" },
{ 65540, "get-caps" },
{ 65541, "cb-rx-conn-addr" },
{ 0, NULL },
};
static const struct tok cb_req[] = {
{ 204, "callback" },
{ 205, "initcb" },
{ 206, "probe" },
{ 207, "getlock" },
{ 208, "getce" },
{ 209, "xstatver" },
{ 210, "getxstat" },
{ 211, "initcb2" },
{ 212, "whoareyou" },
{ 213, "initcb3" },
{ 214, "probeuuid" },
{ 215, "getsrvprefs" },
{ 216, "getcellservdb" },
{ 217, "getlocalcell" },
{ 218, "getcacheconf" },
{ 65536, "getce64" },
{ 65537, "getcellbynum" },
{ 65538, "tellmeaboutyourself" },
{ 0, NULL },
};
static const struct tok pt_req[] = {
{ 500, "new-user" },
{ 501, "where-is-it" },
{ 502, "dump-entry" },
{ 503, "add-to-group" },
{ 504, "name-to-id" },
{ 505, "id-to-name" },
{ 506, "delete" },
{ 507, "remove-from-group" },
{ 508, "get-cps" },
{ 509, "new-entry" },
{ 510, "list-max" },
{ 511, "set-max" },
{ 512, "list-entry" },
{ 513, "change-entry" },
{ 514, "list-elements" },
{ 515, "same-mbr-of" },
{ 516, "set-fld-sentry" },
{ 517, "list-owned" },
{ 518, "get-cps2" },
{ 519, "get-host-cps" },
{ 520, "update-entry" },
{ 521, "list-entries" },
{ 530, "list-super-groups" },
{ 0, NULL },
};
static const struct tok vldb_req[] = {
{ 501, "create-entry" },
{ 502, "delete-entry" },
{ 503, "get-entry-by-id" },
{ 504, "get-entry-by-name" },
{ 505, "get-new-volume-id" },
{ 506, "replace-entry" },
{ 507, "update-entry" },
{ 508, "setlock" },
{ 509, "releaselock" },
{ 510, "list-entry" },
{ 511, "list-attrib" },
{ 512, "linked-list" },
{ 513, "get-stats" },
{ 514, "probe" },
{ 515, "get-addrs" },
{ 516, "change-addr" },
{ 517, "create-entry-n" },
{ 518, "get-entry-by-id-n" },
{ 519, "get-entry-by-name-n" },
{ 520, "replace-entry-n" },
{ 521, "list-entry-n" },
{ 522, "list-attrib-n" },
{ 523, "linked-list-n" },
{ 524, "update-entry-by-name" },
{ 525, "create-entry-u" },
{ 526, "get-entry-by-id-u" },
{ 527, "get-entry-by-name-u" },
{ 528, "replace-entry-u" },
{ 529, "list-entry-u" },
{ 530, "list-attrib-u" },
{ 531, "linked-list-u" },
{ 532, "regaddr" },
{ 533, "get-addrs-u" },
{ 534, "list-attrib-n2" },
{ 0, NULL },
};
static const struct tok kauth_req[] = {
{ 1, "auth-old" },
{ 21, "authenticate" },
{ 22, "authenticate-v2" },
{ 2, "change-pw" },
{ 3, "get-ticket-old" },
{ 23, "get-ticket" },
{ 4, "set-pw" },
{ 5, "set-fields" },
{ 6, "create-user" },
{ 7, "delete-user" },
{ 8, "get-entry" },
{ 9, "list-entry" },
{ 10, "get-stats" },
{ 11, "debug" },
{ 12, "get-pw" },
{ 13, "get-random-key" },
{ 14, "unlock" },
{ 15, "lock-status" },
{ 0, NULL },
};
static const struct tok vol_req[] = {
{ 100, "create-volume" },
{ 101, "delete-volume" },
{ 102, "restore" },
{ 103, "forward" },
{ 104, "end-trans" },
{ 105, "clone" },
{ 106, "set-flags" },
{ 107, "get-flags" },
{ 108, "trans-create" },
{ 109, "dump" },
{ 110, "get-nth-volume" },
{ 111, "set-forwarding" },
{ 112, "get-name" },
{ 113, "get-status" },
{ 114, "sig-restore" },
{ 115, "list-partitions" },
{ 116, "list-volumes" },
{ 117, "set-id-types" },
{ 118, "monitor" },
{ 119, "partition-info" },
{ 120, "reclone" },
{ 121, "list-one-volume" },
{ 122, "nuke" },
{ 123, "set-date" },
{ 124, "x-list-volumes" },
{ 125, "x-list-one-volume" },
{ 126, "set-info" },
{ 127, "x-list-partitions" },
{ 128, "forward-multiple" },
{ 65536, "convert-ro" },
{ 65537, "get-size" },
{ 65538, "dump-v2" },
{ 0, NULL },
};
static const struct tok bos_req[] = {
{ 80, "create-bnode" },
{ 81, "delete-bnode" },
{ 82, "set-status" },
{ 83, "get-status" },
{ 84, "enumerate-instance" },
{ 85, "get-instance-info" },
{ 86, "get-instance-parm" },
{ 87, "add-superuser" },
{ 88, "delete-superuser" },
{ 89, "list-superusers" },
{ 90, "list-keys" },
{ 91, "add-key" },
{ 92, "delete-key" },
{ 93, "set-cell-name" },
{ 94, "get-cell-name" },
{ 95, "get-cell-host" },
{ 96, "add-cell-host" },
{ 97, "delete-cell-host" },
{ 98, "set-t-status" },
{ 99, "shutdown-all" },
{ 100, "restart-all" },
{ 101, "startup-all" },
{ 102, "set-noauth-flag" },
{ 103, "re-bozo" },
{ 104, "restart" },
{ 105, "start-bozo-install" },
{ 106, "uninstall" },
{ 107, "get-dates" },
{ 108, "exec" },
{ 109, "prune" },
{ 110, "set-restart-time" },
{ 111, "get-restart-time" },
{ 112, "start-bozo-log" },
{ 113, "wait-all" },
{ 114, "get-instance-strings" },
{ 115, "get-restricted" },
{ 116, "set-restricted" },
{ 0, NULL },
};
static const struct tok ubik_req[] = {
{ 10000, "vote-beacon" },
{ 10001, "vote-debug-old" },
{ 10002, "vote-sdebug-old" },
{ 10003, "vote-getsyncsite" },
{ 10004, "vote-debug" },
{ 10005, "vote-sdebug" },
{ 10006, "vote-xdebug" },
{ 10007, "vote-xsdebug" },
{ 20000, "disk-begin" },
{ 20001, "disk-commit" },
{ 20002, "disk-lock" },
{ 20003, "disk-write" },
{ 20004, "disk-getversion" },
{ 20005, "disk-getfile" },
{ 20006, "disk-sendfile" },
{ 20007, "disk-abort" },
{ 20008, "disk-releaselocks" },
{ 20009, "disk-truncate" },
{ 20010, "disk-probe" },
{ 20011, "disk-writev" },
{ 20012, "disk-interfaceaddr" },
{ 20013, "disk-setversion" },
{ 0, NULL },
};
#define VOTE_LOW 10000
#define VOTE_HIGH 10007
#define DISK_LOW 20000
#define DISK_HIGH 20013
static const struct tok cb_types[] = {
{ 1, "exclusive" },
{ 2, "shared" },
{ 3, "dropped" },
{ 0, NULL },
};
static const struct tok ubik_lock_types[] = {
{ 1, "read" },
{ 2, "write" },
{ 3, "wait" },
{ 0, NULL },
};
static const char *voltype[] = { "read-write", "read-only", "backup" };
static const struct tok afs_fs_errors[] = {
{ 101, "salvage volume" },
{ 102, "no such vnode" },
{ 103, "no such volume" },
{ 104, "volume exist" },
{ 105, "no service" },
{ 106, "volume offline" },
{ 107, "voline online" },
{ 108, "diskfull" },
{ 109, "diskquota exceeded" },
{ 110, "volume busy" },
{ 111, "volume moved" },
{ 112, "AFS IO error" },
{ 0xffffff9c, "restarting fileserver" }, /* -100, sic! */
{ 0, NULL }
};
/*
* Reasons for acknowledging a packet
*/
static const struct tok rx_ack_reasons[] = {
{ 1, "ack requested" },
{ 2, "duplicate packet" },
{ 3, "out of sequence" },
{ 4, "exceeds window" },
{ 5, "no buffer space" },
{ 6, "ping" },
{ 7, "ping response" },
{ 8, "delay" },
{ 9, "idle" },
{ 0, NULL },
};
/*
* Cache entries we keep around so we can figure out the RX opcode
* numbers for replies. This allows us to make sense of RX reply packets.
*/
struct rx_cache_entry {
uint32_t callnum; /* Call number (net order) */
uint32_t client; /* client IP address (net order) */
uint32_t server; /* server IP address (net order) */
uint16_t dport; /* server UDP port (host order) */
uint16_t serviceId; /* Service identifier (net order) */
uint32_t opcode; /* RX opcode (host order) */
};
#define RX_CACHE_SIZE 64
static struct rx_cache_entry rx_cache[RX_CACHE_SIZE];
static uint32_t rx_cache_next = 0;
static uint32_t rx_cache_hint = 0;
static void rx_cache_insert(netdissect_options *, const u_char *, const struct ip *, uint16_t);
static int rx_cache_find(netdissect_options *, const struct rx_header *,
const struct ip *, uint16_t, uint32_t *);
static void fs_print(netdissect_options *, const u_char *, u_int);
static void fs_reply_print(netdissect_options *, const u_char *, u_int, uint32_t);
static void acl_print(netdissect_options *, u_char *, const u_char *);
static void cb_print(netdissect_options *, const u_char *, u_int);
static void cb_reply_print(netdissect_options *, const u_char *, u_int, uint32_t);
static void prot_print(netdissect_options *, const u_char *, u_int);
static void prot_reply_print(netdissect_options *, const u_char *, u_int, uint32_t);
static void vldb_print(netdissect_options *, const u_char *, u_int);
static void vldb_reply_print(netdissect_options *, const u_char *, u_int, uint32_t);
static void kauth_print(netdissect_options *, const u_char *, u_int);
static void kauth_reply_print(netdissect_options *, const u_char *, u_int, uint32_t);
static void vol_print(netdissect_options *, const u_char *, u_int);
static void vol_reply_print(netdissect_options *, const u_char *, u_int, uint32_t);
static void bos_print(netdissect_options *, const u_char *, u_int);
static void bos_reply_print(netdissect_options *, const u_char *, u_int, uint32_t);
static void ubik_print(netdissect_options *, const u_char *);
static void ubik_reply_print(netdissect_options *, const u_char *, u_int, uint32_t);
static void rx_ack_print(netdissect_options *, const u_char *, u_int);
static int is_ubik(uint32_t);
/*
* Handle the rx-level packet. See if we know what port it's going to so
* we can peek at the afs call inside
*/
void
rx_print(netdissect_options *ndo,
const u_char *bp, u_int length, uint16_t sport, uint16_t dport,
const u_char *bp2)
{
const struct rx_header *rxh;
uint32_t i;
uint8_t type, flags;
uint32_t opcode;
ndo->ndo_protocol = "rx";
if (!ND_TTEST_LEN(bp, sizeof(struct rx_header))) {
ND_PRINT(" [|rx] (%u)", length);
return;
}
rxh = (const struct rx_header *) bp;
type = GET_U_1(rxh->type);
ND_PRINT(" rx %s", tok2str(rx_types, "type %u", type));
flags = GET_U_1(rxh->flags);
if (ndo->ndo_vflag) {
int firstflag = 0;
if (ndo->ndo_vflag > 1)
ND_PRINT(" cid %08x call# %u",
GET_BE_U_4(rxh->cid),
GET_BE_U_4(rxh->callNumber));
ND_PRINT(" seq %u ser %u",
GET_BE_U_4(rxh->seq),
GET_BE_U_4(rxh->serial));
if (ndo->ndo_vflag > 2)
ND_PRINT(" secindex %u serviceid %hu",
GET_U_1(rxh->securityIndex),
GET_BE_U_2(rxh->serviceId));
if (ndo->ndo_vflag > 1)
for (i = 0; i < NUM_RX_FLAGS; i++) {
if (flags & rx_flags[i].flag &&
(!rx_flags[i].packetType ||
type == rx_flags[i].packetType)) {
if (!firstflag) {
firstflag = 1;
ND_PRINT(" ");
} else {
ND_PRINT(",");
}
ND_PRINT("<%s>", rx_flags[i].s);
}
}
}
/*
* Try to handle AFS calls that we know about. Check the destination
* port and make sure it's a data packet. Also, make sure the
* seq number is 1 (because otherwise it's a continuation packet,
* and we can't interpret that). Also, seems that reply packets
* do not have the client-init flag set, so we check for that
* as well.
*/
if (type == RX_PACKET_TYPE_DATA &&
GET_BE_U_4(rxh->seq) == 1 &&
flags & RX_CLIENT_INITIATED) {
/*
* Insert this call into the call cache table, so we
* have a chance to print out replies
*/
rx_cache_insert(ndo, bp, (const struct ip *) bp2, dport);
switch (dport) {
case FS_RX_PORT: /* AFS file service */
fs_print(ndo, bp, length);
break;
case CB_RX_PORT: /* AFS callback service */
cb_print(ndo, bp, length);
break;
case PROT_RX_PORT: /* AFS protection service */
prot_print(ndo, bp, length);
break;
case VLDB_RX_PORT: /* AFS VLDB service */
vldb_print(ndo, bp, length);
break;
case KAUTH_RX_PORT: /* AFS Kerberos auth service */
kauth_print(ndo, bp, length);
break;
case VOL_RX_PORT: /* AFS Volume service */
vol_print(ndo, bp, length);
break;
case BOS_RX_PORT: /* AFS BOS service */
bos_print(ndo, bp, length);
break;
default:
;
}
/*
* If it's a reply (client-init is _not_ set, but seq is one)
* then look it up in the cache. If we find it, call the reply
* printing functions Note that we handle abort packets here,
* because printing out the return code can be useful at times.
*/
} else if (((type == RX_PACKET_TYPE_DATA &&
GET_BE_U_4(rxh->seq) == 1) ||
type == RX_PACKET_TYPE_ABORT) &&
(flags & RX_CLIENT_INITIATED) == 0 &&
rx_cache_find(ndo, rxh, (const struct ip *) bp2,
sport, &opcode)) {
switch (sport) {
case FS_RX_PORT: /* AFS file service */
fs_reply_print(ndo, bp, length, opcode);
break;
case CB_RX_PORT: /* AFS callback service */
cb_reply_print(ndo, bp, length, opcode);
break;
case PROT_RX_PORT: /* AFS PT service */
prot_reply_print(ndo, bp, length, opcode);
break;
case VLDB_RX_PORT: /* AFS VLDB service */
vldb_reply_print(ndo, bp, length, opcode);
break;
case KAUTH_RX_PORT: /* AFS Kerberos auth service */
kauth_reply_print(ndo, bp, length, opcode);
break;
case VOL_RX_PORT: /* AFS Volume service */
vol_reply_print(ndo, bp, length, opcode);
break;
case BOS_RX_PORT: /* AFS BOS service */
bos_reply_print(ndo, bp, length, opcode);
break;
default:
;
}
/*
* If it's an RX ack packet, then use the appropriate ack decoding
* function (there isn't any service-specific information in the
* ack packet, so we can use one for all AFS services)
*/
} else if (type == RX_PACKET_TYPE_ACK)
rx_ack_print(ndo, bp, length);
ND_PRINT(" (%u)", length);
}
/*
* Insert an entry into the cache. Taken from print-nfs.c
*/
static void
rx_cache_insert(netdissect_options *ndo,
const u_char *bp, const struct ip *ip, uint16_t dport)
{
struct rx_cache_entry *rxent;
const struct rx_header *rxh = (const struct rx_header *) bp;
if (!ND_TTEST_4(bp + sizeof(struct rx_header)))
return;
rxent = &rx_cache[rx_cache_next];
if (++rx_cache_next >= RX_CACHE_SIZE)
rx_cache_next = 0;
rxent->callnum = GET_BE_U_4(rxh->callNumber);
rxent->client = GET_IPV4_TO_NETWORK_ORDER(ip->ip_src);
rxent->server = GET_IPV4_TO_NETWORK_ORDER(ip->ip_dst);
rxent->dport = dport;
rxent->serviceId = GET_BE_U_2(rxh->serviceId);
rxent->opcode = GET_BE_U_4(bp + sizeof(struct rx_header));
}
/*
* Lookup an entry in the cache. Also taken from print-nfs.c
*
* Note that because this is a reply, we're looking at the _source_
* port.
*/
static int
rx_cache_find(netdissect_options *ndo, const struct rx_header *rxh,
const struct ip *ip, uint16_t sport, uint32_t *opcode)
{
uint32_t i;
struct rx_cache_entry *rxent;
uint32_t clip;
uint32_t sip;
clip = GET_IPV4_TO_NETWORK_ORDER(ip->ip_dst);
sip = GET_IPV4_TO_NETWORK_ORDER(ip->ip_src);
/* Start the search where we last left off */
i = rx_cache_hint;
do {
rxent = &rx_cache[i];
if (rxent->callnum == GET_BE_U_4(rxh->callNumber) &&
rxent->client == clip &&
rxent->server == sip &&
rxent->serviceId == GET_BE_U_2(rxh->serviceId) &&
rxent->dport == sport) {
/* We got a match! */
rx_cache_hint = i;
*opcode = rxent->opcode;
return(1);
}
if (++i >= RX_CACHE_SIZE)
i = 0;
} while (i != rx_cache_hint);
/* Our search failed */
return(0);
}
/*
* These extremely grody macros handle the printing of various AFS stuff.
*/
#define FIDOUT() { uint32_t n1, n2, n3; \
ND_TCHECK_LEN(bp, sizeof(uint32_t) * 3); \
n1 = GET_BE_U_4(bp); \
bp += sizeof(uint32_t); \
n2 = GET_BE_U_4(bp); \
bp += sizeof(uint32_t); \
n3 = GET_BE_U_4(bp); \
bp += sizeof(uint32_t); \
ND_PRINT(" fid %u/%u/%u", n1, n2, n3); \
}
#define STROUT(MAX) { uint32_t _i; \
_i = GET_BE_U_4(bp); \
if (_i > (MAX)) \
goto trunc; \
bp += sizeof(uint32_t); \
ND_PRINT(" \""); \
if (nd_printn(ndo, bp, _i, ndo->ndo_snapend)) \
goto trunc; \
ND_PRINT("\""); \
bp += ((_i + sizeof(uint32_t) - 1) / sizeof(uint32_t)) * sizeof(uint32_t); \
}
#define INTOUT() { int32_t _i; \
_i = GET_BE_S_4(bp); \
bp += sizeof(int32_t); \
ND_PRINT(" %d", _i); \
}
#define UINTOUT() { uint32_t _i; \
_i = GET_BE_U_4(bp); \
bp += sizeof(uint32_t); \
ND_PRINT(" %u", _i); \
}
#define UINT64OUT() { uint64_t _i; \
_i = GET_BE_U_8(bp); \
bp += sizeof(uint64_t); \
ND_PRINT(" %" PRIu64, _i); \
}
#define DATEOUT() { time_t _t; char str[256]; \
_t = (time_t) GET_BE_S_4(bp); \
bp += sizeof(int32_t); \
ND_PRINT(" %s", \
nd_format_time(str, sizeof(str), \
- "%Y/%m/%d %H:%M:%S", localtime(&_t))); \
+ "%Y-%m-%d %H:%M:%S", localtime(&_t))); \
}
#define STOREATTROUT() { uint32_t mask, _i; \
ND_TCHECK_LEN(bp, (sizeof(uint32_t) * 6)); \
mask = GET_BE_U_4(bp); bp += sizeof(uint32_t); \
if (mask) ND_PRINT(" StoreStatus"); \
if (mask & 1) { ND_PRINT(" date"); DATEOUT(); } \
else bp += sizeof(uint32_t); \
_i = GET_BE_U_4(bp); bp += sizeof(uint32_t); \
if (mask & 2) ND_PRINT(" owner %u", _i); \
_i = GET_BE_U_4(bp); bp += sizeof(uint32_t); \
if (mask & 4) ND_PRINT(" group %u", _i); \
_i = GET_BE_U_4(bp); bp += sizeof(uint32_t); \
if (mask & 8) ND_PRINT(" mode %o", _i & 07777); \
_i = GET_BE_U_4(bp); bp += sizeof(uint32_t); \
if (mask & 16) ND_PRINT(" segsize %u", _i); \
/* undocumented in 3.3 docu */ \
if (mask & 1024) ND_PRINT(" fsync"); \
}
#define UBIK_VERSIONOUT() {uint32_t epoch; uint32_t counter; \
ND_TCHECK_LEN(bp, sizeof(uint32_t) * 2); \
epoch = GET_BE_U_4(bp); \
bp += sizeof(uint32_t); \
counter = GET_BE_U_4(bp); \
bp += sizeof(uint32_t); \
ND_PRINT(" %u.%u", epoch, counter); \
}
#define AFSUUIDOUT() {uint32_t temp; int _i; \
ND_TCHECK_LEN(bp, 11 * sizeof(uint32_t)); \
temp = GET_BE_U_4(bp); \
bp += sizeof(uint32_t); \
ND_PRINT(" %08x", temp); \
temp = GET_BE_U_4(bp); \
bp += sizeof(uint32_t); \
ND_PRINT("%04x", temp); \
temp = GET_BE_U_4(bp); \
bp += sizeof(uint32_t); \
ND_PRINT("%04x", temp); \
for (_i = 0; _i < 8; _i++) { \
temp = GET_BE_U_4(bp); \
bp += sizeof(uint32_t); \
ND_PRINT("%02x", (unsigned char) temp); \
} \
}
/*
* This is the sickest one of all
* MAX is expected to be a constant here
*/
#define VECOUT(MAX) { u_char *sp; \
u_char s[(MAX) + 1]; \
uint32_t k; \
ND_TCHECK_LEN(bp, (MAX) * sizeof(uint32_t)); \
sp = s; \
for (k = 0; k < (MAX); k++) { \
*sp++ = (u_char) GET_BE_U_4(bp); \
bp += sizeof(uint32_t); \
} \
s[(MAX)] = '\0'; \
ND_PRINT(" \""); \
fn_print_str(ndo, s); \
ND_PRINT("\""); \
}
#define DESTSERVEROUT() { uint32_t n1, n2, n3; \
ND_TCHECK_LEN(bp, sizeof(uint32_t) * 3); \
n1 = GET_BE_U_4(bp); \
bp += sizeof(uint32_t); \
n2 = GET_BE_U_4(bp); \
bp += sizeof(uint32_t); \
n3 = GET_BE_U_4(bp); \
bp += sizeof(uint32_t); \
ND_PRINT(" server %u:%u:%u", n1, n2, n3); \
}
/*
* Handle calls to the AFS file service (fs)
*/
static void
fs_print(netdissect_options *ndo,
const u_char *bp, u_int length)
{
uint32_t fs_op;
uint32_t i;
if (length <= sizeof(struct rx_header))
return;
/*
* Print out the afs call we're invoking. The table used here was
* gleaned from fsint/afsint.xg
*/
fs_op = GET_BE_U_4(bp + sizeof(struct rx_header));
ND_PRINT(" fs call %s", tok2str(fs_req, "op#%u", fs_op));
/*
* Print out arguments to some of the AFS calls. This stuff is
* all from afsint.xg
*/
bp += sizeof(struct rx_header) + 4;
/*
* Sigh. This is gross. Ritchie forgive me.
*/
switch (fs_op) {
case 130: /* Fetch data */
FIDOUT();
ND_PRINT(" offset");
UINTOUT();
ND_PRINT(" length");
UINTOUT();
break;
case 131: /* Fetch ACL */
case 132: /* Fetch Status */
case 143: /* Old set lock */
case 144: /* Old extend lock */
case 145: /* Old release lock */
case 156: /* Set lock */
case 157: /* Extend lock */
case 158: /* Release lock */
FIDOUT();
break;
case 135: /* Store status */
FIDOUT();
STOREATTROUT();
break;
case 133: /* Store data */
FIDOUT();
STOREATTROUT();
ND_PRINT(" offset");
UINTOUT();
ND_PRINT(" length");
UINTOUT();
ND_PRINT(" flen");
UINTOUT();
break;
case 134: /* Store ACL */
{
char a[AFSOPAQUEMAX+1];
FIDOUT();
i = GET_BE_U_4(bp);
bp += sizeof(uint32_t);
ND_TCHECK_LEN(bp, i);
i = ND_MIN(AFSOPAQUEMAX, i);
strncpy(a, (const char *) bp, i);
a[i] = '\0';
acl_print(ndo, (u_char *) a, (u_char *) a + i);
break;
}
case 137: /* Create file */
case 141: /* MakeDir */
FIDOUT();
STROUT(AFSNAMEMAX);
STOREATTROUT();
break;
case 136: /* Remove file */
case 142: /* Remove directory */
FIDOUT();
STROUT(AFSNAMEMAX);
break;
case 138: /* Rename file */
ND_PRINT(" old");
FIDOUT();
STROUT(AFSNAMEMAX);
ND_PRINT(" new");
FIDOUT();
STROUT(AFSNAMEMAX);
break;
case 139: /* Symlink */
FIDOUT();
STROUT(AFSNAMEMAX);
ND_PRINT(" link to");
STROUT(AFSNAMEMAX);
break;
case 140: /* Link */
FIDOUT();
STROUT(AFSNAMEMAX);
ND_PRINT(" link to");
FIDOUT();
break;
case 148: /* Get volume info */
STROUT(AFSNAMEMAX);
break;
case 149: /* Get volume stats */
case 150: /* Set volume stats */
ND_PRINT(" volid");
UINTOUT();
break;
case 154: /* New get volume info */
ND_PRINT(" volname");
STROUT(AFSNAMEMAX);
break;
case 155: /* Bulk stat */
case 65536: /* Inline bulk stat */
{
uint32_t j;
j = GET_BE_U_4(bp);
bp += sizeof(uint32_t);
for (i = 0; i < j; i++) {
FIDOUT();
if (i != j - 1)
ND_PRINT(",");
}
if (j == 0)
ND_PRINT(" <none!>");
break;
}
case 65537: /* Fetch data 64 */
FIDOUT();
ND_PRINT(" offset");
UINT64OUT();
ND_PRINT(" length");
UINT64OUT();
break;
case 65538: /* Store data 64 */
FIDOUT();
STOREATTROUT();
ND_PRINT(" offset");
UINT64OUT();
ND_PRINT(" length");
UINT64OUT();
ND_PRINT(" flen");
UINT64OUT();
break;
case 65541: /* CallBack rx conn address */
ND_PRINT(" addr");
UINTOUT();
default:
;
}
return;
trunc:
ND_PRINT(" [|fs]");
}
/*
* Handle replies to the AFS file service
*/
static void
fs_reply_print(netdissect_options *ndo,
const u_char *bp, u_int length, uint32_t opcode)
{
uint32_t i;
const struct rx_header *rxh;
uint8_t type;
if (length <= sizeof(struct rx_header))
return;
rxh = (const struct rx_header *) bp;
/*
* Print out the afs call we're invoking. The table used here was
* gleaned from fsint/afsint.xg
*/
ND_PRINT(" fs reply %s", tok2str(fs_req, "op#%u", opcode));
type = GET_U_1(rxh->type);
bp += sizeof(struct rx_header);
/*
* If it was a data packet, interpret the response
*/
if (type == RX_PACKET_TYPE_DATA) {
switch (opcode) {
case 131: /* Fetch ACL */
{
char a[AFSOPAQUEMAX+1];
i = GET_BE_U_4(bp);
bp += sizeof(uint32_t);
ND_TCHECK_LEN(bp, i);
i = ND_MIN(AFSOPAQUEMAX, i);
strncpy(a, (const char *) bp, i);
a[i] = '\0';
acl_print(ndo, (u_char *) a, (u_char *) a + i);
break;
}
case 137: /* Create file */
case 141: /* MakeDir */
ND_PRINT(" new");
FIDOUT();
break;
case 151: /* Get root volume */
ND_PRINT(" root volume");
STROUT(AFSNAMEMAX);
break;
case 153: /* Get time */
DATEOUT();
break;
default:
;
}
} else if (type == RX_PACKET_TYPE_ABORT) {
/*
* Otherwise, just print out the return code
*/
int32_t errcode;
errcode = GET_BE_S_4(bp);
bp += sizeof(int32_t);
ND_PRINT(" error %s", tok2str(afs_fs_errors, "#%d", errcode));
} else {
ND_PRINT(" strange fs reply of type %u", type);
}
return;
trunc:
ND_PRINT(" [|fs]");
}
/*
* Print out an AFS ACL string. An AFS ACL is a string that has the
* following format:
*
* <positive> <negative>
* <uid1> <aclbits1>
* ....
*
* "positive" and "negative" are integers which contain the number of
* positive and negative ACL's in the string. The uid/aclbits pair are
* ASCII strings containing the UID/PTS record and an ASCII number
* representing a logical OR of all the ACL permission bits
*/
#define XSTRINGIFY(x) #x
#define NUMSTRINGIFY(x) XSTRINGIFY(x)
static void
acl_print(netdissect_options *ndo,
u_char *s, const u_char *end)
{
int pos, neg, acl;
int n, i;
char user[USERNAMEMAX+1];
if (sscanf((char *) s, "%d %d\n%n", &pos, &neg, &n) != 2)
return;
s += n;
if (s > end)
return;
/*
* This wacky order preserves the order used by the "fs" command
*/
#define ACLOUT(acl) \
ND_PRINT("%s%s%s%s%s%s%s", \
acl & PRSFS_READ ? "r" : "", \
acl & PRSFS_LOOKUP ? "l" : "", \
acl & PRSFS_INSERT ? "i" : "", \
acl & PRSFS_DELETE ? "d" : "", \
acl & PRSFS_WRITE ? "w" : "", \
acl & PRSFS_LOCK ? "k" : "", \
acl & PRSFS_ADMINISTER ? "a" : "");
for (i = 0; i < pos; i++) {
if (sscanf((char *) s, "%" NUMSTRINGIFY(USERNAMEMAX) "s %d\n%n", user, &acl, &n) != 2)
return;
s += n;
ND_PRINT(" +{");
fn_print_str(ndo, (u_char *)user);
ND_PRINT(" ");
ACLOUT(acl);
ND_PRINT("}");
if (s > end)
return;
}
for (i = 0; i < neg; i++) {
if (sscanf((char *) s, "%" NUMSTRINGIFY(USERNAMEMAX) "s %d\n%n", user, &acl, &n) != 2)
return;
s += n;
ND_PRINT(" -{");
fn_print_str(ndo, (u_char *)user);
ND_PRINT(" ");
ACLOUT(acl);
ND_PRINT("}");
if (s > end)
return;
}
}
#undef ACLOUT
/*
* Handle calls to the AFS callback service
*/
static void
cb_print(netdissect_options *ndo,
const u_char *bp, u_int length)
{
uint32_t cb_op;
uint32_t i;
if (length <= sizeof(struct rx_header))
return;
/*
* Print out the afs call we're invoking. The table used here was
* gleaned from fsint/afscbint.xg
*/
cb_op = GET_BE_U_4(bp + sizeof(struct rx_header));
ND_PRINT(" cb call %s", tok2str(cb_req, "op#%u", cb_op));
bp += sizeof(struct rx_header) + 4;
/*
* Print out the afs call we're invoking. The table used here was
* gleaned from fsint/afscbint.xg
*/
switch (cb_op) {
case 204: /* Callback */
{
uint32_t j, t;
j = GET_BE_U_4(bp);
bp += sizeof(uint32_t);
for (i = 0; i < j; i++) {
FIDOUT();
if (i != j - 1)
ND_PRINT(",");
}
if (j == 0)
ND_PRINT(" <none!>");
j = GET_BE_U_4(bp);
bp += sizeof(uint32_t);
if (j != 0)
ND_PRINT(";");
for (i = 0; i < j; i++) {
ND_PRINT(" ver");
INTOUT();
ND_PRINT(" expires");
DATEOUT();
t = GET_BE_U_4(bp);
bp += sizeof(uint32_t);
tok2str(cb_types, "type %u", t);
}
break;
}
case 214: {
ND_PRINT(" afsuuid");
AFSUUIDOUT();
break;
}
default:
;
}
return;
trunc:
ND_PRINT(" [|cb]");
}
/*
* Handle replies to the AFS Callback Service
*/
static void
cb_reply_print(netdissect_options *ndo,
const u_char *bp, u_int length, uint32_t opcode)
{
const struct rx_header *rxh;
uint8_t type;
if (length <= sizeof(struct rx_header))
return;
rxh = (const struct rx_header *) bp;
/*
* Print out the afs call we're invoking. The table used here was
* gleaned from fsint/afscbint.xg
*/
ND_PRINT(" cb reply %s", tok2str(cb_req, "op#%u", opcode));
type = GET_U_1(rxh->type);
bp += sizeof(struct rx_header);
/*
* If it was a data packet, interpret the response.
*/
if (type == RX_PACKET_TYPE_DATA)
switch (opcode) {
case 213: /* InitCallBackState3 */
AFSUUIDOUT();
break;
default:
;
}
else {
/*
* Otherwise, just print out the return code
*/
ND_PRINT(" errcode");
INTOUT();
}
return;
trunc:
ND_PRINT(" [|cb]");
}
/*
* Handle calls to the AFS protection database server
*/
static void
prot_print(netdissect_options *ndo,
const u_char *bp, u_int length)
{
uint32_t i;
uint32_t pt_op;
if (length <= sizeof(struct rx_header))
return;
/*
* Print out the afs call we're invoking. The table used here was
* gleaned from ptserver/ptint.xg
*/
pt_op = GET_BE_U_4(bp + sizeof(struct rx_header));
ND_PRINT(" pt");
if (is_ubik(pt_op)) {
ubik_print(ndo, bp);
return;
}
ND_PRINT(" call %s", tok2str(pt_req, "op#%u", pt_op));
/*
* Decode some of the arguments to the PT calls
*/
bp += sizeof(struct rx_header) + 4;
switch (pt_op) {
case 500: /* I New User */
STROUT(PRNAMEMAX);
ND_PRINT(" id");
INTOUT();
ND_PRINT(" oldid");
INTOUT();
break;
case 501: /* Where is it */
case 506: /* Delete */
case 508: /* Get CPS */
case 512: /* List entry */
case 514: /* List elements */
case 517: /* List owned */
case 518: /* Get CPS2 */
case 519: /* Get host CPS */
case 530: /* List super groups */
ND_PRINT(" id");
INTOUT();
break;
case 502: /* Dump entry */
ND_PRINT(" pos");
INTOUT();
break;
case 503: /* Add to group */
case 507: /* Remove from group */
case 515: /* Is a member of? */
ND_PRINT(" uid");
INTOUT();
ND_PRINT(" gid");
INTOUT();
break;
case 504: /* Name to ID */
{
uint32_t j;
j = GET_BE_U_4(bp);
bp += sizeof(uint32_t);
/*
* Who designed this chicken-shit protocol?
*
* Each character is stored as a 32-bit
* integer!
*/
for (i = 0; i < j; i++) {
VECOUT(PRNAMEMAX);
}
if (j == 0)
ND_PRINT(" <none!>");
}
break;
case 505: /* Id to name */
{
uint32_t j;
ND_PRINT(" ids:");
i = GET_BE_U_4(bp);
bp += sizeof(uint32_t);
for (j = 0; j < i; j++)
INTOUT();
if (j == 0)
ND_PRINT(" <none!>");
}
break;
case 509: /* New entry */
STROUT(PRNAMEMAX);
ND_PRINT(" flag");
INTOUT();
ND_PRINT(" oid");
INTOUT();
break;
case 511: /* Set max */
ND_PRINT(" id");
INTOUT();
ND_PRINT(" gflag");
INTOUT();
break;
case 513: /* Change entry */
ND_PRINT(" id");
INTOUT();
STROUT(PRNAMEMAX);
ND_PRINT(" oldid");
INTOUT();
ND_PRINT(" newid");
INTOUT();
break;
case 520: /* Update entry */
ND_PRINT(" id");
INTOUT();
STROUT(PRNAMEMAX);
break;
default:
;
}
return;
trunc:
ND_PRINT(" [|pt]");
}
/*
* Handle replies to the AFS protection service
*/
static void
prot_reply_print(netdissect_options *ndo,
const u_char *bp, u_int length, uint32_t opcode)
{
const struct rx_header *rxh;
uint8_t type;
uint32_t i;
if (length < sizeof(struct rx_header))
return;
rxh = (const struct rx_header *) bp;
/*
* Print out the afs call we're invoking. The table used here was
* gleaned from ptserver/ptint.xg. Check to see if it's a
* Ubik call, however.
*/
ND_PRINT(" pt");
if (is_ubik(opcode)) {
ubik_reply_print(ndo, bp, length, opcode);
return;
}
ND_PRINT(" reply %s", tok2str(pt_req, "op#%u", opcode));
type = GET_U_1(rxh->type);
bp += sizeof(struct rx_header);
/*
* If it was a data packet, interpret the response
*/
if (type == RX_PACKET_TYPE_DATA)
switch (opcode) {
case 504: /* Name to ID */
{
uint32_t j;
ND_PRINT(" ids:");
i = GET_BE_U_4(bp);
bp += sizeof(uint32_t);
for (j = 0; j < i; j++)
INTOUT();
if (j == 0)
ND_PRINT(" <none!>");
}
break;
case 505: /* ID to name */
{
uint32_t j;
j = GET_BE_U_4(bp);
bp += sizeof(uint32_t);
/*
* Who designed this chicken-shit protocol?
*
* Each character is stored as a 32-bit
* integer!
*/
for (i = 0; i < j; i++) {
VECOUT(PRNAMEMAX);
}
if (j == 0)
ND_PRINT(" <none!>");
}
break;
case 508: /* Get CPS */
case 514: /* List elements */
case 517: /* List owned */
case 518: /* Get CPS2 */
case 519: /* Get host CPS */
{
uint32_t j;
j = GET_BE_U_4(bp);
bp += sizeof(uint32_t);
for (i = 0; i < j; i++) {
INTOUT();
}
if (j == 0)
ND_PRINT(" <none!>");
}
break;
case 510: /* List max */
ND_PRINT(" maxuid");
INTOUT();
ND_PRINT(" maxgid");
INTOUT();
break;
default:
;
}
else {
/*
* Otherwise, just print out the return code
*/
ND_PRINT(" errcode");
INTOUT();
}
return;
trunc:
ND_PRINT(" [|pt]");
}
/*
* Handle calls to the AFS volume location database service
*/
static void
vldb_print(netdissect_options *ndo,
const u_char *bp, u_int length)
{
uint32_t vldb_op;
uint32_t i;
if (length <= sizeof(struct rx_header))
return;
/*
* Print out the afs call we're invoking. The table used here was
* gleaned from vlserver/vldbint.xg
*/
vldb_op = GET_BE_U_4(bp + sizeof(struct rx_header));
ND_PRINT(" vldb");
if (is_ubik(vldb_op)) {
ubik_print(ndo, bp);
return;
}
ND_PRINT(" call %s", tok2str(vldb_req, "op#%u", vldb_op));
/*
* Decode some of the arguments to the VLDB calls
*/
bp += sizeof(struct rx_header) + 4;
switch (vldb_op) {
case 501: /* Create new volume */
case 517: /* Create entry N */
VECOUT(VLNAMEMAX);
break;
case 502: /* Delete entry */
case 503: /* Get entry by ID */
case 507: /* Update entry */
case 508: /* Set lock */
case 509: /* Release lock */
case 518: /* Get entry by ID N */
ND_PRINT(" volid");
INTOUT();
i = GET_BE_U_4(bp);
bp += sizeof(uint32_t);
if (i <= 2)
ND_PRINT(" type %s", voltype[i]);
break;
case 504: /* Get entry by name */
case 519: /* Get entry by name N */
case 524: /* Update entry by name */
case 527: /* Get entry by name U */
STROUT(VLNAMEMAX);
break;
case 505: /* Get new vol id */
ND_PRINT(" bump");
INTOUT();
break;
case 506: /* Replace entry */
case 520: /* Replace entry N */
ND_PRINT(" volid");
INTOUT();
i = GET_BE_U_4(bp);
bp += sizeof(uint32_t);
if (i <= 2)
ND_PRINT(" type %s", voltype[i]);
VECOUT(VLNAMEMAX);
break;
case 510: /* List entry */
case 521: /* List entry N */
ND_PRINT(" index");
INTOUT();
break;
default:
;
}
return;
trunc:
ND_PRINT(" [|vldb]");
}
/*
* Handle replies to the AFS volume location database service
*/
static void
vldb_reply_print(netdissect_options *ndo,
const u_char *bp, u_int length, uint32_t opcode)
{
const struct rx_header *rxh;
uint8_t type;
uint32_t i;
if (length < sizeof(struct rx_header))
return;
rxh = (const struct rx_header *) bp;
/*
* Print out the afs call we're invoking. The table used here was
* gleaned from vlserver/vldbint.xg. Check to see if it's a
* Ubik call, however.
*/
ND_PRINT(" vldb");
if (is_ubik(opcode)) {
ubik_reply_print(ndo, bp, length, opcode);
return;
}
ND_PRINT(" reply %s", tok2str(vldb_req, "op#%u", opcode));
type = GET_U_1(rxh->type);
bp += sizeof(struct rx_header);
/*
* If it was a data packet, interpret the response
*/
if (type == RX_PACKET_TYPE_DATA)
switch (opcode) {
case 510: /* List entry */
ND_PRINT(" count");
INTOUT();
ND_PRINT(" nextindex");
INTOUT();
ND_FALL_THROUGH;
case 503: /* Get entry by id */
case 504: /* Get entry by name */
{ uint32_t nservers, j;
VECOUT(VLNAMEMAX);
ND_TCHECK_4(bp);
bp += sizeof(uint32_t);
ND_PRINT(" numservers");
nservers = GET_BE_U_4(bp);
bp += sizeof(uint32_t);
ND_PRINT(" %u", nservers);
ND_PRINT(" servers");
for (i = 0; i < 8; i++) {
ND_TCHECK_4(bp);
if (i < nservers)
ND_PRINT(" %s",
intoa(GET_IPV4_TO_NETWORK_ORDER(bp)));
bp += sizeof(nd_ipv4);
}
ND_PRINT(" partitions");
for (i = 0; i < 8; i++) {
j = GET_BE_U_4(bp);
if (i < nservers && j <= 26)
ND_PRINT(" %c", 'a' + j);
else if (i < nservers)
ND_PRINT(" %u", j);
bp += sizeof(uint32_t);
}
ND_TCHECK_LEN(bp, 8 * sizeof(uint32_t));
bp += 8 * sizeof(uint32_t);
ND_PRINT(" rwvol");
UINTOUT();
ND_PRINT(" rovol");
UINTOUT();
ND_PRINT(" backup");
UINTOUT();
}
break;
case 505: /* Get new volume ID */
ND_PRINT(" newvol");
UINTOUT();
break;
case 521: /* List entry */
case 529: /* List entry U */
ND_PRINT(" count");
INTOUT();
ND_PRINT(" nextindex");
INTOUT();
ND_FALL_THROUGH;
case 518: /* Get entry by ID N */
case 519: /* Get entry by name N */
{ uint32_t nservers, j;
VECOUT(VLNAMEMAX);
ND_PRINT(" numservers");
nservers = GET_BE_U_4(bp);
bp += sizeof(uint32_t);
ND_PRINT(" %u", nservers);
ND_PRINT(" servers");
for (i = 0; i < 13; i++) {
ND_TCHECK_4(bp);
if (i < nservers)
ND_PRINT(" %s",
intoa(GET_IPV4_TO_NETWORK_ORDER(bp)));
bp += sizeof(nd_ipv4);
}
ND_PRINT(" partitions");
for (i = 0; i < 13; i++) {
j = GET_BE_U_4(bp);
if (i < nservers && j <= 26)
ND_PRINT(" %c", 'a' + j);
else if (i < nservers)
ND_PRINT(" %u", j);
bp += sizeof(uint32_t);
}
ND_TCHECK_LEN(bp, 13 * sizeof(uint32_t));
bp += 13 * sizeof(uint32_t);
ND_PRINT(" rwvol");
UINTOUT();
ND_PRINT(" rovol");
UINTOUT();
ND_PRINT(" backup");
UINTOUT();
}
break;
case 526: /* Get entry by ID U */
case 527: /* Get entry by name U */
{ uint32_t nservers, j;
VECOUT(VLNAMEMAX);
ND_PRINT(" numservers");
nservers = GET_BE_U_4(bp);
bp += sizeof(uint32_t);
ND_PRINT(" %u", nservers);
ND_PRINT(" servers");
for (i = 0; i < 13; i++) {
if (i < nservers) {
ND_PRINT(" afsuuid");
AFSUUIDOUT();
} else {
ND_TCHECK_LEN(bp, 44);
bp += 44;
}
}
ND_TCHECK_LEN(bp, 4 * 13);
bp += 4 * 13;
ND_PRINT(" partitions");
for (i = 0; i < 13; i++) {
j = GET_BE_U_4(bp);
if (i < nservers && j <= 26)
ND_PRINT(" %c", 'a' + j);
else if (i < nservers)
ND_PRINT(" %u", j);
bp += sizeof(uint32_t);
}
ND_TCHECK_LEN(bp, 13 * sizeof(uint32_t));
bp += 13 * sizeof(uint32_t);
ND_PRINT(" rwvol");
UINTOUT();
ND_PRINT(" rovol");
UINTOUT();
ND_PRINT(" backup");
UINTOUT();
}
default:
;
}
else {
/*
* Otherwise, just print out the return code
*/
ND_PRINT(" errcode");
INTOUT();
}
return;
trunc:
ND_PRINT(" [|vldb]");
}
/*
* Handle calls to the AFS Kerberos Authentication service
*/
static void
kauth_print(netdissect_options *ndo,
const u_char *bp, u_int length)
{
uint32_t kauth_op;
if (length <= sizeof(struct rx_header))
return;
/*
* Print out the afs call we're invoking. The table used here was
* gleaned from kauth/kauth.rg
*/
kauth_op = GET_BE_U_4(bp + sizeof(struct rx_header));
ND_PRINT(" kauth");
if (is_ubik(kauth_op)) {
ubik_print(ndo, bp);
return;
}
ND_PRINT(" call %s", tok2str(kauth_req, "op#%u", kauth_op));
/*
* Decode some of the arguments to the KA calls
*/
bp += sizeof(struct rx_header) + 4;
switch (kauth_op) {
case 1: /* Authenticate old */
case 21: /* Authenticate */
case 22: /* Authenticate-V2 */
case 2: /* Change PW */
case 5: /* Set fields */
case 6: /* Create user */
case 7: /* Delete user */
case 8: /* Get entry */
case 14: /* Unlock */
case 15: /* Lock status */
ND_PRINT(" principal");
STROUT(KANAMEMAX);
STROUT(KANAMEMAX);
break;
case 3: /* GetTicket-old */
case 23: /* GetTicket */
{
uint32_t i;
ND_PRINT(" kvno");
INTOUT();
ND_PRINT(" domain");
STROUT(KANAMEMAX);
i = GET_BE_U_4(bp);
bp += sizeof(uint32_t);
ND_TCHECK_LEN(bp, i);
bp += i;
ND_PRINT(" principal");
STROUT(KANAMEMAX);
STROUT(KANAMEMAX);
break;
}
case 4: /* Set Password */
ND_PRINT(" principal");
STROUT(KANAMEMAX);
STROUT(KANAMEMAX);
ND_PRINT(" kvno");
INTOUT();
break;
case 12: /* Get password */
ND_PRINT(" name");
STROUT(KANAMEMAX);
break;
default:
;
}
return;
trunc:
ND_PRINT(" [|kauth]");
}
/*
* Handle replies to the AFS Kerberos Authentication Service
*/
static void
kauth_reply_print(netdissect_options *ndo,
const u_char *bp, u_int length, uint32_t opcode)
{
const struct rx_header *rxh;
uint8_t type;
if (length <= sizeof(struct rx_header))
return;
rxh = (const struct rx_header *) bp;
/*
* Print out the afs call we're invoking. The table used here was
* gleaned from kauth/kauth.rg
*/
ND_PRINT(" kauth");
if (is_ubik(opcode)) {
ubik_reply_print(ndo, bp, length, opcode);
return;
}
ND_PRINT(" reply %s", tok2str(kauth_req, "op#%u", opcode));
type = GET_U_1(rxh->type);
bp += sizeof(struct rx_header);
/*
* If it was a data packet, interpret the response.
*/
if (type == RX_PACKET_TYPE_DATA)
/* Well, no, not really. Leave this for later */
;
else {
/*
* Otherwise, just print out the return code
*/
ND_PRINT(" errcode");
INTOUT();
}
}
/*
* Handle calls to the AFS Volume location service
*/
static void
vol_print(netdissect_options *ndo,
const u_char *bp, u_int length)
{
uint32_t vol_op;
if (length <= sizeof(struct rx_header))
return;
/*
* Print out the afs call we're invoking. The table used here was
* gleaned from volser/volint.xg
*/
vol_op = GET_BE_U_4(bp + sizeof(struct rx_header));
ND_PRINT(" vol call %s", tok2str(vol_req, "op#%u", vol_op));
bp += sizeof(struct rx_header) + 4;
switch (vol_op) {
case 100: /* Create volume */
ND_PRINT(" partition");
UINTOUT();
ND_PRINT(" name");
STROUT(AFSNAMEMAX);
ND_PRINT(" type");
UINTOUT();
ND_PRINT(" parent");
UINTOUT();
break;
case 101: /* Delete volume */
case 107: /* Get flags */
ND_PRINT(" trans");
UINTOUT();
break;
case 102: /* Restore */
ND_PRINT(" totrans");
UINTOUT();
ND_PRINT(" flags");
UINTOUT();
break;
case 103: /* Forward */
ND_PRINT(" fromtrans");
UINTOUT();
ND_PRINT(" fromdate");
DATEOUT();
DESTSERVEROUT();
ND_PRINT(" desttrans");
INTOUT();
break;
case 104: /* End trans */
ND_PRINT(" trans");
UINTOUT();
break;
case 105: /* Clone */
ND_PRINT(" trans");
UINTOUT();
ND_PRINT(" purgevol");
UINTOUT();
ND_PRINT(" newtype");
UINTOUT();
ND_PRINT(" newname");
STROUT(AFSNAMEMAX);
break;
case 106: /* Set flags */
ND_PRINT(" trans");
UINTOUT();
ND_PRINT(" flags");
UINTOUT();
break;
case 108: /* Trans create */
ND_PRINT(" vol");
UINTOUT();
ND_PRINT(" partition");
UINTOUT();
ND_PRINT(" flags");
UINTOUT();
break;
case 109: /* Dump */
case 655537: /* Get size */
ND_PRINT(" fromtrans");
UINTOUT();
ND_PRINT(" fromdate");
DATEOUT();
break;
case 110: /* Get n-th volume */
ND_PRINT(" index");
UINTOUT();
break;
case 111: /* Set forwarding */
ND_PRINT(" tid");
UINTOUT();
ND_PRINT(" newsite");
UINTOUT();
break;
case 112: /* Get name */
case 113: /* Get status */
ND_PRINT(" tid");
break;
case 114: /* Signal restore */
ND_PRINT(" name");
STROUT(AFSNAMEMAX);
ND_PRINT(" type");
UINTOUT();
ND_PRINT(" pid");
UINTOUT();
ND_PRINT(" cloneid");
UINTOUT();
break;
case 116: /* List volumes */
ND_PRINT(" partition");
UINTOUT();
ND_PRINT(" flags");
UINTOUT();
break;
case 117: /* Set id types */
ND_PRINT(" tid");
UINTOUT();
ND_PRINT(" name");
STROUT(AFSNAMEMAX);
ND_PRINT(" type");
UINTOUT();
ND_PRINT(" pid");
UINTOUT();
ND_PRINT(" clone");
UINTOUT();
ND_PRINT(" backup");
UINTOUT();
break;
case 119: /* Partition info */
ND_PRINT(" name");
STROUT(AFSNAMEMAX);
break;
case 120: /* Reclone */
ND_PRINT(" tid");
UINTOUT();
break;
case 121: /* List one volume */
case 122: /* Nuke volume */
case 124: /* Extended List volumes */
case 125: /* Extended List one volume */
case 65536: /* Convert RO to RW volume */
ND_PRINT(" partid");
UINTOUT();
ND_PRINT(" volid");
UINTOUT();
break;
case 123: /* Set date */
ND_PRINT(" tid");
UINTOUT();
ND_PRINT(" date");
DATEOUT();
break;
case 126: /* Set info */
ND_PRINT(" tid");
UINTOUT();
break;
case 128: /* Forward multiple */
ND_PRINT(" fromtrans");
UINTOUT();
ND_PRINT(" fromdate");
DATEOUT();
{
uint32_t i, j;
j = GET_BE_U_4(bp);
bp += sizeof(uint32_t);
for (i = 0; i < j; i++) {
DESTSERVEROUT();
if (i != j - 1)
ND_PRINT(",");
}
if (j == 0)
ND_PRINT(" <none!>");
}
break;
case 65538: /* Dump version 2 */
ND_PRINT(" fromtrans");
UINTOUT();
ND_PRINT(" fromdate");
DATEOUT();
ND_PRINT(" flags");
UINTOUT();
break;
default:
;
}
return;
trunc:
ND_PRINT(" [|vol]");
}
/*
* Handle replies to the AFS Volume Service
*/
static void
vol_reply_print(netdissect_options *ndo,
const u_char *bp, u_int length, uint32_t opcode)
{
const struct rx_header *rxh;
uint8_t type;
if (length <= sizeof(struct rx_header))
return;
rxh = (const struct rx_header *) bp;
/*
* Print out the afs call we're invoking. The table used here was
* gleaned from volser/volint.xg
*/
ND_PRINT(" vol reply %s", tok2str(vol_req, "op#%u", opcode));
type = GET_U_1(rxh->type);
bp += sizeof(struct rx_header);
/*
* If it was a data packet, interpret the response.
*/
if (type == RX_PACKET_TYPE_DATA) {
switch (opcode) {
case 100: /* Create volume */
ND_PRINT(" volid");
UINTOUT();
ND_PRINT(" trans");
UINTOUT();
break;
case 104: /* End transaction */
UINTOUT();
break;
case 105: /* Clone */
ND_PRINT(" newvol");
UINTOUT();
break;
case 107: /* Get flags */
UINTOUT();
break;
case 108: /* Transaction create */
ND_PRINT(" trans");
UINTOUT();
break;
case 110: /* Get n-th volume */
ND_PRINT(" volume");
UINTOUT();
ND_PRINT(" partition");
UINTOUT();
break;
case 112: /* Get name */
STROUT(AFSNAMEMAX);
break;
case 113: /* Get status */
ND_PRINT(" volid");
UINTOUT();
ND_PRINT(" nextuniq");
UINTOUT();
ND_PRINT(" type");
UINTOUT();
ND_PRINT(" parentid");
UINTOUT();
ND_PRINT(" clone");
UINTOUT();
ND_PRINT(" backup");
UINTOUT();
ND_PRINT(" restore");
UINTOUT();
ND_PRINT(" maxquota");
UINTOUT();
ND_PRINT(" minquota");
UINTOUT();
ND_PRINT(" owner");
UINTOUT();
ND_PRINT(" create");
DATEOUT();
ND_PRINT(" access");
DATEOUT();
ND_PRINT(" update");
DATEOUT();
ND_PRINT(" expire");
DATEOUT();
ND_PRINT(" backup");
DATEOUT();
ND_PRINT(" copy");
DATEOUT();
break;
case 115: /* Old list partitions */
break;
case 116: /* List volumes */
case 121: /* List one volume */
{
uint32_t i, j;
j = GET_BE_U_4(bp);
bp += sizeof(uint32_t);
for (i = 0; i < j; i++) {
ND_PRINT(" name");
VECOUT(32);
ND_PRINT(" volid");
UINTOUT();
ND_PRINT(" type");
bp += sizeof(uint32_t) * 21;
if (i != j - 1)
ND_PRINT(",");
}
if (j == 0)
ND_PRINT(" <none!>");
}
break;
default:
;
}
} else {
/*
* Otherwise, just print out the return code
*/
ND_PRINT(" errcode");
INTOUT();
}
return;
trunc:
ND_PRINT(" [|vol]");
}
/*
* Handle calls to the AFS BOS service
*/
static void
bos_print(netdissect_options *ndo,
const u_char *bp, u_int length)
{
uint32_t bos_op;
if (length <= sizeof(struct rx_header))
return;
/*
* Print out the afs call we're invoking. The table used here was
* gleaned from bozo/bosint.xg
*/
bos_op = GET_BE_U_4(bp + sizeof(struct rx_header));
ND_PRINT(" bos call %s", tok2str(bos_req, "op#%u", bos_op));
/*
* Decode some of the arguments to the BOS calls
*/
bp += sizeof(struct rx_header) + 4;
switch (bos_op) {
case 80: /* Create B node */
ND_PRINT(" type");
STROUT(BOSNAMEMAX);
ND_PRINT(" instance");
STROUT(BOSNAMEMAX);
break;
case 81: /* Delete B node */
case 83: /* Get status */
case 85: /* Get instance info */
case 87: /* Add super user */
case 88: /* Delete super user */
case 93: /* Set cell name */
case 96: /* Add cell host */
case 97: /* Delete cell host */
case 104: /* Restart */
case 106: /* Uninstall */
case 108: /* Exec */
case 112: /* Getlog */
case 114: /* Get instance strings */
STROUT(BOSNAMEMAX);
break;
case 82: /* Set status */
case 98: /* Set T status */
STROUT(BOSNAMEMAX);
ND_PRINT(" status");
INTOUT();
break;
case 86: /* Get instance parm */
STROUT(BOSNAMEMAX);
ND_PRINT(" num");
INTOUT();
break;
case 84: /* Enumerate instance */
case 89: /* List super users */
case 90: /* List keys */
case 91: /* Add key */
case 92: /* Delete key */
case 95: /* Get cell host */
INTOUT();
break;
case 105: /* Install */
STROUT(BOSNAMEMAX);
ND_PRINT(" size");
INTOUT();
ND_PRINT(" flags");
INTOUT();
ND_PRINT(" date");
INTOUT();
break;
default:
;
}
return;
trunc:
ND_PRINT(" [|bos]");
}
/*
* Handle replies to the AFS BOS Service
*/
static void
bos_reply_print(netdissect_options *ndo,
const u_char *bp, u_int length, uint32_t opcode)
{
const struct rx_header *rxh;
uint8_t type;
if (length <= sizeof(struct rx_header))
return;
rxh = (const struct rx_header *) bp;
/*
* Print out the afs call we're invoking. The table used here was
* gleaned from volser/volint.xg
*/
ND_PRINT(" bos reply %s", tok2str(bos_req, "op#%u", opcode));
type = GET_U_1(rxh->type);
bp += sizeof(struct rx_header);
/*
* If it was a data packet, interpret the response.
*/
if (type == RX_PACKET_TYPE_DATA)
/* Well, no, not really. Leave this for later */
;
else {
/*
* Otherwise, just print out the return code
*/
ND_PRINT(" errcode");
INTOUT();
}
}
/*
* Check to see if this is a Ubik opcode.
*/
static int
is_ubik(uint32_t opcode)
{
if ((opcode >= VOTE_LOW && opcode <= VOTE_HIGH) ||
(opcode >= DISK_LOW && opcode <= DISK_HIGH))
return(1);
else
return(0);
}
/*
* Handle Ubik opcodes to any one of the replicated database services
*/
static void
ubik_print(netdissect_options *ndo,
const u_char *bp)
{
uint32_t ubik_op;
uint32_t temp;
/*
* Print out the afs call we're invoking. The table used here was
* gleaned from ubik/ubik_int.xg
*/
/* Every function that calls this function first makes a bounds check
* for (sizeof(rx_header) + 4) bytes, so long as it remains this way
* the line below will not over-read.
*/
ubik_op = GET_BE_U_4(bp + sizeof(struct rx_header));
ND_PRINT(" ubik call %s", tok2str(ubik_req, "op#%u", ubik_op));
/*
* Decode some of the arguments to the Ubik calls
*/
bp += sizeof(struct rx_header) + 4;
switch (ubik_op) {
case 10000: /* Beacon */
temp = GET_BE_U_4(bp);
bp += sizeof(uint32_t);
ND_PRINT(" syncsite %s", temp ? "yes" : "no");
ND_PRINT(" votestart");
DATEOUT();
ND_PRINT(" dbversion");
UBIK_VERSIONOUT();
ND_PRINT(" tid");
UBIK_VERSIONOUT();
break;
case 10003: /* Get sync site */
ND_PRINT(" site");
UINTOUT();
break;
case 20000: /* Begin */
case 20001: /* Commit */
case 20007: /* Abort */
case 20008: /* Release locks */
case 20010: /* Writev */
ND_PRINT(" tid");
UBIK_VERSIONOUT();
break;
case 20002: /* Lock */
ND_PRINT(" tid");
UBIK_VERSIONOUT();
ND_PRINT(" file");
INTOUT();
ND_PRINT(" pos");
INTOUT();
ND_PRINT(" length");
INTOUT();
temp = GET_BE_U_4(bp);
bp += sizeof(uint32_t);
tok2str(ubik_lock_types, "type %u", temp);
break;
case 20003: /* Write */
ND_PRINT(" tid");
UBIK_VERSIONOUT();
ND_PRINT(" file");
INTOUT();
ND_PRINT(" pos");
INTOUT();
break;
case 20005: /* Get file */
ND_PRINT(" file");
INTOUT();
break;
case 20006: /* Send file */
ND_PRINT(" file");
INTOUT();
ND_PRINT(" length");
INTOUT();
ND_PRINT(" dbversion");
UBIK_VERSIONOUT();
break;
case 20009: /* Truncate */
ND_PRINT(" tid");
UBIK_VERSIONOUT();
ND_PRINT(" file");
INTOUT();
ND_PRINT(" length");
INTOUT();
break;
case 20012: /* Set version */
ND_PRINT(" tid");
UBIK_VERSIONOUT();
ND_PRINT(" oldversion");
UBIK_VERSIONOUT();
ND_PRINT(" newversion");
UBIK_VERSIONOUT();
break;
default:
;
}
return;
trunc:
ND_PRINT(" [|ubik]");
}
/*
* Handle Ubik replies to any one of the replicated database services
*/
static void
ubik_reply_print(netdissect_options *ndo,
const u_char *bp, u_int length, uint32_t opcode)
{
const struct rx_header *rxh;
uint8_t type;
if (length < sizeof(struct rx_header))
return;
rxh = (const struct rx_header *) bp;
/*
* Print out the ubik call we're invoking. This table was gleaned
* from ubik/ubik_int.xg
*/
ND_PRINT(" ubik reply %s", tok2str(ubik_req, "op#%u", opcode));
type = GET_U_1(rxh->type);
bp += sizeof(struct rx_header);
/*
* If it was a data packet, print out the arguments to the Ubik calls
*/
if (type == RX_PACKET_TYPE_DATA)
switch (opcode) {
case 10000: /* Beacon */
ND_PRINT(" vote no");
break;
case 20004: /* Get version */
ND_PRINT(" dbversion");
UBIK_VERSIONOUT();
break;
default:
;
}
/*
* Otherwise, print out "yes" if it was a beacon packet (because
* that's how yes votes are returned, go figure), otherwise
* just print out the error code.
*/
else
switch (opcode) {
case 10000: /* Beacon */
ND_PRINT(" vote yes until");
DATEOUT();
break;
default:
ND_PRINT(" errcode");
INTOUT();
}
return;
trunc:
ND_PRINT(" [|ubik]");
}
/*
* Handle RX ACK packets.
*/
static void
rx_ack_print(netdissect_options *ndo,
const u_char *bp, u_int length)
{
const struct rx_ackPacket *rxa;
uint8_t nAcks;
int i, start, last;
uint32_t firstPacket;
if (length < sizeof(struct rx_header))
return;
bp += sizeof(struct rx_header);
ND_TCHECK_LEN(bp, sizeof(struct rx_ackPacket));
rxa = (const struct rx_ackPacket *) bp;
bp += sizeof(struct rx_ackPacket);
/*
* Print out a few useful things from the ack packet structure
*/
if (ndo->ndo_vflag > 2)
ND_PRINT(" bufspace %u maxskew %u",
GET_BE_U_2(rxa->bufferSpace),
GET_BE_U_2(rxa->maxSkew));
firstPacket = GET_BE_U_4(rxa->firstPacket);
ND_PRINT(" first %u serial %u reason %s",
firstPacket, GET_BE_U_4(rxa->serial),
tok2str(rx_ack_reasons, "#%u", GET_U_1(rxa->reason)));
/*
* Okay, now we print out the ack array. The way _this_ works
* is that we start at "first", and step through the ack array.
* If we have a contiguous range of acks/nacks, try to
* collapse them into a range.
*
* If you're really clever, you might have noticed that this
* doesn't seem quite correct. Specifically, due to structure
* padding, sizeof(struct rx_ackPacket) - RX_MAXACKS won't actually
* yield the start of the ack array (because RX_MAXACKS is 255
* and the structure will likely get padded to a 2 or 4 byte
* boundary). However, this is the way it's implemented inside
* of AFS - the start of the extra fields are at
* sizeof(struct rx_ackPacket) - RX_MAXACKS + nAcks, which _isn't_
* the exact start of the ack array. Sigh. That's why we aren't
* using bp, but instead use rxa->acks[]. But nAcks gets added
* to bp after this, so bp ends up at the right spot. Go figure.
*/
nAcks = GET_U_1(rxa->nAcks);
if (nAcks != 0) {
ND_TCHECK_LEN(bp, nAcks);
/*
* Sigh, this is gross, but it seems to work to collapse
* ranges correctly.
*/
for (i = 0, start = last = -2; i < nAcks; i++)
if (GET_U_1(bp + i) == RX_ACK_TYPE_ACK) {
/*
* I figured this deserved _some_ explanation.
* First, print "acked" and the packet seq
* number if this is the first time we've
* seen an acked packet.
*/
if (last == -2) {
ND_PRINT(" acked %u", firstPacket + i);
start = i;
}
/*
* Otherwise, if there is a skip in
* the range (such as an nacked packet in
* the middle of some acked packets),
* then print the current packet number
* separated from the last number by
* a comma.
*/
else if (last != i - 1) {
ND_PRINT(",%u", firstPacket + i);
start = i;
}
/*
* We always set last to the value of
* the last ack we saw. Conversely, start
* is set to the value of the first ack
* we saw in a range.
*/
last = i;
/*
* Okay, this bit a code gets executed when
* we hit a nack ... in _this_ case we
* want to print out the range of packets
* that were acked, so we need to print
* the _previous_ packet number separated
* from the first by a dash (-). Since we
* already printed the first packet above,
* just print the final packet. Don't
* do this if there will be a single-length
* range.
*/
} else if (last == i - 1 && start != last)
ND_PRINT("-%u", firstPacket + i - 1);
/*
* So, what's going on here? We ran off the end of the
* ack list, and if we got a range we need to finish it up.
* So we need to determine if the last packet in the list
* was an ack (if so, then last will be set to it) and
* we need to see if the last range didn't start with the
* last packet (because if it _did_, then that would mean
* that the packet number has already been printed and
* we don't need to print it again).
*/
if (last == i - 1 && start != last)
ND_PRINT("-%u", firstPacket + i - 1);
/*
* Same as above, just without comments
*/
for (i = 0, start = last = -2; i < nAcks; i++)
if (GET_U_1(bp + i) == RX_ACK_TYPE_NACK) {
if (last == -2) {
ND_PRINT(" nacked %u", firstPacket + i);
start = i;
} else if (last != i - 1) {
ND_PRINT(",%u", firstPacket + i);
start = i;
}
last = i;
} else if (last == i - 1 && start != last)
ND_PRINT("-%u", firstPacket + i - 1);
if (last == i - 1 && start != last)
ND_PRINT("-%u", firstPacket + i - 1);
bp += nAcks;
}
/* Padding. */
bp += 3;
/*
* These are optional fields; depending on your version of AFS,
* you may or may not see them
*/
#define TRUNCRET(n) if (ndo->ndo_snapend - bp + 1 <= n) return;
if (ndo->ndo_vflag > 1) {
TRUNCRET(4);
ND_PRINT(" ifmtu");
UINTOUT();
TRUNCRET(4);
ND_PRINT(" maxmtu");
UINTOUT();
TRUNCRET(4);
ND_PRINT(" rwind");
UINTOUT();
TRUNCRET(4);
ND_PRINT(" maxpackets");
UINTOUT();
}
return;
trunc:
ND_PRINT(" [|ack]");
}
#undef TRUNCRET
diff --git a/contrib/tcpdump/print-sctp.c b/contrib/tcpdump/print-sctp.c
index ad0f7851889a..e49fc41fad26 100644
--- a/contrib/tcpdump/print-sctp.c
+++ b/contrib/tcpdump/print-sctp.c
@@ -1,775 +1,772 @@
/* Copyright (c) 2001 NETLAB, Temple University
* Copyright (c) 2001 Protocol Engineering Lab, University of Delaware
*
* Jerry Heinz <gheinz@astro.temple.edu>
* John Fiore <jfiore@joda.cis.temple.edu>
* Armando L. Caro Jr. <acaro@cis.udel.edu>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the University nor of the Laboratory may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* \summary: Stream Control Transmission Protocol (SCTP) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#include "ip.h"
#include "ip6.h"
/* Definitions from:
*
* SCTP reference Implementation Copyright (C) 1999 Cisco And Motorola
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of Cisco nor of Motorola may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the SCTP reference Implementation
*
*
* Please send any bug reports or fixes you make to one of the following email
* addresses:
*
* rstewar1@email.mot.com
* kmorneau@cisco.com
* qxie1@email.mot.com
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
*/
/* The valid defines for all message
* types know to SCTP. 0 is reserved
*/
#define SCTP_DATA 0x00
#define SCTP_INITIATION 0x01
#define SCTP_INITIATION_ACK 0x02
#define SCTP_SELECTIVE_ACK 0x03
#define SCTP_HEARTBEAT_REQUEST 0x04
#define SCTP_HEARTBEAT_ACK 0x05
#define SCTP_ABORT_ASSOCIATION 0x06
#define SCTP_SHUTDOWN 0x07
#define SCTP_SHUTDOWN_ACK 0x08
#define SCTP_OPERATION_ERR 0x09
#define SCTP_COOKIE_ECHO 0x0a
#define SCTP_COOKIE_ACK 0x0b
#define SCTP_ECN_ECHO 0x0c
#define SCTP_ECN_CWR 0x0d
#define SCTP_SHUTDOWN_COMPLETE 0x0e
#define SCTP_FORWARD_CUM_TSN 0xc0
#define SCTP_RELIABLE_CNTL 0xc1
#define SCTP_RELIABLE_CNTL_ACK 0xc2
static const struct tok sctp_chunkid_str[] = {
{ SCTP_DATA, "DATA" },
{ SCTP_INITIATION, "INIT" },
{ SCTP_INITIATION_ACK, "INIT ACK" },
{ SCTP_SELECTIVE_ACK, "SACK" },
{ SCTP_HEARTBEAT_REQUEST, "HB REQ" },
{ SCTP_HEARTBEAT_ACK, "HB ACK" },
{ SCTP_ABORT_ASSOCIATION, "ABORT" },
{ SCTP_SHUTDOWN, "SHUTDOWN" },
{ SCTP_SHUTDOWN_ACK, "SHUTDOWN ACK" },
{ SCTP_OPERATION_ERR, "OP ERR" },
{ SCTP_COOKIE_ECHO, "COOKIE ECHO" },
{ SCTP_COOKIE_ACK, "COOKIE ACK" },
{ SCTP_ECN_ECHO, "ECN ECHO" },
{ SCTP_ECN_CWR, "ECN CWR" },
{ SCTP_SHUTDOWN_COMPLETE, "SHUTDOWN COMPLETE" },
{ SCTP_FORWARD_CUM_TSN, "FOR CUM TSN" },
{ SCTP_RELIABLE_CNTL, "REL CTRL" },
{ SCTP_RELIABLE_CNTL_ACK, "REL CTRL ACK" },
{ 0, NULL }
};
/* Data Chuck Specific Flags */
#define SCTP_DATA_FRAG_MASK 0x03
#define SCTP_DATA_MIDDLE_FRAG 0x00
#define SCTP_DATA_LAST_FRAG 0x01
#define SCTP_DATA_FIRST_FRAG 0x02
#define SCTP_DATA_NOT_FRAG 0x03
#define SCTP_DATA_UNORDERED 0x04
#define SCTP_ADDRMAX 60
#define CHAN_HP 6704
#define CHAN_MP 6705
#define CHAN_LP 6706
/* the sctp common header */
struct sctpHeader{
nd_uint16_t source;
nd_uint16_t destination;
nd_uint32_t verificationTag;
nd_uint32_t adler32;
};
/* various descriptor parsers */
struct sctpChunkDesc{
nd_uint8_t chunkID;
nd_uint8_t chunkFlg;
nd_uint16_t chunkLength;
};
struct sctpParamDesc{
nd_uint16_t paramType;
nd_uint16_t paramLength;
};
struct sctpRelChunkDesc{
struct sctpChunkDesc chk;
nd_uint32_t serialNumber;
};
struct sctpVendorSpecificParam {
struct sctpParamDesc p; /* type must be 0xfffe */
nd_uint32_t vendorId; /* vendor ID from RFC 1700 */
nd_uint16_t vendorSpecificType;
nd_uint16_t vendorSpecificLen;
};
/* Structures for the control parts */
/* Sctp association init request/ack */
/* this is used for init ack, too */
struct sctpInitiation{
nd_uint32_t initTag; /* tag of mine */
nd_uint32_t rcvWindowCredit; /* rwnd */
nd_uint16_t NumPreopenStreams; /* OS */
nd_uint16_t MaxInboundStreams; /* MIS */
nd_uint32_t initialTSN;
/* optional param's follow in sctpParamDesc form */
};
struct sctpV4IpAddress{
struct sctpParamDesc p; /* type is set to SCTP_IPV4_PARAM_TYPE, len=10 */
nd_ipv4 ipAddress;
};
struct sctpV6IpAddress{
struct sctpParamDesc p; /* type is set to SCTP_IPV6_PARAM_TYPE, len=22 */
nd_ipv6 ipAddress;
};
struct sctpDNSName{
struct sctpParamDesc param;
nd_byte name[1];
};
struct sctpCookiePreserve{
struct sctpParamDesc p; /* type is set to SCTP_COOKIE_PRESERVE, len=8 */
nd_uint32_t extraTime;
};
struct sctpTimeStamp{
nd_uint32_t ts_sec;
nd_uint32_t ts_usec;
};
/* this guy is for use when
* I have a initiate message gloming the
* things together.
*/
struct sctpUnifiedInit{
struct sctpChunkDesc uh;
struct sctpInitiation initm;
};
struct sctpSendableInit{
struct sctpHeader mh;
struct sctpUnifiedInit msg;
};
/* Selective Acknowledgement
* has the following structure with
* a optional amount of trailing int's
* on the last part (based on the numberOfDesc
* field).
*/
struct sctpSelectiveAck{
nd_uint32_t highestConseqTSN;
nd_uint32_t updatedRwnd;
nd_uint16_t numberOfdesc;
nd_uint16_t numDupTsns;
};
struct sctpSelectiveFrag{
nd_uint16_t fragmentStart;
nd_uint16_t fragmentEnd;
};
struct sctpUnifiedSack{
struct sctpChunkDesc uh;
struct sctpSelectiveAck sack;
};
/* for the abort and shutdown ACK
* we must carry the init tag in the common header. Just the
* common header is all that is needed with a chunk descriptor.
*/
struct sctpUnifiedAbort{
struct sctpChunkDesc uh;
};
struct sctpUnifiedAbortLight{
struct sctpHeader mh;
struct sctpChunkDesc uh;
};
struct sctpUnifiedAbortHeavy{
struct sctpHeader mh;
struct sctpChunkDesc uh;
nd_uint16_t causeCode;
nd_uint16_t causeLen;
};
/* For the graceful shutdown we must carry
- * the tag (in common header) and the highest consequitive acking value
+ * the tag (in common header) and the highest consecutive acking value
*/
struct sctpShutdown {
nd_uint32_t TSN_Seen;
};
struct sctpUnifiedShutdown{
struct sctpChunkDesc uh;
struct sctpShutdown shut;
};
/* in the unified message we add the trailing
* stream id since it is the only message
* that is defined as a operation error.
*/
struct sctpOpErrorCause{
nd_uint16_t cause;
nd_uint16_t causeLen;
};
struct sctpUnifiedOpError{
struct sctpChunkDesc uh;
struct sctpOpErrorCause c;
};
struct sctpUnifiedStreamError{
struct sctpHeader mh;
struct sctpChunkDesc uh;
struct sctpOpErrorCause c;
nd_uint16_t strmNum;
nd_uint16_t reserved;
};
struct staleCookieMsg{
struct sctpHeader mh;
struct sctpChunkDesc uh;
struct sctpOpErrorCause c;
nd_uint32_t moretime;
};
/* the following is used in all sends
* where nothing is needed except the
* chunk/type i.e. shutdownAck Abort */
struct sctpUnifiedSingleMsg{
struct sctpHeader mh;
struct sctpChunkDesc uh;
};
struct sctpDataPart{
nd_uint32_t TSN;
nd_uint16_t streamId;
nd_uint16_t sequence;
nd_uint32_t payloadtype;
};
struct sctpUnifiedDatagram{
struct sctpChunkDesc uh;
struct sctpDataPart dp;
};
struct sctpECN_echo{
struct sctpChunkDesc uh;
nd_uint32_t Lowest_TSN;
};
struct sctpCWR{
struct sctpChunkDesc uh;
nd_uint32_t TSN_reduced_at;
};
static const struct tok ForCES_channels[] = {
{ CHAN_HP, "ForCES HP" },
{ CHAN_MP, "ForCES MP" },
{ CHAN_LP, "ForCES LP" },
{ 0, NULL }
};
/* data chunk's payload protocol identifiers */
#define SCTP_PPID_IUA 1
#define SCTP_PPID_M2UA 2
#define SCTP_PPID_M3UA 3
#define SCTP_PPID_SUA 4
#define SCTP_PPID_M2PA 5
#define SCTP_PPID_V5UA 6
#define SCTP_PPID_H248 7
#define SCTP_PPID_BICC 8
#define SCTP_PPID_TALI 9
#define SCTP_PPID_DUA 10
#define SCTP_PPID_ASAP 11
#define SCTP_PPID_ENRP 12
#define SCTP_PPID_H323 13
#define SCTP_PPID_QIPC 14
#define SCTP_PPID_SIMCO 15
#define SCTP_PPID_DDPSC 16
#define SCTP_PPID_DDPSSC 17
#define SCTP_PPID_S1AP 18
#define SCTP_PPID_RUA 19
#define SCTP_PPID_HNBAP 20
#define SCTP_PPID_FORCES_HP 21
#define SCTP_PPID_FORCES_MP 22
#define SCTP_PPID_FORCES_LP 23
#define SCTP_PPID_SBC_AP 24
#define SCTP_PPID_NBAP 25
/* 26 */
#define SCTP_PPID_X2AP 27
static const struct tok PayloadProto_idents[] = {
{ SCTP_PPID_IUA, "ISDN Q.921" },
{ SCTP_PPID_M2UA, "M2UA" },
{ SCTP_PPID_M3UA, "M3UA" },
{ SCTP_PPID_SUA, "SUA" },
{ SCTP_PPID_M2PA, "M2PA" },
{ SCTP_PPID_V5UA, "V5.2" },
{ SCTP_PPID_H248, "H.248" },
{ SCTP_PPID_BICC, "BICC" },
{ SCTP_PPID_TALI, "TALI" },
{ SCTP_PPID_DUA, "DUA" },
{ SCTP_PPID_ASAP, "ASAP" },
{ SCTP_PPID_ENRP, "ENRP" },
{ SCTP_PPID_H323, "H.323" },
{ SCTP_PPID_QIPC, "Q.IPC" },
{ SCTP_PPID_SIMCO, "SIMCO" },
{ SCTP_PPID_DDPSC, "DDPSC" },
{ SCTP_PPID_DDPSSC, "DDPSSC" },
{ SCTP_PPID_S1AP, "S1AP" },
{ SCTP_PPID_RUA, "RUA" },
{ SCTP_PPID_HNBAP, "HNBAP" },
{ SCTP_PPID_FORCES_HP, "ForCES HP" },
{ SCTP_PPID_FORCES_MP, "ForCES MP" },
{ SCTP_PPID_FORCES_LP, "ForCES LP" },
{ SCTP_PPID_SBC_AP, "SBc-AP" },
{ SCTP_PPID_NBAP, "NBAP" },
/* 26 */
{ SCTP_PPID_X2AP, "X2AP" },
{ 0, NULL }
};
static int
isForCES_port(u_short Port)
{
if (Port == CHAN_HP)
return 1;
if (Port == CHAN_MP)
return 1;
if (Port == CHAN_LP)
return 1;
return 0;
}
void
sctp_print(netdissect_options *ndo,
const u_char *bp, /* beginning of sctp packet */
const u_char *bp2, /* beginning of enclosing */
u_int sctpPacketLength) /* ip packet */
{
u_int sctpPacketLengthRemaining;
const struct sctpHeader *sctpPktHdr;
const struct ip *ip;
const struct ip6_hdr *ip6;
uint8_t chunkID;
u_short sourcePort, destPort;
u_int chunkCount;
const struct sctpChunkDesc *chunkDescPtr;
const char *sep;
int isforces = 0;
ndo->ndo_protocol = "sctp";
if (sctpPacketLength < sizeof(struct sctpHeader))
{
ND_PRINT("truncated-sctp - %zu bytes missing!",
sizeof(struct sctpHeader) - sctpPacketLength);
return;
}
sctpPktHdr = (const struct sctpHeader*) bp;
ND_TCHECK_SIZE(sctpPktHdr);
sctpPacketLengthRemaining = sctpPacketLength;
sourcePort = GET_BE_U_2(sctpPktHdr->source);
destPort = GET_BE_U_2(sctpPktHdr->destination);
ip = (const struct ip *)bp2;
if (IP_V(ip) == 6)
ip6 = (const struct ip6_hdr *)bp2;
else
ip6 = NULL;
if (ip6) {
ND_PRINT("%s.%u > %s.%u: sctp",
GET_IP6ADDR_STRING(ip6->ip6_src),
sourcePort,
GET_IP6ADDR_STRING(ip6->ip6_dst),
destPort);
} else {
ND_PRINT("%s.%u > %s.%u: sctp",
GET_IPADDR_STRING(ip->ip_src),
sourcePort,
GET_IPADDR_STRING(ip->ip_dst),
destPort);
}
if (isForCES_port(sourcePort)) {
ND_PRINT("[%s]", tok2str(ForCES_channels, NULL, sourcePort));
isforces = 1;
}
if (isForCES_port(destPort)) {
ND_PRINT("[%s]", tok2str(ForCES_channels, NULL, destPort));
isforces = 1;
}
bp += sizeof(struct sctpHeader);
sctpPacketLengthRemaining -= sizeof(struct sctpHeader);
if (ndo->ndo_vflag >= 2)
sep = "\n\t";
else
sep = " (";
/* cycle through all chunks, printing information on each one */
for (chunkCount = 0, chunkDescPtr = (const struct sctpChunkDesc *)bp;
sctpPacketLengthRemaining != 0;
chunkCount++)
{
uint16_t chunkLength, chunkLengthRemaining;
uint16_t align;
chunkDescPtr = (const struct sctpChunkDesc *)bp;
if (sctpPacketLengthRemaining < sizeof(*chunkDescPtr)) {
ND_PRINT("%s%u) [chunk descriptor cut off at end of packet]", sep, chunkCount+1);
break;
}
ND_TCHECK_SIZE(chunkDescPtr);
chunkLength = GET_BE_U_2(chunkDescPtr->chunkLength);
if (chunkLength < sizeof(*chunkDescPtr)) {
ND_PRINT("%s%u) [Bad chunk length %u, < size of chunk descriptor]", sep, chunkCount+1, chunkLength);
break;
}
chunkLengthRemaining = chunkLength;
align = chunkLength % 4;
if (align != 0)
align = 4 - align;
if (sctpPacketLengthRemaining < align) {
ND_PRINT("%s%u) [Bad chunk length %u, > remaining data in packet]", sep, chunkCount+1, chunkLength);
break;
}
ND_TCHECK_LEN(bp, chunkLength);
bp += sizeof(*chunkDescPtr);
sctpPacketLengthRemaining -= sizeof(*chunkDescPtr);
chunkLengthRemaining -= sizeof(*chunkDescPtr);
ND_PRINT("%s%u) ", sep, chunkCount+1);
chunkID = GET_U_1(chunkDescPtr->chunkID);
ND_PRINT("[%s] ", tok2str(sctp_chunkid_str, "Unknown chunk type: 0x%x",
chunkID));
- switch (chunkID)
- {
+ switch (chunkID) {
case SCTP_DATA :
{
const struct sctpDataPart *dataHdrPtr;
uint8_t chunkFlg;
uint32_t ppid;
uint16_t payload_size;
chunkFlg = GET_U_1(chunkDescPtr->chunkFlg);
if ((chunkFlg & SCTP_DATA_UNORDERED) == SCTP_DATA_UNORDERED)
ND_PRINT("(U)");
if ((chunkFlg & SCTP_DATA_FIRST_FRAG) == SCTP_DATA_FIRST_FRAG)
ND_PRINT("(B)");
if ((chunkFlg & SCTP_DATA_LAST_FRAG) == SCTP_DATA_LAST_FRAG)
ND_PRINT("(E)");
if( ((chunkFlg & SCTP_DATA_UNORDERED) == SCTP_DATA_UNORDERED) ||
((chunkFlg & SCTP_DATA_FIRST_FRAG) == SCTP_DATA_FIRST_FRAG) ||
((chunkFlg & SCTP_DATA_LAST_FRAG) == SCTP_DATA_LAST_FRAG) )
ND_PRINT(" ");
if (chunkLengthRemaining < sizeof(*dataHdrPtr)) {
ND_PRINT("bogus chunk length %u]", chunkLength);
return;
}
dataHdrPtr=(const struct sctpDataPart*)bp;
ppid = GET_BE_U_4(dataHdrPtr->payloadtype);
ND_PRINT("[TSN: %u] ", GET_BE_U_4(dataHdrPtr->TSN));
ND_PRINT("[SID: %u] ", GET_BE_U_2(dataHdrPtr->streamId));
ND_PRINT("[SSEQ %u] ", GET_BE_U_2(dataHdrPtr->sequence));
ND_PRINT("[PPID %s] ",
tok2str(PayloadProto_idents, "0x%x", ppid));
if (!isforces) {
isforces = (ppid == SCTP_PPID_FORCES_HP) ||
(ppid == SCTP_PPID_FORCES_MP) ||
(ppid == SCTP_PPID_FORCES_LP);
}
bp += sizeof(*dataHdrPtr);
sctpPacketLengthRemaining -= sizeof(*dataHdrPtr);
chunkLengthRemaining -= sizeof(*dataHdrPtr);
payload_size = chunkLengthRemaining;
if (payload_size == 0) {
ND_PRINT("bogus chunk length %u]", chunkLength);
return;
}
if (isforces) {
forces_print(ndo, bp, payload_size);
/* ndo_protocol reassignment after forces_print() call */
ndo->ndo_protocol = "sctp";
} else if (ndo->ndo_vflag >= 2) { /* if verbose output is specified */
/* at the command line */
switch (ppid) {
case SCTP_PPID_M3UA :
m3ua_print(ndo, bp, payload_size);
/* ndo_protocol reassignment after m3ua_print() call */
ndo->ndo_protocol = "sctp";
break;
default:
ND_PRINT("[Payload");
if (!ndo->ndo_suppress_default_print) {
ND_PRINT(":");
ND_DEFAULTPRINT(bp, payload_size);
}
ND_PRINT("]");
break;
}
}
bp += payload_size;
sctpPacketLengthRemaining -= payload_size;
chunkLengthRemaining -= payload_size;
break;
}
case SCTP_INITIATION :
{
const struct sctpInitiation *init;
if (chunkLengthRemaining < sizeof(*init)) {
ND_PRINT("bogus chunk length %u]", chunkLength);
return;
}
init=(const struct sctpInitiation*)bp;
ND_PRINT("[init tag: %u] ", GET_BE_U_4(init->initTag));
ND_PRINT("[rwnd: %u] ", GET_BE_U_4(init->rcvWindowCredit));
ND_PRINT("[OS: %u] ", GET_BE_U_2(init->NumPreopenStreams));
ND_PRINT("[MIS: %u] ", GET_BE_U_2(init->MaxInboundStreams));
ND_PRINT("[init TSN: %u] ", GET_BE_U_4(init->initialTSN));
bp += sizeof(*init);
sctpPacketLengthRemaining -= sizeof(*init);
chunkLengthRemaining -= sizeof(*init);
#if 0 /* ALC you can add code for optional params here */
if( chunkLengthRemaining != 0 )
ND_PRINT(" @@@@@ UNFINISHED @@@@@@%s\n",
"Optional params present, but not printed.");
#endif
bp += chunkLengthRemaining;
sctpPacketLengthRemaining -= chunkLengthRemaining;
chunkLengthRemaining = 0;
break;
}
case SCTP_INITIATION_ACK :
{
const struct sctpInitiation *init;
if (chunkLengthRemaining < sizeof(*init)) {
ND_PRINT("bogus chunk length %u]", chunkLength);
return;
}
init=(const struct sctpInitiation*)bp;
ND_PRINT("[init tag: %u] ", GET_BE_U_4(init->initTag));
ND_PRINT("[rwnd: %u] ", GET_BE_U_4(init->rcvWindowCredit));
ND_PRINT("[OS: %u] ", GET_BE_U_2(init->NumPreopenStreams));
ND_PRINT("[MIS: %u] ", GET_BE_U_2(init->MaxInboundStreams));
ND_PRINT("[init TSN: %u] ", GET_BE_U_4(init->initialTSN));
bp += sizeof(*init);
sctpPacketLengthRemaining -= sizeof(*init);
chunkLengthRemaining -= sizeof(*init);
#if 0 /* ALC you can add code for optional params here */
if( chunkLengthRemaining != 0 )
ND_PRINT(" @@@@@ UNFINISHED @@@@@@%s\n",
"Optional params present, but not printed.");
#endif
bp += chunkLengthRemaining;
sctpPacketLengthRemaining -= chunkLengthRemaining;
chunkLengthRemaining = 0;
break;
}
case SCTP_SELECTIVE_ACK:
{
const struct sctpSelectiveAck *sack;
const struct sctpSelectiveFrag *frag;
u_int fragNo, tsnNo;
const u_char *dupTSN;
if (chunkLengthRemaining < sizeof(*sack)) {
ND_PRINT("bogus chunk length %u]", chunkLength);
return;
}
sack=(const struct sctpSelectiveAck*)bp;
ND_PRINT("[cum ack %u] ", GET_BE_U_4(sack->highestConseqTSN));
ND_PRINT("[a_rwnd %u] ", GET_BE_U_4(sack->updatedRwnd));
ND_PRINT("[#gap acks %u] ", GET_BE_U_2(sack->numberOfdesc));
ND_PRINT("[#dup tsns %u] ", GET_BE_U_2(sack->numDupTsns));
bp += sizeof(*sack);
sctpPacketLengthRemaining -= sizeof(*sack);
chunkLengthRemaining -= sizeof(*sack);
/* print gaps */
for (fragNo=0;
chunkLengthRemaining != 0 && fragNo < GET_BE_U_2(sack->numberOfdesc);
bp += sizeof(*frag), sctpPacketLengthRemaining -= sizeof(*frag), chunkLengthRemaining -= sizeof(*frag), fragNo++) {
if (chunkLengthRemaining < sizeof(*frag)) {
ND_PRINT("bogus chunk length %u]", chunkLength);
return;
}
frag = (const struct sctpSelectiveFrag *)bp;
ND_PRINT("\n\t\t[gap ack block #%u: start = %u, end = %u] ",
fragNo+1,
GET_BE_U_4(sack->highestConseqTSN) + GET_BE_U_2(frag->fragmentStart),
GET_BE_U_4(sack->highestConseqTSN) + GET_BE_U_2(frag->fragmentEnd));
}
/* print duplicate TSNs */
for (tsnNo=0;
chunkLengthRemaining != 0 && tsnNo<GET_BE_U_2(sack->numDupTsns);
bp += 4, sctpPacketLengthRemaining -= 4, chunkLengthRemaining -= 4, tsnNo++) {
if (chunkLengthRemaining < 4) {
ND_PRINT("bogus chunk length %u]", chunkLength);
return;
}
dupTSN = (const u_char *)bp;
ND_PRINT("\n\t\t[dup TSN #%u: %u] ", tsnNo+1,
GET_BE_U_4(dupTSN));
}
break;
}
default :
{
bp += chunkLengthRemaining;
sctpPacketLengthRemaining -= chunkLengthRemaining;
chunkLengthRemaining = 0;
break;
}
}
/*
* Any extra stuff at the end of the chunk?
* XXX - report this?
*/
bp += chunkLengthRemaining;
sctpPacketLengthRemaining -= chunkLengthRemaining;
if (ndo->ndo_vflag < 2)
sep = ", (";
if (align != 0) {
/*
* Fail if the alignment padding isn't in the captured data.
* Otherwise, skip it.
*/
ND_TCHECK_LEN(bp, align);
bp += align;
sctpPacketLengthRemaining -= align;
}
}
return;
trunc:
nd_print_trunc(ndo);
}
diff --git a/contrib/tcpdump/print-sflow.c b/contrib/tcpdump/print-sflow.c
index f508ccc4233e..22de02b720cd 100644
--- a/contrib/tcpdump/print-sflow.c
+++ b/contrib/tcpdump/print-sflow.c
@@ -1,962 +1,960 @@
/*
* Copyright (c) 1998-2007 The TCPDUMP project
*
* 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.
*
* Original code by Carles Kishimoto <carles.kishimoto@gmail.com>
*
* Expansion and refactoring by Rick Jones <rick.jones2@hp.com>
*/
/* \summary: sFlow protocol printer */
/* specification: https://sflow.org/developers/specifications.php */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
#include "addrtoname.h"
/*
* sFlow datagram
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Sflow version (2,4,5) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | IP version (1 for IPv4 | 2 for IPv6) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | IP Address AGENT (4 or 16 bytes) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Sub agent ID |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Datagram sequence number |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Switch uptime in ms |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | num samples in datagram |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*/
struct sflow_datagram_t {
nd_uint32_t version;
nd_uint32_t ip_version;
nd_ipv4 agent;
nd_uint32_t agent_id;
nd_uint32_t seqnum;
nd_uint32_t uptime;
nd_uint32_t samples;
};
struct sflow_v6_datagram_t {
nd_uint32_t version;
nd_uint32_t ip_version;
nd_ipv6 agent;
nd_uint32_t agent_id;
nd_uint32_t seqnum;
nd_uint32_t uptime;
nd_uint32_t samples;
};
struct sflow_sample_header {
nd_uint32_t format;
nd_uint32_t len;
};
#define SFLOW_FLOW_SAMPLE 1
#define SFLOW_COUNTER_SAMPLE 2
#define SFLOW_EXPANDED_FLOW_SAMPLE 3
#define SFLOW_EXPANDED_COUNTER_SAMPLE 4
static const struct tok sflow_format_values[] = {
{ SFLOW_FLOW_SAMPLE, "flow sample" },
{ SFLOW_COUNTER_SAMPLE, "counter sample" },
{ SFLOW_EXPANDED_FLOW_SAMPLE, "expanded flow sample" },
{ SFLOW_EXPANDED_COUNTER_SAMPLE, "expanded counter sample" },
{ 0, NULL}
};
struct sflow_flow_sample_t {
nd_uint32_t seqnum;
nd_uint8_t type;
nd_uint24_t index;
nd_uint32_t rate;
nd_uint32_t pool;
nd_uint32_t drops;
nd_uint32_t in_interface;
nd_uint32_t out_interface;
nd_uint32_t records;
};
struct sflow_expanded_flow_sample_t {
nd_uint32_t seqnum;
nd_uint32_t type;
nd_uint32_t index;
nd_uint32_t rate;
nd_uint32_t pool;
nd_uint32_t drops;
nd_uint32_t in_interface_format;
nd_uint32_t in_interface_value;
nd_uint32_t out_interface_format;
nd_uint32_t out_interface_value;
nd_uint32_t records;
};
#define SFLOW_FLOW_RAW_PACKET 1
#define SFLOW_FLOW_ETHERNET_FRAME 2
#define SFLOW_FLOW_IPV4_DATA 3
#define SFLOW_FLOW_IPV6_DATA 4
#define SFLOW_FLOW_EXTENDED_SWITCH_DATA 1001
#define SFLOW_FLOW_EXTENDED_ROUTER_DATA 1002
#define SFLOW_FLOW_EXTENDED_GATEWAY_DATA 1003
#define SFLOW_FLOW_EXTENDED_USER_DATA 1004
#define SFLOW_FLOW_EXTENDED_URL_DATA 1005
#define SFLOW_FLOW_EXTENDED_MPLS_DATA 1006
#define SFLOW_FLOW_EXTENDED_NAT_DATA 1007
#define SFLOW_FLOW_EXTENDED_MPLS_TUNNEL 1008
#define SFLOW_FLOW_EXTENDED_MPLS_VC 1009
#define SFLOW_FLOW_EXTENDED_MPLS_FEC 1010
#define SFLOW_FLOW_EXTENDED_MPLS_LVP_FEC 1011
#define SFLOW_FLOW_EXTENDED_VLAN_TUNNEL 1012
static const struct tok sflow_flow_type_values[] = {
{ SFLOW_FLOW_RAW_PACKET, "Raw packet"},
{ SFLOW_FLOW_ETHERNET_FRAME, "Ethernet frame"},
{ SFLOW_FLOW_IPV4_DATA, "IPv4 Data"},
{ SFLOW_FLOW_IPV6_DATA, "IPv6 Data"},
{ SFLOW_FLOW_EXTENDED_SWITCH_DATA, "Extended Switch data"},
{ SFLOW_FLOW_EXTENDED_ROUTER_DATA, "Extended Router data"},
{ SFLOW_FLOW_EXTENDED_GATEWAY_DATA, "Extended Gateway data"},
{ SFLOW_FLOW_EXTENDED_USER_DATA, "Extended User data"},
{ SFLOW_FLOW_EXTENDED_URL_DATA, "Extended URL data"},
{ SFLOW_FLOW_EXTENDED_MPLS_DATA, "Extended MPLS data"},
{ SFLOW_FLOW_EXTENDED_NAT_DATA, "Extended NAT data"},
{ SFLOW_FLOW_EXTENDED_MPLS_TUNNEL, "Extended MPLS tunnel"},
{ SFLOW_FLOW_EXTENDED_MPLS_VC, "Extended MPLS VC"},
{ SFLOW_FLOW_EXTENDED_MPLS_FEC, "Extended MPLS FEC"},
{ SFLOW_FLOW_EXTENDED_MPLS_LVP_FEC, "Extended MPLS LVP FEC"},
{ SFLOW_FLOW_EXTENDED_VLAN_TUNNEL, "Extended VLAN Tunnel"},
{ 0, NULL}
};
#define SFLOW_HEADER_PROTOCOL_ETHERNET 1
#define SFLOW_HEADER_PROTOCOL_IPV4 11
#define SFLOW_HEADER_PROTOCOL_IPV6 12
static const struct tok sflow_flow_raw_protocol_values[] = {
{ SFLOW_HEADER_PROTOCOL_ETHERNET, "Ethernet"},
{ SFLOW_HEADER_PROTOCOL_IPV4, "IPv4"},
{ SFLOW_HEADER_PROTOCOL_IPV6, "IPv6"},
{ 0, NULL}
};
struct sflow_expanded_flow_raw_t {
nd_uint32_t protocol;
nd_uint32_t length;
nd_uint32_t stripped_bytes;
nd_uint32_t header_size;
};
struct sflow_ethernet_frame_t {
nd_uint32_t length;
nd_byte src_mac[8];
nd_byte dst_mac[8];
nd_uint32_t type;
};
struct sflow_extended_switch_data_t {
nd_uint32_t src_vlan;
nd_uint32_t src_pri;
nd_uint32_t dst_vlan;
nd_uint32_t dst_pri;
};
struct sflow_counter_record_t {
nd_uint32_t format;
nd_uint32_t length;
};
struct sflow_flow_record_t {
nd_uint32_t format;
nd_uint32_t length;
};
struct sflow_counter_sample_t {
nd_uint32_t seqnum;
nd_uint8_t type;
nd_uint24_t index;
nd_uint32_t records;
};
struct sflow_expanded_counter_sample_t {
nd_uint32_t seqnum;
nd_uint32_t type;
nd_uint32_t index;
nd_uint32_t records;
};
#define SFLOW_COUNTER_GENERIC 1
#define SFLOW_COUNTER_ETHERNET 2
#define SFLOW_COUNTER_TOKEN_RING 3
#define SFLOW_COUNTER_BASEVG 4
#define SFLOW_COUNTER_VLAN 5
#define SFLOW_COUNTER_PROCESSOR 1001
static const struct tok sflow_counter_type_values[] = {
{ SFLOW_COUNTER_GENERIC, "Generic counter"},
{ SFLOW_COUNTER_ETHERNET, "Ethernet counter"},
{ SFLOW_COUNTER_TOKEN_RING, "Token ring counter"},
{ SFLOW_COUNTER_BASEVG, "100 BaseVG counter"},
{ SFLOW_COUNTER_VLAN, "Vlan counter"},
{ SFLOW_COUNTER_PROCESSOR, "Processor counter"},
{ 0, NULL}
};
#define SFLOW_IFACE_DIRECTION_UNKNOWN 0
#define SFLOW_IFACE_DIRECTION_FULLDUPLEX 1
#define SFLOW_IFACE_DIRECTION_HALFDUPLEX 2
#define SFLOW_IFACE_DIRECTION_IN 3
#define SFLOW_IFACE_DIRECTION_OUT 4
static const struct tok sflow_iface_direction_values[] = {
{ SFLOW_IFACE_DIRECTION_UNKNOWN, "unknown"},
{ SFLOW_IFACE_DIRECTION_FULLDUPLEX, "full-duplex"},
{ SFLOW_IFACE_DIRECTION_HALFDUPLEX, "half-duplex"},
{ SFLOW_IFACE_DIRECTION_IN, "in"},
{ SFLOW_IFACE_DIRECTION_OUT, "out"},
{ 0, NULL}
};
struct sflow_generic_counter_t {
nd_uint32_t ifindex;
nd_uint32_t iftype;
nd_uint64_t ifspeed;
nd_uint32_t ifdirection;
nd_uint32_t ifstatus;
nd_uint64_t ifinoctets;
nd_uint32_t ifinunicastpkts;
nd_uint32_t ifinmulticastpkts;
nd_uint32_t ifinbroadcastpkts;
nd_uint32_t ifindiscards;
nd_uint32_t ifinerrors;
nd_uint32_t ifinunkownprotos;
nd_uint64_t ifoutoctets;
nd_uint32_t ifoutunicastpkts;
nd_uint32_t ifoutmulticastpkts;
nd_uint32_t ifoutbroadcastpkts;
nd_uint32_t ifoutdiscards;
nd_uint32_t ifouterrors;
nd_uint32_t ifpromiscmode;
};
struct sflow_ethernet_counter_t {
nd_uint32_t alignerrors;
nd_uint32_t fcserrors;
nd_uint32_t single_collision_frames;
nd_uint32_t multiple_collision_frames;
nd_uint32_t test_errors;
nd_uint32_t deferred_transmissions;
nd_uint32_t late_collisions;
nd_uint32_t excessive_collisions;
nd_uint32_t mac_transmit_errors;
nd_uint32_t carrier_sense_errors;
nd_uint32_t frame_too_longs;
nd_uint32_t mac_receive_errors;
nd_uint32_t symbol_errors;
};
struct sflow_100basevg_counter_t {
nd_uint32_t in_highpriority_frames;
nd_uint64_t in_highpriority_octets;
nd_uint32_t in_normpriority_frames;
nd_uint64_t in_normpriority_octets;
nd_uint32_t in_ipmerrors;
nd_uint32_t in_oversized;
nd_uint32_t in_data_errors;
nd_uint32_t in_null_addressed_frames;
nd_uint32_t out_highpriority_frames;
nd_uint64_t out_highpriority_octets;
nd_uint32_t transitioninto_frames;
nd_uint64_t hc_in_highpriority_octets;
nd_uint64_t hc_in_normpriority_octets;
nd_uint64_t hc_out_highpriority_octets;
};
struct sflow_vlan_counter_t {
nd_uint32_t vlan_id;
nd_uint64_t octets;
nd_uint32_t unicast_pkt;
nd_uint32_t multicast_pkt;
nd_uint32_t broadcast_pkt;
nd_uint32_t discards;
};
static int
print_sflow_counter_generic(netdissect_options *ndo,
const u_char *pointer, u_int len)
{
const struct sflow_generic_counter_t *sflow_gen_counter;
if (len < sizeof(struct sflow_generic_counter_t))
return 1;
sflow_gen_counter = (const struct sflow_generic_counter_t *)pointer;
ND_PRINT("\n\t ifindex %u, iftype %u, ifspeed %" PRIu64 ", ifdirection %u (%s)",
GET_BE_U_4(sflow_gen_counter->ifindex),
GET_BE_U_4(sflow_gen_counter->iftype),
GET_BE_U_8(sflow_gen_counter->ifspeed),
GET_BE_U_4(sflow_gen_counter->ifdirection),
tok2str(sflow_iface_direction_values, "Unknown",
GET_BE_U_4(sflow_gen_counter->ifdirection)));
ND_PRINT("\n\t ifstatus %u, adminstatus: %s, operstatus: %s",
GET_BE_U_4(sflow_gen_counter->ifstatus),
GET_BE_U_4(sflow_gen_counter->ifstatus)&1 ? "up" : "down",
(GET_BE_U_4(sflow_gen_counter->ifstatus)>>1)&1 ? "up" : "down");
ND_PRINT("\n\t In octets %" PRIu64
", unicast pkts %u, multicast pkts %u, broadcast pkts %u, discards %u",
GET_BE_U_8(sflow_gen_counter->ifinoctets),
GET_BE_U_4(sflow_gen_counter->ifinunicastpkts),
GET_BE_U_4(sflow_gen_counter->ifinmulticastpkts),
GET_BE_U_4(sflow_gen_counter->ifinbroadcastpkts),
GET_BE_U_4(sflow_gen_counter->ifindiscards));
ND_PRINT("\n\t In errors %u, unknown protos %u",
GET_BE_U_4(sflow_gen_counter->ifinerrors),
GET_BE_U_4(sflow_gen_counter->ifinunkownprotos));
ND_PRINT("\n\t Out octets %" PRIu64
", unicast pkts %u, multicast pkts %u, broadcast pkts %u, discards %u",
GET_BE_U_8(sflow_gen_counter->ifoutoctets),
GET_BE_U_4(sflow_gen_counter->ifoutunicastpkts),
GET_BE_U_4(sflow_gen_counter->ifoutmulticastpkts),
GET_BE_U_4(sflow_gen_counter->ifoutbroadcastpkts),
GET_BE_U_4(sflow_gen_counter->ifoutdiscards));
ND_PRINT("\n\t Out errors %u, promisc mode %u",
GET_BE_U_4(sflow_gen_counter->ifouterrors),
GET_BE_U_4(sflow_gen_counter->ifpromiscmode));
return 0;
}
static int
print_sflow_counter_ethernet(netdissect_options *ndo,
const u_char *pointer, u_int len)
{
const struct sflow_ethernet_counter_t *sflow_eth_counter;
if (len < sizeof(struct sflow_ethernet_counter_t))
return 1;
sflow_eth_counter = (const struct sflow_ethernet_counter_t *)pointer;
ND_PRINT("\n\t align errors %u, fcs errors %u, single collision %u, multiple collision %u, test error %u",
GET_BE_U_4(sflow_eth_counter->alignerrors),
GET_BE_U_4(sflow_eth_counter->fcserrors),
GET_BE_U_4(sflow_eth_counter->single_collision_frames),
GET_BE_U_4(sflow_eth_counter->multiple_collision_frames),
GET_BE_U_4(sflow_eth_counter->test_errors));
ND_PRINT("\n\t deferred %u, late collision %u, excessive collision %u, mac trans error %u",
GET_BE_U_4(sflow_eth_counter->deferred_transmissions),
GET_BE_U_4(sflow_eth_counter->late_collisions),
GET_BE_U_4(sflow_eth_counter->excessive_collisions),
GET_BE_U_4(sflow_eth_counter->mac_transmit_errors));
ND_PRINT("\n\t carrier error %u, frames too long %u, mac receive errors %u, symbol errors %u",
GET_BE_U_4(sflow_eth_counter->carrier_sense_errors),
GET_BE_U_4(sflow_eth_counter->frame_too_longs),
GET_BE_U_4(sflow_eth_counter->mac_receive_errors),
GET_BE_U_4(sflow_eth_counter->symbol_errors));
return 0;
}
static int
print_sflow_counter_token_ring(netdissect_options *ndo _U_,
const u_char *pointer _U_, u_int len _U_)
{
return 0;
}
static int
print_sflow_counter_basevg(netdissect_options *ndo,
const u_char *pointer, u_int len)
{
const struct sflow_100basevg_counter_t *sflow_100basevg_counter;
if (len < sizeof(struct sflow_100basevg_counter_t))
return 1;
sflow_100basevg_counter = (const struct sflow_100basevg_counter_t *)pointer;
ND_PRINT("\n\t in high prio frames %u, in high prio octets %" PRIu64,
GET_BE_U_4(sflow_100basevg_counter->in_highpriority_frames),
GET_BE_U_8(sflow_100basevg_counter->in_highpriority_octets));
ND_PRINT("\n\t in norm prio frames %u, in norm prio octets %" PRIu64,
GET_BE_U_4(sflow_100basevg_counter->in_normpriority_frames),
GET_BE_U_8(sflow_100basevg_counter->in_normpriority_octets));
ND_PRINT("\n\t in ipm errors %u, oversized %u, in data errors %u, null addressed frames %u",
GET_BE_U_4(sflow_100basevg_counter->in_ipmerrors),
GET_BE_U_4(sflow_100basevg_counter->in_oversized),
GET_BE_U_4(sflow_100basevg_counter->in_data_errors),
GET_BE_U_4(sflow_100basevg_counter->in_null_addressed_frames));
ND_PRINT("\n\t out high prio frames %u, out high prio octets %" PRIu64
", trans into frames %u",
GET_BE_U_4(sflow_100basevg_counter->out_highpriority_frames),
GET_BE_U_8(sflow_100basevg_counter->out_highpriority_octets),
GET_BE_U_4(sflow_100basevg_counter->transitioninto_frames));
ND_PRINT("\n\t in hc high prio octets %" PRIu64
", in hc norm prio octets %" PRIu64
", out hc high prio octets %" PRIu64,
GET_BE_U_8(sflow_100basevg_counter->hc_in_highpriority_octets),
GET_BE_U_8(sflow_100basevg_counter->hc_in_normpriority_octets),
GET_BE_U_8(sflow_100basevg_counter->hc_out_highpriority_octets));
return 0;
}
static int
print_sflow_counter_vlan(netdissect_options *ndo,
const u_char *pointer, u_int len)
{
const struct sflow_vlan_counter_t *sflow_vlan_counter;
if (len < sizeof(struct sflow_vlan_counter_t))
return 1;
sflow_vlan_counter = (const struct sflow_vlan_counter_t *)pointer;
ND_PRINT("\n\t vlan_id %u, octets %" PRIu64
", unicast_pkt %u, multicast_pkt %u, broadcast_pkt %u, discards %u",
GET_BE_U_4(sflow_vlan_counter->vlan_id),
GET_BE_U_8(sflow_vlan_counter->octets),
GET_BE_U_4(sflow_vlan_counter->unicast_pkt),
GET_BE_U_4(sflow_vlan_counter->multicast_pkt),
GET_BE_U_4(sflow_vlan_counter->broadcast_pkt),
GET_BE_U_4(sflow_vlan_counter->discards));
return 0;
}
struct sflow_processor_counter_t {
nd_uint32_t five_sec_util;
nd_uint32_t one_min_util;
nd_uint32_t five_min_util;
nd_uint64_t total_memory;
nd_uint64_t free_memory;
};
static int
print_sflow_counter_processor(netdissect_options *ndo,
const u_char *pointer, u_int len)
{
const struct sflow_processor_counter_t *sflow_processor_counter;
if (len < sizeof(struct sflow_processor_counter_t))
return 1;
sflow_processor_counter = (const struct sflow_processor_counter_t *)pointer;
ND_PRINT("\n\t 5sec %u, 1min %u, 5min %u, total_mem %" PRIu64
", total_mem %" PRIu64,
GET_BE_U_4(sflow_processor_counter->five_sec_util),
GET_BE_U_4(sflow_processor_counter->one_min_util),
GET_BE_U_4(sflow_processor_counter->five_min_util),
GET_BE_U_8(sflow_processor_counter->total_memory),
GET_BE_U_8(sflow_processor_counter->free_memory));
return 0;
}
static int
sflow_print_counter_records(netdissect_options *ndo,
const u_char *pointer, u_int len, u_int records)
{
u_int nrecords;
const u_char *tptr;
u_int tlen;
u_int counter_type;
u_int counter_len;
u_int enterprise;
const struct sflow_counter_record_t *sflow_counter_record;
nrecords = records;
tptr = pointer;
tlen = len;
while (nrecords > 0) {
/* do we have the "header?" */
if (tlen < sizeof(struct sflow_counter_record_t))
return 1;
sflow_counter_record = (const struct sflow_counter_record_t *)tptr;
enterprise = GET_BE_U_4(sflow_counter_record->format);
counter_type = enterprise & 0x0FFF;
enterprise = enterprise >> 20;
counter_len = GET_BE_U_4(sflow_counter_record->length);
ND_PRINT("\n\t enterprise %u, %s (%u) length %u",
enterprise,
(enterprise == 0) ? tok2str(sflow_counter_type_values,"Unknown",counter_type) : "Unknown",
counter_type,
counter_len);
tptr += sizeof(struct sflow_counter_record_t);
tlen -= sizeof(struct sflow_counter_record_t);
if (tlen < counter_len)
return 1;
if (enterprise == 0) {
switch (counter_type) {
case SFLOW_COUNTER_GENERIC:
if (print_sflow_counter_generic(ndo, tptr, tlen))
return 1;
break;
case SFLOW_COUNTER_ETHERNET:
if (print_sflow_counter_ethernet(ndo, tptr, tlen))
return 1;
break;
case SFLOW_COUNTER_TOKEN_RING:
if (print_sflow_counter_token_ring(ndo, tptr,tlen))
return 1;
break;
case SFLOW_COUNTER_BASEVG:
if (print_sflow_counter_basevg(ndo, tptr, tlen))
return 1;
break;
case SFLOW_COUNTER_VLAN:
if (print_sflow_counter_vlan(ndo, tptr, tlen))
return 1;
break;
case SFLOW_COUNTER_PROCESSOR:
if (print_sflow_counter_processor(ndo, tptr, tlen))
return 1;
break;
default:
if (ndo->ndo_vflag <= 1)
print_unknown_data(ndo, tptr, "\n\t\t", counter_len);
break;
}
}
tptr += counter_len;
tlen -= counter_len;
nrecords--;
}
return 0;
}
static int
sflow_print_counter_sample(netdissect_options *ndo,
const u_char *pointer, u_int len)
{
const struct sflow_counter_sample_t *sflow_counter_sample;
u_int nrecords;
if (len < sizeof(struct sflow_counter_sample_t))
return 1;
sflow_counter_sample = (const struct sflow_counter_sample_t *)pointer;
nrecords = GET_BE_U_4(sflow_counter_sample->records);
ND_PRINT(" seqnum %u, type %u, idx %u, records %u",
GET_BE_U_4(sflow_counter_sample->seqnum),
GET_U_1(sflow_counter_sample->type),
GET_BE_U_3(sflow_counter_sample->index),
nrecords);
return sflow_print_counter_records(ndo, pointer + sizeof(struct sflow_counter_sample_t),
len - sizeof(struct sflow_counter_sample_t),
nrecords);
}
static int
sflow_print_expanded_counter_sample(netdissect_options *ndo,
const u_char *pointer, u_int len)
{
const struct sflow_expanded_counter_sample_t *sflow_expanded_counter_sample;
u_int nrecords;
if (len < sizeof(struct sflow_expanded_counter_sample_t))
return 1;
sflow_expanded_counter_sample = (const struct sflow_expanded_counter_sample_t *)pointer;
nrecords = GET_BE_U_4(sflow_expanded_counter_sample->records);
ND_PRINT(" seqnum %u, type %u, idx %u, records %u",
GET_BE_U_4(sflow_expanded_counter_sample->seqnum),
GET_BE_U_4(sflow_expanded_counter_sample->type),
GET_BE_U_4(sflow_expanded_counter_sample->index),
nrecords);
return sflow_print_counter_records(ndo, pointer + sizeof(struct sflow_expanded_counter_sample_t),
len - sizeof(struct sflow_expanded_counter_sample_t),
nrecords);
}
static int
print_sflow_raw_packet(netdissect_options *ndo,
const u_char *pointer, u_int len)
{
const struct sflow_expanded_flow_raw_t *sflow_flow_raw;
if (len < sizeof(struct sflow_expanded_flow_raw_t))
return 1;
sflow_flow_raw = (const struct sflow_expanded_flow_raw_t *)pointer;
ND_PRINT("\n\t protocol %s (%u), length %u, stripped bytes %u, header_size %u",
tok2str(sflow_flow_raw_protocol_values,"Unknown",GET_BE_U_4(sflow_flow_raw->protocol)),
GET_BE_U_4(sflow_flow_raw->protocol),
GET_BE_U_4(sflow_flow_raw->length),
GET_BE_U_4(sflow_flow_raw->stripped_bytes),
GET_BE_U_4(sflow_flow_raw->header_size));
/* QUESTION - should we attempt to print the raw header itself?
assuming of course there is enough data present to do so... */
return 0;
}
static int
print_sflow_ethernet_frame(netdissect_options *ndo,
const u_char *pointer, u_int len)
{
const struct sflow_ethernet_frame_t *sflow_ethernet_frame;
if (len < sizeof(struct sflow_ethernet_frame_t))
return 1;
sflow_ethernet_frame = (const struct sflow_ethernet_frame_t *)pointer;
ND_PRINT("\n\t frame len %u, type %u",
GET_BE_U_4(sflow_ethernet_frame->length),
GET_BE_U_4(sflow_ethernet_frame->type));
return 0;
}
static int
print_sflow_extended_switch_data(netdissect_options *ndo,
const u_char *pointer, u_int len)
{
const struct sflow_extended_switch_data_t *sflow_extended_sw_data;
if (len < sizeof(struct sflow_extended_switch_data_t))
return 1;
sflow_extended_sw_data = (const struct sflow_extended_switch_data_t *)pointer;
ND_PRINT("\n\t src vlan %u, src pri %u, dst vlan %u, dst pri %u",
GET_BE_U_4(sflow_extended_sw_data->src_vlan),
GET_BE_U_4(sflow_extended_sw_data->src_pri),
GET_BE_U_4(sflow_extended_sw_data->dst_vlan),
GET_BE_U_4(sflow_extended_sw_data->dst_pri));
return 0;
}
static int
sflow_print_flow_records(netdissect_options *ndo,
const u_char *pointer, u_int len, u_int records)
{
u_int nrecords;
const u_char *tptr;
u_int tlen;
u_int flow_type;
u_int enterprise;
u_int flow_len;
const struct sflow_flow_record_t *sflow_flow_record;
nrecords = records;
tptr = pointer;
tlen = len;
while (nrecords > 0) {
/* do we have the "header?" */
if (tlen < sizeof(struct sflow_flow_record_t))
return 1;
sflow_flow_record = (const struct sflow_flow_record_t *)tptr;
- /* so, the funky encoding means we cannot blythly mask-off
+ /* so, the funky encoding means we cannot blithely mask-off
bits, we must also check the enterprise. */
enterprise = GET_BE_U_4(sflow_flow_record->format);
flow_type = enterprise & 0x0FFF;
enterprise = enterprise >> 12;
flow_len = GET_BE_U_4(sflow_flow_record->length);
ND_PRINT("\n\t enterprise %u %s (%u) length %u",
enterprise,
(enterprise == 0) ? tok2str(sflow_flow_type_values,"Unknown",flow_type) : "Unknown",
flow_type,
flow_len);
tptr += sizeof(struct sflow_flow_record_t);
tlen -= sizeof(struct sflow_flow_record_t);
if (tlen < flow_len)
return 1;
if (enterprise == 0) {
switch (flow_type) {
case SFLOW_FLOW_RAW_PACKET:
if (print_sflow_raw_packet(ndo, tptr, tlen))
return 1;
break;
case SFLOW_FLOW_EXTENDED_SWITCH_DATA:
if (print_sflow_extended_switch_data(ndo, tptr, tlen))
return 1;
break;
case SFLOW_FLOW_ETHERNET_FRAME:
if (print_sflow_ethernet_frame(ndo, tptr, tlen))
return 1;
break;
/* FIXME these need a decoder */
case SFLOW_FLOW_IPV4_DATA:
case SFLOW_FLOW_IPV6_DATA:
case SFLOW_FLOW_EXTENDED_ROUTER_DATA:
case SFLOW_FLOW_EXTENDED_GATEWAY_DATA:
case SFLOW_FLOW_EXTENDED_USER_DATA:
case SFLOW_FLOW_EXTENDED_URL_DATA:
case SFLOW_FLOW_EXTENDED_MPLS_DATA:
case SFLOW_FLOW_EXTENDED_NAT_DATA:
case SFLOW_FLOW_EXTENDED_MPLS_TUNNEL:
case SFLOW_FLOW_EXTENDED_MPLS_VC:
case SFLOW_FLOW_EXTENDED_MPLS_FEC:
case SFLOW_FLOW_EXTENDED_MPLS_LVP_FEC:
case SFLOW_FLOW_EXTENDED_VLAN_TUNNEL:
break;
default:
if (ndo->ndo_vflag <= 1)
print_unknown_data(ndo, tptr, "\n\t\t", flow_len);
break;
}
}
tptr += flow_len;
tlen -= flow_len;
nrecords--;
}
return 0;
}
static int
sflow_print_flow_sample(netdissect_options *ndo,
const u_char *pointer, u_int len)
{
const struct sflow_flow_sample_t *sflow_flow_sample;
u_int nrecords;
if (len < sizeof(struct sflow_flow_sample_t))
return 1;
sflow_flow_sample = (const struct sflow_flow_sample_t *)pointer;
nrecords = GET_BE_U_4(sflow_flow_sample->records);
ND_PRINT(" seqnum %u, type %u, idx %u, rate %u, pool %u, drops %u, input %u output %u records %u",
GET_BE_U_4(sflow_flow_sample->seqnum),
GET_U_1(sflow_flow_sample->type),
GET_BE_U_3(sflow_flow_sample->index),
GET_BE_U_4(sflow_flow_sample->rate),
GET_BE_U_4(sflow_flow_sample->pool),
GET_BE_U_4(sflow_flow_sample->drops),
GET_BE_U_4(sflow_flow_sample->in_interface),
GET_BE_U_4(sflow_flow_sample->out_interface),
nrecords);
return sflow_print_flow_records(ndo, pointer + sizeof(struct sflow_flow_sample_t),
len - sizeof(struct sflow_flow_sample_t),
nrecords);
}
static int
sflow_print_expanded_flow_sample(netdissect_options *ndo,
const u_char *pointer, u_int len)
{
const struct sflow_expanded_flow_sample_t *sflow_expanded_flow_sample;
u_int nrecords;
if (len < sizeof(struct sflow_expanded_flow_sample_t))
return 1;
sflow_expanded_flow_sample = (const struct sflow_expanded_flow_sample_t *)pointer;
nrecords = GET_BE_U_4(sflow_expanded_flow_sample->records);
ND_PRINT(" seqnum %u, type %u, idx %u, rate %u, pool %u, drops %u, records %u",
GET_BE_U_4(sflow_expanded_flow_sample->seqnum),
GET_BE_U_4(sflow_expanded_flow_sample->type),
GET_BE_U_4(sflow_expanded_flow_sample->index),
GET_BE_U_4(sflow_expanded_flow_sample->rate),
GET_BE_U_4(sflow_expanded_flow_sample->pool),
GET_BE_U_4(sflow_expanded_flow_sample->drops),
nrecords);
return sflow_print_flow_records(ndo, pointer + sizeof(struct sflow_expanded_flow_sample_t),
len - sizeof(struct sflow_expanded_flow_sample_t),
nrecords);
}
void
sflow_print(netdissect_options *ndo,
const u_char *pptr, u_int len)
{
const struct sflow_datagram_t *sflow_datagram;
const struct sflow_v6_datagram_t *sflow_v6_datagram;
const struct sflow_sample_header *sflow_sample;
const u_char *tptr;
u_int tlen;
uint32_t sflow_sample_type, sflow_sample_len;
uint32_t nsamples;
uint32_t ip_version;
ndo->ndo_protocol = "sflow";
tptr = pptr;
tlen = len;
sflow_datagram = (const struct sflow_datagram_t *)pptr;
sflow_v6_datagram = (const struct sflow_v6_datagram_t *)pptr;
ip_version = GET_BE_U_4(sflow_datagram->ip_version);
if ((len < sizeof(struct sflow_datagram_t) && (ip_version == 1)) ||
(len < sizeof(struct sflow_v6_datagram_t) && (ip_version == 2))) {
ND_PRINT("sFlowv%u", GET_BE_U_4(sflow_datagram->version));
ND_PRINT(" [length %u < %zu]", len, sizeof(struct sflow_datagram_t));
nd_print_invalid(ndo);
return;
}
ND_TCHECK_SIZE(sflow_datagram);
/*
* Sanity checking of the header.
*/
if (GET_BE_U_4(sflow_datagram->version) != 5) {
ND_PRINT("sFlow version %u packet not supported",
GET_BE_U_4(sflow_datagram->version));
return;
}
if (ndo->ndo_vflag < 1) {
ND_PRINT("sFlowv%u, %s agent %s, agent-id %u, length %u",
GET_BE_U_4(sflow_datagram->version),
ip_version == 1 ? "IPv4" : "IPv6",
ip_version == 1 ? GET_IPADDR_STRING(sflow_datagram->agent) :
GET_IP6ADDR_STRING( sflow_v6_datagram->agent),
ip_version == 1 ? GET_BE_U_4(sflow_datagram->agent_id) :
GET_BE_U_4(sflow_v6_datagram->agent_id),
len);
return;
}
/* ok they seem to want to know everything - lets fully decode it */
if (ip_version == 1) {
nsamples=GET_BE_U_4(sflow_datagram->samples);
ND_PRINT("sFlowv%u, %s agent %s, agent-id %u, seqnum %u, uptime %u, samples %u, length %u",
GET_BE_U_4(sflow_datagram->version),
"IPv4",
GET_IPADDR_STRING(sflow_datagram->agent),
GET_BE_U_4(sflow_datagram->agent_id),
GET_BE_U_4(sflow_datagram->seqnum),
GET_BE_U_4(sflow_datagram->uptime),
nsamples,
len);
/* skip Common header */
- ND_LCHECK_ZU(tlen, sizeof(struct sflow_datagram_t));
+ ND_ICHECK_ZU(tlen, <, sizeof(struct sflow_datagram_t));
tptr += sizeof(struct sflow_datagram_t);
tlen -= sizeof(struct sflow_datagram_t);
} else {
nsamples=GET_BE_U_4(sflow_v6_datagram->samples);
ND_PRINT("sFlowv%u, %s agent %s, agent-id %u, seqnum %u, uptime %u, samples %u, length %u",
GET_BE_U_4(sflow_v6_datagram->version),
"IPv6",
GET_IP6ADDR_STRING(sflow_v6_datagram->agent),
GET_BE_U_4(sflow_v6_datagram->agent_id),
GET_BE_U_4(sflow_v6_datagram->seqnum),
GET_BE_U_4(sflow_v6_datagram->uptime),
nsamples,
len);
/* skip Common header */
- ND_LCHECK_ZU(tlen, sizeof(struct sflow_v6_datagram_t));
+ ND_ICHECK_ZU(tlen, <, sizeof(struct sflow_v6_datagram_t));
tptr += sizeof(struct sflow_v6_datagram_t);
tlen -= sizeof(struct sflow_v6_datagram_t);
}
while (nsamples > 0 && tlen > 0) {
sflow_sample = (const struct sflow_sample_header *)tptr;
sflow_sample_type = (GET_BE_U_4(sflow_sample->format)&0x0FFF);
sflow_sample_len = GET_BE_U_4(sflow_sample->len);
if (tlen < sizeof(struct sflow_sample_header))
goto invalid;
tptr += sizeof(struct sflow_sample_header);
tlen -= sizeof(struct sflow_sample_header);
ND_PRINT("\n\t%s (%u), length %u,",
tok2str(sflow_format_values, "Unknown", sflow_sample_type),
sflow_sample_type,
sflow_sample_len);
/* basic sanity check */
if (sflow_sample_type == 0 || sflow_sample_len ==0) {
return;
}
if (tlen < sflow_sample_len)
goto invalid;
/* did we capture enough for fully decoding the sample ? */
ND_TCHECK_LEN(tptr, sflow_sample_len);
switch(sflow_sample_type) {
case SFLOW_FLOW_SAMPLE:
if (sflow_print_flow_sample(ndo, tptr, tlen))
goto invalid;
break;
case SFLOW_COUNTER_SAMPLE:
if (sflow_print_counter_sample(ndo, tptr,tlen))
goto invalid;
break;
case SFLOW_EXPANDED_FLOW_SAMPLE:
if (sflow_print_expanded_flow_sample(ndo, tptr, tlen))
goto invalid;
break;
case SFLOW_EXPANDED_COUNTER_SAMPLE:
if (sflow_print_expanded_counter_sample(ndo, tptr,tlen))
goto invalid;
break;
default:
if (ndo->ndo_vflag <= 1)
print_unknown_data(ndo, tptr, "\n\t ", sflow_sample_len);
break;
}
tptr += sflow_sample_len;
tlen -= sflow_sample_len;
nsamples--;
}
return;
invalid:
nd_print_invalid(ndo);
ND_TCHECK_LEN(tptr, tlen);
}
diff --git a/contrib/tcpdump/print-sip.c b/contrib/tcpdump/print-sip.c
index bfbfddfd4749..9af728a3576f 100644
--- a/contrib/tcpdump/print-sip.c
+++ b/contrib/tcpdump/print-sip.c
@@ -1,54 +1,52 @@
/*
* 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.
*
* Original code by Hannes Gredler (hannes@gredler.at)
* Turned into common "text protocol" code, which this uses, by
* Guy Harris.
*/
/* \summary: Session Initiation Protocol (SIP) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
static const char *sipcmds[] = {
"ACK",
"BYE",
"CANCEL",
"DO",
"INFO",
"INVITE",
"MESSAGE",
"NOTIFY",
"OPTIONS",
"PRACK",
"QAUTH",
"REFER",
"REGISTER",
"SPRACK",
"SUBSCRIBE",
"UPDATE",
"PUBLISH",
NULL
};
void
sip_print(netdissect_options *ndo, const u_char *pptr, u_int len)
{
ndo->ndo_protocol = "sip";
txtproto_print(ndo, pptr, len, sipcmds, RESP_CODE_SECOND_TOKEN);
}
diff --git a/contrib/tcpdump/print-sl.c b/contrib/tcpdump/print-sl.c
index 85b762496d24..c80f0765d24a 100644
--- a/contrib/tcpdump/print-sl.c
+++ b/contrib/tcpdump/print-sl.c
@@ -1,259 +1,257 @@
/*
* Copyright (c) 1989, 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.
*/
/* \summary: Compressed Serial Line Internet Protocol printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
#include "ip.h"
#include "tcp.h"
#include "slcompress.h"
/*
* definitions of the pseudo- link-level header attached to slip
* packets grabbed by the packet filter (bpf) traffic monitor.
*/
#define SLIP_HDRLEN 16
#define SLX_DIR 0
#define SLX_CHDR 1
#define SLIPDIR_IN 0
#define SLIPDIR_OUT 1
static u_int lastlen[2][256];
static u_int lastconn = 255;
static void sliplink_print(netdissect_options *, const u_char *, const struct ip *, u_int);
static void compressed_sl_print(netdissect_options *, const u_char *, const struct ip *, u_int, int);
void
sl_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h, const u_char *p)
{
u_int length = h->len;
const struct ip *ip;
ndo->ndo_protocol = "slip";
ND_TCHECK_LEN(p, SLIP_HDRLEN);
ndo->ndo_ll_hdr_len += SLIP_HDRLEN;
length -= SLIP_HDRLEN;
ip = (const struct ip *)(p + SLIP_HDRLEN);
if (ndo->ndo_eflag)
sliplink_print(ndo, p, ip, length);
switch (IP_V(ip)) {
case 4:
ip_print(ndo, (const u_char *)ip, length);
break;
case 6:
ip6_print(ndo, (const u_char *)ip, length);
break;
default:
ND_PRINT("ip v%u", IP_V(ip));
}
}
void
sl_bsdos_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h, const u_char *p)
{
u_int length = h->len;
const struct ip *ip;
ndo->ndo_protocol = "slip_bsdos";
ND_TCHECK_LEN(p, SLIP_HDRLEN);
ndo->ndo_ll_hdr_len += SLIP_HDRLEN;
length -= SLIP_HDRLEN;
ip = (const struct ip *)(p + SLIP_HDRLEN);
#ifdef notdef
if (ndo->ndo_eflag)
sliplink_print(ndo, p, ip, length);
#endif
ip_print(ndo, (const u_char *)ip, length);
}
static void
sliplink_print(netdissect_options *ndo,
const u_char *p, const struct ip *ip,
u_int length)
{
int dir;
u_int hlen;
dir = GET_U_1(p + SLX_DIR);
switch (dir) {
case SLIPDIR_IN:
ND_PRINT("I ");
break;
case SLIPDIR_OUT:
ND_PRINT("O ");
break;
default:
ND_PRINT("Invalid direction %d ", dir);
dir = -1;
break;
}
switch (GET_U_1(p + SLX_CHDR) & 0xf0) {
case TYPE_IP:
ND_PRINT("ip %u: ", length + SLIP_HDRLEN);
break;
case TYPE_UNCOMPRESSED_TCP:
/*
* The connection id is stored in the IP protocol field.
* Get it from the link layer since sl_uncompress_tcp()
* has restored the IP header copy to IPPROTO_TCP.
*/
lastconn = GET_U_1(((const struct ip *)(p + SLX_CHDR))->ip_p);
ND_PRINT("utcp %u: ", lastconn);
if (dir == -1) {
/* Direction is bogus, don't use it */
return;
}
ND_TCHECK_SIZE(ip);
hlen = IP_HL(ip);
ND_TCHECK_SIZE((const struct tcphdr *)&((const int *)ip)[hlen]);
hlen += TH_OFF((const struct tcphdr *)&((const int *)ip)[hlen]);
lastlen[dir][lastconn] = length - (hlen << 2);
break;
default:
if (dir == -1) {
/* Direction is bogus, don't use it */
return;
}
if (GET_U_1(p + SLX_CHDR) & TYPE_COMPRESSED_TCP) {
compressed_sl_print(ndo, p + SLX_CHDR, ip, length, dir);
ND_PRINT(": ");
} else
ND_PRINT("slip-%u!: ", GET_U_1(p + SLX_CHDR));
}
}
static const u_char *
print_sl_change(netdissect_options *ndo,
const char *str, const u_char *cp)
{
u_int i;
if ((i = GET_U_1(cp)) == 0) {
cp++;
i = GET_BE_U_2(cp);
cp += 2;
}
ND_PRINT(" %s%u", str, i);
return (cp);
}
static const u_char *
print_sl_winchange(netdissect_options *ndo,
const u_char *cp)
{
int16_t i;
if ((i = GET_U_1(cp)) == 0) {
cp++;
i = GET_BE_S_2(cp);
cp += 2;
}
if (i >= 0)
ND_PRINT(" W+%d", i);
else
ND_PRINT(" W%d", i);
return (cp);
}
static void
compressed_sl_print(netdissect_options *ndo,
const u_char *chdr, const struct ip *ip,
u_int length, int dir)
{
const u_char *cp = chdr;
u_int flags, hlen;
flags = GET_U_1(cp);
cp++;
if (flags & NEW_C) {
lastconn = GET_U_1(cp);
cp++;
ND_PRINT("ctcp %u", lastconn);
} else
ND_PRINT("ctcp *");
/* skip tcp checksum */
cp += 2;
switch (flags & SPECIALS_MASK) {
case SPECIAL_I:
ND_PRINT(" *SA+%u", lastlen[dir][lastconn]);
break;
case SPECIAL_D:
ND_PRINT(" *S+%u", lastlen[dir][lastconn]);
break;
default:
if (flags & NEW_U)
cp = print_sl_change(ndo, "U=", cp);
if (flags & NEW_W)
cp = print_sl_winchange(ndo, cp);
if (flags & NEW_A)
cp = print_sl_change(ndo, "A+", cp);
if (flags & NEW_S)
cp = print_sl_change(ndo, "S+", cp);
break;
}
if (flags & NEW_I)
cp = print_sl_change(ndo, "I+", cp);
/*
* 'hlen' is the length of the uncompressed TCP/IP header (in words).
* 'cp - chdr' is the length of the compressed header.
* 'length - hlen' is the amount of data in the packet.
*/
ND_TCHECK_SIZE(ip);
hlen = IP_HL(ip);
ND_TCHECK_SIZE((const struct tcphdr *)&((const int32_t *)ip)[hlen]);
hlen += TH_OFF((const struct tcphdr *)&((const int32_t *)ip)[hlen]);
lastlen[dir][lastconn] = length - (hlen << 2);
ND_PRINT(" %u (%ld)", lastlen[dir][lastconn], (long)(cp - chdr));
}
diff --git a/contrib/tcpdump/print-sll.c b/contrib/tcpdump/print-sll.c
index eb8d620a448b..de767781e016 100644
--- a/contrib/tcpdump/print-sll.c
+++ b/contrib/tcpdump/print-sll.c
@@ -1,535 +1,533 @@
/*
* Copyright (c) 1988, 1989, 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.
*/
/* \summary: Linux cooked sockets capture printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#ifdef HAVE_NET_IF_H
/*
* Include diag-control.h before <net/if.h>, which too defines a macro
* named ND_UNREACHABLE.
*/
#include "diag-control.h"
#include <net/if.h>
#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "addrtoname.h"
#include "ethertype.h"
#include "extract.h"
/*
* For captures on Linux cooked sockets, we construct a fake header
* that includes:
*
* a 2-byte "packet type" which is one of:
*
* LINUX_SLL_HOST packet was sent to us
* LINUX_SLL_BROADCAST packet was broadcast
* LINUX_SLL_MULTICAST packet was multicast
* LINUX_SLL_OTHERHOST packet was sent to somebody else
* LINUX_SLL_OUTGOING packet was sent *by* us;
*
* a 2-byte Ethernet protocol field;
*
* a 2-byte link-layer type;
*
* a 2-byte link-layer address length;
*
* an 8-byte source link-layer address, whose actual length is
* specified by the previous value.
*
* All fields except for the link-layer address are in network byte order.
*
* DO NOT change the layout of this structure, or change any of the
* LINUX_SLL_ values below. If you must change the link-layer header
* for a "cooked" Linux capture, introduce a new DLT_ type (ask
* "tcpdump-workers@lists.tcpdump.org" for one, so that you don't give it
* a value that collides with a value already being used), and use the
* new header in captures of that type, so that programs that can
* handle DLT_LINUX_SLL captures will continue to handle them correctly
* without any change, and so that capture files with different headers
* can be told apart and programs that read them can dissect the
* packets in them.
*
* This structure, and the #defines below, must be the same in the
* libpcap and tcpdump versions of "sll.h".
*/
/*
* A DLT_LINUX_SLL fake link-layer header.
*/
#define SLL_HDR_LEN 16 /* total header length */
#define SLL_ADDRLEN 8 /* length of address field */
struct sll_header {
nd_uint16_t sll_pkttype; /* packet type */
nd_uint16_t sll_hatype; /* link-layer address type */
nd_uint16_t sll_halen; /* link-layer address length */
nd_byte sll_addr[SLL_ADDRLEN]; /* link-layer address */
nd_uint16_t sll_protocol; /* protocol */
};
/*
* A DLT_LINUX_SLL2 fake link-layer header.
*/
#define SLL2_HDR_LEN 20 /* total header length */
struct sll2_header {
nd_uint16_t sll2_protocol; /* protocol */
nd_uint16_t sll2_reserved_mbz; /* reserved - must be zero */
nd_uint32_t sll2_if_index; /* 1-based interface index */
nd_uint16_t sll2_hatype; /* link-layer address type */
nd_uint8_t sll2_pkttype; /* packet type */
nd_uint8_t sll2_halen; /* link-layer address length */
nd_byte sll2_addr[SLL_ADDRLEN]; /* link-layer address */
};
/*
* The LINUX_SLL_ values for "sll_pkttype"; these correspond to the
* PACKET_ values on Linux, but are defined here so that they're
* available even on systems other than Linux, and so that they
* don't change even if the PACKET_ values change.
*/
#define LINUX_SLL_HOST 0
#define LINUX_SLL_BROADCAST 1
#define LINUX_SLL_MULTICAST 2
#define LINUX_SLL_OTHERHOST 3
#define LINUX_SLL_OUTGOING 4
/*
* The LINUX_SLL_ values for "sll_protocol"; these correspond to the
* ETH_P_ values on Linux, but are defined here so that they're
* available even on systems other than Linux. We assume, for now,
* that the ETH_P_ values won't change in Linux; if they do, then:
*
* if we don't translate them in "pcap-linux.c", capture files
* won't necessarily be readable if captured on a system that
* defines ETH_P_ values that don't match these values;
*
* if we do translate them in "pcap-linux.c", that makes life
* unpleasant for the BPF code generator, as the values you test
* for in the kernel aren't the values that you test for when
* reading a capture file, so the fixup code run on BPF programs
* handed to the kernel ends up having to do more work.
*
* Add other values here as necessary, for handling packet types that
* might show up on non-Ethernet, non-802.x networks. (Not all the ones
* in the Linux "if_ether.h" will, I suspect, actually show up in
* captures.)
*/
#define LINUX_SLL_P_802_3 0x0001 /* Novell 802.3 frames without 802.2 LLC header */
#define LINUX_SLL_P_802_2 0x0004 /* 802.2 frames (not D/I/X Ethernet) */
static const struct tok sll_pkttype_values[] = {
{ LINUX_SLL_HOST, "In" },
{ LINUX_SLL_BROADCAST, "B" },
{ LINUX_SLL_MULTICAST, "M" },
{ LINUX_SLL_OTHERHOST, "P" },
{ LINUX_SLL_OUTGOING, "Out" },
{ 0, NULL}
};
static void
sll_print(netdissect_options *ndo, const struct sll_header *sllp, u_int length)
{
u_short ether_type;
ndo->ndo_protocol = "sll";
ND_PRINT("%3s ",
tok2str(sll_pkttype_values,"?",GET_BE_U_2(sllp->sll_pkttype)));
/*
* XXX - check the link-layer address type value?
* For now, we just assume 6 means Ethernet.
* XXX - print others as strings of hex?
*/
if (GET_BE_U_2(sllp->sll_halen) == MAC_ADDR_LEN)
ND_PRINT("%s ", GET_ETHERADDR_STRING(sllp->sll_addr));
if (!ndo->ndo_qflag) {
ether_type = GET_BE_U_2(sllp->sll_protocol);
if (ether_type <= MAX_ETHERNET_LENGTH_VAL) {
/*
* Not an Ethernet type; what type is it?
*/
switch (ether_type) {
case LINUX_SLL_P_802_3:
/*
* Ethernet_802.3 IPX frame.
*/
ND_PRINT("802.3");
break;
case LINUX_SLL_P_802_2:
/*
* 802.2.
*/
ND_PRINT("802.2");
break;
default:
/*
* What is it?
*/
ND_PRINT("ethertype Unknown (0x%04x)",
ether_type);
break;
}
} else {
ND_PRINT("ethertype %s (0x%04x)",
tok2str(ethertype_values, "Unknown", ether_type),
ether_type);
}
ND_PRINT(", length %u: ", length);
}
}
/*
* This is the top level routine of the printer. 'p' points to the
* Linux "cooked capture" header of the packet, 'h->ts' is the timestamp,
* 'h->len' is the length of the packet off the wire, and 'h->caplen'
* is the number of bytes actually captured.
*/
void
sll_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
{
u_int caplen = h->caplen;
u_int length = h->len;
const struct sll_header *sllp;
u_short hatype;
u_short ether_type;
int llc_hdrlen;
u_int hdrlen;
ndo->ndo_protocol = "sll";
ND_TCHECK_LEN(p, SLL_HDR_LEN);
sllp = (const struct sll_header *)p;
if (ndo->ndo_eflag)
sll_print(ndo, sllp, length);
/*
* Go past the cooked-mode header.
*/
length -= SLL_HDR_LEN;
caplen -= SLL_HDR_LEN;
p += SLL_HDR_LEN;
hdrlen = SLL_HDR_LEN;
hatype = GET_BE_U_2(sllp->sll_hatype);
switch (hatype) {
case 803:
/*
* This is an packet with a radiotap header;
* just dissect the payload as such.
*/
ndo->ndo_ll_hdr_len += SLL_HDR_LEN;
ndo->ndo_ll_hdr_len += ieee802_11_radio_print(ndo, p, length, caplen);
return;
}
ether_type = GET_BE_U_2(sllp->sll_protocol);
recurse:
/*
* Is it (gag) an 802.3 encapsulation, or some non-Ethernet
* packet type?
*/
if (ether_type <= MAX_ETHERNET_LENGTH_VAL) {
/*
* Yes - what type is it?
*/
switch (ether_type) {
case LINUX_SLL_P_802_3:
/*
* Ethernet_802.3 IPX frame.
*/
ipx_print(ndo, p, length);
break;
case LINUX_SLL_P_802_2:
/*
* 802.2.
* Try to print the LLC-layer header & higher layers.
*/
llc_hdrlen = llc_print(ndo, p, length, caplen, NULL, NULL);
if (llc_hdrlen < 0)
goto unknown; /* unknown LLC type */
hdrlen += llc_hdrlen;
break;
default:
/*FALLTHROUGH*/
unknown:
/* packet type not known, print raw packet */
if (!ndo->ndo_suppress_default_print)
ND_DEFAULTPRINT(p, caplen);
break;
}
} else if (ether_type == ETHERTYPE_8021Q) {
/*
* Print VLAN information, and then go back and process
* the enclosed type field.
*/
if (caplen < 4) {
ndo->ndo_protocol = "vlan";
nd_print_trunc(ndo);
ndo->ndo_ll_hdr_len += hdrlen + caplen;
return;
}
if (ndo->ndo_eflag) {
uint16_t tag = GET_BE_U_2(p);
ND_PRINT("%s, ", ieee8021q_tci_string(tag));
}
ether_type = GET_BE_U_2(p + 2);
if (ether_type <= MAX_ETHERNET_LENGTH_VAL)
ether_type = LINUX_SLL_P_802_2;
if (!ndo->ndo_qflag) {
ND_PRINT("ethertype %s, ",
tok2str(ethertype_values, "Unknown", ether_type));
}
p += 4;
length -= 4;
caplen -= 4;
hdrlen += 4;
goto recurse;
} else {
if (ethertype_print(ndo, ether_type, p, length, caplen, NULL, NULL) == 0) {
/* ether_type not known, print raw packet */
if (!ndo->ndo_eflag)
sll_print(ndo, sllp, length + SLL_HDR_LEN);
if (!ndo->ndo_suppress_default_print)
ND_DEFAULTPRINT(p, caplen);
}
}
ndo->ndo_ll_hdr_len += hdrlen;
}
static void
sll2_print(netdissect_options *ndo, const struct sll2_header *sllp, u_int length)
{
u_short ether_type;
ndo->ndo_protocol = "sll2";
ND_PRINT("ifindex %u ", GET_BE_U_4(sllp->sll2_if_index));
/*
* XXX - check the link-layer address type value?
* For now, we just assume 6 means Ethernet.
* XXX - print others as strings of hex?
*/
if (GET_U_1(sllp->sll2_halen) == MAC_ADDR_LEN)
ND_PRINT("%s ", GET_ETHERADDR_STRING(sllp->sll2_addr));
if (!ndo->ndo_qflag) {
ether_type = GET_BE_U_2(sllp->sll2_protocol);
if (ether_type <= MAX_ETHERNET_LENGTH_VAL) {
/*
* Not an Ethernet type; what type is it?
*/
switch (ether_type) {
case LINUX_SLL_P_802_3:
/*
* Ethernet_802.3 IPX frame.
*/
ND_PRINT("802.3");
break;
case LINUX_SLL_P_802_2:
/*
* 802.2.
*/
ND_PRINT("802.2");
break;
default:
/*
* What is it?
*/
ND_PRINT("ethertype Unknown (0x%04x)",
ether_type);
break;
}
} else {
ND_PRINT("ethertype %s (0x%04x)",
tok2str(ethertype_values, "Unknown", ether_type),
ether_type);
}
ND_PRINT(", length %u: ", length);
}
}
/*
* This is the top level routine of the printer. 'p' points to the
* Linux "cooked capture" header of the packet, 'h->ts' is the timestamp,
* 'h->len' is the length of the packet off the wire, and 'h->caplen'
* is the number of bytes actually captured.
*/
void
sll2_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
{
u_int caplen = h->caplen;
u_int length = h->len;
const struct sll2_header *sllp;
u_short hatype;
u_short ether_type;
int llc_hdrlen;
u_int hdrlen;
#ifdef HAVE_NET_IF_H
uint32_t if_index;
char ifname[IF_NAMESIZE];
#endif
ndo->ndo_protocol = "sll2";
ND_TCHECK_LEN(p, SLL2_HDR_LEN);
sllp = (const struct sll2_header *)p;
#ifdef HAVE_NET_IF_H
if_index = GET_BE_U_4(sllp->sll2_if_index);
if (!if_indextoname(if_index, ifname))
strncpy(ifname, "?", 2);
ND_PRINT("%-5s ", ifname);
#endif
ND_PRINT("%-3s ",
tok2str(sll_pkttype_values, "?", GET_U_1(sllp->sll2_pkttype)));
if (ndo->ndo_eflag)
sll2_print(ndo, sllp, length);
/*
* Go past the cooked-mode header.
*/
length -= SLL2_HDR_LEN;
caplen -= SLL2_HDR_LEN;
p += SLL2_HDR_LEN;
hdrlen = SLL2_HDR_LEN;
hatype = GET_BE_U_2(sllp->sll2_hatype);
switch (hatype) {
case 803:
/*
* This is an packet with a radiotap header;
* just dissect the payload as such.
*/
ndo->ndo_ll_hdr_len += SLL2_HDR_LEN;
ndo->ndo_ll_hdr_len += ieee802_11_radio_print(ndo, p, length, caplen);
return;
}
ether_type = GET_BE_U_2(sllp->sll2_protocol);
recurse:
/*
* Is it (gag) an 802.3 encapsulation, or some non-Ethernet
* packet type?
*/
if (ether_type <= MAX_ETHERNET_LENGTH_VAL) {
/*
* Yes - what type is it?
*/
switch (ether_type) {
case LINUX_SLL_P_802_3:
/*
* Ethernet_802.3 IPX frame.
*/
ipx_print(ndo, p, length);
break;
case LINUX_SLL_P_802_2:
/*
* 802.2.
* Try to print the LLC-layer header & higher layers.
*/
llc_hdrlen = llc_print(ndo, p, length, caplen, NULL, NULL);
if (llc_hdrlen < 0)
goto unknown; /* unknown LLC type */
hdrlen += llc_hdrlen;
break;
default:
/*FALLTHROUGH*/
unknown:
/* packet type not known, print raw packet */
if (!ndo->ndo_suppress_default_print)
ND_DEFAULTPRINT(p, caplen);
break;
}
} else if (ether_type == ETHERTYPE_8021Q) {
/*
* Print VLAN information, and then go back and process
* the enclosed type field.
*/
if (caplen < 4) {
ndo->ndo_protocol = "vlan";
nd_print_trunc(ndo);
ndo->ndo_ll_hdr_len += hdrlen + caplen;
return;
}
if (ndo->ndo_eflag) {
uint16_t tag = GET_BE_U_2(p);
ND_PRINT("%s, ", ieee8021q_tci_string(tag));
}
ether_type = GET_BE_U_2(p + 2);
if (ether_type <= MAX_ETHERNET_LENGTH_VAL)
ether_type = LINUX_SLL_P_802_2;
if (!ndo->ndo_qflag) {
ND_PRINT("ethertype %s, ",
tok2str(ethertype_values, "Unknown", ether_type));
}
p += 4;
length -= 4;
caplen -= 4;
hdrlen += 4;
goto recurse;
} else {
if (ethertype_print(ndo, ether_type, p, length, caplen, NULL, NULL) == 0) {
/* ether_type not known, print raw packet */
if (!ndo->ndo_eflag)
sll2_print(ndo, sllp, length + SLL2_HDR_LEN);
if (!ndo->ndo_suppress_default_print)
ND_DEFAULTPRINT(p, caplen);
}
}
ndo->ndo_ll_hdr_len += hdrlen;
}
diff --git a/contrib/tcpdump/print-slow.c b/contrib/tcpdump/print-slow.c
index 118381808fda..72062d930f22 100644
--- a/contrib/tcpdump/print-slow.c
+++ b/contrib/tcpdump/print-slow.c
@@ -1,737 +1,735 @@
/*
* Copyright (c) 1998-2006 The TCPDUMP project
*
* 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.
*
* support for the IEEE "slow protocols" LACP, MARKER as per 802.3ad
* OAM as per 802.3ah
*
* Original code by Hannes Gredler (hannes@gredler.at)
*/
/* \summary: IEEE "slow protocols" (802.3ad/802.3ah) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
#include "addrtoname.h"
#include "oui.h"
#define SLOW_PROTO_LACP 1
#define SLOW_PROTO_MARKER 2
#define SLOW_PROTO_OAM 3
#define LACP_VERSION 1
#define MARKER_VERSION 1
static const struct tok slow_proto_values[] = {
{ SLOW_PROTO_LACP, "LACP" },
{ SLOW_PROTO_MARKER, "MARKER" },
{ SLOW_PROTO_OAM, "OAM" },
{ 0, NULL}
};
static const struct tok slow_oam_flag_values[] = {
{ 0x0001, "Link Fault" },
{ 0x0002, "Dying Gasp" },
{ 0x0004, "Critical Event" },
{ 0x0008, "Local Evaluating" },
{ 0x0010, "Local Stable" },
{ 0x0020, "Remote Evaluating" },
{ 0x0040, "Remote Stable" },
{ 0, NULL}
};
#define SLOW_OAM_CODE_INFO 0x00
#define SLOW_OAM_CODE_EVENT_NOTIF 0x01
#define SLOW_OAM_CODE_VAR_REQUEST 0x02
#define SLOW_OAM_CODE_VAR_RESPONSE 0x03
#define SLOW_OAM_CODE_LOOPBACK_CTRL 0x04
#define SLOW_OAM_CODE_PRIVATE 0xfe
static const struct tok slow_oam_code_values[] = {
{ SLOW_OAM_CODE_INFO, "Information" },
{ SLOW_OAM_CODE_EVENT_NOTIF, "Event Notification" },
{ SLOW_OAM_CODE_VAR_REQUEST, "Variable Request" },
{ SLOW_OAM_CODE_VAR_RESPONSE, "Variable Response" },
{ SLOW_OAM_CODE_LOOPBACK_CTRL, "Loopback Control" },
{ SLOW_OAM_CODE_PRIVATE, "Vendor Private" },
{ 0, NULL}
};
struct slow_oam_info_t {
nd_uint8_t info_type;
nd_uint8_t info_length;
nd_uint8_t oam_version;
nd_uint16_t revision;
nd_uint8_t state;
nd_uint8_t oam_config;
nd_uint16_t oam_pdu_config;
nd_uint24_t oui;
nd_uint32_t vendor_private;
};
#define SLOW_OAM_INFO_TYPE_END_OF_TLV 0x00
#define SLOW_OAM_INFO_TYPE_LOCAL 0x01
#define SLOW_OAM_INFO_TYPE_REMOTE 0x02
#define SLOW_OAM_INFO_TYPE_ORG_SPECIFIC 0xfe
static const struct tok slow_oam_info_type_values[] = {
{ SLOW_OAM_INFO_TYPE_END_OF_TLV, "End of TLV marker" },
{ SLOW_OAM_INFO_TYPE_LOCAL, "Local" },
{ SLOW_OAM_INFO_TYPE_REMOTE, "Remote" },
{ SLOW_OAM_INFO_TYPE_ORG_SPECIFIC, "Organization specific" },
{ 0, NULL}
};
#define OAM_INFO_TYPE_PARSER_MASK 0x3
static const struct tok slow_oam_info_type_state_parser_values[] = {
{ 0x00, "forwarding" },
{ 0x01, "looping back" },
{ 0x02, "discarding" },
{ 0x03, "reserved" },
{ 0, NULL}
};
#define OAM_INFO_TYPE_MUX_MASK 0x4
static const struct tok slow_oam_info_type_state_mux_values[] = {
{ 0x00, "forwarding" },
{ 0x04, "discarding" },
{ 0, NULL}
};
static const struct tok slow_oam_info_type_oam_config_values[] = {
{ 0x01, "Active" },
{ 0x02, "Unidirectional" },
{ 0x04, "Remote-Loopback" },
{ 0x08, "Link-Events" },
{ 0x10, "Variable-Retrieval" },
{ 0, NULL}
};
/* 11 Bits */
#define OAM_INFO_TYPE_PDU_SIZE_MASK 0x7ff
#define SLOW_OAM_LINK_EVENT_END_OF_TLV 0x00
#define SLOW_OAM_LINK_EVENT_ERR_SYM_PER 0x01
#define SLOW_OAM_LINK_EVENT_ERR_FRM 0x02
#define SLOW_OAM_LINK_EVENT_ERR_FRM_PER 0x03
#define SLOW_OAM_LINK_EVENT_ERR_FRM_SUMM 0x04
#define SLOW_OAM_LINK_EVENT_ORG_SPECIFIC 0xfe
static const struct tok slow_oam_link_event_values[] = {
{ SLOW_OAM_LINK_EVENT_END_OF_TLV, "End of TLV marker" },
{ SLOW_OAM_LINK_EVENT_ERR_SYM_PER, "Errored Symbol Period Event" },
{ SLOW_OAM_LINK_EVENT_ERR_FRM, "Errored Frame Event" },
{ SLOW_OAM_LINK_EVENT_ERR_FRM_PER, "Errored Frame Period Event" },
{ SLOW_OAM_LINK_EVENT_ERR_FRM_SUMM, "Errored Frame Seconds Summary Event" },
{ SLOW_OAM_LINK_EVENT_ORG_SPECIFIC, "Organization specific" },
{ 0, NULL}
};
struct slow_oam_link_event_t {
nd_uint8_t event_type;
nd_uint8_t event_length;
nd_uint16_t time_stamp;
nd_uint64_t window;
nd_uint64_t threshold;
nd_uint64_t errors;
nd_uint64_t errors_running_total;
nd_uint32_t event_running_total;
};
struct slow_oam_variablerequest_t {
nd_uint8_t branch;
nd_uint16_t leaf;
};
struct slow_oam_variableresponse_t {
nd_uint8_t branch;
nd_uint16_t leaf;
nd_uint8_t length;
};
struct slow_oam_loopbackctrl_t {
nd_uint8_t command;
};
static const struct tok slow_oam_loopbackctrl_cmd_values[] = {
{ 0x01, "Enable OAM Remote Loopback" },
{ 0x02, "Disable OAM Remote Loopback" },
{ 0, NULL}
};
struct tlv_header_t {
nd_uint8_t type;
nd_uint8_t length;
};
#define LACP_MARKER_TLV_TERMINATOR 0x00 /* same code for LACP and Marker */
#define LACP_TLV_ACTOR_INFO 0x01
#define LACP_TLV_PARTNER_INFO 0x02
#define LACP_TLV_COLLECTOR_INFO 0x03
#define MARKER_TLV_MARKER_INFO 0x01
static const struct tok slow_tlv_values[] = {
{ (SLOW_PROTO_LACP << 8) + LACP_MARKER_TLV_TERMINATOR, "Terminator"},
{ (SLOW_PROTO_LACP << 8) + LACP_TLV_ACTOR_INFO, "Actor Information"},
{ (SLOW_PROTO_LACP << 8) + LACP_TLV_PARTNER_INFO, "Partner Information"},
{ (SLOW_PROTO_LACP << 8) + LACP_TLV_COLLECTOR_INFO, "Collector Information"},
{ (SLOW_PROTO_MARKER << 8) + LACP_MARKER_TLV_TERMINATOR, "Terminator"},
{ (SLOW_PROTO_MARKER << 8) + MARKER_TLV_MARKER_INFO, "Marker Information"},
{ 0, NULL}
};
struct lacp_tlv_actor_partner_info_t {
nd_uint16_t sys_pri;
nd_mac_addr sys;
nd_uint16_t key;
nd_uint16_t port_pri;
nd_uint16_t port;
nd_uint8_t state;
nd_byte pad[3];
};
static const struct tok lacp_tlv_actor_partner_info_state_values[] = {
{ 0x01, "Activity"},
{ 0x02, "Timeout"},
{ 0x04, "Aggregation"},
{ 0x08, "Synchronization"},
{ 0x10, "Collecting"},
{ 0x20, "Distributing"},
{ 0x40, "Default"},
{ 0x80, "Expired"},
{ 0, NULL}
};
struct lacp_tlv_collector_info_t {
nd_uint16_t max_delay;
nd_byte pad[12];
};
struct marker_tlv_marker_info_t {
nd_uint16_t req_port;
nd_mac_addr req_sys;
nd_uint32_t req_trans_id;
nd_byte pad[2];
};
struct lacp_marker_tlv_terminator_t {
nd_byte pad[50];
};
static void slow_marker_lacp_print(netdissect_options *, const u_char *, u_int, u_int);
static void slow_oam_print(netdissect_options *, const u_char *, u_int);
void
slow_print(netdissect_options *ndo,
const u_char *pptr, u_int len)
{
int print_version;
u_int subtype;
ndo->ndo_protocol = "slow";
if (len < 1)
goto tooshort;
subtype = GET_U_1(pptr);
/*
* Sanity checking of the header.
*/
switch (subtype) {
case SLOW_PROTO_LACP:
if (len < 2)
goto tooshort;
if (GET_U_1(pptr + 1) != LACP_VERSION) {
ND_PRINT("LACP version %u packet not supported",
GET_U_1(pptr + 1));
return;
}
print_version = 1;
break;
case SLOW_PROTO_MARKER:
if (len < 2)
goto tooshort;
if (GET_U_1(pptr + 1) != MARKER_VERSION) {
ND_PRINT("MARKER version %u packet not supported",
GET_U_1(pptr + 1));
return;
}
print_version = 1;
break;
case SLOW_PROTO_OAM: /* fall through */
print_version = 0;
break;
default:
/* print basic information and exit */
print_version = -1;
break;
}
if (print_version == 1) {
ND_PRINT("%sv%u, length %u",
tok2str(slow_proto_values, "unknown (%u)", subtype),
GET_U_1((pptr + 1)),
len);
} else {
/* some slow protos don't have a version number in the header */
ND_PRINT("%s, length %u",
tok2str(slow_proto_values, "unknown (%u)", subtype),
len);
}
/* unrecognized subtype */
if (print_version == -1) {
print_unknown_data(ndo, pptr, "\n\t", len);
return;
}
if (!ndo->ndo_vflag)
return;
switch (subtype) {
default: /* should not happen */
break;
case SLOW_PROTO_OAM:
/* skip subtype */
len -= 1;
pptr += 1;
slow_oam_print(ndo, pptr, len);
break;
case SLOW_PROTO_LACP: /* LACP and MARKER share the same semantics */
case SLOW_PROTO_MARKER:
/* skip subtype and version */
len -= 2;
pptr += 2;
slow_marker_lacp_print(ndo, pptr, len, subtype);
break;
}
return;
tooshort:
if (!ndo->ndo_vflag)
ND_PRINT(" (packet is too short)");
else
ND_PRINT("\n\t\t packet is too short");
}
static void
slow_marker_lacp_print(netdissect_options *ndo,
const u_char *tptr, u_int tlen,
u_int proto_subtype)
{
const struct tlv_header_t *tlv_header;
const u_char *tlv_tptr;
u_int tlv_type, tlv_len, tlv_tlen;
union {
const struct lacp_marker_tlv_terminator_t *lacp_marker_tlv_terminator;
const struct lacp_tlv_actor_partner_info_t *lacp_tlv_actor_partner_info;
const struct lacp_tlv_collector_info_t *lacp_tlv_collector_info;
const struct marker_tlv_marker_info_t *marker_tlv_marker_info;
} tlv_ptr;
while(tlen>0) {
/* is the packet big enough to include the tlv header ? */
if (tlen < sizeof(struct tlv_header_t))
goto tooshort;
/* did we capture enough for fully decoding the tlv header ? */
tlv_header = (const struct tlv_header_t *)tptr;
tlv_type = GET_U_1(tlv_header->type);
tlv_len = GET_U_1(tlv_header->length);
ND_PRINT("\n\t%s TLV (0x%02x), length %u",
tok2str(slow_tlv_values,
"Unknown",
(proto_subtype << 8) + tlv_type),
tlv_type,
tlv_len);
if (tlv_type == LACP_MARKER_TLV_TERMINATOR) {
/*
* This TLV has a length of zero, and means there are no
* more TLVs to process.
*/
return;
}
/* length includes the type and length fields */
if (tlv_len < sizeof(struct tlv_header_t)) {
ND_PRINT("\n\t ERROR: illegal length - should be >= %zu",
sizeof(struct tlv_header_t));
return;
}
/* is the packet big enough to include the tlv ? */
if (tlen < tlv_len)
goto tooshort;
/* did we capture enough for fully decoding the tlv ? */
ND_TCHECK_LEN(tptr, tlv_len);
tlv_tptr=tptr+sizeof(struct tlv_header_t);
tlv_tlen=tlv_len-sizeof(struct tlv_header_t);
switch((proto_subtype << 8) + tlv_type) {
/* those two TLVs have the same structure -> fall through */
case ((SLOW_PROTO_LACP << 8) + LACP_TLV_ACTOR_INFO):
case ((SLOW_PROTO_LACP << 8) + LACP_TLV_PARTNER_INFO):
if (tlv_tlen !=
sizeof(struct lacp_tlv_actor_partner_info_t)) {
ND_PRINT("\n\t ERROR: illegal length - should be %zu",
sizeof(struct tlv_header_t) + sizeof(struct lacp_tlv_actor_partner_info_t));
goto badlength;
}
tlv_ptr.lacp_tlv_actor_partner_info = (const struct lacp_tlv_actor_partner_info_t *)tlv_tptr;
ND_PRINT("\n\t System %s, System Priority %u, Key %u"
", Port %u, Port Priority %u\n\t State Flags [%s]",
GET_ETHERADDR_STRING(tlv_ptr.lacp_tlv_actor_partner_info->sys),
GET_BE_U_2(tlv_ptr.lacp_tlv_actor_partner_info->sys_pri),
GET_BE_U_2(tlv_ptr.lacp_tlv_actor_partner_info->key),
GET_BE_U_2(tlv_ptr.lacp_tlv_actor_partner_info->port),
GET_BE_U_2(tlv_ptr.lacp_tlv_actor_partner_info->port_pri),
bittok2str(lacp_tlv_actor_partner_info_state_values,
"none",
GET_U_1(tlv_ptr.lacp_tlv_actor_partner_info->state)));
break;
case ((SLOW_PROTO_LACP << 8) + LACP_TLV_COLLECTOR_INFO):
if (tlv_tlen !=
sizeof(struct lacp_tlv_collector_info_t)) {
ND_PRINT("\n\t ERROR: illegal length - should be %zu",
sizeof(struct tlv_header_t) + sizeof(struct lacp_tlv_collector_info_t));
goto badlength;
}
tlv_ptr.lacp_tlv_collector_info = (const struct lacp_tlv_collector_info_t *)tlv_tptr;
ND_PRINT("\n\t Max Delay %u",
GET_BE_U_2(tlv_ptr.lacp_tlv_collector_info->max_delay));
break;
case ((SLOW_PROTO_MARKER << 8) + MARKER_TLV_MARKER_INFO):
if (tlv_tlen !=
sizeof(struct marker_tlv_marker_info_t)) {
ND_PRINT("\n\t ERROR: illegal length - should be %zu",
sizeof(struct tlv_header_t) + sizeof(struct marker_tlv_marker_info_t));
goto badlength;
}
tlv_ptr.marker_tlv_marker_info = (const struct marker_tlv_marker_info_t *)tlv_tptr;
ND_PRINT("\n\t Request System %s, Request Port %u, Request Transaction ID 0x%08x",
GET_ETHERADDR_STRING(tlv_ptr.marker_tlv_marker_info->req_sys),
GET_BE_U_2(tlv_ptr.marker_tlv_marker_info->req_port),
GET_BE_U_4(tlv_ptr.marker_tlv_marker_info->req_trans_id));
break;
default:
if (ndo->ndo_vflag <= 1)
print_unknown_data(ndo, tlv_tptr, "\n\t ", tlv_tlen);
break;
}
badlength:
/* do we want to see an additional hexdump ? */
if (ndo->ndo_vflag > 1) {
print_unknown_data(ndo, tptr+sizeof(struct tlv_header_t), "\n\t ",
tlv_len-sizeof(struct tlv_header_t));
}
tptr+=tlv_len;
tlen-=tlv_len;
}
return;
tooshort:
ND_PRINT("\n\t\t packet is too short");
}
static void
slow_oam_print(netdissect_options *ndo,
const u_char *tptr, u_int tlen)
{
uint8_t code;
uint8_t type, length;
uint8_t state;
uint8_t command;
u_int hexdump;
struct slow_oam_common_header_t {
nd_uint16_t flags;
nd_uint8_t code;
};
struct slow_oam_tlv_header_t {
nd_uint8_t type;
nd_uint8_t length;
};
union {
const struct slow_oam_common_header_t *slow_oam_common_header;
const struct slow_oam_tlv_header_t *slow_oam_tlv_header;
} ptr;
union {
const struct slow_oam_info_t *slow_oam_info;
const struct slow_oam_link_event_t *slow_oam_link_event;
const struct slow_oam_variablerequest_t *slow_oam_variablerequest;
const struct slow_oam_variableresponse_t *slow_oam_variableresponse;
const struct slow_oam_loopbackctrl_t *slow_oam_loopbackctrl;
} tlv;
ptr.slow_oam_common_header = (const struct slow_oam_common_header_t *)tptr;
if (tlen < sizeof(*ptr.slow_oam_common_header))
goto tooshort;
ND_TCHECK_SIZE(ptr.slow_oam_common_header);
tptr += sizeof(struct slow_oam_common_header_t);
tlen -= sizeof(struct slow_oam_common_header_t);
code = GET_U_1(ptr.slow_oam_common_header->code);
ND_PRINT("\n\tCode %s OAM PDU, Flags [%s]",
tok2str(slow_oam_code_values, "Unknown (%u)", code),
bittok2str(slow_oam_flag_values,
"none",
GET_BE_U_2(ptr.slow_oam_common_header->flags)));
switch (code) {
case SLOW_OAM_CODE_INFO:
while (tlen > 0) {
ptr.slow_oam_tlv_header = (const struct slow_oam_tlv_header_t *)tptr;
if (tlen < sizeof(*ptr.slow_oam_tlv_header))
goto tooshort;
ND_TCHECK_SIZE(ptr.slow_oam_tlv_header);
type = GET_U_1(ptr.slow_oam_tlv_header->type);
length = GET_U_1(ptr.slow_oam_tlv_header->length);
ND_PRINT("\n\t %s Information Type (%u), length %u",
tok2str(slow_oam_info_type_values, "Reserved", type),
type,
length);
if (type == SLOW_OAM_INFO_TYPE_END_OF_TLV) {
/*
* As IEEE Std 802.3-2015 says for the End of TLV Marker,
* "(the length and value of the Type 0x00 TLV can be ignored)".
*/
return;
}
/* length includes the type and length fields */
if (length < sizeof(struct slow_oam_tlv_header_t)) {
ND_PRINT("\n\t ERROR: illegal length - should be >= %zu",
sizeof(struct slow_oam_tlv_header_t));
return;
}
if (tlen < length)
goto tooshort;
ND_TCHECK_LEN(tptr, length);
hexdump = FALSE;
switch (type) {
case SLOW_OAM_INFO_TYPE_LOCAL: /* identical format - fall through */
case SLOW_OAM_INFO_TYPE_REMOTE:
tlv.slow_oam_info = (const struct slow_oam_info_t *)tptr;
if (GET_U_1(tlv.slow_oam_info->info_length) !=
sizeof(struct slow_oam_info_t)) {
ND_PRINT("\n\t ERROR: illegal length - should be %zu",
sizeof(struct slow_oam_info_t));
hexdump = TRUE;
goto badlength_code_info;
}
ND_PRINT("\n\t OAM-Version %u, Revision %u",
GET_U_1(tlv.slow_oam_info->oam_version),
GET_BE_U_2(tlv.slow_oam_info->revision));
state = GET_U_1(tlv.slow_oam_info->state);
ND_PRINT("\n\t State-Parser-Action %s, State-MUX-Action %s",
tok2str(slow_oam_info_type_state_parser_values, "Reserved",
state & OAM_INFO_TYPE_PARSER_MASK),
tok2str(slow_oam_info_type_state_mux_values, "Reserved",
state & OAM_INFO_TYPE_MUX_MASK));
ND_PRINT("\n\t OAM-Config Flags [%s], OAM-PDU-Config max-PDU size %u",
bittok2str(slow_oam_info_type_oam_config_values, "none",
GET_U_1(tlv.slow_oam_info->oam_config)),
GET_BE_U_2(tlv.slow_oam_info->oam_pdu_config) &
OAM_INFO_TYPE_PDU_SIZE_MASK);
ND_PRINT("\n\t OUI %s (0x%06x), Vendor-Private 0x%08x",
tok2str(oui_values, "Unknown",
GET_BE_U_3(tlv.slow_oam_info->oui)),
GET_BE_U_3(tlv.slow_oam_info->oui),
GET_BE_U_4(tlv.slow_oam_info->vendor_private));
break;
case SLOW_OAM_INFO_TYPE_ORG_SPECIFIC:
hexdump = TRUE;
break;
default:
hexdump = TRUE;
break;
}
badlength_code_info:
/* do we also want to see a hex dump ? */
if (ndo->ndo_vflag > 1 || hexdump==TRUE) {
print_unknown_data(ndo, tptr, "\n\t ",
length);
}
tlen -= length;
tptr += length;
}
break;
case SLOW_OAM_CODE_EVENT_NOTIF:
/* Sequence number */
if (tlen < 2)
goto tooshort;
ND_PRINT("\n\t Sequence Number %u", GET_BE_U_2(tptr));
tlen -= 2;
tptr += 2;
/* TLVs */
while (tlen > 0) {
ptr.slow_oam_tlv_header = (const struct slow_oam_tlv_header_t *)tptr;
if (tlen < sizeof(*ptr.slow_oam_tlv_header))
goto tooshort;
type = GET_U_1(ptr.slow_oam_tlv_header->type);
length = GET_U_1(ptr.slow_oam_tlv_header->length);
ND_PRINT("\n\t %s Link Event Type (%u), length %u",
tok2str(slow_oam_link_event_values, "Reserved",
type),
type,
length);
if (type == SLOW_OAM_INFO_TYPE_END_OF_TLV) {
/*
* As IEEE Std 802.3-2015 says for the End of TLV Marker,
* "(the length and value of the Type 0x00 TLV can be ignored)".
*/
return;
}
/* length includes the type and length fields */
if (length < sizeof(struct slow_oam_tlv_header_t)) {
ND_PRINT("\n\t ERROR: illegal length - should be >= %zu",
sizeof(struct slow_oam_tlv_header_t));
return;
}
if (tlen < length)
goto tooshort;
ND_TCHECK_LEN(tptr, length);
hexdump = FALSE;
switch (type) {
case SLOW_OAM_LINK_EVENT_ERR_SYM_PER: /* identical format - fall through */
case SLOW_OAM_LINK_EVENT_ERR_FRM:
case SLOW_OAM_LINK_EVENT_ERR_FRM_PER:
case SLOW_OAM_LINK_EVENT_ERR_FRM_SUMM:
tlv.slow_oam_link_event = (const struct slow_oam_link_event_t *)tptr;
if (GET_U_1(tlv.slow_oam_link_event->event_length) !=
sizeof(struct slow_oam_link_event_t)) {
ND_PRINT("\n\t ERROR: illegal length - should be %zu",
sizeof(struct slow_oam_link_event_t));
hexdump = TRUE;
goto badlength_event_notif;
}
ND_PRINT("\n\t Timestamp %u ms, Errored Window %" PRIu64
"\n\t Errored Threshold %" PRIu64
"\n\t Errors %" PRIu64
"\n\t Error Running Total %" PRIu64
"\n\t Event Running Total %u",
GET_BE_U_2(tlv.slow_oam_link_event->time_stamp)*100,
GET_BE_U_8(tlv.slow_oam_link_event->window),
GET_BE_U_8(tlv.slow_oam_link_event->threshold),
GET_BE_U_8(tlv.slow_oam_link_event->errors),
GET_BE_U_8(tlv.slow_oam_link_event->errors_running_total),
GET_BE_U_4(tlv.slow_oam_link_event->event_running_total));
break;
case SLOW_OAM_LINK_EVENT_ORG_SPECIFIC:
hexdump = TRUE;
break;
default:
hexdump = TRUE;
break;
}
badlength_event_notif:
/* do we also want to see a hex dump ? */
if (ndo->ndo_vflag > 1 || hexdump==TRUE) {
print_unknown_data(ndo, tptr, "\n\t ",
length);
}
tlen -= length;
tptr += length;
}
break;
case SLOW_OAM_CODE_LOOPBACK_CTRL:
tlv.slow_oam_loopbackctrl = (const struct slow_oam_loopbackctrl_t *)tptr;
if (tlen < sizeof(*tlv.slow_oam_loopbackctrl))
goto tooshort;
command = GET_U_1(tlv.slow_oam_loopbackctrl->command);
ND_PRINT("\n\t Command %s (%u)",
tok2str(slow_oam_loopbackctrl_cmd_values,
"Unknown",
command),
command);
tptr ++;
tlen --;
break;
/*
* FIXME those are the defined codes that lack a decoder
* you are welcome to contribute code ;-)
*/
case SLOW_OAM_CODE_VAR_REQUEST:
case SLOW_OAM_CODE_VAR_RESPONSE:
case SLOW_OAM_CODE_PRIVATE:
default:
if (ndo->ndo_vflag <= 1) {
print_unknown_data(ndo, tptr, "\n\t ", tlen);
}
break;
}
return;
tooshort:
ND_PRINT("\n\t\t packet is too short");
}
diff --git a/contrib/tcpdump/print-smb.c b/contrib/tcpdump/print-smb.c
index bcd7363dec95..46dd2ef37360 100644
--- a/contrib/tcpdump/print-smb.c
+++ b/contrib/tcpdump/print-smb.c
@@ -1,1476 +1,1478 @@
/*
* Copyright (C) Andrew Tridgell 1995-1999
*
* This software may be distributed either under the terms of the
* BSD-style license that accompanies tcpdump or the GNU GPL version 2
* or later
*/
/* \summary: SMB/CIFS printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <string.h>
#include "netdissect.h"
#include "extract.h"
#include "smb.h"
static int request = 0;
static int unicodestr = 0;
extern const u_char *startbuf;
const u_char *startbuf = NULL;
struct smbdescript {
const char *req_f1;
const char *req_f2;
const char *rep_f1;
const char *rep_f2;
void (*fn)(netdissect_options *, const u_char *, const u_char *, const u_char *, const u_char *);
};
struct smbdescriptint {
const char *req_f1;
const char *req_f2;
const char *rep_f1;
const char *rep_f2;
void (*fn)(netdissect_options *, const u_char *, const u_char *, u_int, u_int);
};
struct smbfns
{
int id;
const char *name;
int flags;
struct smbdescript descript;
};
struct smbfnsint
{
int id;
const char *name;
int flags;
struct smbdescriptint descript;
};
#define DEFDESCRIPT { NULL, NULL, NULL, NULL, NULL }
#define FLG_CHAIN (1 << 0)
static const struct smbfns *
smbfind(int id, const struct smbfns *list)
{
int sindex;
for (sindex = 0; list[sindex].name; sindex++)
if (list[sindex].id == id)
return(&list[sindex]);
return(&list[0]);
}
static const struct smbfnsint *
smbfindint(int id, const struct smbfnsint *list)
{
int sindex;
for (sindex = 0; list[sindex].name; sindex++)
if (list[sindex].id == id)
return(&list[sindex]);
return(&list[0]);
}
static void
trans2_findfirst(netdissect_options *ndo,
const u_char *param, const u_char *data, u_int pcnt, u_int dcnt)
{
const char *fmt;
if (request)
fmt = "Attribute=[A]\nSearchCount=[u]\nFlags=[w]\nLevel=[uP4]\nFile=[S]\n";
else
fmt = "Handle=[w]\nCount=[u]\nEOS=[w]\nEoffset=[u]\nLastNameOfs=[w]\n";
smb_fdata(ndo, param, fmt, param + pcnt, unicodestr);
if (dcnt) {
ND_PRINT("data:\n");
smb_data_print(ndo, data, dcnt);
}
}
static void
trans2_qfsinfo(netdissect_options *ndo,
const u_char *param, const u_char *data, u_int pcnt, u_int dcnt)
{
static u_int level = 0;
const char *fmt="";
if (request) {
level = GET_LE_U_2(param);
fmt = "InfoLevel=[u]\n";
smb_fdata(ndo, param, fmt, param + pcnt, unicodestr);
} else {
switch (level) {
case 1:
fmt = "idFileSystem=[W]\nSectorUnit=[U]\nUnit=[U]\nAvail=[U]\nSectorSize=[u]\n";
break;
case 2:
fmt = "CreationTime=[T2]VolNameLength=[lb]\nVolumeLabel=[c]\n";
break;
case 0x105:
fmt = "Capabilities=[W]\nMaxFileLen=[U]\nVolNameLen=[lU]\nVolume=[C]\n";
break;
default:
fmt = "UnknownLevel\n";
break;
}
smb_fdata(ndo, data, fmt, data + dcnt, unicodestr);
}
if (dcnt) {
ND_PRINT("data:\n");
smb_data_print(ndo, data, dcnt);
}
}
static const struct smbfnsint trans2_fns[] = {
{ 0, "TRANSACT2_OPEN", 0,
{ "Flags2=[w]\nMode=[w]\nSearchAttrib=[A]\nAttrib=[A]\nTime=[T2]\nOFun=[w]\nSize=[U]\nRes=([w, w, w, w, w])\nPath=[S]",
NULL,
"Handle=[u]\nAttrib=[A]\nTime=[T2]\nSize=[U]\nAccess=[w]\nType=[w]\nState=[w]\nAction=[w]\nInode=[W]\nOffErr=[u]\n|EALength=[u]\n",
NULL, NULL }},
{ 1, "TRANSACT2_FINDFIRST", 0,
{ NULL, NULL, NULL, NULL, trans2_findfirst }},
{ 2, "TRANSACT2_FINDNEXT", 0, DEFDESCRIPT },
{ 3, "TRANSACT2_QFSINFO", 0,
{ NULL, NULL, NULL, NULL, trans2_qfsinfo }},
{ 4, "TRANSACT2_SETFSINFO", 0, DEFDESCRIPT },
{ 5, "TRANSACT2_QPATHINFO", 0, DEFDESCRIPT },
{ 6, "TRANSACT2_SETPATHINFO", 0, DEFDESCRIPT },
{ 7, "TRANSACT2_QFILEINFO", 0, DEFDESCRIPT },
{ 8, "TRANSACT2_SETFILEINFO", 0, DEFDESCRIPT },
{ 9, "TRANSACT2_FSCTL", 0, DEFDESCRIPT },
{ 10, "TRANSACT2_IOCTL", 0, DEFDESCRIPT },
{ 11, "TRANSACT2_FINDNOTIFYFIRST", 0, DEFDESCRIPT },
{ 12, "TRANSACT2_FINDNOTIFYNEXT", 0, DEFDESCRIPT },
{ 13, "TRANSACT2_MKDIR", 0, DEFDESCRIPT },
{ -1, NULL, 0, DEFDESCRIPT }
};
static void
print_trans2(netdissect_options *ndo,
const u_char *words, const u_char *dat, const u_char *buf, const u_char *maxbuf)
{
u_int bcc;
static const struct smbfnsint *fn = &trans2_fns[0];
const u_char *data, *param;
const u_char *w = words + 1;
const char *f1 = NULL, *f2 = NULL;
u_int pcnt, dcnt;
ND_TCHECK_1(words);
if (request) {
ND_TCHECK_2(w + (14 * 2));
pcnt = GET_LE_U_2(w + 9 * 2);
param = buf + GET_LE_U_2(w + 10 * 2);
dcnt = GET_LE_U_2(w + 11 * 2);
data = buf + GET_LE_U_2(w + 12 * 2);
fn = smbfindint(GET_LE_U_2(w + 14 * 2), trans2_fns);
} else {
if (GET_U_1(words) == 0) {
ND_PRINT("%s\n", fn->name);
ND_PRINT("Trans2Interim\n");
return;
}
ND_TCHECK_2(w + (7 * 2));
pcnt = GET_LE_U_2(w + 3 * 2);
param = buf + GET_LE_U_2(w + 4 * 2);
dcnt = GET_LE_U_2(w + 6 * 2);
data = buf + GET_LE_U_2(w + 7 * 2);
}
ND_PRINT("%s param_length=%u data_length=%u\n", fn->name, pcnt, dcnt);
if (request) {
if (GET_U_1(words) == 8) {
smb_fdata(ndo, words + 1,
"Trans2Secondary\nTotParam=[u]\nTotData=[u]\nParamCnt=[u]\nParamOff=[u]\nParamDisp=[u]\nDataCnt=[u]\nDataOff=[u]\nDataDisp=[u]\nHandle=[u]\n",
maxbuf, unicodestr);
return;
} else {
smb_fdata(ndo, words + 1,
"TotParam=[u]\nTotData=[u]\nMaxParam=[u]\nMaxData=[u]\nMaxSetup=[b][P1]\nFlags=[w]\nTimeOut=[D]\nRes1=[w]\nParamCnt=[u]\nParamOff=[u]\nDataCnt=[u]\nDataOff=[u]\nSetupCnt=[b][P1]\n",
words + 1 + 14 * 2, unicodestr);
}
f1 = fn->descript.req_f1;
f2 = fn->descript.req_f2;
} else {
smb_fdata(ndo, words + 1,
"TotParam=[u]\nTotData=[u]\nRes1=[w]\nParamCnt=[u]\nParamOff=[u]\nParamDisp[u]\nDataCnt=[u]\nDataOff=[u]\nDataDisp=[u]\nSetupCnt=[b][P1]\n",
words + 1 + 10 * 2, unicodestr);
f1 = fn->descript.rep_f1;
f2 = fn->descript.rep_f2;
}
bcc = GET_LE_U_2(dat);
ND_PRINT("smb_bcc=%u\n", bcc);
if (fn->descript.fn)
(*fn->descript.fn)(ndo, param, data, pcnt, dcnt);
else {
smb_fdata(ndo, param, f1 ? f1 : "Parameters=\n", param + pcnt, unicodestr);
smb_fdata(ndo, data, f2 ? f2 : "Data=\n", data + dcnt, unicodestr);
}
return;
trunc:
nd_print_trunc(ndo);
}
static void
print_browse(netdissect_options *ndo,
const u_char *param, u_int paramlen, const u_char *data, u_int datalen)
{
const u_char *maxbuf = data + datalen;
u_int command;
command = GET_U_1(data);
smb_fdata(ndo, param, "BROWSE PACKET\n|Param ", param+paramlen, unicodestr);
switch (command) {
case 0xF:
data = smb_fdata(ndo, data,
"BROWSE PACKET:\nType=[B] (LocalMasterAnnouncement)\nUpdateCount=[w]\nRes1=[B]\nAnnounceInterval=[u]\nName=[n2]\nMajorVersion=[B]\nMinorVersion=[B]\nServerType=[W]\nElectionVersion=[w]\nBrowserConstant=[w]\n",
maxbuf, unicodestr);
break;
case 0x1:
data = smb_fdata(ndo, data,
"BROWSE PACKET:\nType=[B] (HostAnnouncement)\nUpdateCount=[w]\nRes1=[B]\nAnnounceInterval=[u]\nName=[n2]\nMajorVersion=[B]\nMinorVersion=[B]\nServerType=[W]\nElectionVersion=[w]\nBrowserConstant=[w]\n",
maxbuf, unicodestr);
break;
case 0x2:
data = smb_fdata(ndo, data,
"BROWSE PACKET:\nType=[B] (AnnouncementRequest)\nFlags=[B]\nReplySystemName=[S]\n",
maxbuf, unicodestr);
break;
case 0xc:
data = smb_fdata(ndo, data,
"BROWSE PACKET:\nType=[B] (WorkgroupAnnouncement)\nUpdateCount=[w]\nRes1=[B]\nAnnounceInterval=[u]\nName=[n2]\nMajorVersion=[B]\nMinorVersion=[B]\nServerType=[W]\nCommentPointer=[W]\nServerName=[S]\n",
maxbuf, unicodestr);
break;
case 0x8:
data = smb_fdata(ndo, data,
"BROWSE PACKET:\nType=[B] (ElectionFrame)\nElectionVersion=[B]\nOSSummary=[W]\nUptime=[(W, W)]\nServerName=[S]\n",
maxbuf, unicodestr);
break;
case 0xb:
data = smb_fdata(ndo, data,
"BROWSE PACKET:\nType=[B] (BecomeBackupBrowser)\nName=[S]\n",
maxbuf, unicodestr);
break;
case 0x9:
data = smb_fdata(ndo, data,
"BROWSE PACKET:\nType=[B] (GetBackupList)\nListCount?=[B]\nToken=[W]\n",
maxbuf, unicodestr);
break;
case 0xa:
data = smb_fdata(ndo, data,
"BROWSE PACKET:\nType=[B] (BackupListResponse)\nServerCount?=[B]\nToken=[W]\n*Name=[S]\n",
maxbuf, unicodestr);
break;
case 0xd:
data = smb_fdata(ndo, data,
"BROWSE PACKET:\nType=[B] (MasterAnnouncement)\nMasterName=[S]\n",
maxbuf, unicodestr);
break;
case 0xe:
data = smb_fdata(ndo, data,
"BROWSE PACKET:\nType=[B] (ResetBrowser)\nOptions=[B]\n", maxbuf, unicodestr);
break;
default:
data = smb_fdata(ndo, data, "Unknown Browser Frame ", maxbuf, unicodestr);
break;
}
}
static void
print_ipc(netdissect_options *ndo,
const u_char *param, u_int paramlen, const u_char *data, u_int datalen)
{
if (paramlen)
smb_fdata(ndo, param, "Command=[w]\nStr1=[S]\nStr2=[S]\n", param + paramlen,
unicodestr);
if (datalen)
smb_fdata(ndo, data, "IPC ", data + datalen, unicodestr);
}
static void
print_trans(netdissect_options *ndo,
const u_char *words, const u_char *data1, const u_char *buf, const u_char *maxbuf)
{
u_int bcc;
const char *f1, *f2, *f3, *f4;
const u_char *data, *param;
const u_char *w = words + 1;
u_int datalen, paramlen;
if (request) {
ND_TCHECK_2(w + (12 * 2));
paramlen = GET_LE_U_2(w + 9 * 2);
param = buf + GET_LE_U_2(w + 10 * 2);
datalen = GET_LE_U_2(w + 11 * 2);
data = buf + GET_LE_U_2(w + 12 * 2);
f1 = "TotParamCnt=[u]\nTotDataCnt=[u]\nMaxParmCnt=[u]\nMaxDataCnt=[u]\nMaxSCnt=[u]\nTransFlags=[w]\nRes1=[w]\nRes2=[w]\nRes3=[w]\nParamCnt=[u]\nParamOff=[u]\nDataCnt=[u]\nDataOff=[u]\nSUCnt=[u]\n";
f2 = "|Name=[S]\n";
f3 = "|Param ";
f4 = "|Data ";
} else {
ND_TCHECK_2(w + (7 * 2));
paramlen = GET_LE_U_2(w + 3 * 2);
param = buf + GET_LE_U_2(w + 4 * 2);
datalen = GET_LE_U_2(w + 6 * 2);
data = buf + GET_LE_U_2(w + 7 * 2);
f1 = "TotParamCnt=[u]\nTotDataCnt=[u]\nRes1=[u]\nParamCnt=[u]\nParamOff=[u]\nRes2=[u]\nDataCnt=[u]\nDataOff=[u]\nRes3=[u]\nLsetup=[u]\n";
f2 = "|Unknown ";
f3 = "|Param ";
f4 = "|Data ";
}
smb_fdata(ndo, words + 1, f1,
ND_MIN(words + 1 + 2 * GET_U_1(words), maxbuf),
unicodestr);
bcc = GET_LE_U_2(data1);
ND_PRINT("smb_bcc=%u\n", bcc);
if (bcc > 0) {
smb_fdata(ndo, data1 + 2, f2, maxbuf - (paramlen + datalen), unicodestr);
#define MAILSLOT_BROWSE_STR "\\MAILSLOT\\BROWSE"
ND_TCHECK_LEN(data1 + 2, strlen(MAILSLOT_BROWSE_STR) + 1);
if (strcmp((const char *)(data1 + 2), MAILSLOT_BROWSE_STR) == 0) {
print_browse(ndo, param, paramlen, data, datalen);
return;
}
#undef MAILSLOT_BROWSE_STR
#define PIPE_LANMAN_STR "\\PIPE\\LANMAN"
ND_TCHECK_LEN(data1 + 2, strlen(PIPE_LANMAN_STR) + 1);
if (strcmp((const char *)(data1 + 2), PIPE_LANMAN_STR) == 0) {
print_ipc(ndo, param, paramlen, data, datalen);
return;
}
#undef PIPE_LANMAN_STR
if (paramlen)
smb_fdata(ndo, param, f3, ND_MIN(param + paramlen, maxbuf), unicodestr);
if (datalen)
smb_fdata(ndo, data, f4, ND_MIN(data + datalen, maxbuf), unicodestr);
}
return;
trunc:
nd_print_trunc(ndo);
}
static void
print_negprot(netdissect_options *ndo,
const u_char *words, const u_char *data, const u_char *buf _U_, const u_char *maxbuf)
{
u_int wct, bcc;
const char *f1 = NULL, *f2 = NULL;
wct = GET_U_1(words);
if (request)
f2 = "*|Dialect=[Y]\n";
else {
if (wct == 1)
f1 = "Core Protocol\nDialectIndex=[u]";
else if (wct == 17)
f1 = "NT1 Protocol\nDialectIndex=[u]\nSecMode=[B]\nMaxMux=[u]\nNumVcs=[u]\nMaxBuffer=[U]\nRawSize=[U]\nSessionKey=[W]\nCapabilities=[W]\nServerTime=[T3]TimeZone=[u]\nCryptKey=";
else if (wct == 13)
f1 = "Coreplus/Lanman1/Lanman2 Protocol\nDialectIndex=[u]\nSecMode=[w]\nMaxXMit=[u]\nMaxMux=[u]\nMaxVcs=[u]\nBlkMode=[w]\nSessionKey=[W]\nServerTime=[T1]TimeZone=[u]\nRes=[W]\nCryptKey=";
}
if (f1)
smb_fdata(ndo, words + 1, f1, ND_MIN(words + 1 + wct * 2, maxbuf),
unicodestr);
else
- smb_data_print(ndo, words + 1, ND_MIN(wct * 2, ND_BYTES_BETWEEN(maxbuf, words + 1)));
+ smb_data_print(ndo, words + 1,
+ ND_MIN(wct * 2, ND_BYTES_BETWEEN(words + 1, maxbuf)));
bcc = GET_LE_U_2(data);
ND_PRINT("smb_bcc=%u\n", bcc);
if (bcc > 0) {
if (f2)
smb_fdata(ndo, data + 2, f2, ND_MIN(data + 2 + GET_LE_U_2(data),
maxbuf), unicodestr);
else
smb_data_print(ndo, data + 2,
- ND_MIN(GET_LE_U_2(data), ND_BYTES_BETWEEN(maxbuf, data + 2)));
+ ND_MIN(GET_LE_U_2(data), ND_BYTES_BETWEEN(data + 2, maxbuf)));
}
}
static void
print_sesssetup(netdissect_options *ndo,
const u_char *words, const u_char *data, const u_char *buf _U_, const u_char *maxbuf)
{
u_int wct, bcc;
const char *f1 = NULL, *f2 = NULL;
wct = GET_U_1(words);
if (request) {
if (wct == 10)
f1 = "Com2=[w]\nOff2=[u]\nBufSize=[u]\nMpxMax=[u]\nVcNum=[u]\nSessionKey=[W]\nPassLen=[u]\nCryptLen=[u]\nCryptOff=[u]\nPass&Name=\n";
else
f1 = "Com2=[B]\nRes1=[B]\nOff2=[u]\nMaxBuffer=[u]\nMaxMpx=[u]\nVcNumber=[u]\nSessionKey=[W]\nCaseInsensitivePasswordLength=[u]\nCaseSensitivePasswordLength=[u]\nRes=[W]\nCapabilities=[W]\nPass1&Pass2&Account&Domain&OS&LanMan=\n";
} else {
if (wct == 3) {
f1 = "Com2=[w]\nOff2=[u]\nAction=[w]\n";
} else if (wct == 13) {
f1 = "Com2=[B]\nRes=[B]\nOff2=[u]\nAction=[w]\n";
f2 = "NativeOS=[S]\nNativeLanMan=[S]\nPrimaryDomain=[S]\n";
}
}
if (f1)
smb_fdata(ndo, words + 1, f1, ND_MIN(words + 1 + wct * 2, maxbuf),
unicodestr);
else
- smb_data_print(ndo, words + 1, ND_MIN(wct * 2, ND_BYTES_BETWEEN(maxbuf, words + 1)));
+ smb_data_print(ndo, words + 1,
+ ND_MIN(wct * 2, ND_BYTES_BETWEEN(words + 1, maxbuf)));
bcc = GET_LE_U_2(data);
ND_PRINT("smb_bcc=%u\n", bcc);
if (bcc > 0) {
if (f2)
smb_fdata(ndo, data + 2, f2, ND_MIN(data + 2 + GET_LE_U_2(data),
maxbuf), unicodestr);
else
smb_data_print(ndo, data + 2,
- ND_MIN(GET_LE_U_2(data), ND_BYTES_BETWEEN(maxbuf, data + 2)));
+ ND_MIN(GET_LE_U_2(data), ND_BYTES_BETWEEN(data + 2, maxbuf)));
}
}
static void
print_lockingandx(netdissect_options *ndo,
const u_char *words, const u_char *data, const u_char *buf _U_, const u_char *maxbuf)
{
u_int wct, bcc;
const u_char *maxwords;
const char *f1 = NULL, *f2 = NULL;
wct = GET_U_1(words);
if (request) {
f1 = "Com2=[w]\nOff2=[u]\nHandle=[u]\nLockType=[w]\nTimeOut=[D]\nUnlockCount=[u]\nLockCount=[u]\n";
if (GET_U_1(words + 7) & 0x10)
f2 = "*Process=[u]\n[P2]Offset=[M]\nLength=[M]\n";
else
f2 = "*Process=[u]\nOffset=[D]\nLength=[U]\n";
} else {
f1 = "Com2=[w]\nOff2=[u]\n";
}
maxwords = ND_MIN(words + 1 + wct * 2, maxbuf);
if (wct)
smb_fdata(ndo, words + 1, f1, maxwords, unicodestr);
bcc = GET_LE_U_2(data);
ND_PRINT("smb_bcc=%u\n", bcc);
if (bcc > 0) {
if (f2)
smb_fdata(ndo, data + 2, f2, ND_MIN(data + 2 + GET_LE_U_2(data),
maxbuf), unicodestr);
else
smb_data_print(ndo, data + 2,
- ND_MIN(GET_LE_U_2(data), ND_BYTES_BETWEEN(maxbuf, data + 2)));
+ ND_MIN(GET_LE_U_2(data), ND_BYTES_BETWEEN(data + 2, maxbuf)));
}
}
static const struct smbfns smb_fns[] = {
{ -1, "SMBunknown", 0, DEFDESCRIPT },
{ SMBtcon, "SMBtcon", 0,
{ NULL, "Path=[Z]\nPassword=[Z]\nDevice=[Z]\n",
"MaxXmit=[u]\nTreeId=[u]\n", NULL,
NULL } },
{ SMBtdis, "SMBtdis", 0, DEFDESCRIPT },
{ SMBexit, "SMBexit", 0, DEFDESCRIPT },
{ SMBioctl, "SMBioctl", 0, DEFDESCRIPT },
{ SMBecho, "SMBecho", 0,
{ "ReverbCount=[u]\n", NULL,
"SequenceNum=[u]\n", NULL,
NULL } },
{ SMBulogoffX, "SMBulogoffX", FLG_CHAIN, DEFDESCRIPT },
{ SMBgetatr, "SMBgetatr", 0,
{ NULL, "Path=[Z]\n",
"Attribute=[A]\nTime=[T2]Size=[U]\nRes=([w,w,w,w,w])\n", NULL,
NULL } },
{ SMBsetatr, "SMBsetatr", 0,
{ "Attribute=[A]\nTime=[T2]Res=([w,w,w,w,w])\n", "Path=[Z]\n",
NULL, NULL, NULL } },
{ SMBchkpth, "SMBchkpth", 0,
{ NULL, "Path=[Z]\n", NULL, NULL, NULL } },
{ SMBsearch, "SMBsearch", 0,
{ "Count=[u]\nAttrib=[A]\n",
"Path=[Z]\nBlkType=[B]\nBlkLen=[u]\n|Res1=[B]\nMask=[s11]\nSrv1=[B]\nDirIndex=[u]\nSrv2=[w]\nRes2=[W]\n",
"Count=[u]\n",
"BlkType=[B]\nBlkLen=[u]\n*\nRes1=[B]\nMask=[s11]\nSrv1=[B]\nDirIndex=[u]\nSrv2=[w]\nRes2=[W]\nAttrib=[a]\nTime=[T1]Size=[U]\nName=[s13]\n",
NULL } },
{ SMBopen, "SMBopen", 0,
{ "Mode=[w]\nAttribute=[A]\n", "Path=[Z]\n",
"Handle=[u]\nOAttrib=[A]\nTime=[T2]Size=[U]\nAccess=[w]\n",
NULL, NULL } },
{ SMBcreate, "SMBcreate", 0,
{ "Attrib=[A]\nTime=[T2]", "Path=[Z]\n", "Handle=[u]\n", NULL, NULL } },
{ SMBmknew, "SMBmknew", 0,
{ "Attrib=[A]\nTime=[T2]", "Path=[Z]\n", "Handle=[u]\n", NULL, NULL } },
{ SMBunlink, "SMBunlink", 0,
{ "Attrib=[A]\n", "Path=[Z]\n", NULL, NULL, NULL } },
{ SMBread, "SMBread", 0,
{ "Handle=[u]\nByteCount=[u]\nOffset=[D]\nCountLeft=[u]\n", NULL,
"Count=[u]\nRes=([w,w,w,w])\n", NULL, NULL } },
{ SMBwrite, "SMBwrite", 0,
{ "Handle=[u]\nByteCount=[u]\nOffset=[D]\nCountLeft=[u]\n", NULL,
"Count=[u]\n", NULL, NULL } },
{ SMBclose, "SMBclose", 0,
{ "Handle=[u]\nTime=[T2]", NULL, NULL, NULL, NULL } },
{ SMBmkdir, "SMBmkdir", 0,
{ NULL, "Path=[Z]\n", NULL, NULL, NULL } },
{ SMBrmdir, "SMBrmdir", 0,
{ NULL, "Path=[Z]\n", NULL, NULL, NULL } },
{ SMBdskattr, "SMBdskattr", 0,
{ NULL, NULL,
"TotalUnits=[u]\nBlocksPerUnit=[u]\nBlockSize=[u]\nFreeUnits=[u]\nMedia=[w]\n",
NULL, NULL } },
{ SMBmv, "SMBmv", 0,
{ "Attrib=[A]\n", "OldPath=[Z]\nNewPath=[Z]\n", NULL, NULL, NULL } },
/*
* this is a Pathworks specific call, allowing the
* changing of the root path
*/
{ pSETDIR, "SMBsetdir", 0, { NULL, "Path=[Z]\n", NULL, NULL, NULL } },
{ SMBlseek, "SMBlseek", 0,
{ "Handle=[u]\nMode=[w]\nOffset=[D]\n", "Offset=[D]\n", NULL, NULL, NULL } },
{ SMBflush, "SMBflush", 0, { "Handle=[u]\n", NULL, NULL, NULL, NULL } },
{ SMBsplopen, "SMBsplopen", 0,
{ "SetupLen=[u]\nMode=[w]\n", "Ident=[Z]\n", "Handle=[u]\n",
NULL, NULL } },
{ SMBsplclose, "SMBsplclose", 0,
{ "Handle=[u]\n", NULL, NULL, NULL, NULL } },
{ SMBsplretq, "SMBsplretq", 0,
{ "MaxCount=[u]\nStartIndex=[u]\n", NULL,
"Count=[u]\nIndex=[u]\n",
"*Time=[T2]Status=[B]\nJobID=[u]\nSize=[U]\nRes=[B]Name=[s16]\n",
NULL } },
{ SMBsplwr, "SMBsplwr", 0,
{ "Handle=[u]\n", NULL, NULL, NULL, NULL } },
{ SMBlock, "SMBlock", 0,
{ "Handle=[u]\nCount=[U]\nOffset=[D]\n", NULL, NULL, NULL, NULL } },
{ SMBunlock, "SMBunlock", 0,
{ "Handle=[u]\nCount=[U]\nOffset=[D]\n", NULL, NULL, NULL, NULL } },
/* CORE+ PROTOCOL FOLLOWS */
{ SMBreadbraw, "SMBreadbraw", 0,
{ "Handle=[u]\nOffset=[D]\nMaxCount=[u]\nMinCount=[u]\nTimeOut=[D]\nRes=[u]\n",
NULL, NULL, NULL, NULL } },
{ SMBwritebraw, "SMBwritebraw", 0,
{ "Handle=[u]\nTotalCount=[u]\nRes=[w]\nOffset=[D]\nTimeOut=[D]\nWMode=[w]\nRes2=[W]\n|DataSize=[u]\nDataOff=[u]\n",
NULL, "WriteRawAck", NULL, NULL } },
{ SMBwritec, "SMBwritec", 0,
{ NULL, NULL, "Count=[u]\n", NULL, NULL } },
{ SMBwriteclose, "SMBwriteclose", 0,
{ "Handle=[u]\nCount=[u]\nOffset=[D]\nTime=[T2]Res=([w,w,w,w,w,w])",
NULL, "Count=[u]\n", NULL, NULL } },
{ SMBlockread, "SMBlockread", 0,
{ "Handle=[u]\nByteCount=[u]\nOffset=[D]\nCountLeft=[u]\n", NULL,
"Count=[u]\nRes=([w,w,w,w])\n", NULL, NULL } },
{ SMBwriteunlock, "SMBwriteunlock", 0,
{ "Handle=[u]\nByteCount=[u]\nOffset=[D]\nCountLeft=[u]\n", NULL,
"Count=[u]\n", NULL, NULL } },
{ SMBreadBmpx, "SMBreadBmpx", 0,
{ "Handle=[u]\nOffset=[D]\nMaxCount=[u]\nMinCount=[u]\nTimeOut=[D]\nRes=[w]\n",
NULL,
"Offset=[D]\nTotCount=[u]\nRemaining=[u]\nRes=([w,w])\nDataSize=[u]\nDataOff=[u]\n",
NULL, NULL } },
{ SMBwriteBmpx, "SMBwriteBmpx", 0,
{ "Handle=[u]\nTotCount=[u]\nRes=[w]\nOffset=[D]\nTimeOut=[D]\nWMode=[w]\nRes2=[W]\nDataSize=[u]\nDataOff=[u]\n", NULL,
"Remaining=[u]\n", NULL, NULL } },
{ SMBwriteBs, "SMBwriteBs", 0,
{ "Handle=[u]\nTotCount=[u]\nOffset=[D]\nRes=[W]\nDataSize=[u]\nDataOff=[u]\n",
NULL, "Count=[u]\n", NULL, NULL } },
{ SMBsetattrE, "SMBsetattrE", 0,
{ "Handle=[u]\nCreationTime=[T2]AccessTime=[T2]ModifyTime=[T2]", NULL,
NULL, NULL, NULL } },
{ SMBgetattrE, "SMBgetattrE", 0,
{ "Handle=[u]\n", NULL,
"CreationTime=[T2]AccessTime=[T2]ModifyTime=[T2]Size=[U]\nAllocSize=[U]\nAttribute=[A]\n",
NULL, NULL } },
{ SMBtranss, "SMBtranss", 0, DEFDESCRIPT },
{ SMBioctls, "SMBioctls", 0, DEFDESCRIPT },
{ SMBcopy, "SMBcopy", 0,
{ "TreeID2=[u]\nOFun=[w]\nFlags=[w]\n", "Path=[S]\nNewPath=[S]\n",
"CopyCount=[u]\n", "|ErrStr=[S]\n", NULL } },
{ SMBmove, "SMBmove", 0,
{ "TreeID2=[u]\nOFun=[w]\nFlags=[w]\n", "Path=[S]\nNewPath=[S]\n",
"MoveCount=[u]\n", "|ErrStr=[S]\n", NULL } },
{ SMBopenX, "SMBopenX", FLG_CHAIN,
{ "Com2=[w]\nOff2=[u]\nFlags=[w]\nMode=[w]\nSearchAttrib=[A]\nAttrib=[A]\nTime=[T2]OFun=[w]\nSize=[U]\nTimeOut=[D]\nRes=[W]\n",
"Path=[S]\n",
"Com2=[w]\nOff2=[u]\nHandle=[u]\nAttrib=[A]\nTime=[T2]Size=[U]\nAccess=[w]\nType=[w]\nState=[w]\nAction=[w]\nFileID=[W]\nRes=[w]\n",
NULL, NULL } },
{ SMBreadX, "SMBreadX", FLG_CHAIN,
{ "Com2=[w]\nOff2=[u]\nHandle=[u]\nOffset=[D]\nMaxCount=[u]\nMinCount=[u]\nTimeOut=[D]\nCountLeft=[u]\n",
NULL,
"Com2=[w]\nOff2=[u]\nRemaining=[u]\nRes=[W]\nDataSize=[u]\nDataOff=[u]\nRes=([w,w,w,w])\n",
NULL, NULL } },
{ SMBwriteX, "SMBwriteX", FLG_CHAIN,
{ "Com2=[w]\nOff2=[u]\nHandle=[u]\nOffset=[D]\nTimeOut=[D]\nWMode=[w]\nCountLeft=[u]\nRes=[w]\nDataSize=[u]\nDataOff=[u]\n",
NULL,
"Com2=[w]\nOff2=[u]\nCount=[u]\nRemaining=[u]\nRes=[W]\n",
NULL, NULL } },
{ SMBffirst, "SMBffirst", 0,
{ "Count=[u]\nAttrib=[A]\n",
"Path=[Z]\nBlkType=[B]\nBlkLen=[u]\n|Res1=[B]\nMask=[s11]\nSrv1=[B]\nDirIndex=[u]\nSrv2=[w]\n",
"Count=[u]\n",
"BlkType=[B]\nBlkLen=[u]\n*\nRes1=[B]\nMask=[s11]\nSrv1=[B]\nDirIndex=[u]\nSrv2=[w]\nRes2=[W]\nAttrib=[a]\nTime=[T1]Size=[U]\nName=[s13]\n",
NULL } },
{ SMBfunique, "SMBfunique", 0,
{ "Count=[u]\nAttrib=[A]\n",
"Path=[Z]\nBlkType=[B]\nBlkLen=[u]\n|Res1=[B]\nMask=[s11]\nSrv1=[B]\nDirIndex=[u]\nSrv2=[w]\n",
"Count=[u]\n",
"BlkType=[B]\nBlkLen=[u]\n*\nRes1=[B]\nMask=[s11]\nSrv1=[B]\nDirIndex=[u]\nSrv2=[w]\nRes2=[W]\nAttrib=[a]\nTime=[T1]Size=[U]\nName=[s13]\n",
NULL } },
{ SMBfclose, "SMBfclose", 0,
{ "Count=[u]\nAttrib=[A]\n",
"Path=[Z]\nBlkType=[B]\nBlkLen=[u]\n|Res1=[B]\nMask=[s11]\nSrv1=[B]\nDirIndex=[u]\nSrv2=[w]\n",
"Count=[u]\n",
"BlkType=[B]\nBlkLen=[u]\n*\nRes1=[B]\nMask=[s11]\nSrv1=[B]\nDirIndex=[u]\nSrv2=[w]\nRes2=[W]\nAttrib=[a]\nTime=[T1]Size=[U]\nName=[s13]\n",
NULL } },
{ SMBfindnclose, "SMBfindnclose", 0,
{ "Handle=[u]\n", NULL, NULL, NULL, NULL } },
{ SMBfindclose, "SMBfindclose", 0,
{ "Handle=[u]\n", NULL, NULL, NULL, NULL } },
{ SMBsends, "SMBsends", 0,
{ NULL, "Source=[Z]\nDest=[Z]\n", NULL, NULL, NULL } },
{ SMBsendstrt, "SMBsendstrt", 0,
{ NULL, "Source=[Z]\nDest=[Z]\n", "GroupID=[u]\n", NULL, NULL } },
{ SMBsendend, "SMBsendend", 0,
{ "GroupID=[u]\n", NULL, NULL, NULL, NULL } },
{ SMBsendtxt, "SMBsendtxt", 0,
{ "GroupID=[u]\n", NULL, NULL, NULL, NULL } },
{ SMBsendb, "SMBsendb", 0,
{ NULL, "Source=[Z]\nDest=[Z]\n", NULL, NULL, NULL } },
{ SMBfwdname, "SMBfwdname", 0, DEFDESCRIPT },
{ SMBcancelf, "SMBcancelf", 0, DEFDESCRIPT },
{ SMBgetmac, "SMBgetmac", 0, DEFDESCRIPT },
{ SMBnegprot, "SMBnegprot", 0,
{ NULL, NULL, NULL, NULL, print_negprot } },
{ SMBsesssetupX, "SMBsesssetupX", FLG_CHAIN,
{ NULL, NULL, NULL, NULL, print_sesssetup } },
{ SMBtconX, "SMBtconX", FLG_CHAIN,
{ "Com2=[w]\nOff2=[u]\nFlags=[w]\nPassLen=[u]\nPasswd&Path&Device=\n",
NULL, "Com2=[w]\nOff2=[u]\n", "ServiceType=[R]\n", NULL } },
{ SMBlockingX, "SMBlockingX", FLG_CHAIN,
{ NULL, NULL, NULL, NULL, print_lockingandx } },
{ SMBtrans2, "SMBtrans2", 0, { NULL, NULL, NULL, NULL, print_trans2 } },
{ SMBtranss2, "SMBtranss2", 0, DEFDESCRIPT },
{ SMBctemp, "SMBctemp", 0, DEFDESCRIPT },
{ SMBreadBs, "SMBreadBs", 0, DEFDESCRIPT },
{ SMBtrans, "SMBtrans", 0, { NULL, NULL, NULL, NULL, print_trans } },
{ SMBnttrans, "SMBnttrans", 0, DEFDESCRIPT },
{ SMBnttranss, "SMBnttranss", 0, DEFDESCRIPT },
{ SMBntcreateX, "SMBntcreateX", FLG_CHAIN,
{ "Com2=[w]\nOff2=[u]\nRes=[b]\nNameLen=[lu]\nFlags=[W]\nRootDirectoryFid=[U]\nAccessMask=[W]\nAllocationSize=[L]\nExtFileAttributes=[W]\nShareAccess=[W]\nCreateDisposition=[W]\nCreateOptions=[W]\nImpersonationLevel=[W]\nSecurityFlags=[b]\n",
"Path=[C]\n",
"Com2=[w]\nOff2=[u]\nOplockLevel=[b]\nFid=[u]\nCreateAction=[W]\nCreateTime=[T3]LastAccessTime=[T3]LastWriteTime=[T3]ChangeTime=[T3]ExtFileAttributes=[W]\nAllocationSize=[L]\nEndOfFile=[L]\nFileType=[w]\nDeviceState=[w]\nDirectory=[b]\n",
NULL, NULL } },
{ SMBntcancel, "SMBntcancel", 0, DEFDESCRIPT },
{ -1, NULL, 0, DEFDESCRIPT }
};
/*
* print a SMB message
*/
static void
print_smb(netdissect_options *ndo,
const u_char *buf, const u_char *maxbuf)
{
uint16_t flags2;
u_int nterrcodes;
u_int command;
uint32_t nterror;
const u_char *words, *maxwords, *data;
const struct smbfns *fn;
const char *fmt_smbheader =
"[P4]SMB Command = [B]\nError class = [BP1]\nError code = [u]\nFlags1 = [B]\nFlags2 = [B][P13]\nTree ID = [u]\nProc ID = [u]\nUID = [u]\nMID = [u]\nWord Count = [b]\n";
u_int smboffset;
ndo->ndo_protocol = "smb";
request = (GET_U_1(buf + 9) & 0x80) ? 0 : 1;
startbuf = buf;
command = GET_U_1(buf + 4);
fn = smbfind(command, smb_fns);
if (ndo->ndo_vflag > 1)
ND_PRINT("\n");
ND_PRINT("SMB PACKET: %s (%s)", fn->name, request ? "REQUEST" : "REPLY");
if (ndo->ndo_vflag < 2)
return;
ND_PRINT("\n");
flags2 = GET_LE_U_2(buf + 10);
unicodestr = flags2 & 0x8000;
nterrcodes = flags2 & 0x4000;
/* print out the header */
smb_fdata(ndo, buf, fmt_smbheader, buf + 33, unicodestr);
if (nterrcodes) {
nterror = GET_LE_U_4(buf + 5);
if (nterror)
ND_PRINT("NTError = %s\n", nt_errstr(nterror));
} else {
if (GET_U_1(buf + 5))
ND_PRINT("SMBError = %s\n", smb_errstr(GET_U_1(buf + 5),
GET_LE_U_2(buf + 7)));
}
smboffset = 32;
for (;;) {
const char *f1, *f2;
int wct;
u_int bcc;
u_int newsmboffset;
words = buf + smboffset;
wct = GET_U_1(words);
data = words + 1 + wct * 2;
maxwords = ND_MIN(data, maxbuf);
if (request) {
f1 = fn->descript.req_f1;
f2 = fn->descript.req_f2;
} else {
f1 = fn->descript.rep_f1;
f2 = fn->descript.rep_f2;
}
smb_reset();
if (fn->descript.fn)
(*fn->descript.fn)(ndo, words, data, buf, maxbuf);
else {
if (wct) {
if (f1)
smb_fdata(ndo, words + 1, f1, words + 1 + wct * 2, unicodestr);
else {
u_int i;
u_int v;
for (i = 0; words + 1 + 2 * i < maxwords; i++) {
v = GET_LE_U_2(words + 1 + 2 * i);
ND_PRINT("smb_vwv[%u]=%u (0x%X)\n", i, v, v);
}
}
}
bcc = GET_LE_U_2(data);
ND_PRINT("smb_bcc=%u\n", bcc);
if (f2) {
if (bcc > 0)
smb_fdata(ndo, data + 2, f2, data + 2 + bcc, unicodestr);
} else {
if (bcc > 0) {
ND_PRINT("smb_buf[]=\n");
- smb_data_print(ndo, data + 2, ND_MIN(bcc, ND_BYTES_BETWEEN(maxbuf, data + 2)));
+ smb_data_print(ndo, data + 2,
+ ND_MIN(bcc, ND_BYTES_BETWEEN(data + 2, maxbuf)));
}
}
}
if ((fn->flags & FLG_CHAIN) == 0)
break;
if (wct == 0)
break;
command = GET_U_1(words + 1);
if (command == 0xFF)
break;
newsmboffset = GET_LE_U_2(words + 3);
fn = smbfind(command, smb_fns);
ND_PRINT("\nSMB PACKET: %s (%s) (CHAINED)\n",
fn->name, request ? "REQUEST" : "REPLY");
if (newsmboffset <= smboffset) {
ND_PRINT("Bad andX offset: %u <= %u\n", newsmboffset, smboffset);
break;
}
smboffset = newsmboffset;
}
}
/*
* print a NBT packet received across tcp on port 139
*/
void
nbt_tcp_print(netdissect_options *ndo,
const u_char *data, u_int length)
{
u_int caplen;
u_int type;
u_int nbt_len;
const u_char *maxbuf;
ndo->ndo_protocol = "nbt_tcp";
if (length < 4)
goto trunc;
if (ndo->ndo_snapend < data)
goto trunc;
caplen = ND_BYTES_AVAILABLE_AFTER(data);
if (caplen < 4)
goto trunc;
maxbuf = data + caplen;
type = GET_U_1(data);
nbt_len = GET_BE_U_2(data + 2);
length -= 4;
caplen -= 4;
startbuf = data;
if (ndo->ndo_vflag < 2) {
ND_PRINT(" NBT Session Packet: ");
switch (type) {
case 0x00:
ND_PRINT("Session Message");
break;
case 0x81:
ND_PRINT("Session Request");
break;
case 0x82:
ND_PRINT("Session Granted");
break;
case 0x83:
{
u_int ecode;
if (nbt_len < 4)
goto trunc;
if (length < 4)
goto trunc;
if (caplen < 4)
goto trunc;
ecode = GET_U_1(data + 4);
ND_PRINT("Session Reject, ");
switch (ecode) {
case 0x80:
ND_PRINT("Not listening on called name");
break;
case 0x81:
ND_PRINT("Not listening for calling name");
break;
case 0x82:
ND_PRINT("Called name not present");
break;
case 0x83:
ND_PRINT("Called name present, but insufficient resources");
break;
default:
ND_PRINT("Unspecified error 0x%X", ecode);
break;
}
}
break;
case 0x85:
ND_PRINT("Session Keepalive");
break;
default:
data = smb_fdata(ndo, data, "Unknown packet type [rB]", maxbuf, 0);
break;
}
} else {
ND_PRINT("\n>>> NBT Session Packet\n");
switch (type) {
case 0x00:
data = smb_fdata(ndo, data, "[P1]NBT Session Message\nFlags=[B]\nLength=[ru]\n",
data + 4, 0);
if (data == NULL)
break;
if (nbt_len >= 4 && caplen >= 4 && memcmp(data,"\377SMB",4) == 0) {
if (nbt_len > caplen) {
if (nbt_len > length)
ND_PRINT("WARNING: Packet is continued in later TCP segments\n");
else
ND_PRINT("WARNING: Short packet. Try increasing the snap length by %u\n",
nbt_len - caplen);
}
print_smb(ndo, data, maxbuf > data + nbt_len ? data + nbt_len : maxbuf);
} else
ND_PRINT("Session packet:(raw data or continuation?)\n");
break;
case 0x81:
data = smb_fdata(ndo, data,
"[P1]NBT Session Request\nFlags=[B]\nLength=[ru]\nDestination=[n1]\nSource=[n1]\n",
maxbuf, 0);
break;
case 0x82:
data = smb_fdata(ndo, data, "[P1]NBT Session Granted\nFlags=[B]\nLength=[ru]\n", maxbuf, 0);
break;
case 0x83:
{
const u_char *origdata;
u_int ecode;
origdata = data;
data = smb_fdata(ndo, data, "[P1]NBT SessionReject\nFlags=[B]\nLength=[ru]\nReason=[B]\n",
maxbuf, 0);
if (data == NULL)
break;
if (nbt_len >= 1 && caplen >= 1) {
ecode = GET_U_1(origdata + 4);
switch (ecode) {
case 0x80:
ND_PRINT("Not listening on called name\n");
break;
case 0x81:
ND_PRINT("Not listening for calling name\n");
break;
case 0x82:
ND_PRINT("Called name not present\n");
break;
case 0x83:
ND_PRINT("Called name present, but insufficient resources\n");
break;
default:
ND_PRINT("Unspecified error 0x%X\n", ecode);
break;
}
}
}
break;
case 0x85:
data = smb_fdata(ndo, data, "[P1]NBT Session Keepalive\nFlags=[B]\nLength=[ru]\n", maxbuf, 0);
break;
default:
data = smb_fdata(ndo, data, "NBT - Unknown packet type\nType=[B]\n", maxbuf, 0);
break;
}
}
return;
trunc:
nd_print_trunc(ndo);
}
static const struct tok opcode_str[] = {
{ 0, "QUERY" },
{ 5, "REGISTRATION" },
{ 6, "RELEASE" },
{ 7, "WACK" },
{ 8, "REFRESH(8)" },
{ 9, "REFRESH" },
{ 15, "MULTIHOMED REGISTRATION" },
{ 0, NULL }
};
/*
* print a NBT packet received across udp on port 137
*/
void
nbt_udp137_print(netdissect_options *ndo,
const u_char *data, u_int length)
{
const u_char *maxbuf = data + length;
u_int name_trn_id, response, opcode, nm_flags, rcode;
u_int qdcount, ancount, nscount, arcount;
const u_char *p;
u_int total, i;
ndo->ndo_protocol = "nbt_udp137";
name_trn_id = GET_BE_U_2(data);
response = (GET_U_1(data + 2) >> 7);
opcode = (GET_U_1(data + 2) >> 3) & 0xF;
nm_flags = ((GET_U_1(data + 2) & 0x7) << 4) + (GET_U_1(data + 3) >> 4);
rcode = GET_U_1(data + 3) & 0xF;
qdcount = GET_BE_U_2(data + 4);
ancount = GET_BE_U_2(data + 6);
nscount = GET_BE_U_2(data + 8);
arcount = GET_BE_U_2(data + 10);
startbuf = data;
if (maxbuf <= data)
return;
if (ndo->ndo_vflag > 1)
ND_PRINT("\n>>> ");
ND_PRINT("NBT UDP PACKET(137): %s", tok2str(opcode_str, "OPUNKNOWN", opcode));
if (response) {
ND_PRINT("; %s", rcode ? "NEGATIVE" : "POSITIVE");
}
ND_PRINT("; %s; %s", response ? "RESPONSE" : "REQUEST",
(nm_flags & 1) ? "BROADCAST" : "UNICAST");
if (ndo->ndo_vflag < 2)
return;
ND_PRINT("\nTrnID=0x%X\nOpCode=%u\nNmFlags=0x%X\nRcode=%u\nQueryCount=%u\nAnswerCount=%u\nAuthorityCount=%u\nAddressRecCount=%u\n",
name_trn_id, opcode, nm_flags, rcode, qdcount, ancount, nscount,
arcount);
p = data + 12;
total = ancount + nscount + arcount;
if (qdcount > 100 || total > 100) {
ND_PRINT("Corrupt packet??\n");
return;
}
if (qdcount) {
ND_PRINT("QuestionRecords:\n");
for (i = 0; i < qdcount; i++) {
p = smb_fdata(ndo, p,
"|Name=[n1]\nQuestionType=[rw]\nQuestionClass=[rw]\n#",
maxbuf, 0);
if (p == NULL)
goto out;
}
}
if (total) {
ND_PRINT("\nResourceRecords:\n");
for (i = 0; i < total; i++) {
u_int rdlen;
u_int restype;
p = smb_fdata(ndo, p, "Name=[n1]\n#", maxbuf, 0);
if (p == NULL)
goto out;
restype = GET_BE_U_2(p);
p = smb_fdata(ndo, p, "ResType=[rw]\nResClass=[rw]\nTTL=[rU]\n", p + 8, 0);
if (p == NULL)
goto out;
rdlen = GET_BE_U_2(p);
ND_PRINT("ResourceLength=%u\nResourceData=\n", rdlen);
p += 2;
if (rdlen == 6) {
p = smb_fdata(ndo, p, "AddrType=[rw]\nAddress=[b.b.b.b]\n", p + rdlen, 0);
if (p == NULL)
goto out;
} else {
if (restype == 0x21) {
u_int numnames;
numnames = GET_U_1(p);
p = smb_fdata(ndo, p, "NumNames=[B]\n", p + 1, 0);
if (p == NULL)
goto out;
while (numnames) {
p = smb_fdata(ndo, p, "Name=[n2]\t#", maxbuf, 0);
if (p == NULL)
goto out;
ND_TCHECK_1(p);
if (p >= maxbuf)
goto out;
if (GET_U_1(p) & 0x80)
ND_PRINT("<GROUP> ");
switch (GET_U_1(p) & 0x60) {
case 0x00: ND_PRINT("B "); break;
case 0x20: ND_PRINT("P "); break;
case 0x40: ND_PRINT("M "); break;
case 0x60: ND_PRINT("_ "); break;
}
if (GET_U_1(p) & 0x10)
ND_PRINT("<DEREGISTERING> ");
if (GET_U_1(p) & 0x08)
ND_PRINT("<CONFLICT> ");
if (GET_U_1(p) & 0x04)
ND_PRINT("<ACTIVE> ");
if (GET_U_1(p) & 0x02)
ND_PRINT("<PERMANENT> ");
ND_PRINT("\n");
p += 2;
numnames--;
}
} else {
if (p >= maxbuf)
goto out;
- smb_data_print(ndo, p, ND_MIN(rdlen, length - ND_BYTES_BETWEEN(p, data)));
+ smb_data_print(ndo, p,
+ ND_MIN(rdlen, length - ND_BYTES_BETWEEN(data, p)));
p += rdlen;
}
}
}
}
if (p < maxbuf)
smb_fdata(ndo, p, "AdditionalData:\n", maxbuf, 0);
out:
return;
trunc:
nd_print_trunc(ndo);
}
/*
* Print an SMB-over-TCP packet received across tcp on port 445
*/
void
smb_tcp_print(netdissect_options *ndo,
const u_char * data, u_int length)
{
u_int caplen;
u_int smb_len;
const u_char *maxbuf;
ndo->ndo_protocol = "smb_tcp";
if (length < 4)
goto trunc;
if (ndo->ndo_snapend < data)
goto trunc;
caplen = ND_BYTES_AVAILABLE_AFTER(data);
if (caplen < 4)
goto trunc;
maxbuf = data + caplen;
smb_len = GET_BE_U_3(data + 1);
length -= 4;
caplen -= 4;
startbuf = data;
data += 4;
if (smb_len >= 4 && caplen >= 4 && memcmp(data,"\377SMB",4) == 0) {
if (smb_len > caplen) {
if (smb_len > length)
ND_PRINT(" WARNING: Packet is continued in later TCP segments\n");
else
ND_PRINT(" WARNING: Short packet. Try increasing the snap length by %u\n",
smb_len - caplen);
} else
ND_PRINT(" ");
print_smb(ndo, data, maxbuf > data + smb_len ? data + smb_len : maxbuf);
} else
ND_PRINT(" SMB-over-TCP packet:(raw data or continuation?)\n");
return;
trunc:
nd_print_trunc(ndo);
}
/*
* print a NBT packet received across udp on port 138
*/
void
nbt_udp138_print(netdissect_options *ndo,
const u_char *data, u_int length)
{
const u_char *maxbuf = data + length;
ndo->ndo_protocol = "nbt_udp138";
if (maxbuf > ndo->ndo_snapend)
maxbuf = ndo->ndo_snapend;
if (maxbuf <= data)
return;
startbuf = data;
if (ndo->ndo_vflag < 2) {
ND_PRINT("NBT UDP PACKET(138)");
return;
}
data = smb_fdata(ndo, data,
"\n>>> NBT UDP PACKET(138) Res=[rw] ID=[rw] IP=[b.b.b.b] Port=[ru] Length=[ru] Res2=[rw]\nSourceName=[n1]\nDestName=[n1]\n#",
maxbuf, 0);
if (data != NULL) {
/* If there isn't enough data for "\377SMB", don't check for it. */
if ((data + 3) >= maxbuf)
goto out;
if (memcmp(data, "\377SMB",4) == 0)
print_smb(ndo, data, maxbuf);
}
out:
return;
}
/*
print netbeui frames
*/
static struct nbf_strings {
const char *name;
const char *nonverbose;
const char *verbose;
} nbf_strings[0x20] = {
{ "Add Group Name Query", ", [P23]Name to add=[n2]#",
"[P5]ResponseCorrelator=[w]\n[P16]Name to add=[n2]\n" },
{ "Add Name Query", ", [P23]Name to add=[n2]#",
"[P5]ResponseCorrelator=[w]\n[P16]Name to add=[n2]\n" },
{ "Name In Conflict", NULL, NULL },
{ "Status Query", NULL, NULL },
{ NULL, NULL, NULL }, /* not used */
{ NULL, NULL, NULL }, /* not used */
{ NULL, NULL, NULL }, /* not used */
{ "Terminate Trace", NULL, NULL },
{ "Datagram", NULL,
"[P7]Destination=[n2]\nSource=[n2]\n" },
{ "Broadcast Datagram", NULL,
"[P7]Destination=[n2]\nSource=[n2]\n" },
{ "Name Query", ", [P7]Name=[n2]#",
"[P1]SessionNumber=[B]\nNameType=[B][P2]\nResponseCorrelator=[w]\nName=[n2]\nName of sender=[n2]\n" },
{ NULL, NULL, NULL }, /* not used */
{ NULL, NULL, NULL }, /* not used */
{ "Add Name Response", ", [P1]GroupName=[w] [P4]Destination=[n2] Source=[n2]#",
"AddNameInProcess=[B]\nGroupName=[w]\nTransmitCorrelator=[w][P2]\nDestination=[n2]\nSource=[n2]\n" },
{ "Name Recognized", NULL,
"[P1]Data2=[w]\nTransmitCorrelator=[w]\nResponseCorelator=[w]\nDestination=[n2]\nSource=[n2]\n" },
{ "Status Response", NULL, NULL },
{ NULL, NULL, NULL }, /* not used */
{ NULL, NULL, NULL }, /* not used */
{ NULL, NULL, NULL }, /* not used */
{ "Terminate Trace", NULL, NULL },
{ "Data Ack", NULL,
"[P3]TransmitCorrelator=[w][P2]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n" },
{ "Data First/Middle", NULL,
"Flags=[{RECEIVE_CONTINUE|NO_ACK||PIGGYBACK_ACK_INCLUDED|}]\nResyncIndicator=[w][P2]\nResponseCorelator=[w]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n" },
{ "Data Only/Last", NULL,
"Flags=[{|NO_ACK|PIGGYBACK_ACK_ALLOWED|PIGGYBACK_ACK_INCLUDED|}]\nResyncIndicator=[w][P2]\nResponseCorelator=[w]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n" },
{ "Session Confirm", NULL,
"Data1=[B]\nData2=[w]\nTransmitCorrelator=[w]\nResponseCorelator=[w]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n" },
{ "Session End", NULL,
"[P1]Data2=[w][P4]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n" },
{ "Session Initialize", NULL,
"Data1=[B]\nData2=[w]\nTransmitCorrelator=[w]\nResponseCorelator=[w]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n" },
{ "No Receive", NULL,
"Flags=[{|SEND_NO_ACK}]\nDataBytesAccepted=[b][P4]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n" },
{ "Receive Outstanding", NULL,
"[P1]DataBytesAccepted=[b][P4]\nRemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n" },
{ "Receive Continue", NULL,
"[P2]TransmitCorrelator=[w]\n[P2]RemoteSessionNumber=[B]\nLocalSessionNumber=[B]\n" },
{ NULL, NULL, NULL }, /* not used */
{ NULL, NULL, NULL }, /* not used */
{ "Session Alive", NULL, NULL }
};
void
netbeui_print(netdissect_options *ndo,
u_short control, const u_char *data, u_int length)
{
const u_char *maxbuf = data + length;
u_int len;
u_int command;
const u_char *data2;
int is_truncated = 0;
ndo->ndo_protocol = "netbeui";
if (maxbuf > ndo->ndo_snapend)
maxbuf = ndo->ndo_snapend;
len = GET_LE_U_2(data);
command = GET_U_1(data + 4);
data2 = data + len;
if (data2 >= maxbuf) {
data2 = maxbuf;
is_truncated = 1;
}
startbuf = data;
if (ndo->ndo_vflag < 2) {
ND_PRINT("NBF Packet: ");
data = smb_fdata(ndo, data, "[P5]#", maxbuf, 0);
} else {
ND_PRINT("\n>>> NBF Packet\nType=0x%X ", control);
data = smb_fdata(ndo, data, "Length=[u] Signature=[w] Command=[B]\n#", maxbuf, 0);
}
if (data == NULL)
goto out;
if (command > 0x1f || nbf_strings[command].name == NULL) {
if (ndo->ndo_vflag < 2)
data = smb_fdata(ndo, data, "Unknown NBF Command#", data2, 0);
else
data = smb_fdata(ndo, data, "Unknown NBF Command\n", data2, 0);
} else {
if (ndo->ndo_vflag < 2) {
ND_PRINT("%s", nbf_strings[command].name);
if (nbf_strings[command].nonverbose != NULL)
data = smb_fdata(ndo, data, nbf_strings[command].nonverbose, data2, 0);
} else {
ND_PRINT("%s:\n", nbf_strings[command].name);
if (nbf_strings[command].verbose != NULL)
data = smb_fdata(ndo, data, nbf_strings[command].verbose, data2, 0);
else
ND_PRINT("\n");
}
}
if (ndo->ndo_vflag < 2)
return;
if (data == NULL)
goto out;
if (is_truncated) {
/* data2 was past the end of the buffer */
goto out;
}
/* If this isn't a command that would contain an SMB message, quit. */
if (command != 0x08 && command != 0x09 && command != 0x15 &&
command != 0x16)
goto out;
/* If there isn't enough data for "\377SMB", don't look for it. */
if ((data2 + 3) >= maxbuf)
goto out;
if (memcmp(data2, "\377SMB",4) == 0)
print_smb(ndo, data2, maxbuf);
else {
u_int i;
for (i = 0; i < 128; i++) {
if ((data2 + i + 3) >= maxbuf)
break;
if (memcmp(data2 + i, "\377SMB", 4) == 0) {
ND_PRINT("found SMB packet at %u\n", i);
print_smb(ndo, data2 + i, maxbuf);
break;
}
}
}
out:
return;
}
/*
* print IPX-Netbios frames
*/
void
ipx_netbios_print(netdissect_options *ndo,
const u_char *data, u_int length)
{
/*
* this is a hack till I work out how to parse the rest of the
* NetBIOS-over-IPX stuff
*/
u_int i;
const u_char *maxbuf;
ndo->ndo_protocol = "ipx_netbios";
maxbuf = data + length;
/* Don't go past the end of the captured data in the packet. */
if (maxbuf > ndo->ndo_snapend)
maxbuf = ndo->ndo_snapend;
startbuf = data;
for (i = 0; i < 128; i++) {
if ((data + i + 4) > maxbuf)
break;
if (memcmp(data + i, "\377SMB", 4) == 0) {
smb_fdata(ndo, data, "\n>>> IPX transport ", data + i, 0);
print_smb(ndo, data + i, maxbuf);
break;
}
}
if (i == 128)
smb_fdata(ndo, data, "\n>>> Unknown IPX ", maxbuf, 0);
}
diff --git a/contrib/tcpdump/print-smtp.c b/contrib/tcpdump/print-smtp.c
index 4acf87c962a6..fba7f2371ba5 100644
--- a/contrib/tcpdump/print-smtp.c
+++ b/contrib/tcpdump/print-smtp.c
@@ -1,29 +1,27 @@
/*
* 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.
*/
/* \summary: Simple Mail Transfer Protocol (SMTP) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
void
smtp_print(netdissect_options *ndo, const u_char *pptr, u_int len)
{
ndo->ndo_protocol = "smtp";
txtproto_print(ndo, pptr, len, NULL, 0);
}
diff --git a/contrib/tcpdump/print-snmp.c b/contrib/tcpdump/print-snmp.c
index 6aae34caa7de..76f0bbacaf0b 100644
--- a/contrib/tcpdump/print-snmp.c
+++ b/contrib/tcpdump/print-snmp.c
@@ -1,1932 +1,1932 @@
/*
* Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
* John Robert LoVerso. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
* This implementation has been influenced by the CMU SNMP release,
* by Steve Waldbusser. However, this shares no code with that system.
* Additional ASN.1 insight gained from Marshall T. Rose's _The_Open_Book_.
* Earlier forms of this implementation were derived and/or inspired by an
* awk script originally written by C. Philip Wood of LANL (but later
* heavily modified by John Robert LoVerso). The copyright notice for
* that work is preserved below, even though it may not rightly apply
* to this file.
*
* Support for SNMPv2c/SNMPv3 and the ability to link the module against
* the libsmi was added by J. Schoenwaelder, Copyright (c) 1999.
*
* This started out as a very simple program, but the incremental decoding
* (into the BE structure) complicated things.
*
# Los Alamos National Laboratory
#
# Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
# This software was produced under a U.S. Government contract
# (W-7405-ENG-36) by Los Alamos National Laboratory, which is
# operated by the University of California for the U.S. Department
# of Energy. The U.S. Government is licensed to use, reproduce,
# and distribute this software. Permission is granted to the
# public to copy and use this software without charge, provided
# that this Notice and any statement of authorship are reproduced
# on all copies. Neither the Government nor the University makes
# any warranty, express or implied, or assumes any liability or
# responsibility for the use of this software.
# @(#)snmp.awk.x 1.1 (LANL) 1/15/90
*/
/* \summary: Simple Network Management Protocol (SNMP) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <stdio.h>
#include <string.h>
+#include <limits.h>
#ifdef USE_LIBSMI
#include <smi.h>
#endif
#include "netdissect-ctype.h"
#include "netdissect.h"
#include "extract.h"
#undef OPAQUE /* defined in <wingdi.h> */
/*
* Universal ASN.1 types
* (we only care about the tag values for those allowed in the Internet SMI)
*/
static const char *Universal[] = {
"U-0",
"Boolean",
"Integer",
#define INTEGER 2
"Bitstring",
"String",
#define STRING 4
"Null",
#define ASN_NULL 5
"ObjID",
#define OBJECTID 6
"ObjectDes",
"U-8","U-9","U-10","U-11", /* 8-11 */
"U-12","U-13","U-14","U-15", /* 12-15 */
"Sequence",
#define SEQUENCE 16
"Set"
};
/*
* Application-wide ASN.1 types from the Internet SMI and their tags
*/
static const char *Application[] = {
"IpAddress",
#define IPADDR 0
"Counter",
#define COUNTER 1
"Gauge",
#define GAUGE 2
"TimeTicks",
#define TIMETICKS 3
"Opaque",
#define OPAQUE 4
"C-5",
"Counter64"
#define COUNTER64 6
};
/*
* Context-specific ASN.1 types for the SNMP PDUs and their tags
*/
static const char *Context[] = {
"GetRequest",
#define GETREQ 0
"GetNextRequest",
#define GETNEXTREQ 1
"GetResponse",
#define GETRESP 2
"SetRequest",
#define SETREQ 3
"Trap",
#define TRAP 4
"GetBulk",
#define GETBULKREQ 5
"Inform",
#define INFORMREQ 6
"V2Trap",
#define V2TRAP 7
"Report"
#define REPORT 8
};
#define NOTIFY_CLASS(x) (x == TRAP || x == V2TRAP || x == INFORMREQ)
#define READ_CLASS(x) (x == GETREQ || x == GETNEXTREQ || x == GETBULKREQ)
#define WRITE_CLASS(x) (x == SETREQ)
#define RESPONSE_CLASS(x) (x == GETRESP)
#define INTERNAL_CLASS(x) (x == REPORT)
/*
* Context-specific ASN.1 types for the SNMP Exceptions and their tags
*/
static const char *Exceptions[] = {
"noSuchObject",
#define NOSUCHOBJECT 0
"noSuchInstance",
#define NOSUCHINSTANCE 1
"endOfMibView",
#define ENDOFMIBVIEW 2
};
/*
* Private ASN.1 types
* The Internet SMI does not specify any
*/
static const char *Private[] = {
"P-0"
};
/*
* error-status values for any SNMP PDU
*/
static const char *ErrorStatus[] = {
"noError",
"tooBig",
"noSuchName",
"badValue",
"readOnly",
"genErr",
"noAccess",
"wrongType",
"wrongLength",
"wrongEncoding",
"wrongValue",
"noCreation",
"inconsistentValue",
"resourceUnavailable",
"commitFailed",
"undoFailed",
"authorizationError",
"notWritable",
"inconsistentName"
};
#define DECODE_ErrorStatus(e) \
( e >= 0 && (size_t)e < sizeof(ErrorStatus)/sizeof(ErrorStatus[0]) \
? ErrorStatus[e] \
: (snprintf(errbuf, sizeof(errbuf), "err=%u", e), errbuf))
/*
* generic-trap values in the SNMP Trap-PDU
*/
static const char *GenericTrap[] = {
"coldStart",
"warmStart",
"linkDown",
"linkUp",
"authenticationFailure",
"egpNeighborLoss",
"enterpriseSpecific"
#define GT_ENTERPRISE 6
};
#define DECODE_GenericTrap(t) \
( t >= 0 && (size_t)t < sizeof(GenericTrap)/sizeof(GenericTrap[0]) \
? GenericTrap[t] \
: (snprintf(buf, sizeof(buf), "gt=%d", t), buf))
/*
* ASN.1 type class table
* Ties together the preceding Universal, Application, Context, and Private
* type definitions.
*/
#define defineCLASS(x) { "x", x, sizeof(x)/sizeof(x[0]) } /* not ANSI-C */
static const struct {
const char *name;
const char **Id;
int numIDs;
} Class[] = {
defineCLASS(Universal),
#define UNIVERSAL 0
defineCLASS(Application),
#define APPLICATION 1
defineCLASS(Context),
#define CONTEXT 2
defineCLASS(Private),
#define PRIVATE 3
defineCLASS(Exceptions),
#define EXCEPTIONS 4
};
/*
* defined forms for ASN.1 types
*/
static const char *Form[] = {
"Primitive",
#define PRIMITIVE 0
"Constructed",
#define CONSTRUCTED 1
};
/*
* A structure for the OID tree for the compiled-in MIB.
* This is stored as a general-order tree.
*/
static struct obj {
const char *desc; /* name of object */
u_char oid; /* sub-id following parent */
u_char type; /* object type (unused) */
struct obj *child, *next; /* child and next sibling pointers */
} *objp = NULL;
/*
* Include the compiled in SNMP MIB. "mib.h" is produced by feeding
* RFC-1156 format files into "makemib". "mib.h" MUST define at least
* a value for `mibroot'.
*
* In particular, this is gross, as this is including initialized structures,
* and by right shouldn't be an "include" file.
*/
#include "mib.h"
/*
* This defines a list of OIDs which will be abbreviated on output.
* Currently, this includes the prefixes for the Internet MIB, the
* private enterprises tree, and the experimental tree.
*/
#define OID_FIRST_OCTET(x, y) (((x)*40) + (y)) /* X.690 8.19.4 */
#ifndef NO_ABREV_MIB
static const uint8_t mib_oid[] = { OID_FIRST_OCTET(1, 3), 6, 1, 2, 1 };
#endif
#ifndef NO_ABREV_ENTER
static const uint8_t enterprises_oid[] = { OID_FIRST_OCTET(1, 3), 6, 1, 4, 1 };
#endif
#ifndef NO_ABREV_EXPERI
static const uint8_t experimental_oid[] = { OID_FIRST_OCTET(1, 3), 6, 1, 3 };
#endif
#ifndef NO_ABBREV_SNMPMODS
static const uint8_t snmpModules_oid[] = { OID_FIRST_OCTET(1, 3), 6, 1, 6, 3 };
#endif
#define OBJ_ABBREV_ENTRY(prefix, obj) \
{ prefix, &_ ## obj ## _obj, obj ## _oid, sizeof (obj ## _oid) }
static const struct obj_abrev {
const char *prefix; /* prefix for this abrev */
struct obj *node; /* pointer into object table */
const uint8_t *oid; /* ASN.1 encoded OID */
size_t oid_len; /* length of OID */
} obj_abrev_list[] = {
#ifndef NO_ABREV_MIB
/* .iso.org.dod.internet.mgmt.mib */
OBJ_ABBREV_ENTRY("", mib),
#endif
#ifndef NO_ABREV_ENTER
/* .iso.org.dod.internet.private.enterprises */
OBJ_ABBREV_ENTRY("E:", enterprises),
#endif
#ifndef NO_ABREV_EXPERI
/* .iso.org.dod.internet.experimental */
OBJ_ABBREV_ENTRY("X:", experimental),
#endif
#ifndef NO_ABBREV_SNMPMODS
/* .iso.org.dod.internet.snmpV2.snmpModules */
OBJ_ABBREV_ENTRY("S:", snmpModules),
#endif
{ 0,0,0,0 }
};
/*
* This is used in the OID print routine to walk down the object tree
* rooted at `mibroot'.
*/
#define OBJ_PRINT(o, suppressdot) \
{ \
if (objp) { \
do { \
if ((o) == objp->oid) \
break; \
} while ((objp = objp->next) != NULL); \
} \
if (objp) { \
ND_PRINT(suppressdot?"%s":".%s", objp->desc); \
objp = objp->child; \
} else \
ND_PRINT(suppressdot?"%u":".%u", (o)); \
}
/*
* This is the definition for the Any-Data-Type storage used purely for
* temporary internal representation while decoding an ASN.1 data stream.
*/
struct be {
uint32_t asnlen;
union {
const uint8_t *raw;
int32_t integer;
uint32_t uns;
const u_char *str;
uint64_t uns64;
} data;
u_short id;
u_char form, class; /* tag info */
u_char type;
#define BE_ANY 255
#define BE_NONE 0
#define BE_NULL 1
#define BE_OCTET 2
#define BE_OID 3
#define BE_INT 4
#define BE_UNS 5
#define BE_STR 6
#define BE_SEQ 7
#define BE_INETADDR 8
#define BE_PDU 9
#define BE_UNS64 10
#define BE_NOSUCHOBJECT 128
#define BE_NOSUCHINST 129
#define BE_ENDOFMIBVIEW 130
};
/*
* SNMP versions recognized by this module
*/
static const char *SnmpVersion[] = {
"SNMPv1",
#define SNMP_VERSION_1 0
"SNMPv2c",
#define SNMP_VERSION_2 1
"SNMPv2u",
#define SNMP_VERSION_2U 2
"SNMPv3"
#define SNMP_VERSION_3 3
};
/*
* Defaults for SNMP PDU components
*/
#define DEF_COMMUNITY "public"
/*
* constants for ASN.1 decoding
*/
#define OIDMUX 40
#define ASNLEN_INETADDR 4
#define ASN_SHIFT7 7
#define ASN_SHIFT8 8
#define ASN_BIT8 0x80
#define ASN_LONGLEN 0x80
#define ASN_ID_BITS 0x1f
#define ASN_FORM_BITS 0x20
#define ASN_FORM_SHIFT 5
#define ASN_CLASS_BITS 0xc0
#define ASN_CLASS_SHIFT 6
#define ASN_ID_EXT 0x1f /* extension ID in tag field */
/*
* This decodes the next ASN.1 object in the stream pointed to by "p"
* (and of real-length "len") and stores the intermediate data in the
* provided BE object.
*
* This returns -l if it fails (i.e., the ASN.1 stream is not valid).
* O/w, this returns the number of bytes parsed from "p".
*/
static int
asn1_parse(netdissect_options *ndo,
const u_char *p, u_int len, struct be *elem)
{
u_char form, class, id;
u_int i, hdr;
elem->asnlen = 0;
elem->type = BE_ANY;
if (len < 1) {
ND_PRINT("[nothing to parse]");
return -1;
}
/*
* it would be nice to use a bit field, but you can't depend on them.
* +---+---+---+---+---+---+---+---+
* + class |frm| id |
* +---+---+---+---+---+---+---+---+
* 7 6 5 4 3 2 1 0
*/
id = GET_U_1(p) & ASN_ID_BITS; /* lower 5 bits, range 00-1f */
#ifdef notdef
form = (GET_U_1(p) & 0xe0) >> 5; /* move upper 3 bits to lower 3 */
class = form >> 1; /* bits 7&6 -> bits 1&0, range 0-3 */
form &= 0x1; /* bit 5 -> bit 0, range 0-1 */
#else
form = (u_char)(GET_U_1(p) & ASN_FORM_BITS) >> ASN_FORM_SHIFT;
class = (u_char)(GET_U_1(p) & ASN_CLASS_BITS) >> ASN_CLASS_SHIFT;
#endif
elem->form = form;
elem->class = class;
elem->id = id;
p++; len--; hdr = 1;
/* extended tag field */
if (id == ASN_ID_EXT) {
/*
* The ID follows, as a sequence of octets with the
* 8th bit set and the remaining 7 bits being
* the next 7 bits of the value, terminated with
* an octet with the 8th bit not set.
*
* First, assemble all the octets with the 8th
* bit set. XXX - this doesn't handle a value
* that won't fit in 32 bits.
*/
id = 0;
while (GET_U_1(p) & ASN_BIT8) {
if (len < 1) {
ND_PRINT("[Xtagfield?]");
return -1;
}
id = (id << 7) | (GET_U_1(p) & ~ASN_BIT8);
len--;
hdr++;
p++;
}
if (len < 1) {
ND_PRINT("[Xtagfield?]");
return -1;
}
elem->id = id = (id << 7) | GET_U_1(p);
--len;
++hdr;
++p;
}
if (len < 1) {
ND_PRINT("[no asnlen]");
return -1;
}
elem->asnlen = GET_U_1(p);
p++; len--; hdr++;
if (elem->asnlen & ASN_BIT8) {
uint32_t noct = elem->asnlen % ASN_BIT8;
elem->asnlen = 0;
if (len < noct) {
ND_PRINT("[asnlen? %d<%d]", len, noct);
return -1;
}
ND_TCHECK_LEN(p, noct);
for (; noct != 0; len--, hdr++, noct--) {
elem->asnlen = (elem->asnlen << ASN_SHIFT8) | GET_U_1(p);
p++;
}
}
if (len < elem->asnlen) {
ND_PRINT("[len%d<asnlen%u]", len, elem->asnlen);
return -1;
}
if (form >= sizeof(Form)/sizeof(Form[0])) {
ND_PRINT("[form?%d]", form);
return -1;
}
if (class >= sizeof(Class)/sizeof(Class[0])) {
ND_PRINT("[class?%c/%d]", *Form[form], class);
return -1;
}
if ((int)id >= Class[class].numIDs) {
ND_PRINT("[id?%c/%s/%d]", *Form[form], Class[class].name, id);
return -1;
}
ND_TCHECK_LEN(p, elem->asnlen);
switch (form) {
case PRIMITIVE:
switch (class) {
case UNIVERSAL:
switch (id) {
case STRING:
elem->type = BE_STR;
elem->data.str = p;
break;
case INTEGER: {
- int32_t data;
+ uint32_t data;
elem->type = BE_INT;
data = 0;
if (elem->asnlen == 0) {
ND_PRINT("[asnlen=0]");
return -1;
}
if (GET_U_1(p) & ASN_BIT8) /* negative */
- data = -1;
+ data = UINT_MAX;
for (i = elem->asnlen; i != 0; p++, i--)
data = (data << ASN_SHIFT8) | GET_U_1(p);
elem->data.integer = data;
break;
}
case OBJECTID:
elem->type = BE_OID;
elem->data.raw = (const uint8_t *)p;
break;
case ASN_NULL:
elem->type = BE_NULL;
elem->data.raw = NULL;
break;
default:
elem->type = BE_OCTET;
elem->data.raw = (const uint8_t *)p;
ND_PRINT("[P/U/%s]", Class[class].Id[id]);
break;
}
break;
case APPLICATION:
switch (id) {
case IPADDR:
elem->type = BE_INETADDR;
elem->data.raw = (const uint8_t *)p;
break;
case COUNTER:
case GAUGE:
case TIMETICKS: {
uint32_t data;
elem->type = BE_UNS;
data = 0;
for (i = elem->asnlen; i != 0; p++, i--)
data = (data << 8) + GET_U_1(p);
elem->data.uns = data;
break;
}
case COUNTER64: {
uint64_t data64;
elem->type = BE_UNS64;
data64 = 0;
for (i = elem->asnlen; i != 0; p++, i--)
data64 = (data64 << 8) + GET_U_1(p);
elem->data.uns64 = data64;
break;
}
default:
elem->type = BE_OCTET;
elem->data.raw = (const uint8_t *)p;
ND_PRINT("[P/A/%s]",
Class[class].Id[id]);
break;
}
break;
case CONTEXT:
switch (id) {
case NOSUCHOBJECT:
elem->type = BE_NOSUCHOBJECT;
elem->data.raw = NULL;
break;
case NOSUCHINSTANCE:
elem->type = BE_NOSUCHINST;
elem->data.raw = NULL;
break;
case ENDOFMIBVIEW:
elem->type = BE_ENDOFMIBVIEW;
elem->data.raw = NULL;
break;
}
break;
default:
ND_PRINT("[P/%s/%s]", Class[class].name, Class[class].Id[id]);
elem->type = BE_OCTET;
elem->data.raw = (const uint8_t *)p;
break;
}
break;
case CONSTRUCTED:
switch (class) {
case UNIVERSAL:
switch (id) {
case SEQUENCE:
elem->type = BE_SEQ;
elem->data.raw = (const uint8_t *)p;
break;
default:
elem->type = BE_OCTET;
elem->data.raw = (const uint8_t *)p;
ND_PRINT("C/U/%s", Class[class].Id[id]);
break;
}
break;
case CONTEXT:
elem->type = BE_PDU;
elem->data.raw = (const uint8_t *)p;
break;
default:
elem->type = BE_OCTET;
elem->data.raw = (const uint8_t *)p;
ND_PRINT("C/%s/%s", Class[class].name, Class[class].Id[id]);
break;
}
break;
}
p += elem->asnlen;
len -= elem->asnlen;
return elem->asnlen + hdr;
trunc:
nd_print_trunc(ndo);
return -1;
}
static int
asn1_print_octets(netdissect_options *ndo, struct be *elem)
{
const u_char *p = (const u_char *)elem->data.raw;
uint32_t asnlen = elem->asnlen;
uint32_t i;
ND_TCHECK_LEN(p, asnlen);
for (i = asnlen; i != 0; p++, i--)
ND_PRINT("_%.2x", GET_U_1(p));
return 0;
trunc:
nd_print_trunc(ndo);
return -1;
}
static int
asn1_print_string(netdissect_options *ndo, struct be *elem)
{
int printable = 1, first = 1;
const u_char *p;
uint32_t asnlen = elem->asnlen;
uint32_t i;
p = elem->data.str;
ND_TCHECK_LEN(p, asnlen);
for (i = asnlen; printable && i != 0; p++, i--)
printable = ND_ASCII_ISPRINT(GET_U_1(p));
p = elem->data.str;
if (printable) {
ND_PRINT("\"");
if (nd_printn(ndo, p, asnlen, ndo->ndo_snapend)) {
ND_PRINT("\"");
goto trunc;
}
ND_PRINT("\"");
} else {
for (i = asnlen; i != 0; p++, i--) {
ND_PRINT(first ? "%.2x" : "_%.2x", GET_U_1(p));
first = 0;
}
}
return 0;
trunc:
nd_print_trunc(ndo);
return -1;
}
/*
* Display the ASN.1 object represented by the BE object.
* This used to be an integral part of asn1_parse() before the intermediate
* BE form was added.
*/
static int
asn1_print(netdissect_options *ndo,
struct be *elem)
{
const u_char *p;
uint32_t asnlen = elem->asnlen;
uint32_t i;
switch (elem->type) {
case BE_OCTET:
if (asn1_print_octets(ndo, elem) == -1)
return -1;
break;
case BE_NULL:
break;
case BE_OID: {
- int o = 0, first = -1;
+ int first = -1;
+ uint32_t o = 0;
p = (const u_char *)elem->data.raw;
i = asnlen;
if (!ndo->ndo_nflag && asnlen > 2) {
const struct obj_abrev *a = &obj_abrev_list[0];
for (; a->node; a++) {
if (i < a->oid_len)
continue;
if (!ND_TTEST_LEN(p, a->oid_len))
continue;
if (memcmp(a->oid, p, a->oid_len) == 0) {
objp = a->node->child;
i -= a->oid_len;
p += a->oid_len;
ND_PRINT("%s", a->prefix);
first = 1;
break;
}
}
}
for (; i != 0; p++, i--) {
o = (o << ASN_SHIFT7) + (GET_U_1(p) & ~ASN_BIT8);
if (GET_U_1(p) & ASN_LONGLEN)
continue;
/*
* first subitem encodes two items with
* 1st*OIDMUX+2nd
* (see X.690:1997 clause 8.19 for the details)
*/
if (first < 0) {
int s;
if (!ndo->ndo_nflag)
objp = mibroot;
first = 0;
s = o / OIDMUX;
if (s > 2) s = 2;
OBJ_PRINT(s, first);
o -= s * OIDMUX;
}
OBJ_PRINT(o, first);
if (--first < 0)
first = 0;
o = 0;
}
break;
}
case BE_INT:
ND_PRINT("%d", elem->data.integer);
break;
case BE_UNS:
ND_PRINT("%u", elem->data.uns);
break;
case BE_UNS64:
ND_PRINT("%" PRIu64, elem->data.uns64);
break;
case BE_STR:
if (asn1_print_string(ndo, elem) == -1)
return -1;
break;
case BE_SEQ:
ND_PRINT("Seq(%u)", elem->asnlen);
break;
case BE_INETADDR:
if (asnlen != ASNLEN_INETADDR)
ND_PRINT("[inetaddr len!=%d]", ASNLEN_INETADDR);
p = (const u_char *)elem->data.raw;
ND_TCHECK_LEN(p, asnlen);
for (i = asnlen; i != 0; p++, i--) {
ND_PRINT((i == asnlen) ? "%u" : ".%u", GET_U_1(p));
}
break;
case BE_NOSUCHOBJECT:
case BE_NOSUCHINST:
case BE_ENDOFMIBVIEW:
ND_PRINT("[%s]", Class[EXCEPTIONS].Id[elem->id]);
break;
case BE_PDU:
ND_PRINT("%s(%u)", Class[CONTEXT].Id[elem->id], elem->asnlen);
break;
case BE_ANY:
ND_PRINT("[BE_ANY!?]");
break;
default:
ND_PRINT("[be!?]");
break;
}
return 0;
trunc:
nd_print_trunc(ndo);
return -1;
}
#ifdef notdef
/*
* This is a brute force ASN.1 printer: recurses to dump an entire structure.
* This will work for any ASN.1 stream, not just an SNMP PDU.
*
* By adding newlines and spaces at the correct places, this would print in
* Rose-Normal-Form.
*
* This is not currently used.
*/
static void
asn1_decode(u_char *p, u_int length)
{
struct be elem;
int i = 0;
while (i >= 0 && length > 0) {
i = asn1_parse(ndo, p, length, &elem);
if (i >= 0) {
ND_PRINT(" ");
if (asn1_print(ndo, &elem) < 0)
return;
if (elem.type == BE_SEQ || elem.type == BE_PDU) {
ND_PRINT(" {");
asn1_decode(elem.data.raw, elem.asnlen);
ND_PRINT(" }");
}
length -= i;
p += i;
}
}
}
#endif
#ifdef USE_LIBSMI
struct smi2be {
SmiBasetype basetype;
int be;
};
static const struct smi2be smi2betab[] = {
{ SMI_BASETYPE_INTEGER32, BE_INT },
{ SMI_BASETYPE_OCTETSTRING, BE_STR },
{ SMI_BASETYPE_OCTETSTRING, BE_INETADDR },
{ SMI_BASETYPE_OBJECTIDENTIFIER, BE_OID },
{ SMI_BASETYPE_UNSIGNED32, BE_UNS },
{ SMI_BASETYPE_INTEGER64, BE_NONE },
{ SMI_BASETYPE_UNSIGNED64, BE_UNS64 },
{ SMI_BASETYPE_FLOAT32, BE_NONE },
{ SMI_BASETYPE_FLOAT64, BE_NONE },
{ SMI_BASETYPE_FLOAT128, BE_NONE },
{ SMI_BASETYPE_ENUM, BE_INT },
{ SMI_BASETYPE_BITS, BE_STR },
{ SMI_BASETYPE_UNKNOWN, BE_NONE }
};
static int
smi_decode_oid(netdissect_options *ndo,
struct be *elem, unsigned int *oid,
unsigned int oidsize, unsigned int *oidlen)
{
const u_char *p = (const u_char *)elem->data.raw;
uint32_t asnlen = elem->asnlen;
uint32_t i = asnlen;
int o = 0, first = -1;
unsigned int firstval;
for (*oidlen = 0; i != 0; p++, i--) {
o = (o << ASN_SHIFT7) + (GET_U_1(p) & ~ASN_BIT8);
if (GET_U_1(p) & ASN_LONGLEN)
continue;
/*
* first subitem encodes two items with 1st*OIDMUX+2nd
* (see X.690:1997 clause 8.19 for the details)
*/
if (first < 0) {
first = 0;
firstval = o / OIDMUX;
if (firstval > 2) firstval = 2;
o -= firstval * OIDMUX;
if (*oidlen < oidsize) {
oid[(*oidlen)++] = firstval;
}
}
if (*oidlen < oidsize) {
oid[(*oidlen)++] = o;
}
o = 0;
}
return 0;
}
static int smi_check_type(SmiBasetype basetype, int be)
{
int i;
for (i = 0; smi2betab[i].basetype != SMI_BASETYPE_UNKNOWN; i++) {
if (smi2betab[i].basetype == basetype && smi2betab[i].be == be) {
return 1;
}
}
return 0;
}
static int smi_check_a_range(SmiType *smiType, SmiRange *smiRange,
struct be *elem)
{
int ok = 1;
switch (smiType->basetype) {
case SMI_BASETYPE_OBJECTIDENTIFIER:
case SMI_BASETYPE_OCTETSTRING:
if (smiRange->minValue.value.unsigned32
== smiRange->maxValue.value.unsigned32) {
ok = (elem->asnlen == smiRange->minValue.value.unsigned32);
} else {
ok = (elem->asnlen >= smiRange->minValue.value.unsigned32
&& elem->asnlen <= smiRange->maxValue.value.unsigned32);
}
break;
case SMI_BASETYPE_INTEGER32:
ok = (elem->data.integer >= smiRange->minValue.value.integer32
&& elem->data.integer <= smiRange->maxValue.value.integer32);
break;
case SMI_BASETYPE_UNSIGNED32:
ok = (elem->data.uns >= smiRange->minValue.value.unsigned32
&& elem->data.uns <= smiRange->maxValue.value.unsigned32);
break;
case SMI_BASETYPE_UNSIGNED64:
/* XXX */
break;
/* case SMI_BASETYPE_INTEGER64: SMIng */
/* case SMI_BASETYPE_FLOAT32: SMIng */
/* case SMI_BASETYPE_FLOAT64: SMIng */
/* case SMI_BASETYPE_FLOAT128: SMIng */
case SMI_BASETYPE_ENUM:
case SMI_BASETYPE_BITS:
case SMI_BASETYPE_UNKNOWN:
ok = 1;
break;
default:
ok = 0;
break;
}
return ok;
}
static int smi_check_range(SmiType *smiType, struct be *elem)
{
SmiRange *smiRange;
int ok = 1;
for (smiRange = smiGetFirstRange(smiType);
smiRange;
smiRange = smiGetNextRange(smiRange)) {
ok = smi_check_a_range(smiType, smiRange, elem);
if (ok) {
break;
}
}
if (ok) {
SmiType *parentType;
parentType = smiGetParentType(smiType);
if (parentType) {
ok = smi_check_range(parentType, elem);
}
}
return ok;
}
static SmiNode *
smi_print_variable(netdissect_options *ndo,
struct be *elem, int *status)
{
unsigned int oid[128], oidlen;
SmiNode *smiNode = NULL;
unsigned int i;
if (!nd_smi_module_loaded) {
*status = asn1_print(ndo, elem);
return NULL;
}
*status = smi_decode_oid(ndo, elem, oid, sizeof(oid) / sizeof(unsigned int),
&oidlen);
if (*status < 0)
return NULL;
smiNode = smiGetNodeByOID(oidlen, oid);
if (! smiNode) {
*status = asn1_print(ndo, elem);
return NULL;
}
if (ndo->ndo_vflag) {
ND_PRINT("%s::", smiGetNodeModule(smiNode)->name);
}
ND_PRINT("%s", smiNode->name);
if (smiNode->oidlen < oidlen) {
for (i = smiNode->oidlen; i < oidlen; i++) {
ND_PRINT(".%u", oid[i]);
}
}
*status = 0;
return smiNode;
}
static int
smi_print_value(netdissect_options *ndo,
SmiNode *smiNode, u_short pduid, struct be *elem)
{
unsigned int i, oid[128], oidlen;
SmiType *smiType;
SmiNamedNumber *nn;
int done = 0;
if (! smiNode || ! (smiNode->nodekind
& (SMI_NODEKIND_SCALAR | SMI_NODEKIND_COLUMN))) {
return asn1_print(ndo, elem);
}
if (elem->type == BE_NOSUCHOBJECT
|| elem->type == BE_NOSUCHINST
|| elem->type == BE_ENDOFMIBVIEW) {
return asn1_print(ndo, elem);
}
if (NOTIFY_CLASS(pduid) && smiNode->access < SMI_ACCESS_NOTIFY) {
- ND_PRINT("[notNotifyable]");
+ ND_PRINT("[notNotifiable]");
}
if (READ_CLASS(pduid) && smiNode->access < SMI_ACCESS_READ_ONLY) {
ND_PRINT("[notReadable]");
}
if (WRITE_CLASS(pduid) && smiNode->access < SMI_ACCESS_READ_WRITE) {
ND_PRINT("[notWritable]");
}
if (RESPONSE_CLASS(pduid)
&& smiNode->access == SMI_ACCESS_NOT_ACCESSIBLE) {
ND_PRINT("[noAccess]");
}
smiType = smiGetNodeType(smiNode);
if (! smiType) {
return asn1_print(ndo, elem);
}
if (! smi_check_type(smiType->basetype, elem->type)) {
ND_PRINT("[wrongType]");
}
if (! smi_check_range(smiType, elem)) {
ND_PRINT("[outOfRange]");
}
/* resolve bits to named bits */
/* check whether instance identifier is valid */
/* apply display hints (integer, octetstring) */
/* convert instance identifier to index type values */
switch (elem->type) {
case BE_OID:
if (smiType->basetype == SMI_BASETYPE_BITS) {
/* print bit labels */
} else {
if (nd_smi_module_loaded &&
smi_decode_oid(ndo, elem, oid,
sizeof(oid)/sizeof(unsigned int),
&oidlen) == 0) {
smiNode = smiGetNodeByOID(oidlen, oid);
if (smiNode) {
if (ndo->ndo_vflag) {
ND_PRINT("%s::", smiGetNodeModule(smiNode)->name);
}
ND_PRINT("%s", smiNode->name);
if (smiNode->oidlen < oidlen) {
for (i = smiNode->oidlen;
i < oidlen; i++) {
ND_PRINT(".%u", oid[i]);
}
}
done++;
}
}
}
break;
case BE_INT:
if (smiType->basetype == SMI_BASETYPE_ENUM) {
for (nn = smiGetFirstNamedNumber(smiType);
nn;
nn = smiGetNextNamedNumber(nn)) {
if (nn->value.value.integer32
== elem->data.integer) {
ND_PRINT("%s", nn->name);
ND_PRINT("(%d)", elem->data.integer);
done++;
break;
}
}
}
break;
}
if (! done) {
return asn1_print(ndo, elem);
}
return 0;
}
#endif
/*
* General SNMP header
* SEQUENCE {
* version INTEGER {version-1(0)},
* community OCTET STRING,
* data ANY -- PDUs
* }
* PDUs for all but Trap: (see rfc1157 from page 15 on)
* SEQUENCE {
* request-id INTEGER,
* error-status INTEGER,
* error-index INTEGER,
* varbindlist SEQUENCE OF
* SEQUENCE {
* name ObjectName,
* value ObjectValue
* }
* }
* PDU for Trap:
* SEQUENCE {
* enterprise OBJECT IDENTIFIER,
* agent-addr NetworkAddress,
* generic-trap INTEGER,
* specific-trap INTEGER,
* time-stamp TimeTicks,
* varbindlist SEQUENCE OF
* SEQUENCE {
* name ObjectName,
* value ObjectValue
* }
* }
*/
/*
* Decode SNMP varBind
*/
static void
varbind_print(netdissect_options *ndo,
u_short pduid, const u_char *np, u_int length)
{
struct be elem;
int count = 0;
#ifdef USE_LIBSMI
SmiNode *smiNode = NULL;
#endif
int status;
/* Sequence of varBind */
if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
return;
if (elem.type != BE_SEQ) {
ND_PRINT("[!SEQ of varbind]");
asn1_print(ndo, &elem);
return;
}
if ((u_int)count < length)
ND_PRINT("[%d extra after SEQ of varbind]", length - count);
/* descend */
length = elem.asnlen;
np = (const u_char *)elem.data.raw;
while (length) {
const u_char *vbend;
u_int vblength;
ND_PRINT(" ");
/* Sequence */
if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
return;
if (elem.type != BE_SEQ) {
ND_PRINT("[!varbind]");
asn1_print(ndo, &elem);
return;
}
vbend = np + count;
vblength = length - count;
/* descend */
length = elem.asnlen;
np = (const u_char *)elem.data.raw;
/* objName (OID) */
if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
return;
if (elem.type != BE_OID) {
ND_PRINT("[objName!=OID]");
asn1_print(ndo, &elem);
return;
}
#ifdef USE_LIBSMI
smiNode = smi_print_variable(ndo, &elem, &status);
#else
status = asn1_print(ndo, &elem);
#endif
if (status < 0)
return;
length -= count;
np += count;
if (pduid != GETREQ && pduid != GETNEXTREQ
&& pduid != GETBULKREQ)
ND_PRINT("=");
/* objVal (ANY) */
if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
return;
if (pduid == GETREQ || pduid == GETNEXTREQ
|| pduid == GETBULKREQ) {
if (elem.type != BE_NULL) {
ND_PRINT("[objVal!=NULL]");
if (asn1_print(ndo, &elem) < 0)
return;
}
} else {
if (elem.type != BE_NULL) {
#ifdef USE_LIBSMI
status = smi_print_value(ndo, smiNode, pduid, &elem);
#else
status = asn1_print(ndo, &elem);
#endif
}
if (status < 0)
return;
}
length = vblength;
np = vbend;
}
}
/*
* Decode SNMP PDUs: GetRequest, GetNextRequest, GetResponse, SetRequest,
* GetBulk, Inform, V2Trap, and Report
*/
static void
snmppdu_print(netdissect_options *ndo,
u_short pduid, const u_char *np, u_int length)
{
struct be elem;
int count = 0, error_status;
/* reqId (Integer) */
if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
return;
if (elem.type != BE_INT) {
ND_PRINT("[reqId!=INT]");
asn1_print(ndo, &elem);
return;
}
if (ndo->ndo_vflag)
ND_PRINT("R=%d ", elem.data.integer);
length -= count;
np += count;
/* errorStatus (Integer) */
if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
return;
if (elem.type != BE_INT) {
ND_PRINT("[errorStatus!=INT]");
asn1_print(ndo, &elem);
return;
}
error_status = 0;
if ((pduid == GETREQ || pduid == GETNEXTREQ || pduid == SETREQ
|| pduid == INFORMREQ || pduid == V2TRAP || pduid == REPORT)
&& elem.data.integer != 0) {
char errbuf[20];
ND_PRINT("[errorStatus(%s)!=0]",
DECODE_ErrorStatus(elem.data.integer));
} else if (pduid == GETBULKREQ) {
ND_PRINT(" N=%d", elem.data.integer);
} else if (elem.data.integer != 0) {
char errbuf[20];
ND_PRINT(" %s", DECODE_ErrorStatus(elem.data.integer));
error_status = elem.data.integer;
}
length -= count;
np += count;
/* errorIndex (Integer) */
if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
return;
if (elem.type != BE_INT) {
ND_PRINT("[errorIndex!=INT]");
asn1_print(ndo, &elem);
return;
}
if ((pduid == GETREQ || pduid == GETNEXTREQ || pduid == SETREQ
|| pduid == INFORMREQ || pduid == V2TRAP || pduid == REPORT)
&& elem.data.integer != 0)
ND_PRINT("[errorIndex(%d)!=0]", elem.data.integer);
else if (pduid == GETBULKREQ)
ND_PRINT(" M=%d", elem.data.integer);
else if (elem.data.integer != 0) {
if (!error_status)
ND_PRINT("[errorIndex(%d) w/o errorStatus]", elem.data.integer);
else
ND_PRINT("@%d", elem.data.integer);
} else if (error_status) {
ND_PRINT("[errorIndex==0]");
}
length -= count;
np += count;
varbind_print(ndo, pduid, np, length);
}
/*
* Decode SNMP Trap PDU
*/
static void
trappdu_print(netdissect_options *ndo,
const u_char *np, u_int length)
{
struct be elem;
int count = 0, generic;
ND_PRINT(" ");
/* enterprise (oid) */
if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
return;
if (elem.type != BE_OID) {
ND_PRINT("[enterprise!=OID]");
asn1_print(ndo, &elem);
return;
}
if (asn1_print(ndo, &elem) < 0)
return;
length -= count;
np += count;
ND_PRINT(" ");
/* agent-addr (inetaddr) */
if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
return;
if (elem.type != BE_INETADDR) {
ND_PRINT("[agent-addr!=INETADDR]");
asn1_print(ndo, &elem);
return;
}
if (asn1_print(ndo, &elem) < 0)
return;
length -= count;
np += count;
/* generic-trap (Integer) */
if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
return;
if (elem.type != BE_INT) {
ND_PRINT("[generic-trap!=INT]");
asn1_print(ndo, &elem);
return;
}
generic = elem.data.integer;
{
char buf[20];
ND_PRINT(" %s", DECODE_GenericTrap(generic));
}
length -= count;
np += count;
/* specific-trap (Integer) */
if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
return;
if (elem.type != BE_INT) {
ND_PRINT("[specific-trap!=INT]");
asn1_print(ndo, &elem);
return;
}
if (generic != GT_ENTERPRISE) {
if (elem.data.integer != 0)
ND_PRINT("[specific-trap(%d)!=0]", elem.data.integer);
} else
ND_PRINT(" s=%d", elem.data.integer);
length -= count;
np += count;
ND_PRINT(" ");
/* time-stamp (TimeTicks) */
if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
return;
if (elem.type != BE_UNS) { /* XXX */
ND_PRINT("[time-stamp!=TIMETICKS]");
asn1_print(ndo, &elem);
return;
}
if (asn1_print(ndo, &elem) < 0)
return;
length -= count;
np += count;
varbind_print(ndo, TRAP, np, length);
}
/*
* Decode arbitrary SNMP PDUs.
*/
static void
pdu_print(netdissect_options *ndo,
const u_char *np, u_int length, int version)
{
struct be pdu;
int count = 0;
/* PDU (Context) */
if ((count = asn1_parse(ndo, np, length, &pdu)) < 0)
return;
if (pdu.type != BE_PDU) {
ND_PRINT("[no PDU]");
return;
}
if ((u_int)count < length)
ND_PRINT("[%d extra after PDU]", length - count);
if (ndo->ndo_vflag) {
ND_PRINT("{ ");
}
if (asn1_print(ndo, &pdu) < 0)
return;
ND_PRINT(" ");
/* descend into PDU */
length = pdu.asnlen;
np = (const u_char *)pdu.data.raw;
if (version == SNMP_VERSION_1 &&
(pdu.id == GETBULKREQ || pdu.id == INFORMREQ ||
pdu.id == V2TRAP || pdu.id == REPORT)) {
ND_PRINT("[v2 PDU in v1 message]");
return;
}
if (version == SNMP_VERSION_2 && pdu.id == TRAP) {
ND_PRINT("[v1 PDU in v2 message]");
return;
}
switch (pdu.id) {
case TRAP:
trappdu_print(ndo, np, length);
break;
case GETREQ:
case GETNEXTREQ:
case GETRESP:
case SETREQ:
case GETBULKREQ:
case INFORMREQ:
case V2TRAP:
case REPORT:
snmppdu_print(ndo, pdu.id, np, length);
break;
}
if (ndo->ndo_vflag) {
ND_PRINT(" } ");
}
}
/*
* Decode a scoped SNMP PDU.
*/
static void
scopedpdu_print(netdissect_options *ndo,
const u_char *np, u_int length, int version)
{
struct be elem;
int count = 0;
/* Sequence */
if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
return;
if (elem.type != BE_SEQ) {
ND_PRINT("[!scoped PDU]");
asn1_print(ndo, &elem);
return;
}
length = elem.asnlen;
np = (const u_char *)elem.data.raw;
/* contextEngineID (OCTET STRING) */
if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
return;
if (elem.type != BE_STR) {
ND_PRINT("[contextEngineID!=STR]");
asn1_print(ndo, &elem);
return;
}
length -= count;
np += count;
ND_PRINT("E=");
if (asn1_print_octets(ndo, &elem) == -1)
return;
ND_PRINT(" ");
/* contextName (OCTET STRING) */
if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
return;
if (elem.type != BE_STR) {
ND_PRINT("[contextName!=STR]");
asn1_print(ndo, &elem);
return;
}
length -= count;
np += count;
ND_PRINT("C=");
if (asn1_print_string(ndo, &elem) == -1)
return;
ND_PRINT(" ");
pdu_print(ndo, np, length, version);
}
/*
* Decode SNMP Community Header (SNMPv1 and SNMPv2c)
*/
static void
community_print(netdissect_options *ndo,
const u_char *np, u_int length, int version)
{
struct be elem;
int count = 0;
/* Community (String) */
if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
return;
if (elem.type != BE_STR) {
ND_PRINT("[comm!=STR]");
asn1_print(ndo, &elem);
return;
}
/* default community */
if (!(elem.asnlen == sizeof(DEF_COMMUNITY) - 1 &&
strncmp((const char *)elem.data.str, DEF_COMMUNITY,
sizeof(DEF_COMMUNITY) - 1) == 0)) {
/* ! "public" */
ND_PRINT("C=");
if (asn1_print_string(ndo, &elem) == -1)
return;
ND_PRINT(" ");
}
length -= count;
np += count;
pdu_print(ndo, np, length, version);
}
/*
* Decode SNMPv3 User-based Security Message Header (SNMPv3)
*/
static void
usm_print(netdissect_options *ndo,
const u_char *np, u_int length)
{
struct be elem;
int count = 0;
/* Sequence */
if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
return;
if (elem.type != BE_SEQ) {
ND_PRINT("[!usm]");
asn1_print(ndo, &elem);
return;
}
length = elem.asnlen;
np = (const u_char *)elem.data.raw;
/* msgAuthoritativeEngineID (OCTET STRING) */
if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
return;
if (elem.type != BE_STR) {
ND_PRINT("[msgAuthoritativeEngineID!=STR]");
asn1_print(ndo, &elem);
return;
}
length -= count;
np += count;
/* msgAuthoritativeEngineBoots (INTEGER) */
if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
return;
if (elem.type != BE_INT) {
ND_PRINT("[msgAuthoritativeEngineBoots!=INT]");
asn1_print(ndo, &elem);
return;
}
if (ndo->ndo_vflag)
ND_PRINT("B=%d ", elem.data.integer);
length -= count;
np += count;
/* msgAuthoritativeEngineTime (INTEGER) */
if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
return;
if (elem.type != BE_INT) {
ND_PRINT("[msgAuthoritativeEngineTime!=INT]");
asn1_print(ndo, &elem);
return;
}
if (ndo->ndo_vflag)
ND_PRINT("T=%d ", elem.data.integer);
length -= count;
np += count;
/* msgUserName (OCTET STRING) */
if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
return;
if (elem.type != BE_STR) {
ND_PRINT("[msgUserName!=STR]");
asn1_print(ndo, &elem);
return;
}
length -= count;
np += count;
ND_PRINT("U=");
if (asn1_print_string(ndo, &elem) == -1)
return;
ND_PRINT(" ");
/* msgAuthenticationParameters (OCTET STRING) */
if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
return;
if (elem.type != BE_STR) {
ND_PRINT("[msgAuthenticationParameters!=STR]");
asn1_print(ndo, &elem);
return;
}
length -= count;
np += count;
/* msgPrivacyParameters (OCTET STRING) */
if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
return;
if (elem.type != BE_STR) {
ND_PRINT("[msgPrivacyParameters!=STR]");
asn1_print(ndo, &elem);
return;
}
length -= count;
np += count;
if ((u_int)count < length)
ND_PRINT("[%d extra after usm SEQ]", length - count);
}
/*
* Decode SNMPv3 Message Header (SNMPv3)
*/
static void
v3msg_print(netdissect_options *ndo,
const u_char *np, u_int length)
{
struct be elem;
int count = 0;
u_char flags;
int model;
const u_char *xnp = np;
int xlength = length;
/* Sequence */
if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
return;
if (elem.type != BE_SEQ) {
ND_PRINT("[!message]");
asn1_print(ndo, &elem);
return;
}
length = elem.asnlen;
np = (const u_char *)elem.data.raw;
if (ndo->ndo_vflag) {
ND_PRINT("{ ");
}
/* msgID (INTEGER) */
if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
return;
if (elem.type != BE_INT) {
ND_PRINT("[msgID!=INT]");
asn1_print(ndo, &elem);
return;
}
length -= count;
np += count;
/* msgMaxSize (INTEGER) */
if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
return;
if (elem.type != BE_INT) {
ND_PRINT("[msgMaxSize!=INT]");
asn1_print(ndo, &elem);
return;
}
length -= count;
np += count;
/* msgFlags (OCTET STRING) */
if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
return;
if (elem.type != BE_STR) {
ND_PRINT("[msgFlags!=STR]");
asn1_print(ndo, &elem);
return;
}
if (elem.asnlen != 1) {
ND_PRINT("[msgFlags size %d]", elem.asnlen);
return;
}
flags = GET_U_1(elem.data.str);
if (flags != 0x00 && flags != 0x01 && flags != 0x03
&& flags != 0x04 && flags != 0x05 && flags != 0x07) {
ND_PRINT("[msgFlags=0x%02X]", flags);
return;
}
length -= count;
np += count;
ND_PRINT("F=%s%s%s ",
flags & 0x01 ? "a" : "",
flags & 0x02 ? "p" : "",
flags & 0x04 ? "r" : "");
/* msgSecurityModel (INTEGER) */
if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
return;
if (elem.type != BE_INT) {
ND_PRINT("[msgSecurityModel!=INT]");
asn1_print(ndo, &elem);
return;
}
model = elem.data.integer;
length -= count;
np += count;
if ((u_int)count < length)
ND_PRINT("[%d extra after message SEQ]", length - count);
if (ndo->ndo_vflag) {
ND_PRINT("} ");
}
if (model == 3) {
if (ndo->ndo_vflag) {
ND_PRINT("{ USM ");
}
} else {
ND_PRINT("[security model %d]", model);
return;
}
np = xnp + (np - xnp);
length = xlength - (np - xnp);
/* msgSecurityParameters (OCTET STRING) */
if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
return;
if (elem.type != BE_STR) {
ND_PRINT("[msgSecurityParameters!=STR]");
asn1_print(ndo, &elem);
return;
}
length -= count;
np += count;
if (model == 3) {
usm_print(ndo, elem.data.str, elem.asnlen);
if (ndo->ndo_vflag) {
ND_PRINT("} ");
}
}
if (ndo->ndo_vflag) {
ND_PRINT("{ ScopedPDU ");
}
scopedpdu_print(ndo, np, length, 3);
if (ndo->ndo_vflag) {
ND_PRINT("} ");
}
}
/*
* Decode SNMP header and pass on to PDU printing routines
*/
void
snmp_print(netdissect_options *ndo,
const u_char *np, u_int length)
{
struct be elem;
int count = 0;
int version = 0;
ndo->ndo_protocol = "snmp";
ND_PRINT(" ");
/* initial Sequence */
if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
return;
if (elem.type != BE_SEQ) {
ND_PRINT("[!init SEQ]");
asn1_print(ndo, &elem);
return;
}
if ((u_int)count < length)
ND_PRINT("[%d extra after iSEQ]", length - count);
/* descend */
length = elem.asnlen;
np = (const u_char *)elem.data.raw;
/* Version (INTEGER) */
if ((count = asn1_parse(ndo, np, length, &elem)) < 0)
return;
if (elem.type != BE_INT) {
ND_PRINT("[version!=INT]");
asn1_print(ndo, &elem);
return;
}
switch (elem.data.integer) {
case SNMP_VERSION_1:
case SNMP_VERSION_2:
case SNMP_VERSION_3:
if (ndo->ndo_vflag)
ND_PRINT("{ %s ", SnmpVersion[elem.data.integer]);
break;
default:
ND_PRINT("SNMP [version = %d]", elem.data.integer);
return;
}
version = elem.data.integer;
length -= count;
np += count;
switch (version) {
case SNMP_VERSION_1:
case SNMP_VERSION_2:
community_print(ndo, np, length, version);
break;
case SNMP_VERSION_3:
v3msg_print(ndo, np, length);
break;
default:
ND_PRINT("[version = %d]", elem.data.integer);
break;
}
if (ndo->ndo_vflag) {
ND_PRINT("} ");
}
}
diff --git a/contrib/tcpdump/print-someip.c b/contrib/tcpdump/print-someip.c
index 210e413f6481..d21219aeadfb 100644
--- a/contrib/tcpdump/print-someip.c
+++ b/contrib/tcpdump/print-someip.c
@@ -1,142 +1,139 @@
/*
* 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.
*
* Original code by Francesco Fondelli (francesco dot fondelli, gmail dot com)
*/
/* \summary: Autosar SOME/IP Protocol printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "extract.h"
-#include "udp.h"
/*
* SOMEIP Header (R19-11)
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Message ID (Service ID/Method ID) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Length |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Request ID (Client ID/Session ID) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Protocol Ver | Interface Ver | Message Type | Return Code |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Payload |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
static const struct tok message_type_values[] = {
{ 0x00, "REQUEST" },
{ 0x01, "REQUEST_NO_RETURN" },
{ 0x02, "NOTIFICATION" },
{ 0x80, "RESPONSE" },
{ 0x81, "ERROR" },
{ 0x20, "TP_REQUEST" },
{ 0x21, "TP_REQUEST_NO_RETURN" },
{ 0x22, "TP_NOTIFICATION" },
{ 0xa0, "TP_RESPONSE" },
{ 0xa1, "TP_ERROR" },
{ 0, NULL }
};
static const struct tok return_code_values[] = {
{ 0x00, "E_OK" },
{ 0x01, "E_NOT_OK" },
{ 0x02, "E_UNKNOWN_SERVICE" },
{ 0x03, "E_UNKNOWN_METHOD" },
{ 0x04, "E_NOT_READY" },
{ 0x05, "E_NOT_REACHABLE" },
{ 0x06, "E_TIMEOUT" },
{ 0x07, "E_WRONG_PROTOCOL_VERSION" },
{ 0x08, "E_WRONG_INTERFACE_VERSION" },
{ 0x09, "E_MALFORMED_MESSAGE" },
{ 0x0a, "E_WRONG_MESSAGE_TYPE" },
{ 0x0b, "E_E2E_REPEATED" },
{ 0x0c, "E_E2E_WRONG_SEQUENCE" },
{ 0x0d, "E_E2E" },
{ 0x0e, "E_E2E_NOT_AVAILABLE" },
{ 0x0f, "E_E2E_NO_NEW_DATA" },
{ 0, NULL }
};
void
someip_print(netdissect_options *ndo, const u_char *bp, const u_int len)
{
uint32_t message_id;
uint16_t service_id;
uint16_t method_or_event_id;
uint8_t event_flag;
uint32_t message_len;
uint32_t request_id;
uint16_t client_id;
uint16_t session_id;
uint8_t protocol_version;
uint8_t interface_version;
uint8_t message_type;
uint8_t return_code;
ndo->ndo_protocol = "someip";
nd_print_protocol_caps(ndo);
if (len < 16) {
goto invalid;
}
message_id = GET_BE_U_4(bp);
service_id = message_id >> 16;
event_flag = (message_id & 0x00008000) >> 15;
method_or_event_id = message_id & 0x00007FFF;
bp += 4;
ND_PRINT(", service %u, %s %u",
service_id, event_flag ? "event" : "method", method_or_event_id);
message_len = GET_BE_U_4(bp);
bp += 4;
ND_PRINT(", len %u", message_len);
request_id = GET_BE_U_4(bp);
client_id = request_id >> 16;
session_id = request_id & 0x0000FFFF;
bp += 4;
ND_PRINT(", client %u, session %u", client_id, session_id);
protocol_version = GET_U_1(bp);
bp += 1;
ND_PRINT(", pver %u", protocol_version);
interface_version = GET_U_1(bp);
bp += 1;
ND_PRINT(", iver %u", interface_version);
message_type = GET_U_1(bp);
bp += 1;
ND_PRINT(", msgtype %s",
tok2str(message_type_values, "Unknown", message_type));
return_code = GET_U_1(bp);
bp += 1;
ND_PRINT(", retcode %s\n",
tok2str(return_code_values, "Unknown", return_code));
return;
invalid:
nd_print_invalid(ndo);
}
diff --git a/contrib/tcpdump/print-ssh.c b/contrib/tcpdump/print-ssh.c
index 5207c52ee247..f9dd419cb5ae 100644
--- a/contrib/tcpdump/print-ssh.c
+++ b/contrib/tcpdump/print-ssh.c
@@ -1,99 +1,97 @@
/*
* 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.
*/
/* \summary: Secure Shell (SSH) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect-ctype.h"
#include "netdissect.h"
#include "extract.h"
static int
ssh_print_version(netdissect_options *ndo, const u_char *pptr, u_int len)
{
u_int idx = 0;
if ( GET_U_1(pptr+idx) != 'S' )
return 0;
idx++;
if ( GET_U_1(pptr+idx) != 'S' )
return 0;
idx++;
if ( GET_U_1(pptr+idx) != 'H' )
return 0;
idx++;
if ( GET_U_1(pptr+idx) != '-' )
return 0;
idx++;
while (idx < len) {
u_char c;
c = GET_U_1(pptr + idx);
if (c == '\n') {
/*
* LF without CR; end of line.
* Skip the LF and print the line, with the
* exception of the LF.
*/
goto print;
} else if (c == '\r') {
/* CR - any LF? */
if ((idx+1) >= len) {
/* not in this packet */
goto trunc;
}
if (GET_U_1(pptr + idx + 1) == '\n') {
/*
* CR-LF; end of line.
* Skip the CR-LF and print the line, with
* the exception of the CR-LF.
*/
goto print;
}
/*
* CR followed by something else; treat this as
* if it were binary data and don't print it.
*/
goto trunc;
} else if (!ND_ASCII_ISPRINT(c) ) {
/*
* Not a printable ASCII character; treat this
* as if it were binary data and don't print it.
*/
goto trunc;
}
idx++;
}
trunc:
return -1;
print:
ND_PRINT(": ");
nd_print_protocol_caps(ndo);
ND_PRINT(": %.*s", (int)idx, pptr);
return idx;
}
void
ssh_print(netdissect_options *ndo, const u_char *pptr, u_int len)
{
ndo->ndo_protocol = "ssh";
ssh_print_version(ndo, pptr, len);
}
diff --git a/contrib/tcpdump/print-stp.c b/contrib/tcpdump/print-stp.c
index a4d49c4797f8..7e928b33f3b1 100644
--- a/contrib/tcpdump/print-stp.c
+++ b/contrib/tcpdump/print-stp.c
@@ -1,471 +1,468 @@
/*
* Copyright (c) 2000 Lennert Buytenhek
*
* This software may be distributed either under the terms of the
* BSD-style license that accompanies tcpdump or the GNU General
* Public License
*
* Contributed by Lennert Buytenhek <buytenh@gnu.org>
*/
/* \summary: IEEE 802.1d Spanning Tree Protocol (STP) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <stdio.h>
#include "netdissect.h"
#include "extract.h"
#define RSTP_EXTRACT_PORT_ROLE(x) (((x)&0x0C)>>2)
/* STP timers are expressed in multiples of 1/256th second */
#define STP_TIME_BASE 256
#define STP_BPDU_MSTP_MIN_LEN 102
struct stp_bpdu_ {
nd_uint16_t protocol_id;
nd_uint8_t protocol_version;
nd_uint8_t bpdu_type;
nd_uint8_t flags;
nd_byte root_id[8];
nd_uint32_t root_path_cost;
nd_byte bridge_id[8];
nd_uint16_t port_id;
nd_uint16_t message_age;
nd_uint16_t max_age;
nd_uint16_t hello_time;
nd_uint16_t forward_delay;
nd_uint8_t v1_length;
};
#define STP_PROTO_REGULAR 0x00
#define STP_PROTO_RAPID 0x02
#define STP_PROTO_MSTP 0x03
#define STP_PROTO_SPB 0x04
static const struct tok stp_proto_values[] = {
{ STP_PROTO_REGULAR, "802.1d" },
{ STP_PROTO_RAPID, "802.1w" },
{ STP_PROTO_MSTP, "802.1s" },
{ STP_PROTO_SPB, "802.1aq" },
{ 0, NULL}
};
#define STP_BPDU_TYPE_CONFIG 0x00
#define STP_BPDU_TYPE_RSTP 0x02
#define STP_BPDU_TYPE_TOPO_CHANGE 0x80
static const struct tok stp_bpdu_flag_values[] = {
{ 0x01, "Topology change" },
{ 0x02, "Proposal" },
{ 0x10, "Learn" },
{ 0x20, "Forward" },
{ 0x40, "Agreement" },
{ 0x80, "Topology change ACK" },
{ 0, NULL}
};
static const struct tok stp_bpdu_type_values[] = {
{ STP_BPDU_TYPE_CONFIG, "Config" },
{ STP_BPDU_TYPE_RSTP, "Rapid STP" },
{ STP_BPDU_TYPE_TOPO_CHANGE, "Topology Change" },
{ 0, NULL}
};
static const struct tok rstp_obj_port_role_values[] = {
{ 0x00, "Unknown" },
{ 0x01, "Alternate" },
{ 0x02, "Root" },
{ 0x03, "Designated" },
{ 0, NULL}
};
static char *
stp_print_bridge_id(netdissect_options *ndo, const u_char *p)
{
static char bridge_id_str[sizeof("pppp.aa:bb:cc:dd:ee:ff")];
snprintf(bridge_id_str, sizeof(bridge_id_str),
"%.2x%.2x.%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
GET_U_1(p), GET_U_1(p + 1), GET_U_1(p + 2),
GET_U_1(p + 3), GET_U_1(p + 4), GET_U_1(p + 5),
GET_U_1(p + 6), GET_U_1(p + 7));
return bridge_id_str;
}
static void
stp_print_config_bpdu(netdissect_options *ndo, const struct stp_bpdu_ *stp_bpdu,
u_int length)
{
uint8_t bpdu_flags;
bpdu_flags = GET_U_1(stp_bpdu->flags);
ND_PRINT(", Flags [%s]",
bittok2str(stp_bpdu_flag_values, "none", bpdu_flags));
ND_PRINT(", bridge-id %s.%04x, length %u",
stp_print_bridge_id(ndo, stp_bpdu->bridge_id),
GET_BE_U_2(stp_bpdu->port_id), length);
/* in non-verbose mode just print the bridge-id */
if (!ndo->ndo_vflag) {
return;
}
ND_PRINT("\n\tmessage-age %.2fs, max-age %.2fs"
", hello-time %.2fs, forwarding-delay %.2fs",
(float) GET_BE_U_2(stp_bpdu->message_age) / STP_TIME_BASE,
(float) GET_BE_U_2(stp_bpdu->max_age) / STP_TIME_BASE,
(float) GET_BE_U_2(stp_bpdu->hello_time) / STP_TIME_BASE,
(float) GET_BE_U_2(stp_bpdu->forward_delay) / STP_TIME_BASE);
ND_PRINT("\n\troot-id %s, root-pathcost %u",
stp_print_bridge_id(ndo, stp_bpdu->root_id),
GET_BE_U_4(stp_bpdu->root_path_cost));
/* Port role is only valid for 802.1w */
if (GET_U_1(stp_bpdu->protocol_version) == STP_PROTO_RAPID) {
ND_PRINT(", port-role %s",
tok2str(rstp_obj_port_role_values, "Unknown",
RSTP_EXTRACT_PORT_ROLE(bpdu_flags)));
}
}
/*
* MSTP packet format
* Ref. IEEE 802.1Q 2003 Ed. Section 14
*
* MSTP BPDU
*
* 2 - bytes Protocol Id
* 1 - byte Protocol Ver.
* 1 - byte BPDU type
* 1 - byte Flags
* 8 - bytes CIST Root Identifier
* 4 - bytes CIST External Path Cost
* 8 - bytes CIST Regional Root Identifier
* 2 - bytes CIST Port Identifier
* 2 - bytes Message Age
* 2 - bytes Max age
* 2 - bytes Hello Time
* 2 - bytes Forward delay
* 1 - byte Version 1 length. Must be 0
* 2 - bytes Version 3 length
* 1 - byte Config Identifier
* 32 - bytes Config Name
* 2 - bytes Revision level
* 16 - bytes Config Digest [MD5]
* 4 - bytes CIST Internal Root Path Cost
* 8 - bytes CIST Bridge Identifier
* 1 - byte CIST Remaining Hops
* 16 - bytes MSTI information [Max 64 MSTI, each 16 bytes]
*
*
* SPB BPDU
* Ref. IEEE 802.1aq. Section 14
*
* 2 - bytes Version 4 length
* 1 - byte Aux Config Identifier
* 32 - bytes Aux Config Name
* 2 - bytes Aux Revision level
* 16 - bytes Aux Config Digest [MD5]
* 1 - byte (1 - 2) Agreement Number
* (3 - 4) Discarded Agreement Number
* (5) Agreement Valid Flag
* (6) Restricted Role Flag
* (7 - 8) Unused sent zero
* 1 - byte Unused
* 1 - byte (1 - 4) Agreement Digest Format Identifier
* (5 - 8) Agreement Digest Format Capabilities
* 1 - byte (1 - 4) Agreement Digest Convention Identifier
* (5 - 8) Agreement Digest Convention Capabilities
* 2 - bytes Agreement Digest Edge Count
* 8 - byte Reserved Set
* 20 - bytes Computed Topology Digest
*
*
* MSTI Payload
*
* 1 - byte MSTI flag
* 8 - bytes MSTI Regional Root Identifier
* 4 - bytes MSTI Regional Path Cost
* 1 - byte MSTI Bridge Priority
* 1 - byte MSTI Port Priority
* 1 - byte MSTI Remaining Hops
*
*/
#define MST_BPDU_MSTI_LENGTH 16
#define MST_BPDU_CONFIG_INFO_LENGTH 64
/* Offsets of fields from the beginning for the packet */
#define MST_BPDU_VER3_LEN_OFFSET 36
#define MST_BPDU_CONFIG_NAME_OFFSET 39
#define MST_BPDU_CONFIG_DIGEST_OFFSET 73
#define MST_BPDU_CIST_INT_PATH_COST_OFFSET 89
#define MST_BPDU_CIST_BRIDGE_ID_OFFSET 93
#define MST_BPDU_CIST_REMAIN_HOPS_OFFSET 101
#define MST_BPDU_MSTI_OFFSET 102
/* Offsets within an MSTI */
#define MST_BPDU_MSTI_ROOT_PRIO_OFFSET 1
#define MST_BPDU_MSTI_ROOT_PATH_COST_OFFSET 9
#define MST_BPDU_MSTI_BRIDGE_PRIO_OFFSET 13
#define MST_BPDU_MSTI_PORT_PRIO_OFFSET 14
#define MST_BPDU_MSTI_REMAIN_HOPS_OFFSET 15
#define SPB_BPDU_MIN_LEN 87
#define SPB_BPDU_CONFIG_NAME_OFFSET 3
#define SPB_BPDU_CONFIG_REV_OFFSET SPB_BPDU_CONFIG_NAME_OFFSET + 32
#define SPB_BPDU_CONFIG_DIGEST_OFFSET SPB_BPDU_CONFIG_REV_OFFSET + 2
#define SPB_BPDU_AGREEMENT_OFFSET SPB_BPDU_CONFIG_DIGEST_OFFSET + 16
#define SPB_BPDU_AGREEMENT_UNUSED_OFFSET SPB_BPDU_AGREEMENT_OFFSET + 1
#define SPB_BPDU_AGREEMENT_FORMAT_OFFSET SPB_BPDU_AGREEMENT_UNUSED_OFFSET + 1
#define SPB_BPDU_AGREEMENT_CON_OFFSET SPB_BPDU_AGREEMENT_FORMAT_OFFSET + 1
#define SPB_BPDU_AGREEMENT_EDGE_OFFSET SPB_BPDU_AGREEMENT_CON_OFFSET + 1
#define SPB_BPDU_AGREEMENT_RES1_OFFSET SPB_BPDU_AGREEMENT_EDGE_OFFSET + 2
#define SPB_BPDU_AGREEMENT_RES2_OFFSET SPB_BPDU_AGREEMENT_RES1_OFFSET + 4
#define SPB_BPDU_AGREEMENT_DIGEST_OFFSET SPB_BPDU_AGREEMENT_RES2_OFFSET + 4
static void
stp_print_mstp_bpdu(netdissect_options *ndo, const struct stp_bpdu_ *stp_bpdu,
u_int length)
{
const u_char *ptr;
uint8_t bpdu_flags;
uint16_t v3len;
uint16_t len;
uint16_t msti;
u_int offset;
ptr = (const u_char *)stp_bpdu;
bpdu_flags = GET_U_1(stp_bpdu->flags);
ND_PRINT(", CIST Flags [%s], length %u",
bittok2str(stp_bpdu_flag_values, "none", bpdu_flags), length);
/*
* in non-verbose mode just print the flags.
*/
if (!ndo->ndo_vflag) {
return;
}
ND_PRINT("\n\tport-role %s, ",
tok2str(rstp_obj_port_role_values, "Unknown",
RSTP_EXTRACT_PORT_ROLE(bpdu_flags)));
ND_PRINT("CIST root-id %s, CIST ext-pathcost %u",
stp_print_bridge_id(ndo, stp_bpdu->root_id),
GET_BE_U_4(stp_bpdu->root_path_cost));
ND_PRINT("\n\tCIST regional-root-id %s, ",
stp_print_bridge_id(ndo, stp_bpdu->bridge_id));
ND_PRINT("CIST port-id %04x,", GET_BE_U_2(stp_bpdu->port_id));
ND_PRINT("\n\tmessage-age %.2fs, max-age %.2fs"
", hello-time %.2fs, forwarding-delay %.2fs",
(float) GET_BE_U_2(stp_bpdu->message_age) / STP_TIME_BASE,
(float) GET_BE_U_2(stp_bpdu->max_age) / STP_TIME_BASE,
(float) GET_BE_U_2(stp_bpdu->hello_time) / STP_TIME_BASE,
(float) GET_BE_U_2(stp_bpdu->forward_delay) / STP_TIME_BASE);
ND_PRINT("\n\tv3len %u, ", GET_BE_U_2(ptr + MST_BPDU_VER3_LEN_OFFSET));
ND_PRINT("MCID Name ");
nd_printjnp(ndo, ptr + MST_BPDU_CONFIG_NAME_OFFSET, 32);
ND_PRINT(", rev %u,"
"\n\t\tdigest %08x%08x%08x%08x, ",
GET_BE_U_2(ptr + MST_BPDU_CONFIG_NAME_OFFSET + 32),
GET_BE_U_4(ptr + MST_BPDU_CONFIG_DIGEST_OFFSET),
GET_BE_U_4(ptr + MST_BPDU_CONFIG_DIGEST_OFFSET + 4),
GET_BE_U_4(ptr + MST_BPDU_CONFIG_DIGEST_OFFSET + 8),
GET_BE_U_4(ptr + MST_BPDU_CONFIG_DIGEST_OFFSET + 12));
ND_PRINT("CIST int-root-pathcost %u,",
GET_BE_U_4(ptr + MST_BPDU_CIST_INT_PATH_COST_OFFSET));
ND_PRINT("\n\tCIST bridge-id %s, ",
stp_print_bridge_id(ndo, ptr + MST_BPDU_CIST_BRIDGE_ID_OFFSET));
ND_PRINT("CIST remaining-hops %u",
GET_U_1(ptr + MST_BPDU_CIST_REMAIN_HOPS_OFFSET));
/* Dump all MSTI's */
v3len = GET_BE_U_2(ptr + MST_BPDU_VER3_LEN_OFFSET);
if (v3len > MST_BPDU_CONFIG_INFO_LENGTH) {
len = v3len - MST_BPDU_CONFIG_INFO_LENGTH;
offset = MST_BPDU_MSTI_OFFSET;
while (len >= MST_BPDU_MSTI_LENGTH) {
msti = GET_BE_U_2(ptr + offset + MST_BPDU_MSTI_ROOT_PRIO_OFFSET);
msti = msti & 0x0FFF;
ND_PRINT("\n\tMSTI %u, Flags [%s], port-role %s",
msti,
bittok2str(stp_bpdu_flag_values, "none", GET_U_1(ptr + offset)),
tok2str(rstp_obj_port_role_values, "Unknown",
RSTP_EXTRACT_PORT_ROLE(GET_U_1(ptr + offset))));
ND_PRINT("\n\t\tMSTI regional-root-id %s, pathcost %u",
stp_print_bridge_id(ndo, ptr + offset +
MST_BPDU_MSTI_ROOT_PRIO_OFFSET),
GET_BE_U_4(ptr + offset + MST_BPDU_MSTI_ROOT_PATH_COST_OFFSET));
ND_PRINT("\n\t\tMSTI bridge-prio %u, port-prio %u, hops %u",
GET_U_1(ptr + offset + MST_BPDU_MSTI_BRIDGE_PRIO_OFFSET) >> 4,
GET_U_1(ptr + offset + MST_BPDU_MSTI_PORT_PRIO_OFFSET) >> 4,
GET_U_1(ptr + offset + MST_BPDU_MSTI_REMAIN_HOPS_OFFSET));
len -= MST_BPDU_MSTI_LENGTH;
offset += MST_BPDU_MSTI_LENGTH;
}
}
}
static void
stp_print_spb_bpdu(netdissect_options *ndo, const struct stp_bpdu_ *stp_bpdu,
u_int offset)
{
const u_char *ptr;
/*
* in non-verbose mode don't print anything.
*/
if (!ndo->ndo_vflag) {
return;
}
ptr = (const u_char *)stp_bpdu;
ND_PRINT("\n\tv4len %u, ", GET_BE_U_2(ptr + offset));
ND_PRINT("AUXMCID Name ");
nd_printjnp(ndo, ptr + offset + SPB_BPDU_CONFIG_NAME_OFFSET, 32);
ND_PRINT(", Rev %u,\n\t\tdigest %08x%08x%08x%08x",
GET_BE_U_2(ptr + offset + SPB_BPDU_CONFIG_REV_OFFSET),
GET_BE_U_4(ptr + offset + SPB_BPDU_CONFIG_DIGEST_OFFSET),
GET_BE_U_4(ptr + offset + SPB_BPDU_CONFIG_DIGEST_OFFSET + 4),
GET_BE_U_4(ptr + offset + SPB_BPDU_CONFIG_DIGEST_OFFSET + 8),
GET_BE_U_4(ptr + offset + SPB_BPDU_CONFIG_DIGEST_OFFSET + 12));
ND_PRINT("\n\tAgreement num %u, Discarded Agreement num %u, Agreement valid-"
"flag %u,\n\tRestricted role-flag: %u, Format id %u cap %u, "
"Convention id %u cap %u,\n\tEdge count %u, "
"Agreement digest %08x%08x%08x%08x%08x",
GET_U_1(ptr + offset + SPB_BPDU_AGREEMENT_OFFSET)>>6,
GET_U_1(ptr + offset + SPB_BPDU_AGREEMENT_OFFSET)>>4 & 0x3,
GET_U_1(ptr + offset + SPB_BPDU_AGREEMENT_OFFSET)>>3 & 0x1,
GET_U_1(ptr + offset + SPB_BPDU_AGREEMENT_OFFSET)>>2 & 0x1,
GET_U_1(ptr + offset + SPB_BPDU_AGREEMENT_FORMAT_OFFSET)>>4,
GET_U_1(ptr + offset + SPB_BPDU_AGREEMENT_FORMAT_OFFSET)&0x00ff,
GET_U_1(ptr + offset + SPB_BPDU_AGREEMENT_CON_OFFSET)>>4,
GET_U_1(ptr + offset + SPB_BPDU_AGREEMENT_CON_OFFSET)&0x00ff,
GET_BE_U_2(ptr + offset + SPB_BPDU_AGREEMENT_EDGE_OFFSET),
GET_BE_U_4(ptr + offset + SPB_BPDU_AGREEMENT_DIGEST_OFFSET),
GET_BE_U_4(ptr + offset + SPB_BPDU_AGREEMENT_DIGEST_OFFSET + 4),
GET_BE_U_4(ptr + offset + SPB_BPDU_AGREEMENT_DIGEST_OFFSET + 8),
GET_BE_U_4(ptr + offset + SPB_BPDU_AGREEMENT_DIGEST_OFFSET + 12),
GET_BE_U_4(ptr + offset + SPB_BPDU_AGREEMENT_DIGEST_OFFSET + 16));
}
/*
* Print 802.1d / 802.1w / 802.1q (mstp) / 802.1aq (spb) packets.
*/
void
stp_print(netdissect_options *ndo, const u_char *p, u_int length)
{
const struct stp_bpdu_ *stp_bpdu;
u_int protocol_version;
u_int bpdu_type;
u_int mstp_len;
u_int spb_len;
ndo->ndo_protocol = "stp";
stp_bpdu = (const struct stp_bpdu_*)p;
/* Minimum STP Frame size. */
if (length < 4)
goto invalid;
if (GET_BE_U_2(stp_bpdu->protocol_id)) {
ND_PRINT("unknown STP version, length %u", length);
return;
}
protocol_version = GET_U_1(stp_bpdu->protocol_version);
ND_PRINT("STP %s", tok2str(stp_proto_values, "Unknown STP protocol (0x%02x)",
protocol_version));
switch (protocol_version) {
case STP_PROTO_REGULAR:
case STP_PROTO_RAPID:
case STP_PROTO_MSTP:
case STP_PROTO_SPB:
break;
default:
return;
}
bpdu_type = GET_U_1(stp_bpdu->bpdu_type);
ND_PRINT(", %s", tok2str(stp_bpdu_type_values, "Unknown BPDU Type (0x%02x)",
bpdu_type));
switch (bpdu_type) {
case STP_BPDU_TYPE_CONFIG:
if (length < sizeof(struct stp_bpdu_) - 1) {
goto invalid;
}
stp_print_config_bpdu(ndo, stp_bpdu, length);
break;
case STP_BPDU_TYPE_RSTP:
if (protocol_version == STP_PROTO_RAPID) {
if (length < sizeof(struct stp_bpdu_)) {
goto invalid;
}
stp_print_config_bpdu(ndo, stp_bpdu, length);
} else if (protocol_version == STP_PROTO_MSTP ||
protocol_version == STP_PROTO_SPB) {
if (length < STP_BPDU_MSTP_MIN_LEN) {
goto invalid;
}
if (GET_U_1(stp_bpdu->v1_length) != 0) {
/* FIX ME: Emit a message here ? */
goto invalid;
}
/* Validate v3 length */
mstp_len = GET_BE_U_2(p + MST_BPDU_VER3_LEN_OFFSET);
mstp_len += 2; /* length encoding itself is 2 bytes */
if (length < (sizeof(struct stp_bpdu_) + mstp_len)) {
goto invalid;
}
stp_print_mstp_bpdu(ndo, stp_bpdu, length);
- if (protocol_version == STP_PROTO_SPB)
- {
+ if (protocol_version == STP_PROTO_SPB) {
/* Validate v4 length */
spb_len = GET_BE_U_2(p + MST_BPDU_VER3_LEN_OFFSET + mstp_len);
spb_len += 2;
if (length < (sizeof(struct stp_bpdu_) + mstp_len + spb_len) ||
spb_len < SPB_BPDU_MIN_LEN) {
goto invalid;
}
stp_print_spb_bpdu(ndo, stp_bpdu, (sizeof(struct stp_bpdu_) + mstp_len));
}
}
break;
case STP_BPDU_TYPE_TOPO_CHANGE:
/* always empty message - just break out */
break;
default:
break;
}
return;
invalid:
nd_print_invalid(ndo);
}
diff --git a/contrib/tcpdump/print-sunatm.c b/contrib/tcpdump/print-sunatm.c
index 0fe5eee8e411..97d592c7757d 100644
--- a/contrib/tcpdump/print-sunatm.c
+++ b/contrib/tcpdump/print-sunatm.c
@@ -1,102 +1,100 @@
/*
* Copyright (c) 1997 Yen Yen Lim and North Dakota State University
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Yen Yen Lim and
North Dakota State University
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* \summary: SunATM DLPI capture printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
#include "atm.h"
/* SunATM header for ATM packet */
#define DIR_POS 0 /* Direction (0x80 = transmit, 0x00 = receive) */
#define VPI_POS 1 /* VPI */
#define VCI_POS 2 /* VCI */
#define PKT_BEGIN_POS 4 /* Start of the ATM packet */
/* Protocol type values in the bottom for bits of the byte at SUNATM_DIR_POS. */
#define PT_LANE 0x01 /* LANE */
#define PT_LLC 0x02 /* LLC encapsulation */
/*
* This is the top level routine of the printer. 'p' points
* to the SunATM pseudo-header for the packet, 'h->ts' is the timestamp,
* 'h->len' is the length of the packet off the wire, and 'h->caplen'
* is the number of bytes actually captured.
*/
void
sunatm_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h, const u_char *p)
{
u_int caplen = h->caplen;
u_int length = h->len;
u_short vci;
u_char vpi;
u_int traftype;
ndo->ndo_protocol = "sunatm";
if (ndo->ndo_eflag) {
ND_PRINT(GET_U_1(p + DIR_POS) & 0x80 ? "Tx: " : "Rx: ");
}
switch (GET_U_1(p + DIR_POS) & 0x0f) {
case PT_LANE:
traftype = ATM_LANE;
break;
case PT_LLC:
traftype = ATM_LLC;
break;
default:
traftype = ATM_UNKNOWN;
break;
}
vpi = GET_U_1(p + VPI_POS);
vci = GET_BE_U_2(p + VCI_POS);
p += PKT_BEGIN_POS;
caplen -= PKT_BEGIN_POS;
length -= PKT_BEGIN_POS;
ndo->ndo_ll_hdr_len += PKT_BEGIN_POS;
atm_print(ndo, vpi, vci, traftype, p, length, caplen);
}
diff --git a/contrib/tcpdump/print-sunrpc.c b/contrib/tcpdump/print-sunrpc.c
index b2b33f25a020..5fc6597fc287 100644
--- a/contrib/tcpdump/print-sunrpc.c
+++ b/contrib/tcpdump/print-sunrpc.c
@@ -1,241 +1,239 @@
/*
* Copyright (c) 1992, 1993, 1994, 1995, 1996
* 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.
*/
/* \summary: Sun Remote Procedure Call printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
/*
* At least on HP-UX:
*
* 1) getrpcbynumber() is declared in <netdb.h>, not any of the RPC
* header files
*
* and
*
* 2) if _XOPEN_SOURCE_EXTENDED is defined, <netdb.h> doesn't declare
* it
*
* so we undefine it.
*/
#undef _XOPEN_SOURCE_EXTENDED
#include "netdissect-stdinc.h"
#if defined(HAVE_GETRPCBYNUMBER) && defined(HAVE_RPC_RPC_H)
#include <rpc/rpc.h>
#ifdef HAVE_RPC_RPCENT_H
#include <rpc/rpcent.h>
#endif /* HAVE_RPC_RPCENT_H */
#endif /* defined(HAVE_GETRPCBYNUMBER) && defined(HAVE_RPC_RPC_H) */
#include <stdio.h>
#include <string.h>
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#include "ip.h"
#include "ip6.h"
#include "rpc_auth.h"
#include "rpc_msg.h"
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
* media and as a part of the software program in whole or part. Users
* may copy or modify Sun RPC without charge, but are not authorized
* to license or distribute it to anyone else except as part of a product or
* program developed by the user.
*
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
* WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun RPC is provided with no support and without any obligation on the
* part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*
* from: @(#)pmap_prot.h 1.14 88/02/08 SMI
* from: @(#)pmap_prot.h 2.1 88/07/29 4.0 RPCSRC
* $FreeBSD: projects/clang400-import/contrib/tcpdump/print-sunrpc.c 276788 2015-01-07 19:55:18Z delphij $
*/
/*
* pmap_prot.h
* Protocol for the local binder service, or pmap.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*
* The following procedures are supported by the protocol:
*
* PMAPPROC_NULL() returns ()
* takes nothing, returns nothing
*
* PMAPPROC_SET(struct pmap) returns (bool_t)
* TRUE is success, FALSE is failure. Registers the tuple
* [prog, vers, prot, port].
*
* PMAPPROC_UNSET(struct pmap) returns (bool_t)
* TRUE is success, FALSE is failure. Un-registers pair
* [prog, vers]. prot and port are ignored.
*
* PMAPPROC_GETPORT(struct pmap) returns (long unsigned).
* 0 is failure. Otherwise returns the port number where the pair
* [prog, vers] is registered. It may lie!
*
* PMAPPROC_DUMP() RETURNS (struct pmaplist *)
*
* PMAPPROC_CALLIT(unsigned, unsigned, unsigned, string<>)
* RETURNS (port, string<>);
* usage: encapsulatedresults = PMAPPROC_CALLIT(prog, vers, proc, encapsulatedargs);
* Calls the procedure on the local machine. If it is not registered,
* this procedure is quite; ie it does not return error information!!!
* This procedure only is supported on rpc/udp and calls via
* rpc/udp. This routine only passes null authentication parameters.
* This file has no interface to xdr routines for PMAPPROC_CALLIT.
*
* The service supports remote procedure calls on udp/ip or tcp/ip socket 111.
*/
#define SUNRPC_PMAPPORT ((uint16_t)111)
#define SUNRPC_PMAPPROC_NULL ((uint32_t)0)
#define SUNRPC_PMAPPROC_SET ((uint32_t)1)
#define SUNRPC_PMAPPROC_UNSET ((uint32_t)2)
#define SUNRPC_PMAPPROC_GETPORT ((uint32_t)3)
#define SUNRPC_PMAPPROC_DUMP ((uint32_t)4)
#define SUNRPC_PMAPPROC_CALLIT ((uint32_t)5)
static const struct tok proc2str[] = {
{ SUNRPC_PMAPPROC_NULL, "null" },
{ SUNRPC_PMAPPROC_SET, "set" },
{ SUNRPC_PMAPPROC_UNSET, "unset" },
{ SUNRPC_PMAPPROC_GETPORT, "getport" },
{ SUNRPC_PMAPPROC_DUMP, "dump" },
{ SUNRPC_PMAPPROC_CALLIT, "call" },
{ 0, NULL }
};
/* Forwards */
static char *progstr(uint32_t);
void
sunrpc_print(netdissect_options *ndo, const u_char *bp,
u_int length, const u_char *bp2)
{
const struct sunrpc_msg *rp;
const struct ip *ip;
const struct ip6_hdr *ip6;
uint32_t x;
char srcid[20], dstid[20]; /*fits 32bit*/
ndo->ndo_protocol = "sunrpc";
rp = (const struct sunrpc_msg *)bp;
ND_TCHECK_SIZE(rp);
if (!ndo->ndo_nflag) {
snprintf(srcid, sizeof(srcid), "0x%x",
GET_BE_U_4(rp->rm_xid));
strlcpy(dstid, "sunrpc", sizeof(dstid));
} else {
snprintf(srcid, sizeof(srcid), "0x%x",
GET_BE_U_4(rp->rm_xid));
snprintf(dstid, sizeof(dstid), "0x%x", SUNRPC_PMAPPORT);
}
switch (IP_V((const struct ip *)bp2)) {
case 4:
ip = (const struct ip *)bp2;
ND_PRINT("%s.%s > %s.%s: %u",
GET_IPADDR_STRING(ip->ip_src), srcid,
GET_IPADDR_STRING(ip->ip_dst), dstid, length);
break;
case 6:
ip6 = (const struct ip6_hdr *)bp2;
ND_PRINT("%s.%s > %s.%s: %u",
GET_IP6ADDR_STRING(ip6->ip6_src), srcid,
GET_IP6ADDR_STRING(ip6->ip6_dst), dstid, length);
break;
default:
ND_PRINT("%s.%s > %s.%s: %u", "?", srcid, "?", dstid, length);
break;
}
ND_PRINT(" %s", tok2str(proc2str, " proc #%u",
GET_BE_U_4(rp->rm_call.cb_proc)));
x = GET_BE_U_4(rp->rm_call.cb_rpcvers);
if (x != SUNRPC_MSG_VERSION)
ND_PRINT(" [rpcver %u]", x);
switch (GET_BE_U_4(rp->rm_call.cb_proc)) {
case SUNRPC_PMAPPROC_SET:
case SUNRPC_PMAPPROC_UNSET:
case SUNRPC_PMAPPROC_GETPORT:
case SUNRPC_PMAPPROC_CALLIT:
x = GET_BE_U_4(rp->rm_call.cb_prog);
if (!ndo->ndo_nflag)
ND_PRINT(" %s", progstr(x));
else
ND_PRINT(" %u", x);
ND_PRINT(".%u", GET_BE_U_4(rp->rm_call.cb_vers));
break;
}
}
static char *
progstr(uint32_t prog)
{
#if defined(HAVE_GETRPCBYNUMBER) && defined(HAVE_RPC_RPC_H)
struct rpcent *rp;
#endif
static char buf[32];
static uint32_t lastprog = 0;
if (lastprog != 0 && prog == lastprog)
return (buf);
#if defined(HAVE_GETRPCBYNUMBER) && defined(HAVE_RPC_RPC_H)
rp = getrpcbynumber(prog);
if (rp != NULL)
strlcpy(buf, rp->r_name, sizeof(buf));
else
#endif
(void) snprintf(buf, sizeof(buf), "#%u", prog);
lastprog = prog;
return (buf);
}
diff --git a/contrib/tcpdump/print-symantec.c b/contrib/tcpdump/print-symantec.c
index 0d394e30f2ec..3cbf221246e9 100644
--- a/contrib/tcpdump/print-symantec.c
+++ b/contrib/tcpdump/print-symantec.c
@@ -1,110 +1,108 @@
/*
* 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.
*/
/* \summary: Symantec Enterprise Firewall printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
#include "ethertype.h"
struct symantec_header {
nd_byte stuff1[6];
nd_uint16_t ether_type;
nd_byte stuff2[36];
};
static void
symantec_hdr_print(netdissect_options *ndo, const u_char *bp, u_int length)
{
const struct symantec_header *sp;
uint16_t etype;
sp = (const struct symantec_header *)bp;
etype = GET_BE_U_2(sp->ether_type);
if (!ndo->ndo_qflag) {
if (etype <= MAX_ETHERNET_LENGTH_VAL)
ND_PRINT("invalid ethertype %u", etype);
else
ND_PRINT("ethertype %s (0x%04x)",
tok2str(ethertype_values,"Unknown", etype),
etype);
} else {
if (etype <= MAX_ETHERNET_LENGTH_VAL)
ND_PRINT("invalid ethertype %u", etype);
else
ND_PRINT("%s", tok2str(ethertype_values,"Unknown Ethertype (0x%04x)", etype));
}
ND_PRINT(", length %u: ", length);
}
/*
* This is the top level routine of the printer. 'p' points
* to the ether header of the packet, 'h->ts' is the timestamp,
* 'h->len' is the length of the packet off the wire, and 'h->caplen'
* is the number of bytes actually captured.
*/
void
symantec_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
{
u_int length = h->len;
u_int caplen = h->caplen;
const struct symantec_header *sp;
u_short ether_type;
ndo->ndo_protocol = "symantec";
ND_TCHECK_LEN(p, sizeof(struct symantec_header));
ndo->ndo_ll_hdr_len += sizeof (struct symantec_header);
if (ndo->ndo_eflag)
symantec_hdr_print(ndo, p, length);
length -= sizeof (struct symantec_header);
caplen -= sizeof (struct symantec_header);
sp = (const struct symantec_header *)p;
p += sizeof (struct symantec_header);
ether_type = GET_BE_U_2(sp->ether_type);
if (ether_type <= MAX_ETHERNET_LENGTH_VAL) {
/* ether_type not known, print raw packet */
if (!ndo->ndo_eflag)
symantec_hdr_print(ndo, (const u_char *)sp, length + sizeof (struct symantec_header));
if (!ndo->ndo_suppress_default_print)
ND_DEFAULTPRINT(p, caplen);
} else if (ethertype_print(ndo, ether_type, p, length, caplen, NULL, NULL) == 0) {
/* ether_type not known, print raw packet */
if (!ndo->ndo_eflag)
symantec_hdr_print(ndo, (const u_char *)sp, length + sizeof (struct symantec_header));
if (!ndo->ndo_suppress_default_print)
ND_DEFAULTPRINT(p, caplen);
}
}
diff --git a/contrib/tcpdump/print-syslog.c b/contrib/tcpdump/print-syslog.c
index b0e1c91aa784..b4a801d2a418 100644
--- a/contrib/tcpdump/print-syslog.c
+++ b/contrib/tcpdump/print-syslog.c
@@ -1,150 +1,147 @@
/*
* Copyright (c) 1998-2004 Hannes Gredler <hannes@gredler.at>
* The TCPDUMP project
*
* 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.
*/
/* \summary: Syslog protocol printer */
/* specification: RFC 3164 (not RFC 5424) */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "extract.h"
/*
* tokenlists and #defines taken from Ethereal - Network traffic analyzer
* by Gerald Combs <gerald@ethereal.com>
*/
#define SYSLOG_SEVERITY_MASK 0x0007 /* 0000 0000 0000 0111 */
#define SYSLOG_FACILITY_MASK 0x03f8 /* 0000 0011 1111 1000 */
#define SYSLOG_MAX_DIGITS 3 /* The maximum number of priority digits to read in. */
static const struct tok syslog_severity_values[] = {
{ 0, "emergency" },
{ 1, "alert" },
{ 2, "critical" },
{ 3, "error" },
{ 4, "warning" },
{ 5, "notice" },
{ 6, "info" },
{ 7, "debug" },
{ 0, NULL },
};
static const struct tok syslog_facility_values[] = {
{ 0, "kernel" },
{ 1, "user" },
{ 2, "mail" },
{ 3, "daemon" },
{ 4, "auth" },
{ 5, "syslog" },
{ 6, "lpr" },
{ 7, "news" },
{ 8, "uucp" },
{ 9, "cron" },
{ 10, "authpriv" },
{ 11, "ftp" },
{ 12, "ntp" },
{ 13, "security" },
{ 14, "console" },
{ 15, "cron" },
{ 16, "local0" },
{ 17, "local1" },
{ 18, "local2" },
{ 19, "local3" },
{ 20, "local4" },
{ 21, "local5" },
{ 22, "local6" },
{ 23, "local7" },
{ 0, NULL },
};
void
syslog_print(netdissect_options *ndo,
const u_char *pptr, u_int len)
{
uint16_t msg_off = 0;
uint16_t pri = 0;
uint16_t facility,severity;
ndo->ndo_protocol = "syslog";
/* extract decimal figures that are
* encapsulated within < > tags
* based on this decimal figure extract the
* severity and facility values
*/
if (GET_U_1(pptr) != '<')
goto invalid;
msg_off++;
while (msg_off <= SYSLOG_MAX_DIGITS &&
GET_U_1(pptr + msg_off) >= '0' &&
GET_U_1(pptr + msg_off) <= '9') {
pri = pri * 10 + (GET_U_1(pptr + msg_off) - '0');
msg_off++;
}
if (GET_U_1(pptr + msg_off) != '>')
goto invalid;
msg_off++;
facility = (pri & SYSLOG_FACILITY_MASK) >> 3;
severity = pri & SYSLOG_SEVERITY_MASK;
- if (ndo->ndo_vflag < 1 )
- {
+ if (ndo->ndo_vflag < 1 ) {
ND_PRINT("SYSLOG %s.%s, length: %u",
tok2str(syslog_facility_values, "unknown (%u)", facility),
tok2str(syslog_severity_values, "unknown (%u)", severity),
len);
return;
}
ND_PRINT("SYSLOG, length: %u\n\tFacility %s (%u), Severity %s (%u)\n\tMsg: ",
len,
tok2str(syslog_facility_values, "unknown (%u)", facility),
facility,
tok2str(syslog_severity_values, "unknown (%u)", severity),
severity);
/* print the syslog text in verbose mode */
/*
* RFC 3164 Section 4.1.3: "There is no ending delimiter to this part.
* The MSG part of the syslog packet MUST contain visible (printing)
* characters."
*
* RFC 5424 Section 8.2: "This document does not impose any mandatory
* restrictions on the MSG or PARAM-VALUE content. As such, they MAY
* contain control characters, including the NUL character."
*
* Hence, to aid in protocol debugging, print the full MSG without
* beautification to make it clear what was transmitted on the wire.
*/
if (len > msg_off)
(void)nd_printn(ndo, pptr + msg_off, len - msg_off, NULL);
if (ndo->ndo_vflag > 1)
print_unknown_data(ndo, pptr, "\n\t", len);
return;
invalid:
nd_print_invalid(ndo);
}
diff --git a/contrib/tcpdump/print-tcp.c b/contrib/tcpdump/print-tcp.c
index 72964eb88ea2..b727dde05543 100644
--- a/contrib/tcpdump/print-tcp.c
+++ b/contrib/tcpdump/print-tcp.c
@@ -1,972 +1,978 @@
/* $NetBSD: print-tcp.c,v 1.9 2007/07/26 18:15:12 plunky Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
* The Regents of the University of California. All rights reserved.
*
* Copyright (c) 1999-2004 The tcpdump.org project
*
* 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.
*/
/* \summary: TCP printer */
#ifndef lint
#else
__RCSID("$NetBSD: print-tcp.c,v 1.8 2007/07/24 11:53:48 drochner Exp $");
#endif
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <stdlib.h>
#include <string.h>
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#include "diag-control.h"
#include "tcp.h"
#include "ip.h"
#include "ip6.h"
#include "ipproto.h"
#include "rpc_auth.h"
#include "rpc_msg.h"
#ifdef HAVE_LIBCRYPTO
#include <openssl/md5.h>
#include "signature.h"
static int tcp_verify_signature(netdissect_options *ndo,
const struct ip *ip, const struct tcphdr *tp,
const u_char *data, u_int length, const u_char *rcvsig);
#endif
static void print_tcp_rst_data(netdissect_options *, const u_char *sp, u_int length);
static void print_tcp_fastopen_option(netdissect_options *ndo, const u_char *cp,
u_int datalen, int exp);
#define MAX_RST_DATA_LEN 30
struct tha {
nd_ipv4 src;
nd_ipv4 dst;
u_int port;
};
struct tcp_seq_hash {
struct tcp_seq_hash *nxt;
struct tha addr;
uint32_t seq;
uint32_t ack;
};
struct tha6 {
nd_ipv6 src;
nd_ipv6 dst;
u_int port;
};
struct tcp_seq_hash6 {
struct tcp_seq_hash6 *nxt;
struct tha6 addr;
uint32_t seq;
uint32_t ack;
};
#define TSEQ_HASHSIZE 919
/* These tcp options do not have the size octet */
#define ZEROLENOPT(o) ((o) == TCPOPT_EOL || (o) == TCPOPT_NOP)
static struct tcp_seq_hash tcp_seq_hash4[TSEQ_HASHSIZE];
static struct tcp_seq_hash6 tcp_seq_hash6[TSEQ_HASHSIZE];
static const struct tok tcp_flag_values[] = {
{ TH_FIN, "F" },
{ TH_SYN, "S" },
{ TH_RST, "R" },
{ TH_PUSH, "P" },
{ TH_ACK, "." },
{ TH_URG, "U" },
{ TH_ECNECHO, "E" },
{ TH_CWR, "W" },
{ 0, NULL }
};
static const struct tok tcp_option_values[] = {
{ TCPOPT_EOL, "eol" },
{ TCPOPT_NOP, "nop" },
{ TCPOPT_MAXSEG, "mss" },
{ TCPOPT_WSCALE, "wscale" },
{ TCPOPT_SACKOK, "sackOK" },
{ TCPOPT_SACK, "sack" },
{ TCPOPT_ECHO, "echo" },
{ TCPOPT_ECHOREPLY, "echoreply" },
{ TCPOPT_TIMESTAMP, "TS" },
{ TCPOPT_CC, "cc" },
{ TCPOPT_CCNEW, "ccnew" },
- { TCPOPT_CCECHO, "" },
+ { TCPOPT_CCECHO, "ccecho" },
{ TCPOPT_SIGNATURE, "md5" },
{ TCPOPT_SCPS, "scps" },
{ TCPOPT_UTO, "uto" },
{ TCPOPT_TCPAO, "tcp-ao" },
{ TCPOPT_MPTCP, "mptcp" },
{ TCPOPT_FASTOPEN, "tfo" },
{ TCPOPT_EXPERIMENT2, "exp" },
{ 0, NULL }
};
static uint16_t
tcp_cksum(netdissect_options *ndo,
const struct ip *ip,
const struct tcphdr *tp,
u_int len)
{
return nextproto4_cksum(ndo, ip, (const uint8_t *)tp, len, len,
IPPROTO_TCP);
}
static uint16_t
tcp6_cksum(netdissect_options *ndo,
const struct ip6_hdr *ip6,
const struct tcphdr *tp,
u_int len)
{
return nextproto6_cksum(ndo, ip6, (const uint8_t *)tp, len, len,
IPPROTO_TCP);
}
void
tcp_print(netdissect_options *ndo,
const u_char *bp, u_int length,
const u_char *bp2, int fragmented)
{
const struct tcphdr *tp;
const struct ip *ip;
u_char flags;
u_int hlen;
char ch;
uint16_t sport, dport, win, urp;
uint32_t seq, ack, thseq, thack;
u_int utoval;
uint16_t magic;
int rev;
const struct ip6_hdr *ip6;
u_int header_len; /* Header length in bytes */
ndo->ndo_protocol = "tcp";
tp = (const struct tcphdr *)bp;
ip = (const struct ip *)bp2;
if (IP_V(ip) == 6)
ip6 = (const struct ip6_hdr *)bp2;
else
ip6 = NULL;
ch = '\0';
if (!ND_TTEST_2(tp->th_dport)) {
if (ip6) {
ND_PRINT("%s > %s:",
GET_IP6ADDR_STRING(ip6->ip6_src),
GET_IP6ADDR_STRING(ip6->ip6_dst));
} else {
ND_PRINT("%s > %s:",
GET_IPADDR_STRING(ip->ip_src),
GET_IPADDR_STRING(ip->ip_dst));
}
nd_print_trunc(ndo);
return;
}
sport = GET_BE_U_2(tp->th_sport);
dport = GET_BE_U_2(tp->th_dport);
if (ip6) {
if (GET_U_1(ip6->ip6_nxt) == IPPROTO_TCP) {
ND_PRINT("%s.%s > %s.%s: ",
GET_IP6ADDR_STRING(ip6->ip6_src),
tcpport_string(ndo, sport),
GET_IP6ADDR_STRING(ip6->ip6_dst),
tcpport_string(ndo, dport));
} else {
ND_PRINT("%s > %s: ",
tcpport_string(ndo, sport), tcpport_string(ndo, dport));
}
} else {
if (GET_U_1(ip->ip_p) == IPPROTO_TCP) {
ND_PRINT("%s.%s > %s.%s: ",
GET_IPADDR_STRING(ip->ip_src),
tcpport_string(ndo, sport),
GET_IPADDR_STRING(ip->ip_dst),
tcpport_string(ndo, dport));
} else {
ND_PRINT("%s > %s: ",
tcpport_string(ndo, sport), tcpport_string(ndo, dport));
}
}
ND_TCHECK_SIZE(tp);
hlen = TH_OFF(tp) * 4;
if (hlen < sizeof(*tp)) {
ND_PRINT(" tcp %u [bad hdr length %u - too short, < %zu]",
length - hlen, hlen, sizeof(*tp));
return;
}
seq = GET_BE_U_4(tp->th_seq);
ack = GET_BE_U_4(tp->th_ack);
win = GET_BE_U_2(tp->th_win);
urp = GET_BE_U_2(tp->th_urp);
if (ndo->ndo_qflag) {
ND_PRINT("tcp %u", length - hlen);
if (hlen > length) {
ND_PRINT(" [bad hdr length %u - too long, > %u]",
hlen, length);
}
return;
}
flags = GET_U_1(tp->th_flags);
ND_PRINT("Flags [%s]", bittok2str_nosep(tcp_flag_values, "none", flags));
if (!ndo->ndo_Sflag && (flags & TH_ACK)) {
/*
* Find (or record) the initial sequence numbers for
* this conversation. (we pick an arbitrary
* collating order so there's only one entry for
* both directions).
*/
rev = 0;
if (ip6) {
struct tcp_seq_hash6 *th;
struct tcp_seq_hash6 *tcp_seq_hash;
const void *src, *dst;
struct tha6 tha;
tcp_seq_hash = tcp_seq_hash6;
src = (const void *)ip6->ip6_src;
dst = (const void *)ip6->ip6_dst;
if (sport > dport)
rev = 1;
else if (sport == dport) {
if (UNALIGNED_MEMCMP(src, dst, sizeof(ip6->ip6_dst)) > 0)
rev = 1;
}
if (rev) {
UNALIGNED_MEMCPY(&tha.src, dst, sizeof(ip6->ip6_dst));
UNALIGNED_MEMCPY(&tha.dst, src, sizeof(ip6->ip6_src));
tha.port = ((u_int)dport) << 16 | sport;
} else {
UNALIGNED_MEMCPY(&tha.dst, dst, sizeof(ip6->ip6_dst));
UNALIGNED_MEMCPY(&tha.src, src, sizeof(ip6->ip6_src));
tha.port = ((u_int)sport) << 16 | dport;
}
for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE];
th->nxt; th = th->nxt)
if (memcmp((char *)&tha, (char *)&th->addr,
sizeof(th->addr)) == 0)
break;
if (!th->nxt || (flags & TH_SYN)) {
/* didn't find it or new conversation */
/* calloc() return used by the 'tcp_seq_hash6'
hash table: do not free() */
if (th->nxt == NULL) {
th->nxt = (struct tcp_seq_hash6 *)
calloc(1, sizeof(*th));
if (th->nxt == NULL)
(*ndo->ndo_error)(ndo,
S_ERR_ND_MEM_ALLOC,
"%s: calloc", __func__);
}
th->addr = tha;
if (rev)
th->ack = seq, th->seq = ack - 1;
else
th->seq = seq, th->ack = ack - 1;
} else {
if (rev)
seq -= th->ack, ack -= th->seq;
else
seq -= th->seq, ack -= th->ack;
}
thseq = th->seq;
thack = th->ack;
} else {
struct tcp_seq_hash *th;
struct tcp_seq_hash *tcp_seq_hash;
struct tha tha;
tcp_seq_hash = tcp_seq_hash4;
if (sport > dport)
rev = 1;
else if (sport == dport) {
if (UNALIGNED_MEMCMP(ip->ip_src, ip->ip_dst, sizeof(ip->ip_dst)) > 0)
rev = 1;
}
if (rev) {
UNALIGNED_MEMCPY(&tha.src, ip->ip_dst,
sizeof(ip->ip_dst));
UNALIGNED_MEMCPY(&tha.dst, ip->ip_src,
sizeof(ip->ip_src));
tha.port = ((u_int)dport) << 16 | sport;
} else {
UNALIGNED_MEMCPY(&tha.dst, ip->ip_dst,
sizeof(ip->ip_dst));
UNALIGNED_MEMCPY(&tha.src, ip->ip_src,
sizeof(ip->ip_src));
tha.port = ((u_int)sport) << 16 | dport;
}
for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE];
th->nxt; th = th->nxt)
if (memcmp((char *)&tha, (char *)&th->addr,
sizeof(th->addr)) == 0)
break;
if (!th->nxt || (flags & TH_SYN)) {
/* didn't find it or new conversation */
/* calloc() return used by the 'tcp_seq_hash4'
hash table: do not free() */
if (th->nxt == NULL) {
th->nxt = (struct tcp_seq_hash *)
calloc(1, sizeof(*th));
if (th->nxt == NULL)
(*ndo->ndo_error)(ndo,
S_ERR_ND_MEM_ALLOC,
"%s: calloc", __func__);
}
th->addr = tha;
if (rev)
th->ack = seq, th->seq = ack - 1;
else
th->seq = seq, th->ack = ack - 1;
} else {
if (rev)
seq -= th->ack, ack -= th->seq;
else
seq -= th->seq, ack -= th->ack;
}
thseq = th->seq;
thack = th->ack;
}
} else {
/*fool gcc*/
thseq = thack = rev = 0;
}
if (hlen > length) {
ND_PRINT(" [bad hdr length %u - too long, > %u]",
hlen, length);
return;
}
if (ndo->ndo_vflag && !ndo->ndo_Kflag && !fragmented) {
/* Check the checksum, if possible. */
uint16_t sum, tcp_sum;
if (IP_V(ip) == 4) {
if (ND_TTEST_LEN(tp->th_sport, length)) {
sum = tcp_cksum(ndo, ip, tp, length);
tcp_sum = GET_BE_U_2(tp->th_sum);
ND_PRINT(", cksum 0x%04x", tcp_sum);
if (sum != 0)
ND_PRINT(" (incorrect -> 0x%04x)",
in_cksum_shouldbe(tcp_sum, sum));
else
ND_PRINT(" (correct)");
}
} else if (IP_V(ip) == 6) {
if (ND_TTEST_LEN(tp->th_sport, length)) {
sum = tcp6_cksum(ndo, ip6, tp, length);
tcp_sum = GET_BE_U_2(tp->th_sum);
ND_PRINT(", cksum 0x%04x", tcp_sum);
if (sum != 0)
ND_PRINT(" (incorrect -> 0x%04x)",
in_cksum_shouldbe(tcp_sum, sum));
else
ND_PRINT(" (correct)");
}
}
}
length -= hlen;
if (ndo->ndo_vflag > 1 || length > 0 || flags & (TH_SYN | TH_FIN | TH_RST)) {
ND_PRINT(", seq %u", seq);
if (length > 0) {
ND_PRINT(":%u", seq + length);
}
}
if (flags & TH_ACK) {
ND_PRINT(", ack %u", ack);
}
ND_PRINT(", win %u", win);
if (flags & TH_URG)
ND_PRINT(", urg %u", urp);
/*
* Handle any options.
*/
if (hlen > sizeof(*tp)) {
const u_char *cp;
u_int i, opt, datalen;
u_int len;
hlen -= sizeof(*tp);
cp = (const u_char *)tp + sizeof(*tp);
ND_PRINT(", options [");
while (hlen > 0) {
if (ch != '\0')
ND_PRINT("%c", ch);
opt = GET_U_1(cp);
cp++;
if (ZEROLENOPT(opt))
len = 1;
else {
len = GET_U_1(cp);
cp++; /* total including type, len */
if (len < 2 || len > hlen)
goto bad;
--hlen; /* account for length byte */
}
--hlen; /* account for type byte */
datalen = 0;
/* Bail if "l" bytes of data are not left or were not captured */
#define LENCHECK(l) { if ((l) > hlen) goto bad; ND_TCHECK_LEN(cp, l); }
ND_PRINT("%s", tok2str(tcp_option_values, "unknown-%u", opt));
switch (opt) {
case TCPOPT_MAXSEG:
datalen = 2;
LENCHECK(datalen);
ND_PRINT(" %u", GET_BE_U_2(cp));
break;
case TCPOPT_WSCALE:
datalen = 1;
LENCHECK(datalen);
ND_PRINT(" %u", GET_U_1(cp));
break;
case TCPOPT_SACK:
datalen = len - 2;
if (datalen % 8 != 0) {
ND_PRINT(" invalid sack");
} else {
uint32_t s, e;
ND_PRINT(" %u ", datalen / 8);
for (i = 0; i < datalen; i += 8) {
LENCHECK(i + 4);
s = GET_BE_U_4(cp + i);
LENCHECK(i + 8);
e = GET_BE_U_4(cp + i + 4);
if (rev) {
s -= thseq;
e -= thseq;
} else {
s -= thack;
e -= thack;
}
ND_PRINT("{%u:%u}", s, e);
}
}
break;
case TCPOPT_CC:
case TCPOPT_CCNEW:
case TCPOPT_CCECHO:
case TCPOPT_ECHO:
case TCPOPT_ECHOREPLY:
/*
* those options share their semantics.
* fall through
*/
datalen = 4;
LENCHECK(datalen);
ND_PRINT(" %u", GET_BE_U_4(cp));
break;
case TCPOPT_TIMESTAMP:
datalen = 8;
LENCHECK(datalen);
ND_PRINT(" val %u ecr %u",
GET_BE_U_4(cp),
GET_BE_U_4(cp + 4));
break;
case TCPOPT_SIGNATURE:
datalen = TCP_SIGLEN;
LENCHECK(datalen);
ND_PRINT(" ");
#ifdef HAVE_LIBCRYPTO
switch (tcp_verify_signature(ndo, ip, tp,
bp + TH_OFF(tp) * 4, length, cp)) {
case SIGNATURE_VALID:
ND_PRINT("valid");
break;
case SIGNATURE_INVALID:
nd_print_invalid(ndo);
break;
case CANT_CHECK_SIGNATURE:
ND_PRINT("can't check - ");
for (i = 0; i < TCP_SIGLEN; ++i)
ND_PRINT("%02x",
GET_U_1(cp + i));
break;
}
#else
for (i = 0; i < TCP_SIGLEN; ++i)
ND_PRINT("%02x", GET_U_1(cp + i));
#endif
break;
case TCPOPT_SCPS:
datalen = 2;
LENCHECK(datalen);
ND_PRINT(" cap %02x id %u", GET_U_1(cp),
GET_U_1(cp + 1));
break;
case TCPOPT_TCPAO:
datalen = len - 2;
/* RFC 5925 Section 2.2:
* "The Length value MUST be greater than or equal to 4."
* (This includes the Kind and Length fields already processed
* at this point.)
*/
if (datalen < 2) {
nd_print_invalid(ndo);
} else {
LENCHECK(1);
ND_PRINT(" keyid %u", GET_U_1(cp));
LENCHECK(2);
ND_PRINT(" rnextkeyid %u",
GET_U_1(cp + 1));
if (datalen > 2) {
ND_PRINT(" mac 0x");
for (i = 2; i < datalen; i++) {
LENCHECK(i + 1);
ND_PRINT("%02x",
GET_U_1(cp + i));
}
}
}
break;
case TCPOPT_EOL:
case TCPOPT_NOP:
case TCPOPT_SACKOK:
/*
* Nothing interesting.
* fall through
*/
break;
case TCPOPT_UTO:
datalen = 2;
LENCHECK(datalen);
utoval = GET_BE_U_2(cp);
ND_PRINT(" 0x%x", utoval);
if (utoval & 0x0001)
utoval = (utoval >> 1) * 60;
else
utoval >>= 1;
ND_PRINT(" %u", utoval);
break;
case TCPOPT_MPTCP:
{
const u_char *snapend_save;
int ret;
datalen = len - 2;
LENCHECK(datalen);
/* Update the snapend to the end of the option
* before calling mptcp_print(). Some options
* (MPTCP or others) may be present after a
* MPTCP option. This prevents that, in
* mptcp_print(), the remaining length < the
* remaining caplen.
*/
snapend_save = ndo->ndo_snapend;
ndo->ndo_snapend = ND_MIN(cp - 2 + len,
ndo->ndo_snapend);
ret = mptcp_print(ndo, cp - 2, len, flags);
ndo->ndo_snapend = snapend_save;
if (!ret)
goto bad;
break;
}
case TCPOPT_FASTOPEN:
datalen = len - 2;
LENCHECK(datalen);
ND_PRINT(" ");
print_tcp_fastopen_option(ndo, cp, datalen, FALSE);
break;
case TCPOPT_EXPERIMENT2:
datalen = len - 2;
LENCHECK(datalen);
if (datalen < 2)
goto bad;
/* RFC6994 */
magic = GET_BE_U_2(cp);
ND_PRINT("-");
switch(magic) {
case 0xf989: /* TCP Fast Open RFC 7413 */
print_tcp_fastopen_option(ndo, cp + 2, datalen - 2, TRUE);
break;
default:
/* Unknown magic number */
ND_PRINT("%04x", magic);
break;
}
break;
default:
datalen = len - 2;
if (datalen)
ND_PRINT(" 0x");
for (i = 0; i < datalen; ++i) {
LENCHECK(i + 1);
ND_PRINT("%02x", GET_U_1(cp + i));
}
break;
}
/* Account for data printed */
cp += datalen;
hlen -= datalen;
/* Check specification against observed length */
++datalen; /* option octet */
if (!ZEROLENOPT(opt))
++datalen; /* size octet */
if (datalen != len)
ND_PRINT("[len %u]", len);
ch = ',';
if (opt == TCPOPT_EOL)
break;
}
ND_PRINT("]");
}
/*
* Print length field before crawling down the stack.
*/
ND_PRINT(", length %u", length);
if (length == 0)
return;
/*
* Decode payload if necessary.
*/
header_len = TH_OFF(tp) * 4;
/*
* Do a bounds check before decoding the payload.
* At least the header data is required.
*/
if (!ND_TTEST_LEN(bp, header_len)) {
ND_PRINT(" [remaining caplen(%u) < header length(%u)]",
ND_BYTES_AVAILABLE_AFTER(bp), header_len);
nd_trunc_longjmp(ndo);
}
bp += header_len;
if ((flags & TH_RST) && ndo->ndo_vflag) {
print_tcp_rst_data(ndo, bp, length);
return;
}
if (ndo->ndo_packettype) {
switch (ndo->ndo_packettype) {
case PT_ZMTP1:
zmtp1_print(ndo, bp, length);
break;
case PT_RESP:
resp_print(ndo, bp, length);
break;
case PT_DOMAIN:
/* over_tcp: TRUE, is_mdns: FALSE */
domain_print(ndo, bp, length, TRUE, FALSE);
break;
}
return;
}
- if (IS_SRC_OR_DST_PORT(TELNET_PORT)) {
+ if (IS_SRC_OR_DST_PORT(FTP_PORT)) {
+ ND_PRINT(": ");
+ ftp_print(ndo, bp, length);
+ } else if (IS_SRC_OR_DST_PORT(SSH_PORT)) {
+ ssh_print(ndo, bp, length);
+ } else if (IS_SRC_OR_DST_PORT(TELNET_PORT)) {
telnet_print(ndo, bp, length);
} else if (IS_SRC_OR_DST_PORT(SMTP_PORT)) {
ND_PRINT(": ");
smtp_print(ndo, bp, length);
} else if (IS_SRC_OR_DST_PORT(WHOIS_PORT)) {
ND_PRINT(": ");
whois_print(ndo, bp, length);
- } else if (IS_SRC_OR_DST_PORT(BGP_PORT))
- bgp_print(ndo, bp, length);
- else if (IS_SRC_OR_DST_PORT(PPTP_PORT))
- pptp_print(ndo, bp);
- else if (IS_SRC_OR_DST_PORT(REDIS_PORT))
- resp_print(ndo, bp, length);
- else if (IS_SRC_OR_DST_PORT(SSH_PORT))
- ssh_print(ndo, bp, length);
+ } else if (IS_SRC_OR_DST_PORT(NAMESERVER_PORT)) {
+ /* over_tcp: TRUE, is_mdns: FALSE */
+ domain_print(ndo, bp, length, TRUE, FALSE);
+ } else if (IS_SRC_OR_DST_PORT(HTTP_PORT)) {
+ ND_PRINT(": ");
+ http_print(ndo, bp, length);
#ifdef ENABLE_SMB
- else if (IS_SRC_OR_DST_PORT(NETBIOS_SSN_PORT))
+ } else if (IS_SRC_OR_DST_PORT(NETBIOS_SSN_PORT)) {
nbt_tcp_print(ndo, bp, length);
- else if (IS_SRC_OR_DST_PORT(SMB_PORT))
+#endif
+ } else if (IS_SRC_OR_DST_PORT(BGP_PORT)) {
+ bgp_print(ndo, bp, length);
+ } else if (IS_SRC_OR_DST_PORT(RPKI_RTR_PORT)) {
+ rpki_rtr_print(ndo, bp, length);
+#ifdef ENABLE_SMB
+ } else if (IS_SRC_OR_DST_PORT(SMB_PORT)) {
smb_tcp_print(ndo, bp, length);
#endif
+ } else if (IS_SRC_OR_DST_PORT(RTSP_PORT)) {
+ ND_PRINT(": ");
+ rtsp_print(ndo, bp, length);
+ } else if (IS_SRC_OR_DST_PORT(MSDP_PORT)) {
+ msdp_print(ndo, bp, length);
+ } else if (IS_SRC_OR_DST_PORT(LDP_PORT)) {
+ ldp_print(ndo, bp, length);
+ } else if (IS_SRC_OR_DST_PORT(PPTP_PORT))
+ pptp_print(ndo, bp);
+ else if (IS_SRC_OR_DST_PORT(REDIS_PORT))
+ resp_print(ndo, bp, length);
else if (IS_SRC_OR_DST_PORT(BEEP_PORT))
beep_print(ndo, bp, length);
- else if (IS_SRC_OR_DST_PORT(OPENFLOW_PORT_OLD) || IS_SRC_OR_DST_PORT(OPENFLOW_PORT_IANA))
+ else if (IS_SRC_OR_DST_PORT(OPENFLOW_PORT_OLD) || IS_SRC_OR_DST_PORT(OPENFLOW_PORT_IANA)) {
openflow_print(ndo, bp, length);
- else if (IS_SRC_OR_DST_PORT(FTP_PORT)) {
- ND_PRINT(": ");
- ftp_print(ndo, bp, length);
- } else if (IS_SRC_OR_DST_PORT(HTTP_PORT) || IS_SRC_OR_DST_PORT(HTTP_PORT_ALT)) {
+ } else if (IS_SRC_OR_DST_PORT(HTTP_PORT_ALT)) {
ND_PRINT(": ");
http_print(ndo, bp, length);
- } else if (IS_SRC_OR_DST_PORT(RTSP_PORT) || IS_SRC_OR_DST_PORT(RTSP_PORT_ALT)) {
+ } else if (IS_SRC_OR_DST_PORT(RTSP_PORT_ALT)) {
ND_PRINT(": ");
rtsp_print(ndo, bp, length);
- } else if (IS_SRC_OR_DST_PORT(NAMESERVER_PORT)) {
- /* over_tcp: TRUE, is_mdns: FALSE */
- domain_print(ndo, bp, length, TRUE, FALSE);
- } else if (IS_SRC_OR_DST_PORT(MSDP_PORT)) {
- msdp_print(ndo, bp, length);
- } else if (IS_SRC_OR_DST_PORT(RPKI_RTR_PORT)) {
- rpki_rtr_print(ndo, bp, length);
- } else if (IS_SRC_OR_DST_PORT(LDP_PORT)) {
- ldp_print(ndo, bp, length);
} else if ((IS_SRC_OR_DST_PORT(NFS_PORT)) &&
length >= 4 && ND_TTEST_4(bp)) {
/*
* If data present, header length valid, and NFS port used,
* assume NFS.
* Pass offset of data plus 4 bytes for RPC TCP msg length
* to NFS print routines.
*/
uint32_t fraglen;
const struct sunrpc_msg *rp;
enum sunrpc_msg_type direction;
fraglen = GET_BE_U_4(bp) & 0x7FFFFFFF;
if (fraglen > (length) - 4)
fraglen = (length) - 4;
rp = (const struct sunrpc_msg *)(bp + 4);
if (ND_TTEST_4(rp->rm_direction)) {
direction = (enum sunrpc_msg_type) GET_BE_U_4(rp->rm_direction);
if (dport == NFS_PORT && direction == SUNRPC_CALL) {
ND_PRINT(": NFS request xid %u ",
GET_BE_U_4(rp->rm_xid));
nfsreq_noaddr_print(ndo, (const u_char *)rp, fraglen, (const u_char *)ip);
return;
}
if (sport == NFS_PORT && direction == SUNRPC_REPLY) {
ND_PRINT(": NFS reply xid %u ",
GET_BE_U_4(rp->rm_xid));
nfsreply_noaddr_print(ndo, (const u_char *)rp, fraglen, (const u_char *)ip);
return;
}
}
}
return;
bad:
ND_PRINT("[bad opt]");
if (ch != '\0')
ND_PRINT("]");
return;
trunc:
nd_print_trunc(ndo);
if (ch != '\0')
ND_PRINT(">");
}
/*
* RFC1122 says the following on data in RST segments:
*
* 4.2.2.12 RST Segment: RFC-793 Section 3.4
*
* A TCP SHOULD allow a received RST segment to include data.
*
* DISCUSSION
* It has been suggested that a RST segment could contain
* ASCII text that encoded and explained the cause of the
* RST. No standard has yet been established for such
* data.
*
*/
static void
print_tcp_rst_data(netdissect_options *ndo,
const u_char *sp, u_int length)
{
u_char c;
ND_PRINT(ND_TTEST_LEN(sp, length) ? " [RST" : " [!RST");
if (length > MAX_RST_DATA_LEN) {
length = MAX_RST_DATA_LEN; /* can use -X for longer */
ND_PRINT("+"); /* indicate we truncate */
}
ND_PRINT(" ");
while (length && sp < ndo->ndo_snapend) {
c = GET_U_1(sp);
sp++;
fn_print_char(ndo, c);
length--;
}
ND_PRINT("]");
}
static void
print_tcp_fastopen_option(netdissect_options *ndo, const u_char *cp,
u_int datalen, int exp)
{
u_int i;
if (exp)
ND_PRINT("tfo");
if (datalen == 0) {
/* Fast Open Cookie Request */
ND_PRINT(" cookiereq");
} else {
/* Fast Open Cookie */
if (datalen % 2 != 0 || datalen < 4 || datalen > 16) {
nd_print_invalid(ndo);
} else {
ND_PRINT(" cookie ");
for (i = 0; i < datalen; ++i)
ND_PRINT("%02x", GET_U_1(cp + i));
}
}
}
#ifdef HAVE_LIBCRYPTO
DIAG_OFF_DEPRECATION
static int
tcp_verify_signature(netdissect_options *ndo,
const struct ip *ip, const struct tcphdr *tp,
const u_char *data, u_int length, const u_char *rcvsig)
{
struct tcphdr tp1;
u_char sig[TCP_SIGLEN];
char zero_proto = 0;
MD5_CTX ctx;
uint16_t savecsum, tlen;
const struct ip6_hdr *ip6;
uint32_t len32;
uint8_t nxt;
if (data + length > ndo->ndo_snapend) {
ND_PRINT("snaplen too short, ");
return (CANT_CHECK_SIGNATURE);
}
tp1 = *tp;
if (ndo->ndo_sigsecret == NULL) {
ND_PRINT("shared secret not supplied with -M, ");
return (CANT_CHECK_SIGNATURE);
}
MD5_Init(&ctx);
/*
* Step 1: Update MD5 hash with IP pseudo-header.
*/
if (IP_V(ip) == 4) {
MD5_Update(&ctx, (const char *)&ip->ip_src, sizeof(ip->ip_src));
MD5_Update(&ctx, (const char *)&ip->ip_dst, sizeof(ip->ip_dst));
MD5_Update(&ctx, (const char *)&zero_proto, sizeof(zero_proto));
MD5_Update(&ctx, (const char *)&ip->ip_p, sizeof(ip->ip_p));
tlen = GET_BE_U_2(ip->ip_len) - IP_HL(ip) * 4;
tlen = htons(tlen);
MD5_Update(&ctx, (const char *)&tlen, sizeof(tlen));
} else if (IP_V(ip) == 6) {
ip6 = (const struct ip6_hdr *)ip;
MD5_Update(&ctx, (const char *)&ip6->ip6_src, sizeof(ip6->ip6_src));
MD5_Update(&ctx, (const char *)&ip6->ip6_dst, sizeof(ip6->ip6_dst));
len32 = htonl(GET_BE_U_2(ip6->ip6_plen));
MD5_Update(&ctx, (const char *)&len32, sizeof(len32));
nxt = 0;
MD5_Update(&ctx, (const char *)&nxt, sizeof(nxt));
MD5_Update(&ctx, (const char *)&nxt, sizeof(nxt));
MD5_Update(&ctx, (const char *)&nxt, sizeof(nxt));
nxt = IPPROTO_TCP;
MD5_Update(&ctx, (const char *)&nxt, sizeof(nxt));
} else {
ND_PRINT("IP version not 4 or 6, ");
return (CANT_CHECK_SIGNATURE);
}
/*
* Step 2: Update MD5 hash with TCP header, excluding options.
* The TCP checksum must be set to zero.
*/
memcpy(&savecsum, tp1.th_sum, sizeof(savecsum));
memset(tp1.th_sum, 0, sizeof(tp1.th_sum));
MD5_Update(&ctx, (const char *)&tp1, sizeof(struct tcphdr));
memcpy(tp1.th_sum, &savecsum, sizeof(tp1.th_sum));
/*
* Step 3: Update MD5 hash with TCP segment data, if present.
*/
if (length > 0)
MD5_Update(&ctx, data, length);
/*
* Step 4: Update MD5 hash with shared secret.
*/
MD5_Update(&ctx, ndo->ndo_sigsecret, strlen(ndo->ndo_sigsecret));
MD5_Final(sig, &ctx);
if (memcmp(rcvsig, sig, TCP_SIGLEN) == 0)
return (SIGNATURE_VALID);
else
return (SIGNATURE_INVALID);
}
DIAG_ON_DEPRECATION
#endif /* HAVE_LIBCRYPTO */
diff --git a/contrib/tcpdump/print-telnet.c b/contrib/tcpdump/print-telnet.c
index ea7464f0dc4d..97be4b916071 100644
--- a/contrib/tcpdump/print-telnet.c
+++ b/contrib/tcpdump/print-telnet.c
@@ -1,540 +1,538 @@
/* $NetBSD: print-telnet.c,v 1.2 1999/10/11 12:40:12 sjg Exp $ */
/*-
* Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Simon J. Gerraty.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation 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 BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* @(#)Copyright (c) 1994, Simon J. Gerraty.
*
* This is free software. It comes with NO WARRANTY.
* Permission to use, modify and distribute this source code
* is granted subject to the following conditions.
* 1/ that the above copyright notice and this notice
* are preserved in all copies.
*/
/* \summary: Telnet option printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <stdio.h>
#include "netdissect.h"
#include "extract.h"
/* NetBSD: telnet.h,v 1.9 2001/06/11 01:50:50 wiz Exp */
/*
* Definitions for the TELNET protocol.
*/
#define IAC 255 /* interpret as command: */
#define DONT 254 /* you are not to use option */
#define DO 253 /* please, you use option */
#define WONT 252 /* I won't use option */
#define WILL 251 /* I will use option */
#define SB 250 /* interpret as subnegotiation */
#define GA 249 /* you may reverse the line */
#define EL 248 /* erase the current line */
#define EC 247 /* erase the current character */
#define AYT 246 /* are you there */
#define AO 245 /* abort output--but let prog finish */
#define IP 244 /* interrupt process--permanently */
#define BREAK 243 /* break */
#define DM 242 /* data mark--for connect. cleaning */
#define NOP 241 /* nop */
#define SE 240 /* end sub negotiation */
#define EOR 239 /* end of record (transparent mode) */
#define ABORT 238 /* Abort process */
#define SUSP 237 /* Suspend process */
#define xEOF 236 /* End of file: EOF is already used... */
#define SYNCH 242 /* for telfunc calls */
static const char *telcmds[] = {
"EOF", "SUSP", "ABORT", "EOR",
"SE", "NOP", "DMARK", "BRK", "IP", "AO", "AYT", "EC",
"EL", "GA", "SB", "WILL", "WONT", "DO", "DONT", "IAC", 0,
};
#define TELCMD_FIRST xEOF
#define TELCMD_LAST IAC
#define TELCMD_OK(x) ((unsigned int)(x) <= TELCMD_LAST && \
(unsigned int)(x) >= TELCMD_FIRST)
#define TELCMD(x) telcmds[(x)-TELCMD_FIRST]
/* telnet options */
#define TELOPT_BINARY 0 /* 8-bit data path */
#define TELOPT_ECHO 1 /* echo */
#define TELOPT_RCP 2 /* prepare to reconnect */
#define TELOPT_SGA 3 /* suppress go ahead */
#define TELOPT_NAMS 4 /* approximate message size */
#define TELOPT_STATUS 5 /* give status */
#define TELOPT_TM 6 /* timing mark */
#define TELOPT_RCTE 7 /* remote controlled transmission and echo */
#define TELOPT_NAOL 8 /* negotiate about output line width */
#define TELOPT_NAOP 9 /* negotiate about output page size */
#define TELOPT_NAOCRD 10 /* negotiate about CR disposition */
#define TELOPT_NAOHTS 11 /* negotiate about horizontal tabstops */
#define TELOPT_NAOHTD 12 /* negotiate about horizontal tab disposition */
#define TELOPT_NAOFFD 13 /* negotiate about formfeed disposition */
#define TELOPT_NAOVTS 14 /* negotiate about vertical tab stops */
#define TELOPT_NAOVTD 15 /* negotiate about vertical tab disposition */
#define TELOPT_NAOLFD 16 /* negotiate about output LF disposition */
-#define TELOPT_XASCII 17 /* extended ascic character set */
+#define TELOPT_XASCII 17 /* extended ascii character set */
#define TELOPT_LOGOUT 18 /* force logout */
#define TELOPT_BM 19 /* byte macro */
#define TELOPT_DET 20 /* data entry terminal */
#define TELOPT_SUPDUP 21 /* supdup protocol */
#define TELOPT_SUPDUPOUTPUT 22 /* supdup output */
#define TELOPT_SNDLOC 23 /* send location */
#define TELOPT_TTYPE 24 /* terminal type */
#define TELOPT_EOR 25 /* end or record */
#define TELOPT_TUID 26 /* TACACS user identification */
#define TELOPT_OUTMRK 27 /* output marking */
#define TELOPT_TTYLOC 28 /* terminal location number */
#define TELOPT_3270REGIME 29 /* 3270 regime */
#define TELOPT_X3PAD 30 /* X.3 PAD */
#define TELOPT_NAWS 31 /* window size */
#define TELOPT_TSPEED 32 /* terminal speed */
#define TELOPT_LFLOW 33 /* remote flow control */
#define TELOPT_LINEMODE 34 /* Linemode option */
#define TELOPT_XDISPLOC 35 /* X Display Location */
#define TELOPT_OLD_ENVIRON 36 /* Old - Environment variables */
#define TELOPT_AUTHENTICATION 37/* Authenticate */
#define TELOPT_ENCRYPT 38 /* Encryption option */
#define TELOPT_NEW_ENVIRON 39 /* New - Environment variables */
#define TELOPT_EXOPL 255 /* extended-options-list */
#define NTELOPTS (1+TELOPT_NEW_ENVIRON)
static const char *telopts[NTELOPTS+1] = {
"BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME",
"STATUS", "TIMING MARK", "RCTE", "NAOL", "NAOP",
"NAOCRD", "NAOHTS", "NAOHTD", "NAOFFD", "NAOVTS",
"NAOVTD", "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO",
"DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT",
"SEND LOCATION", "TERMINAL TYPE", "END OF RECORD",
"TACACS UID", "OUTPUT MARKING", "TTYLOC",
"3270 REGIME", "X.3 PAD", "NAWS", "TSPEED", "LFLOW",
"LINEMODE", "XDISPLOC", "OLD-ENVIRON", "AUTHENTICATION",
"ENCRYPT", "NEW-ENVIRON",
0,
};
#define TELOPT_FIRST TELOPT_BINARY
#define TELOPT_LAST TELOPT_NEW_ENVIRON
#define TELOPT_OK(x) ((unsigned int)(x) <= TELOPT_LAST)
#define TELOPT(x) telopts[(x)-TELOPT_FIRST]
/* sub-option qualifiers */
#define TELQUAL_IS 0 /* option is... */
#define TELQUAL_SEND 1 /* send option */
#define TELQUAL_INFO 2 /* ENVIRON: informational version of IS */
#define TELQUAL_REPLY 2 /* AUTHENTICATION: client version of IS */
#define TELQUAL_NAME 3 /* AUTHENTICATION: client version of IS */
#define LFLOW_OFF 0 /* Disable remote flow control */
#define LFLOW_ON 1 /* Enable remote flow control */
#define LFLOW_RESTART_ANY 2 /* Restart output on any char */
#define LFLOW_RESTART_XON 3 /* Restart output only on XON */
/*
* LINEMODE suboptions
*/
#define LM_MODE 1
#define LM_FORWARDMASK 2
#define LM_SLC 3
#define MODE_EDIT 0x01
#define MODE_TRAPSIG 0x02
#define MODE_ACK 0x04
#define MODE_SOFT_TAB 0x08
#define MODE_LIT_ECHO 0x10
#define MODE_MASK 0x1f
#define SLC_SYNCH 1
#define SLC_BRK 2
#define SLC_IP 3
#define SLC_AO 4
#define SLC_AYT 5
#define SLC_EOR 6
#define SLC_ABORT 7
#define SLC_EOF 8
#define SLC_SUSP 9
#define SLC_EC 10
#define SLC_EL 11
#define SLC_EW 12
#define SLC_RP 13
#define SLC_LNEXT 14
#define SLC_XON 15
#define SLC_XOFF 16
#define SLC_FORW1 17
#define SLC_FORW2 18
#define SLC_MCL 19
#define SLC_MCR 20
#define SLC_MCWL 21
#define SLC_MCWR 22
#define SLC_MCBOL 23
#define SLC_MCEOL 24
#define SLC_INSRT 25
#define SLC_OVER 26
#define SLC_ECR 27
#define SLC_EWR 28
#define SLC_EBOL 29
#define SLC_EEOL 30
#define NSLC 30
/*
* For backwards compatibility, we define SLC_NAMES to be the
* list of names if SLC_NAMES is not defined.
*/
#define SLC_NAMELIST "0", "SYNCH", "BRK", "IP", "AO", "AYT", "EOR", \
"ABORT", "EOF", "SUSP", "EC", "EL", "EW", "RP", \
"LNEXT", "XON", "XOFF", "FORW1", "FORW2", \
"MCL", "MCR", "MCWL", "MCWR", "MCBOL", \
"MCEOL", "INSRT", "OVER", "ECR", "EWR", \
"EBOL", "EEOL", \
0,
#ifdef SLC_NAMES
const char *slc_names[] = {
SLC_NAMELIST
};
#else
extern char *slc_names[];
#define SLC_NAMES SLC_NAMELIST
#endif
#define SLC_NAME_OK(x) ((unsigned int)(x) <= NSLC)
#define SLC_NAME(x) slc_names[x]
#define SLC_NOSUPPORT 0
#define SLC_CANTCHANGE 1
#define SLC_VARIABLE 2
#define SLC_DEFAULT 3
#define SLC_LEVELBITS 0x03
#define SLC_FUNC 0
#define SLC_FLAGS 1
#define SLC_VALUE 2
#define SLC_ACK 0x80
#define SLC_FLUSHIN 0x40
#define SLC_FLUSHOUT 0x20
#define OLD_ENV_VAR 1
#define OLD_ENV_VALUE 0
#define NEW_ENV_VAR 0
#define NEW_ENV_VALUE 1
#define ENV_ESC 2
#define ENV_USERVAR 3
/*
* AUTHENTICATION suboptions
*/
/*
* Who is authenticating who ...
*/
#define AUTH_WHO_CLIENT 0 /* Client authenticating server */
#define AUTH_WHO_SERVER 1 /* Server authenticating client */
#define AUTH_WHO_MASK 1
#define AUTHTYPE_NULL 0
#define AUTHTYPE_KERBEROS_V4 1
#define AUTHTYPE_KERBEROS_V5 2
#define AUTHTYPE_SPX 3
#define AUTHTYPE_MINK 4
#define AUTHTYPE_CNT 5
#define AUTHTYPE_TEST 99
#ifdef AUTH_NAMES
const char *authtype_names[] = {
"NULL", "KERBEROS_V4", "KERBEROS_V5", "SPX", "MINK", 0,
};
#else
extern char *authtype_names[];
#endif
#define AUTHTYPE_NAME_OK(x) ((unsigned int)(x) < AUTHTYPE_CNT)
#define AUTHTYPE_NAME(x) authtype_names[x]
/*
* ENCRYPTion suboptions
*/
#define ENCRYPT_IS 0 /* I pick encryption type ... */
#define ENCRYPT_SUPPORT 1 /* I support encryption types ... */
#define ENCRYPT_REPLY 2 /* Initial setup response */
#define ENCRYPT_START 3 /* Am starting to send encrypted */
#define ENCRYPT_END 4 /* Am ending encrypted */
#define ENCRYPT_REQSTART 5 /* Request you start encrypting */
#define ENCRYPT_REQEND 6 /* Request you send encrypting */
#define ENCRYPT_ENC_KEYID 7
#define ENCRYPT_DEC_KEYID 8
#define ENCRYPT_CNT 9
#define ENCTYPE_ANY 0
#define ENCTYPE_DES_CFB64 1
#define ENCTYPE_DES_OFB64 2
#define ENCTYPE_CNT 3
#ifdef ENCRYPT_NAMES
const char *encrypt_names[] = {
"IS", "SUPPORT", "REPLY", "START", "END",
"REQUEST-START", "REQUEST-END", "ENC-KEYID", "DEC-KEYID",
0,
};
const char *enctype_names[] = {
"ANY", "DES_CFB64", "DES_OFB64", 0,
};
#else
extern char *encrypt_names[];
extern char *enctype_names[];
#endif
#define ENCRYPT_NAME_OK(x) ((unsigned int)(x) < ENCRYPT_CNT)
#define ENCRYPT_NAME(x) encrypt_names[x]
#define ENCTYPE_NAME_OK(x) ((unsigned int)(x) < ENCTYPE_CNT)
#define ENCTYPE_NAME(x) enctype_names[x]
/* normal */
static const char *cmds[] = {
"IS", "SEND", "INFO",
};
/* 37: Authentication */
static const char *authcmd[] = {
"IS", "SEND", "REPLY", "NAME",
};
static const char *authtype[] = {
"NULL", "KERBEROS_V4", "KERBEROS_V5", "SPX", "MINK",
"SRP", "RSA", "SSL", NULL, NULL,
"LOKI", "SSA", "KEA_SJ", "KEA_SJ_INTEG", "DSS",
"NTLM",
};
/* 38: Encryption */
static const char *enccmd[] = {
"IS", "SUPPORT", "REPLY", "START", "END",
"REQUEST-START", "REQUEST-END", "END_KEYID", "DEC_KEYID",
};
static const char *enctype[] = {
"NULL", "DES_CFB64", "DES_OFB64", "DES3_CFB64", "DES3_OFB64",
NULL, "CAST5_40_CFB64", "CAST5_40_OFB64", "CAST128_CFB64", "CAST128_OFB64",
};
#define STR_OR_ID(x, tab) \
(((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)]) ? tab[(x)] : numstr(x))
static char *
numstr(int x)
{
static char buf[20];
snprintf(buf, sizeof(buf), "%#x", x);
return buf;
}
/* sp points to IAC byte */
static int
telnet_parse(netdissect_options *ndo, const u_char *sp, u_int length, int print)
{
int i, x;
u_int c;
const u_char *osp, *p;
#define FETCH(c, sp, length) \
do { \
if (length < 1) \
goto pktend; \
c = GET_U_1(sp); \
sp++; \
length--; \
} while (0)
osp = sp;
FETCH(c, sp, length);
if (c != IAC)
goto pktend;
FETCH(c, sp, length);
if (c == IAC) { /* <IAC><IAC>! */
if (print)
ND_PRINT("IAC IAC");
goto done;
}
i = c - TELCMD_FIRST;
if (i < 0 || i > IAC - TELCMD_FIRST)
goto pktend;
switch (c) {
case DONT:
case DO:
case WONT:
case WILL:
case SB:
/* DONT/DO/WONT/WILL x */
FETCH(x, sp, length);
if (x >= 0 && x < NTELOPTS) {
if (print)
ND_PRINT("%s %s", telcmds[i], telopts[x]);
} else {
if (print)
ND_PRINT("%s %#x", telcmds[i], x);
}
if (c != SB)
break;
/* IAC SB .... IAC SE */
p = sp;
while (length > (u_int)(p + 1 - sp)) {
if (GET_U_1(p) == IAC && GET_U_1(p + 1) == SE)
break;
p++;
}
if (GET_U_1(p) != IAC)
goto pktend;
switch (x) {
case TELOPT_AUTHENTICATION:
if (p <= sp)
break;
FETCH(c, sp, length);
if (print)
ND_PRINT(" %s", STR_OR_ID(c, authcmd));
if (p <= sp)
break;
FETCH(c, sp, length);
if (print)
ND_PRINT(" %s", STR_OR_ID(c, authtype));
break;
case TELOPT_ENCRYPT:
if (p <= sp)
break;
FETCH(c, sp, length);
if (print)
ND_PRINT(" %s", STR_OR_ID(c, enccmd));
if (p <= sp)
break;
FETCH(c, sp, length);
if (print)
ND_PRINT(" %s", STR_OR_ID(c, enctype));
break;
default:
if (p <= sp)
break;
FETCH(c, sp, length);
if (print)
ND_PRINT(" %s", STR_OR_ID(c, cmds));
break;
}
while (p > sp) {
FETCH(x, sp, length);
if (print)
ND_PRINT(" %#x", x);
}
/* terminating IAC SE */
if (print)
ND_PRINT(" SE");
sp += 2;
break;
default:
if (print)
ND_PRINT("%s", telcmds[i]);
goto done;
}
done:
return (int)(sp - osp);
pktend:
return -1;
#undef FETCH
}
void
telnet_print(netdissect_options *ndo, const u_char *sp, u_int length)
{
int first = 1;
const u_char *osp;
int l;
ndo->ndo_protocol = "telnet";
osp = sp;
while (length > 0 && GET_U_1(sp) == IAC) {
/*
* Parse the Telnet command without printing it,
* to determine its length.
*/
l = telnet_parse(ndo, sp, length, 0);
if (l < 0)
break;
/*
* now print it
*/
if (ndo->ndo_Xflag && 2 < ndo->ndo_vflag) {
if (first)
ND_PRINT("\nTelnet:");
hex_print_with_offset(ndo, "\n", sp, l, (u_int)(sp - osp));
if (l > 8)
ND_PRINT("\n\t\t\t\t");
else
ND_PRINT("%*s\t", (8 - l) * 3, "");
} else
ND_PRINT("%s", (first) ? " [telnet " : ", ");
(void)telnet_parse(ndo, sp, length, 1);
first = 0;
sp += l;
length -= l;
}
if (!first) {
if (ndo->ndo_Xflag && 2 < ndo->ndo_vflag)
ND_PRINT("\n");
else
ND_PRINT("]");
}
}
diff --git a/contrib/tcpdump/print-tftp.c b/contrib/tcpdump/print-tftp.c
index 39fc6964b8a2..ec64a5c9dfa9 100644
--- a/contrib/tcpdump/print-tftp.c
+++ b/contrib/tcpdump/print-tftp.c
@@ -1,198 +1,196 @@
/*
* 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.
*/
/* \summary: Trivial File Transfer Protocol (TFTP) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "extract.h"
/*
* Trivial File Transfer Protocol (IEN-133)
*/
/*
* Packet types.
*/
#define RRQ 01 /* read request */
#define WRQ 02 /* write request */
#define DATA 03 /* data packet */
#define ACK 04 /* acknowledgement */
#define TFTP_ERROR 05 /* error code */
#define OACK 06 /* option acknowledgement */
/*
* Error codes.
*/
#define EUNDEF 0 /* not defined */
#define ENOTFOUND 1 /* file not found */
#define EACCESS 2 /* access violation */
#define ENOSPACE 3 /* disk full or allocation exceeded */
#define EBADOP 4 /* illegal TFTP operation */
#define EBADID 5 /* unknown transfer ID */
#define EEXISTS 6 /* file already exists */
#define ENOUSER 7 /* no such user */
/* op code to string mapping */
static const struct tok op2str[] = {
{ RRQ, "RRQ" }, /* read request */
{ WRQ, "WRQ" }, /* write request */
{ DATA, "DATA" }, /* data packet */
{ ACK, "ACK" }, /* acknowledgement */
{ TFTP_ERROR, "ERROR" }, /* error code */
{ OACK, "OACK" }, /* option acknowledgement */
{ 0, NULL }
};
/* error code to string mapping */
static const struct tok err2str[] = {
{ EUNDEF, "EUNDEF" }, /* not defined */
{ ENOTFOUND, "ENOTFOUND" }, /* file not found */
{ EACCESS, "EACCESS" }, /* access violation */
{ ENOSPACE, "ENOSPACE" }, /* disk full or allocation exceeded */
{ EBADOP, "EBADOP" }, /* illegal TFTP operation */
{ EBADID, "EBADID" }, /* unknown transfer ID */
{ EEXISTS, "EEXISTS" }, /* file already exists */
{ ENOUSER, "ENOUSER" }, /* no such user */
{ 0, NULL }
};
/*
* Print trivial file transfer program requests
*/
void
tftp_print(netdissect_options *ndo,
const u_char *bp, u_int length)
{
const char *cp;
u_int opcode;
u_int ui;
ndo->ndo_protocol = "tftp";
/* Print protocol */
nd_print_protocol_caps(ndo);
/* Print length */
ND_PRINT(", length %u", length);
/* Print tftp request type */
if (length < 2)
goto trunc;
opcode = GET_BE_U_2(bp);
cp = tok2str(op2str, "tftp-#%u", opcode);
ND_PRINT(", %s", cp);
/* Bail if bogus opcode */
if (*cp == 't')
return;
bp += 2;
length -= 2;
switch (opcode) {
case RRQ:
case WRQ:
if (length == 0)
goto trunc;
ND_PRINT(" ");
/* Print filename */
ND_PRINT("\"");
ui = nd_printztn(ndo, bp, length, ndo->ndo_snapend);
ND_PRINT("\"");
if (ui == 0)
goto trunc;
bp += ui;
length -= ui;
/* Print the mode - RRQ and WRQ only */
if (length == 0)
goto trunc; /* no mode */
ND_PRINT(" ");
ui = nd_printztn(ndo, bp, length, ndo->ndo_snapend);
if (ui == 0)
goto trunc;
bp += ui;
length -= ui;
/* Print options, if any */
while (length != 0) {
if (GET_U_1(bp) != '\0')
ND_PRINT(" ");
ui = nd_printztn(ndo, bp, length, ndo->ndo_snapend);
if (ui == 0)
goto trunc;
bp += ui;
length -= ui;
}
break;
case OACK:
/* Print options */
while (length != 0) {
if (GET_U_1(bp) != '\0')
ND_PRINT(" ");
ui = nd_printztn(ndo, bp, length, ndo->ndo_snapend);
if (ui == 0)
goto trunc;
bp += ui;
length -= ui;
}
break;
case ACK:
case DATA:
if (length < 2)
goto trunc; /* no block number */
ND_PRINT(" block %u", GET_BE_U_2(bp));
break;
case TFTP_ERROR:
/* Print error code string */
if (length < 2)
goto trunc; /* no error code */
ND_PRINT(" %s", tok2str(err2str, "tftp-err-#%u \"",
GET_BE_U_2(bp)));
bp += 2;
length -= 2;
/* Print error message string */
if (length == 0)
goto trunc; /* no error message */
ND_PRINT(" \"");
ui = nd_printztn(ndo, bp, length, ndo->ndo_snapend);
ND_PRINT("\"");
if (ui == 0)
goto trunc;
break;
default:
/* We shouldn't get here */
ND_PRINT("(unknown #%u)", opcode);
break;
}
return;
trunc:
nd_print_trunc(ndo);
}
diff --git a/contrib/tcpdump/print-timed.c b/contrib/tcpdump/print-timed.c
index ebd0ac8adca6..6733ef1beef3 100644
--- a/contrib/tcpdump/print-timed.c
+++ b/contrib/tcpdump/print-timed.c
@@ -1,153 +1,151 @@
/*
* Copyright (c) 2000 Ben Smithurst <ben@scientia.demon.co.uk>
* 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.
*/
/* \summary: Berkeley UNIX Time Synchronization Protocol */
/* specification: https://docs.freebsd.org/44doc/smm/12.timed/paper.pdf */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "extract.h"
struct tsp_timeval {
nd_int32_t tv_sec;
nd_int32_t tv_usec;
};
struct tsp {
nd_uint8_t tsp_type;
nd_uint8_t tsp_vers;
nd_uint16_t tsp_seq;
union {
struct tsp_timeval tspu_time;
nd_int8_t tspu_hopcnt;
} tsp_u;
nd_byte tsp_name[256]; /* null-terminated string up to 256 */
};
#define tsp_time tsp_u.tspu_time
#define tsp_hopcnt tsp_u.tspu_hopcnt
/*
* Command types.
*/
#define TSP_ANY 0 /* match any types */
#define TSP_ADJTIME 1 /* send adjtime */
#define TSP_ACK 2 /* generic acknowledgement */
#define TSP_MASTERREQ 3 /* ask for master's name */
#define TSP_MASTERACK 4 /* acknowledge master request */
#define TSP_SETTIME 5 /* send network time */
#define TSP_MASTERUP 6 /* inform slaves that master is up */
#define TSP_SLAVEUP 7 /* slave is up but not polled */
#define TSP_ELECTION 8 /* advance candidature for master */
#define TSP_ACCEPT 9 /* support candidature of master */
#define TSP_REFUSE 10 /* reject candidature of master */
#define TSP_CONFLICT 11 /* two or more masters present */
#define TSP_RESOLVE 12 /* masters' conflict resolution */
#define TSP_QUIT 13 /* reject candidature if master is up */
#define TSP_DATE 14 /* reset the time (date command) */
#define TSP_DATEREQ 15 /* remote request to reset the time */
#define TSP_DATEACK 16 /* acknowledge time setting */
#define TSP_TRACEON 17 /* turn tracing on */
#define TSP_TRACEOFF 18 /* turn tracing off */
#define TSP_MSITE 19 /* find out master's site */
#define TSP_MSITEREQ 20 /* remote master's site request */
#define TSP_TEST 21 /* for testing election algo */
#define TSP_SETDATE 22 /* New from date command */
#define TSP_SETDATEREQ 23 /* New remote for above */
#define TSP_LOOP 24 /* loop detection packet */
static const struct tok tsptype_str[] = {
{ TSP_ANY, "TSP_ANY" },
{ TSP_ADJTIME, "TSP_ADJTIME" },
{ TSP_ACK, "TSP_ACK" },
{ TSP_MASTERREQ, "TSP_MASTERREQ" },
{ TSP_MASTERACK, "TSP_MASTERACK" },
{ TSP_SETTIME, "TSP_SETTIME" },
{ TSP_MASTERUP, "TSP_MASTERUP" },
{ TSP_SLAVEUP, "TSP_SLAVEUP" },
{ TSP_ELECTION, "TSP_ELECTION" },
{ TSP_ACCEPT, "TSP_ACCEPT" },
{ TSP_REFUSE, "TSP_REFUSE" },
{ TSP_CONFLICT, "TSP_CONFLICT" },
{ TSP_RESOLVE, "TSP_RESOLVE" },
{ TSP_QUIT, "TSP_QUIT" },
{ TSP_DATE, "TSP_DATE" },
{ TSP_DATEREQ, "TSP_DATEREQ" },
{ TSP_DATEACK, "TSP_DATEACK" },
{ TSP_TRACEON, "TSP_TRACEON" },
{ TSP_TRACEOFF, "TSP_TRACEOFF" },
{ TSP_MSITE, "TSP_MSITE" },
{ TSP_MSITEREQ, "TSP_MSITEREQ" },
{ TSP_TEST, "TSP_TEST" },
{ TSP_SETDATE, "TSP_SETDATE" },
{ TSP_SETDATEREQ, "TSP_SETDATEREQ" },
{ TSP_LOOP, "TSP_LOOP" },
{ 0, NULL }
};
void
timed_print(netdissect_options *ndo,
const u_char *bp)
{
const struct tsp *tsp = (const struct tsp *)bp;
uint8_t tsp_type;
int sec, usec;
ndo->ndo_protocol = "timed";
tsp_type = GET_U_1(tsp->tsp_type);
ND_PRINT("%s", tok2str(tsptype_str, "(tsp_type %#x)", tsp_type));
ND_PRINT(" vers %u", GET_U_1(tsp->tsp_vers));
ND_PRINT(" seq %u", GET_BE_U_2(tsp->tsp_seq));
switch (tsp_type) {
case TSP_LOOP:
ND_PRINT(" hopcnt %u", GET_U_1(tsp->tsp_hopcnt));
break;
case TSP_SETTIME:
case TSP_ADJTIME:
case TSP_SETDATE:
case TSP_SETDATEREQ:
sec = GET_BE_S_4(tsp->tsp_time.tv_sec);
usec = GET_BE_S_4(tsp->tsp_time.tv_usec);
/* XXX The comparison below is always false? */
if (usec < 0)
/* invalid, skip the rest of the packet */
return;
ND_PRINT(" time ");
if (sec < 0 && usec != 0) {
sec++;
if (sec == 0)
ND_PRINT("-");
usec = 1000000 - usec;
}
ND_PRINT("%d.%06d", sec, usec);
break;
}
ND_PRINT(" name ");
nd_printjnp(ndo, tsp->tsp_name, sizeof(tsp->tsp_name));
}
diff --git a/contrib/tcpdump/print-tipc.c b/contrib/tcpdump/print-tipc.c
index 54179a4ea605..ec5f1a542c7b 100644
--- a/contrib/tcpdump/print-tipc.c
+++ b/contrib/tcpdump/print-tipc.c
@@ -1,354 +1,350 @@
/*
* Copyright (c) 1988, 1989, 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.
*/
/* \summary: Transparent Inter-Process Communication (TIPC) protocol printer */
/*
* specification:
* https://web.archive.org/web/20150302152944/http://tipc.sourceforge.net/doc/draft-spec-tipc-07.html
* https://web.archive.org/web/20161025110514/http://tipc.sourceforge.net/doc/tipc_message_formats.html
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
-#include "ethertype.h"
#include "extract.h"
#define TIPC_USER_LOW_IMPORTANCE 0
#define TIPC_USER_MEDIUM_IMPORTANCE 1
#define TIPC_USER_HIGH_IMPORTANCE 2
#define TIPC_USER_CRITICAL_IMPORTANCE 3
#define TIPC_USER_BCAST_PROTOCOL 5
#define TIPC_USER_MSG_BUNDLER 6
#define TIPC_USER_LINK_PROTOCOL 7
#define TIPC_USER_CONN_MANAGER 8
#define TIPC_USER_CHANGEOVER_PROTOCOL 10
#define TIPC_USER_NAME_DISTRIBUTOR 11
#define TIPC_USER_MSG_FRAGMENTER 12
#define TIPC_USER_LINK_CONFIG 13
#define TIPC_CONN_MSG 0
#define TIPC_DIRECT_MSG 1
#define TIPC_NAMED_MSG 2
#define TIPC_MCAST_MSG 3
#define TIPC_ZONE(addr) (((addr) >> 24) & 0xFF)
#define TIPC_CLUSTER(addr) (((addr) >> 12) & 0xFFF)
#define TIPC_NODE(addr) (((addr) >> 0) & 0xFFF)
struct tipc_pkthdr {
nd_uint32_t w0;
nd_uint32_t w1;
};
#define TIPC_VER(w0) (((w0) >> 29) & 0x07)
#define TIPC_USER(w0) (((w0) >> 25) & 0x0F)
#define TIPC_HSIZE(w0) (((w0) >> 21) & 0x0F)
#define TIPC_MSIZE(w0) (((w0) >> 0) & 0x1FFFF)
#define TIPC_MTYPE(w1) (((w1) >> 29) & 0x07)
#define TIPC_BROADCAST_ACK(w1) (((w1) >> 0) & 0xFFFF)
#define TIPC_LINK_ACK(w2) (((w2) >> 16) & 0xFFFF)
#define TIPC_LINK_SEQ(w2) (((w2) >> 0) & 0xFFFF)
static const struct tok tipcuser_values[] = {
{ TIPC_USER_LOW_IMPORTANCE, "Low Importance Data payload" },
{ TIPC_USER_MEDIUM_IMPORTANCE, "Medium Importance Data payload" },
{ TIPC_USER_HIGH_IMPORTANCE, "High Importance Data payload" },
{ TIPC_USER_CRITICAL_IMPORTANCE, "Critical Importance Data payload" },
{ TIPC_USER_BCAST_PROTOCOL, "Broadcast Link Protocol internal" },
{ TIPC_USER_MSG_BUNDLER, "Message Bundler Protocol internal" },
{ TIPC_USER_LINK_PROTOCOL, "Link State Protocol internal" },
{ TIPC_USER_CONN_MANAGER, "Connection Manager internal" },
{ TIPC_USER_CHANGEOVER_PROTOCOL, "Link Changeover Protocol internal" },
{ TIPC_USER_NAME_DISTRIBUTOR, "Name Table Update Protocol internal" },
{ TIPC_USER_MSG_FRAGMENTER, "Message Fragmentation Protocol internal" },
{ TIPC_USER_LINK_CONFIG, "Neighbor Detection Protocol internal" },
{ 0, NULL }
};
static const struct tok tipcmtype_values[] = {
{ TIPC_CONN_MSG, "CONN_MSG" },
{ TIPC_DIRECT_MSG, "MCAST_MSG" },
{ TIPC_NAMED_MSG, "NAMED_MSG" },
{ TIPC_MCAST_MSG, "DIRECT_MSG" },
{ 0, NULL }
};
static const struct tok tipc_linkconf_mtype_values[] = {
{ 0, "Link request" },
{ 1, "Link response" },
{ 0, NULL }
};
struct payload_tipc_pkthdr {
nd_uint32_t w0;
nd_uint32_t w1;
nd_uint32_t w2;
nd_uint32_t prev_node;
nd_uint32_t orig_port;
nd_uint32_t dest_port;
nd_uint32_t orig_node;
nd_uint32_t dest_node;
nd_uint32_t name_type;
nd_uint32_t w9;
nd_uint32_t wA;
};
struct internal_tipc_pkthdr {
nd_uint32_t w0;
nd_uint32_t w1;
nd_uint32_t w2;
nd_uint32_t prev_node;
nd_uint32_t w4;
nd_uint32_t w5;
nd_uint32_t orig_node;
nd_uint32_t dest_node;
nd_uint32_t trans_seq;
nd_uint32_t w9;
};
#define TIPC_SEQ_GAP(w1) (((w1) >> 16) & 0x1FFF)
#define TIPC_BC_GAP_AFTER(w2) (((w2) >> 16) & 0xFFFF)
#define TIPC_BC_GAP_TO(w2) (((w2) >> 0) & 0xFFFF)
#define TIPC_LAST_SENT_FRAG(w4) (((w4) >> 16) & 0xFFFF)
#define TIPC_NEXT_SENT_FRAG(w4) (((w4) >> 0) & 0xFFFF)
#define TIPC_SESS_NO(w5) (((w5) >> 16) & 0xFFFF)
#define TIPC_MSG_CNT(w9) (((w9) >> 16) & 0xFFFF)
#define TIPC_LINK_TOL(w9) (((w9) >> 0) & 0xFFFF)
struct link_conf_tipc_pkthdr {
nd_uint32_t w0;
nd_uint32_t w1;
nd_uint32_t dest_domain;
nd_uint32_t prev_node;
nd_uint32_t ntwrk_id;
nd_uint32_t w5;
nd_byte media_address[16];
};
#define TIPC_NODE_SIG(w1) (((w1) >> 0) & 0xFFFF)
#define TIPC_MEDIA_ID(w5) (((w5) >> 0) & 0xFF)
static void
print_payload(netdissect_options *ndo, const struct payload_tipc_pkthdr *ap)
{
uint32_t w0, w1, w2;
u_int user;
u_int hsize;
u_int msize;
u_int mtype;
u_int broadcast_ack;
u_int link_ack;
u_int link_seq;
u_int prev_node;
u_int orig_port;
u_int dest_port;
u_int orig_node;
u_int dest_node;
w0 = GET_BE_U_4(ap->w0);
user = TIPC_USER(w0);
hsize = TIPC_HSIZE(w0);
msize = TIPC_MSIZE(w0);
w1 = GET_BE_U_4(ap->w1);
mtype = TIPC_MTYPE(w1);
prev_node = GET_BE_U_4(ap->prev_node);
orig_port = GET_BE_U_4(ap->orig_port);
dest_port = GET_BE_U_4(ap->dest_port);
if (hsize <= 6) {
ND_PRINT("TIPC v%u.0 %u.%u.%u:%u > %u, headerlength %u bytes, MessageSize %u bytes, %s, messageType %s",
TIPC_VER(w0),
TIPC_ZONE(prev_node), TIPC_CLUSTER(prev_node), TIPC_NODE(prev_node),
orig_port, dest_port,
hsize*4, msize,
tok2str(tipcuser_values, "unknown", user),
tok2str(tipcmtype_values, "Unknown", mtype));
} else {
orig_node = GET_BE_U_4(ap->orig_node);
dest_node = GET_BE_U_4(ap->dest_node);
ND_PRINT("TIPC v%u.0 %u.%u.%u:%u > %u.%u.%u:%u, headerlength %u bytes, MessageSize %u bytes, %s, messageType %s",
TIPC_VER(w0),
TIPC_ZONE(orig_node), TIPC_CLUSTER(orig_node), TIPC_NODE(orig_node),
orig_port,
TIPC_ZONE(dest_node), TIPC_CLUSTER(dest_node), TIPC_NODE(dest_node),
dest_port,
hsize*4, msize,
tok2str(tipcuser_values, "unknown", user),
tok2str(tipcmtype_values, "Unknown", mtype));
if (ndo->ndo_vflag) {
broadcast_ack = TIPC_BROADCAST_ACK(w1);
w2 = GET_BE_U_4(ap->w2);
link_ack = TIPC_LINK_ACK(w2);
link_seq = TIPC_LINK_SEQ(w2);
ND_PRINT("\n\tPrevious Node %u.%u.%u, Broadcast Ack %u, Link Ack %u, Link Sequence %u",
TIPC_ZONE(prev_node), TIPC_CLUSTER(prev_node), TIPC_NODE(prev_node),
broadcast_ack, link_ack, link_seq);
}
}
}
static void
print_internal(netdissect_options *ndo, const struct internal_tipc_pkthdr *ap)
{
uint32_t w0, w1, w2, w4, w5, w9;
u_int user;
u_int hsize;
u_int msize;
u_int mtype;
u_int seq_gap;
u_int broadcast_ack;
u_int bc_gap_after;
u_int bc_gap_to;
u_int prev_node;
u_int last_sent_frag;
u_int next_sent_frag;
u_int sess_no;
u_int orig_node;
u_int dest_node;
u_int trans_seq;
u_int msg_cnt;
u_int link_tol;
w0 = GET_BE_U_4(ap->w0);
user = TIPC_USER(w0);
hsize = TIPC_HSIZE(w0);
msize = TIPC_MSIZE(w0);
w1 = GET_BE_U_4(ap->w1);
mtype = TIPC_MTYPE(w1);
orig_node = GET_BE_U_4(ap->orig_node);
dest_node = GET_BE_U_4(ap->dest_node);
ND_PRINT("TIPC v%u.0 %u.%u.%u > %u.%u.%u, headerlength %u bytes, MessageSize %u bytes, %s, messageType %s (0x%08x)",
TIPC_VER(w0),
TIPC_ZONE(orig_node), TIPC_CLUSTER(orig_node), TIPC_NODE(orig_node),
TIPC_ZONE(dest_node), TIPC_CLUSTER(dest_node), TIPC_NODE(dest_node),
hsize*4, msize,
tok2str(tipcuser_values, "unknown", user),
tok2str(tipcmtype_values, "Unknown", mtype), w1);
if (ndo->ndo_vflag) {
seq_gap = TIPC_SEQ_GAP(w1);
broadcast_ack = TIPC_BROADCAST_ACK(w1);
w2 = GET_BE_U_4(ap->w2);
bc_gap_after = TIPC_BC_GAP_AFTER(w2);
bc_gap_to = TIPC_BC_GAP_TO(w2);
prev_node = GET_BE_U_4(ap->prev_node);
w4 = GET_BE_U_4(ap->w4);
last_sent_frag = TIPC_LAST_SENT_FRAG(w4);
next_sent_frag = TIPC_NEXT_SENT_FRAG(w4);
w5 = GET_BE_U_4(ap->w5);
sess_no = TIPC_SESS_NO(w5);
trans_seq = GET_BE_U_4(ap->trans_seq);
w9 = GET_BE_U_4(ap->w9);
msg_cnt = TIPC_MSG_CNT(w9);
link_tol = TIPC_LINK_TOL(w9);
ND_PRINT("\n\tPrevious Node %u.%u.%u, Session No. %u, Broadcast Ack %u, Sequence Gap %u, Broadcast Gap After %u, Broadcast Gap To %u, Last Sent Packet No. %u, Next sent Packet No. %u, Transport Sequence %u, msg_count %u, Link Tolerance %u",
TIPC_ZONE(prev_node), TIPC_CLUSTER(prev_node), TIPC_NODE(prev_node),
sess_no, broadcast_ack, seq_gap, bc_gap_after, bc_gap_to,
last_sent_frag, next_sent_frag, trans_seq, msg_cnt,
link_tol);
}
}
static void
print_link_conf(netdissect_options *ndo, const struct link_conf_tipc_pkthdr *ap)
{
uint32_t w0, w1, w5;
u_int user;
u_int hsize;
u_int msize;
u_int mtype;
u_int node_sig;
u_int prev_node;
u_int dest_domain;
u_int ntwrk_id;
u_int media_id;
w0 = GET_BE_U_4(ap->w0);
user = TIPC_USER(w0);
hsize = TIPC_HSIZE(w0);
msize = TIPC_MSIZE(w0);
w1 = GET_BE_U_4(ap->w1);
mtype = TIPC_MTYPE(w1);
dest_domain = GET_BE_U_4(ap->dest_domain);
prev_node = GET_BE_U_4(ap->prev_node);
ND_PRINT("TIPC v%u.0 %u.%u.%u > %u.%u.%u, headerlength %u bytes, MessageSize %u bytes, %s, messageType %s",
TIPC_VER(w0),
TIPC_ZONE(prev_node), TIPC_CLUSTER(prev_node), TIPC_NODE(prev_node),
TIPC_ZONE(dest_domain), TIPC_CLUSTER(dest_domain), TIPC_NODE(dest_domain),
hsize*4, msize,
tok2str(tipcuser_values, "unknown", user),
tok2str(tipc_linkconf_mtype_values, "Unknown", mtype));
if (ndo->ndo_vflag) {
node_sig = TIPC_NODE_SIG(w1);
ntwrk_id = GET_BE_U_4(ap->ntwrk_id);
w5 = GET_BE_U_4(ap->w5);
media_id = TIPC_MEDIA_ID(w5);
ND_PRINT("\n\tNodeSignature %u, network_id %u, media_id %u",
node_sig, ntwrk_id, media_id);
}
}
void
tipc_print(netdissect_options *ndo, const u_char *bp, u_int length _U_,
u_int caplen _U_)
{
const struct tipc_pkthdr *ap;
uint32_t w0;
u_int user;
ndo->ndo_protocol = "tipc";
ap = (const struct tipc_pkthdr *)bp;
w0 = GET_BE_U_4(ap->w0);
user = TIPC_USER(w0);
- switch (user)
- {
+ switch (user) {
case TIPC_USER_LOW_IMPORTANCE:
case TIPC_USER_MEDIUM_IMPORTANCE:
case TIPC_USER_HIGH_IMPORTANCE:
case TIPC_USER_CRITICAL_IMPORTANCE:
case TIPC_USER_NAME_DISTRIBUTOR:
case TIPC_USER_CONN_MANAGER:
print_payload(ndo, (const struct payload_tipc_pkthdr *)bp);
break;
case TIPC_USER_LINK_CONFIG:
print_link_conf(ndo, (const struct link_conf_tipc_pkthdr *)bp);
break;
case TIPC_USER_BCAST_PROTOCOL:
case TIPC_USER_MSG_BUNDLER:
case TIPC_USER_LINK_PROTOCOL:
case TIPC_USER_CHANGEOVER_PROTOCOL:
case TIPC_USER_MSG_FRAGMENTER:
print_internal(ndo, (const struct internal_tipc_pkthdr *)bp);
break;
}
}
diff --git a/contrib/tcpdump/print-token.c b/contrib/tcpdump/print-token.c
index bcb72584c294..6426cfe23514 100644
--- a/contrib/tcpdump/print-token.c
+++ b/contrib/tcpdump/print-token.c
@@ -1,250 +1,248 @@
/*
* Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
* 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.
*
* Hacked version of print-ether.c Larry Lile <lile@stdio.com>
*
* Further tweaked to more closely resemble print-fddi.c
* Guy Harris <guy@alum.mit.edu>
*/
/* \summary: Token Ring printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <string.h>
#include "netdissect.h"
#include "extract.h"
#include "addrtoname.h"
/*
* Copyright (c) 1998, Larry Lile
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#define TOKEN_HDRLEN 14
#define ROUTING_SEGMENT_MAX 16
#define IS_SOURCE_ROUTED(trp) ((trp)->token_shost[0] & 0x80)
#define FRAME_TYPE(trp) ((GET_U_1((trp)->token_fc) & 0xC0) >> 6)
#define TOKEN_FC_LLC 1
#define BROADCAST(trp) ((GET_BE_U_2((trp)->token_rcf) & 0xE000) >> 13)
#define RIF_LENGTH(trp) ((GET_BE_U_2((trp)->token_rcf) & 0x1f00) >> 8)
#define DIRECTION(trp) ((GET_BE_U_2((trp)->token_rcf) & 0x0080) >> 7)
#define LARGEST_FRAME(trp) ((GET_BE_U_2((trp)->token_rcf) & 0x0070) >> 4)
#define RING_NUMBER(trp, x) ((GET_BE_U_2((trp)->token_rseg[x]) & 0xfff0) >> 4)
#define BRIDGE_NUMBER(trp, x) (GET_BE_U_2((trp)->token_rseg[x]) & 0x000f)
#define SEGMENT_COUNT(trp) ((int)((RIF_LENGTH(trp) - 2) / 2))
struct token_header {
nd_uint8_t token_ac;
nd_uint8_t token_fc;
nd_mac_addr token_dhost;
nd_mac_addr token_shost;
nd_uint16_t token_rcf;
nd_uint16_t token_rseg[ROUTING_SEGMENT_MAX];
};
/* Extract src, dst addresses */
static void
extract_token_addrs(const struct token_header *trp, char *fsrc, char *fdst)
{
memcpy(fdst, (const char *)trp->token_dhost, 6);
memcpy(fsrc, (const char *)trp->token_shost, 6);
}
/*
* Print the TR MAC header
*/
static void
token_hdr_print(netdissect_options *ndo,
const struct token_header *trp, u_int length,
const u_char *fsrc, const u_char *fdst)
{
const char *srcname, *dstname;
srcname = etheraddr_string(ndo, fsrc);
dstname = etheraddr_string(ndo, fdst);
if (!ndo->ndo_qflag)
ND_PRINT("%02x %02x ",
GET_U_1(trp->token_ac),
GET_U_1(trp->token_fc));
ND_PRINT("%s > %s, length %u: ",
srcname, dstname,
length);
}
static const char *broadcast_indicator[] = {
"Non-Broadcast", "Non-Broadcast",
"Non-Broadcast", "Non-Broadcast",
"All-routes", "All-routes",
"Single-route", "Single-route"
};
static const char *direction[] = {
"Forward", "Backward"
};
static const char *largest_frame[] = {
"516",
"1500",
"2052",
"4472",
"8144",
"11407",
"17800",
"??"
};
u_int
token_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen)
{
const struct token_header *trp;
int llc_hdrlen;
nd_mac_addr srcmac, dstmac;
struct lladdr_info src, dst;
u_int route_len = 0, hdr_len = TOKEN_HDRLEN;
int seg;
ndo->ndo_protocol = "token-ring";
trp = (const struct token_header *)p;
if (caplen < TOKEN_HDRLEN) {
nd_print_trunc(ndo);
return hdr_len;
}
/*
* Get the TR addresses into a canonical form
*/
extract_token_addrs(trp, (char*)srcmac, (char*)dstmac);
/* Adjust for source routing information in the MAC header */
if (IS_SOURCE_ROUTED(trp)) {
/* Clear source-routed bit */
srcmac[0] &= 0x7f;
if (ndo->ndo_eflag)
token_hdr_print(ndo, trp, length, srcmac, dstmac);
if (caplen < TOKEN_HDRLEN + 2) {
nd_print_trunc(ndo);
return hdr_len;
}
route_len = RIF_LENGTH(trp);
hdr_len += route_len;
if (caplen < hdr_len) {
nd_print_trunc(ndo);
return hdr_len;
}
if (ndo->ndo_vflag) {
ND_PRINT("%s ", broadcast_indicator[BROADCAST(trp)]);
ND_PRINT("%s", direction[DIRECTION(trp)]);
for (seg = 0; seg < SEGMENT_COUNT(trp); seg++)
ND_PRINT(" [%u:%u]", RING_NUMBER(trp, seg),
BRIDGE_NUMBER(trp, seg));
} else {
ND_PRINT("rt = %x", GET_BE_U_2(trp->token_rcf));
for (seg = 0; seg < SEGMENT_COUNT(trp); seg++)
ND_PRINT(":%x",
GET_BE_U_2(trp->token_rseg[seg]));
}
ND_PRINT(" (%s) ", largest_frame[LARGEST_FRAME(trp)]);
} else {
if (ndo->ndo_eflag)
token_hdr_print(ndo, trp, length, srcmac, dstmac);
}
src.addr = srcmac;
src.addr_string = etheraddr_string;
dst.addr = dstmac;
dst.addr_string = etheraddr_string;
/* Skip over token ring MAC header and routing information */
length -= hdr_len;
p += hdr_len;
caplen -= hdr_len;
/* Frame Control field determines interpretation of packet */
if (FRAME_TYPE(trp) == TOKEN_FC_LLC) {
/* Try to print the LLC-layer header & higher layers */
llc_hdrlen = llc_print(ndo, p, length, caplen, &src, &dst);
if (llc_hdrlen < 0) {
/* packet type not known, print raw packet */
if (!ndo->ndo_suppress_default_print)
ND_DEFAULTPRINT(p, caplen);
llc_hdrlen = -llc_hdrlen;
}
hdr_len += llc_hdrlen;
} else {
/* Some kinds of TR packet we cannot handle intelligently */
/* XXX - dissect MAC packets if frame type is 0 */
if (!ndo->ndo_eflag)
token_hdr_print(ndo, trp, length + TOKEN_HDRLEN + route_len,
srcmac, dstmac);
if (!ndo->ndo_suppress_default_print)
ND_DEFAULTPRINT(p, caplen);
}
return (hdr_len);
}
/*
* This is the top level routine of the printer. 'p' points
* to the TR header of the packet, 'h->ts' is the timestamp,
* 'h->len' is the length of the packet off the wire, and 'h->caplen'
* is the number of bytes actually captured.
*/
void
token_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
{
ndo->ndo_protocol = "token-ring";
ndo->ndo_ll_hdr_len += token_print(ndo, p, h->len, h->caplen);
}
diff --git a/contrib/tcpdump/print-udld.c b/contrib/tcpdump/print-udld.c
index aec1d9e57278..a778c7262f74 100644
--- a/contrib/tcpdump/print-udld.c
+++ b/contrib/tcpdump/print-udld.c
@@ -1,207 +1,205 @@
/*
* Copyright (c) 1998-2007 The TCPDUMP project
*
* 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.
*
* Original code by Carles Kishimoto <carles.kishimoto@gmail.com>
*/
/* \summary: Cisco UniDirectional Link Detection (UDLD) protocol printer */
/* specification: RFC 5171 */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
#define UDLD_HEADER_LEN 4
#define UDLD_TLV_HEADER_LEN 4
#define UDLD_DEVICE_ID_TLV 0x0001
#define UDLD_PORT_ID_TLV 0x0002
#define UDLD_ECHO_TLV 0x0003
#define UDLD_MESSAGE_INTERVAL_TLV 0x0004
#define UDLD_TIMEOUT_INTERVAL_TLV 0x0005
#define UDLD_DEVICE_NAME_TLV 0x0006
#define UDLD_SEQ_NUMBER_TLV 0x0007
static const struct tok udld_tlv_values[] = {
{ UDLD_DEVICE_ID_TLV, "Device-ID TLV"},
{ UDLD_PORT_ID_TLV, "Port-ID TLV"},
{ UDLD_ECHO_TLV, "Echo TLV"},
{ UDLD_MESSAGE_INTERVAL_TLV, "Message Interval TLV"},
{ UDLD_TIMEOUT_INTERVAL_TLV, "Timeout Interval TLV"},
{ UDLD_DEVICE_NAME_TLV, "Device Name TLV"},
{ UDLD_SEQ_NUMBER_TLV,"Sequence Number TLV"},
{ 0, NULL}
};
static const struct tok udld_code_values[] = {
{ 0x00, "Reserved"},
{ 0x01, "Probe message"},
{ 0x02, "Echo message"},
{ 0x03, "Flush message"},
{ 0, NULL}
};
static const struct tok udld_flags_bitmap_str[] = {
{ 1U << 0, "RT" },
{ 1U << 1, "RSY" },
{ 1U << 2, "MBZ-2" },
{ 1U << 3, "MBZ-3" },
{ 1U << 4, "MBZ-4" },
{ 1U << 5, "MBZ-5" },
{ 1U << 6, "MBZ-6" },
{ 1U << 7, "MBZ-7" },
{ 0, NULL}
};
/*
* UDLD's Protocol Data Unit format:
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Ver | Opcode | Flags | Checksum |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | List of TLVs (variable length list) |
* | ... |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* TLV format:
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | TYPE | LENGTH |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | VALUE |
* | ... |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* LENGTH: Length in bytes of the Type, Length, and Value fields.
*/
#define UDLD_EXTRACT_VERSION(x) (((x)&0xe0)>>5)
#define UDLD_EXTRACT_OPCODE(x) ((x)&0x1f)
void
udld_print(netdissect_options *ndo,
const u_char *tptr, u_int length)
{
uint8_t ver, code, flags;
ndo->ndo_protocol = "udld";
if (length < UDLD_HEADER_LEN)
goto invalid;
ver = UDLD_EXTRACT_VERSION(GET_U_1(tptr));
code = UDLD_EXTRACT_OPCODE(GET_U_1(tptr));
tptr += 1;
length -= 1;
flags = GET_U_1(tptr);
tptr += 1;
length -= 1;
ND_PRINT("UDLDv%u, Code %s (%x), Flags [%s] (0x%02x), length %u",
ver,
tok2str(udld_code_values, "Reserved", code),
code,
bittok2str(udld_flags_bitmap_str, "none", flags),
flags,
length + 2);
/*
* In non-verbose mode, just print version and opcode type
*/
if (ndo->ndo_vflag < 1) {
goto tcheck_remainder;
}
ND_PRINT("\n\tChecksum 0x%04x (unverified)", GET_BE_U_2(tptr));
tptr += 2;
length -= 2;
while (length) {
uint16_t type, len;
if (length < UDLD_TLV_HEADER_LEN)
goto invalid;
type = GET_BE_U_2(tptr);
tptr += 2;
length -= 2;
len = GET_BE_U_2(tptr);
tptr += 2;
length -= 2;
ND_PRINT("\n\t%s (0x%04x) TLV, length %u",
tok2str(udld_tlv_values, "Unknown", type),
type, len);
/* infinite loop check */
if (len <= UDLD_TLV_HEADER_LEN)
goto invalid;
len -= UDLD_TLV_HEADER_LEN;
if (length < len)
goto invalid;
switch (type) {
case UDLD_DEVICE_ID_TLV:
case UDLD_PORT_ID_TLV:
case UDLD_DEVICE_NAME_TLV:
ND_PRINT(", ");
nd_printjnp(ndo, tptr, len);
break;
case UDLD_ECHO_TLV:
ND_PRINT(", ");
(void)nd_printn(ndo, tptr, len, NULL);
break;
case UDLD_MESSAGE_INTERVAL_TLV:
case UDLD_TIMEOUT_INTERVAL_TLV:
if (len != 1)
goto invalid;
ND_PRINT(", %us", (GET_U_1(tptr)));
break;
case UDLD_SEQ_NUMBER_TLV:
if (len != 4)
goto invalid;
ND_PRINT(", %u", GET_BE_U_4(tptr));
break;
default:
ND_TCHECK_LEN(tptr, len);
break;
}
tptr += len;
length -= len;
}
return;
invalid:
nd_print_invalid(ndo);
tcheck_remainder:
ND_TCHECK_LEN(tptr, length);
}
diff --git a/contrib/tcpdump/print-udp.c b/contrib/tcpdump/print-udp.c
index 769cbe417256..26371f040119 100644
--- a/contrib/tcpdump/print-udp.c
+++ b/contrib/tcpdump/print-udp.c
@@ -1,743 +1,742 @@
/*
* Copyright (c) 1988, 1989, 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.
*/
/* \summary: UDP printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#include "appletalk.h"
#include "udp.h"
#include "ip.h"
#include "ip6.h"
#include "ipproto.h"
#include "rpc_auth.h"
#include "rpc_msg.h"
#include "nfs.h"
struct rtcphdr {
nd_uint16_t rh_flags; /* T:2 P:1 CNT:5 PT:8 */
nd_uint16_t rh_len; /* length of message (in words) */
nd_uint32_t rh_ssrc; /* synchronization src id */
};
typedef struct {
nd_uint32_t upper; /* more significant 32 bits */
nd_uint32_t lower; /* less significant 32 bits */
} ntp64;
/*
* Sender report.
*/
struct rtcp_sr {
ntp64 sr_ntp; /* 64-bit ntp timestamp */
nd_uint32_t sr_ts; /* reference media timestamp */
nd_uint32_t sr_np; /* no. packets sent */
nd_uint32_t sr_nb; /* no. bytes sent */
};
/*
* Receiver report.
* Time stamps are middle 32-bits of ntp timestamp.
*/
struct rtcp_rr {
nd_uint32_t rr_srcid; /* sender being reported */
nd_uint32_t rr_nl; /* no. packets lost */
nd_uint32_t rr_ls; /* extended last seq number received */
nd_uint32_t rr_dv; /* jitter (delay variance) */
nd_uint32_t rr_lsr; /* orig. ts from last rr from this src */
nd_uint32_t rr_dlsr; /* time from recpt of last rr to xmit time */
};
/*XXX*/
#define RTCP_PT_SR 200
#define RTCP_PT_RR 201
#define RTCP_PT_SDES 202
#define RTCP_SDES_CNAME 1
#define RTCP_SDES_NAME 2
#define RTCP_SDES_EMAIL 3
#define RTCP_SDES_PHONE 4
#define RTCP_SDES_LOC 5
#define RTCP_SDES_TOOL 6
#define RTCP_SDES_NOTE 7
#define RTCP_SDES_PRIV 8
#define RTCP_PT_BYE 203
#define RTCP_PT_APP 204
static void
vat_print(netdissect_options *ndo, const u_char *hdr, u_int length)
{
/* vat/vt audio */
u_int ts;
ndo->ndo_protocol = "vat";
if (length < 2) {
ND_PRINT("udp/va/vat, length %u < 2", length);
return;
}
ts = GET_BE_U_2(hdr);
if ((ts & 0xf060) != 0) {
/* probably vt */
ND_PRINT("udp/vt %u %u / %u",
length,
ts & 0x3ff, ts >> 10);
} else {
/* probably vat */
uint32_t i0, i1;
if (length < 8) {
ND_PRINT("udp/vat, length %u < 8", length);
return;
}
i0 = GET_BE_U_4(&((const u_int *)hdr)[0]);
i1 = GET_BE_U_4(&((const u_int *)hdr)[1]);
ND_PRINT("udp/vat %u c%u %u%s",
length - 8,
i0 & 0xffff,
i1, i0 & 0x800000? "*" : "");
/* audio format */
if (i0 & 0x1f0000)
ND_PRINT(" f%u", (i0 >> 16) & 0x1f);
if (i0 & 0x3f000000)
ND_PRINT(" s%u", (i0 >> 24) & 0x3f);
}
}
static void
rtp_print(netdissect_options *ndo, const u_char *hdr, u_int len)
{
/* rtp v1 or v2 */
const u_int *ip = (const u_int *)hdr;
u_int hasopt, hasext, contype, hasmarker, dlen;
uint32_t i0, i1;
const char * ptype;
ndo->ndo_protocol = "rtp";
if (len < 8) {
ND_PRINT("udp/rtp, length %u < 8", len);
return;
}
i0 = GET_BE_U_4(&((const u_int *)hdr)[0]);
i1 = GET_BE_U_4(&((const u_int *)hdr)[1]);
dlen = len - 8;
ip += 2;
len >>= 2;
len -= 2;
hasopt = 0;
hasext = 0;
if ((i0 >> 30) == 1) {
/* rtp v1 - draft-ietf-avt-rtp-04 */
hasopt = i0 & 0x800000;
contype = (i0 >> 16) & 0x3f;
hasmarker = i0 & 0x400000;
ptype = "rtpv1";
} else {
/* rtp v2 - RFC 3550 */
if (dlen < 4) {
ND_PRINT("udp/rtp, length %u < 12", dlen + 8);
return;
}
hasext = i0 & 0x10000000;
contype = (i0 >> 16) & 0x7f;
hasmarker = i0 & 0x800000;
dlen -= 4;
ptype = "rtp";
ip += 1;
len -= 1;
}
ND_PRINT("udp/%s %u c%u %s%s %u %u",
ptype,
dlen,
contype,
(hasopt || hasext)? "+" : "",
hasmarker? "*" : "",
i0 & 0xffff,
i1);
if (ndo->ndo_vflag) {
ND_PRINT(" %u", GET_BE_U_4(&((const u_int *)hdr)[2]));
if (hasopt) {
u_int i2, optlen;
do {
i2 = GET_BE_U_4(ip);
optlen = (i2 >> 16) & 0xff;
if (optlen == 0 || optlen > len) {
ND_PRINT(" !opt");
return;
}
ip += optlen;
len -= optlen;
} while ((int)i2 >= 0);
}
if (hasext) {
u_int i2, extlen;
i2 = GET_BE_U_4(ip);
extlen = (i2 & 0xffff) + 1;
if (extlen > len) {
ND_PRINT(" !ext");
return;
}
ip += extlen;
}
if (contype == 0x1f) /*XXX H.261 */
ND_PRINT(" 0x%04x", GET_BE_U_4(ip) >> 16);
}
}
static const u_char *
rtcp_print(netdissect_options *ndo, const u_char *hdr, const u_char *ep)
{
/* rtp v2 control (rtcp) */
const struct rtcp_rr *rr = 0;
const struct rtcp_sr *sr;
const struct rtcphdr *rh = (const struct rtcphdr *)hdr;
u_int len;
uint16_t flags;
u_int cnt;
double ts, dts;
ndo->ndo_protocol = "rtcp";
if ((const u_char *)(rh + 1) > ep)
goto trunc;
ND_TCHECK_SIZE(rh);
len = (GET_BE_U_2(rh->rh_len) + 1) * 4;
flags = GET_BE_U_2(rh->rh_flags);
cnt = (flags >> 8) & 0x1f;
switch (flags & 0xff) {
case RTCP_PT_SR:
sr = (const struct rtcp_sr *)(rh + 1);
ND_PRINT(" sr");
if (len != cnt * sizeof(*rr) + sizeof(*sr) + sizeof(*rh))
ND_PRINT(" [%u]", len);
if (ndo->ndo_vflag)
ND_PRINT(" %u", GET_BE_U_4(rh->rh_ssrc));
if ((const u_char *)(sr + 1) > ep)
goto trunc;
ND_TCHECK_SIZE(sr);
ts = (double)(GET_BE_U_4(sr->sr_ntp.upper)) +
((double)(GET_BE_U_4(sr->sr_ntp.lower)) /
FMAXINT);
ND_PRINT(" @%.2f %u %up %ub", ts, GET_BE_U_4(sr->sr_ts),
GET_BE_U_4(sr->sr_np), GET_BE_U_4(sr->sr_nb));
rr = (const struct rtcp_rr *)(sr + 1);
break;
case RTCP_PT_RR:
ND_PRINT(" rr");
if (len != cnt * sizeof(*rr) + sizeof(*rh))
ND_PRINT(" [%u]", len);
rr = (const struct rtcp_rr *)(rh + 1);
if (ndo->ndo_vflag)
ND_PRINT(" %u", GET_BE_U_4(rh->rh_ssrc));
break;
case RTCP_PT_SDES:
ND_PRINT(" sdes %u", len);
if (ndo->ndo_vflag)
ND_PRINT(" %u", GET_BE_U_4(rh->rh_ssrc));
cnt = 0;
break;
case RTCP_PT_BYE:
ND_PRINT(" bye %u", len);
if (ndo->ndo_vflag)
ND_PRINT(" %u", GET_BE_U_4(rh->rh_ssrc));
cnt = 0;
break;
default:
ND_PRINT(" type-0x%x %u", flags & 0xff, len);
cnt = 0;
break;
}
if (cnt > 1)
ND_PRINT(" c%u", cnt);
while (cnt != 0) {
if ((const u_char *)(rr + 1) > ep)
goto trunc;
ND_TCHECK_SIZE(rr);
if (ndo->ndo_vflag)
ND_PRINT(" %u", GET_BE_U_4(rr->rr_srcid));
ts = (double)(GET_BE_U_4(rr->rr_lsr)) / 65536.;
dts = (double)(GET_BE_U_4(rr->rr_dlsr)) / 65536.;
ND_PRINT(" %ul %us %uj @%.2f+%.2f",
GET_BE_U_4(rr->rr_nl) & 0x00ffffff,
GET_BE_U_4(rr->rr_ls),
GET_BE_U_4(rr->rr_dv), ts, dts);
cnt--;
}
return (hdr + len);
trunc:
nd_print_trunc(ndo);
return ep;
}
static uint16_t udp_cksum(netdissect_options *ndo, const struct ip *ip,
const struct udphdr *up,
u_int len)
{
return nextproto4_cksum(ndo, ip, (const uint8_t *)(const void *)up, len, len,
IPPROTO_UDP);
}
static uint16_t udp6_cksum(netdissect_options *ndo, const struct ip6_hdr *ip6,
const struct udphdr *up, u_int len)
{
return nextproto6_cksum(ndo, ip6, (const uint8_t *)(const void *)up, len, len,
IPPROTO_UDP);
}
static void
udpipaddr_print(netdissect_options *ndo, const struct ip *ip, int sport, int dport)
{
const struct ip6_hdr *ip6;
if (IP_V(ip) == 6)
ip6 = (const struct ip6_hdr *)ip;
else
ip6 = NULL;
if (ip6) {
if (GET_U_1(ip6->ip6_nxt) == IPPROTO_UDP) {
if (sport == -1) {
ND_PRINT("%s > %s: ",
GET_IP6ADDR_STRING(ip6->ip6_src),
GET_IP6ADDR_STRING(ip6->ip6_dst));
} else {
ND_PRINT("%s.%s > %s.%s: ",
GET_IP6ADDR_STRING(ip6->ip6_src),
udpport_string(ndo, (uint16_t)sport),
GET_IP6ADDR_STRING(ip6->ip6_dst),
udpport_string(ndo, (uint16_t)dport));
}
} else {
if (sport != -1) {
ND_PRINT("%s > %s: ",
udpport_string(ndo, (uint16_t)sport),
udpport_string(ndo, (uint16_t)dport));
}
}
} else {
if (GET_U_1(ip->ip_p) == IPPROTO_UDP) {
if (sport == -1) {
ND_PRINT("%s > %s: ",
GET_IPADDR_STRING(ip->ip_src),
GET_IPADDR_STRING(ip->ip_dst));
} else {
ND_PRINT("%s.%s > %s.%s: ",
GET_IPADDR_STRING(ip->ip_src),
udpport_string(ndo, (uint16_t)sport),
GET_IPADDR_STRING(ip->ip_dst),
udpport_string(ndo, (uint16_t)dport));
}
} else {
if (sport != -1) {
ND_PRINT("%s > %s: ",
udpport_string(ndo, (uint16_t)sport),
udpport_string(ndo, (uint16_t)dport));
}
}
}
}
void
udp_print(netdissect_options *ndo, const u_char *bp, u_int length,
const u_char *bp2, int fragmented, u_int ttl_hl)
{
const struct udphdr *up;
const struct ip *ip;
const u_char *cp;
const u_char *ep = ndo->ndo_snapend;
uint16_t sport, dport;
u_int ulen;
const struct ip6_hdr *ip6;
ndo->ndo_protocol = "udp";
up = (const struct udphdr *)bp;
ip = (const struct ip *)bp2;
if (IP_V(ip) == 6)
ip6 = (const struct ip6_hdr *)bp2;
else
ip6 = NULL;
if (!ND_TTEST_2(up->uh_dport)) {
udpipaddr_print(ndo, ip, -1, -1);
goto trunc;
}
sport = GET_BE_U_2(up->uh_sport);
dport = GET_BE_U_2(up->uh_dport);
if (length < sizeof(struct udphdr)) {
udpipaddr_print(ndo, ip, sport, dport);
ND_PRINT("truncated-udp %u", length);
return;
}
if (!ND_TTEST_2(up->uh_ulen)) {
udpipaddr_print(ndo, ip, sport, dport);
goto trunc;
}
ulen = GET_BE_U_2(up->uh_ulen);
/*
* IPv6 Jumbo Datagrams; see RFC 2675.
* If the length is zero, and the length provided to us is
* > 65535, use the provided length as the length.
*/
if (ulen == 0 && length > 65535)
ulen = length;
if (ulen < sizeof(struct udphdr)) {
udpipaddr_print(ndo, ip, sport, dport);
ND_PRINT("truncated-udplength %u", ulen);
return;
}
ulen -= sizeof(struct udphdr);
length -= sizeof(struct udphdr);
if (ulen < length)
length = ulen;
cp = (const u_char *)(up + 1);
if (cp > ndo->ndo_snapend) {
udpipaddr_print(ndo, ip, sport, dport);
goto trunc;
}
if (ndo->ndo_packettype) {
const struct sunrpc_msg *rp;
enum sunrpc_msg_type direction;
switch (ndo->ndo_packettype) {
case PT_VAT:
udpipaddr_print(ndo, ip, sport, dport);
vat_print(ndo, cp, length);
break;
case PT_WB:
udpipaddr_print(ndo, ip, sport, dport);
wb_print(ndo, cp, length);
break;
case PT_RPC:
rp = (const struct sunrpc_msg *)cp;
direction = (enum sunrpc_msg_type) GET_BE_U_4(rp->rm_direction);
if (direction == SUNRPC_CALL)
sunrpc_print(ndo, (const u_char *)rp, length,
(const u_char *)ip);
else
nfsreply_print(ndo, (const u_char *)rp, length,
(const u_char *)ip); /*XXX*/
break;
case PT_RTP:
udpipaddr_print(ndo, ip, sport, dport);
rtp_print(ndo, cp, length);
break;
case PT_RTCP:
udpipaddr_print(ndo, ip, sport, dport);
while (cp < ep)
cp = rtcp_print(ndo, cp, ep);
break;
case PT_SNMP:
udpipaddr_print(ndo, ip, sport, dport);
snmp_print(ndo, cp, length);
break;
case PT_CNFP:
udpipaddr_print(ndo, ip, sport, dport);
cnfp_print(ndo, cp);
break;
case PT_TFTP:
udpipaddr_print(ndo, ip, sport, dport);
tftp_print(ndo, cp, length);
break;
case PT_AODV:
udpipaddr_print(ndo, ip, sport, dport);
- aodv_print(ndo, cp, length,
- ip6 != NULL);
+ aodv_print(ndo, cp, length, IP_V(ip) == 6);
break;
case PT_RADIUS:
udpipaddr_print(ndo, ip, sport, dport);
radius_print(ndo, cp, length);
break;
case PT_VXLAN:
udpipaddr_print(ndo, ip, sport, dport);
vxlan_print(ndo, cp, length);
break;
case PT_PGM:
case PT_PGM_ZMTP1:
udpipaddr_print(ndo, ip, sport, dport);
pgm_print(ndo, cp, length, bp2);
break;
case PT_LMP:
udpipaddr_print(ndo, ip, sport, dport);
lmp_print(ndo, cp, length);
break;
case PT_PTP:
udpipaddr_print(ndo, ip, sport, dport);
ptp_print(ndo, cp, length);
break;
case PT_SOMEIP:
udpipaddr_print(ndo, ip, sport, dport);
someip_print(ndo, cp, length);
break;
case PT_DOMAIN:
udpipaddr_print(ndo, ip, sport, dport);
/* over_tcp: FALSE, is_mdns: FALSE */
domain_print(ndo, cp, length, FALSE, FALSE);
break;
}
return;
}
udpipaddr_print(ndo, ip, sport, dport);
if (!ndo->ndo_qflag) {
const struct sunrpc_msg *rp;
enum sunrpc_msg_type direction;
rp = (const struct sunrpc_msg *)cp;
if (ND_TTEST_4(rp->rm_direction)) {
direction = (enum sunrpc_msg_type) GET_BE_U_4(rp->rm_direction);
if (dport == NFS_PORT && direction == SUNRPC_CALL) {
ND_PRINT("NFS request xid %u ",
GET_BE_U_4(rp->rm_xid));
nfsreq_noaddr_print(ndo, (const u_char *)rp, length,
(const u_char *)ip);
return;
}
if (sport == NFS_PORT && direction == SUNRPC_REPLY) {
ND_PRINT("NFS reply xid %u ",
GET_BE_U_4(rp->rm_xid));
nfsreply_noaddr_print(ndo, (const u_char *)rp, length,
(const u_char *)ip);
return;
}
#ifdef notdef
if (dport == SUNRPC_PORT && direction == SUNRPC_CALL) {
sunrpc_print((const u_char *)rp, length, (const u_char *)ip);
return;
}
#endif
}
}
if (ndo->ndo_vflag && !ndo->ndo_Kflag && !fragmented) {
/* Check the checksum, if possible. */
uint16_t sum, udp_sum;
/*
* XXX - do this even if vflag == 1?
* TCP does, and we do so for UDP-over-IPv6.
*/
if (IP_V(ip) == 4 && (ndo->ndo_vflag > 1)) {
udp_sum = GET_BE_U_2(up->uh_sum);
if (udp_sum == 0) {
ND_PRINT("[no cksum] ");
} else if (ND_TTEST_LEN(cp, length)) {
sum = udp_cksum(ndo, ip, up, length + sizeof(struct udphdr));
if (sum != 0) {
ND_PRINT("[bad udp cksum 0x%04x -> 0x%04x!] ",
udp_sum,
in_cksum_shouldbe(udp_sum, sum));
} else
ND_PRINT("[udp sum ok] ");
}
- }
- else if (IP_V(ip) == 6) {
+ } else if (IP_V(ip) == 6) {
/* for IPv6, UDP checksum is mandatory */
if (ND_TTEST_LEN(cp, length)) {
sum = udp6_cksum(ndo, ip6, up, length + sizeof(struct udphdr));
udp_sum = GET_BE_U_2(up->uh_sum);
if (sum != 0) {
ND_PRINT("[bad udp cksum 0x%04x -> 0x%04x!] ",
udp_sum,
in_cksum_shouldbe(udp_sum, sum));
} else
ND_PRINT("[udp sum ok] ");
}
}
}
if (!ndo->ndo_qflag) {
if (IS_SRC_OR_DST_PORT(NAMESERVER_PORT))
/* over_tcp: FALSE, is_mdns: FALSE */
domain_print(ndo, cp, length, FALSE, FALSE);
- else if (IS_SRC_OR_DST_PORT(MULTICASTDNS_PORT))
- /* over_tcp: FALSE, is_mdns: TRUE */
- domain_print(ndo, cp, length, FALSE, TRUE);
- else if (IS_SRC_OR_DST_PORT(TIMED_PORT))
- timed_print(ndo, (const u_char *)cp);
+ else if (IS_SRC_OR_DST_PORT(BOOTPC_PORT) ||
+ IS_SRC_OR_DST_PORT(BOOTPS_PORT))
+ bootp_print(ndo, cp, length);
else if (IS_SRC_OR_DST_PORT(TFTP_PORT))
tftp_print(ndo, cp, length);
- else if (IS_SRC_OR_DST_PORT(BOOTPC_PORT) || IS_SRC_OR_DST_PORT(BOOTPS_PORT))
- bootp_print(ndo, cp, length);
+ else if (IS_SRC_OR_DST_PORT(KERBEROS_PORT))
+ krb_print(ndo, (const u_char *)cp);
+ else if (IS_SRC_OR_DST_PORT(NTP_PORT))
+ ntp_print(ndo, cp, length);
+#ifdef ENABLE_SMB
+ else if (IS_SRC_OR_DST_PORT(NETBIOS_NS_PORT))
+ nbt_udp137_print(ndo, cp, length);
+ else if (IS_SRC_OR_DST_PORT(NETBIOS_DGRAM_PORT))
+ nbt_udp138_print(ndo, cp, length);
+#endif
+ else if (IS_SRC_OR_DST_PORT(SNMP_PORT) ||
+ IS_SRC_OR_DST_PORT(SNMPTRAP_PORT))
+ snmp_print(ndo, cp, length);
+ else if (IS_SRC_OR_DST_PORT(PTP_EVENT_PORT) ||
+ IS_SRC_OR_DST_PORT(PTP_GENERAL_PORT))
+ ptp_print(ndo, cp, length);
+ else if (IS_SRC_OR_DST_PORT(CISCO_AUTORP_PORT))
+ cisco_autorp_print(ndo, cp, length);
+ else if (IS_SRC_OR_DST_PORT(ISAKMP_PORT))
+ isakmp_print(ndo, cp, length, bp2);
+ else if (IS_SRC_OR_DST_PORT(SYSLOG_PORT))
+ syslog_print(ndo, cp, length);
else if (IS_SRC_OR_DST_PORT(RIP_PORT))
rip_print(ndo, cp, length);
+ else if (IS_SRC_OR_DST_PORT(RIPNG_PORT))
+ ripng_print(ndo, cp, length);
+ else if (IS_SRC_OR_DST_PORT(TIMED_PORT))
+ timed_print(ndo, (const u_char *)cp);
+ else if (IS_SRC_OR_DST_PORT(DHCP6_SERV_PORT) ||
+ IS_SRC_OR_DST_PORT(DHCP6_CLI_PORT))
+ dhcp6_print(ndo, cp, length);
+ else if (IS_SRC_OR_DST_PORT(LDP_PORT))
+ ldp_print(ndo, cp, length);
else if (IS_SRC_OR_DST_PORT(AODV_PORT))
- aodv_print(ndo, cp, length,
- ip6 != NULL);
- else if (IS_SRC_OR_DST_PORT(ISAKMP_PORT))
- isakmp_print(ndo, cp, length, bp2);
+ aodv_print(ndo, cp, length, IP_V(ip) == 6);
+ else if (IS_SRC_OR_DST_PORT(OLSR_PORT))
+ olsr_print(ndo, cp, length, IP_V(ip) == 6);
+ else if (IS_SRC_OR_DST_PORT(LMP_PORT))
+ lmp_print(ndo, cp, length);
+ else if (IS_SRC_OR_DST_PORT(KERBEROS_SEC_PORT))
+ krb_print(ndo, (const u_char *)cp);
+ else if (IS_SRC_OR_DST_PORT(LWRES_PORT))
+ lwres_print(ndo, cp, length);
+ else if (IS_SRC_OR_DST_PORT(MULTICASTDNS_PORT))
+ /* over_tcp: FALSE, is_mdns: TRUE */
+ domain_print(ndo, cp, length, FALSE, TRUE);
else if (IS_SRC_OR_DST_PORT(ISAKMP_PORT_NATT))
isakmp_rfc3948_print(ndo, cp, length, bp2, IP_V(ip), fragmented, ttl_hl);
else if (IS_SRC_OR_DST_PORT(ISAKMP_PORT_USER1) || IS_SRC_OR_DST_PORT(ISAKMP_PORT_USER2))
isakmp_print(ndo, cp, length, bp2);
- else if (IS_SRC_OR_DST_PORT(SNMP_PORT) || IS_SRC_OR_DST_PORT(SNMPTRAP_PORT))
- snmp_print(ndo, cp, length);
- else if (IS_SRC_OR_DST_PORT(NTP_PORT))
- ntp_print(ndo, cp, length);
- else if (IS_SRC_OR_DST_PORT(KERBEROS_PORT) || IS_SRC_OR_DST_PORT(KERBEROS_SEC_PORT))
- krb_print(ndo, (const u_char *)cp);
else if (IS_SRC_OR_DST_PORT(L2TP_PORT))
l2tp_print(ndo, cp, length);
-#ifdef ENABLE_SMB
- else if (IS_SRC_OR_DST_PORT(NETBIOS_NS_PORT))
- nbt_udp137_print(ndo, cp, length);
- else if (IS_SRC_OR_DST_PORT(NETBIOS_DGRAM_PORT))
- nbt_udp138_print(ndo, cp, length);
-#endif
else if (dport == VAT_PORT)
vat_print(ndo, cp, length);
else if (IS_SRC_OR_DST_PORT(ZEPHYR_SRV_PORT) || IS_SRC_OR_DST_PORT(ZEPHYR_CLT_PORT))
zephyr_print(ndo, cp, length);
/*
* Since there are 10 possible ports to check, I think
* a <> test would be more efficient
*/
else if ((sport >= RX_PORT_LOW && sport <= RX_PORT_HIGH) ||
(dport >= RX_PORT_LOW && dport <= RX_PORT_HIGH))
rx_print(ndo, cp, length, sport, dport,
(const u_char *) ip);
- else if (IS_SRC_OR_DST_PORT(RIPNG_PORT))
- ripng_print(ndo, cp, length);
- else if (IS_SRC_OR_DST_PORT(DHCP6_SERV_PORT) || IS_SRC_OR_DST_PORT(DHCP6_CLI_PORT))
- dhcp6_print(ndo, cp, length);
else if (IS_SRC_OR_DST_PORT(AHCP_PORT))
ahcp_print(ndo, cp, length);
else if (IS_SRC_OR_DST_PORT(BABEL_PORT) || IS_SRC_OR_DST_PORT(BABEL_PORT_OLD))
babel_print(ndo, cp, length);
else if (IS_SRC_OR_DST_PORT(HNCP_PORT))
hncp_print(ndo, cp, length);
/*
* Kludge in test for whiteboard packets.
*/
else if (dport == WB_PORT)
wb_print(ndo, cp, length);
- else if (IS_SRC_OR_DST_PORT(CISCO_AUTORP_PORT))
- cisco_autorp_print(ndo, cp, length);
else if (IS_SRC_OR_DST_PORT(RADIUS_PORT) ||
IS_SRC_OR_DST_PORT(RADIUS_NEW_PORT) ||
IS_SRC_OR_DST_PORT(RADIUS_ACCOUNTING_PORT) ||
IS_SRC_OR_DST_PORT(RADIUS_NEW_ACCOUNTING_PORT) ||
IS_SRC_OR_DST_PORT(RADIUS_CISCO_COA_PORT) ||
IS_SRC_OR_DST_PORT(RADIUS_COA_PORT) )
radius_print(ndo, cp, length);
else if (dport == HSRP_PORT)
hsrp_print(ndo, cp, length);
- else if (IS_SRC_OR_DST_PORT(LWRES_PORT))
- lwres_print(ndo, cp, length);
- else if (IS_SRC_OR_DST_PORT(LDP_PORT))
- ldp_print(ndo, cp, length);
- else if (IS_SRC_OR_DST_PORT(OLSR_PORT))
- olsr_print(ndo, cp, length,
- (IP_V(ip) == 6) ? 1 : 0);
else if (IS_SRC_OR_DST_PORT(MPLS_LSP_PING_PORT))
lspping_print(ndo, cp, length);
- else if (sport == BCM_LI_PORT)
- bcm_li_print(ndo, cp, length);
else if (dport == BFD_CONTROL_PORT ||
dport == BFD_MULTIHOP_PORT ||
dport == BFD_LAG_PORT ||
dport == BFD_ECHO_PORT )
bfd_print(ndo, cp, length, dport);
- else if (IS_SRC_OR_DST_PORT(LMP_PORT))
- lmp_print(ndo, cp, length);
else if (IS_SRC_OR_DST_PORT(VQP_PORT))
vqp_print(ndo, cp, length);
else if (IS_SRC_OR_DST_PORT(SFLOW_PORT))
sflow_print(ndo, cp, length);
else if (dport == LWAPP_CONTROL_PORT)
lwapp_control_print(ndo, cp, length, 1);
else if (sport == LWAPP_CONTROL_PORT)
lwapp_control_print(ndo, cp, length, 0);
else if (IS_SRC_OR_DST_PORT(LWAPP_DATA_PORT))
lwapp_data_print(ndo, cp, length);
else if (IS_SRC_OR_DST_PORT(SIP_PORT))
sip_print(ndo, cp, length);
- else if (IS_SRC_OR_DST_PORT(SYSLOG_PORT))
- syslog_print(ndo, cp, length);
else if (IS_SRC_OR_DST_PORT(OTV_PORT))
otv_print(ndo, cp, length);
else if (IS_SRC_OR_DST_PORT(VXLAN_PORT))
vxlan_print(ndo, cp, length);
else if (dport == GENEVE_PORT)
geneve_print(ndo, cp, length);
else if (IS_SRC_OR_DST_PORT(LISP_CONTROL_PORT))
lisp_print(ndo, cp, length);
else if (IS_SRC_OR_DST_PORT(VXLAN_GPE_PORT))
vxlan_gpe_print(ndo, cp, length);
else if (IS_SRC_OR_DST_PORT(ZEP_PORT))
zep_print(ndo, cp, length);
else if (IS_SRC_OR_DST_PORT(MPLS_PORT))
mpls_print(ndo, cp, length);
else if (ND_TTEST_1(((const struct LAP *)cp)->type) &&
GET_U_1(((const struct LAP *)cp)->type) == lapDDP &&
(atalk_port(sport) || atalk_port(dport))) {
if (ndo->ndo_vflag)
ND_PRINT("kip ");
llap_print(ndo, cp, length);
- } else if (IS_SRC_OR_DST_PORT(PTP_EVENT_PORT) ||
- IS_SRC_OR_DST_PORT(PTP_GENERAL_PORT)) {
- ptp_print(ndo, cp, length);
} else if (IS_SRC_OR_DST_PORT(SOMEIP_PORT))
someip_print(ndo, cp, length);
+ else if (sport == BCM_LI_PORT)
+ bcm_li_print(ndo, cp, length);
else {
if (ulen > length && !fragmented)
ND_PRINT("UDP, bad length %u > %u",
ulen, length);
else
ND_PRINT("UDP, length %u", ulen);
}
} else {
if (ulen > length && !fragmented)
ND_PRINT("UDP, bad length %u > %u",
ulen, length);
else
ND_PRINT("UDP, length %u", ulen);
}
return;
trunc:
nd_print_trunc(ndo);
}
diff --git a/contrib/tcpdump/print-unsupported.c b/contrib/tcpdump/print-unsupported.c
index 009cf6f9b9ce..2dbab773720d 100644
--- a/contrib/tcpdump/print-unsupported.c
+++ b/contrib/tcpdump/print-unsupported.c
@@ -1,34 +1,32 @@
/*
* Copyright (c) 2020 The TCPDUMP project
* 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, 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.
*/
/* \summary: unsupported link-layer protocols printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
void
unsupported_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h,
const u_char *p)
{
ndo->ndo_protocol = "unsupported";
nd_print_protocol_caps(ndo);
hex_and_ascii_print(ndo, "\n\t", p, h->caplen);
}
diff --git a/contrib/tcpdump/print-usb.c b/contrib/tcpdump/print-usb.c
index 3f5937ba16ca..98bd91b20fb3 100644
--- a/contrib/tcpdump/print-usb.c
+++ b/contrib/tcpdump/print-usb.c
@@ -1,284 +1,278 @@
/*
* Copyright 2009 Bert Vermeulen <bert@biot.com>
*
* 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 Paolo Abeni.''
* The name of author may not 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 USB packets
*
*/
/* \summary: USB printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
#ifdef DLT_USB_LINUX
/*
* possible transfer mode
*/
#define URB_TRANSFER_IN 0x80
#define URB_ISOCHRONOUS 0x0
#define URB_INTERRUPT 0x1
#define URB_CONTROL 0x2
#define URB_BULK 0x3
/*
* possible event type
*/
#define URB_SUBMIT 'S'
#define URB_COMPLETE 'C'
#define URB_ERROR 'E'
/*
* USB setup header as defined in USB specification.
* Appears at the front of each Control S-type packet in DLT_USB captures.
*/
typedef struct _usb_setup {
nd_uint8_t bmRequestType;
nd_uint8_t bRequest;
nd_uint16_t wValue;
nd_uint16_t wIndex;
nd_uint16_t wLength;
} pcap_usb_setup;
/*
* Information from the URB for Isochronous transfers.
*/
typedef struct _iso_rec {
nd_int32_t error_count;
nd_int32_t numdesc;
} iso_rec;
/*
* Header prepended by linux kernel to each event.
* Appears at the front of each packet in DLT_USB_LINUX captures.
*/
typedef struct _usb_header {
nd_uint64_t id;
nd_uint8_t event_type;
nd_uint8_t transfer_type;
nd_uint8_t endpoint_number;
nd_uint8_t device_address;
nd_uint16_t bus_id;
nd_uint8_t setup_flag;/*if !=0 the urb setup header is not present*/
nd_uint8_t data_flag; /*if !=0 no urb data is present*/
nd_int64_t ts_sec;
nd_int32_t ts_usec;
nd_int32_t status;
nd_uint32_t urb_len;
nd_uint32_t data_len; /* amount of urb data really present in this event*/
pcap_usb_setup setup;
} pcap_usb_header;
/*
* Header prepended by linux kernel to each event for the 2.6.31
* and later kernels; for the 2.6.21 through 2.6.30 kernels, the
* "iso_rec" information, and the fields starting with "interval"
* are zeroed-out padding fields.
*
* Appears at the front of each packet in DLT_USB_LINUX_MMAPPED captures.
*/
typedef struct _usb_header_mmapped {
nd_uint64_t id;
nd_uint8_t event_type;
nd_uint8_t transfer_type;
nd_uint8_t endpoint_number;
nd_uint8_t device_address;
nd_uint16_t bus_id;
nd_uint8_t setup_flag;/*if !=0 the urb setup header is not present*/
nd_uint8_t data_flag; /*if !=0 no urb data is present*/
nd_int64_t ts_sec;
nd_int32_t ts_usec;
nd_int32_t status;
nd_uint32_t urb_len;
nd_uint32_t data_len; /* amount of urb data really present in this event*/
union {
pcap_usb_setup setup;
iso_rec iso;
} s;
nd_int32_t interval; /* for Interrupt and Isochronous events */
nd_int32_t start_frame; /* for Isochronous events */
nd_uint32_t xfer_flags; /* copy of URB's transfer flags */
nd_uint32_t ndesc; /* number of isochronous descriptors */
} pcap_usb_header_mmapped;
/*
* Isochronous descriptors; for isochronous transfers there might be
* one or more of these at the beginning of the packet data. The
* number of descriptors is given by the "ndesc" field in the header;
* as indicated, in older kernels that don't put the descriptors at
* the beginning of the packet, that field is zeroed out, so that field
* can be trusted even in captures from older kernels.
*/
typedef struct _usb_isodesc {
nd_int32_t status;
nd_uint32_t offset;
nd_uint32_t len;
nd_byte pad[4];
} usb_isodesc;
/* returns direction: 1=inbound 2=outbound -1=invalid */
static int
get_direction(int transfer_type, int event_type)
{
int direction;
direction = -1;
switch(transfer_type){
case URB_BULK:
case URB_CONTROL:
case URB_ISOCHRONOUS:
- switch(event_type)
- {
+ switch(event_type) {
case URB_SUBMIT:
direction = 2;
break;
case URB_COMPLETE:
case URB_ERROR:
direction = 1;
break;
default:
direction = -1;
}
break;
case URB_INTERRUPT:
- switch(event_type)
- {
+ switch(event_type) {
case URB_SUBMIT:
direction = 1;
break;
case URB_COMPLETE:
case URB_ERROR:
direction = 2;
break;
default:
direction = -1;
}
break;
default:
direction = -1;
}
return direction;
}
static void
usb_header_print(netdissect_options *ndo, const pcap_usb_header *uh)
{
int direction;
uint8_t transfer_type, event_type;
ndo->ndo_protocol = "usb";
nd_print_protocol_caps(ndo);
if (ndo->ndo_qflag)
return;
ND_PRINT(" ");
transfer_type = GET_U_1(uh->transfer_type);
- switch(transfer_type)
- {
+ switch(transfer_type) {
case URB_ISOCHRONOUS:
ND_PRINT("ISOCHRONOUS");
break;
case URB_INTERRUPT:
ND_PRINT("INTERRUPT");
break;
case URB_CONTROL:
ND_PRINT("CONTROL");
break;
case URB_BULK:
ND_PRINT("BULK");
break;
default:
ND_PRINT(" ?");
}
event_type = GET_U_1(uh->event_type);
- switch(event_type)
- {
+ switch(event_type) {
case URB_SUBMIT:
ND_PRINT(" SUBMIT");
break;
case URB_COMPLETE:
ND_PRINT(" COMPLETE");
break;
case URB_ERROR:
ND_PRINT(" ERROR");
break;
default:
ND_PRINT(" ?");
}
direction = get_direction(transfer_type, event_type);
if(direction == 1)
ND_PRINT(" from");
else if(direction == 2)
ND_PRINT(" to");
ND_PRINT(" %u:%u:%u", GET_HE_U_2(uh->bus_id),
GET_U_1(uh->device_address),
GET_U_1(uh->endpoint_number) & 0x7f);
}
/*
* This is the top level routine of the printer for captures with a
* 48-byte header.
*
* 'p' points to the header of the packet, 'h->ts' is the timestamp,
* 'h->len' is the length of the packet off the wire, and 'h->caplen'
* is the number of bytes actually captured.
*/
void
usb_linux_48_byte_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h _U_, const u_char *p)
{
ndo->ndo_protocol = "usb_linux_48_byte";
ND_TCHECK_LEN(p, sizeof(pcap_usb_header));
ndo->ndo_ll_hdr_len += sizeof (pcap_usb_header);
usb_header_print(ndo, (const pcap_usb_header *) p);
}
#ifdef DLT_USB_LINUX_MMAPPED
/*
* This is the top level routine of the printer for captures with a
* 64-byte header.
*
* 'p' points to the header of the packet, 'h->ts' is the timestamp,
* 'h->len' is the length of the packet off the wire, and 'h->caplen'
* is the number of bytes actually captured.
*/
void
usb_linux_64_byte_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h _U_, const u_char *p)
{
ndo->ndo_protocol = "usb_linux_64_byte";
ND_TCHECK_LEN(p, sizeof(pcap_usb_header_mmapped));
ndo->ndo_ll_hdr_len += sizeof (pcap_usb_header_mmapped);
usb_header_print(ndo, (const pcap_usb_header *) p);
}
#endif /* DLT_USB_LINUX_MMAPPED */
#endif /* DLT_USB_LINUX */
diff --git a/contrib/tcpdump/print-vjc.c b/contrib/tcpdump/print-vjc.c
index 830330717ea4..48a36f10ad88 100644
--- a/contrib/tcpdump/print-vjc.c
+++ b/contrib/tcpdump/print-vjc.c
@@ -1,122 +1,120 @@
/*
* 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.
*/
/* \summary: PPP Van Jacobson compression printer */
/* specification: RFC 1144 */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "extract.h"
#include "slcompress.h"
#include "ppp.h"
/*
* XXX - for BSD/OS PPP, what packets get supplied with a PPP header type
* of PPP_VJC and what packets get supplied with a PPP header type of
* PPP_VJNC? PPP_VJNC is for "UNCOMPRESSED_TCP" packets, and PPP_VJC
* is for COMPRESSED_TCP packets (PPP_IP is used for TYPE_IP packets).
*
* RFC 1144 implies that, on the wire, the packet type is *not* needed
* for PPP, as different PPP protocol types can be used; it only needs
* to be put on the wire for SLIP.
*
* It also indicates that, for compressed SLIP:
*
* If the COMPRESSED_TCP bit is set in the first byte, it's
* a COMPRESSED_TCP packet; that byte is the change byte, and
* the COMPRESSED_TCP bit, 0x80, isn't used in the change byte.
*
* If the upper 4 bits of the first byte are 7, it's an
* UNCOMPRESSED_TCP packet; that byte is the first byte of
* the UNCOMPRESSED_TCP modified IP header, with a connection
* number in the protocol field, and with the version field
* being 7, not 4.
*
* Otherwise, the packet is an IPv4 packet (where the upper 4 bits
* of the packet are 4).
*
* So this routine looks as if it's sort-of intended to handle
* compressed SLIP, although it doesn't handle UNCOMPRESSED_TCP
* correctly for that (it doesn't fix the version number and doesn't
* do anything to the protocol field), and doesn't check for COMPRESSED_TCP
* packets correctly for that (you only check the first bit - see
* B.1 in RFC 1144).
*
* But it's called for BSD/OS PPP, not SLIP - perhaps BSD/OS does weird
* things with the headers?
*
* Without a BSD/OS VJC-compressed PPP trace, or knowledge of what the
* BSD/OS VJC code does, we can't say what's the case.
*
* We therefore leave "proto" - which is the PPP protocol type - in place,
* *not* marked as unused, for now, so that GCC warnings about the
* unused argument remind us that we should fix this some day.
*
* XXX - also, it fetches the TCP checksum field in COMPRESSED_TCP
* packets with GET_HE_U_2, rather than with GET_BE_U_2(); RFC 1144 says
* it's "the unmodified TCP checksum", which would imply that it's
* big-endian, but perhaps, on the platform where this was developed,
* the packets were munged by the networking stack before being handed
* to the packet capture mechanism.
*/
int
vjc_print(netdissect_options *ndo, const u_char *bp, u_short proto _U_)
{
int i;
ndo->ndo_protocol = "vjc";
switch (GET_U_1(bp) & 0xf0) {
case TYPE_IP:
if (ndo->ndo_eflag)
ND_PRINT("(vjc type=IP) ");
return PPP_IP;
case TYPE_UNCOMPRESSED_TCP:
if (ndo->ndo_eflag)
ND_PRINT("(vjc type=raw TCP) ");
return PPP_IP;
case TYPE_COMPRESSED_TCP:
if (ndo->ndo_eflag)
ND_PRINT("(vjc type=compressed TCP) ");
for (i = 0; i < 8; i++) {
if (GET_U_1(bp + 1) & (0x80 >> i))
ND_PRINT("%c", "?CI?SAWU"[i]);
}
if (GET_U_1(bp + 1))
ND_PRINT(" ");
ND_PRINT("C=0x%02x ", GET_U_1(bp + 2));
ND_PRINT("sum=0x%04x ", GET_HE_U_2(bp + 3));
return -1;
case TYPE_ERROR:
if (ndo->ndo_eflag)
ND_PRINT("(vjc type=error) ");
return -1;
default:
if (ndo->ndo_eflag)
ND_PRINT("(vjc type=0x%02x) ", GET_U_1(bp) & 0xf0);
return -1;
}
}
diff --git a/contrib/tcpdump/print-vqp.c b/contrib/tcpdump/print-vqp.c
index 1b2f6bfe022b..57b7b3f1d18e 100644
--- a/contrib/tcpdump/print-vqp.c
+++ b/contrib/tcpdump/print-vqp.c
@@ -1,214 +1,212 @@
/*
* Copyright (c) 1998-2006 The TCPDUMP project
*
* 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.
*
* Original code by Carles Kishimoto <Carles.Kishimoto@bsc.es>
*/
/* \summary: Cisco VLAN Query Protocol (VQP) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
#include "addrtoname.h"
#define VQP_VERSION 1
/*
* VQP common header
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Constant | Packet type | Error Code | nitems |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Packet Sequence Number (4 bytes) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct vqp_common_header_t {
nd_uint8_t version;
nd_uint8_t msg_type;
nd_uint8_t error_code;
nd_uint8_t nitems;
nd_uint32_t sequence;
};
struct vqp_obj_tlv_t {
nd_uint32_t obj_type;
nd_uint16_t obj_length;
};
#define VQP_OBJ_REQ_JOIN_PORT 0x01
#define VQP_OBJ_RESP_VLAN 0x02
#define VQP_OBJ_REQ_RECONFIRM 0x03
#define VQP_OBJ_RESP_RECONFIRM 0x04
static const struct tok vqp_msg_type_values[] = {
{ VQP_OBJ_REQ_JOIN_PORT, "Request, Join Port"},
{ VQP_OBJ_RESP_VLAN, "Response, VLAN"},
{ VQP_OBJ_REQ_RECONFIRM, "Request, Reconfirm"},
{ VQP_OBJ_RESP_RECONFIRM, "Response, Reconfirm"},
{ 0, NULL}
};
static const struct tok vqp_error_code_values[] = {
{ 0x00, "No error"},
{ 0x03, "Access denied"},
{ 0x04, "Shutdown port"},
{ 0x05, "Wrong VTP domain"},
{ 0, NULL}
};
/* FIXME the heading 0x0c looks ugly - those must be flags etc. */
#define VQP_OBJ_IP_ADDRESS 0x0c01
#define VQP_OBJ_PORT_NAME 0x0c02
#define VQP_OBJ_VLAN_NAME 0x0c03
#define VQP_OBJ_VTP_DOMAIN 0x0c04
#define VQP_OBJ_ETHERNET_PKT 0x0c05
#define VQP_OBJ_MAC_NULL 0x0c06
#define VQP_OBJ_MAC_ADDRESS 0x0c08
static const struct tok vqp_obj_values[] = {
{ VQP_OBJ_IP_ADDRESS, "Client IP Address" },
{ VQP_OBJ_PORT_NAME, "Port Name" },
{ VQP_OBJ_VLAN_NAME, "VLAN Name" },
{ VQP_OBJ_VTP_DOMAIN, "VTP Domain" },
{ VQP_OBJ_ETHERNET_PKT, "Ethernet Packet" },
{ VQP_OBJ_MAC_NULL, "MAC Null" },
{ VQP_OBJ_MAC_ADDRESS, "MAC Address" },
{ 0, NULL}
};
void
vqp_print(netdissect_options *ndo, const u_char *pptr, u_int len)
{
const struct vqp_common_header_t *vqp_common_header;
const struct vqp_obj_tlv_t *vqp_obj_tlv;
const u_char *tptr;
uint8_t version;
uint16_t vqp_obj_len;
uint32_t vqp_obj_type;
u_int tlen;
uint8_t nitems;
ndo->ndo_protocol = "vqp";
tptr=pptr;
tlen = len;
vqp_common_header = (const struct vqp_common_header_t *)pptr;
ND_TCHECK_SIZE(vqp_common_header);
if (sizeof(struct vqp_common_header_t) > tlen)
goto invalid;
version = GET_U_1(vqp_common_header->version);
/*
* Sanity checking of the header.
*/
if (version != VQP_VERSION) {
ND_PRINT("VQP version %u packet not supported",
version);
return;
}
/* in non-verbose mode just lets print the basic Message Type */
if (ndo->ndo_vflag < 1) {
ND_PRINT("VQPv%u %s Message, error-code %s (%u), length %u",
version,
tok2str(vqp_msg_type_values, "unknown (%u)",GET_U_1(vqp_common_header->msg_type)),
tok2str(vqp_error_code_values, "unknown", GET_U_1(vqp_common_header->error_code)),
GET_U_1(vqp_common_header->error_code),
len);
return;
}
/* ok they seem to want to know everything - lets fully decode it */
nitems = GET_U_1(vqp_common_header->nitems);
ND_PRINT("\n\tVQPv%u, %s Message, error-code %s (%u), seq 0x%08x, items %u, length %u",
version,
tok2str(vqp_msg_type_values, "unknown (%u)",GET_U_1(vqp_common_header->msg_type)),
tok2str(vqp_error_code_values, "unknown", GET_U_1(vqp_common_header->error_code)),
GET_U_1(vqp_common_header->error_code),
GET_BE_U_4(vqp_common_header->sequence),
nitems,
len);
/* skip VQP Common header */
tptr+=sizeof(struct vqp_common_header_t);
tlen-=sizeof(struct vqp_common_header_t);
while (nitems != 0 && tlen != 0) {
vqp_obj_tlv = (const struct vqp_obj_tlv_t *)tptr;
ND_TCHECK_SIZE(vqp_obj_tlv);
if (sizeof(struct vqp_obj_tlv_t) > tlen)
goto invalid;
vqp_obj_type = GET_BE_U_4(vqp_obj_tlv->obj_type);
vqp_obj_len = GET_BE_U_2(vqp_obj_tlv->obj_length);
tptr+=sizeof(struct vqp_obj_tlv_t);
tlen-=sizeof(struct vqp_obj_tlv_t);
ND_PRINT("\n\t %s Object (0x%08x), length %u, value: ",
tok2str(vqp_obj_values, "Unknown", vqp_obj_type),
vqp_obj_type, vqp_obj_len);
/* basic sanity check */
if (vqp_obj_type == 0 || vqp_obj_len ==0) {
return;
}
/* did we capture enough for fully decoding the object ? */
ND_TCHECK_LEN(tptr, vqp_obj_len);
if (vqp_obj_len > tlen)
goto invalid;
switch(vqp_obj_type) {
case VQP_OBJ_IP_ADDRESS:
if (vqp_obj_len != 4)
goto invalid;
ND_PRINT("%s (0x%08x)", GET_IPADDR_STRING(tptr),
GET_BE_U_4(tptr));
break;
/* those objects have similar semantics - fall through */
case VQP_OBJ_PORT_NAME:
case VQP_OBJ_VLAN_NAME:
case VQP_OBJ_VTP_DOMAIN:
case VQP_OBJ_ETHERNET_PKT:
nd_printjnp(ndo, tptr, vqp_obj_len);
break;
/* those objects have similar semantics - fall through */
case VQP_OBJ_MAC_ADDRESS:
case VQP_OBJ_MAC_NULL:
if (vqp_obj_len != MAC_ADDR_LEN)
goto invalid;
ND_PRINT("%s", GET_ETHERADDR_STRING(tptr));
break;
default:
if (ndo->ndo_vflag <= 1)
print_unknown_data(ndo,tptr, "\n\t ", vqp_obj_len);
break;
}
tptr += vqp_obj_len;
tlen -= vqp_obj_len;
nitems--;
}
return;
invalid:
nd_print_invalid(ndo);
}
diff --git a/contrib/tcpdump/print-vrrp.c b/contrib/tcpdump/print-vrrp.c
index 7ac595561b56..bd0bb30dc482 100644
--- a/contrib/tcpdump/print-vrrp.c
+++ b/contrib/tcpdump/print-vrrp.c
@@ -1,190 +1,188 @@
/*
* Copyright (c) 2000 William C. Fenner.
* All rights reserved.
*
* Kevin Steves <ks@hp.se> July 2000
* Modified to:
* - print version, type string and packet length
* - print IP address count if > 1 (-v)
* - verify checksum (-v)
* - print authentication string (-v)
*
* 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.
* The name of William C. Fenner may not 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.
*/
/* \summary: Virtual Router Redundancy Protocol (VRRP) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "extract.h"
#include "addrtoname.h"
#include "ip.h"
#include "ipproto.h"
/*
* RFC 2338 (VRRP v2):
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |Version| Type | Virtual Rtr ID| Priority | Count IP Addrs|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Auth Type | Adver Int | Checksum |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | IP Address (1) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | . |
* | . |
* | . |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | IP Address (n) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Authentication Data (1) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Authentication Data (2) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*
* RFC 5798 (VRRP v3):
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | IPv4 Fields or IPv6 Fields |
* ... ...
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |Version| Type | Virtual Rtr ID| Priority |Count IPvX Addr|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |(rsvd) | Max Adver Int | Checksum |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* + +
* | IPvX Address(es) |
* + +
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/* Type */
#define VRRP_TYPE_ADVERTISEMENT 1
static const struct tok type2str[] = {
{ VRRP_TYPE_ADVERTISEMENT, "Advertisement" },
{ 0, NULL }
};
/* Auth Type */
#define VRRP_AUTH_NONE 0
#define VRRP_AUTH_SIMPLE 1
#define VRRP_AUTH_AH 2
static const struct tok auth2str[] = {
{ VRRP_AUTH_NONE, "none" },
{ VRRP_AUTH_SIMPLE, "simple" },
{ VRRP_AUTH_AH, "ah" },
{ 0, NULL }
};
void
vrrp_print(netdissect_options *ndo,
const u_char *bp, u_int len,
const u_char *bp2, int ttl,
int ver)
{
int version, type, auth_type = VRRP_AUTH_NONE; /* keep compiler happy */
const char *type_s;
ndo->ndo_protocol = "vrrp";
nd_print_protocol_caps(ndo);
version = (GET_U_1(bp) & 0xf0) >> 4;
type = GET_U_1(bp) & 0x0f;
type_s = tok2str(type2str, "unknown type (%u)", type);
ND_PRINT("v%u, %s", version, type_s);
if (ttl != 255)
ND_PRINT(", (ttl %u)", ttl);
if (version < 2 || version > 3 || type != VRRP_TYPE_ADVERTISEMENT)
return;
ND_PRINT(", vrid %u, prio %u", GET_U_1(bp + 1), GET_U_1(bp + 2));
if (version == 2) {
auth_type = GET_U_1(bp + 4);
ND_PRINT(", authtype %s", tok2str(auth2str, NULL, auth_type));
ND_PRINT(", intvl %us, length %u", GET_U_1(bp + 5), len);
} else { /* version == 3 */
uint16_t intvl = (GET_U_1(bp + 4) & 0x0f) << 8 | GET_U_1(bp + 5);
ND_PRINT(", intvl %ucs, length %u", intvl, len);
}
if (ndo->ndo_vflag) {
u_int naddrs = GET_U_1(bp + 3);
u_int i;
char c;
if (version == 2 && ND_TTEST_LEN(bp, len)) {
struct cksum_vec vec[1];
vec[0].ptr = bp;
vec[0].len = len;
if (in_cksum(vec, 1))
ND_PRINT(", (bad vrrp cksum %x)",
GET_BE_U_2(bp + 6));
}
if (version == 3 && ND_TTEST_LEN(bp, len)) {
uint16_t cksum;
if (ver == 4)
cksum = nextproto4_cksum(ndo, (const struct ip *)bp2, bp,
len, len, IPPROTO_VRRP);
else
cksum = nextproto6_cksum(ndo, (const struct ip6_hdr *)bp2, bp,
len, len, IPPROTO_VRRP);
if (cksum)
ND_PRINT(", (bad vrrp cksum %x)",
GET_BE_U_2(bp + 6));
}
ND_PRINT(", addrs");
if (naddrs > 1)
ND_PRINT("(%u)", naddrs);
ND_PRINT(":");
c = ' ';
bp += 8;
for (i = 0; i < naddrs; i++) {
if (ver == 4) {
ND_PRINT("%c%s", c, GET_IPADDR_STRING(bp));
bp += 4;
} else {
ND_PRINT("%c%s", c, GET_IP6ADDR_STRING(bp));
bp += 16;
}
c = ',';
}
if (version == 2 && auth_type == VRRP_AUTH_SIMPLE) { /* simple text password */
ND_PRINT(" auth \"");
/*
* RFC 2338 Section 5.3.10: "If the configured authentication string
* is shorter than 8 bytes, the remaining space MUST be zero-filled.
*/
nd_printjnp(ndo, bp, 8);
ND_PRINT("\"");
}
}
}
diff --git a/contrib/tcpdump/print-vsock.c b/contrib/tcpdump/print-vsock.c
index bb18c92b8cef..bcb08cc77e10 100644
--- a/contrib/tcpdump/print-vsock.c
+++ b/contrib/tcpdump/print-vsock.c
@@ -1,262 +1,260 @@
/*
* Copyright (c) 2016 Gerard Garcia <nouboh@gmail.com>
* Copyright (c) 2017 Red Hat, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. The names of the authors may not 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.
*/
/* \summary: Linux vsock printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <stddef.h>
#include "netdissect.h"
#include "extract.h"
enum af_vsockmon_transport {
AF_VSOCK_TRANSPORT_UNKNOWN = 0,
AF_VSOCK_TRANSPORT_NO_INFO = 1, /* No transport information */
AF_VSOCK_TRANSPORT_VIRTIO = 2, /* Virtio transport header */
};
static const struct tok vsock_transport[] = {
{AF_VSOCK_TRANSPORT_UNKNOWN, "UNKNOWN"},
{AF_VSOCK_TRANSPORT_NO_INFO, "NO_INFO"},
{AF_VSOCK_TRANSPORT_VIRTIO, "VIRTIO"},
{ 0, NULL }
};
enum af_vsockmon_op {
AF_VSOCK_OP_UNKNOWN = 0,
AF_VSOCK_OP_CONNECT = 1,
AF_VSOCK_OP_DISCONNECT = 2,
AF_VSOCK_OP_CONTROL = 3,
AF_VSOCK_OP_PAYLOAD = 4,
};
static const struct tok vsock_op[] = {
{AF_VSOCK_OP_UNKNOWN, "UNKNOWN"},
{AF_VSOCK_OP_CONNECT, "CONNECT"},
{AF_VSOCK_OP_DISCONNECT, "DISCONNECT"},
{AF_VSOCK_OP_CONTROL, "CONTROL"},
{AF_VSOCK_OP_PAYLOAD, "PAYLOAD"},
{ 0, NULL }
};
enum virtio_vsock_type {
VIRTIO_VSOCK_TYPE_STREAM = 1,
};
static const struct tok virtio_type[] = {
{VIRTIO_VSOCK_TYPE_STREAM, "STREAM"},
{ 0, NULL }
};
enum virtio_vsock_op {
VIRTIO_VSOCK_OP_INVALID = 0,
VIRTIO_VSOCK_OP_REQUEST = 1,
VIRTIO_VSOCK_OP_RESPONSE = 2,
VIRTIO_VSOCK_OP_RST = 3,
VIRTIO_VSOCK_OP_SHUTDOWN = 4,
VIRTIO_VSOCK_OP_RW = 5,
VIRTIO_VSOCK_OP_CREDIT_UPDATE = 6,
VIRTIO_VSOCK_OP_CREDIT_REQUEST = 7,
};
static const struct tok virtio_op[] = {
{VIRTIO_VSOCK_OP_INVALID, "INVALID"},
{VIRTIO_VSOCK_OP_REQUEST, "REQUEST"},
{VIRTIO_VSOCK_OP_RESPONSE, "RESPONSE"},
{VIRTIO_VSOCK_OP_RST, "RST"},
{VIRTIO_VSOCK_OP_SHUTDOWN, "SHUTDOWN"},
{VIRTIO_VSOCK_OP_RW, "RW"},
{VIRTIO_VSOCK_OP_CREDIT_UPDATE, "CREDIT UPDATE"},
{VIRTIO_VSOCK_OP_CREDIT_REQUEST, "CREDIT REQUEST"},
{ 0, NULL }
};
/* All fields are little-endian */
struct virtio_vsock_hdr {
nd_uint64_t src_cid;
nd_uint64_t dst_cid;
nd_uint32_t src_port;
nd_uint32_t dst_port;
nd_uint32_t len;
nd_uint16_t type; /* enum virtio_vsock_type */
nd_uint16_t op; /* enum virtio_vsock_op */
nd_uint32_t flags;
nd_uint32_t buf_alloc;
nd_uint32_t fwd_cnt;
};
struct af_vsockmon_hdr {
nd_uint64_t src_cid;
nd_uint64_t dst_cid;
nd_uint32_t src_port;
nd_uint32_t dst_port;
nd_uint16_t op; /* enum af_vsockmon_op */
nd_uint16_t transport; /* enum af_vosckmon_transport */
nd_uint16_t len; /* size of transport header */
nd_uint8_t reserved[2];
};
static void
vsock_virtio_hdr_print(netdissect_options *ndo, const struct virtio_vsock_hdr *hdr)
{
uint16_t u16_v;
uint32_t u32_v;
u32_v = GET_LE_U_4(hdr->len);
ND_PRINT("len %u", u32_v);
u16_v = GET_LE_U_2(hdr->type);
ND_PRINT(", type %s",
tok2str(virtio_type, "Invalid type (%hu)", u16_v));
u16_v = GET_LE_U_2(hdr->op);
ND_PRINT(", op %s",
tok2str(virtio_op, "Invalid op (%hu)", u16_v));
u32_v = GET_LE_U_4(hdr->flags);
ND_PRINT(", flags %x", u32_v);
u32_v = GET_LE_U_4(hdr->buf_alloc);
ND_PRINT(", buf_alloc %u", u32_v);
u32_v = GET_LE_U_4(hdr->fwd_cnt);
ND_PRINT(", fwd_cnt %u", u32_v);
}
/*
* This size had better fit in a u_int.
*/
static u_int
vsock_transport_hdr_size(uint16_t transport)
{
switch (transport) {
case AF_VSOCK_TRANSPORT_VIRTIO:
return (u_int)sizeof(struct virtio_vsock_hdr);
default:
return 0;
}
}
/* Returns 0 on success, -1 on truncation */
static int
vsock_transport_hdr_print(netdissect_options *ndo, uint16_t transport,
const u_char *p, const u_int caplen)
{
u_int transport_size = vsock_transport_hdr_size(transport);
const void *hdr;
if (caplen < sizeof(struct af_vsockmon_hdr) + transport_size) {
return -1;
}
hdr = p + sizeof(struct af_vsockmon_hdr);
switch (transport) {
case AF_VSOCK_TRANSPORT_VIRTIO:
ND_PRINT(" (");
vsock_virtio_hdr_print(ndo, hdr);
ND_PRINT(")");
break;
default:
break;
}
return 0;
}
static void
vsock_hdr_print(netdissect_options *ndo, const u_char *p, const u_int caplen)
{
const struct af_vsockmon_hdr *hdr = (const struct af_vsockmon_hdr *)p;
uint16_t hdr_transport, hdr_op;
uint32_t hdr_src_port, hdr_dst_port;
uint64_t hdr_src_cid, hdr_dst_cid;
u_int total_hdr_size;
int ret = 0;
hdr_transport = GET_LE_U_2(hdr->transport);
ND_PRINT("%s",
tok2str(vsock_transport, "Invalid transport (%u)",
hdr_transport));
/* If verbose level is more than 0 print transport details */
if (ndo->ndo_vflag) {
ret = vsock_transport_hdr_print(ndo, hdr_transport, p, caplen);
if (ret == 0)
ND_PRINT("\n\t");
} else
ND_PRINT(" ");
hdr_src_cid = GET_LE_U_8(hdr->src_cid);
hdr_dst_cid = GET_LE_U_8(hdr->dst_cid);
hdr_src_port = GET_LE_U_4(hdr->src_port);
hdr_dst_port = GET_LE_U_4(hdr->dst_port);
hdr_op = GET_LE_U_2(hdr->op);
ND_PRINT("%" PRIu64 ".%u > %" PRIu64 ".%u %s, length %u",
hdr_src_cid, hdr_src_port,
hdr_dst_cid, hdr_dst_port,
tok2str(vsock_op, " invalid op (%u)", hdr_op),
caplen);
if (ret < 0)
goto trunc;
/* If debug level is more than 1 print payload contents */
/* This size had better fit in a u_int */
total_hdr_size = (u_int)sizeof(struct af_vsockmon_hdr) +
vsock_transport_hdr_size(hdr_transport);
if (ndo->ndo_vflag > 1 && hdr_op == AF_VSOCK_OP_PAYLOAD) {
if (caplen > total_hdr_size) {
const u_char *payload = p + total_hdr_size;
ND_PRINT("\n");
print_unknown_data(ndo, payload, "\t",
caplen - total_hdr_size);
} else
goto trunc;
}
return;
trunc:
nd_print_trunc(ndo);
}
void
vsock_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h,
const u_char *cp)
{
u_int caplen = h->caplen;
ndo->ndo_protocol = "vsock";
if (caplen < sizeof(struct af_vsockmon_hdr)) {
nd_print_trunc(ndo);
ndo->ndo_ll_hdr_len += caplen;
return;
}
ndo->ndo_ll_hdr_len += sizeof(struct af_vsockmon_hdr);
vsock_hdr_print(ndo, cp, caplen);
}
diff --git a/contrib/tcpdump/print-vtp.c b/contrib/tcpdump/print-vtp.c
index bcee64cfe58d..5b6030477da3 100644
--- a/contrib/tcpdump/print-vtp.c
+++ b/contrib/tcpdump/print-vtp.c
@@ -1,392 +1,390 @@
/*
* Copyright (c) 1998-2007 The TCPDUMP project
*
* 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.
*
* Reference documentation:
* https://www.cisco.com/c/en/us/support/docs/lan-switching/vtp/10558-21.html
* https://docstore.mik.ua/univercd/cc/td/doc/product/lan/trsrb/frames.htm
*
* Original code ode by Carles Kishimoto <carles.kishimoto@gmail.com>
*/
/* \summary: Cisco VLAN Trunking Protocol (VTP) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#define VTP_HEADER_LEN 36
#define VTP_DOMAIN_NAME_LEN 32
#define VTP_MD5_DIGEST_LEN 16
#define VTP_UPDATE_TIMESTAMP_LEN 12
#define VTP_VLAN_INFO_FIXED_PART_LEN 12 /* length of VLAN info before VLAN name */
#define VTP_SUMMARY_ADV 0x01
#define VTP_SUBSET_ADV 0x02
#define VTP_ADV_REQUEST 0x03
#define VTP_JOIN_MESSAGE 0x04
struct vtp_vlan_ {
nd_uint8_t len;
nd_uint8_t status;
nd_uint8_t type;
nd_uint8_t name_len;
nd_uint16_t vlanid;
nd_uint16_t mtu;
nd_uint32_t index;
};
static const struct tok vtp_message_type_values[] = {
{ VTP_SUMMARY_ADV, "Summary advertisement"},
{ VTP_SUBSET_ADV, "Subset advertisement"},
{ VTP_ADV_REQUEST, "Advertisement request"},
{ VTP_JOIN_MESSAGE, "Join message"},
{ 0, NULL }
};
static const struct tok vtp_header_values[] = {
{ 0x01, "Followers"}, /* On Summary advertisement, 3rd byte is Followers */
{ 0x02, "Seq number"}, /* On Subset advertisement, 3rd byte is Sequence number */
{ 0x03, "Rsvd"}, /* On Adver. requests 3rd byte is Rsvd */
{ 0x04, "Rsvd"}, /* On Adver. requests 3rd byte is Rsvd */
{ 0, NULL }
};
static const struct tok vtp_vlan_type_values[] = {
{ 0x01, "Ethernet"},
{ 0x02, "FDDI"},
{ 0x03, "TrCRF"},
{ 0x04, "FDDI-net"},
{ 0x05, "TrBRF"},
{ 0, NULL }
};
static const struct tok vtp_vlan_status[] = {
{ 0x00, "Operational"},
{ 0x01, "Suspended"},
{ 0, NULL }
};
#define VTP_VLAN_SOURCE_ROUTING_RING_NUMBER 0x01
#define VTP_VLAN_SOURCE_ROUTING_BRIDGE_NUMBER 0x02
#define VTP_VLAN_STP_TYPE 0x03
#define VTP_VLAN_PARENT_VLAN 0x04
#define VTP_VLAN_TRANS_BRIDGED_VLAN 0x05
#define VTP_VLAN_PRUNING 0x06
#define VTP_VLAN_BRIDGE_TYPE 0x07
#define VTP_VLAN_ARP_HOP_COUNT 0x08
#define VTP_VLAN_STE_HOP_COUNT 0x09
#define VTP_VLAN_BACKUP_CRF_MODE 0x0A
static const struct tok vtp_vlan_tlv_values[] = {
{ VTP_VLAN_SOURCE_ROUTING_RING_NUMBER, "Source-Routing Ring Number TLV"},
{ VTP_VLAN_SOURCE_ROUTING_BRIDGE_NUMBER, "Source-Routing Bridge Number TLV"},
{ VTP_VLAN_STP_TYPE, "STP type TLV"},
{ VTP_VLAN_PARENT_VLAN, "Parent VLAN TLV"},
{ VTP_VLAN_TRANS_BRIDGED_VLAN, "Translationally bridged VLANs TLV"},
{ VTP_VLAN_PRUNING, "Pruning TLV"},
{ VTP_VLAN_BRIDGE_TYPE, "Bridge Type TLV"},
{ VTP_VLAN_ARP_HOP_COUNT, "Max ARP Hop Count TLV"},
{ VTP_VLAN_STE_HOP_COUNT, "Max STE Hop Count TLV"},
{ VTP_VLAN_BACKUP_CRF_MODE, "Backup CRF Mode TLV"},
{ 0, NULL }
};
static const struct tok vtp_stp_type_values[] = {
{ 1, "SRT"},
{ 2, "SRB"},
{ 3, "Auto"},
{ 0, NULL }
};
void
vtp_print(netdissect_options *ndo,
const u_char *pptr, const u_int length)
{
u_int type, len, name_len, tlv_len, tlv_value, mgmtd_len;
const u_char *tptr;
const struct vtp_vlan_ *vtp_vlan;
ndo->ndo_protocol = "vtp";
if (length < VTP_HEADER_LEN)
goto invalid;
tptr = pptr;
ND_TCHECK_LEN(tptr, VTP_HEADER_LEN);
type = GET_U_1(tptr + 1);
ND_PRINT("VTPv%u, Message %s (0x%02x), length %u",
GET_U_1(tptr),
tok2str(vtp_message_type_values,"Unknown message type", type),
type,
length);
/* In non-verbose mode, just print version and message type */
if (ndo->ndo_vflag < 1) {
goto tcheck_full_packet;
}
/* verbose mode print all fields */
ND_PRINT("\n\tDomain name: ");
mgmtd_len = GET_U_1(tptr + 3);
if (mgmtd_len < 1 || mgmtd_len > VTP_DOMAIN_NAME_LEN) {
- ND_PRINT(" [invalid MgmtD Len %u]", mgmtd_len);
+ ND_PRINT(" [MgmtD Len %u]", mgmtd_len);
goto invalid;
}
nd_printjnp(ndo, tptr + 4, mgmtd_len);
ND_PRINT(", %s: %u",
tok2str(vtp_header_values, "Unknown", type),
GET_U_1(tptr + 2));
tptr += VTP_HEADER_LEN;
switch (type) {
case VTP_SUMMARY_ADV:
/*
* SUMMARY ADVERTISEMENT
*
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Version | Code | Followers | MgmtD Len |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Management Domain Name (zero-padded to 32 bytes) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Configuration revision number |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Updater Identity IP address |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Update Timestamp (12 bytes) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | MD5 digest (16 bytes) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*/
ND_PRINT("\n\t Config Rev %x, Updater %s",
GET_BE_U_4(tptr),
GET_IPADDR_STRING(tptr+4));
tptr += 8;
ND_PRINT(", Timestamp 0x%08x 0x%08x 0x%08x",
GET_BE_U_4(tptr),
GET_BE_U_4(tptr + 4),
GET_BE_U_4(tptr + 8));
tptr += VTP_UPDATE_TIMESTAMP_LEN;
ND_PRINT(", MD5 digest: %08x%08x%08x%08x",
GET_BE_U_4(tptr),
GET_BE_U_4(tptr + 4),
GET_BE_U_4(tptr + 8),
GET_BE_U_4(tptr + 12));
tptr += VTP_MD5_DIGEST_LEN;
break;
case VTP_SUBSET_ADV:
/*
* SUBSET ADVERTISEMENT
*
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Version | Code | Seq number | MgmtD Len |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Management Domain Name (zero-padded to 32 bytes) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Configuration revision number |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | VLAN info field 1 |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | ................ |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | VLAN info field N |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*/
ND_PRINT(", Config Rev %x", GET_BE_U_4(tptr));
/*
* VLAN INFORMATION
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | V info len | Status | VLAN type | VLAN name len |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | ISL vlan id | MTU size |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | 802.10 index (SAID) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | VLAN name |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*/
tptr += 4;
while ((unsigned)(tptr - pptr) < length) {
len = GET_U_1(tptr);
if (len == 0)
break;
ND_TCHECK_LEN(tptr, len);
vtp_vlan = (const struct vtp_vlan_*)tptr;
if (len < VTP_VLAN_INFO_FIXED_PART_LEN)
goto invalid;
ND_PRINT("\n\tVLAN info status %s, type %s, VLAN-id %u, MTU %u, SAID 0x%08x, Name ",
tok2str(vtp_vlan_status,"Unknown",GET_U_1(vtp_vlan->status)),
tok2str(vtp_vlan_type_values,"Unknown",GET_U_1(vtp_vlan->type)),
GET_BE_U_2(vtp_vlan->vlanid),
GET_BE_U_2(vtp_vlan->mtu),
GET_BE_U_4(vtp_vlan->index));
len -= VTP_VLAN_INFO_FIXED_PART_LEN;
tptr += VTP_VLAN_INFO_FIXED_PART_LEN;
name_len = GET_U_1(vtp_vlan->name_len);
if (len < 4*((name_len + 3)/4))
goto invalid;
nd_printjnp(ndo, tptr, name_len);
/*
* Vlan names are aligned to 32-bit boundaries.
*/
len -= 4*((name_len + 3)/4);
tptr += 4*((name_len + 3)/4);
/* TLV information follows */
while (len > 0) {
/*
* Cisco specs say 2 bytes for type + 2 bytes for length;
* see https://docstore.mik.ua/univercd/cc/td/doc/product/lan/trsrb/frames.htm
* However, actual packets on the wire appear to use 1
* byte for the type and 1 byte for the length, so that's
* what we do.
*/
if (len < 2)
goto invalid;
type = GET_U_1(tptr);
tlv_len = GET_U_1(tptr + 1);
ND_PRINT("\n\t\t%s (0x%04x) TLV",
tok2str(vtp_vlan_tlv_values, "Unknown", type),
type);
if (len < tlv_len * 2 + 2) {
ND_PRINT(" (TLV goes past the end of the packet)");
goto invalid;
}
ND_TCHECK_LEN(tptr, tlv_len * 2 + 2);
/*
* We assume the value is a 2-byte integer; the length is
* in units of 16-bit words.
*/
if (tlv_len != 1) {
- ND_PRINT(" (invalid TLV length %u != 1)", tlv_len);
+ ND_PRINT(" [TLV length %u != 1]", tlv_len);
goto invalid;
} else {
tlv_value = GET_BE_U_2(tptr + 2);
switch (type) {
case VTP_VLAN_STE_HOP_COUNT:
ND_PRINT(", %u", tlv_value);
break;
case VTP_VLAN_PRUNING:
ND_PRINT(", %s (%u)",
tlv_value == 1 ? "Enabled" : "Disabled",
tlv_value);
break;
case VTP_VLAN_STP_TYPE:
ND_PRINT(", %s (%u)",
tok2str(vtp_stp_type_values, "Unknown", tlv_value),
tlv_value);
break;
case VTP_VLAN_BRIDGE_TYPE:
ND_PRINT(", %s (%u)",
tlv_value == 1 ? "SRB" : "SRT",
tlv_value);
break;
case VTP_VLAN_BACKUP_CRF_MODE:
ND_PRINT(", %s (%u)",
tlv_value == 1 ? "Backup" : "Not backup",
tlv_value);
break;
/*
* FIXME those are the defined TLVs that lack a decoder
* you are welcome to contribute code ;-)
*/
case VTP_VLAN_SOURCE_ROUTING_RING_NUMBER:
case VTP_VLAN_SOURCE_ROUTING_BRIDGE_NUMBER:
case VTP_VLAN_PARENT_VLAN:
case VTP_VLAN_TRANS_BRIDGED_VLAN:
case VTP_VLAN_ARP_HOP_COUNT:
default:
print_unknown_data(ndo, tptr, "\n\t\t ", 2 + tlv_len*2);
break;
}
}
len -= 2 + tlv_len*2;
tptr += 2 + tlv_len*2;
}
}
break;
case VTP_ADV_REQUEST:
/*
* ADVERTISEMENT REQUEST
*
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Version | Code | Reserved | MgmtD Len |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Management Domain Name (zero-padded to 32 bytes) |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Start value |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
*/
ND_PRINT("\n\tStart value: %u", GET_BE_U_4(tptr));
break;
case VTP_JOIN_MESSAGE:
/* FIXME - Could not find message format */
break;
default:
break;
}
return;
invalid:
nd_print_invalid(ndo);
tcheck_full_packet:
ND_TCHECK_LEN(pptr, length);
}
diff --git a/contrib/tcpdump/print-vxlan-gpe.c b/contrib/tcpdump/print-vxlan-gpe.c
index 13cba4229377..e990f9667769 100644
--- a/contrib/tcpdump/print-vxlan-gpe.c
+++ b/contrib/tcpdump/print-vxlan-gpe.c
@@ -1,124 +1,122 @@
/* Copyright (c) 2015, bugyo
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* \summary: Generic Protocol Extension for VXLAN (VXLAN GPE) printer */
/* specification: draft-ietf-nvo3-vxlan-gpe-10 */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
static const struct tok vxlan_gpe_flags [] = {
{ 0x08, "I" },
{ 0x04, "P" },
{ 0x02, "B" },
{ 0x01, "O" },
{ 0, NULL }
};
#define VXLAN_GPE_HDR_LEN 8
/*
* VXLAN GPE header, draft-ietf-nvo3-vxlan-gpe-01
* Generic Protocol Extension for VXLAN
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |R|R|Ver|I|P|R|O| Reserved |Next Protocol |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | VXLAN Network Identifier (VNI) | Reserved |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
void
vxlan_gpe_print(netdissect_options *ndo, const u_char *bp, u_int len)
{
uint8_t flags;
uint8_t next_protocol;
uint32_t vni;
ndo->ndo_protocol = "vxlan_gpe";
ND_PRINT("VXLAN-GPE, ");
if (len < VXLAN_GPE_HDR_LEN) {
ND_PRINT(" (len %u < %u)", len, VXLAN_GPE_HDR_LEN);
goto invalid;
}
flags = GET_U_1(bp);
bp += 1;
len -= 1;
ND_PRINT("flags [%s], ",
bittok2str_nosep(vxlan_gpe_flags, "none", flags));
/* Reserved */
bp += 2;
len -= 2;
next_protocol = GET_U_1(bp);
bp += 1;
len -= 1;
vni = GET_BE_U_3(bp);
bp += 3;
len -= 3;
/* Reserved */
ND_TCHECK_1(bp);
bp += 1;
len -= 1;
ND_PRINT("vni %u", vni);
ND_PRINT(ndo->ndo_vflag ? "\n " : ": ");
switch (next_protocol) {
case 0x1:
ip_print(ndo, bp, len);
break;
case 0x2:
ip6_print(ndo, bp, len);
break;
case 0x3:
ether_print(ndo, bp, len, ND_BYTES_AVAILABLE_AFTER(bp), NULL, NULL);
break;
case 0x4:
nsh_print(ndo, bp, len);
break;
default:
ND_PRINT("ERROR: unknown-next-protocol");
goto invalid;
}
return;
invalid:
nd_print_invalid(ndo);
}
diff --git a/contrib/tcpdump/print-vxlan.c b/contrib/tcpdump/print-vxlan.c
index 60dcd44def50..b40061b67d8a 100644
--- a/contrib/tcpdump/print-vxlan.c
+++ b/contrib/tcpdump/print-vxlan.c
@@ -1,83 +1,81 @@
/*
* 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.
*
* Original code by Francesco Fondelli (francesco dot fondelli, gmail dot com)
*/
/* \summary: Virtual eXtensible Local Area Network (VXLAN) printer */
/* specification: RFC 7348 */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
static const struct tok vxlan_flags [] = {
{ 0x08, "I" },
{ 0, NULL }
};
#define VXLAN_HDR_LEN 8
/*
* VXLAN header, RFC7348
* Virtual eXtensible Local Area Network (VXLAN): A Framework
* for Overlaying Virtualized Layer 2 Networks over Layer 3 Networks
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |R|R|R|R|I|R|R|R| Reserved |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | VXLAN Network Identifier (VNI) | Reserved |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
void
vxlan_print(netdissect_options *ndo, const u_char *bp, u_int len)
{
uint8_t flags;
uint32_t vni;
ndo->ndo_protocol = "vxlan";
nd_print_protocol_caps(ndo);
if (len < VXLAN_HDR_LEN)
goto invalid;
flags = GET_U_1(bp);
bp += 1;
ND_PRINT(", flags [%s] (0x%02x), ",
bittok2str_nosep(vxlan_flags, "invalid", flags), flags);
/* 1st Reserved */
bp += 3;
vni = GET_BE_U_3(bp);
bp += 3;
ND_PRINT("vni %u\n", vni);
/* 2nd Reserved */
ND_TCHECK_1(bp);
bp += 1;
ether_print(ndo, bp, len - VXLAN_HDR_LEN, ND_BYTES_AVAILABLE_AFTER(bp), NULL, NULL);
return;
invalid:
nd_print_invalid(ndo);
}
diff --git a/contrib/tcpdump/print-wb.c b/contrib/tcpdump/print-wb.c
index 35b5a196d8bf..30c751b8f684 100644
--- a/contrib/tcpdump/print-wb.c
+++ b/contrib/tcpdump/print-wb.c
@@ -1,445 +1,443 @@
/*
* Copyright (c) 1993, 1994, 1995, 1996
* 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.
*/
/* \summary: White Board printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "addrtoname.h"
#include "extract.h"
#if 0
/*
* Largest packet size. Everything should fit within this space.
* For instance, multiline objects are sent piecewise.
*/
#define MAXFRAMESIZE 1024
#endif
/*
* Multiple drawing ops can be sent in one packet. Each one starts on a
* an even multiple of DOP_ALIGN bytes, which must be a power of two.
*/
#define DOP_ALIGN 4
#define DOP_ROUNDUP(x) roundup2(x, DOP_ALIGN)
#define DOP_NEXT(d)\
((const struct dophdr *)((const u_char *)(d) + \
DOP_ROUNDUP(GET_BE_U_2((d)->dh_len) + sizeof(*(d)))))
/*
* Format of the whiteboard packet header.
* The transport level header.
*/
struct pkt_hdr {
nd_uint32_t ph_src; /* site id of source */
nd_uint32_t ph_ts; /* time stamp (for skew computation) */
nd_uint16_t ph_version; /* version number */
nd_uint8_t ph_type; /* message type */
nd_uint8_t ph_flags; /* message flags */
};
/* Packet types */
#define PT_DRAWOP 0 /* drawing operation */
#define PT_ID 1 /* announcement packet */
#define PT_RREQ 2 /* repair request */
#define PT_RREP 3 /* repair reply */
#define PT_KILL 4 /* terminate participation */
#define PT_PREQ 5 /* page vector request */
#define PT_PREP 7 /* page vector reply */
#if 0
#ifdef PF_USER
#undef PF_USER /* {Digital,Tru64} UNIX define this, alas */
#endif
/* flags */
#define PF_USER 0x01 /* hint that packet has interactive data */
#define PF_VIS 0x02 /* only visible ops wanted */
#endif
struct PageID {
nd_uint32_t p_sid; /* session id of initiator */
nd_uint32_t p_uid; /* page number */
};
struct dophdr {
nd_uint32_t dh_ts; /* sender's timestamp */
nd_uint16_t dh_len; /* body length */
nd_uint8_t dh_flags;
nd_uint8_t dh_type; /* body type */
/* body follows */
};
/*
* Drawing op sub-types.
*/
#define DT_RECT 2
#define DT_LINE 3
#define DT_ML 4
#define DT_DEL 5
#define DT_XFORM 6
#define DT_ELL 7
#define DT_CHAR 8
#define DT_STR 9
#define DT_NOP 10
#define DT_PSCODE 11
#define DT_PSCOMP 12
#define DT_REF 13
#define DT_SKIP 14
#define DT_HOLE 15
static const struct tok dop_str[] = {
{ DT_RECT, "RECT" },
{ DT_LINE, "LINE" },
{ DT_ML, "ML" },
{ DT_DEL, "DEL" },
{ DT_XFORM, "XFORM" },
{ DT_ELL, "ELL" },
{ DT_CHAR, "CHAR" },
{ DT_STR, "STR" },
{ DT_NOP, "NOP" },
{ DT_PSCODE, "PSCODE" },
{ DT_PSCOMP, "PSCOMP" },
{ DT_REF, "REF" },
{ DT_SKIP, "SKIP" },
{ DT_HOLE, "HOLE" },
{ 0, NULL }
};
/*
* A drawing operation.
*/
struct pkt_dop {
struct PageID pd_page; /* page that operations apply to */
nd_uint32_t pd_sseq; /* start sequence number */
nd_uint32_t pd_eseq; /* end sequence number */
/* drawing ops follow */
};
/*
* A repair request.
*/
struct pkt_rreq {
nd_uint32_t pr_id; /* source id of drawops to be repaired */
struct PageID pr_page; /* page of drawops */
nd_uint32_t pr_sseq; /* start seqno */
nd_uint32_t pr_eseq; /* end seqno */
};
/*
* A repair reply.
*/
struct pkt_rrep {
nd_uint32_t pr_id; /* original site id of ops */
struct pkt_dop pr_dop;
/* drawing ops follow */
};
struct id_off {
nd_uint32_t id;
nd_uint32_t off;
};
struct pgstate {
nd_uint32_t slot;
struct PageID page;
nd_uint16_t nid;
nd_uint16_t rsvd;
/* seqptr's */
};
/*
* An announcement packet.
*/
struct pkt_id {
nd_uint32_t pi_mslot;
struct PageID pi_mpage; /* current page */
struct pgstate pi_ps;
/* seqptr's */
/* null-terminated site name */
};
struct pkt_preq {
struct PageID pp_page;
nd_uint32_t pp_low;
nd_uint32_t pp_high;
};
struct pkt_prep {
nd_uint32_t pp_n; /* size of pageid array */
/* pgstate's follow */
};
static int
wb_id(netdissect_options *ndo,
const struct pkt_id *id, u_int len)
{
u_int i;
const u_char *sitename;
const struct id_off *io;
char c;
u_int nid;
ND_PRINT(" wb-id:");
if (len < sizeof(*id))
return (-1);
len -= sizeof(*id);
ND_PRINT(" %u/%s:%u (max %u/%s:%u) ",
GET_BE_U_4(id->pi_ps.slot),
GET_IPADDR_STRING(id->pi_ps.page.p_sid),
GET_BE_U_4(id->pi_ps.page.p_uid),
GET_BE_U_4(id->pi_mslot),
GET_IPADDR_STRING(id->pi_mpage.p_sid),
GET_BE_U_4(id->pi_mpage.p_uid));
/* now the rest of the fixed-size part of struct pkt_id */
ND_TCHECK_SIZE(id);
nid = GET_BE_U_2(id->pi_ps.nid);
if (len < sizeof(*io) * nid)
return (-1);
len -= sizeof(*io) * nid;
io = (const struct id_off *)(id + 1);
sitename = (const u_char *)(io + nid);
c = '<';
for (i = 0; i < nid; ++io, ++i) {
ND_PRINT("%c%s:%u",
c, GET_IPADDR_STRING(io->id), GET_BE_U_4(io->off));
c = ',';
}
ND_PRINT("> \"");
nd_printjnp(ndo, sitename, len);
ND_PRINT("\"");
return (0);
}
static int
wb_rreq(netdissect_options *ndo,
const struct pkt_rreq *rreq, u_int len)
{
ND_PRINT(" wb-rreq:");
if (len < sizeof(*rreq))
return (-1);
ND_PRINT(" please repair %s %s:%u<%u:%u>",
GET_IPADDR_STRING(rreq->pr_id),
GET_IPADDR_STRING(rreq->pr_page.p_sid),
GET_BE_U_4(rreq->pr_page.p_uid),
GET_BE_U_4(rreq->pr_sseq),
GET_BE_U_4(rreq->pr_eseq));
return (0);
}
static int
wb_preq(netdissect_options *ndo,
const struct pkt_preq *preq, u_int len)
{
ND_PRINT(" wb-preq:");
if (len < sizeof(*preq))
return (-1);
ND_PRINT(" need %u/%s:%u",
GET_BE_U_4(preq->pp_low),
GET_IPADDR_STRING(preq->pp_page.p_sid),
GET_BE_U_4(preq->pp_page.p_uid));
/* now the rest of the fixed-size part of struct pkt_req */
ND_TCHECK_SIZE(preq);
return (0);
}
static int
wb_prep(netdissect_options *ndo,
const struct pkt_prep *prep, u_int len)
{
u_int n;
const struct pgstate *ps;
ND_PRINT(" wb-prep:");
if (len < sizeof(*prep))
return (-1);
n = GET_BE_U_4(prep->pp_n);
ps = (const struct pgstate *)(prep + 1);
while (n != 0) {
const struct id_off *io, *ie;
char c = '<';
ND_PRINT(" %u/%s:%u",
GET_BE_U_4(ps->slot),
GET_IPADDR_STRING(ps->page.p_sid),
GET_BE_U_4(ps->page.p_uid));
/* now the rest of the fixed-size part of struct pgstate */
ND_TCHECK_SIZE(ps);
io = (const struct id_off *)(ps + 1);
for (ie = io + GET_U_1(ps->nid); io < ie; ++io) {
ND_PRINT("%c%s:%u", c, GET_IPADDR_STRING(io->id),
GET_BE_U_4(io->off));
c = ',';
}
ND_PRINT(">");
ps = (const struct pgstate *)io;
n--;
}
return 0;
}
static void
wb_dops(netdissect_options *ndo, const struct pkt_dop *dop,
uint32_t ss, uint32_t es)
{
const struct dophdr *dh = (const struct dophdr *)((const u_char *)dop + sizeof(*dop));
ND_PRINT(" <");
for ( ; ss <= es; ++ss) {
u_int t;
t = GET_U_1(dh->dh_type);
ND_PRINT(" %s", tok2str(dop_str, "dop-%u!", t));
if (t == DT_SKIP || t == DT_HOLE) {
uint32_t ts = GET_BE_U_4(dh->dh_ts);
ND_PRINT("%u", ts - ss + 1);
if (ss > ts || ts > es) {
ND_PRINT("[|]");
if (ts < ss)
return;
}
ss = ts;
}
dh = DOP_NEXT(dh);
}
ND_PRINT(" >");
}
static int
wb_rrep(netdissect_options *ndo,
const struct pkt_rrep *rrep, u_int len)
{
const struct pkt_dop *dop = &rrep->pr_dop;
ND_PRINT(" wb-rrep:");
if (len < sizeof(*rrep))
return (-1);
len -= sizeof(*rrep);
ND_PRINT(" for %s %s:%u<%u:%u>",
GET_IPADDR_STRING(rrep->pr_id),
GET_IPADDR_STRING(dop->pd_page.p_sid),
GET_BE_U_4(dop->pd_page.p_uid),
GET_BE_U_4(dop->pd_sseq),
GET_BE_U_4(dop->pd_eseq));
if (ndo->ndo_vflag)
wb_dops(ndo, dop,
GET_BE_U_4(dop->pd_sseq),
GET_BE_U_4(dop->pd_eseq));
return (0);
}
static int
wb_drawop(netdissect_options *ndo,
const struct pkt_dop *dop, u_int len)
{
ND_PRINT(" wb-dop:");
if (len < sizeof(*dop))
return (-1);
len -= sizeof(*dop);
ND_PRINT(" %s:%u<%u:%u>",
GET_IPADDR_STRING(dop->pd_page.p_sid),
GET_BE_U_4(dop->pd_page.p_uid),
GET_BE_U_4(dop->pd_sseq),
GET_BE_U_4(dop->pd_eseq));
if (ndo->ndo_vflag)
wb_dops(ndo, dop,
GET_BE_U_4(dop->pd_sseq),
GET_BE_U_4(dop->pd_eseq));
return (0);
}
/*
* Print whiteboard multicast packets.
*/
void
wb_print(netdissect_options *ndo,
const u_char *hdr, u_int len)
{
const struct pkt_hdr *ph;
uint8_t type;
int print_result;
ndo->ndo_protocol = "wb";
ph = (const struct pkt_hdr *)hdr;
if (len < sizeof(*ph))
goto invalid;
ND_TCHECK_SIZE(ph);
len -= sizeof(*ph);
if (GET_U_1(ph->ph_flags))
ND_PRINT("*");
type = GET_U_1(ph->ph_type);
switch (type) {
case PT_KILL:
ND_PRINT(" wb-kill");
return;
case PT_ID:
print_result = wb_id(ndo, (const struct pkt_id *)(ph + 1), len);
break;
case PT_RREQ:
print_result = wb_rreq(ndo, (const struct pkt_rreq *)(ph + 1), len);
break;
case PT_RREP:
print_result = wb_rrep(ndo, (const struct pkt_rrep *)(ph + 1), len);
break;
case PT_DRAWOP:
print_result = wb_drawop(ndo, (const struct pkt_dop *)(ph + 1), len);
break;
case PT_PREQ:
print_result = wb_preq(ndo, (const struct pkt_preq *)(ph + 1), len);
break;
case PT_PREP:
print_result = wb_prep(ndo, (const struct pkt_prep *)(ph + 1), len);
break;
default:
ND_PRINT(" wb-%u!", type);
print_result = -1;
}
if (print_result < 0)
goto invalid;
return;
invalid:
nd_print_invalid(ndo);
}
diff --git a/contrib/tcpdump/print-whois.c b/contrib/tcpdump/print-whois.c
index 30c254aafbe2..2111a56d2737 100644
--- a/contrib/tcpdump/print-whois.c
+++ b/contrib/tcpdump/print-whois.c
@@ -1,31 +1,29 @@
/*
* 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.
*/
/* \summary: WHOIS Protocol printer */
/* RFC 3912 */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
void
whois_print(netdissect_options *ndo, const u_char *pptr, u_int len)
{
ndo->ndo_protocol = "whois";
txtproto_print(ndo, pptr, len, NULL, 0);
}
diff --git a/contrib/tcpdump/print-zep.c b/contrib/tcpdump/print-zep.c
index 52901e789b1d..c507e369d38b 100644
--- a/contrib/tcpdump/print-zep.c
+++ b/contrib/tcpdump/print-zep.c
@@ -1,181 +1,179 @@
/*
* Copyright (c) 1988, 1989, 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.
*/
/* \summary: ZigBee Encapsulation Protocol (ZEP) printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
/* From wireshark packet-zep.c:
*
***********************************************************************
*
* ZEP Packets must be received in the following format:
*
* |UDP Header| ZEP Header |IEEE 802.15.4 Packet|
* | 8 bytes | 16/32 bytes | <= 127 bytes |
*
***********************************************************************
*
* ZEP v1 Header will have the following format:
* |Preamble|Version|Channel ID|Device ID|CRC/LQI Mode|LQI Val|Reserved|Length|
* |2 bytes |1 byte | 1 byte | 2 bytes | 1 byte |1 byte |7 bytes |1 byte|
*
* ZEP v2 Header will have the following format (if type=1/Data):
* |Prmbl|Ver |Type |ChnlID|DevID|C/L Mode|LQI|NTP TS|Seq#|Res |Len|
* | 2 | 1 | 1 | 1 | 2 | 1 | 1 | 8 | 4 | 10 | 1 |
*
* ZEP v2 Header will have the following format (if type=2/Ack):
* |Preamble|Version| Type |Sequence#|
* |2 bytes |1 byte |1 byte| 4 bytes |
*------------------------------------------------------------
*/
#define JAN_1970 2208988800U
/* Print timestamp */
static void zep_print_ts(netdissect_options *ndo, const u_char *p)
{
int32_t i;
uint32_t uf;
uint32_t f;
float ff;
i = GET_BE_U_4(p);
uf = GET_BE_U_4(p + 4);
ff = (float) uf;
if (ff < 0.0) /* some compilers are buggy */
ff += FMAXINT;
ff = (float) (ff / FMAXINT); /* shift radix point by 32 bits */
f = (uint32_t) (ff * 1000000000.0); /* treat fraction as parts per
billion */
ND_PRINT("%u.%09d", i, f);
/*
* print the time in human-readable format.
*/
if (i) {
time_t seconds = i - JAN_1970;
char time_buf[128];
ND_PRINT(" (%s)",
- nd_format_time(time_buf, sizeof (time_buf), "%Y/%m/%d %H:%M:%S",
+ nd_format_time(time_buf, sizeof (time_buf), "%Y-%m-%d %H:%M:%S",
localtime(&seconds)));
}
}
/*
* Main function to print packets.
*/
void
zep_print(netdissect_options *ndo,
const u_char *bp, u_int len)
{
uint8_t version, inner_len;
uint32_t seq_no;
ndo->ndo_protocol = "zep";
nd_print_protocol_caps(ndo);
/* Preamble Code (must be "EX") */
if (GET_U_1(bp) != 'E' || GET_U_1(bp + 1) != 'X') {
ND_PRINT(" [Preamble Code: ");
fn_print_char(ndo, GET_U_1(bp));
fn_print_char(ndo, GET_U_1(bp + 1));
ND_PRINT("]");
nd_print_invalid(ndo);
return;
}
version = GET_U_1(bp + 2);
ND_PRINT("v%u ", version);
if (version == 1) {
/* ZEP v1 packet. */
- ND_LCHECK_U(len, 16);
+ ND_ICHECK_U(len, <, 16);
ND_PRINT("Channel ID %u, Device ID 0x%04x, ",
GET_U_1(bp + 3), GET_BE_U_2(bp + 4));
if (GET_U_1(bp + 6))
ND_PRINT("CRC, ");
else
ND_PRINT("LQI %u, ", GET_U_1(bp + 7));
inner_len = GET_U_1(bp + 15);
ND_PRINT("inner len = %u", inner_len);
bp += 16;
len -= 16;
} else {
/* ZEP v2 packet. */
if (GET_U_1(bp + 3) == 2) {
/* ZEP v2 ack. */
- ND_LCHECK_U(len, 8);
+ ND_ICHECK_U(len, <, 8);
seq_no = GET_BE_U_4(bp + 4);
ND_PRINT("ACK, seq# = %u", seq_no);
inner_len = 0;
bp += 8;
len -= 8;
} else {
/* ZEP v2 data, or some other. */
- ND_LCHECK_U(len, 32);
+ ND_ICHECK_U(len, <, 32);
ND_PRINT("Type %u, Channel ID %u, Device ID 0x%04x, ",
GET_U_1(bp + 3), GET_U_1(bp + 4),
GET_BE_U_2(bp + 5));
if (GET_U_1(bp + 7))
ND_PRINT("CRC, ");
else
ND_PRINT("LQI %u, ", GET_U_1(bp + 8));
zep_print_ts(ndo, bp + 9);
seq_no = GET_BE_U_4(bp + 17);
inner_len = GET_U_1(bp + 31);
ND_PRINT(", seq# = %u, inner len = %u",
seq_no, inner_len);
bp += 32;
len -= 32;
}
}
if (inner_len != 0) {
/* Call 802.15.4 dissector. */
ND_PRINT("\n\t");
if (ieee802_15_4_print(ndo, bp, inner_len)) {
ND_TCHECK_LEN(bp, len);
bp += len;
len = 0;
}
}
if (!ndo->ndo_suppress_default_print)
ND_DEFAULTPRINT(bp, len);
return;
invalid:
nd_print_invalid(ndo);
}
diff --git a/contrib/tcpdump/print-zephyr.c b/contrib/tcpdump/print-zephyr.c
index 11e1e59316a4..796f4e93f79c 100644
--- a/contrib/tcpdump/print-zephyr.c
+++ b/contrib/tcpdump/print-zephyr.c
@@ -1,348 +1,346 @@
/*
* Decode and print Zephyr packets.
*
* https://web.mit.edu/zephyr/doc/protocol
*
* Copyright (c) 2001 Nickolai Zeldovich <kolya@MIT.EDU>
* 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, 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.
* The name of the author(s) may not 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.
*/
/* \summary: Zephyr printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "netdissect-ctype.h"
#include "netdissect.h"
#include "extract.h"
struct z_packet {
const char *version;
int numfields;
int kind;
const char *uid;
int port;
int auth;
int authlen;
const char *authdata;
const char *class;
const char *inst;
const char *opcode;
const char *sender;
const char *recipient;
const char *format;
int cksum;
int multi;
const char *multi_uid;
/* Other fields follow here.. */
};
enum z_packet_type {
Z_PACKET_UNSAFE = 0,
Z_PACKET_UNACKED,
Z_PACKET_ACKED,
Z_PACKET_HMACK,
Z_PACKET_HMCTL,
Z_PACKET_SERVACK,
Z_PACKET_SERVNAK,
Z_PACKET_CLIENTACK,
Z_PACKET_STAT
};
static const struct tok z_types[] = {
{ Z_PACKET_UNSAFE, "unsafe" },
{ Z_PACKET_UNACKED, "unacked" },
{ Z_PACKET_ACKED, "acked" },
{ Z_PACKET_HMACK, "hm-ack" },
{ Z_PACKET_HMCTL, "hm-ctl" },
{ Z_PACKET_SERVACK, "serv-ack" },
{ Z_PACKET_SERVNAK, "serv-nak" },
{ Z_PACKET_CLIENTACK, "client-ack" },
{ Z_PACKET_STAT, "stat" },
{ 0, NULL }
};
static char z_buf[256];
static const char *
parse_field(netdissect_options *ndo, const char **pptr, int *len)
{
const char *s;
/* Start of string */
s = *pptr;
/* Scan for the NUL terminator */
for (;;) {
if (*len == 0) {
/* Ran out of packet data without finding it */
return NULL;
}
if (GET_U_1(*pptr) == '\0') {
/* Found it */
break;
}
/* Keep scanning */
(*pptr)++;
(*len)--;
}
/* Skip the NUL terminator */
(*pptr)++;
(*len)--;
return s;
}
static const char *
z_triple(const char *class, const char *inst, const char *recipient)
{
if (!*recipient)
recipient = "*";
snprintf(z_buf, sizeof(z_buf), "<%s,%s,%s>", class, inst, recipient);
z_buf[sizeof(z_buf)-1] = '\0';
return z_buf;
}
static const char *
str_to_lower(const char *string)
{
char *zb_string;
strncpy(z_buf, string, sizeof(z_buf));
z_buf[sizeof(z_buf)-1] = '\0';
zb_string = z_buf;
while (*zb_string) {
*zb_string = ND_ASCII_TOLOWER(*zb_string);
zb_string++;
}
return z_buf;
}
#define ZEPHYR_PRINT(str1,str2) \
{ ND_PRINT("%s", (str1)); fn_print_str(ndo, (const u_char *)(str2)); }
void
zephyr_print(netdissect_options *ndo, const u_char *cp, u_int length)
{
struct z_packet z = {
NULL, /* version */
0, /* numfields */
0, /* kind */
NULL, /* uid */
0, /* port */
0, /* auth */
0, /* authlen */
NULL, /* authdata */
NULL, /* class */
NULL, /* inst */
NULL, /* opcode */
NULL, /* sender */
NULL, /* recipient */
NULL, /* format */
0, /* cksum */
0, /* multi */
NULL /* multi_uid */
};
const char *parse = (const char *) cp;
int parselen = length;
const char *s;
int lose = 0;
ndo->ndo_protocol = "zephyr";
/* squelch compiler warnings */
#define PARSE_STRING \
s = parse_field(ndo, &parse, &parselen); \
if (!s) lose = 1;
#define PARSE_FIELD_INT(field) \
PARSE_STRING \
if (!lose) field = strtol(s, 0, 16);
#define PARSE_FIELD_STR(field) \
PARSE_STRING \
if (!lose) field = s;
PARSE_FIELD_STR(z.version);
if (lose)
goto invalid;
if (strncmp(z.version, "ZEPH", 4))
return;
PARSE_FIELD_INT(z.numfields);
PARSE_FIELD_INT(z.kind);
PARSE_FIELD_STR(z.uid);
PARSE_FIELD_INT(z.port);
PARSE_FIELD_INT(z.auth);
PARSE_FIELD_INT(z.authlen);
PARSE_FIELD_STR(z.authdata);
PARSE_FIELD_STR(z.class);
PARSE_FIELD_STR(z.inst);
PARSE_FIELD_STR(z.opcode);
PARSE_FIELD_STR(z.sender);
PARSE_FIELD_STR(z.recipient);
PARSE_FIELD_STR(z.format);
PARSE_FIELD_INT(z.cksum);
PARSE_FIELD_INT(z.multi);
PARSE_FIELD_STR(z.multi_uid);
if (lose)
goto invalid;
ND_PRINT(" zephyr");
if (strncmp(z.version+4, "0.2", 3)) {
ZEPHYR_PRINT(" v", z.version+4)
return;
}
ND_PRINT(" %s", tok2str(z_types, "type %d", z.kind));
if (z.kind == Z_PACKET_SERVACK) {
/* Initialization to silence warnings */
const char *ackdata = NULL;
PARSE_FIELD_STR(ackdata);
if (!lose && strcmp(ackdata, "SENT"))
ZEPHYR_PRINT("/", str_to_lower(ackdata))
}
if (*z.sender) ZEPHYR_PRINT(" ", z.sender);
if (!strcmp(z.class, "USER_LOCATE")) {
if (!strcmp(z.opcode, "USER_HIDE"))
ND_PRINT(" hide");
else if (!strcmp(z.opcode, "USER_UNHIDE"))
ND_PRINT(" unhide");
else
ZEPHYR_PRINT(" locate ", z.inst);
return;
}
if (!strcmp(z.class, "ZEPHYR_ADMIN")) {
ZEPHYR_PRINT(" zephyr-admin ", str_to_lower(z.opcode));
return;
}
if (!strcmp(z.class, "ZEPHYR_CTL")) {
if (!strcmp(z.inst, "CLIENT")) {
if (!strcmp(z.opcode, "SUBSCRIBE") ||
!strcmp(z.opcode, "SUBSCRIBE_NODEFS") ||
!strcmp(z.opcode, "UNSUBSCRIBE")) {
ND_PRINT(" %ssub%s", strcmp(z.opcode, "SUBSCRIBE") ? "un" : "",
strcmp(z.opcode, "SUBSCRIBE_NODEFS") ? "" :
"-nodefs");
if (z.kind != Z_PACKET_SERVACK) {
/* Initialization to silence warnings */
const char *c = NULL, *i = NULL, *r = NULL;
PARSE_FIELD_STR(c);
PARSE_FIELD_STR(i);
PARSE_FIELD_STR(r);
if (!lose) ZEPHYR_PRINT(" ", z_triple(c, i, r));
}
return;
}
if (!strcmp(z.opcode, "GIMME")) {
ND_PRINT(" ret");
return;
}
if (!strcmp(z.opcode, "GIMMEDEFS")) {
ND_PRINT(" gimme-defs");
return;
}
if (!strcmp(z.opcode, "CLEARSUB")) {
ND_PRINT(" clear-subs");
return;
}
ZEPHYR_PRINT(" ", str_to_lower(z.opcode));
return;
}
if (!strcmp(z.inst, "HM")) {
ZEPHYR_PRINT(" ", str_to_lower(z.opcode));
return;
}
if (!strcmp(z.inst, "REALM")) {
if (!strcmp(z.opcode, "ADD_SUBSCRIBE"))
ND_PRINT(" realm add-subs");
if (!strcmp(z.opcode, "REQ_SUBSCRIBE"))
ND_PRINT(" realm req-subs");
if (!strcmp(z.opcode, "RLM_SUBSCRIBE"))
ND_PRINT(" realm rlm-sub");
if (!strcmp(z.opcode, "RLM_UNSUBSCRIBE"))
ND_PRINT(" realm rlm-unsub");
return;
}
}
if (!strcmp(z.class, "HM_CTL")) {
ZEPHYR_PRINT(" hm_ctl ", str_to_lower(z.inst));
ZEPHYR_PRINT(" ", str_to_lower(z.opcode));
return;
}
if (!strcmp(z.class, "HM_STAT")) {
if (!strcmp(z.inst, "HMST_CLIENT") && !strcmp(z.opcode, "GIMMESTATS")) {
ND_PRINT(" get-client-stats");
return;
}
}
if (!strcmp(z.class, "WG_CTL")) {
ZEPHYR_PRINT(" wg_ctl ", str_to_lower(z.inst));
ZEPHYR_PRINT(" ", str_to_lower(z.opcode));
return;
}
if (!strcmp(z.class, "LOGIN")) {
if (!strcmp(z.opcode, "USER_FLUSH")) {
ND_PRINT(" flush_locs");
return;
}
if (!strcmp(z.opcode, "NONE") ||
!strcmp(z.opcode, "OPSTAFF") ||
!strcmp(z.opcode, "REALM-VISIBLE") ||
!strcmp(z.opcode, "REALM-ANNOUNCED") ||
!strcmp(z.opcode, "NET-VISIBLE") ||
!strcmp(z.opcode, "NET-ANNOUNCED")) {
ZEPHYR_PRINT(" set-exposure ", str_to_lower(z.opcode));
return;
}
}
if (!*z.recipient)
z.recipient = "*";
ZEPHYR_PRINT(" to ", z_triple(z.class, z.inst, z.recipient));
if (*z.opcode)
ZEPHYR_PRINT(" op ", z.opcode);
return;
invalid:
nd_print_invalid(ndo);
}
diff --git a/contrib/tcpdump/print-zeromq.c b/contrib/tcpdump/print-zeromq.c
index c702046822b1..820104758a2b 100644
--- a/contrib/tcpdump/print-zeromq.c
+++ b/contrib/tcpdump/print-zeromq.c
@@ -1,215 +1,217 @@
/*
* Copyright (c) 2013 The TCPDUMP project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* \summary: ZeroMQ Message Transport Protocol (ZMTP) printer */
+/* specification: https://rfc.zeromq.org/spec/13/ */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "extract.h"
/* Maximum number of ZMTP/1.0 frame body bytes (without the flags) to dump in
* hex and ASCII under a single "-v" flag.
*/
#define VBYTES 128
+static const struct tok flags_bm[] = {
+ { 0x01, "MORE" },
+ { 0x02, "R1" },
+ { 0x04, "R2" },
+ { 0x08, "R3" },
+ { 0x10, "R4" },
+ { 0x20, "R5" },
+ { 0x40, "R6" },
+ { 0x80, "R7" },
+ { 0, NULL }
+};
+
/*
* Below is an excerpt from the "13/ZMTP" specification:
*
* A ZMTP message consists of 1 or more frames.
*
* A ZMTP frame consists of a length, followed by a flags field and a frame
* body of (length - 1) octets. Note: the length includes the flags field, so
* an empty frame has a length of 1.
*
* For frames with a length of 1 to 254 octets, the length SHOULD BE encoded
* as a single octet. The minimum valid length of a frame is 1 octet, thus a
* length of 0 is invalid and such frames SHOULD be discarded silently.
*
* For frames with lengths of 255 and greater, the length SHALL BE encoded as
* a single octet with the value 255, followed by the length encoded as a
* 64-bit unsigned integer in network byte order. For frames with lengths of
* 1 to 254 octets this encoding MAY be also used.
*
* The flags field consists of a single octet containing various control
* flags. Bit 0 is the least significant bit.
*
* - Bit 0 (MORE): More frames to follow. A value of 0 indicates that there
* are no more frames to follow. A value of 1 indicates that more frames
* will follow. On messages consisting of a single frame the MORE flag MUST
* be 0.
*
* - Bits 1-7: Reserved. Bits 1-7 are reserved for future use and SHOULD be
* zero.
*/
static const u_char *
zmtp1_print_frame(netdissect_options *ndo, const u_char *cp, const u_char *ep)
{
uint64_t body_len_declared, body_len_captured, header_len;
uint8_t flags;
ND_PRINT("\n\t");
if (GET_U_1(cp) != 0xFF) { /* length/0xFF */
header_len = 1; /* length */
body_len_declared = GET_U_1(cp);
ND_PRINT(" frame flags+body (8-bit) length %" PRIu64, body_len_declared);
} else {
header_len = 1 + 8; /* 0xFF, length */
ND_PRINT(" frame flags+body (64-bit) length");
ND_TCHECK_LEN(cp, header_len); /* 0xFF, length */
body_len_declared = GET_BE_U_8(cp + 1);
ND_PRINT(" %" PRIu64, body_len_declared);
}
if (body_len_declared == 0)
return cp + header_len; /* skip to the next frame */
ND_TCHECK_LEN(cp, header_len + 1); /* ..., flags */
flags = GET_U_1(cp + header_len);
body_len_captured = ep - cp - header_len;
if (body_len_declared > body_len_captured)
ND_PRINT(" (%" PRIu64 " captured)", body_len_captured);
ND_PRINT(", flags 0x%02x", flags);
if (ndo->ndo_vflag) {
uint64_t body_len_printed = ND_MIN(body_len_captured, body_len_declared);
- ND_PRINT(" (%s|%s|%s|%s|%s|%s|%s|%s)",
- flags & 0x80 ? "MBZ" : "-",
- flags & 0x40 ? "MBZ" : "-",
- flags & 0x20 ? "MBZ" : "-",
- flags & 0x10 ? "MBZ" : "-",
- flags & 0x08 ? "MBZ" : "-",
- flags & 0x04 ? "MBZ" : "-",
- flags & 0x02 ? "MBZ" : "-",
- flags & 0x01 ? "MORE" : "-");
-
+ ND_PRINT(" (%s)", bittok2str(flags_bm, "none", flags));
if (ndo->ndo_vflag == 1)
body_len_printed = ND_MIN(VBYTES + 1, body_len_printed);
if (body_len_printed > 1) {
ND_PRINT(", first %" PRIu64 " byte(s) of body:", body_len_printed - 1);
hex_and_ascii_print(ndo, "\n\t ", cp + header_len + 1, body_len_printed - 1);
}
}
/*
* Do not advance cp by the sum of header_len and body_len_declared
* before each offset has successfully passed ND_TCHECK_LEN() as the
* sum can roll over (9 + 0xfffffffffffffff7 = 0) and cause an
* infinite loop.
*/
cp += header_len;
ND_TCHECK_LEN(cp, body_len_declared); /* Next frame within the buffer ? */
return cp + body_len_declared;
trunc:
nd_trunc_longjmp(ndo);
}
void
zmtp1_print(netdissect_options *ndo, const u_char *cp, u_int len)
{
const u_char *ep = ND_MIN(ndo->ndo_snapend, cp + len);
ndo->ndo_protocol = "zmtp1";
ND_PRINT(": ZMTP/1.0");
while (cp < ep)
cp = zmtp1_print_frame(ndo, cp, ep);
}
/* The functions below decode a ZeroMQ datagram, supposedly stored in the "Data"
* field of an ODATA/RDATA [E]PGM packet. An excerpt from zmq_pgm(7) man page
* follows.
*
* In order for late joining consumers to be able to identify message
* boundaries, each PGM datagram payload starts with a 16-bit unsigned integer
* in network byte order specifying either the offset of the first message frame
* in the datagram or containing the value 0xFFFF if the datagram contains
* solely an intermediate part of a larger message.
*
* Note that offset specifies where the first message begins rather than the
* first message part. Thus, if there are trailing message parts at the
* beginning of the packet the offset ignores them and points to first initial
* message part in the packet.
*/
static const u_char *
zmtp1_print_intermediate_part(netdissect_options *ndo, const u_char *cp, const u_int len)
{
u_int frame_offset;
u_int remaining_len;
frame_offset = GET_BE_U_2(cp);
ND_PRINT("\n\t frame offset 0x%04x", frame_offset);
cp += 2;
remaining_len = ND_BYTES_AVAILABLE_AFTER(cp); /* without the frame length */
if (frame_offset == 0xFFFF)
frame_offset = len - 2; /* always within the declared length */
else if (2 + frame_offset > len) {
ND_PRINT(" (exceeds datagram declared length)");
goto trunc;
}
/* offset within declared length of the datagram */
if (frame_offset) {
ND_PRINT("\n\t frame intermediate part, %u bytes", frame_offset);
if (frame_offset > remaining_len)
ND_PRINT(" (%u captured)", remaining_len);
if (ndo->ndo_vflag) {
u_int len_printed = ND_MIN(frame_offset, remaining_len);
if (ndo->ndo_vflag == 1)
len_printed = ND_MIN(VBYTES, len_printed);
if (len_printed > 1) {
ND_PRINT(", first %u byte(s):", len_printed);
hex_and_ascii_print(ndo, "\n\t ", cp, len_printed);
}
}
}
return cp + frame_offset;
trunc:
nd_trunc_longjmp(ndo);
}
void
zmtp1_datagram_print(netdissect_options *ndo, const u_char *cp, const u_int len)
{
const u_char *ep = ND_MIN(ndo->ndo_snapend, cp + len);
ndo->ndo_protocol = "zmtp1";
cp = zmtp1_print_intermediate_part(ndo, cp, len);
while (cp < ep)
cp = zmtp1_print_frame(ndo, cp, ep);
}
diff --git a/contrib/tcpdump/print.c b/contrib/tcpdump/print.c
index 96d34b772f08..9f7969e539cf 100644
--- a/contrib/tcpdump/print.c
+++ b/contrib/tcpdump/print.c
@@ -1,580 +1,590 @@
/*
* 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 <swebster@sst.ll.mit.edu>
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "addrtoname.h"
#include "print.h"
#include "netdissect-alloc.h"
#include "pcap-missing.h"
struct printer {
if_printer f;
int type;
};
static const struct printer printers[] = {
#ifdef DLT_APPLE_IP_OVER_IEEE1394
{ ap1394_if_print, DLT_APPLE_IP_OVER_IEEE1394 },
#endif
{ arcnet_if_print, DLT_ARCNET },
#ifdef DLT_ARCNET_LINUX
{ arcnet_linux_if_print, DLT_ARCNET_LINUX },
#endif
{ atm_if_print, DLT_ATM_RFC1483 },
#ifdef DLT_DSA_TAG_BRCM
{ brcm_tag_if_print, DLT_DSA_TAG_BRCM },
#endif
#ifdef DLT_DSA_TAG_BRCM_PREPEND
{ brcm_tag_prepend_if_print, DLT_DSA_TAG_BRCM_PREPEND },
#endif
#ifdef DLT_BLUETOOTH_HCI_H4_WITH_PHDR
{ bt_if_print, DLT_BLUETOOTH_HCI_H4_WITH_PHDR},
#endif
#ifdef DLT_C_HDLC
{ chdlc_if_print, DLT_C_HDLC },
#endif
#ifdef DLT_HDLC
{ chdlc_if_print, DLT_HDLC },
#endif
#ifdef DLT_ATM_CLIP
{ cip_if_print, DLT_ATM_CLIP },
#endif
#ifdef DLT_CIP
{ cip_if_print, DLT_CIP },
#endif
#ifdef DLT_DSA_TAG_DSA
{ dsa_if_print, DLT_DSA_TAG_DSA },
#endif
#ifdef DLT_DSA_TAG_EDSA
{ edsa_if_print, DLT_DSA_TAG_EDSA },
#endif
#ifdef DLT_ENC
{ enc_if_print, DLT_ENC },
#endif
{ ether_if_print, DLT_EN10MB },
{ fddi_if_print, DLT_FDDI },
#ifdef DLT_FR
{ fr_if_print, DLT_FR },
#endif
#ifdef DLT_FRELAY
{ fr_if_print, DLT_FRELAY },
#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_IEEE802_11_RADIO
{ ieee802_11_radio_if_print, DLT_IEEE802_11_RADIO },
#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_IEEE802_15_4_TAP
{ ieee802_15_4_tap_if_print, DLT_IEEE802_15_4_TAP },
#endif
#ifdef DLT_IP_OVER_FC
{ ipfc_if_print, DLT_IP_OVER_FC },
#endif
#ifdef DLT_IPNET
{ ipnet_if_print, DLT_IPNET },
#endif
#ifdef DLT_IPOIB
{ ipoib_if_print, DLT_IPOIB },
#endif
#ifdef DLT_JUNIPER_ATM1
{ juniper_atm1_if_print, DLT_JUNIPER_ATM1 },
#endif
#ifdef DLT_JUNIPER_ATM2
{ juniper_atm2_if_print, DLT_JUNIPER_ATM2 },
#endif
#ifdef DLT_JUNIPER_CHDLC
{ juniper_chdlc_if_print, DLT_JUNIPER_CHDLC },
#endif
#ifdef DLT_JUNIPER_ES
{ juniper_es_if_print, DLT_JUNIPER_ES },
#endif
#ifdef DLT_JUNIPER_ETHER
{ juniper_ether_if_print, DLT_JUNIPER_ETHER },
#endif
#ifdef DLT_JUNIPER_FRELAY
{ juniper_frelay_if_print, DLT_JUNIPER_FRELAY },
#endif
#ifdef DLT_JUNIPER_GGSN
{ juniper_ggsn_if_print, DLT_JUNIPER_GGSN },
#endif
#ifdef DLT_JUNIPER_MFR
{ juniper_mfr_if_print, DLT_JUNIPER_MFR },
#endif
#ifdef DLT_JUNIPER_MLFR
{ juniper_mlfr_if_print, DLT_JUNIPER_MLFR },
#endif
#ifdef DLT_JUNIPER_MLPPP
{ juniper_mlppp_if_print, DLT_JUNIPER_MLPPP },
#endif
#ifdef DLT_JUNIPER_MONITOR
{ juniper_monitor_if_print, DLT_JUNIPER_MONITOR },
#endif
#ifdef DLT_JUNIPER_PPP
{ juniper_ppp_if_print, DLT_JUNIPER_PPP },
#endif
#ifdef DLT_JUNIPER_PPPOE_ATM
{ juniper_pppoe_atm_if_print, DLT_JUNIPER_PPPOE_ATM },
#endif
#ifdef DLT_JUNIPER_PPPOE
{ juniper_pppoe_if_print, DLT_JUNIPER_PPPOE },
#endif
#ifdef DLT_JUNIPER_SERVICES
{ juniper_services_if_print, DLT_JUNIPER_SERVICES },
#endif
#ifdef DLT_LTALK
{ ltalk_if_print, DLT_LTALK },
#endif
#ifdef DLT_MFR
{ mfr_if_print, DLT_MFR },
#endif
#ifdef DLT_NETANALYZER
{ netanalyzer_if_print, DLT_NETANALYZER },
#endif
#ifdef DLT_NETANALYZER_TRANSPARENT
{ netanalyzer_transparent_if_print, DLT_NETANALYZER_TRANSPARENT },
#endif
#ifdef DLT_NFLOG
{ nflog_if_print, DLT_NFLOG},
#endif
{ null_if_print, DLT_NULL },
#ifdef DLT_LOOP
{ null_if_print, DLT_LOOP },
#endif
#if defined(DLT_PFLOG) && defined(HAVE_NET_IF_PFLOG_H)
{ pflog_if_print, DLT_PFLOG },
#endif
#if defined(DLT_PFSYNC) && defined(HAVE_NET_PFVAR_H)
{ pfsync_if_print, DLT_PFSYNC},
#endif
#ifdef DLT_PKTAP
{ pktap_if_print, DLT_PKTAP },
#endif
#ifdef DLT_PPI
{ ppi_if_print, DLT_PPI },
#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
{ ppp_if_print, DLT_PPP },
#ifdef DLT_PPP_PPPD
{ ppp_if_print, DLT_PPP_PPPD },
#endif
#ifdef DLT_PPP_ETHER
{ pppoe_if_print, DLT_PPP_ETHER },
#endif
#ifdef DLT_PRISM_HEADER
{ prism_if_print, DLT_PRISM_HEADER },
#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 DLT_SLIP_BSDOS
{ sl_bsdos_if_print, DLT_SLIP_BSDOS },
#endif
{ sl_if_print, DLT_SLIP },
#ifdef DLT_LINUX_SLL
{ sll_if_print, DLT_LINUX_SLL },
#endif
#ifdef DLT_LINUX_SLL2
{ sll2_if_print, DLT_LINUX_SLL2 },
#endif
#ifdef DLT_SUNATM
{ sunatm_if_print, DLT_SUNATM },
#endif
#ifdef DLT_SYMANTEC_FIREWALL
{ symantec_if_print, DLT_SYMANTEC_FIREWALL },
#endif
{ token_if_print, DLT_IEEE802 },
#ifdef DLT_USB_LINUX
{ usb_linux_48_byte_if_print, DLT_USB_LINUX},
#endif /* DLT_USB_LINUX */
#ifdef DLT_USB_LINUX_MMAPPED
{ usb_linux_64_byte_if_print, DLT_USB_LINUX_MMAPPED},
#endif /* DLT_USB_LINUX_MMAPPED */
#ifdef DLT_VSOCK
{ vsock_if_print, DLT_VSOCK },
#endif
{ NULL, 0 },
};
static void ndo_default_print(netdissect_options *ndo, const u_char *bp,
u_int length);
static void NORETURN ndo_error(netdissect_options *ndo,
status_exit_codes_t status,
FORMAT_STRING(const char *fmt), ...)
PRINTFLIKE(3, 4);
static void ndo_warning(netdissect_options *ndo,
FORMAT_STRING(const char *fmt), ...)
PRINTFLIKE(2, 3);
static int ndo_printf(netdissect_options *ndo,
FORMAT_STRING(const char *fmt), ...)
PRINTFLIKE(2, 3);
void
init_print(netdissect_options *ndo, uint32_t localnet, uint32_t mask)
{
-
init_addrtoname(ndo, 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);
}
if_printer
get_if_printer(int type)
{
if_printer printer;
printer = lookup_printer(type);
if (printer == NULL)
printer = unsupported_if_print;
return printer;
}
+#ifdef ENABLE_INSTRUMENT_FUNCTIONS
+extern int profile_func_level;
+static int pretty_print_packet_level = -1;
+#endif
+
void
pretty_print_packet(netdissect_options *ndo, const struct pcap_pkthdr *h,
const u_char *sp, u_int packets_captured)
{
u_int hdrlen = 0;
int invalid_header = 0;
+#ifdef ENABLE_INSTRUMENT_FUNCTIONS
+ if (pretty_print_packet_level == -1)
+ pretty_print_packet_level = profile_func_level;
+#endif
+
if (ndo->ndo_packet_number)
ND_PRINT("%5u ", packets_captured);
/* Sanity checks on packet length / capture length */
if (h->caplen == 0) {
invalid_header = 1;
ND_PRINT("[Invalid header: caplen==0");
}
if (h->len == 0) {
if (!invalid_header) {
invalid_header = 1;
ND_PRINT("[Invalid header:");
} else
ND_PRINT(",");
ND_PRINT(" len==0");
} else if (h->len < h->caplen) {
if (!invalid_header) {
invalid_header = 1;
ND_PRINT("[Invalid header:");
} else
ND_PRINT(",");
ND_PRINT(" len(%u) < caplen(%u)", h->len, h->caplen);
}
if (h->caplen > MAXIMUM_SNAPLEN) {
if (!invalid_header) {
invalid_header = 1;
ND_PRINT("[Invalid header:");
} else
ND_PRINT(",");
ND_PRINT(" caplen(%u) > %u", h->caplen, MAXIMUM_SNAPLEN);
}
if (h->len > MAXIMUM_SNAPLEN) {
if (!invalid_header) {
invalid_header = 1;
ND_PRINT("[Invalid header:");
} else
ND_PRINT(",");
ND_PRINT(" len(%u) > %u", h->len, MAXIMUM_SNAPLEN);
}
if (invalid_header) {
ND_PRINT("]\n");
return;
}
/*
* At this point:
* capture length != 0,
* packet length != 0,
* capture length <= MAXIMUM_SNAPLEN,
* packet length <= MAXIMUM_SNAPLEN,
* packet length >= capture length.
*
* Currently, there is no D-Bus printer, thus no need for
* bigger lengths.
*/
/*
* The header /usr/include/pcap/pcap.h in OpenBSD declares h->ts as
* struct bpf_timeval, not struct timeval. The former comes from
* /usr/include/net/bpf.h and uses 32-bit unsigned types instead of
* the types used in struct timeval.
*/
struct timeval tvbuf;
tvbuf.tv_sec = h->ts.tv_sec;
tvbuf.tv_usec = h->ts.tv_usec;
ts_print(ndo, &tvbuf);
/*
* Printers must 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;
ndo->ndo_packetp = sp;
ndo->ndo_protocol = "";
ndo->ndo_ll_hdr_len = 0;
switch (setjmp(ndo->ndo_early_end)) {
case 0:
/* Print the packet. */
(ndo->ndo_if_printer)(ndo, h, sp);
break;
case ND_TRUNCATED:
/* A printer quit because the packet was truncated; report it */
nd_print_trunc(ndo);
/* Print the full packet */
ndo->ndo_ll_hdr_len = 0;
+#ifdef ENABLE_INSTRUMENT_FUNCTIONS
+ /* truncation => reassignment */
+ profile_func_level = pretty_print_packet_level;
+#endif
break;
}
hdrlen = ndo->ndo_ll_hdr_len;
/*
* Empty the stack of packet information, freeing all pushed buffers;
* if we got here by a printer quitting, we need to release anything
* that didn't get released because we longjmped out of the code
* before it popped the packet information.
*/
nd_pop_all_packet_info(ndo);
/*
* Restore the originals snapend and packetp, as a printer
* might have changed them.
*
* XXX - nd_pop_all_packet_info() should have restored the
* original values, but, just in case....
*/
ndo->ndo_snapend = sp + h->caplen;
ndo->ndo_packetp = sp;
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);
}
}
ND_PRINT("\n");
nd_free_all(ndo);
}
/*
* 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, status_exit_codes_t status,
const char *fmt, ...)
{
va_list ap;
if (ndo->program_name)
(void)fprintf(stderr, "%s: ", ndo->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);
}
nd_cleanup();
exit(status);
/* NOTREACHED */
}
/* VARARGS */
static void
ndo_warning(netdissect_options *ndo, const char *fmt, ...)
{
va_list ap;
if (ndo->program_name)
(void)fprintf(stderr, "%s: ", ndo->program_name);
(void)fprintf(stderr, "WARNING: ");
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
ndo_printf(netdissect_options *ndo, const char *fmt, ...)
{
va_list args;
int ret;
va_start(args, fmt);
ret = vfprintf(stdout, fmt, args);
va_end(args);
if (ret < 0)
ndo_error(ndo, S_ERR_ND_WRITE_FILE,
"Unable to write output: %s", pcap_strerror(errno));
return (ret);
}
void
ndo_set_function_pointers(netdissect_options *ndo)
{
ndo->ndo_default_print=ndo_default_print;
ndo->ndo_printf=ndo_printf;
ndo->ndo_error=ndo_error;
ndo->ndo_warning=ndo_warning;
}
diff --git a/contrib/tcpdump/signature.c b/contrib/tcpdump/signature.c
index 77d6e81ac3ab..f10a90b94ee9 100644
--- a/contrib/tcpdump/signature.c
+++ b/contrib/tcpdump/signature.c
@@ -1,208 +1,206 @@
/*
* 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.
*
* Functions for signature and digest verification.
*
* Original code by Hannes Gredler (hannes@gredler.at)
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <string.h>
#include <stdlib.h>
#include "netdissect.h"
#include "signature.h"
#include "diag-control.h"
#ifdef HAVE_LIBCRYPTO
#include <openssl/md5.h>
#endif
const struct tok signature_check_values[] = {
{ SIGNATURE_VALID, "valid"},
{ SIGNATURE_INVALID, "invalid"},
{ CANT_ALLOCATE_COPY, "can't allocate memory"},
{ CANT_CHECK_SIGNATURE, "unchecked"},
{ 0, NULL }
};
#ifdef HAVE_LIBCRYPTO
/*
* Compute a HMAC MD5 sum.
* Taken from rfc2104, Appendix.
*/
DIAG_OFF_DEPRECATION
static void
signature_compute_hmac_md5(const uint8_t *text, int text_len, unsigned char *key,
unsigned int key_len, uint8_t *digest)
{
MD5_CTX context;
unsigned char k_ipad[65]; /* inner padding - key XORd with ipad */
unsigned char k_opad[65]; /* outer padding - key XORd with opad */
unsigned char tk[16];
int i;
/* if key is longer than 64 bytes reset it to key=MD5(key) */
if (key_len > 64) {
MD5_CTX tctx;
MD5_Init(&tctx);
MD5_Update(&tctx, key, key_len);
MD5_Final(tk, &tctx);
key = tk;
key_len = 16;
}
/*
* the HMAC_MD5 transform looks like:
*
* MD5(K XOR opad, MD5(K XOR ipad, text))
*
* where K is an n byte key
* ipad is the byte 0x36 repeated 64 times
* opad is the byte 0x5c repeated 64 times
* and text is the data being protected
*/
/* start out by storing key in pads */
memset(k_ipad, 0, sizeof(k_ipad));
memset(k_opad, 0, sizeof(k_opad));
memcpy(k_ipad, key, key_len);
memcpy(k_opad, key, key_len);
/* XOR key with ipad and opad values */
for (i=0; i<64; i++) {
k_ipad[i] ^= 0x36;
k_opad[i] ^= 0x5c;
}
/*
* perform inner MD5
*/
MD5_Init(&context); /* init context for 1st pass */
MD5_Update(&context, k_ipad, 64); /* start with inner pad */
MD5_Update(&context, text, text_len); /* then text of datagram */
MD5_Final(digest, &context); /* finish up 1st pass */
/*
* perform outer MD5
*/
MD5_Init(&context); /* init context for 2nd pass */
MD5_Update(&context, k_opad, 64); /* start with outer pad */
MD5_Update(&context, digest, 16); /* then results of 1st hash */
MD5_Final(digest, &context); /* finish up 2nd pass */
}
DIAG_ON_DEPRECATION
/*
* Verify a cryptographic signature of the packet.
* Currently only MD5 is supported.
*/
int
signature_verify(netdissect_options *ndo, const u_char *pptr, u_int plen,
const u_char *sig_ptr, void (*clear_rtn)(void *),
const void *clear_arg)
{
uint8_t *packet_copy, *sig_copy;
uint8_t sig[16];
unsigned int i;
if (!ndo->ndo_sigsecret) {
return (CANT_CHECK_SIGNATURE);
}
/*
* Do we have all the packet data to be checked?
*/
if (!ND_TTEST_LEN(pptr, plen)) {
/* No. */
return (CANT_CHECK_SIGNATURE);
}
/*
* Do we have the entire signature to check?
*/
if (!ND_TTEST_LEN(sig_ptr, sizeof(sig))) {
/* No. */
return (CANT_CHECK_SIGNATURE);
}
if (sig_ptr + sizeof(sig) > pptr + plen) {
/* No. */
return (CANT_CHECK_SIGNATURE);
}
/*
* Make a copy of the packet, so we don't overwrite the original.
*/
packet_copy = malloc(plen);
if (packet_copy == NULL) {
return (CANT_ALLOCATE_COPY);
}
memcpy(packet_copy, pptr, plen);
/*
* Clear the signature in the copy.
*/
sig_copy = packet_copy + (sig_ptr - pptr);
memset(sig_copy, 0, sizeof(sig));
/*
* Clear anything else that needs to be cleared in the copy.
* Our caller is assumed to have vetted the clear_arg pointer.
*/
(*clear_rtn)((void *)(packet_copy + ((const uint8_t *)clear_arg - pptr)));
/*
* Compute the signature.
*/
signature_compute_hmac_md5(packet_copy, plen,
(unsigned char *)ndo->ndo_sigsecret,
strlen(ndo->ndo_sigsecret), sig);
/*
* Free the copy.
*/
free(packet_copy);
/*
* Does the computed signature match the signature in the packet?
*/
if (memcmp(sig_ptr, sig, sizeof(sig)) == 0) {
/* Yes. */
return (SIGNATURE_VALID);
} else {
/* No - print the computed signature. */
for (i = 0; i < sizeof(sig); ++i) {
ND_PRINT("%02x", sig[i]);
}
return (SIGNATURE_INVALID);
}
}
#else
int
signature_verify(netdissect_options *ndo _U_, const u_char *pptr _U_,
u_int plen _U_, const u_char *sig_ptr _U_,
void (*clear_rtn)(void *) _U_, const void *clear_arg _U_)
{
return (CANT_CHECK_SIGNATURE);
}
#endif
diff --git a/contrib/tcpdump/smbutil.c b/contrib/tcpdump/smbutil.c
index 97217a8d9fc6..fa5e133fa2a8 100644
--- a/contrib/tcpdump/smbutil.c
+++ b/contrib/tcpdump/smbutil.c
@@ -1,1968 +1,1967 @@
/*
* Copyright (C) Andrew Tridgell 1995-1999
*
* This software may be distributed either under the terms of the
* BSD-style license that accompanies tcpdump or the GNU GPL version 2
* or later
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "netdissect-ctype.h"
#include "netdissect.h"
#include "extract.h"
#include "smb.h"
static int stringlen_is_set;
static uint32_t stringlen;
extern const u_char *startbuf;
/*
* Reset SMB state.
*/
void
smb_reset(void)
{
stringlen_is_set = 0;
stringlen = 0;
}
/*
* interpret a 32 bit dos packed date/time to some parameters
*/
static void
interpret_dos_date(uint32_t date, struct tm *tp)
{
uint32_t p0, p1, p2, p3;
p0 = date & 0xFF;
p1 = ((date & 0xFF00) >> 8) & 0xFF;
p2 = ((date & 0xFF0000) >> 16) & 0xFF;
p3 = ((date & 0xFF000000) >> 24) & 0xFF;
tp->tm_sec = 2 * (p0 & 0x1F);
tp->tm_min = ((p0 >> 5) & 0xFF) + ((p1 & 0x7) << 3);
tp->tm_hour = (p1 >> 3) & 0xFF;
tp->tm_mday = (p2 & 0x1F);
tp->tm_mon = ((p2 >> 5) & 0xFF) + ((p3 & 0x1) << 3) - 1;
tp->tm_year = ((p3 >> 1) & 0xFF) + 80;
}
/*
* common portion:
* create a unix date from a dos date
*/
static time_t
int_unix_date(uint32_t dos_date)
{
struct tm t;
if (dos_date == 0)
return(0);
interpret_dos_date(dos_date, &t);
t.tm_wday = 1;
t.tm_yday = 1;
t.tm_isdst = 0;
return (mktime(&t));
}
/*
* create a unix date from a dos date
* in network byte order
*/
static time_t
make_unix_date(netdissect_options *ndo, const u_char *date_ptr)
{
uint32_t dos_date = 0;
dos_date = GET_LE_U_4(date_ptr);
return int_unix_date(dos_date);
}
/*
* create a unix date from a dos date
* in halfword-swapped network byte order!
*/
static time_t
make_unix_date2(netdissect_options *ndo, const u_char *date_ptr)
{
uint32_t x, x2;
x = GET_LE_U_4(date_ptr);
x2 = ((x & 0xFFFF) << 16) | ((x & 0xFFFF0000) >> 16);
return int_unix_date(x2);
}
/*
* interpret an 8 byte "filetime" structure to a time_t
* It's originally in "100ns units since jan 1st 1601"
*/
static time_t
interpret_long_date(netdissect_options *ndo, const u_char *p)
{
double d;
time_t ret;
/* this gives us seconds since jan 1st 1601 (approx) */
d = (GET_LE_U_4(p + 4) * 256.0 + GET_U_1(p + 3)) * (1.0e-7 * (1 << 24));
/* now adjust by 369 years to make the secs since 1970 */
d -= 369.0 * 365.25 * 24 * 60 * 60;
/* and a fudge factor as we got it wrong by a few days */
d += (3 * 24 * 60 * 60 + 6 * 60 * 60 + 2);
if (d < 0)
return(0);
ret = (time_t)d;
return(ret);
}
/*
* interpret the weird netbios "name". Return the name type, or -1 if
* we run past the end of the buffer
*/
static int
name_interpret(netdissect_options *ndo,
const u_char *in, const u_char *maxbuf, char *out)
{
int ret;
u_int len;
if (in >= maxbuf)
return(-1); /* name goes past the end of the buffer */
len = GET_U_1(in) / 2;
in++;
*out=0;
if (len > 30 || len == 0)
return(0);
while (len) {
ND_TCHECK_2(in);
if (in + 1 >= maxbuf)
return(-1); /* name goes past the end of the buffer */
if (GET_U_1(in) < 'A' || GET_U_1(in) > 'P' ||
GET_U_1(in + 1) < 'A' || GET_U_1(in + 1) > 'P') {
*out = 0;
return(0);
}
*out = ((GET_U_1(in) - 'A') << 4) + (GET_U_1(in + 1) - 'A');
in += 2;
out++;
len--;
}
*out = 0;
ret = out[-1];
return(ret);
trunc:
return(-1);
}
/*
* find a pointer to a netbios name
*/
static const u_char *
name_ptr(netdissect_options *ndo,
const u_char *buf, u_int ofs, const u_char *maxbuf)
{
const u_char *p;
u_char c;
p = buf + ofs;
if (p >= maxbuf)
return(NULL); /* name goes past the end of the buffer */
c = GET_U_1(p);
/* XXX - this should use the same code that the DNS dissector does */
if ((c & 0xC0) == 0xC0) {
uint16_t l;
ND_TCHECK_2(p);
if ((p + 1) >= maxbuf)
return(NULL); /* name goes past the end of the buffer */
l = GET_BE_U_2(p) & 0x3FFF;
if (l == 0) {
/* We have a pointer that points to itself. */
return(NULL);
}
p = buf + l;
if (p >= maxbuf)
return(NULL); /* name goes past the end of the buffer */
ND_TCHECK_1(p);
}
return(p);
trunc:
return(NULL); /* name goes past the end of the buffer */
}
/*
* extract a netbios name from a buf
*/
static int
name_extract(netdissect_options *ndo,
const u_char *buf, u_int ofs, const u_char *maxbuf, char *name)
{
const u_char *p = name_ptr(ndo, buf, ofs, maxbuf);
if (p == NULL)
return(-1); /* error (probably name going past end of buffer) */
name[0] = '\0';
return(name_interpret(ndo, p, maxbuf, name));
}
/*
* return the total storage length of a mangled name
*/
static int
name_len(netdissect_options *ndo,
const u_char *s, const u_char *maxbuf)
{
const u_char *s0 = s;
unsigned char c;
if (s >= maxbuf)
return(-1); /* name goes past the end of the buffer */
c = GET_U_1(s);
if ((c & 0xC0) == 0xC0)
return(2);
while (GET_U_1(s)) {
if (s >= maxbuf)
return(-1); /* name goes past the end of the buffer */
s += GET_U_1(s) + 1;
ND_TCHECK_1(s);
}
- return(ND_BYTES_BETWEEN(s, s0) + 1);
+ return(ND_BYTES_BETWEEN(s0, s) + 1);
trunc:
return(-1); /* name goes past the end of the buffer */
}
static void
print_asc(netdissect_options *ndo,
const u_char *buf, u_int len)
{
u_int i;
for (i = 0; i < len; i++)
fn_print_char(ndo, GET_U_1(buf + i));
}
static const char *
name_type_str(int name_type)
{
const char *f = NULL;
switch (name_type) {
case 0: f = "Workstation"; break;
case 0x03: f = "Client?"; break;
case 0x20: f = "Server"; break;
case 0x1d: f = "Master Browser"; break;
case 0x1b: f = "Domain Controller"; break;
case 0x1e: f = "Browser Server"; break;
default: f = "Unknown"; break;
}
return(f);
}
void
smb_data_print(netdissect_options *ndo, const u_char *buf, u_int len)
{
u_int i = 0;
if (len == 0)
return;
ND_PRINT("[%03X] ", i);
for (i = 0; i < len; /*nothing*/) {
ND_PRINT("%02X ", GET_U_1(buf + i) & 0xff);
i++;
if (i%8 == 0)
ND_PRINT(" ");
if (i % 16 == 0) {
print_asc(ndo, buf + i - 16, 8);
ND_PRINT(" ");
print_asc(ndo, buf + i - 8, 8);
ND_PRINT("\n");
if (i < len)
ND_PRINT("[%03X] ", i);
}
}
if (i % 16) {
int n;
n = 16 - (i % 16);
ND_PRINT(" ");
if (n>8)
ND_PRINT(" ");
while (n--)
ND_PRINT(" ");
n = ND_MIN(8, i % 16);
print_asc(ndo, buf + i - (i % 16), n);
ND_PRINT(" ");
n = (i % 16) - n;
if (n > 0)
print_asc(ndo, buf + i - n, n);
ND_PRINT("\n");
}
}
static void
write_bits(netdissect_options *ndo,
unsigned int val, const char *fmt)
{
const char *p = fmt;
u_int i = 0;
while ((p = strchr(fmt, '|'))) {
- u_int l = ND_BYTES_BETWEEN(p, fmt);
+ u_int l = ND_BYTES_BETWEEN(fmt, p);
if (l && (val & (1 << i)))
ND_PRINT("%.*s ", (int)l, fmt);
fmt = p + 1;
i++;
}
}
/* convert a UCS-2 string into an ASCII string */
#define MAX_UNISTR_SIZE 1000
static const u_char *
unistr(netdissect_options *ndo, char (*buf)[MAX_UNISTR_SIZE+1],
const u_char *s, uint32_t strsize, int is_null_terminated,
int use_unicode)
{
u_int c;
size_t l = 0;
const u_char *sp;
if (use_unicode) {
/*
* Skip padding that puts the string on an even boundary.
*/
if (((s - startbuf) % 2) != 0) {
ND_TCHECK_1(s);
s++;
}
}
if (is_null_terminated) {
/*
* Null-terminated string.
* Find the length, counting the terminating NUL.
*/
strsize = 0;
sp = s;
if (!use_unicode) {
for (;;) {
c = GET_U_1(sp);
sp++;
strsize++;
if (c == '\0')
break;
}
} else {
for (;;) {
c = GET_LE_U_2(sp);
sp += 2;
strsize += 2;
if (c == '\0')
break;
}
}
}
if (!use_unicode) {
while (strsize != 0) {
c = GET_U_1(s);
s++;
strsize--;
if (c == 0) {
/*
* Even counted strings may have embedded null
* terminators, so quit here, and skip past
* the rest of the data.
*
* Make sure, however, that the rest of the data
* is there, so we don't overflow the buffer when
* skipping past it.
*/
ND_TCHECK_LEN(s, strsize);
s += strsize;
strsize = 0;
break;
}
if (l < MAX_UNISTR_SIZE) {
if (ND_ASCII_ISPRINT(c)) {
/* It's a printable ASCII character */
(*buf)[l] = (char)c;
} else {
/* It's a non-ASCII character or a non-printable ASCII character */
(*buf)[l] = '.';
}
l++;
}
}
} else {
while (strsize > 1) {
c = GET_LE_U_2(s);
s += 2;
strsize -= 2;
if (c == 0) {
/*
* Even counted strings may have embedded null
* terminators, so quit here, and skip past
* the rest of the data.
*
* Make sure, however, that the rest of the data
* is there, so we don't overflow the buffer when
* skipping past it.
*/
ND_TCHECK_LEN(s, strsize);
s += strsize;
strsize = 0;
break;
}
if (l < MAX_UNISTR_SIZE) {
if (ND_ASCII_ISPRINT(c)) {
/* It's a printable ASCII character */
(*buf)[l] = (char)c;
} else {
/* It's a non-ASCII character or a non-printable ASCII character */
(*buf)[l] = '.';
}
l++;
}
}
if (strsize == 1) {
/* We have half of a code point; skip past it */
ND_TCHECK_1(s);
s++;
}
}
(*buf)[l] = 0;
return s;
trunc:
(*buf)[l] = 0;
return NULL;
}
static const u_char *
smb_fdata1(netdissect_options *ndo,
const u_char *buf, const char *fmt, const u_char *maxbuf,
int unicodestr)
{
int reverse = 0;
const char *attrib_fmt = "READONLY|HIDDEN|SYSTEM|VOLUME|DIR|ARCHIVE|";
char strbuf[MAX_UNISTR_SIZE+1];
while (*fmt && buf<maxbuf) {
switch (*fmt) {
case 'a':
write_bits(ndo, GET_U_1(buf), attrib_fmt);
buf++;
fmt++;
break;
case 'A':
write_bits(ndo, GET_LE_U_2(buf), attrib_fmt);
buf += 2;
fmt++;
break;
case '{':
{
char bitfmt[128];
char *p;
u_int l;
p = strchr(++fmt, '}');
- l = ND_BYTES_BETWEEN(p, fmt);
+ l = ND_BYTES_BETWEEN(fmt, p);
if (l > sizeof(bitfmt) - 1)
l = sizeof(bitfmt)-1;
strncpy(bitfmt, fmt, l);
bitfmt[l] = '\0';
fmt = p + 1;
write_bits(ndo, GET_U_1(buf), bitfmt);
buf++;
break;
}
case 'P':
{
int l = atoi(fmt + 1);
ND_TCHECK_LEN(buf, l);
buf += l;
fmt++;
while (ND_ASCII_ISDIGIT(*fmt))
fmt++;
break;
}
case 'r':
reverse = !reverse;
fmt++;
break;
case 'b':
{
unsigned int x;
x = GET_U_1(buf);
ND_PRINT("%u (0x%x)", x, x);
buf += 1;
fmt++;
break;
}
case 'd':
{
int x;
x = reverse ? GET_BE_S_2(buf) :
GET_LE_S_2(buf);
ND_PRINT("%d (0x%x)", x, x);
buf += 2;
fmt++;
break;
}
case 'D':
{
int x;
x = reverse ? GET_BE_S_4(buf) :
GET_LE_S_4(buf);
ND_PRINT("%d (0x%x)", x, x);
buf += 4;
fmt++;
break;
}
case 'L':
{
uint64_t x;
x = reverse ? GET_BE_U_8(buf) :
GET_LE_U_8(buf);
ND_PRINT("%" PRIu64 " (0x%" PRIx64 ")", x, x);
buf += 8;
fmt++;
break;
}
case 'u':
{
unsigned int x;
x = reverse ? GET_BE_U_2(buf) :
GET_LE_U_2(buf);
ND_PRINT("%u (0x%x)", x, x);
buf += 2;
fmt++;
break;
}
case 'U':
{
unsigned int x;
x = reverse ? GET_BE_U_4(buf) :
GET_LE_U_4(buf);
ND_PRINT("%u (0x%x)", x, x);
buf += 4;
fmt++;
break;
}
case 'M':
{
/* Weird mixed-endian length values in 64-bit locks */
uint32_t x1, x2;
uint64_t x;
ND_TCHECK_8(buf);
x1 = reverse ? GET_BE_U_4(buf) :
GET_LE_U_4(buf);
x2 = reverse ? GET_BE_U_4(buf + 4) :
GET_LE_U_4(buf + 4);
x = (((uint64_t)x1) << 32) | x2;
ND_PRINT("%" PRIu64 " (0x%" PRIx64 ")", x, x);
buf += 8;
fmt++;
break;
}
case 'B':
{
unsigned int x;
x = GET_U_1(buf);
ND_PRINT("0x%X", x);
buf += 1;
fmt++;
break;
}
case 'w':
{
unsigned int x;
x = reverse ? GET_BE_U_2(buf) :
GET_LE_U_2(buf);
ND_PRINT("0x%X", x);
buf += 2;
fmt++;
break;
}
case 'W':
{
unsigned int x;
x = reverse ? GET_BE_U_4(buf) :
GET_LE_U_4(buf);
ND_PRINT("0x%X", x);
buf += 4;
fmt++;
break;
}
case 'l':
{
fmt++;
switch (*fmt) {
case 'b':
stringlen = GET_U_1(buf);
stringlen_is_set = 1;
ND_PRINT("%u", stringlen);
buf += 1;
break;
case 'd':
case 'u':
stringlen = reverse ? GET_BE_U_2(buf) :
GET_LE_U_2(buf);
stringlen_is_set = 1;
ND_PRINT("%u", stringlen);
buf += 2;
break;
case 'D':
case 'U':
stringlen = reverse ? GET_BE_U_4(buf) :
GET_LE_U_4(buf);
stringlen_is_set = 1;
ND_PRINT("%u", stringlen);
buf += 4;
break;
}
fmt++;
break;
}
case 'S':
case 'R': /* like 'S', but always ASCII */
{
/*XXX unistr() */
buf = unistr(ndo, &strbuf, buf, 0, 1, (*fmt == 'R') ? 0 : unicodestr);
ND_PRINT("%s", strbuf);
if (buf == NULL)
goto trunc;
fmt++;
break;
}
case 'Z':
case 'Y': /* like 'Z', but always ASCII */
{
if (GET_U_1(buf) != 4 && GET_U_1(buf) != 2) {
ND_PRINT("Error! ASCIIZ buffer of type %u", GET_U_1(buf));
return maxbuf; /* give up */
}
buf = unistr(ndo, &strbuf, buf + 1, 0, 1, (*fmt == 'Y') ? 0 : unicodestr);
ND_PRINT("%s", strbuf);
if (buf == NULL)
goto trunc;
fmt++;
break;
}
case 's':
{
int l = atoi(fmt + 1);
ND_TCHECK_LEN(buf, l);
ND_PRINT("%-*.*s", l, l, buf);
buf += l;
fmt++;
while (ND_ASCII_ISDIGIT(*fmt))
fmt++;
break;
}
case 'c':
{
if (!stringlen_is_set) {
ND_PRINT("{stringlen not set}");
goto trunc;
}
ND_TCHECK_LEN(buf, stringlen);
ND_PRINT("%-*.*s", (int)stringlen, (int)stringlen, buf);
buf += stringlen;
fmt++;
while (ND_ASCII_ISDIGIT(*fmt))
fmt++;
break;
}
case 'C':
{
if (!stringlen_is_set) {
ND_PRINT("{stringlen not set}");
goto trunc;
}
buf = unistr(ndo, &strbuf, buf, stringlen, 0, unicodestr);
ND_PRINT("%s", strbuf);
if (buf == NULL)
goto trunc;
fmt++;
break;
}
case 'h':
{
int l = atoi(fmt + 1);
ND_TCHECK_LEN(buf, l);
while (l--) {
ND_PRINT("%02x", GET_U_1(buf));
buf++;
}
fmt++;
while (ND_ASCII_ISDIGIT(*fmt))
fmt++;
break;
}
case 'n':
{
int t = atoi(fmt+1);
char nbuf[255];
int name_type;
int len;
switch (t) {
case 1:
- name_type = name_extract(ndo, startbuf, ND_BYTES_BETWEEN(buf, startbuf),
- maxbuf, nbuf);
+ name_type = name_extract(ndo, startbuf,
+ ND_BYTES_BETWEEN(startbuf, buf),
+ maxbuf, nbuf);
if (name_type < 0)
goto trunc;
len = name_len(ndo, buf, maxbuf);
if (len < 0)
goto trunc;
buf += len;
ND_PRINT("%-15.15s NameType=0x%02X (%s)", nbuf, name_type,
name_type_str(name_type));
break;
case 2:
name_type = GET_U_1(buf + 15);
ND_PRINT("%-15.15s NameType=0x%02X (%s)", buf, name_type,
name_type_str(name_type));
buf += 16;
break;
}
fmt++;
while (ND_ASCII_ISDIGIT(*fmt))
fmt++;
break;
}
case 'T':
{
time_t t;
const char *tstring;
char buffer[sizeof("Www Mmm dd hh:mm:ss yyyyy")];
uint32_t x;
switch (atoi(fmt + 1)) {
case 1:
x = GET_LE_U_4(buf);
if (x == 0 || x == 0xFFFFFFFF)
t = 0;
else
t = make_unix_date(ndo, buf);
buf += 4;
break;
case 2:
x = GET_LE_U_4(buf);
if (x == 0 || x == 0xFFFFFFFF)
t = 0;
else
t = make_unix_date2(ndo, buf);
buf += 4;
break;
case 3:
ND_TCHECK_8(buf);
t = interpret_long_date(ndo, buf);
buf += 8;
break;
default:
t = 0;
break;
}
if (t != 0) {
- tstring = nd_format_time(buffer, sizeof(buffer), "%a %b %e %T %Y",
- localtime(&t));
+ tstring = nd_format_time(buffer, sizeof(buffer), "%Y-%m-%d %T",
+ localtime(&t));
} else
tstring = "NULL";
ND_PRINT("%s\n", tstring);
fmt++;
while (ND_ASCII_ISDIGIT(*fmt))
fmt++;
break;
}
default:
ND_PRINT("%c", *fmt);
fmt++;
break;
}
}
if (buf >= maxbuf && *fmt)
ND_PRINT("END OF BUFFER\n");
return(buf);
trunc:
nd_print_trunc(ndo);
return(NULL);
}
const u_char *
smb_fdata(netdissect_options *ndo,
const u_char *buf, const char *fmt, const u_char *maxbuf,
int unicodestr)
{
static int depth = 0;
char s[128];
char *p;
while (*fmt) {
switch (*fmt) {
case '*':
/*
* List of multiple instances of something described by the
* remainder of the string (which may itself include a list
* of multiple instances of something, so we recurse).
*/
fmt++;
while (buf < maxbuf) {
const u_char *buf2;
depth++;
/*
* In order to avoid stack exhaustion recurse at most 10
* levels; that "should not happen", as no SMB structure
* should be nested *that* deeply, and we thus shouldn't
* have format strings with that level of nesting.
*/
if (depth == 10) {
ND_PRINT("(too many nested levels, not recursing)");
buf2 = buf;
} else
buf2 = smb_fdata(ndo, buf, fmt, maxbuf, unicodestr);
depth--;
if (buf2 == NULL)
return(NULL);
if (buf2 == buf)
return(buf);
buf = buf2;
}
return(buf);
case '|':
/*
* Just do a bounds check.
*/
fmt++;
if (buf >= maxbuf)
return(buf);
break;
case '%':
/*
* XXX - unused?
*/
fmt++;
buf = maxbuf;
break;
case '#':
/*
* Done?
*/
fmt++;
return(buf);
break;
case '[':
/*
* Format of an item, enclosed in square brackets; dissect
* the item with smb_fdata1().
*/
fmt++;
if (buf >= maxbuf)
return(buf);
memset(s, 0, sizeof(s));
p = strchr(fmt, ']');
if ((size_t)(p - fmt + 1) > sizeof(s)) {
/* overrun */
return(buf);
}
strncpy(s, fmt, p - fmt);
s[p - fmt] = '\0';
fmt = p + 1;
buf = smb_fdata1(ndo, buf, s, maxbuf, unicodestr);
if (buf == NULL) {
/*
* Truncated.
* Is the next character a newline?
* If so, print it before quitting, so we don't
* get stuff in the middle of the line.
*/
if (*fmt == '\n')
ND_PRINT("\n");
return(NULL);
}
break;
default:
/*
* Not a formatting character, so just print it.
*/
ND_PRINT("%c", *fmt);
fmt++;
break;
}
}
if (!depth && buf < maxbuf) {
- u_int len = ND_BYTES_BETWEEN(maxbuf, buf);
+ u_int len = ND_BYTES_BETWEEN(buf, maxbuf);
ND_PRINT("Data: (%u bytes)\n", len);
smb_data_print(ndo, buf, len);
return(buf + len);
}
return(buf);
}
typedef struct {
const char *name;
int code;
const char *message;
} err_code_struct;
/* DOS Error Messages */
static const err_code_struct dos_msgs[] = {
{ "ERRbadfunc", 1, "Invalid function." },
{ "ERRbadfile", 2, "File not found." },
{ "ERRbadpath", 3, "Directory invalid." },
{ "ERRnofids", 4, "No file descriptors available" },
{ "ERRnoaccess", 5, "Access denied." },
{ "ERRbadfid", 6, "Invalid file handle." },
{ "ERRbadmcb", 7, "Memory control blocks destroyed." },
{ "ERRnomem", 8, "Insufficient server memory to perform the requested function." },
{ "ERRbadmem", 9, "Invalid memory block address." },
{ "ERRbadenv", 10, "Invalid environment." },
{ "ERRbadformat", 11, "Invalid format." },
{ "ERRbadaccess", 12, "Invalid open mode." },
{ "ERRbaddata", 13, "Invalid data." },
{ "ERR", 14, "reserved." },
{ "ERRbaddrive", 15, "Invalid drive specified." },
{ "ERRremcd", 16, "A Delete Directory request attempted to remove the server's current directory." },
{ "ERRdiffdevice", 17, "Not same device." },
{ "ERRnofiles", 18, "A File Search command can find no more files matching the specified criteria." },
{ "ERRbadshare", 32, "The sharing mode specified for an Open conflicts with existing FIDs on the file." },
{ "ERRlock", 33, "A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process." },
{ "ERRfilexists", 80, "The file named in a Create Directory, Make New File or Link request already exists." },
{ "ERRbadpipe", 230, "Pipe invalid." },
{ "ERRpipebusy", 231, "All instances of the requested pipe are busy." },
{ "ERRpipeclosing", 232, "Pipe close in progress." },
{ "ERRnotconnected", 233, "No process on other end of pipe." },
{ "ERRmoredata", 234, "There is more data to be returned." },
{ NULL, -1, NULL }
};
/* Server Error Messages */
static const err_code_struct server_msgs[] = {
{ "ERRerror", 1, "Non-specific error code." },
{ "ERRbadpw", 2, "Bad password - name/password pair in a Tree Connect or Session Setup are invalid." },
{ "ERRbadtype", 3, "reserved." },
{ "ERRaccess", 4, "The requester does not have the necessary access rights within the specified context for the requested function. The context is defined by the TID or the UID." },
{ "ERRinvnid", 5, "The tree ID (TID) specified in a command was invalid." },
{ "ERRinvnetname", 6, "Invalid network name in tree connect." },
{ "ERRinvdevice", 7, "Invalid device - printer request made to non-printer connection or non-printer request made to printer connection." },
{ "ERRqfull", 49, "Print queue full (files) -- returned by open print file." },
{ "ERRqtoobig", 50, "Print queue full -- no space." },
{ "ERRqeof", 51, "EOF on print queue dump." },
{ "ERRinvpfid", 52, "Invalid print file FID." },
{ "ERRsmbcmd", 64, "The server did not recognize the command received." },
{ "ERRsrverror", 65, "The server encountered an internal error, e.g., system file unavailable." },
{ "ERRfilespecs", 67, "The file handle (FID) and pathname parameters contained an invalid combination of values." },
{ "ERRreserved", 68, "reserved." },
{ "ERRbadpermits", 69, "The access permissions specified for a file or directory are not a valid combination. The server cannot set the requested attribute." },
{ "ERRreserved", 70, "reserved." },
{ "ERRsetattrmode", 71, "The attribute mode in the Set File Attribute request is invalid." },
{ "ERRpaused", 81, "Server is paused." },
{ "ERRmsgoff", 82, "Not receiving messages." },
{ "ERRnoroom", 83, "No room to buffer message." },
{ "ERRrmuns", 87, "Too many remote user names." },
{ "ERRtimeout", 88, "Operation timed out." },
{ "ERRnoresource", 89, "No resources currently available for request." },
{ "ERRtoomanyuids", 90, "Too many UIDs active on this session." },
{ "ERRbaduid", 91, "The UID is not known as a valid ID on this session." },
{ "ERRusempx", 250, "Temp unable to support Raw, use MPX mode." },
{ "ERRusestd", 251, "Temp unable to support Raw, use standard read/write." },
{ "ERRcontmpx", 252, "Continue in MPX mode." },
{ "ERRreserved", 253, "reserved." },
{ "ERRreserved", 254, "reserved." },
{ "ERRnosupport", 0xFFFF, "Function not supported." },
{ NULL, -1, NULL }
};
/* Hard Error Messages */
static const err_code_struct hard_msgs[] = {
{ "ERRnowrite", 19, "Attempt to write on write-protected diskette." },
{ "ERRbadunit", 20, "Unknown unit." },
{ "ERRnotready", 21, "Drive not ready." },
{ "ERRbadcmd", 22, "Unknown command." },
{ "ERRdata", 23, "Data error (CRC)." },
{ "ERRbadreq", 24, "Bad request structure length." },
{ "ERRseek", 25 , "Seek error." },
{ "ERRbadmedia", 26, "Unknown media type." },
{ "ERRbadsector", 27, "Sector not found." },
{ "ERRnopaper", 28, "Printer out of paper." },
{ "ERRwrite", 29, "Write fault." },
{ "ERRread", 30, "Read fault." },
{ "ERRgeneral", 31, "General failure." },
{ "ERRbadshare", 32, "A open conflicts with an existing open." },
{ "ERRlock", 33, "A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process." },
{ "ERRwrongdisk", 34, "The wrong disk was found in a drive." },
{ "ERRFCBUnavail", 35, "No FCBs are available to process request." },
{ "ERRsharebufexc", 36, "A sharing buffer has been exceeded." },
{ NULL, -1, NULL }
};
static const struct {
int code;
const char *class;
const err_code_struct *err_msgs;
} err_classes[] = {
{ 0, "SUCCESS", NULL },
{ 0x01, "ERRDOS", dos_msgs },
{ 0x02, "ERRSRV", server_msgs },
{ 0x03, "ERRHRD", hard_msgs },
{ 0x04, "ERRXOS", NULL },
{ 0xE1, "ERRRMX1", NULL },
{ 0xE2, "ERRRMX2", NULL },
{ 0xE3, "ERRRMX3", NULL },
{ 0xFF, "ERRCMD", NULL },
{ -1, NULL, NULL }
};
/*
* return a SMB error string from a SMB buffer
*/
const char *
smb_errstr(int class, int num)
{
static char ret[128];
int i, j;
ret[0] = 0;
for (i = 0; err_classes[i].class; i++)
if (err_classes[i].code == class) {
if (err_classes[i].err_msgs) {
const err_code_struct *err = err_classes[i].err_msgs;
for (j = 0; err[j].name; j++)
if (num == err[j].code) {
snprintf(ret, sizeof(ret), "%s - %s (%s)",
err_classes[i].class, err[j].name, err[j].message);
return ret;
}
}
snprintf(ret, sizeof(ret), "%s - %d", err_classes[i].class, num);
return ret;
}
snprintf(ret, sizeof(ret), "ERROR: Unknown error (%d,%d)", class, num);
return(ret);
}
typedef struct {
uint32_t code;
const char *name;
} nt_err_code_struct;
/*
* NT Error codes
*/
static const nt_err_code_struct nt_errors[] = {
{ 0x00000000, "STATUS_SUCCESS" },
{ 0x00000000, "STATUS_WAIT_0" },
{ 0x00000001, "STATUS_WAIT_1" },
{ 0x00000002, "STATUS_WAIT_2" },
{ 0x00000003, "STATUS_WAIT_3" },
{ 0x0000003F, "STATUS_WAIT_63" },
{ 0x00000080, "STATUS_ABANDONED" },
{ 0x00000080, "STATUS_ABANDONED_WAIT_0" },
{ 0x000000BF, "STATUS_ABANDONED_WAIT_63" },
{ 0x000000C0, "STATUS_USER_APC" },
{ 0x00000100, "STATUS_KERNEL_APC" },
{ 0x00000101, "STATUS_ALERTED" },
{ 0x00000102, "STATUS_TIMEOUT" },
{ 0x00000103, "STATUS_PENDING" },
{ 0x00000104, "STATUS_REPARSE" },
{ 0x00000105, "STATUS_MORE_ENTRIES" },
{ 0x00000106, "STATUS_NOT_ALL_ASSIGNED" },
{ 0x00000107, "STATUS_SOME_NOT_MAPPED" },
{ 0x00000108, "STATUS_OPLOCK_BREAK_IN_PROGRESS" },
{ 0x00000109, "STATUS_VOLUME_MOUNTED" },
{ 0x0000010A, "STATUS_RXACT_COMMITTED" },
{ 0x0000010B, "STATUS_NOTIFY_CLEANUP" },
{ 0x0000010C, "STATUS_NOTIFY_ENUM_DIR" },
{ 0x0000010D, "STATUS_NO_QUOTAS_FOR_ACCOUNT" },
{ 0x0000010E, "STATUS_PRIMARY_TRANSPORT_CONNECT_FAILED" },
{ 0x00000110, "STATUS_PAGE_FAULT_TRANSITION" },
{ 0x00000111, "STATUS_PAGE_FAULT_DEMAND_ZERO" },
{ 0x00000112, "STATUS_PAGE_FAULT_COPY_ON_WRITE" },
{ 0x00000113, "STATUS_PAGE_FAULT_GUARD_PAGE" },
{ 0x00000114, "STATUS_PAGE_FAULT_PAGING_FILE" },
{ 0x00000115, "STATUS_CACHE_PAGE_LOCKED" },
{ 0x00000116, "STATUS_CRASH_DUMP" },
{ 0x00000117, "STATUS_BUFFER_ALL_ZEROS" },
{ 0x00000118, "STATUS_REPARSE_OBJECT" },
{ 0x0000045C, "STATUS_NO_SHUTDOWN_IN_PROGRESS" },
{ 0x40000000, "STATUS_OBJECT_NAME_EXISTS" },
{ 0x40000001, "STATUS_THREAD_WAS_SUSPENDED" },
{ 0x40000002, "STATUS_WORKING_SET_LIMIT_RANGE" },
{ 0x40000003, "STATUS_IMAGE_NOT_AT_BASE" },
{ 0x40000004, "STATUS_RXACT_STATE_CREATED" },
{ 0x40000005, "STATUS_SEGMENT_NOTIFICATION" },
{ 0x40000006, "STATUS_LOCAL_USER_SESSION_KEY" },
{ 0x40000007, "STATUS_BAD_CURRENT_DIRECTORY" },
{ 0x40000008, "STATUS_SERIAL_MORE_WRITES" },
{ 0x40000009, "STATUS_REGISTRY_RECOVERED" },
{ 0x4000000A, "STATUS_FT_READ_RECOVERY_FROM_BACKUP" },
{ 0x4000000B, "STATUS_FT_WRITE_RECOVERY" },
{ 0x4000000C, "STATUS_SERIAL_COUNTER_TIMEOUT" },
{ 0x4000000D, "STATUS_NULL_LM_PASSWORD" },
{ 0x4000000E, "STATUS_IMAGE_MACHINE_TYPE_MISMATCH" },
{ 0x4000000F, "STATUS_RECEIVE_PARTIAL" },
{ 0x40000010, "STATUS_RECEIVE_EXPEDITED" },
{ 0x40000011, "STATUS_RECEIVE_PARTIAL_EXPEDITED" },
{ 0x40000012, "STATUS_EVENT_DONE" },
{ 0x40000013, "STATUS_EVENT_PENDING" },
{ 0x40000014, "STATUS_CHECKING_FILE_SYSTEM" },
{ 0x40000015, "STATUS_FATAL_APP_EXIT" },
{ 0x40000016, "STATUS_PREDEFINED_HANDLE" },
{ 0x40000017, "STATUS_WAS_UNLOCKED" },
{ 0x40000018, "STATUS_SERVICE_NOTIFICATION" },
{ 0x40000019, "STATUS_WAS_LOCKED" },
{ 0x4000001A, "STATUS_LOG_HARD_ERROR" },
{ 0x4000001B, "STATUS_ALREADY_WIN32" },
{ 0x4000001C, "STATUS_WX86_UNSIMULATE" },
{ 0x4000001D, "STATUS_WX86_CONTINUE" },
{ 0x4000001E, "STATUS_WX86_SINGLE_STEP" },
{ 0x4000001F, "STATUS_WX86_BREAKPOINT" },
{ 0x40000020, "STATUS_WX86_EXCEPTION_CONTINUE" },
{ 0x40000021, "STATUS_WX86_EXCEPTION_LASTCHANCE" },
{ 0x40000022, "STATUS_WX86_EXCEPTION_CHAIN" },
{ 0x40000023, "STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE" },
{ 0x40000024, "STATUS_NO_YIELD_PERFORMED" },
{ 0x40000025, "STATUS_TIMER_RESUME_IGNORED" },
{ 0x80000001, "STATUS_GUARD_PAGE_VIOLATION" },
{ 0x80000002, "STATUS_DATATYPE_MISALIGNMENT" },
{ 0x80000003, "STATUS_BREAKPOINT" },
{ 0x80000004, "STATUS_SINGLE_STEP" },
{ 0x80000005, "STATUS_BUFFER_OVERFLOW" },
{ 0x80000006, "STATUS_NO_MORE_FILES" },
{ 0x80000007, "STATUS_WAKE_SYSTEM_DEBUGGER" },
{ 0x8000000A, "STATUS_HANDLES_CLOSED" },
{ 0x8000000B, "STATUS_NO_INHERITANCE" },
{ 0x8000000C, "STATUS_GUID_SUBSTITUTION_MADE" },
{ 0x8000000D, "STATUS_PARTIAL_COPY" },
{ 0x8000000E, "STATUS_DEVICE_PAPER_EMPTY" },
{ 0x8000000F, "STATUS_DEVICE_POWERED_OFF" },
{ 0x80000010, "STATUS_DEVICE_OFF_LINE" },
{ 0x80000011, "STATUS_DEVICE_BUSY" },
{ 0x80000012, "STATUS_NO_MORE_EAS" },
{ 0x80000013, "STATUS_INVALID_EA_NAME" },
{ 0x80000014, "STATUS_EA_LIST_INCONSISTENT" },
{ 0x80000015, "STATUS_INVALID_EA_FLAG" },
{ 0x80000016, "STATUS_VERIFY_REQUIRED" },
{ 0x80000017, "STATUS_EXTRANEOUS_INFORMATION" },
{ 0x80000018, "STATUS_RXACT_COMMIT_NECESSARY" },
{ 0x8000001A, "STATUS_NO_MORE_ENTRIES" },
{ 0x8000001B, "STATUS_FILEMARK_DETECTED" },
{ 0x8000001C, "STATUS_MEDIA_CHANGED" },
{ 0x8000001D, "STATUS_BUS_RESET" },
{ 0x8000001E, "STATUS_END_OF_MEDIA" },
{ 0x8000001F, "STATUS_BEGINNING_OF_MEDIA" },
{ 0x80000020, "STATUS_MEDIA_CHECK" },
{ 0x80000021, "STATUS_SETMARK_DETECTED" },
{ 0x80000022, "STATUS_NO_DATA_DETECTED" },
{ 0x80000023, "STATUS_REDIRECTOR_HAS_OPEN_HANDLES" },
{ 0x80000024, "STATUS_SERVER_HAS_OPEN_HANDLES" },
{ 0x80000025, "STATUS_ALREADY_DISCONNECTED" },
{ 0x80000026, "STATUS_LONGJUMP" },
{ 0x80040111, "MAPI_E_LOGON_FAILED" },
{ 0x80090300, "SEC_E_INSUFFICIENT_MEMORY" },
{ 0x80090301, "SEC_E_INVALID_HANDLE" },
{ 0x80090302, "SEC_E_UNSUPPORTED_FUNCTION" },
{ 0x8009030B, "SEC_E_NO_IMPERSONATION" },
{ 0x8009030D, "SEC_E_UNKNOWN_CREDENTIALS" },
{ 0x8009030E, "SEC_E_NO_CREDENTIALS" },
{ 0x8009030F, "SEC_E_MESSAGE_ALTERED" },
{ 0x80090310, "SEC_E_OUT_OF_SEQUENCE" },
{ 0x80090311, "SEC_E_NO_AUTHENTICATING_AUTHORITY" },
{ 0xC0000001, "STATUS_UNSUCCESSFUL" },
{ 0xC0000002, "STATUS_NOT_IMPLEMENTED" },
{ 0xC0000003, "STATUS_INVALID_INFO_CLASS" },
{ 0xC0000004, "STATUS_INFO_LENGTH_MISMATCH" },
{ 0xC0000005, "STATUS_ACCESS_VIOLATION" },
{ 0xC0000006, "STATUS_IN_PAGE_ERROR" },
{ 0xC0000007, "STATUS_PAGEFILE_QUOTA" },
{ 0xC0000008, "STATUS_INVALID_HANDLE" },
{ 0xC0000009, "STATUS_BAD_INITIAL_STACK" },
{ 0xC000000A, "STATUS_BAD_INITIAL_PC" },
{ 0xC000000B, "STATUS_INVALID_CID" },
{ 0xC000000C, "STATUS_TIMER_NOT_CANCELED" },
{ 0xC000000D, "STATUS_INVALID_PARAMETER" },
{ 0xC000000E, "STATUS_NO_SUCH_DEVICE" },
{ 0xC000000F, "STATUS_NO_SUCH_FILE" },
{ 0xC0000010, "STATUS_INVALID_DEVICE_REQUEST" },
{ 0xC0000011, "STATUS_END_OF_FILE" },
{ 0xC0000012, "STATUS_WRONG_VOLUME" },
{ 0xC0000013, "STATUS_NO_MEDIA_IN_DEVICE" },
{ 0xC0000014, "STATUS_UNRECOGNIZED_MEDIA" },
{ 0xC0000015, "STATUS_NONEXISTENT_SECTOR" },
{ 0xC0000016, "STATUS_MORE_PROCESSING_REQUIRED" },
{ 0xC0000017, "STATUS_NO_MEMORY" },
{ 0xC0000018, "STATUS_CONFLICTING_ADDRESSES" },
{ 0xC0000019, "STATUS_NOT_MAPPED_VIEW" },
{ 0xC000001A, "STATUS_UNABLE_TO_FREE_VM" },
{ 0xC000001B, "STATUS_UNABLE_TO_DELETE_SECTION" },
{ 0xC000001C, "STATUS_INVALID_SYSTEM_SERVICE" },
{ 0xC000001D, "STATUS_ILLEGAL_INSTRUCTION" },
{ 0xC000001E, "STATUS_INVALID_LOCK_SEQUENCE" },
{ 0xC000001F, "STATUS_INVALID_VIEW_SIZE" },
{ 0xC0000020, "STATUS_INVALID_FILE_FOR_SECTION" },
{ 0xC0000021, "STATUS_ALREADY_COMMITTED" },
{ 0xC0000022, "STATUS_ACCESS_DENIED" },
{ 0xC0000023, "STATUS_BUFFER_TOO_SMALL" },
{ 0xC0000024, "STATUS_OBJECT_TYPE_MISMATCH" },
{ 0xC0000025, "STATUS_NONCONTINUABLE_EXCEPTION" },
{ 0xC0000026, "STATUS_INVALID_DISPOSITION" },
{ 0xC0000027, "STATUS_UNWIND" },
{ 0xC0000028, "STATUS_BAD_STACK" },
{ 0xC0000029, "STATUS_INVALID_UNWIND_TARGET" },
{ 0xC000002A, "STATUS_NOT_LOCKED" },
{ 0xC000002B, "STATUS_PARITY_ERROR" },
{ 0xC000002C, "STATUS_UNABLE_TO_DECOMMIT_VM" },
{ 0xC000002D, "STATUS_NOT_COMMITTED" },
{ 0xC000002E, "STATUS_INVALID_PORT_ATTRIBUTES" },
{ 0xC000002F, "STATUS_PORT_MESSAGE_TOO_LONG" },
{ 0xC0000030, "STATUS_INVALID_PARAMETER_MIX" },
{ 0xC0000031, "STATUS_INVALID_QUOTA_LOWER" },
{ 0xC0000032, "STATUS_DISK_CORRUPT_ERROR" },
{ 0xC0000033, "STATUS_OBJECT_NAME_INVALID" },
{ 0xC0000034, "STATUS_OBJECT_NAME_NOT_FOUND" },
{ 0xC0000035, "STATUS_OBJECT_NAME_COLLISION" },
{ 0xC0000037, "STATUS_PORT_DISCONNECTED" },
{ 0xC0000038, "STATUS_DEVICE_ALREADY_ATTACHED" },
{ 0xC0000039, "STATUS_OBJECT_PATH_INVALID" },
{ 0xC000003A, "STATUS_OBJECT_PATH_NOT_FOUND" },
{ 0xC000003B, "STATUS_OBJECT_PATH_SYNTAX_BAD" },
{ 0xC000003C, "STATUS_DATA_OVERRUN" },
{ 0xC000003D, "STATUS_DATA_LATE_ERROR" },
{ 0xC000003E, "STATUS_DATA_ERROR" },
{ 0xC000003F, "STATUS_CRC_ERROR" },
{ 0xC0000040, "STATUS_SECTION_TOO_BIG" },
{ 0xC0000041, "STATUS_PORT_CONNECTION_REFUSED" },
{ 0xC0000042, "STATUS_INVALID_PORT_HANDLE" },
{ 0xC0000043, "STATUS_SHARING_VIOLATION" },
{ 0xC0000044, "STATUS_QUOTA_EXCEEDED" },
{ 0xC0000045, "STATUS_INVALID_PAGE_PROTECTION" },
{ 0xC0000046, "STATUS_MUTANT_NOT_OWNED" },
{ 0xC0000047, "STATUS_SEMAPHORE_LIMIT_EXCEEDED" },
{ 0xC0000048, "STATUS_PORT_ALREADY_SET" },
{ 0xC0000049, "STATUS_SECTION_NOT_IMAGE" },
{ 0xC000004A, "STATUS_SUSPEND_COUNT_EXCEEDED" },
{ 0xC000004B, "STATUS_THREAD_IS_TERMINATING" },
{ 0xC000004C, "STATUS_BAD_WORKING_SET_LIMIT" },
{ 0xC000004D, "STATUS_INCOMPATIBLE_FILE_MAP" },
{ 0xC000004E, "STATUS_SECTION_PROTECTION" },
{ 0xC000004F, "STATUS_EAS_NOT_SUPPORTED" },
{ 0xC0000050, "STATUS_EA_TOO_LARGE" },
{ 0xC0000051, "STATUS_NONEXISTENT_EA_ENTRY" },
{ 0xC0000052, "STATUS_NO_EAS_ON_FILE" },
{ 0xC0000053, "STATUS_EA_CORRUPT_ERROR" },
{ 0xC0000054, "STATUS_FILE_LOCK_CONFLICT" },
{ 0xC0000055, "STATUS_LOCK_NOT_GRANTED" },
{ 0xC0000056, "STATUS_DELETE_PENDING" },
{ 0xC0000057, "STATUS_CTL_FILE_NOT_SUPPORTED" },
{ 0xC0000058, "STATUS_UNKNOWN_REVISION" },
{ 0xC0000059, "STATUS_REVISION_MISMATCH" },
{ 0xC000005A, "STATUS_INVALID_OWNER" },
{ 0xC000005B, "STATUS_INVALID_PRIMARY_GROUP" },
{ 0xC000005C, "STATUS_NO_IMPERSONATION_TOKEN" },
{ 0xC000005D, "STATUS_CANT_DISABLE_MANDATORY" },
{ 0xC000005E, "STATUS_NO_LOGON_SERVERS" },
{ 0xC000005F, "STATUS_NO_SUCH_LOGON_SESSION" },
{ 0xC0000060, "STATUS_NO_SUCH_PRIVILEGE" },
{ 0xC0000061, "STATUS_PRIVILEGE_NOT_HELD" },
{ 0xC0000062, "STATUS_INVALID_ACCOUNT_NAME" },
{ 0xC0000063, "STATUS_USER_EXISTS" },
{ 0xC0000064, "STATUS_NO_SUCH_USER" },
{ 0xC0000065, "STATUS_GROUP_EXISTS" },
{ 0xC0000066, "STATUS_NO_SUCH_GROUP" },
{ 0xC0000067, "STATUS_MEMBER_IN_GROUP" },
{ 0xC0000068, "STATUS_MEMBER_NOT_IN_GROUP" },
{ 0xC0000069, "STATUS_LAST_ADMIN" },
{ 0xC000006A, "STATUS_WRONG_PASSWORD" },
{ 0xC000006B, "STATUS_ILL_FORMED_PASSWORD" },
{ 0xC000006C, "STATUS_PASSWORD_RESTRICTION" },
{ 0xC000006D, "STATUS_LOGON_FAILURE" },
{ 0xC000006E, "STATUS_ACCOUNT_RESTRICTION" },
{ 0xC000006F, "STATUS_INVALID_LOGON_HOURS" },
{ 0xC0000070, "STATUS_INVALID_WORKSTATION" },
{ 0xC0000071, "STATUS_PASSWORD_EXPIRED" },
{ 0xC0000072, "STATUS_ACCOUNT_DISABLED" },
{ 0xC0000073, "STATUS_NONE_MAPPED" },
{ 0xC0000074, "STATUS_TOO_MANY_LUIDS_REQUESTED" },
{ 0xC0000075, "STATUS_LUIDS_EXHAUSTED" },
{ 0xC0000076, "STATUS_INVALID_SUB_AUTHORITY" },
{ 0xC0000077, "STATUS_INVALID_ACL" },
{ 0xC0000078, "STATUS_INVALID_SID" },
{ 0xC0000079, "STATUS_INVALID_SECURITY_DESCR" },
{ 0xC000007A, "STATUS_PROCEDURE_NOT_FOUND" },
{ 0xC000007B, "STATUS_INVALID_IMAGE_FORMAT" },
{ 0xC000007C, "STATUS_NO_TOKEN" },
{ 0xC000007D, "STATUS_BAD_INHERITANCE_ACL" },
{ 0xC000007E, "STATUS_RANGE_NOT_LOCKED" },
{ 0xC000007F, "STATUS_DISK_FULL" },
{ 0xC0000080, "STATUS_SERVER_DISABLED" },
{ 0xC0000081, "STATUS_SERVER_NOT_DISABLED" },
{ 0xC0000082, "STATUS_TOO_MANY_GUIDS_REQUESTED" },
{ 0xC0000083, "STATUS_GUIDS_EXHAUSTED" },
{ 0xC0000084, "STATUS_INVALID_ID_AUTHORITY" },
{ 0xC0000085, "STATUS_AGENTS_EXHAUSTED" },
{ 0xC0000086, "STATUS_INVALID_VOLUME_LABEL" },
{ 0xC0000087, "STATUS_SECTION_NOT_EXTENDED" },
{ 0xC0000088, "STATUS_NOT_MAPPED_DATA" },
{ 0xC0000089, "STATUS_RESOURCE_DATA_NOT_FOUND" },
{ 0xC000008A, "STATUS_RESOURCE_TYPE_NOT_FOUND" },
{ 0xC000008B, "STATUS_RESOURCE_NAME_NOT_FOUND" },
{ 0xC000008C, "STATUS_ARRAY_BOUNDS_EXCEEDED" },
{ 0xC000008D, "STATUS_FLOAT_DENORMAL_OPERAND" },
{ 0xC000008E, "STATUS_FLOAT_DIVIDE_BY_ZERO" },
{ 0xC000008F, "STATUS_FLOAT_INEXACT_RESULT" },
{ 0xC0000090, "STATUS_FLOAT_INVALID_OPERATION" },
{ 0xC0000091, "STATUS_FLOAT_OVERFLOW" },
{ 0xC0000092, "STATUS_FLOAT_STACK_CHECK" },
{ 0xC0000093, "STATUS_FLOAT_UNDERFLOW" },
{ 0xC0000094, "STATUS_INTEGER_DIVIDE_BY_ZERO" },
{ 0xC0000095, "STATUS_INTEGER_OVERFLOW" },
{ 0xC0000096, "STATUS_PRIVILEGED_INSTRUCTION" },
{ 0xC0000097, "STATUS_TOO_MANY_PAGING_FILES" },
{ 0xC0000098, "STATUS_FILE_INVALID" },
{ 0xC0000099, "STATUS_ALLOTTED_SPACE_EXCEEDED" },
{ 0xC000009A, "STATUS_INSUFFICIENT_RESOURCES" },
{ 0xC000009B, "STATUS_DFS_EXIT_PATH_FOUND" },
{ 0xC000009C, "STATUS_DEVICE_DATA_ERROR" },
{ 0xC000009D, "STATUS_DEVICE_NOT_CONNECTED" },
{ 0xC000009E, "STATUS_DEVICE_POWER_FAILURE" },
{ 0xC000009F, "STATUS_FREE_VM_NOT_AT_BASE" },
{ 0xC00000A0, "STATUS_MEMORY_NOT_ALLOCATED" },
{ 0xC00000A1, "STATUS_WORKING_SET_QUOTA" },
{ 0xC00000A2, "STATUS_MEDIA_WRITE_PROTECTED" },
{ 0xC00000A3, "STATUS_DEVICE_NOT_READY" },
{ 0xC00000A4, "STATUS_INVALID_GROUP_ATTRIBUTES" },
{ 0xC00000A5, "STATUS_BAD_IMPERSONATION_LEVEL" },
{ 0xC00000A6, "STATUS_CANT_OPEN_ANONYMOUS" },
{ 0xC00000A7, "STATUS_BAD_VALIDATION_CLASS" },
{ 0xC00000A8, "STATUS_BAD_TOKEN_TYPE" },
{ 0xC00000A9, "STATUS_BAD_MASTER_BOOT_RECORD" },
{ 0xC00000AA, "STATUS_INSTRUCTION_MISALIGNMENT" },
{ 0xC00000AB, "STATUS_INSTANCE_NOT_AVAILABLE" },
{ 0xC00000AC, "STATUS_PIPE_NOT_AVAILABLE" },
{ 0xC00000AD, "STATUS_INVALID_PIPE_STATE" },
{ 0xC00000AE, "STATUS_PIPE_BUSY" },
{ 0xC00000AF, "STATUS_ILLEGAL_FUNCTION" },
{ 0xC00000B0, "STATUS_PIPE_DISCONNECTED" },
{ 0xC00000B1, "STATUS_PIPE_CLOSING" },
{ 0xC00000B2, "STATUS_PIPE_CONNECTED" },
{ 0xC00000B3, "STATUS_PIPE_LISTENING" },
{ 0xC00000B4, "STATUS_INVALID_READ_MODE" },
{ 0xC00000B5, "STATUS_IO_TIMEOUT" },
{ 0xC00000B6, "STATUS_FILE_FORCED_CLOSED" },
{ 0xC00000B7, "STATUS_PROFILING_NOT_STARTED" },
{ 0xC00000B8, "STATUS_PROFILING_NOT_STOPPED" },
{ 0xC00000B9, "STATUS_COULD_NOT_INTERPRET" },
{ 0xC00000BA, "STATUS_FILE_IS_A_DIRECTORY" },
{ 0xC00000BB, "STATUS_NOT_SUPPORTED" },
{ 0xC00000BC, "STATUS_REMOTE_NOT_LISTENING" },
{ 0xC00000BD, "STATUS_DUPLICATE_NAME" },
{ 0xC00000BE, "STATUS_BAD_NETWORK_PATH" },
{ 0xC00000BF, "STATUS_NETWORK_BUSY" },
{ 0xC00000C0, "STATUS_DEVICE_DOES_NOT_EXIST" },
{ 0xC00000C1, "STATUS_TOO_MANY_COMMANDS" },
{ 0xC00000C2, "STATUS_ADAPTER_HARDWARE_ERROR" },
{ 0xC00000C3, "STATUS_INVALID_NETWORK_RESPONSE" },
{ 0xC00000C4, "STATUS_UNEXPECTED_NETWORK_ERROR" },
{ 0xC00000C5, "STATUS_BAD_REMOTE_ADAPTER" },
{ 0xC00000C6, "STATUS_PRINT_QUEUE_FULL" },
{ 0xC00000C7, "STATUS_NO_SPOOL_SPACE" },
{ 0xC00000C8, "STATUS_PRINT_CANCELLED" },
{ 0xC00000C9, "STATUS_NETWORK_NAME_DELETED" },
{ 0xC00000CA, "STATUS_NETWORK_ACCESS_DENIED" },
{ 0xC00000CB, "STATUS_BAD_DEVICE_TYPE" },
{ 0xC00000CC, "STATUS_BAD_NETWORK_NAME" },
{ 0xC00000CD, "STATUS_TOO_MANY_NAMES" },
{ 0xC00000CE, "STATUS_TOO_MANY_SESSIONS" },
{ 0xC00000CF, "STATUS_SHARING_PAUSED" },
{ 0xC00000D0, "STATUS_REQUEST_NOT_ACCEPTED" },
{ 0xC00000D1, "STATUS_REDIRECTOR_PAUSED" },
{ 0xC00000D2, "STATUS_NET_WRITE_FAULT" },
{ 0xC00000D3, "STATUS_PROFILING_AT_LIMIT" },
{ 0xC00000D4, "STATUS_NOT_SAME_DEVICE" },
{ 0xC00000D5, "STATUS_FILE_RENAMED" },
{ 0xC00000D6, "STATUS_VIRTUAL_CIRCUIT_CLOSED" },
{ 0xC00000D7, "STATUS_NO_SECURITY_ON_OBJECT" },
{ 0xC00000D8, "STATUS_CANT_WAIT" },
{ 0xC00000D9, "STATUS_PIPE_EMPTY" },
{ 0xC00000DA, "STATUS_CANT_ACCESS_DOMAIN_INFO" },
{ 0xC00000DB, "STATUS_CANT_TERMINATE_SELF" },
{ 0xC00000DC, "STATUS_INVALID_SERVER_STATE" },
{ 0xC00000DD, "STATUS_INVALID_DOMAIN_STATE" },
{ 0xC00000DE, "STATUS_INVALID_DOMAIN_ROLE" },
{ 0xC00000DF, "STATUS_NO_SUCH_DOMAIN" },
{ 0xC00000E0, "STATUS_DOMAIN_EXISTS" },
{ 0xC00000E1, "STATUS_DOMAIN_LIMIT_EXCEEDED" },
{ 0xC00000E2, "STATUS_OPLOCK_NOT_GRANTED" },
{ 0xC00000E3, "STATUS_INVALID_OPLOCK_PROTOCOL" },
{ 0xC00000E4, "STATUS_INTERNAL_DB_CORRUPTION" },
{ 0xC00000E5, "STATUS_INTERNAL_ERROR" },
{ 0xC00000E6, "STATUS_GENERIC_NOT_MAPPED" },
{ 0xC00000E7, "STATUS_BAD_DESCRIPTOR_FORMAT" },
{ 0xC00000E8, "STATUS_INVALID_USER_BUFFER" },
{ 0xC00000E9, "STATUS_UNEXPECTED_IO_ERROR" },
{ 0xC00000EA, "STATUS_UNEXPECTED_MM_CREATE_ERR" },
{ 0xC00000EB, "STATUS_UNEXPECTED_MM_MAP_ERROR" },
{ 0xC00000EC, "STATUS_UNEXPECTED_MM_EXTEND_ERR" },
{ 0xC00000ED, "STATUS_NOT_LOGON_PROCESS" },
{ 0xC00000EE, "STATUS_LOGON_SESSION_EXISTS" },
{ 0xC00000EF, "STATUS_INVALID_PARAMETER_1" },
{ 0xC00000F0, "STATUS_INVALID_PARAMETER_2" },
{ 0xC00000F1, "STATUS_INVALID_PARAMETER_3" },
{ 0xC00000F2, "STATUS_INVALID_PARAMETER_4" },
{ 0xC00000F3, "STATUS_INVALID_PARAMETER_5" },
{ 0xC00000F4, "STATUS_INVALID_PARAMETER_6" },
{ 0xC00000F5, "STATUS_INVALID_PARAMETER_7" },
{ 0xC00000F6, "STATUS_INVALID_PARAMETER_8" },
{ 0xC00000F7, "STATUS_INVALID_PARAMETER_9" },
{ 0xC00000F8, "STATUS_INVALID_PARAMETER_10" },
{ 0xC00000F9, "STATUS_INVALID_PARAMETER_11" },
{ 0xC00000FA, "STATUS_INVALID_PARAMETER_12" },
{ 0xC00000FB, "STATUS_REDIRECTOR_NOT_STARTED" },
{ 0xC00000FC, "STATUS_REDIRECTOR_STARTED" },
{ 0xC00000FD, "STATUS_STACK_OVERFLOW" },
{ 0xC00000FE, "STATUS_NO_SUCH_PACKAGE" },
{ 0xC00000FF, "STATUS_BAD_FUNCTION_TABLE" },
{ 0xC0000100, "STATUS_VARIABLE_NOT_FOUND" },
{ 0xC0000101, "STATUS_DIRECTORY_NOT_EMPTY" },
{ 0xC0000102, "STATUS_FILE_CORRUPT_ERROR" },
{ 0xC0000103, "STATUS_NOT_A_DIRECTORY" },
{ 0xC0000104, "STATUS_BAD_LOGON_SESSION_STATE" },
{ 0xC0000105, "STATUS_LOGON_SESSION_COLLISION" },
{ 0xC0000106, "STATUS_NAME_TOO_LONG" },
{ 0xC0000107, "STATUS_FILES_OPEN" },
{ 0xC0000108, "STATUS_CONNECTION_IN_USE" },
{ 0xC0000109, "STATUS_MESSAGE_NOT_FOUND" },
{ 0xC000010A, "STATUS_PROCESS_IS_TERMINATING" },
{ 0xC000010B, "STATUS_INVALID_LOGON_TYPE" },
{ 0xC000010C, "STATUS_NO_GUID_TRANSLATION" },
{ 0xC000010D, "STATUS_CANNOT_IMPERSONATE" },
{ 0xC000010E, "STATUS_IMAGE_ALREADY_LOADED" },
{ 0xC000010F, "STATUS_ABIOS_NOT_PRESENT" },
{ 0xC0000110, "STATUS_ABIOS_LID_NOT_EXIST" },
{ 0xC0000111, "STATUS_ABIOS_LID_ALREADY_OWNED" },
{ 0xC0000112, "STATUS_ABIOS_NOT_LID_OWNER" },
{ 0xC0000113, "STATUS_ABIOS_INVALID_COMMAND" },
{ 0xC0000114, "STATUS_ABIOS_INVALID_LID" },
{ 0xC0000115, "STATUS_ABIOS_SELECTOR_NOT_AVAILABLE" },
{ 0xC0000116, "STATUS_ABIOS_INVALID_SELECTOR" },
{ 0xC0000117, "STATUS_NO_LDT" },
{ 0xC0000118, "STATUS_INVALID_LDT_SIZE" },
{ 0xC0000119, "STATUS_INVALID_LDT_OFFSET" },
{ 0xC000011A, "STATUS_INVALID_LDT_DESCRIPTOR" },
{ 0xC000011B, "STATUS_INVALID_IMAGE_NE_FORMAT" },
{ 0xC000011C, "STATUS_RXACT_INVALID_STATE" },
{ 0xC000011D, "STATUS_RXACT_COMMIT_FAILURE" },
{ 0xC000011E, "STATUS_MAPPED_FILE_SIZE_ZERO" },
{ 0xC000011F, "STATUS_TOO_MANY_OPENED_FILES" },
{ 0xC0000120, "STATUS_CANCELLED" },
{ 0xC0000121, "STATUS_CANNOT_DELETE" },
{ 0xC0000122, "STATUS_INVALID_COMPUTER_NAME" },
{ 0xC0000123, "STATUS_FILE_DELETED" },
{ 0xC0000124, "STATUS_SPECIAL_ACCOUNT" },
{ 0xC0000125, "STATUS_SPECIAL_GROUP" },
{ 0xC0000126, "STATUS_SPECIAL_USER" },
{ 0xC0000127, "STATUS_MEMBERS_PRIMARY_GROUP" },
{ 0xC0000128, "STATUS_FILE_CLOSED" },
{ 0xC0000129, "STATUS_TOO_MANY_THREADS" },
{ 0xC000012A, "STATUS_THREAD_NOT_IN_PROCESS" },
{ 0xC000012B, "STATUS_TOKEN_ALREADY_IN_USE" },
{ 0xC000012C, "STATUS_PAGEFILE_QUOTA_EXCEEDED" },
{ 0xC000012D, "STATUS_COMMITMENT_LIMIT" },
{ 0xC000012E, "STATUS_INVALID_IMAGE_LE_FORMAT" },
{ 0xC000012F, "STATUS_INVALID_IMAGE_NOT_MZ" },
{ 0xC0000130, "STATUS_INVALID_IMAGE_PROTECT" },
{ 0xC0000131, "STATUS_INVALID_IMAGE_WIN_16" },
{ 0xC0000132, "STATUS_LOGON_SERVER_CONFLICT" },
{ 0xC0000133, "STATUS_TIME_DIFFERENCE_AT_DC" },
{ 0xC0000134, "STATUS_SYNCHRONIZATION_REQUIRED" },
{ 0xC0000135, "STATUS_DLL_NOT_FOUND" },
{ 0xC0000136, "STATUS_OPEN_FAILED" },
{ 0xC0000137, "STATUS_IO_PRIVILEGE_FAILED" },
{ 0xC0000138, "STATUS_ORDINAL_NOT_FOUND" },
{ 0xC0000139, "STATUS_ENTRYPOINT_NOT_FOUND" },
{ 0xC000013A, "STATUS_CONTROL_C_EXIT" },
{ 0xC000013B, "STATUS_LOCAL_DISCONNECT" },
{ 0xC000013C, "STATUS_REMOTE_DISCONNECT" },
{ 0xC000013D, "STATUS_REMOTE_RESOURCES" },
{ 0xC000013E, "STATUS_LINK_FAILED" },
{ 0xC000013F, "STATUS_LINK_TIMEOUT" },
{ 0xC0000140, "STATUS_INVALID_CONNECTION" },
{ 0xC0000141, "STATUS_INVALID_ADDRESS" },
{ 0xC0000142, "STATUS_DLL_INIT_FAILED" },
{ 0xC0000143, "STATUS_MISSING_SYSTEMFILE" },
{ 0xC0000144, "STATUS_UNHANDLED_EXCEPTION" },
{ 0xC0000145, "STATUS_APP_INIT_FAILURE" },
{ 0xC0000146, "STATUS_PAGEFILE_CREATE_FAILED" },
{ 0xC0000147, "STATUS_NO_PAGEFILE" },
{ 0xC0000148, "STATUS_INVALID_LEVEL" },
{ 0xC0000149, "STATUS_WRONG_PASSWORD_CORE" },
{ 0xC000014A, "STATUS_ILLEGAL_FLOAT_CONTEXT" },
{ 0xC000014B, "STATUS_PIPE_BROKEN" },
{ 0xC000014C, "STATUS_REGISTRY_CORRUPT" },
{ 0xC000014D, "STATUS_REGISTRY_IO_FAILED" },
{ 0xC000014E, "STATUS_NO_EVENT_PAIR" },
{ 0xC000014F, "STATUS_UNRECOGNIZED_VOLUME" },
{ 0xC0000150, "STATUS_SERIAL_NO_DEVICE_INITED" },
{ 0xC0000151, "STATUS_NO_SUCH_ALIAS" },
{ 0xC0000152, "STATUS_MEMBER_NOT_IN_ALIAS" },
{ 0xC0000153, "STATUS_MEMBER_IN_ALIAS" },
{ 0xC0000154, "STATUS_ALIAS_EXISTS" },
{ 0xC0000155, "STATUS_LOGON_NOT_GRANTED" },
{ 0xC0000156, "STATUS_TOO_MANY_SECRETS" },
{ 0xC0000157, "STATUS_SECRET_TOO_LONG" },
{ 0xC0000158, "STATUS_INTERNAL_DB_ERROR" },
{ 0xC0000159, "STATUS_FULLSCREEN_MODE" },
{ 0xC000015A, "STATUS_TOO_MANY_CONTEXT_IDS" },
{ 0xC000015B, "STATUS_LOGON_TYPE_NOT_GRANTED" },
{ 0xC000015C, "STATUS_NOT_REGISTRY_FILE" },
{ 0xC000015D, "STATUS_NT_CROSS_ENCRYPTION_REQUIRED" },
{ 0xC000015E, "STATUS_DOMAIN_CTRLR_CONFIG_ERROR" },
{ 0xC000015F, "STATUS_FT_MISSING_MEMBER" },
{ 0xC0000160, "STATUS_ILL_FORMED_SERVICE_ENTRY" },
{ 0xC0000161, "STATUS_ILLEGAL_CHARACTER" },
{ 0xC0000162, "STATUS_UNMAPPABLE_CHARACTER" },
{ 0xC0000163, "STATUS_UNDEFINED_CHARACTER" },
{ 0xC0000164, "STATUS_FLOPPY_VOLUME" },
{ 0xC0000165, "STATUS_FLOPPY_ID_MARK_NOT_FOUND" },
{ 0xC0000166, "STATUS_FLOPPY_WRONG_CYLINDER" },
{ 0xC0000167, "STATUS_FLOPPY_UNKNOWN_ERROR" },
{ 0xC0000168, "STATUS_FLOPPY_BAD_REGISTERS" },
{ 0xC0000169, "STATUS_DISK_RECALIBRATE_FAILED" },
{ 0xC000016A, "STATUS_DISK_OPERATION_FAILED" },
{ 0xC000016B, "STATUS_DISK_RESET_FAILED" },
{ 0xC000016C, "STATUS_SHARED_IRQ_BUSY" },
{ 0xC000016D, "STATUS_FT_ORPHANING" },
{ 0xC000016E, "STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT" },
{ 0xC0000172, "STATUS_PARTITION_FAILURE" },
{ 0xC0000173, "STATUS_INVALID_BLOCK_LENGTH" },
{ 0xC0000174, "STATUS_DEVICE_NOT_PARTITIONED" },
{ 0xC0000175, "STATUS_UNABLE_TO_LOCK_MEDIA" },
{ 0xC0000176, "STATUS_UNABLE_TO_UNLOAD_MEDIA" },
{ 0xC0000177, "STATUS_EOM_OVERFLOW" },
{ 0xC0000178, "STATUS_NO_MEDIA" },
{ 0xC000017A, "STATUS_NO_SUCH_MEMBER" },
{ 0xC000017B, "STATUS_INVALID_MEMBER" },
{ 0xC000017C, "STATUS_KEY_DELETED" },
{ 0xC000017D, "STATUS_NO_LOG_SPACE" },
{ 0xC000017E, "STATUS_TOO_MANY_SIDS" },
{ 0xC000017F, "STATUS_LM_CROSS_ENCRYPTION_REQUIRED" },
{ 0xC0000180, "STATUS_KEY_HAS_CHILDREN" },
{ 0xC0000181, "STATUS_CHILD_MUST_BE_VOLATILE" },
{ 0xC0000182, "STATUS_DEVICE_CONFIGURATION_ERROR" },
{ 0xC0000183, "STATUS_DRIVER_INTERNAL_ERROR" },
{ 0xC0000184, "STATUS_INVALID_DEVICE_STATE" },
{ 0xC0000185, "STATUS_IO_DEVICE_ERROR" },
{ 0xC0000186, "STATUS_DEVICE_PROTOCOL_ERROR" },
{ 0xC0000187, "STATUS_BACKUP_CONTROLLER" },
{ 0xC0000188, "STATUS_LOG_FILE_FULL" },
{ 0xC0000189, "STATUS_TOO_LATE" },
{ 0xC000018A, "STATUS_NO_TRUST_LSA_SECRET" },
{ 0xC000018B, "STATUS_NO_TRUST_SAM_ACCOUNT" },
{ 0xC000018C, "STATUS_TRUSTED_DOMAIN_FAILURE" },
{ 0xC000018D, "STATUS_TRUSTED_RELATIONSHIP_FAILURE" },
{ 0xC000018E, "STATUS_EVENTLOG_FILE_CORRUPT" },
{ 0xC000018F, "STATUS_EVENTLOG_CANT_START" },
{ 0xC0000190, "STATUS_TRUST_FAILURE" },
{ 0xC0000191, "STATUS_MUTANT_LIMIT_EXCEEDED" },
{ 0xC0000192, "STATUS_NETLOGON_NOT_STARTED" },
{ 0xC0000193, "STATUS_ACCOUNT_EXPIRED" },
{ 0xC0000194, "STATUS_POSSIBLE_DEADLOCK" },
{ 0xC0000195, "STATUS_NETWORK_CREDENTIAL_CONFLICT" },
{ 0xC0000196, "STATUS_REMOTE_SESSION_LIMIT" },
{ 0xC0000197, "STATUS_EVENTLOG_FILE_CHANGED" },
{ 0xC0000198, "STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT" },
{ 0xC0000199, "STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT" },
{ 0xC000019A, "STATUS_NOLOGON_SERVER_TRUST_ACCOUNT" },
{ 0xC000019B, "STATUS_DOMAIN_TRUST_INCONSISTENT" },
{ 0xC000019C, "STATUS_FS_DRIVER_REQUIRED" },
{ 0xC0000202, "STATUS_NO_USER_SESSION_KEY" },
{ 0xC0000203, "STATUS_USER_SESSION_DELETED" },
{ 0xC0000204, "STATUS_RESOURCE_LANG_NOT_FOUND" },
{ 0xC0000205, "STATUS_INSUFF_SERVER_RESOURCES" },
{ 0xC0000206, "STATUS_INVALID_BUFFER_SIZE" },
{ 0xC0000207, "STATUS_INVALID_ADDRESS_COMPONENT" },
{ 0xC0000208, "STATUS_INVALID_ADDRESS_WILDCARD" },
{ 0xC0000209, "STATUS_TOO_MANY_ADDRESSES" },
{ 0xC000020A, "STATUS_ADDRESS_ALREADY_EXISTS" },
{ 0xC000020B, "STATUS_ADDRESS_CLOSED" },
{ 0xC000020C, "STATUS_CONNECTION_DISCONNECTED" },
{ 0xC000020D, "STATUS_CONNECTION_RESET" },
{ 0xC000020E, "STATUS_TOO_MANY_NODES" },
{ 0xC000020F, "STATUS_TRANSACTION_ABORTED" },
{ 0xC0000210, "STATUS_TRANSACTION_TIMED_OUT" },
{ 0xC0000211, "STATUS_TRANSACTION_NO_RELEASE" },
{ 0xC0000212, "STATUS_TRANSACTION_NO_MATCH" },
{ 0xC0000213, "STATUS_TRANSACTION_RESPONDED" },
{ 0xC0000214, "STATUS_TRANSACTION_INVALID_ID" },
{ 0xC0000215, "STATUS_TRANSACTION_INVALID_TYPE" },
{ 0xC0000216, "STATUS_NOT_SERVER_SESSION" },
{ 0xC0000217, "STATUS_NOT_CLIENT_SESSION" },
{ 0xC0000218, "STATUS_CANNOT_LOAD_REGISTRY_FILE" },
{ 0xC0000219, "STATUS_DEBUG_ATTACH_FAILED" },
{ 0xC000021A, "STATUS_SYSTEM_PROCESS_TERMINATED" },
{ 0xC000021B, "STATUS_DATA_NOT_ACCEPTED" },
{ 0xC000021C, "STATUS_NO_BROWSER_SERVERS_FOUND" },
{ 0xC000021D, "STATUS_VDM_HARD_ERROR" },
{ 0xC000021E, "STATUS_DRIVER_CANCEL_TIMEOUT" },
{ 0xC000021F, "STATUS_REPLY_MESSAGE_MISMATCH" },
{ 0xC0000220, "STATUS_MAPPED_ALIGNMENT" },
{ 0xC0000221, "STATUS_IMAGE_CHECKSUM_MISMATCH" },
{ 0xC0000222, "STATUS_LOST_WRITEBEHIND_DATA" },
{ 0xC0000223, "STATUS_CLIENT_SERVER_PARAMETERS_INVALID" },
{ 0xC0000224, "STATUS_PASSWORD_MUST_CHANGE" },
{ 0xC0000225, "STATUS_NOT_FOUND" },
{ 0xC0000226, "STATUS_NOT_TINY_STREAM" },
{ 0xC0000227, "STATUS_RECOVERY_FAILURE" },
{ 0xC0000228, "STATUS_STACK_OVERFLOW_READ" },
{ 0xC0000229, "STATUS_FAIL_CHECK" },
{ 0xC000022A, "STATUS_DUPLICATE_OBJECTID" },
{ 0xC000022B, "STATUS_OBJECTID_EXISTS" },
{ 0xC000022C, "STATUS_CONVERT_TO_LARGE" },
{ 0xC000022D, "STATUS_RETRY" },
{ 0xC000022E, "STATUS_FOUND_OUT_OF_SCOPE" },
{ 0xC000022F, "STATUS_ALLOCATE_BUCKET" },
{ 0xC0000230, "STATUS_PROPSET_NOT_FOUND" },
{ 0xC0000231, "STATUS_MARSHALL_OVERFLOW" },
{ 0xC0000232, "STATUS_INVALID_VARIANT" },
{ 0xC0000233, "STATUS_DOMAIN_CONTROLLER_NOT_FOUND" },
{ 0xC0000234, "STATUS_ACCOUNT_LOCKED_OUT" },
{ 0xC0000235, "STATUS_HANDLE_NOT_CLOSABLE" },
{ 0xC0000236, "STATUS_CONNECTION_REFUSED" },
{ 0xC0000237, "STATUS_GRACEFUL_DISCONNECT" },
{ 0xC0000238, "STATUS_ADDRESS_ALREADY_ASSOCIATED" },
{ 0xC0000239, "STATUS_ADDRESS_NOT_ASSOCIATED" },
{ 0xC000023A, "STATUS_CONNECTION_INVALID" },
{ 0xC000023B, "STATUS_CONNECTION_ACTIVE" },
{ 0xC000023C, "STATUS_NETWORK_UNREACHABLE" },
{ 0xC000023D, "STATUS_HOST_UNREACHABLE" },
{ 0xC000023E, "STATUS_PROTOCOL_UNREACHABLE" },
{ 0xC000023F, "STATUS_PORT_UNREACHABLE" },
{ 0xC0000240, "STATUS_REQUEST_ABORTED" },
{ 0xC0000241, "STATUS_CONNECTION_ABORTED" },
{ 0xC0000242, "STATUS_BAD_COMPRESSION_BUFFER" },
{ 0xC0000243, "STATUS_USER_MAPPED_FILE" },
{ 0xC0000244, "STATUS_AUDIT_FAILED" },
{ 0xC0000245, "STATUS_TIMER_RESOLUTION_NOT_SET" },
{ 0xC0000246, "STATUS_CONNECTION_COUNT_LIMIT" },
{ 0xC0000247, "STATUS_LOGIN_TIME_RESTRICTION" },
{ 0xC0000248, "STATUS_LOGIN_WKSTA_RESTRICTION" },
{ 0xC0000249, "STATUS_IMAGE_MP_UP_MISMATCH" },
{ 0xC0000250, "STATUS_INSUFFICIENT_LOGON_INFO" },
{ 0xC0000251, "STATUS_BAD_DLL_ENTRYPOINT" },
{ 0xC0000252, "STATUS_BAD_SERVICE_ENTRYPOINT" },
{ 0xC0000253, "STATUS_LPC_REPLY_LOST" },
{ 0xC0000254, "STATUS_IP_ADDRESS_CONFLICT1" },
{ 0xC0000255, "STATUS_IP_ADDRESS_CONFLICT2" },
{ 0xC0000256, "STATUS_REGISTRY_QUOTA_LIMIT" },
{ 0xC0000257, "STATUS_PATH_NOT_COVERED" },
{ 0xC0000258, "STATUS_NO_CALLBACK_ACTIVE" },
{ 0xC0000259, "STATUS_LICENSE_QUOTA_EXCEEDED" },
{ 0xC000025A, "STATUS_PWD_TOO_SHORT" },
{ 0xC000025B, "STATUS_PWD_TOO_RECENT" },
{ 0xC000025C, "STATUS_PWD_HISTORY_CONFLICT" },
{ 0xC000025E, "STATUS_PLUGPLAY_NO_DEVICE" },
{ 0xC000025F, "STATUS_UNSUPPORTED_COMPRESSION" },
{ 0xC0000260, "STATUS_INVALID_HW_PROFILE" },
{ 0xC0000261, "STATUS_INVALID_PLUGPLAY_DEVICE_PATH" },
{ 0xC0000262, "STATUS_DRIVER_ORDINAL_NOT_FOUND" },
{ 0xC0000263, "STATUS_DRIVER_ENTRYPOINT_NOT_FOUND" },
{ 0xC0000264, "STATUS_RESOURCE_NOT_OWNED" },
{ 0xC0000265, "STATUS_TOO_MANY_LINKS" },
{ 0xC0000266, "STATUS_QUOTA_LIST_INCONSISTENT" },
{ 0xC0000267, "STATUS_FILE_IS_OFFLINE" },
{ 0xC0000268, "STATUS_EVALUATION_EXPIRATION" },
{ 0xC0000269, "STATUS_ILLEGAL_DLL_RELOCATION" },
{ 0xC000026A, "STATUS_LICENSE_VIOLATION" },
{ 0xC000026B, "STATUS_DLL_INIT_FAILED_LOGOFF" },
{ 0xC000026C, "STATUS_DRIVER_UNABLE_TO_LOAD" },
{ 0xC000026D, "STATUS_DFS_UNAVAILABLE" },
{ 0xC000026E, "STATUS_VOLUME_DISMOUNTED" },
{ 0xC000026F, "STATUS_WX86_INTERNAL_ERROR" },
{ 0xC0000270, "STATUS_WX86_FLOAT_STACK_CHECK" },
{ 0xC0000271, "STATUS_VALIDATE_CONTINUE" },
{ 0xC0000272, "STATUS_NO_MATCH" },
{ 0xC0000273, "STATUS_NO_MORE_MATCHES" },
{ 0xC0000275, "STATUS_NOT_A_REPARSE_POINT" },
{ 0xC0000276, "STATUS_IO_REPARSE_TAG_INVALID" },
{ 0xC0000277, "STATUS_IO_REPARSE_TAG_MISMATCH" },
{ 0xC0000278, "STATUS_IO_REPARSE_DATA_INVALID" },
{ 0xC0000279, "STATUS_IO_REPARSE_TAG_NOT_HANDLED" },
{ 0xC0000280, "STATUS_REPARSE_POINT_NOT_RESOLVED" },
{ 0xC0000281, "STATUS_DIRECTORY_IS_A_REPARSE_POINT" },
{ 0xC0000282, "STATUS_RANGE_LIST_CONFLICT" },
{ 0xC0000283, "STATUS_SOURCE_ELEMENT_EMPTY" },
{ 0xC0000284, "STATUS_DESTINATION_ELEMENT_FULL" },
{ 0xC0000285, "STATUS_ILLEGAL_ELEMENT_ADDRESS" },
{ 0xC0000286, "STATUS_MAGAZINE_NOT_PRESENT" },
{ 0xC0000287, "STATUS_REINITIALIZATION_NEEDED" },
{ 0x80000288, "STATUS_DEVICE_REQUIRES_CLEANING" },
{ 0x80000289, "STATUS_DEVICE_DOOR_OPEN" },
{ 0xC000028A, "STATUS_ENCRYPTION_FAILED" },
{ 0xC000028B, "STATUS_DECRYPTION_FAILED" },
{ 0xC000028C, "STATUS_RANGE_NOT_FOUND" },
{ 0xC000028D, "STATUS_NO_RECOVERY_POLICY" },
{ 0xC000028E, "STATUS_NO_EFS" },
{ 0xC000028F, "STATUS_WRONG_EFS" },
{ 0xC0000290, "STATUS_NO_USER_KEYS" },
{ 0xC0000291, "STATUS_FILE_NOT_ENCRYPTED" },
{ 0xC0000292, "STATUS_NOT_EXPORT_FORMAT" },
{ 0xC0000293, "STATUS_FILE_ENCRYPTED" },
{ 0x40000294, "STATUS_WAKE_SYSTEM" },
{ 0xC0000295, "STATUS_WMI_GUID_NOT_FOUND" },
{ 0xC0000296, "STATUS_WMI_INSTANCE_NOT_FOUND" },
{ 0xC0000297, "STATUS_WMI_ITEMID_NOT_FOUND" },
{ 0xC0000298, "STATUS_WMI_TRY_AGAIN" },
{ 0xC0000299, "STATUS_SHARED_POLICY" },
{ 0xC000029A, "STATUS_POLICY_OBJECT_NOT_FOUND" },
{ 0xC000029B, "STATUS_POLICY_ONLY_IN_DS" },
{ 0xC000029C, "STATUS_VOLUME_NOT_UPGRADED" },
{ 0xC000029D, "STATUS_REMOTE_STORAGE_NOT_ACTIVE" },
{ 0xC000029E, "STATUS_REMOTE_STORAGE_MEDIA_ERROR" },
{ 0xC000029F, "STATUS_NO_TRACKING_SERVICE" },
{ 0xC00002A0, "STATUS_SERVER_SID_MISMATCH" },
{ 0xC00002A1, "STATUS_DS_NO_ATTRIBUTE_OR_VALUE" },
{ 0xC00002A2, "STATUS_DS_INVALID_ATTRIBUTE_SYNTAX" },
{ 0xC00002A3, "STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED" },
{ 0xC00002A4, "STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS" },
{ 0xC00002A5, "STATUS_DS_BUSY" },
{ 0xC00002A6, "STATUS_DS_UNAVAILABLE" },
{ 0xC00002A7, "STATUS_DS_NO_RIDS_ALLOCATED" },
{ 0xC00002A8, "STATUS_DS_NO_MORE_RIDS" },
{ 0xC00002A9, "STATUS_DS_INCORRECT_ROLE_OWNER" },
{ 0xC00002AA, "STATUS_DS_RIDMGR_INIT_ERROR" },
{ 0xC00002AB, "STATUS_DS_OBJ_CLASS_VIOLATION" },
{ 0xC00002AC, "STATUS_DS_CANT_ON_NON_LEAF" },
{ 0xC00002AD, "STATUS_DS_CANT_ON_RDN" },
{ 0xC00002AE, "STATUS_DS_CANT_MOD_OBJ_CLASS" },
{ 0xC00002AF, "STATUS_DS_CROSS_DOM_MOVE_FAILED" },
{ 0xC00002B0, "STATUS_DS_GC_NOT_AVAILABLE" },
{ 0xC00002B1, "STATUS_DIRECTORY_SERVICE_REQUIRED" },
{ 0xC00002B2, "STATUS_REPARSE_ATTRIBUTE_CONFLICT" },
{ 0xC00002B3, "STATUS_CANT_ENABLE_DENY_ONLY" },
{ 0xC00002B4, "STATUS_FLOAT_MULTIPLE_FAULTS" },
{ 0xC00002B5, "STATUS_FLOAT_MULTIPLE_TRAPS" },
{ 0xC00002B6, "STATUS_DEVICE_REMOVED" },
{ 0xC00002B7, "STATUS_JOURNAL_DELETE_IN_PROGRESS" },
{ 0xC00002B8, "STATUS_JOURNAL_NOT_ACTIVE" },
{ 0xC00002B9, "STATUS_NOINTERFACE" },
{ 0xC00002C1, "STATUS_DS_ADMIN_LIMIT_EXCEEDED" },
{ 0xC00002C2, "STATUS_DRIVER_FAILED_SLEEP" },
{ 0xC00002C3, "STATUS_MUTUAL_AUTHENTICATION_FAILED" },
{ 0xC00002C4, "STATUS_CORRUPT_SYSTEM_FILE" },
{ 0xC00002C5, "STATUS_DATATYPE_MISALIGNMENT_ERROR" },
{ 0xC00002C6, "STATUS_WMI_READ_ONLY" },
{ 0xC00002C7, "STATUS_WMI_SET_FAILURE" },
{ 0xC00002C8, "STATUS_COMMITMENT_MINIMUM" },
{ 0xC00002C9, "STATUS_REG_NAT_CONSUMPTION" },
{ 0xC00002CA, "STATUS_TRANSPORT_FULL" },
{ 0xC00002CB, "STATUS_DS_SAM_INIT_FAILURE" },
{ 0xC00002CC, "STATUS_ONLY_IF_CONNECTED" },
{ 0xC00002CD, "STATUS_DS_SENSITIVE_GROUP_VIOLATION" },
{ 0xC00002CE, "STATUS_PNP_RESTART_ENUMERATION" },
{ 0xC00002CF, "STATUS_JOURNAL_ENTRY_DELETED" },
{ 0xC00002D0, "STATUS_DS_CANT_MOD_PRIMARYGROUPID" },
{ 0xC00002D1, "STATUS_SYSTEM_IMAGE_BAD_SIGNATURE" },
{ 0xC00002D2, "STATUS_PNP_REBOOT_REQUIRED" },
{ 0xC00002D3, "STATUS_POWER_STATE_INVALID" },
{ 0xC00002D4, "STATUS_DS_INVALID_GROUP_TYPE" },
{ 0xC00002D5, "STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN" },
{ 0xC00002D6, "STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN" },
{ 0xC00002D7, "STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER" },
{ 0xC00002D8, "STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER" },
{ 0xC00002D9, "STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER" },
{ 0xC00002DA, "STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER" },
{ 0xC00002DB, "STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER" },
{ 0xC00002DC, "STATUS_DS_HAVE_PRIMARY_MEMBERS" },
{ 0xC00002DD, "STATUS_WMI_NOT_SUPPORTED" },
{ 0xC00002DE, "STATUS_INSUFFICIENT_POWER" },
{ 0xC00002DF, "STATUS_SAM_NEED_BOOTKEY_PASSWORD" },
{ 0xC00002E0, "STATUS_SAM_NEED_BOOTKEY_FLOPPY" },
{ 0xC00002E1, "STATUS_DS_CANT_START" },
{ 0xC00002E2, "STATUS_DS_INIT_FAILURE" },
{ 0xC00002E3, "STATUS_SAM_INIT_FAILURE" },
{ 0xC00002E4, "STATUS_DS_GC_REQUIRED" },
{ 0xC00002E5, "STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY" },
{ 0xC00002E6, "STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS" },
{ 0xC00002E7, "STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED" },
{ 0xC00002E8, "STATUS_MULTIPLE_FAULT_VIOLATION" },
{ 0xC0000300, "STATUS_NOT_SUPPORTED_ON_SBS" },
{ 0xC0009898, "STATUS_WOW_ASSERTION" },
{ 0xC0020001, "RPC_NT_INVALID_STRING_BINDING" },
{ 0xC0020002, "RPC_NT_WRONG_KIND_OF_BINDING" },
{ 0xC0020003, "RPC_NT_INVALID_BINDING" },
{ 0xC0020004, "RPC_NT_PROTSEQ_NOT_SUPPORTED" },
{ 0xC0020005, "RPC_NT_INVALID_RPC_PROTSEQ" },
{ 0xC0020006, "RPC_NT_INVALID_STRING_UUID" },
{ 0xC0020007, "RPC_NT_INVALID_ENDPOINT_FORMAT" },
{ 0xC0020008, "RPC_NT_INVALID_NET_ADDR" },
{ 0xC0020009, "RPC_NT_NO_ENDPOINT_FOUND" },
{ 0xC002000A, "RPC_NT_INVALID_TIMEOUT" },
{ 0xC002000B, "RPC_NT_OBJECT_NOT_FOUND" },
{ 0xC002000C, "RPC_NT_ALREADY_REGISTERED" },
{ 0xC002000D, "RPC_NT_TYPE_ALREADY_REGISTERED" },
{ 0xC002000E, "RPC_NT_ALREADY_LISTENING" },
{ 0xC002000F, "RPC_NT_NO_PROTSEQS_REGISTERED" },
{ 0xC0020010, "RPC_NT_NOT_LISTENING" },
{ 0xC0020011, "RPC_NT_UNKNOWN_MGR_TYPE" },
{ 0xC0020012, "RPC_NT_UNKNOWN_IF" },
{ 0xC0020013, "RPC_NT_NO_BINDINGS" },
{ 0xC0020014, "RPC_NT_NO_PROTSEQS" },
{ 0xC0020015, "RPC_NT_CANT_CREATE_ENDPOINT" },
{ 0xC0020016, "RPC_NT_OUT_OF_RESOURCES" },
{ 0xC0020017, "RPC_NT_SERVER_UNAVAILABLE" },
{ 0xC0020018, "RPC_NT_SERVER_TOO_BUSY" },
{ 0xC0020019, "RPC_NT_INVALID_NETWORK_OPTIONS" },
{ 0xC002001A, "RPC_NT_NO_CALL_ACTIVE" },
{ 0xC002001B, "RPC_NT_CALL_FAILED" },
{ 0xC002001C, "RPC_NT_CALL_FAILED_DNE" },
{ 0xC002001D, "RPC_NT_PROTOCOL_ERROR" },
{ 0xC002001F, "RPC_NT_UNSUPPORTED_TRANS_SYN" },
{ 0xC0020021, "RPC_NT_UNSUPPORTED_TYPE" },
{ 0xC0020022, "RPC_NT_INVALID_TAG" },
{ 0xC0020023, "RPC_NT_INVALID_BOUND" },
{ 0xC0020024, "RPC_NT_NO_ENTRY_NAME" },
{ 0xC0020025, "RPC_NT_INVALID_NAME_SYNTAX" },
{ 0xC0020026, "RPC_NT_UNSUPPORTED_NAME_SYNTAX" },
{ 0xC0020028, "RPC_NT_UUID_NO_ADDRESS" },
{ 0xC0020029, "RPC_NT_DUPLICATE_ENDPOINT" },
{ 0xC002002A, "RPC_NT_UNKNOWN_AUTHN_TYPE" },
{ 0xC002002B, "RPC_NT_MAX_CALLS_TOO_SMALL" },
{ 0xC002002C, "RPC_NT_STRING_TOO_LONG" },
{ 0xC002002D, "RPC_NT_PROTSEQ_NOT_FOUND" },
{ 0xC002002E, "RPC_NT_PROCNUM_OUT_OF_RANGE" },
{ 0xC002002F, "RPC_NT_BINDING_HAS_NO_AUTH" },
{ 0xC0020030, "RPC_NT_UNKNOWN_AUTHN_SERVICE" },
{ 0xC0020031, "RPC_NT_UNKNOWN_AUTHN_LEVEL" },
{ 0xC0020032, "RPC_NT_INVALID_AUTH_IDENTITY" },
{ 0xC0020033, "RPC_NT_UNKNOWN_AUTHZ_SERVICE" },
{ 0xC0020034, "EPT_NT_INVALID_ENTRY" },
{ 0xC0020035, "EPT_NT_CANT_PERFORM_OP" },
{ 0xC0020036, "EPT_NT_NOT_REGISTERED" },
{ 0xC0020037, "RPC_NT_NOTHING_TO_EXPORT" },
{ 0xC0020038, "RPC_NT_INCOMPLETE_NAME" },
{ 0xC0020039, "RPC_NT_INVALID_VERS_OPTION" },
{ 0xC002003A, "RPC_NT_NO_MORE_MEMBERS" },
{ 0xC002003B, "RPC_NT_NOT_ALL_OBJS_UNEXPORTED" },
{ 0xC002003C, "RPC_NT_INTERFACE_NOT_FOUND" },
{ 0xC002003D, "RPC_NT_ENTRY_ALREADY_EXISTS" },
{ 0xC002003E, "RPC_NT_ENTRY_NOT_FOUND" },
{ 0xC002003F, "RPC_NT_NAME_SERVICE_UNAVAILABLE" },
{ 0xC0020040, "RPC_NT_INVALID_NAF_ID" },
{ 0xC0020041, "RPC_NT_CANNOT_SUPPORT" },
{ 0xC0020042, "RPC_NT_NO_CONTEXT_AVAILABLE" },
{ 0xC0020043, "RPC_NT_INTERNAL_ERROR" },
{ 0xC0020044, "RPC_NT_ZERO_DIVIDE" },
{ 0xC0020045, "RPC_NT_ADDRESS_ERROR" },
{ 0xC0020046, "RPC_NT_FP_DIV_ZERO" },
{ 0xC0020047, "RPC_NT_FP_UNDERFLOW" },
{ 0xC0020048, "RPC_NT_FP_OVERFLOW" },
{ 0xC0021007, "RPC_P_RECEIVE_ALERTED" },
{ 0xC0021008, "RPC_P_CONNECTION_CLOSED" },
{ 0xC0021009, "RPC_P_RECEIVE_FAILED" },
{ 0xC002100A, "RPC_P_SEND_FAILED" },
{ 0xC002100B, "RPC_P_TIMEOUT" },
{ 0xC002100C, "RPC_P_SERVER_TRANSPORT_ERROR" },
{ 0xC002100E, "RPC_P_EXCEPTION_OCCURRED" },
{ 0xC0021012, "RPC_P_CONNECTION_SHUTDOWN" },
{ 0xC0021015, "RPC_P_THREAD_LISTENING" },
{ 0xC0030001, "RPC_NT_NO_MORE_ENTRIES" },
{ 0xC0030002, "RPC_NT_SS_CHAR_TRANS_OPEN_FAIL" },
{ 0xC0030003, "RPC_NT_SS_CHAR_TRANS_SHORT_FILE" },
{ 0xC0030004, "RPC_NT_SS_IN_NULL_CONTEXT" },
{ 0xC0030005, "RPC_NT_SS_CONTEXT_MISMATCH" },
{ 0xC0030006, "RPC_NT_SS_CONTEXT_DAMAGED" },
{ 0xC0030007, "RPC_NT_SS_HANDLES_MISMATCH" },
{ 0xC0030008, "RPC_NT_SS_CANNOT_GET_CALL_HANDLE" },
{ 0xC0030009, "RPC_NT_NULL_REF_POINTER" },
{ 0xC003000A, "RPC_NT_ENUM_VALUE_OUT_OF_RANGE" },
{ 0xC003000B, "RPC_NT_BYTE_COUNT_TOO_SMALL" },
{ 0xC003000C, "RPC_NT_BAD_STUB_DATA" },
{ 0xC0020049, "RPC_NT_CALL_IN_PROGRESS" },
{ 0xC002004A, "RPC_NT_NO_MORE_BINDINGS" },
{ 0xC002004B, "RPC_NT_GROUP_MEMBER_NOT_FOUND" },
{ 0xC002004C, "EPT_NT_CANT_CREATE" },
{ 0xC002004D, "RPC_NT_INVALID_OBJECT" },
{ 0xC002004F, "RPC_NT_NO_INTERFACES" },
{ 0xC0020050, "RPC_NT_CALL_CANCELLED" },
{ 0xC0020051, "RPC_NT_BINDING_INCOMPLETE" },
{ 0xC0020052, "RPC_NT_COMM_FAILURE" },
{ 0xC0020053, "RPC_NT_UNSUPPORTED_AUTHN_LEVEL" },
{ 0xC0020054, "RPC_NT_NO_PRINC_NAME" },
{ 0xC0020055, "RPC_NT_NOT_RPC_ERROR" },
{ 0x40020056, "RPC_NT_UUID_LOCAL_ONLY" },
{ 0xC0020057, "RPC_NT_SEC_PKG_ERROR" },
{ 0xC0020058, "RPC_NT_NOT_CANCELLED" },
{ 0xC0030059, "RPC_NT_INVALID_ES_ACTION" },
{ 0xC003005A, "RPC_NT_WRONG_ES_VERSION" },
{ 0xC003005B, "RPC_NT_WRONG_STUB_VERSION" },
{ 0xC003005C, "RPC_NT_INVALID_PIPE_OBJECT" },
{ 0xC003005D, "RPC_NT_INVALID_PIPE_OPERATION" },
{ 0xC003005E, "RPC_NT_WRONG_PIPE_VERSION" },
{ 0x400200AF, "RPC_NT_SEND_INCOMPLETE" },
{ 0, NULL }
};
/*
* return an NT error string from a SMB buffer
*/
const char *
nt_errstr(uint32_t err)
{
static char ret[128];
int i;
ret[0] = 0;
for (i = 0; nt_errors[i].name; i++) {
if (err == nt_errors[i].code)
return nt_errors[i].name;
}
snprintf(ret, sizeof(ret), "0x%08x", err);
return ret;
}
diff --git a/contrib/tcpdump/status-exit-codes.h b/contrib/tcpdump/status-exit-codes.h
index 34d9d16b3c68..1fc350265d9b 100644
--- a/contrib/tcpdump/status-exit-codes.h
+++ b/contrib/tcpdump/status-exit-codes.h
@@ -1,32 +1,31 @@
/*
* Copyright (c) 2018 The TCPDUMP project
* 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, 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.
*/
#ifndef status_exit_codes_h
#define status_exit_codes_h
/* S_ERR_ND_* are libnetdissect status */
typedef enum {
S_SUCCESS = 0, /* not a libnetdissect status */
S_ERR_HOST_PROGRAM = 1, /* not a libnetdissect status */
- S_ERR_ND_NO_PRINTER = 11,
S_ERR_ND_MEM_ALLOC = 12,
S_ERR_ND_OPEN_FILE = 13,
S_ERR_ND_WRITE_FILE = 14,
S_ERR_ND_ESP_SECRET = 15
} status_exit_codes_t;
#endif /* status_exit_codes_h */
diff --git a/contrib/tcpdump/strtoaddr.c b/contrib/tcpdump/strtoaddr.c
index c6f79d9a6ec4..bf8a9d3d5250 100644
--- a/contrib/tcpdump/strtoaddr.c
+++ b/contrib/tcpdump/strtoaddr.c
@@ -1,235 +1,233 @@
/*
* Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1996,1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#include <stddef.h>
#include <string.h>
#include "netdissect-ctype.h"
#include "strtoaddr.h"
#ifndef NS_INADDRSZ
#define NS_INADDRSZ 4 /* IPv4 T_A */
#endif
#ifndef NS_IN6ADDRSZ
#define NS_IN6ADDRSZ 16 /* IPv6 T_AAAA */
#endif
#ifndef NS_INT16SZ
#define NS_INT16SZ 2 /* #/bytes of data in a uint16_t */
#endif
/*%
* WARNING: Don't even consider trying to compile this on a system where
* sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
*/
/* int
* strtoaddr(src, dst)
* convert presentation level IPv4 address to network order binary form.
* return:
* 1 if `src' is a valid input, else 0.
* notice:
* does not touch `dst' unless it's returning 1.
* author:
* Paul Vixie, 1996.
*/
int
strtoaddr(const char *src, void *dst)
{
uint32_t val;
u_int digit;
ptrdiff_t n;
unsigned char c;
u_int parts[4];
u_int *pp = parts;
c = *src;
for (;;) {
/*
* Collect number up to ``.''.
* Values are specified as for C:
* 0x=hex, 0=octal, isdigit=decimal.
*/
if (!ND_ASCII_ISDIGIT(c))
return (0);
val = 0;
if (c == '0') {
c = *++src;
if (c == 'x' || c == 'X')
return (0);
else if (ND_ASCII_ISDIGIT(c) && c != '9')
return (0);
}
for (;;) {
if (ND_ASCII_ISDIGIT(c)) {
digit = c - '0';
val = (val * 10) + digit;
c = *++src;
} else
break;
}
if (c == '.') {
/*
* Internet format:
* a.b.c.d
* a.b.c (with c treated as 16 bits)
* a.b (with b treated as 24 bits)
* a (with a treated as 32 bits)
*/
if (pp >= parts + 3)
return (0);
*pp++ = val;
c = *++src;
} else
break;
}
/*
* Check for trailing characters.
*/
if (c != '\0' && c != ' ' && c != '\t')
return (0);
/*
* Find the number of parts specified.
* It must be 4; we only support dotted quads, we don't
* support shorthand.
*/
n = pp - parts + 1;
if (n != 4)
return (0);
/*
* parts[0-2] were set to the first 3 parts of the address;
* val was set to the 4th part.
*
* Check if any part is bigger than 255.
*/
if ((parts[0] | parts[1] | parts[2] | val) > 0xff)
return (0);
/*
* Add the other three parts to val.
*/
val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
if (dst) {
val = htonl(val);
memcpy(dst, &val, NS_INADDRSZ);
}
return (1);
}
/* int
* strtoaddr6(src, dst)
* convert presentation level IPv6 address to network order binary form.
* return:
* 1 if `src' is a valid [RFC1884 2.2] address, else 0.
* notice:
* (1) does not touch `dst' unless it's returning 1.
* (2) :: in a full address is silently ignored.
* credit:
* inspired by Mark Andrews.
* author:
* Paul Vixie, 1996.
*/
int
strtoaddr6(const char *src, void *dst)
{
static const char xdigits_l[] = "0123456789abcdef",
xdigits_u[] = "0123456789ABCDEF";
u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
const char *xdigits, *curtok;
int ch, seen_xdigits;
u_int val;
memset((tp = tmp), '\0', NS_IN6ADDRSZ);
endp = tp + NS_IN6ADDRSZ;
colonp = NULL;
/* Leading :: requires some special handling. */
if (*src == ':')
if (*++src != ':')
return (0);
curtok = src;
seen_xdigits = 0;
val = 0;
while ((ch = *src++) != '\0') {
const char *pch;
if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
pch = strchr((xdigits = xdigits_u), ch);
if (pch != NULL) {
val <<= 4;
val |= (int)(pch - xdigits);
if (++seen_xdigits > 4)
return (0);
continue;
}
if (ch == ':') {
curtok = src;
if (!seen_xdigits) {
if (colonp)
return (0);
colonp = tp;
continue;
} else if (*src == '\0')
return (0);
if (tp + NS_INT16SZ > endp)
return (0);
*tp++ = (u_char) (val >> 8) & 0xff;
*tp++ = (u_char) val & 0xff;
seen_xdigits = 0;
val = 0;
continue;
}
if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
strtoaddr(curtok, tp) > 0) {
tp += NS_INADDRSZ;
seen_xdigits = 0;
break; /*%< '\\0' was seen by strtoaddr(). */
}
return (0);
}
if (seen_xdigits) {
if (tp + NS_INT16SZ > endp)
return (0);
*tp++ = (u_char) (val >> 8) & 0xff;
*tp++ = (u_char) val & 0xff;
}
if (colonp != NULL) {
/*
* Since some memmove()'s erroneously fail to handle
* overlapping regions, we'll do the shift by hand.
*/
const ptrdiff_t n = tp - colonp;
int i;
if (tp == endp)
return (0);
for (i = 1; i <= n; i++) {
endp[- i] = colonp[n - i];
colonp[n - i] = 0;
}
tp = endp;
}
if (tp != endp)
return (0);
memcpy(dst, tmp, NS_IN6ADDRSZ);
return (1);
}
diff --git a/contrib/tcpdump/tcp.h b/contrib/tcpdump/tcp.h
index 491157b0ae7d..b1ee4aa95f36 100644
--- a/contrib/tcpdump/tcp.h
+++ b/contrib/tcpdump/tcp.h
@@ -1,159 +1,159 @@
/*
* Copyright (c) 1982, 1986, 1993
* 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 the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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 BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)tcp.h 8.1 (Berkeley) 6/10/93
*/
/*
* TCP header.
* Per RFC 793, September, 1981.
*/
struct tcphdr {
nd_uint16_t th_sport; /* source port */
nd_uint16_t th_dport; /* destination port */
nd_uint32_t th_seq; /* sequence number */
nd_uint32_t th_ack; /* acknowledgement number */
nd_uint8_t th_offx2; /* data offset, rsvd */
nd_uint8_t th_flags;
nd_uint16_t th_win; /* window */
nd_uint16_t th_sum; /* checksum */
nd_uint16_t th_urp; /* urgent pointer */
};
#define TH_OFF(th) ((GET_U_1((th)->th_offx2) & 0xf0) >> 4)
/* TCP flags */
#define TH_FIN 0x01
#define TH_SYN 0x02
#define TH_RST 0x04
#define TH_PUSH 0x08
#define TH_ACK 0x10
#define TH_URG 0x20
#define TH_ECNECHO 0x40 /* ECN Echo */
#define TH_CWR 0x80 /* ECN Cwnd Reduced */
#define TCPOPT_EOL 0
#define TCPOPT_NOP 1
#define TCPOPT_MAXSEG 2
#define TCPOLEN_MAXSEG 4
#define TCPOPT_WSCALE 3 /* window scale factor (rfc1323) */
#define TCPOPT_SACKOK 4 /* selective ack ok (rfc2018) */
#define TCPOPT_SACK 5 /* selective ack (rfc2018) */
#define TCPOPT_ECHO 6 /* echo (rfc1072) */
#define TCPOPT_ECHOREPLY 7 /* echo (rfc1072) */
#define TCPOPT_TIMESTAMP 8 /* timestamp (rfc1323) */
#define TCPOLEN_TIMESTAMP 10
#define TCPOLEN_TSTAMP_APPA (TCPOLEN_TIMESTAMP+2) /* appendix A */
#define TCPOPT_CC 11 /* T/TCP CC options (rfc1644) */
#define TCPOPT_CCNEW 12 /* T/TCP CC options (rfc1644) */
#define TCPOPT_CCECHO 13 /* T/TCP CC options (rfc1644) */
#define TCPOPT_SIGNATURE 19 /* Keyed MD5 (rfc2385) */
#define TCPOLEN_SIGNATURE 18
#define TCP_SIGLEN 16 /* length of an option 19 digest */
#define TCPOPT_SCPS 20 /* SCPS-TP (CCSDS 714.0-B-2) */
#define TCPOPT_UTO 28 /* tcp user timeout (rfc5482) */
#define TCPOLEN_UTO 4
#define TCPOPT_TCPAO 29 /* TCP authentication option (rfc5925) */
#define TCPOPT_MPTCP 30 /* MPTCP options */
#define TCPOPT_FASTOPEN 34 /* TCP Fast Open (rfc7413) */
#define TCPOPT_EXPERIMENT2 254 /* experimental headers (rfc4727) */
#define TCPOPT_TSTAMP_HDR \
(TCPOPT_NOP<<24|TCPOPT_NOP<<16|TCPOPT_TIMESTAMP<<8|TCPOLEN_TIMESTAMP)
#ifndef FTP_PORT
#define FTP_PORT 21
#endif
#ifndef SSH_PORT
#define SSH_PORT 22
#endif
#ifndef TELNET_PORT
#define TELNET_PORT 23
#endif
#ifndef SMTP_PORT
#define SMTP_PORT 25
#endif
#ifndef WHOIS_PORT
#define WHOIS_PORT 43
#endif
#ifndef NAMESERVER_PORT
#define NAMESERVER_PORT 53
#endif
#ifndef HTTP_PORT
#define HTTP_PORT 80
#endif
#ifndef NETBIOS_SSN_PORT
#define NETBIOS_SSN_PORT 139 /* RFC 1001, RFC 1002 */
#endif
#ifndef BGP_PORT
#define BGP_PORT 179
#endif
#ifndef RPKI_RTR_PORT
#define RPKI_RTR_PORT 323
#endif
#ifndef SMB_PORT
#define SMB_PORT 445
#endif
#ifndef RTSP_PORT
#define RTSP_PORT 554
#endif
#ifndef MSDP_PORT
#define MSDP_PORT 639
#endif
#ifndef LDP_PORT
#define LDP_PORT 646
#endif
#ifndef PPTP_PORT
#define PPTP_PORT 1723
#endif
#ifndef NFS_PORT
#define NFS_PORT 2049
#endif
+#ifndef REDIS_PORT
+#define REDIS_PORT 6379
+#endif
#ifndef OPENFLOW_PORT_OLD
#define OPENFLOW_PORT_OLD 6633
#endif
#ifndef OPENFLOW_PORT_IANA
#define OPENFLOW_PORT_IANA 6653
#endif
#ifndef HTTP_PORT_ALT
#define HTTP_PORT_ALT 8080
#endif
#ifndef RTSP_PORT_ALT
#define RTSP_PORT_ALT 8554
#endif
#ifndef BEEP_PORT
#define BEEP_PORT 10288
#endif
-#ifndef REDIS_PORT
-#define REDIS_PORT 6379
-#endif
diff --git a/contrib/tcpdump/tcpdump.1.in b/contrib/tcpdump/tcpdump.1.in
index 87e0fbb8cf19..3ed261df6fe7 100644
--- a/contrib/tcpdump/tcpdump.1.in
+++ b/contrib/tcpdump/tcpdump.1.in
@@ -1,2090 +1,2069 @@
.\" $NetBSD: tcpdump.8,v 1.9 2003/03/31 00:18:17 perry Exp $
.\"
.\" Copyright (c) 1987, 1988, 1989, 1990, 1991, 1992, 1994, 1995, 1996, 1997
.\" The Regents of the University of California. All rights reserved.
.\" 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.
.\"
-.TH TCPDUMP 1 "12 March 2023"
+.TH TCPDUMP 1 "26 March 2024"
.SH NAME
tcpdump \- dump traffic on a network
.SH SYNOPSIS
.na
.B tcpdump
[
.B \-AbdDefhHIJKlLnNOpqStuUvxX#
] [
.B \-B
.I buffer_size
]
-.br
.ti +8
[
.B \-c
.I count
]
[
.B \-\-count
]
[
.B \-C
.I file_size
]
.ti +8
[
.B \-E
.I spi@ipaddr algo:secret,...
]
.ti +8
[
.B \-F
.I file
]
[
.B \-G
.I rotate_seconds
]
[
.B \-i
.I interface
]
.ti +8
[
.B \-\-immediate\-mode
]
[
.B \-j
.I tstamp_type
]
[
.B \-m
.I module
]
.ti +8
[
.B \-M
.I secret
]
[
.B \-\-number
]
[
.B \-\-print
]
[
.B \-Q
.I in|out|inout
]
.ti +8
[
.B \-r
.I file
]
[
.B \-s
.I snaplen
]
[
.B \-T
.I type
]
[
.B \-\-version
]
.ti +8
[
.B \-V
.I file
]
[
.B \-w
.I file
]
[
.B \-W
.I filecount
]
[
.B \-y
.I datalinktype
]
.ti +8
[
.B \-z
.I postrotate-command
]
[
.B \-Z
.I user
]
.ti +8
[
.BI \-\-time\-stamp\-precision= tstamp_precision
]
.ti +8
[
.BI \-\-micro
]
[
.BI \-\-nano
]
.ti +8
[
.I expression
]
.br
.ad
.SH DESCRIPTION
.LP
\fITcpdump\fP prints out a description of the contents of packets on a
network interface that match the Boolean \fIexpression\fP (see
.BR \%pcap-filter (@MAN_MISC_INFO@)
for the \fIexpression\fP syntax); the
description is preceded by a time stamp, printed, by default, as hours,
minutes, seconds, and fractions of a second since midnight. It can also
be run with the
.B \-w
flag, which causes it to save the packet data to a file for later
analysis, and/or with the
.B \-r
flag, which causes it to read from a saved packet file rather than to
read packets from a network interface. It can also be run with the
.B \-V
flag, which causes it to read a list of saved packet files. In all cases,
only packets that match
.I expression
will be processed by
.IR tcpdump .
.LP
.I Tcpdump
will, if not run with the
.B \-c
flag, continue capturing packets until it is interrupted by a SIGINT
signal (generated, for example, by typing your interrupt character,
typically control-C) or a SIGTERM signal (typically generated with the
.BR kill (1)
command); if run with the
.B \-c
flag, it will capture packets until it is interrupted by a SIGINT or
SIGTERM signal or the specified number of packets have been processed.
.LP
When
.I tcpdump
finishes capturing packets, it will report counts of:
.IP
packets ``captured'' (this is the number of packets that
.I tcpdump
has received and processed);
.IP
packets ``received by filter'' (the meaning of this depends on the OS on
which you're running
.IR tcpdump ,
and possibly on the way the OS was configured - if a filter was
specified on the command line, on some OSes it counts packets regardless
of whether they were matched by the filter expression and, even if they
were matched by the filter expression, regardless of whether
.I tcpdump
has read and processed them yet, on other OSes it counts only packets that were
matched by the filter expression regardless of whether
.I tcpdump
has read and processed them yet, and on other OSes it counts only
packets that were matched by the filter expression and were processed by
.IR tcpdump );
.IP
packets ``dropped by kernel'' (this is the number of packets that were
dropped, due to a lack of buffer space, by the packet capture mechanism
in the OS on which
.I tcpdump
is running, if the OS reports that information to applications; if not,
it will be reported as 0).
.LP
On platforms that support the SIGINFO signal, such as most BSDs
(including macOS) and Digital/Tru64 UNIX, it will report those counts
when it receives a SIGINFO signal (generated, for example, by typing
your ``status'' character, typically control-T, although on some
platforms, such as macOS, the ``status'' character is not set by
default, so you must set it with
.BR stty (1)
in order to use it) and will continue capturing packets. On platforms that
do not support the SIGINFO signal, the same can be achieved by using the
SIGUSR1 signal.
.LP
Using the SIGUSR2 signal along with the
.B \-w
flag will forcibly flush the packet buffer into the output file.
.LP
Reading packets from a network interface may require that you have
special privileges; see the
.BR pcap (3PCAP)
man page for details. Reading a saved packet file doesn't require
special privileges.
.SH OPTIONS
.TP
.B \-A
Print each packet (minus its link level header) in ASCII. Handy for
capturing web pages.
.TP
.B \-b
Print the AS number in BGP packets in ASDOT notation rather than ASPLAIN
notation.
.TP
.BI \-B " buffer_size"
.PD 0
.TP
.BI \-\-buffer\-size= buffer_size
.PD
Set the operating system capture buffer size to \fIbuffer_size\fP, in
units of KiB (1024 bytes).
.TP
.BI \-c " count"
Exit after receiving \fIcount\fP packets.
.TP
.BI \-\-count
Print only on stdout the packet count when reading capture file(s) instead
of parsing/printing the packets. If a filter is specified on the command
line, \fItcpdump\fP counts only packets that were matched by the filter
expression.
.TP
.BI \-C " file_size"
Before writing a raw packet to a savefile, check whether the file is
currently larger than \fIfile_size\fP and, if so, close the current
savefile and open a new one. Savefiles after the first savefile will
have the name specified with the
.B \-w
flag, with a number after it, starting at 1 and continuing upward.
The units of \fIfile_size\fP are millions of bytes (1,000,000 bytes,
not 1,048,576 bytes).
.TP
.B \-d
Dump the compiled packet-matching code in a human readable form to
standard output and stop.
.IP
Please mind that although code compilation is always DLT-specific,
typically it is impossible (and unnecessary) to specify which DLT to use
for the dump because \fItcpdump\fP uses either the DLT of the input pcap
file specified with
.BR -r ,
or the default DLT of the network interface specified with
.BR -i ,
or the particular DLT of the network interface specified with
.B -y
and
.B -i
respectively. In these cases the dump shows the same exact code that
would filter the input file or the network interface without
.BR -d .
.IP
However, when neither
.B -r
nor
.B -i
is specified, specifying
.B -d
prevents \fItcpdump\fP from guessing a suitable network interface (see
.BR -i ).
In this case the DLT defaults to EN10MB and can be set to another valid
value manually with
.BR -y .
.TP
.B \-dd
Dump packet-matching code as a
.B C
program fragment.
.TP
.B \-ddd
Dump packet-matching code as decimal numbers (preceded with a count).
.TP
.B \-D
.PD 0
.TP
.B \-\-list\-interfaces
.PD
Print the list of the network interfaces available on the system and on
which
.I tcpdump
can capture packets. For each network interface, a number and an
interface name, possibly followed by a text description of the
interface, are printed. The interface name or the number can be supplied
to the
.B \-i
flag to specify an interface on which to capture.
.IP
This can be useful on systems that don't have a command to list them
(e.g., Windows systems, or UNIX systems lacking
.BR "ifconfig \-a" );
the number can be useful on Windows 2000 and later systems, where the
interface name is a somewhat complex string.
.IP
The
.B \-D
flag will not be supported if
.I tcpdump
was built with an older version of
.I libpcap
that lacks the
.BR pcap_findalldevs (3PCAP)
function.
.TP
.B \-e
Print the link-level header on each dump line. This can be used, for
example, to print MAC layer addresses for protocols such as Ethernet and
IEEE 802.11.
.TP
.B \-E
Use \fIspi@ipaddr algo:secret\fP for decrypting IPsec ESP packets that
are addressed to \fIaddr\fP and contain Security Parameter Index value
\fIspi\fP. This combination may be repeated with comma or newline separation.
.IP
Note that setting the secret for IPv4 ESP packets is supported at this time.
.IP
Algorithms may be
\fBdes-cbc\fP,
\fB3des-cbc\fP,
\fBblowfish-cbc\fP,
\fBrc3-cbc\fP,
\fBcast128-cbc\fP, or
\fBnone\fP.
The default is \fBdes-cbc\fP.
The ability to decrypt packets is only present if \fItcpdump\fP was compiled
with cryptography enabled.
.IP
\fIsecret\fP is the ASCII text for ESP secret key.
If preceded by 0x, then a hex value will be read.
.IP
The option assumes RFC 2406 ESP, not RFC 1827 ESP.
The option is only for debugging purposes, and
the use of this option with a true `secret' key is discouraged.
By presenting IPsec secret key onto command line
you make it visible to others, via
.IR ps (1)
and other occasions.
.IP
In addition to the above syntax, the syntax \fIfile name\fP may be used
to have tcpdump read the provided file in. The file is opened upon
receiving the first ESP packet, so any special permissions that tcpdump
may have been given should already have been given up.
.TP
.B \-f
Print `foreign' IPv4 addresses numerically rather than symbolically
(this option is intended to get around serious brain damage in
Sun's NIS server \(em usually it hangs forever translating non-local
internet numbers).
.IP
The test for `foreign' IPv4 addresses is done using the IPv4 address and
netmask of the interface on that capture is being done. If that
address or netmask are not available, either because the
interface on that capture is being done has no address or netmask or
because it is the "any" pseudo-interface, which is
available in Linux and in recent versions of macOS and Solaris, and which
can capture on more than one interface, this option will not work
correctly.
.TP
.BI \-F " file"
Use \fIfile\fP as input for the filter expression.
An additional expression given on the command line is ignored.
.TP
.BI \-G " rotate_seconds"
If specified, rotates the dump file specified with the
.B \-w
option every \fIrotate_seconds\fP seconds.
Savefiles will have the name specified by
.B \-w
which should include a time format as defined by
.BR strftime (3).
If no time format is specified, each new file will overwrite the previous.
Whenever a generated filename is not unique, tcpdump will overwrite the
-pre-existing data; providing a time specification that is coarser than the
+preexisting data; providing a time specification that is coarser than the
capture period is therefore not advised.
.IP
If used in conjunction with the
.B \-C
option, filenames will take the form of `\fIfile\fP<count>'.
.TP
.B \-h
.PD 0
.TP
.B \-\-help
.PD
Print the tcpdump and libpcap version strings, print a usage message,
and exit.
.TP
.B \-\-version
.PD
Print the tcpdump and libpcap version strings and exit.
.TP
.B \-H
Attempt to detect 802.11s draft mesh headers.
.TP
.BI \-i " interface"
.PD 0
.TP
.BI \-\-interface= interface
.PD
Listen, report the list of link-layer types, report the list of time
stamp types, or report the results of compiling a filter expression on
\fIinterface\fP. If unspecified and if the
.B -d
flag is not given, \fItcpdump\fP searches the system
interface list for the lowest numbered, configured up interface
(excluding loopback), which may turn out to be, for example, ``eth0''.
.IP
On Linux systems with 2.2 or later kernels and on recent versions of macOS
and Solaris, an
.I interface
argument of ``any'' can be used to capture packets from all interfaces.
Note that captures on the ``any'' pseudo-interface will not be done in promiscuous
mode.
.IP
If the
.B \-D
flag is supported, an interface number as printed by that flag can be
used as the
.I interface
argument, if no interface on the system has that number as a name.
.TP
.B \-I
.PD 0
.TP
.B \-\-monitor\-mode
.PD
Put the interface in "monitor mode"; this is supported only on IEEE
802.11 Wi-Fi interfaces, and supported only on some operating systems.
.IP
Note that in monitor mode the adapter might disassociate from the
network with which it's associated, so that you will not be able to use
any wireless networks with that adapter. This could prevent accessing
files on a network server, or resolving host names or network addresses,
if you are capturing in monitor mode and are not connected to another
network with another adapter.
.IP
This flag will affect the output of the
.B \-L
flag. If
.B \-I
isn't specified, only those link-layer types available when not in
monitor mode will be shown; if
.B \-I
is specified, only those link-layer types available when in monitor mode
will be shown.
.TP
.BI \-\-immediate\-mode
Capture in "immediate mode". In this mode, packets are delivered to
tcpdump as soon as they arrive, rather than being buffered for
efficiency. This is the default when printing packets rather than
saving packets to a ``savefile'' if the packets are being printed to a
terminal rather than to a file or pipe.
.TP
.BI \-j " tstamp_type"
.PD 0
.TP
.BI \-\-time\-stamp\-type= tstamp_type
.PD
Set the time stamp type for the capture to \fItstamp_type\fP. The names
to use for the time stamp types are given in
.BR \%pcap-tstamp (@MAN_MISC_INFO@);
not all the types listed there will necessarily be valid for any given
interface.
.TP
.B \-J
.PD 0
.TP
.B \-\-list\-time\-stamp\-types
.PD
List the supported time stamp types for the interface and exit. If the
time stamp type cannot be set for the interface, no time stamp types are
listed.
.TP
.BI \-\-time\-stamp\-precision= tstamp_precision
When capturing, set the time stamp precision for the capture to
\fItstamp_precision\fP. Note that availability of high precision time
stamps (nanoseconds) and their actual accuracy is platform and hardware
dependent. Also note that when writing captures made with nanosecond
accuracy to a savefile, the time stamps are written with nanosecond
resolution, and the file is written with a different magic number, to
indicate that the time stamps are in seconds and nanoseconds; not all
programs that read pcap savefiles will be able to read those captures.
.IP
When reading a savefile, convert time stamps to the precision specified
by \fItimestamp_precision\fP, and display them with that resolution. If
the precision specified is less than the precision of time stamps in the
file, the conversion will lose precision.
.IP
The supported values for \fItimestamp_precision\fP are \fBmicro\fP for
microsecond resolution and \fBnano\fP for nanosecond resolution. The
default is microsecond resolution.
.TP
.B \-\-micro
.PD 0
.TP
.B \-\-nano
.PD
Shorthands for \fB\-\-time\-stamp\-precision=micro\fP or
\fB\-\-time\-stamp\-precision=nano\fP, adjusting the time stamp
precision accordingly. When reading packets from a savefile, using
\fB\-\-micro\fP truncates time stamps if the savefile was created with
nanosecond precision. In contrast, a savefile created with microsecond
precision will have trailing zeroes added to the time stamp when
\fB\-\-nano\fP is used.
.TP
.B \-K
.PD 0
.TP
.B \-\-dont\-verify\-checksums
.PD
Don't attempt to verify IP, TCP, or UDP checksums. This is useful for
interfaces that perform some or all of those checksum calculation in
hardware; otherwise, all outgoing TCP checksums will be flagged as bad.
.TP
.B \-l
Make stdout line buffered.
Useful if you want to see the data
while capturing it.
E.g.,
.IP
.RS
.RS
.nf
\fBtcpdump \-l | tee dat\fP
.fi
.RE
.RE
.IP
or
.IP
.RS
.RS
.nf
\fBtcpdump \-l > dat & tail \-f dat\fP
.fi
.RE
.RE
.IP
Note that on Windows,``line buffered'' means ``unbuffered'', so that
WinDump will write each character individually if
.B \-l
is specified.
.IP
.B \-U
is similar to
.B \-l
in its behavior, but it will cause output to be ``packet-buffered'', so
that the output is written to stdout at the end of each packet rather
than at the end of each line; this is buffered on all platforms,
including Windows.
.TP
.B \-L
.PD 0
.TP
.B \-\-list\-data\-link\-types
.PD
List the known data link types for the interface, in the specified mode,
and exit. The list of known data link types may be dependent on the
specified mode; for example, on some platforms, a Wi-Fi interface might
support one set of data link types when not in monitor mode (for
example, it might support only fake Ethernet headers, or might support
802.11 headers but not support 802.11 headers with radio information)
and another set of data link types when in monitor mode (for example, it
might support 802.11 headers, or 802.11 headers with radio information,
only in monitor mode).
.TP
.BI \-m " module"
Load SMI MIB module definitions from file \fImodule\fR.
This option
can be used several times to load several MIB modules into \fItcpdump\fP.
.TP
.BI \-M " secret"
Use \fIsecret\fP as a shared secret for validating the digests found in
TCP segments with the TCP-MD5 option (RFC 2385), if present.
.TP
.B \-n
Don't convert addresses (i.e., host addresses, port numbers, etc.) to names.
.TP
.B \-N
Don't print domain name qualification of host names.
E.g.,
if you give this flag then \fItcpdump\fP will print ``nic''
instead of ``nic.ddn.mil''.
.TP
.B \-#
.PD 0
.TP
.B \-\-number
.PD
-Print an optional packet number at the beginning of the line.
+Print a packet number at the beginning of the line.
.TP
.B \-O
.PD 0
.TP
.B \-\-no\-optimize
.PD
Do not run the packet-matching code optimizer.
This is useful only
if you suspect a bug in the optimizer.
.TP
.B \-p
.PD 0
.TP
.B \-\-no\-promiscuous\-mode
.PD
\fIDon't\fP put the interface
into promiscuous mode.
Note that the interface might be in promiscuous
mode for some other reason; hence, `-p' cannot be used as an abbreviation for
`ether host {local-hw-addr} or ether broadcast'.
.TP
.BI \-\-print
Print parsed packet output, even if the raw packets are being saved to a
file with the
.B \-w
flag.
.TP
.BI \-Q " direction"
.PD 0
.TP
.BI \-\-direction= direction
.PD
Choose send/receive direction \fIdirection\fR for which packets should be
captured. Possible values are `in', `out' and `inout'. Not available
on all platforms.
.TP
.B \-q
Quick (quiet?) output.
Print less protocol information so output
lines are shorter.
.TP
.BI \-r " file"
Read packets from \fIfile\fR (which was created with the
.B \-w
option or by other tools that write pcap or pcapng files).
Standard input is used if \fIfile\fR is ``-''.
.TP
.B \-S
.PD 0
.TP
.B \-\-absolute\-tcp\-sequence\-numbers
.PD
Print absolute, rather than relative, TCP sequence numbers.
.TP
.BI \-s " snaplen"
.PD 0
.TP
.BI \-\-snapshot\-length= snaplen
.PD
Snarf \fIsnaplen\fP bytes of data from each packet rather than the
default of 262144 bytes.
Packets truncated because of a limited snapshot
are indicated in the output with ``[|\fIproto\fP]'', where \fIproto\fP
is the name of the protocol level at which the truncation has occurred.
.IP
Note that taking larger snapshots both increases
the amount of time it takes to process packets and, effectively,
decreases the amount of packet buffering.
This may cause packets to be
lost.
Note also that taking smaller snapshots will discard data from protocols
above the transport layer, which loses information that may be
important. NFS and AFS requests and replies, for example, are very
large, and much of the detail won't be available if a too-short snapshot
length is selected.
.IP
If you need to reduce the snapshot size below the default, you should
limit \fIsnaplen\fP to the smallest number that will capture the
protocol information you're interested in. Setting
\fIsnaplen\fP to 0 sets it to the default of 262144,
for backwards compatibility with recent older versions of
.IR tcpdump .
.TP
.BI \-T " type"
Force packets selected by "\fIexpression\fP" to be interpreted the
specified \fItype\fR.
Currently known types are
\fBaodv\fR (Ad-hoc On-demand Distance Vector protocol),
\fBcarp\fR (Common Address Redundancy Protocol),
\fBcnfp\fR (Cisco NetFlow protocol),
\fBdomain\fR (Domain Name System),
\fBlmp\fR (Link Management Protocol),
\fBpgm\fR (Pragmatic General Multicast),
\fBpgm_zmtp1\fR (ZMTP/1.0 inside PGM/EPGM),
\fBptp\fR (Precision Time Protocol),
\fBradius\fR (RADIUS),
\fBresp\fR (REdis Serialization Protocol),
\fBrpc\fR (Remote Procedure Call),
\fBrtcp\fR (Real-Time Applications control protocol),
\fBrtp\fR (Real-Time Applications protocol),
\fBsnmp\fR (Simple Network Management Protocol),
\fBsomeip\fR (SOME/IP),
\fBtftp\fR (Trivial File Transfer Protocol),
\fBvat\fR (Visual Audio Tool),
\fBvxlan\fR (Virtual eXtensible Local Area Network),
\fBwb\fR (distributed White Board)
and
\fBzmtp1\fR (ZeroMQ Message Transport Protocol 1.0).
.IP
Note that the \fBpgm\fR type above affects UDP interpretation only, the native
PGM is always recognised as IP protocol 113 regardless. UDP-encapsulated PGM is
often called "EPGM" or "PGM/UDP".
.IP
Note that the \fBpgm_zmtp1\fR type above affects interpretation of both native
PGM and UDP at once. During the native PGM decoding the application data of an
ODATA/RDATA packet would be decoded as a ZeroMQ datagram with ZMTP/1.0 frames.
During the UDP decoding in addition to that any UDP packet would be treated as
an encapsulated PGM packet.
.TP
.B \-t
\fIDon't\fP print a timestamp on each dump line.
.TP
.B \-tt
Print the timestamp, as seconds since January 1, 1970, 00:00:00, UTC, and
fractions of a second since that time, on each dump line.
.TP
.B \-ttt
Print a delta (microsecond or nanosecond resolution depending on the
.B \-\-time\-stamp-precision
option) between current and previous line on each dump line.
The default is microsecond resolution.
.TP
.B \-tttt
Print a timestamp, as hours, minutes, seconds, and fractions of a second
since midnight, preceded by the date, on each dump line.
.TP
.B \-ttttt
Print a delta (microsecond or nanosecond resolution depending on the
.B \-\-time\-stamp-precision
option) between current and first line on each dump line.
The default is microsecond resolution.
.TP
.B \-u
Print undecoded NFS handles.
.TP
.B \-U
.PD 0
.TP
.B \-\-packet\-buffered
.PD
If the
.B \-w
option is not specified, or if it is specified but the
.B \-\-print
flag is also specified, make the printed packet output
``packet-buffered''; i.e., as the description of the contents of each
packet is printed, it will be written to the standard output, rather
than, when not writing to a terminal, being written only when the output
buffer fills.
.IP
If the
.B \-w
option is specified, make the saved raw packet output
``packet-buffered''; i.e., as each packet is saved, it will be written
to the output file, rather than being written only when the output
buffer fills.
.IP
The
.B \-U
flag will not be supported if
.I tcpdump
was built with an older version of
.I libpcap
that lacks the
.BR pcap_dump_flush (3PCAP)
function.
.TP
.B \-v
When parsing and printing, produce (slightly more) verbose output.
For example, the time to live,
identification, total length and options in an IP packet are printed.
Also enables additional packet integrity checks such as verifying the
IP and ICMP header checksum.
.IP
When writing to a file with the
.B \-w
option and at the same time not reading from a file with the
.B \-r
option, report to stderr, once per second, the number of packets captured. In
Solaris, FreeBSD and possibly other operating systems this periodic update
currently can cause loss of captured packets on their way from the kernel to
tcpdump.
.TP
.B \-vv
Even more verbose output.
For example, additional fields are
printed from NFS reply packets, and SMB packets are fully decoded.
.TP
.B \-vvv
Even more verbose output.
For example,
telnet \fBSB\fP ... \fBSE\fP options
are printed in full.
With
.B \-X
Telnet options are printed in hex as well.
.TP
.BI \-V " file"
Read a list of filenames from \fIfile\fR. Standard input is used
if \fIfile\fR is ``-''.
.TP
.BI \-w " file"
Write the raw packets to \fIfile\fR rather than parsing and printing
them out.
They can later be printed with the \-r option.
Standard output is used if \fIfile\fR is ``-''.
.IP
This output will be buffered if written to a file or pipe, so a program
reading from the file or pipe may not see packets for an arbitrary
amount of time after they are received. Use the
.B \-U
flag to cause packets to be written as soon as they are received.
.IP
The MIME type \fIapplication/vnd.tcpdump.pcap\fP has been registered
with IANA for \fIpcap\fP files. The filename extension \fI.pcap\fP
appears to be the most commonly used along with \fI.cap\fP and
\fI.dmp\fP. \fITcpdump\fP itself doesn't check the extension when
reading capture files and doesn't add an extension when writing them
(it uses magic numbers in the file header instead). However, many
operating systems and applications will use the extension if it is
present and adding one (e.g. .pcap) is recommended.
.IP
See
.BR \%pcap-savefile (@MAN_FILE_FORMATS@)
for a description of the file format.
.TP
.BI \-W " filecount"
Used in conjunction with the
.B \-C
option, this will limit the number
of files created to the specified number, and begin overwriting files
from the beginning, thus creating a 'rotating' buffer.
In addition, it will name
the files with enough leading 0s to support the maximum number of
files, allowing them to sort correctly.
.IP
Used in conjunction with the
.B \-G
option, this will limit the number of rotated dump files that get
created, exiting with status 0 when reaching the limit.
.IP
If used in conjunction with both
.B \-C
and
.B \-G,
the
.B \-W
option will currently be ignored, and will only affect the file name.
.TP
.B \-x
When parsing and printing,
in addition to printing the headers of each packet, print the data of
each packet (minus its link level header) in hex.
The smaller of the entire packet or
.I snaplen
bytes will be printed. Note that this is the entire link-layer
packet, so for link layers that pad (e.g. Ethernet), the padding bytes
will also be printed when the higher layer packet is shorter than the
required padding.
In the current implementation this flag may have the same effect as
.B \-xx
if the packet is truncated.
.TP
.B \-xx
When parsing and printing,
in addition to printing the headers of each packet, print the data of
each packet,
.I including
its link level header, in hex.
.TP
.B \-X
When parsing and printing,
in addition to printing the headers of each packet, print the data of
each packet (minus its link level header) in hex and ASCII.
This is very handy for analysing new protocols.
In the current implementation this flag may have the same effect as
.B \-XX
if the packet is truncated.
.TP
.B \-XX
When parsing and printing,
in addition to printing the headers of each packet, print the data of
each packet,
.I including
its link level header, in hex and ASCII.
.TP
.BI \-y " datalinktype"
.PD 0
.TP
.BI \-\-linktype= datalinktype
.PD
Set the data link type to use while capturing packets (see
.BR -L )
or just compiling and dumping packet-matching code (see
.BR -d )
to \fIdatalinktype\fP.
.TP
.BI \-z " postrotate-command"
Used in conjunction with the
.B -C
or
.B -G
options, this will make
.I tcpdump
run "
.I postrotate-command file
" where
.I file
is the savefile being closed after each rotation. For example, specifying
.B \-z gzip
or
.B \-z bzip2
will compress each savefile using gzip or bzip2.
.IP
Note that tcpdump will run the command in parallel to the capture, using
the lowest priority so that this doesn't disturb the capture process.
.IP
And in case you would like to use a command that itself takes flags or
different arguments, you can always write a shell script that will take the
savefile name as the only argument, make the flags & arguments arrangements
and execute the command that you want.
.TP
.BI \-Z " user"
.PD 0
.TP
.BI \-\-relinquish\-privileges= user
.PD
If
.I tcpdump
is running as root, after opening the capture device or input savefile,
but before opening any savefiles for output, change the user ID to
.I user
and the group ID to the primary group of
.IR user .
.IP
This behavior can also be enabled by default at compile time.
.IP "\fI expression\fP"
.RS
selects which packets will be dumped.
If no \fIexpression\fP
is given, all packets on the net will be dumped.
Otherwise,
only packets for which \fIexpression\fP is `true' will be dumped.
.LP
For the \fIexpression\fP syntax, see
.BR \%pcap-filter (@MAN_MISC_INFO@).
.LP
The \fIexpression\fP argument can be passed to \fItcpdump\fP as either a single
Shell argument, or as multiple Shell arguments, whichever is more convenient.
Generally, if the expression contains Shell metacharacters, such as
backslashes used to escape protocol names, it is easier to pass it as
a single, quoted argument rather than to escape the Shell
metacharacters.
Multiple arguments are concatenated with spaces before being parsed.
.SH EXAMPLES
.LP
To print all packets arriving at or departing from \fIsundown\fP:
.RS
.nf
\fBtcpdump host sundown\fP
.fi
.RE
.LP
To print traffic between \fIhelios\fR and either \fIhot\fR or \fIace\fR:
.RS
.nf
\fBtcpdump host helios and \\( hot or ace \\)\fP
.fi
.RE
.LP
To print all IP packets between \fIace\fR and any host except \fIhelios\fR:
.RS
.nf
\fBtcpdump ip host ace and not helios\fP
.fi
.RE
.LP
To print all traffic between local hosts and hosts at Berkeley:
.RS
.nf
.B
tcpdump net ucb-ether
.fi
.RE
.LP
To print all ftp traffic through internet gateway \fIsnup\fP:
(note that the expression is quoted to prevent the shell from
(mis-)interpreting the parentheses):
.RS
.nf
.B
tcpdump 'gateway snup and (port ftp or ftp-data)'
.fi
.RE
.LP
To print traffic neither sourced from nor destined for local hosts
(if you gateway to one other net, this stuff should never make it
onto your local net).
.RS
.nf
.B
tcpdump ip and not net \fIlocalnet\fP
.fi
.RE
.LP
To print the start and end packets (the SYN and FIN packets) of each
TCP conversation that involves a non-local host.
.RS
.nf
.B
tcpdump 'tcp[tcpflags] & (tcp-syn|tcp-fin) != 0 and not src and dst net \fIlocalnet\fP'
.fi
.RE
.LP
To print the TCP packets with flags RST and ACK both set.
(i.e. select only the RST and ACK flags in the flags field, and if the result
is "RST and ACK both set", match)
.RS
.nf
.B
tcpdump 'tcp[tcpflags] & (tcp-rst|tcp-ack) == (tcp-rst|tcp-ack)'
.fi
.RE
.LP
To print all IPv4 HTTP packets to and from port 80, i.e. print only
packets that contain data, not, for example, SYN and FIN packets and
ACK-only packets. (IPv6 is left as an exercise for the reader.)
.RS
.nf
.B
tcpdump 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'
.fi
.RE
.LP
To print IP packets longer than 576 bytes sent through gateway \fIsnup\fP:
.RS
.nf
.B
tcpdump 'gateway snup and ip[2:2] > 576'
.fi
.RE
.LP
To print IP broadcast or multicast packets that were
.I not
sent via Ethernet broadcast or multicast:
.RS
.nf
.B
tcpdump 'ether[0] & 1 = 0 and ip[16] >= 224'
.fi
.RE
.LP
To print all ICMP packets that are not echo requests/replies (i.e., not
ping packets):
.RS
.nf
.B
tcpdump 'icmp[icmptype] != icmp-echo and icmp[icmptype] != icmp-echoreply'
.fi
.RE
.SH OUTPUT FORMAT
.LP
The output of \fItcpdump\fP is protocol dependent.
The following
gives a brief description and examples of most of the formats.
.de HD
.sp 1.5
.B
..
-.HD
-Timestamps
+.SS Timestamps
.LP
By default, all output lines are preceded by a timestamp.
The timestamp
is the current clock time in the form
.RS
.nf
\fIhh:mm:ss.frac\fP
.fi
.RE
and is as accurate as the kernel's clock.
The timestamp reflects the time the kernel applied a time stamp to the packet.
No attempt is made to account for the time lag between when the network
interface finished receiving the packet from the network and when the
kernel applied a time stamp to the packet; that time lag could include a
delay between the time when the network interface finished receiving a
packet from the network and the time when an interrupt was delivered to
the kernel to get it to read the packet and a delay between the time
when the kernel serviced the `new packet' interrupt and the time when it
applied a time stamp to the packet.
-.HD
-Link Level Headers
+.SS Interface
+.LP
+When the \fIany\fP interface is selected on capture or when a link-type
+\fILINUX_SLL2\fP capture file is read the
+interface name is printed after the timestamp. This is followed by the packet
+type with \fIIn\fP and \fIOut\fP denoting a packet destined for this host or
+originating from this host respectively. Other possible values are \fIB\fP
+for broadcast packets, \fIM\fP for multicast packets, and \fIP\fP for packets
+destined for other hosts.
+.SS Link Level Headers
.LP
If the '-e' option is given, the link level header is printed out.
On Ethernets, the source and destination addresses, protocol,
and packet length are printed.
.LP
On FDDI networks, the '-e' option causes \fItcpdump\fP to print
the `frame control' field, the source and destination addresses,
and the packet length.
(The `frame control' field governs the
interpretation of the rest of the packet.
Normal packets (such
as those containing IP datagrams) are `async' packets, with a priority
value between 0 and 7; for example, `\fBasync4\fR'.
Such packets
are assumed to contain an 802.2 Logical Link Control (LLC) packet;
the LLC header is printed if it is \fInot\fR an ISO datagram or a
so-called SNAP packet.
.LP
On Token Ring networks, the '-e' option causes \fItcpdump\fP to print
the `access control' and `frame control' fields, the source and
destination addresses, and the packet length.
As on FDDI networks,
packets are assumed to contain an LLC packet.
Regardless of whether
the '-e' option is specified or not, the source routing information is
printed for source-routed packets.
.LP
On 802.11 networks, the '-e' option causes \fItcpdump\fP to print
the `frame control' fields, all of the addresses in the 802.11 header,
and the packet length.
As on FDDI networks,
packets are assumed to contain an LLC packet.
.LP
\fI(N.B.: The following description assumes familiarity with
the SLIP compression algorithm described in RFC 1144.)\fP
.LP
On SLIP links, a direction indicator (``I'' for inbound, ``O'' for outbound),
packet type, and compression information are printed out.
The packet type is printed first.
The three types are \fIip\fP, \fIutcp\fP, and \fIctcp\fP.
No further link information is printed for \fIip\fR packets.
For TCP packets, the connection identifier is printed following the type.
If the packet is compressed, its encoded header is printed out.
The special cases are printed out as
\fB*S+\fIn\fR and \fB*SA+\fIn\fR, where \fIn\fR is the amount by which
the sequence number (or sequence number and ack) has changed.
If it is not a special case,
zero or more changes are printed.
A change is indicated by U (urgent pointer), W (window), A (ack),
S (sequence number), and I (packet ID), followed by a delta (+n or -n),
or a new value (=n).
Finally, the amount of data in the packet and compressed header length
are printed.
.LP
For example, the following line shows an outbound compressed TCP packet,
with an implicit connection identifier; the ack has changed by 6,
the sequence number by 49, and the packet ID by 6; there are 3 bytes of
data and 6 bytes of compressed header:
.RS
.nf
\fBO ctcp * A+6 S+49 I+6 3 (6)\fP
.fi
.RE
-.HD
-ARP/RARP Packets
+.SS ARP/RARP Packets
.LP
ARP/RARP output shows the type of request and its arguments.
The
format is intended to be self explanatory.
Here is a short sample taken from the start of an `rlogin' from
host \fIrtsg\fP to host \fIcsam\fP:
.RS
.nf
.sp .5
\f(CWarp who-has csam tell rtsg
arp reply csam is-at CSAM\fR
.sp .5
.fi
.RE
The first line says that rtsg sent an ARP packet asking
for the Ethernet address of internet host csam.
Csam
replies with its Ethernet address (in this example, Ethernet addresses
are in caps and internet addresses in lower case).
.LP
This would look less redundant if we had done \fItcpdump \-n\fP:
.RS
.nf
.sp .5
\f(CWarp who-has 128.3.254.6 tell 128.3.254.68
arp reply 128.3.254.6 is-at 02:07:01:00:01:c4\fP
.fi
.RE
.LP
If we had done \fItcpdump \-e\fP, the fact that the first packet is
broadcast and the second is point-to-point would be visible:
.RS
.nf
.sp .5
\f(CWRTSG Broadcast 0806 64: arp who-has csam tell rtsg
CSAM RTSG 0806 64: arp reply csam is-at CSAM\fR
.sp .5
.fi
.RE
For the first packet this says the Ethernet source address is RTSG, the
destination is the Ethernet broadcast address, the type field
contained hex 0806 (type ETHER_ARP) and the total length was 64 bytes.
-.HD
-IPv4 Packets
+.SS IPv4 Packets
.LP
If the link-layer header is not being printed, for IPv4 packets,
\fBIP\fP is printed after the time stamp.
.LP
If the
.B \-v
flag is specified, information from the IPv4 header is shown in
parentheses after the \fBIP\fP or the link-layer header.
The general format of this information is:
.RS
.nf
.sp .5
tos \fItos\fP, ttl \fIttl\fP, id \fIid\fP, offset \fIoffset\fP, flags [\fIflags\fP], proto \fIproto\fP, length \fIlength\fP, options (\fIoptions\fP)
.sp .5
.fi
.RE
\fItos\fP is the type of service field; if the ECN bits are non-zero,
those are reported as \fBECT(1)\fP, \fBECT(0)\fP, or \fBCE\fP.
\fIttl\fP is the time-to-live; it is not reported if it is zero.
\fIid\fP is the IP identification field.
\fIoffset\fP is the fragment offset field; it is printed whether this is
part of a fragmented datagram or not.
\fIflags\fP are the MF and DF flags; \fB+\fP is reported if MF is set,
and \fBDF\fP is reported if F is set. If neither are set, \fB.\fP is
reported.
\fIproto\fP is the protocol ID field.
-\fIlength\fP is the total length field.
+\fIlength\fP is the total length field; if the packet is a presumed TSO
+(TCP Segmentation Offload) send, [was 0, presumed TSO] is reported.
\fIoptions\fP are the IP options, if any.
.LP
Next, for TCP and UDP packets, the source and destination IP addresses
and TCP or UDP ports, with a dot between each IP address and its
corresponding port, will be printed, with a > separating the source and
destination. For other protocols, the addresses will be printed, with
a > separating the source and destination. Higher level protocol
information, if any, will be printed after that.
.LP
For fragmented IP datagrams, the first fragment contains the higher
level protocol header; fragments after the first contain no higher level
protocol header. Fragmentation information will be printed only with
the
.B \-v
flag, in the IP header information, as described above.
-.HD
-TCP Packets
+.SS TCP Packets
.LP
\fI(N.B.:The following description assumes familiarity with
the TCP protocol described in RFC 793.
If you are not familiar
with the protocol, this description will not
be of much use to you.)\fP
.LP
The general format of a TCP protocol line is:
.RS
.nf
.sp .5
\fIsrc\fP > \fIdst\fP: Flags [\fItcpflags\fP], seq \fIdata-seqno\fP, ack \fIackno\fP, win \fIwindow\fP, urg \fIurgent\fP, options [\fIopts\fP], length \fIlen\fP
.sp .5
.fi
.RE
\fISrc\fP and \fIdst\fP are the source and destination IP
addresses and ports.
\fITcpflags\fP are some combination of S (SYN),
F (FIN), P (PSH), R (RST), U (URG), W (CWR), E (ECE) or
`.' (ACK), or `none' if no flags are set.
\fIData-seqno\fP describes the portion of sequence space covered
by the data in this packet (see example below).
\fIAckno\fP is sequence number of the next data expected the other
direction on this connection.
\fIWindow\fP is the number of bytes of receive buffer space available
the other direction on this connection.
\fIUrg\fP indicates there is `urgent' data in the packet.
\fIOpts\fP are TCP options (e.g., mss 1024).
\fILen\fP is the length of payload data.
.LP
\fIIptype\fR, \fISrc\fP, \fIdst\fP, and \fIflags\fP are always present.
The other fields
depend on the contents of the packet's TCP protocol header and
are output only if appropriate.
.LP
Here is the opening portion of an rlogin from host \fIrtsg\fP to
host \fIcsam\fP.
.RS
.nf
.sp .5
\f(CWIP rtsg.1023 > csam.login: Flags [S], seq 768512:768512, win 4096, opts [mss 1024]
IP csam.login > rtsg.1023: Flags [S.], seq, 947648:947648, ack 768513, win 4096, opts [mss 1024]
IP rtsg.1023 > csam.login: Flags [.], ack 1, win 4096
IP rtsg.1023 > csam.login: Flags [P.], seq 1:2, ack 1, win 4096, length 1
IP csam.login > rtsg.1023: Flags [.], ack 2, win 4096
IP rtsg.1023 > csam.login: Flags [P.], seq 2:21, ack 1, win 4096, length 19
IP csam.login > rtsg.1023: Flags [P.], seq 1:2, ack 21, win 4077, length 1
IP csam.login > rtsg.1023: Flags [P.], seq 2:3, ack 21, win 4077, urg 1, length 1
IP csam.login > rtsg.1023: Flags [P.], seq 3:4, ack 21, win 4077, urg 1, length 1\fR
.sp .5
.fi
.RE
The first line says that TCP port 1023 on rtsg sent a packet
to port \fIlogin\fP
on csam.
The \fBS\fP indicates that the \fISYN\fP flag was set.
The packet sequence number was 768512 and it contained no data.
(The notation is `first:last' which means `sequence
numbers \fIfirst\fP
up to but not including \fIlast\fP'.)
There was no piggy-backed ACK, the available receive window was 4096
bytes and there was a max-segment-size option requesting an MSS of
1024 bytes.
.LP
Csam replies with a similar packet except it includes a piggy-backed
ACK for rtsg's SYN.
Rtsg then ACKs csam's SYN.
The `.' means the ACK flag was set.
The packet contained no data so there is no data sequence number or length.
Note that the ACK sequence
number is a small integer (1).
The first time \fItcpdump\fP sees a
TCP `conversation', it prints the sequence number from the packet.
On subsequent packets of the conversation, the difference between
the current packet's sequence number and this initial sequence number
is printed.
This means that sequence numbers after the
first can be interpreted
as relative byte positions in the conversation's data stream (with the
first data byte each direction being `1').
`-S' will override this
feature, causing the original sequence numbers to be output.
.LP
On the 6th line, rtsg sends csam 19 bytes of data (bytes 2 through 20
in the rtsg \(-> csam side of the conversation).
The PSH flag is set in the packet.
On the 7th line, csam says it's received data sent by rtsg up to
but not including byte 21.
Most of this data is apparently sitting in the
socket buffer since csam's receive window has gotten 19 bytes smaller.
Csam also sends one byte of data to rtsg in this packet.
On the 8th and 9th lines,
csam sends two bytes of urgent, pushed data to rtsg.
.LP
If the snapshot was small enough that \fItcpdump\fP didn't capture
the full TCP header, it interprets as much of the header as it can
and then reports ``[|\fItcp\fP]'' to indicate the remainder could not
be interpreted.
If the header contains a bogus option (one with a length
that's either too small or beyond the end of the header), \fItcpdump\fP
reports it as ``[\fIbad opt\fP]'' and does not interpret any further
options (since it's impossible to tell where they start).
If the header
length indicates options are present but the IP datagram length is not
long enough for the options to actually be there, \fItcpdump\fP reports
it as ``[\fIbad hdr length\fP]''.
-.HD
-.B Capturing TCP packets with particular flag combinations (SYN-ACK, URG-ACK, etc.)
+.SS Particular TCP Flag Combinations (SYN-ACK, URG-ACK, etc.)
.PP
There are 8 bits in the control bits section of the TCP header:
.IP
.I CWR | ECE | URG | ACK | PSH | RST | SYN | FIN
.PP
Let's assume that we want to watch packets used in establishing
a TCP connection.
Recall that TCP uses a 3-way handshake protocol
when it initializes a new connection; the connection sequence with
regard to the TCP control bits is
.PP
.RS
1) Caller sends SYN
.RE
.RS
2) Recipient responds with SYN, ACK
.RE
.RS
3) Caller sends ACK
.RE
.PP
Now we're interested in capturing packets that have only the
SYN bit set (Step 1).
Note that we don't want packets from step 2
(SYN-ACK), just a plain initial SYN.
What we need is a correct filter
expression for \fItcpdump\fP.
.PP
Recall the structure of a TCP header without options:
.PP
.nf
0 15 31
-----------------------------------------------------------------
| source port | destination port |
-----------------------------------------------------------------
| sequence number |
-----------------------------------------------------------------
| acknowledgment number |
-----------------------------------------------------------------
| HL | rsvd |C|E|U|A|P|R|S|F| window size |
-----------------------------------------------------------------
| TCP checksum | urgent pointer |
-----------------------------------------------------------------
.fi
.PP
A TCP header usually holds 20 octets of data, unless options are
present.
The first line of the graph contains octets 0 - 3, the
second line shows octets 4 - 7 etc.
.PP
Starting to count with 0, the relevant TCP control bits are contained
in octet 13:
.PP
.nf
0 7| 15| 23| 31
----------------|---------------|---------------|----------------
| HL | rsvd |C|E|U|A|P|R|S|F| window size |
----------------|---------------|---------------|----------------
| | 13th octet | | |
.fi
.PP
Let's have a closer look at octet no. 13:
.PP
.nf
| |
|---------------|
|C|E|U|A|P|R|S|F|
|---------------|
|7 5 3 0|
.fi
.PP
These are the TCP control bits we are interested
in.
We have numbered the bits in this octet from 0 to 7, right to
left, so the PSH bit is bit number 3, while the URG bit is number 5.
.PP
Recall that we want to capture packets with only SYN set.
Let's see what happens to octet 13 if a TCP datagram arrives
with the SYN bit set in its header:
.PP
.nf
|C|E|U|A|P|R|S|F|
|---------------|
|0 0 0 0 0 0 1 0|
|---------------|
|7 6 5 4 3 2 1 0|
.fi
.PP
Looking at the
control bits section we see that only bit number 1 (SYN) is set.
.PP
Assuming that octet number 13 is an 8-bit unsigned integer in
network byte order, the binary value of this octet is
.IP
00000010
.PP
and its decimal representation is
.PP
.nf
7 6 5 4 3 2 1 0
0*2 + 0*2 + 0*2 + 0*2 + 0*2 + 0*2 + 1*2 + 0*2 = 2
.fi
.PP
We're almost done, because now we know that if only SYN is set,
the value of the 13th octet in the TCP header, when interpreted
as a 8-bit unsigned integer in network byte order, must be exactly 2.
.PP
This relationship can be expressed as
.RS
.B
tcp[13] == 2
.RE
.PP
We can use this expression as the filter for \fItcpdump\fP in order
to watch packets which have only SYN set:
.RS
.B
-tcpdump -i xl0 tcp[13] == 2
+tcpdump -i xl0 'tcp[13] == 2'
.RE
.PP
The expression says "let the 13th octet of a TCP datagram have
the decimal value 2", which is exactly what we want.
.PP
Now, let's assume that we need to capture SYN packets, but we
don't care if ACK or any other TCP control bit is set at the
same time.
Let's see what happens to octet 13 when a TCP datagram
with SYN-ACK set arrives:
.PP
.nf
|C|E|U|A|P|R|S|F|
|---------------|
|0 0 0 1 0 0 1 0|
|---------------|
|7 6 5 4 3 2 1 0|
.fi
.PP
Now bits 1 and 4 are set in the 13th octet.
The binary value of
octet 13 is
.IP
00010010
.PP
which translates to decimal
.PP
.nf
7 6 5 4 3 2 1 0
0*2 + 0*2 + 0*2 + 1*2 + 0*2 + 0*2 + 1*2 + 0*2 = 18
.fi
.PP
Now we can't just use 'tcp[13] == 18' in the \fItcpdump\fP filter
expression, because that would select only those packets that have
SYN-ACK set, but not those with only SYN set.
Remember that we don't care
if ACK or any other control bit is set as long as SYN is set.
.PP
In order to achieve our goal, we need to logically AND the
binary value of octet 13 with some other value to preserve
the SYN bit.
We know that we want SYN to be set in any case,
so we'll logically AND the value in the 13th octet with
the binary value of a SYN:
.PP
.nf
00010010 SYN-ACK 00000010 SYN
AND 00000010 (we want SYN) AND 00000010 (we want SYN)
-------- --------
= 00000010 = 00000010
.fi
.PP
We see that this AND operation delivers the same result
regardless whether ACK or another TCP control bit is set.
The decimal representation of the AND value as well as
the result of this operation is 2 (binary 00000010),
so we know that for packets with SYN set the following
relation must hold true:
.IP
( ( value of octet 13 ) AND ( 2 ) ) == ( 2 )
.PP
This points us to the \fItcpdump\fP filter expression
.RS
.B
tcpdump -i xl0 'tcp[13] & 2 == 2'
.RE
.PP
Some offsets and field values may be expressed as names
rather than as numeric values. For example tcp[13] may
be replaced with tcp[tcpflags]. The following TCP flag
field values are also available: tcp-fin, tcp-syn, tcp-rst,
tcp-push, tcp-ack, tcp-urg, tcp-ece and tcp-cwr.
.PP
This can be demonstrated as:
.RS
.B
tcpdump -i xl0 'tcp[tcpflags] & tcp-push != 0'
.RE
.PP
Note that you should use single quotes or a backslash
in the expression to hide the AND ('&') special character
from the shell.
-.HD
-.B
-UDP Packets
+.SS UDP Packets
.LP
UDP format is illustrated by this rwho packet:
.RS
.nf
.sp .5
\f(CWactinide.who > broadcast.who: udp 84\fP
.sp .5
.fi
.RE
This says that port \fIwho\fP on host \fIactinide\fP sent a UDP
datagram to port \fIwho\fP on host \fIbroadcast\fP, the Internet
broadcast address.
The packet contained 84 bytes of user data.
.LP
Some UDP services are recognized (from the source or destination
port number) and the higher level protocol information printed.
In particular, Domain Name service requests (RFC 1034/1035) and Sun
RPC calls (RFC 1050) to NFS.
-.HD
-TCP or UDP Name Server Requests
+.SS TCP or UDP Name Server Requests
.LP
\fI(N.B.:The following description assumes familiarity with
the Domain Service protocol described in RFC 1035.
If you are not familiar
with the protocol, the following description will appear to be written
in Greek.)\fP
.LP
Name server requests are formatted as
.RS
.nf
.sp .5
\fIsrc > dst: id op? flags qtype qclass name (len)\fP
.sp .5
\f(CWh2opolo.1538 > helios.domain: 3+ A? ucbvax.berkeley.edu. (37)\fR
.sp .5
.fi
.RE
Host \fIh2opolo\fP asked the domain server on \fIhelios\fP for an
address record (qtype=A) associated with the name \fIucbvax.berkeley.edu.\fP
The query id was `3'.
The `+' indicates the \fIrecursion desired\fP flag
was set.
The query length was 37 bytes, excluding the TCP or UDP and
IP protocol headers.
The query operation was the normal one, \fIQuery\fP,
so the op field was omitted.
If the op had been anything else, it would
have been printed between the `3' and the `+'.
Similarly, the qclass was the normal one,
\fIC_IN\fP, and omitted.
Any other qclass would have been printed
immediately after the `A'.
.LP
A few anomalies are checked and may result in extra fields enclosed in
square brackets: If a query contains an answer, authority records or
additional records section,
.IR ancount ,
.IR nscount ,
or
.I arcount
are printed as `[\fIn\fPa]', `[\fIn\fPn]' or `[\fIn\fPau]' where \fIn\fP
is the appropriate count.
If any of the response bits are set (AA, RA or rcode) or any of the
`must be zero' bits are set in bytes two and three, `[b2&3=\fIx\fP]'
is printed, where \fIx\fP is the hex value of header bytes two and three.
-.HD
-TCP or UDP Name Server Responses
+.SS TCP or UDP Name Server Responses
.LP
Name server responses are formatted as
.RS
.nf
.sp .5
\fIsrc > dst: id op rcode flags a/n/au type class data (len)\fP
.sp .5
\f(CWhelios.domain > h2opolo.1538: 3 3/3/7 A 128.32.137.3 (273)
helios.domain > h2opolo.1537: 2 NXDomain* 0/1/0 (97)\fR
.sp .5
.fi
.RE
In the first example, \fIhelios\fP responds to query id 3 from \fIh2opolo\fP
with 3 answer records, 3 name server records and 7 additional records.
The first answer record is type A (address) and its data is internet
address 128.32.137.3.
The total size of the response was 273 bytes,
excluding TCP or UDP and IP headers.
The op (Query) and response code
(NoError) were omitted, as was the class (C_IN) of the A record.
.LP
In the second example, \fIhelios\fP responds to query 2 with a
-response code of non-existent domain (NXDomain) with no answers,
+response code of nonexistent domain (NXDomain) with no answers,
one name server and no authority records.
The `*' indicates that
the \fIauthoritative answer\fP bit was set.
Since there were no
answers, no type, class or data were printed.
.LP
Other flag characters that might appear are `\-' (recursion available,
RA, \fInot\fP set) and `|' (truncated message, TC, set).
If the
`question' section doesn't contain exactly one entry, `[\fIn\fPq]'
is printed.
-.HD
-SMB/CIFS decoding
+.SS SMB/CIFS Decoding
.LP
\fItcpdump\fP now includes fairly extensive SMB/CIFS/NBT decoding for data
on UDP/137, UDP/138 and TCP/139.
Some primitive decoding of IPX and
NetBEUI SMB data is also done.
.LP
By default a fairly minimal decode is done, with a much more detailed
decode done if -v is used.
Be warned that with -v a single SMB packet
may take up a page or more, so only use -v if you really want all the
gory details.
.LP
For information on SMB packet formats and what all the fields mean see
\%https://download.samba.org/pub/samba/specs/ and other online resources.
The SMB patches were written by Andrew Tridgell
(tridge@samba.org).
-.HD
-NFS Requests and Replies
+.SS NFS Requests and Replies
.LP
Sun NFS (Network File System) requests and replies are printed as:
.RS
.nf
.sp .5
\fIsrc.sport > dst.nfs: NFS request xid xid len op args\fP
\fIsrc.nfs > dst.dport: NFS reply xid xid reply stat len op results\fP
.sp .5
\f(CW
sushi.1023 > wrl.nfs: NFS request xid 26377
112 readlink fh 21,24/10.73165
wrl.nfs > sushi.1023: NFS reply xid 26377
reply ok 40 readlink "../var"
sushi.1022 > wrl.nfs: NFS request xid 8219
144 lookup fh 9,74/4096.6878 "xcolors"
wrl.nfs > sushi.1022: NFS reply xid 8219
reply ok 128 lookup fh 9,74/4134.3150
\fR
.sp .5
.fi
.RE
In the first line, host \fIsushi\fP sends a transaction with id \fI26377\fP
to \fIwrl\fP.
The request was 112 bytes,
excluding the UDP and IP headers.
The operation was a \fIreadlink\fP
(read symbolic link) on file handle (\fIfh\fP) 21,24/10.731657119.
(If one is lucky, as in this case, the file handle can be interpreted
as a major,minor device number pair, followed by the inode number and
generation number.) In the second line, \fIwrl\fP replies `ok' with
the same transaction id and the contents of the link.
.LP
In the third line, \fIsushi\fP asks (using a new transaction id) \fIwrl\fP
to lookup the name `\fIxcolors\fP' in directory file 9,74/4096.6878. In
the fourth line, \fIwrl\fP sends a reply with the respective transaction id.
.LP
Note that the data printed
depends on the operation type.
The format is intended to be self
explanatory if read in conjunction with
an NFS protocol spec.
Also note that older versions of tcpdump printed NFS packets in a
slightly different format: the transaction id (xid) would be printed
instead of the non-NFS port number of the packet.
.LP
If the \-v (verbose) flag is given, additional information is printed.
For example:
.RS
.nf
.sp .5
\f(CW
sushi.1023 > wrl.nfs: NFS request xid 79658
148 read fh 21,11/12.195 8192 bytes @ 24576
wrl.nfs > sushi.1023: NFS reply xid 79658
reply ok 1472 read REG 100664 ids 417/0 sz 29388
\fP
.sp .5
.fi
.RE
(\-v also prints the IP header TTL, ID, length, and fragmentation fields,
which have been omitted from this example.) In the first line,
\fIsushi\fP asks \fIwrl\fP to read 8192 bytes from file 21,11/12.195,
at byte offset 24576.
\fIWrl\fP replies `ok'; the packet shown on the
second line is the first fragment of the reply, and hence is only 1472
bytes long (the other bytes will follow in subsequent fragments, but
these fragments do not have NFS or even UDP headers and so might not be
printed, depending on the filter expression used).
Because the \-v flag
is given, some of the file attributes (which are returned in addition
to the file data) are printed: the file type (``REG'', for regular file),
the file mode (in octal), the UID and GID, and the file size.
.LP
If the \-v flag is given more than once, even more details are printed.
.LP
NFS reply packets do not explicitly identify the RPC operation.
Instead,
\fItcpdump\fP keeps track of ``recent'' requests, and matches them to the
replies using the transaction ID.
If a reply does not closely follow the
corresponding request, it might not be parsable.
-.HD
-AFS Requests and Replies
+.SS AFS Requests and Replies
.LP
Transarc AFS (Andrew File System) requests and replies are printed
as:
.HD
.RS
.nf
.sp .5
\fIsrc.sport > dst.dport: rx packet-type\fP
\fIsrc.sport > dst.dport: rx packet-type service call call-name args\fP
\fIsrc.sport > dst.dport: rx packet-type service reply call-name args\fP
.sp .5
\f(CW
elvis.7001 > pike.afsfs:
rx data fs call rename old fid 536876964/1/1 ".newsrc.new"
new fid 536876964/1/1 ".newsrc"
pike.afsfs > elvis.7001: rx data fs reply rename
\fR
.sp .5
.fi
.RE
In the first line, host elvis sends a RX packet to pike.
This was
a RX data packet to the fs (fileserver) service, and is the start of
an RPC call.
The RPC call was a rename, with the old directory file id
of 536876964/1/1 and an old filename of `.newsrc.new', and a new directory
file id of 536876964/1/1 and a new filename of `.newsrc'.
The host pike
responds with a RPC reply to the rename call (which was successful, because
it was a data packet and not an abort packet).
.LP
In general, all AFS RPCs are decoded at least by RPC call name.
Most
AFS RPCs have at least some of the arguments decoded (generally only
the `interesting' arguments, for some definition of interesting).
.LP
The format is intended to be self-describing, but it will probably
not be useful to people who are not familiar with the workings of
AFS and RX.
.LP
If the -v (verbose) flag is given twice, acknowledgement packets and
additional header information is printed, such as the RX call ID,
call number, sequence number, serial number, and the RX packet flags.
.LP
If the -v flag is given twice, additional information is printed,
such as the RX call ID, serial number, and the RX packet flags.
The MTU negotiation information is also printed from RX ack packets.
.LP
If the -v flag is given three times, the security index and service id
are printed.
.LP
Error codes are printed for abort packets, with the exception of Ubik
beacon packets (because abort packets are used to signify a yes vote
for the Ubik protocol).
.LP
AFS reply packets do not explicitly identify the RPC operation.
Instead,
\fItcpdump\fP keeps track of ``recent'' requests, and matches them to the
replies using the call number and service ID.
If a reply does not closely
follow the
corresponding request, it might not be parsable.
-.HD
-KIP AppleTalk (DDP in UDP)
+.SS KIP AppleTalk (DDP in UDP)
.LP
AppleTalk DDP packets encapsulated in UDP datagrams are de-encapsulated
and dumped as DDP packets (i.e., all the UDP header information is
discarded).
The file
.I /etc/atalk.names
is used to translate AppleTalk net and node numbers to names.
Lines in this file have the form
.RS
.nf
.sp .5
\fInumber name\fP
\f(CW1.254 ether
16.1 icsd-net
1.254.110 ace\fR
.sp .5
.fi
.RE
The first two lines give the names of AppleTalk networks.
The third
line gives the name of a particular host (a host is distinguished
from a net by the 3rd octet in the number \-
a net number \fImust\fP have two octets and a host number \fImust\fP
have three octets.) The number and name should be separated by
whitespace (blanks or tabs).
The
.I /etc/atalk.names
file may contain blank lines or comment lines (lines starting with
a `#').
.LP
AppleTalk addresses are printed in the form
.RS
.nf
.sp .5
\fInet.host.port\fP
\f(CW144.1.209.2 > icsd-net.112.220
office.2 > icsd-net.112.220
jssmag.149.235 > icsd-net.2\fR
.sp .5
.fi
.RE
(If the
.I /etc/atalk.names
doesn't exist or doesn't contain an entry for some AppleTalk
host/net number, addresses are printed in numeric form.)
In the first example, NBP (DDP port 2) on net 144.1 node 209
is sending to whatever is listening on port 220 of net icsd node 112.
The second line is the same except the full name of the source node
is known (`office').
The third line is a send from port 235 on
net jssmag node 149 to broadcast on the icsd-net NBP port (note that
the broadcast address (255) is indicated by a net name with no host
number \- for this reason it's a good idea to keep node names and
net names distinct in /etc/atalk.names).
.LP
NBP (name binding protocol) and ATP (AppleTalk transaction protocol)
packets have their contents interpreted.
Other protocols just dump
the protocol name (or number if no name is registered for the
protocol) and packet size.
-\fBNBP packets\fP are formatted like the following examples:
+.SS NBP Packets
+NBP packets are formatted like the following examples:
.RS
.nf
.sp .5
\f(CWicsd-net.112.220 > jssmag.2: nbp-lkup 190: "=:LaserWriter@*"
jssmag.209.2 > icsd-net.112.220: nbp-reply 190: "RM1140:LaserWriter@*" 250
techpit.2 > icsd-net.112.220: nbp-reply 190: "techpit:LaserWriter@*" 186\fR
.sp .5
.fi
.RE
The first line is a name lookup request for laserwriters sent by net icsd host
112 and broadcast on net jssmag.
The nbp id for the lookup is 190.
The second line shows a reply for this request (note that it has the
same id) from host jssmag.209 saying that it has a laserwriter
resource named "RM1140" registered on port 250.
The third line is
another reply to the same request saying host techpit has laserwriter
"techpit" registered on port 186.
-\fBATP packet\fP formatting is demonstrated by the following example:
+.SS ATP Packets
+ATP packet formatting is demonstrated by the following example:
.RS
.nf
.sp .5
\f(CWjssmag.209.165 > helios.132: atp-req 12266<0-7> 0xae030001
helios.132 > jssmag.209.165: atp-resp 12266:0 (512) 0xae040000
helios.132 > jssmag.209.165: atp-resp 12266:1 (512) 0xae040000
helios.132 > jssmag.209.165: atp-resp 12266:2 (512) 0xae040000
helios.132 > jssmag.209.165: atp-resp 12266:3 (512) 0xae040000
helios.132 > jssmag.209.165: atp-resp 12266:4 (512) 0xae040000
helios.132 > jssmag.209.165: atp-resp 12266:5 (512) 0xae040000
helios.132 > jssmag.209.165: atp-resp 12266:6 (512) 0xae040000
helios.132 > jssmag.209.165: atp-resp*12266:7 (512) 0xae040000
jssmag.209.165 > helios.132: atp-req 12266<3,5> 0xae030001
helios.132 > jssmag.209.165: atp-resp 12266:3 (512) 0xae040000
helios.132 > jssmag.209.165: atp-resp 12266:5 (512) 0xae040000
jssmag.209.165 > helios.132: atp-rel 12266<0-7> 0xae030001
jssmag.209.133 > helios.132: atp-req* 12267<0-7> 0xae030002\fR
.sp .5
.fi
.RE
Jssmag.209 initiates transaction id 12266 with host helios by requesting
up to 8 packets (the `<0-7>').
The hex number at the end of the line
is the value of the `userdata' field in the request.
.LP
Helios responds with 8 512-byte packets.
The `:digit' following the
transaction id gives the packet sequence number in the transaction
and the number in parens is the amount of data in the packet,
excluding the ATP header.
The `*' on packet 7 indicates that the
EOM bit was set.
.LP
Jssmag.209 then requests that packets 3 & 5 be retransmitted.
Helios
resends them then jssmag.209 releases the transaction.
Finally,
jssmag.209 initiates the next request.
The `*' on the request
indicates that XO (`exactly once') was \fInot\fP set.
.SH BACKWARD COMPATIBILITY
The TCP flag names
.B tcp-ece
and
.B tcp-cwr
became available when linking with libpcap 1.9.0 or later.
.SH "SEE ALSO"
.BR stty (1),
.BR pcap (3PCAP),
.BR bpf (4),
.BR nit (4P),
.BR \%pcap-savefile (@MAN_FILE_FORMATS@),
.BR \%pcap-filter (@MAN_MISC_INFO@),
.BR \%pcap-tstamp (@MAN_MISC_INFO@)
.LP
.RS
.na
.I https://www.iana.org/assignments/media-types/application/vnd.tcpdump.pcap
.ad
.RE
.LP
.SH AUTHORS
The original authors are:
.LP
Van Jacobson,
Craig Leres and
Steven McCanne, all of the
Lawrence Berkeley National Laboratory, University of California, Berkeley, CA.
.LP
It is currently maintained by The Tcpdump Group.
.LP
The current version is available via HTTPS:
.LP
.RS
.I https://www.tcpdump.org/
.RE
.LP
The original distribution is available via anonymous ftp:
.LP
.RS
.I ftp://ftp.ee.lbl.gov/old/tcpdump.tar.Z
.RE
.LP
IPv6/IPsec support is added by WIDE/KAME project.
This program uses OpenSSL/LibreSSL, under specific configurations.
.SH BUGS
To report a security issue please send an e-mail to \%security@tcpdump.org.
.LP
To report bugs and other problems, contribute patches, request a
feature, provide generic feedback etc. please see the file
.I CONTRIBUTING.md
in the tcpdump source tree root.
.LP
NIT doesn't let you watch your own outbound traffic, BPF will.
We recommend that you use the latter.
.LP
-On Linux systems with 2.0[.x] kernels:
-.IP
-packets on the loopback device will be seen twice;
-.IP
-packet filtering cannot be done in the kernel, so that all packets must
-be copied from the kernel in order to be filtered in user mode;
-.IP
-all of a packet, not just the part that's within the snapshot length,
-will be copied from the kernel (the 2.0[.x] packet capture mechanism, if
-asked to copy only part of a packet to userspace, will not report the
-true length of the packet; this would cause most IP packets to get an
-error from
-.BR tcpdump );
-.IP
-capturing on some PPP devices won't work correctly.
-.LP
-We recommend that you upgrade to a 2.2 or later kernel.
-.LP
Some attempt should be made to reassemble IP fragments or, at least
to compute the right length for the higher level protocol.
.LP
Name server inverse queries are not dumped correctly: the (empty)
question section is printed rather than real query in the answer
section.
Some believe that inverse queries are themselves a bug and
prefer to fix the program generating them rather than \fItcpdump\fP.
.LP
A packet trace that crosses a daylight savings time change will give
skewed time stamps (the time change is ignored).
.LP
Filter expressions on fields other than those in Token Ring headers will
not correctly handle source-routed Token Ring packets.
.LP
Filter expressions on fields other than those in 802.11 headers will not
correctly handle 802.11 data packets with both To DS and From DS set.
.LP
.BR "ip6 proto"
should chase header chain, but at this moment it does not.
.BR "ip6 protochain"
is supplied for this behavior.
.LP
Arithmetic expression against transport layer headers, like \fBtcp[0]\fP,
does not work against IPv6 packets.
It only looks at IPv4 packets.
diff --git a/contrib/tcpdump/tcpdump.c b/contrib/tcpdump/tcpdump.c
index 8cfcb04fc093..6cf7a066ab5c 100644
--- a/contrib/tcpdump/tcpdump.c
+++ b/contrib/tcpdump/tcpdump.c
@@ -1,3264 +1,3307 @@
/*
* 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 <swebster@sst.ll.mit.edu>
*/
/*
* 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
/*
- * Some older versions of Mac OS X may ship pcap.h from libpcap 0.6 with a
+ * Some older versions of Mac OS X 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 "netdissect-stdinc.h"
/*
* This must appear after including netdissect-stdinc.h, so that _U_ is
* defined.
*/
#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
#include <sys/stat.h>
-#ifdef HAVE_FCNTL_H
#include <fcntl.h>
-#endif
#ifdef HAVE_LIBCRYPTO
#include <openssl/crypto.h>
#endif
#ifdef HAVE_GETOPT_LONG
#include <getopt.h>
#else
#include "missing/getopt_long.h"
#endif
/* Capsicum-specific code requires macros from <net/bpf.h>, which will fail
* to compile if <pcap.h> has already been included; including the headers
* in the opposite order works fine. For the most part anyway, because in
* FreeBSD <pcap/pcap.h> declares bpf_dump() instead of <net/bpf.h>. Thus
* interface.h takes care of it later to avoid a compiler warning.
*/
#ifdef HAVE_CAPSICUM
#include <sys/capsicum.h>
#include <sys/ioccom.h>
#include <net/bpf.h>
#include <libgen.h>
#ifdef HAVE_CASPER
#include <libcasper.h>
#include <casper/cap_dns.h>
#include <sys/nv.h>
#endif /* HAVE_CASPER */
#endif /* HAVE_CAPSICUM */
#ifdef HAVE_PCAP_OPEN
/*
* We found pcap_open() in the capture library, so we'll be using
* the remote capture APIs; define PCAP_REMOTE before we include pcap.h,
* so we get those APIs declared, and the types and #defines that they
* use defined.
*
* WinPcap's headers require that PCAP_REMOTE be defined in order to get
* remote-capture APIs declared and types and #defines that they use
* defined.
*
* (Versions of libpcap with those APIs, and thus Npcap, which is based on
* those versions of libpcap, don't require it.)
*/
#define HAVE_REMOTE
#endif
#include <pcap.h>
#include <signal.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#ifdef _WIN32
#include <windows.h>
#else
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/resource.h>
#include <pwd.h>
#include <grp.h>
#endif /* _WIN32 */
/*
* Pathname separator.
* Use this in pathnames, but do *not* use it in URLs.
*/
#ifdef _WIN32
#define PATH_SEPARATOR '\\'
#else
#define PATH_SEPARATOR '/'
#endif
/* 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 <cap-ng.h>
#else
#undef HAVE_LIBCAP_NG
#endif /* HAVE_CAP_NG_H */
#endif /* HAVE_LIBCAP_NG */
#ifdef __FreeBSD__
#include <sys/sysctl.h>
#endif /* __FreeBSD__ */
#include "netdissect-stdinc.h"
#include "netdissect.h"
#include "interface.h"
#include "addrtoname.h"
#include "machdep.h"
#include "pcap-missing.h"
#include "ascii_strcasecmp.h"
#include "print.h"
#include "diag-control.h"
#include "fptype.h"
#ifndef PATH_MAX
#define PATH_MAX 1024
#endif
#if defined(SIGINFO)
#define SIGNAL_REQ_INFO SIGINFO
#elif defined(SIGUSR1)
#define SIGNAL_REQ_INFO SIGUSR1
#endif
#if defined(HAVE_PCAP_DUMP_FLUSH) && defined(SIGUSR2)
#define SIGNAL_FLUSH_PCAP SIGUSR2
#endif
#if defined(HAVE_PCAP_CREATE) || defined(_WIN32)
static int Bflag; /* buffer size */
#endif
#ifdef HAVE_PCAP_DUMP_FTELL64
static int64_t Cflag; /* rotate dump files after this many bytes */
#else
static long Cflag; /* rotate dump files after this many bytes */
#endif
static int Cflag_count; /* Keep track of which file number we're writing */
#ifdef HAVE_PCAP_FINDALLDEVS
static int Dflag; /* list available devices and exit */
#endif
#ifdef HAVE_PCAP_FINDALLDEVS_EX
static char *remote_interfaces_source; /* list available devices from this source and exit */
#endif
/*
* 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.
*/
extern int dflag;
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 */
static int jflag = -1; /* packet time stamp source */
#endif
static int lflag; /* line-buffered output */
static int pflag; /* don't go promiscuous */
#ifdef HAVE_PCAP_SETDIRECTION
static int Qflag = -1; /* restrict captured packet by send/receive direction */
#endif
#ifdef HAVE_PCAP_DUMP_FLUSH
static int Uflag; /* "unbuffered" output of dump files */
#endif
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 timeout = 1000; /* default timeout = 1000 ms = 1 s */
#ifdef HAVE_PCAP_SET_IMMEDIATE_MODE
static int immediate_mode;
#endif
static int count_mode;
static int infodelay;
static int infoprint;
char *program_name;
/*
* #ifdef HAVE_CASPER
* cap_channel_t *capdns;
* #endif
*/
/* Forwards */
static NORETURN void error(FORMAT_STRING(const char *), ...) PRINTFLIKE(1, 2);
static void warning(FORMAT_STRING(const char *), ...) PRINTFLIKE(1, 2);
static NORETURN void exit_tcpdump(int);
static void (*setsignal (int sig, void (*func)(int)))(int);
static void cleanup(int);
static void child_cleanup(int);
static void print_version(FILE *);
static void print_usage(FILE *);
#ifdef HAVE_PCAP_SET_TSTAMP_TYPE
static NORETURN void show_tstamp_types_and_exit(pcap_t *, const char *device);
#endif
static NORETURN void show_dlts_and_exit(pcap_t *, const char *device);
#ifdef HAVE_PCAP_FINDALLDEVS
static NORETURN void show_devices_and_exit(void);
#endif
#ifdef HAVE_PCAP_FINDALLDEVS_EX
static NORETURN void show_remote_devices_and_exit(void);
#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
static void requestinfo(int);
#endif
#ifdef SIGNAL_FLUSH_PCAP
static void flushpcap(int);
#endif
#ifdef _WIN32
static HANDLE timer_handle = INVALID_HANDLE_VALUE;
static void CALLBACK verbose_stats_dump(PVOID param, BOOLEAN timer_fired);
#else /* _WIN32 */
static void verbose_stats_dump(int sig);
#endif /* _WIN32 */
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" },
#ifdef PCAP_IF_WIRELESS
{ PCAP_IF_WIRELESS, "Wireless" },
#endif
{ 0, NULL }
};
#endif
static pcap_t *pd;
static pcap_dumper_t *pdd = NULL;
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 *pdd;
netdissect_options *ndo;
#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(S_ERR_HOST_PROGRAM);
/* 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(S_SUCCESS);
}
- fprintf(stderr, "Time stamp types for %s (use option -j to set):\n",
+ fprintf(stdout, "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,
+ (void) fprintf(stdout, " %s (%s)\n", tstamp_type_name,
pcap_tstamp_type_val_to_description(tstamp_types[i]));
} else {
- (void) fprintf(stderr, " %d\n", tstamp_types[i]);
+ (void) fprintf(stdout, " %d\n", tstamp_types[i]);
}
}
pcap_free_tstamp_types(tstamp_types);
exit_tcpdump(S_SUCCESS);
}
#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).
*/
+ (void) fprintf(stdout, "Data link types for ");
if (supports_monitor_mode)
- (void) fprintf(stderr, "Data link types for %s %s (use option -y to set):\n",
+ (void) fprintf(stdout, "%s %s",
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",
+ (void) fprintf(stdout, "%s",
device);
+ (void) fprintf(stdout, " (use option -y to set):\n");
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,
+ (void) fprintf(stdout, " %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");
+ (void) fprintf(stdout, " (printing not supported)");
+ fprintf(stdout, "\n");
} else {
- (void) fprintf(stderr, " DLT %d (printing not supported)\n",
+ (void) fprintf(stdout, " DLT %d (printing not supported)\n",
dlts[i]);
}
}
#ifdef HAVE_PCAP_FREE_DATALINKS
pcap_free_datalinks(dlts);
#endif
exit_tcpdump(S_SUCCESS);
}
#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(" [");
printf("%s", bittok2str(status_flags, "none", dev->flags));
#ifdef PCAP_IF_WIRELESS
if (dev->flags & PCAP_IF_WIRELESS) {
switch (dev->flags & PCAP_IF_CONNECTION_STATUS) {
case PCAP_IF_CONNECTION_STATUS_UNKNOWN:
printf(", Association status unknown");
break;
case PCAP_IF_CONNECTION_STATUS_CONNECTED:
printf(", Associated");
break;
case PCAP_IF_CONNECTION_STATUS_DISCONNECTED:
printf(", Not associated");
break;
case PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE:
break;
}
} else {
switch (dev->flags & PCAP_IF_CONNECTION_STATUS) {
case PCAP_IF_CONNECTION_STATUS_UNKNOWN:
printf(", Connection status unknown");
break;
case PCAP_IF_CONNECTION_STATUS_CONNECTED:
printf(", Connected");
break;
case PCAP_IF_CONNECTION_STATUS_DISCONNECTED:
printf(", Disconnected");
break;
case PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE:
break;
}
}
#endif
printf("]");
}
printf("\n");
}
pcap_freealldevs(devlist);
exit_tcpdump(S_SUCCESS);
}
#endif /* HAVE_PCAP_FINDALLDEVS */
#ifdef HAVE_PCAP_FINDALLDEVS_EX
static void
show_remote_devices_and_exit(void)
{
pcap_if_t *dev, *devlist;
char ebuf[PCAP_ERRBUF_SIZE];
int i;
if (pcap_findalldevs_ex(remote_interfaces_source, NULL, &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(S_SUCCESS);
}
#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:
*
* macOS tcpdump uses -g to force non--v output for IP to be on one
* line, making it more "g"repable;
*
* macOS tcpdump uses -k to specify that packet comments in pcapng files
* should be printed;
*
* OpenBSD tcpdump uses -o to indicate that OS fingerprinting should be done
* for hosts sending TCP SYN packets;
*
* macOS tcpdump uses -P to indicate that -w should write pcapng rather
* than pcap files.
*
* macOS 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 macOS 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_FINDALLDEVS
#define D_FLAG "D"
#else
#define D_FLAG
#endif
#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 USE_LIBSMI
#define m_FLAG_USAGE "[ -m module ] ..."
#endif
#ifdef HAVE_PCAP_SETDIRECTION
#define Q_FLAG "Q:"
#define Q_FLAG_USAGE " [ -Q in|out|inout ]"
#else
#define Q_FLAG
#define Q_FLAG_USAGE
#endif
#ifdef HAVE_PCAP_DUMP_FLUSH
#define U_FLAG "U"
#else
#define U_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
#define OPTION_PRINT 131
#define OPTION_LIST_REMOTE_INTERFACES 132
#define OPTION_TSTAMP_MICRO 133
#define OPTION_TSTAMP_NANO 134
#define OPTION_FP_TYPE 135
#define OPTION_COUNT 136
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' },
#ifdef HAVE_PCAP_FINDALLDEVS_EX
{ "list-remote-interfaces", required_argument, NULL, OPTION_LIST_REMOTE_INTERFACES },
#endif
{ "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
{ "micro", no_argument, NULL, OPTION_TSTAMP_MICRO},
{ "nano", no_argument, NULL, OPTION_TSTAMP_NANO},
{ "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' },
{ "count", no_argument, NULL, OPTION_COUNT },
{ "fp-type", no_argument, NULL, OPTION_FP_TYPE },
{ "number", no_argument, NULL, '#' },
{ "print", no_argument, NULL, OPTION_PRINT },
{ "version", no_argument, NULL, OPTION_VERSION },
{ NULL, 0, NULL, 0 }
};
#ifdef HAVE_PCAP_FINDALLDEVS_EX
#define LIST_REMOTE_INTERFACES_USAGE "[ --list-remote-interfaces remote-source ]"
#else
#define LIST_REMOTE_INTERFACES_USAGE
#endif
#ifdef HAVE_PCAP_SET_IMMEDIATE_MODE
#define IMMEDIATE_MODE_USAGE " [ --immediate-mode ]"
#else
#define IMMEDIATE_MODE_USAGE ""
#endif
#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)
error("Chroot without dropping root is insecure");
pw = getpwnam(username);
if (pw) {
if (chroot_dir) {
if (chroot(chroot_dir) != 0 || chdir ("/") != 0)
error("Couldn't chroot/chdir to '%.64s': %s",
chroot_dir, pcap_strerror(errno));
}
#ifdef HAVE_LIBCAP_NG
{
int ret = capng_change_id(pw->pw_uid, pw->pw_gid, CAPNG_NO_FLAG);
if (ret < 0)
error("capng_change_id(): return %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)
error("Couldn't change to '%.32s' uid=%lu gid=%lu: %s",
username,
(unsigned long)pw->pw_uid,
(unsigned long)pw->pw_gid,
pcap_strerror(errno));
else {
fprintf(stderr, "dropped privs to %s\n", username);
}
#endif /* HAVE_LIBCAP_NG */
} else
error("Couldn't find user '%.32s'", username);
#ifdef HAVE_LIBCAP_NG
- /* We don't need CAP_SETUID, CAP_SETGID and CAP_SYS_CHROOT any more. */
+ /* We don't need CAP_SETUID, CAP_SETGID and CAP_SYS_CHROOT anymore. */
DIAG_OFF_ASSIGN_ENUM
capng_updatev(
CAPNG_DROP,
CAPNG_EFFECTIVE | CAPNG_PERMITTED,
CAP_SETUID,
CAP_SETGID,
CAP_SYS_CHROOT,
-1);
DIAG_ON_ASSIGN_ENUM
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("%s: malloc", __func__);
if (strlen(orig_name) == 0)
error("an empty string is not a valid file name");
/* 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("%s: localtime", __func__);
}
/* There's no good way to detect an error in strftime since a return
* value of 0 isn't necessarily failure; if orig_name is an empty
* string, the formatted string will be empty.
*
* However, the C90 standard says that, if there *is* a
* buffer overflow, the content of the buffer is undefined,
* so we must check for a buffer overflow.
*
* So we check above for an empty orig_name, and only call
* strftime() if it's non-empty, in which case the return
* value will only be 0 if the formatted date doesn't fit
* in the buffer.
*
* (We check above because, even if we don't use -G, we
* want a better error message than "tcpdump: : No such
* file or directory" for this case.)
*/
if (strftime(filename, PATH_MAX, orig_name, local_tm) == 0) {
error("%s: strftime", __func__);
}
} 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;
size_t len;
ret = fgets(ptr, PATH_MAX, VFile);
if (!ret)
return NULL;
len = strlen (ptr);
if (len > 0 && ptr[len - 1] == '\n')
ptr[len - 1] = '\0';
return ret;
}
#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] = "ADDR2NAME";
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 /* 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.
+ * regular files notwithstanding.
*
* 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(char **argv)
{
char **p;
size_t 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("%s: malloc", __func__);
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)
{
int i, fd;
ssize_t cc;
char *cp;
our_statb buf;
fd = open(fname, O_RDONLY|O_BINARY);
if (fd < 0)
error("can't open %s: %s", fname, pcap_strerror(errno));
if (our_fstat(fd, &buf) < 0)
error("can't stat %s: %s", fname, pcap_strerror(errno));
/*
* Reject files whose size doesn't fit into an int; a filter
* *that* large will probably be too big.
*/
if (buf.st_size > INT_MAX)
error("%s is too large", fname);
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, (int) 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)
{
const char *p;
long devnum;
char *end;
/*
* Search for a colon, terminating any scheme at the beginning
* of the device.
*/
p = strchr(device, ':');
if (p != NULL) {
/*
* We found it. Is it followed by "//"?
*/
p++; /* skip the : */
if (strncmp(p, "//", 2) == 0) {
/*
* Yes. Search for the next /, at the end of the
* authority part of the URL.
*/
p += 2; /* skip the // */
p = strchr(p, '/');
if (p != NULL) {
/*
* OK, past the / is the path.
*/
device = p + 1;
}
}
}
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");
+ error("Invalid adapter index %s", device);
}
return (devnum);
} else {
/*
* It's not all-numeric; return -1, so our caller
* knows that.
*/
return (-1);
}
}
static char *
find_interface_by_number(const char *url
#ifndef HAVE_PCAP_FINDALLDEVS_EX
_U_
#endif
, long devnum)
{
pcap_if_t *dev, *devlist;
long i;
char ebuf[PCAP_ERRBUF_SIZE];
char *device;
#ifdef HAVE_PCAP_FINDALLDEVS_EX
const char *endp;
char *host_url;
#endif
int status;
#ifdef HAVE_PCAP_FINDALLDEVS_EX
/*
* Search for a colon, terminating any scheme at the beginning
* of the URL.
*/
endp = strchr(url, ':');
if (endp != NULL) {
/*
* We found it. Is it followed by "//"?
*/
endp++; /* skip the : */
if (strncmp(endp, "//", 2) == 0) {
/*
* Yes. Search for the next /, at the end of the
* authority part of the URL.
*/
endp += 2; /* skip the // */
endp = strchr(endp, '/');
} else
endp = NULL;
}
if (endp != NULL) {
/*
* OK, everything from device to endp is a URL to hand
* to pcap_findalldevs_ex().
*/
endp++; /* Include the trailing / in the URL; pcap_findalldevs_ex() requires it */
host_url = malloc(endp - url + 1);
if (host_url == NULL && (endp - url + 1) > 0)
error("Invalid allocation for host");
memcpy(host_url, url, endp - url);
host_url[endp - url] = '\0';
status = pcap_findalldevs_ex(host_url, NULL, &devlist, ebuf);
free(host_url);
} else
#endif
status = pcap_findalldevs(&devlist, ebuf);
if (status < 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");
+ if (dev == NULL) {
+ pcap_freealldevs(devlist);
+ error("Invalid adapter index %ld: only %ld interfaces found",
+ devnum, i);
+ }
device = strdup(dev->name);
pcap_freealldevs(devlist);
return (device);
}
#endif
#ifdef HAVE_PCAP_OPEN
/*
* Prefixes for rpcap URLs.
*/
static char rpcap_prefix[] = "rpcap://";
static char rpcap_ssl_prefix[] = "rpcaps://";
#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_OPEN
/*
* Is this an rpcap URL?
*/
if (strncmp(device, rpcap_prefix, sizeof(rpcap_prefix) - 1) == 0 ||
strncmp(device, rpcap_ssl_prefix, sizeof(rpcap_ssl_prefix) - 1) == 0) {
/*
* Yes. Open it with pcap_open().
*/
*ebuf = '\0';
pc = pcap_open(device, ndo->ndo_snaplen,
pflag ? 0 : PCAP_OPENFLAG_PROMISCUOUS, timeout, NULL,
ebuf);
if (pc == NULL) {
/*
* If this failed with "No such device" or "The system
* cannot find the device specified", 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 ||
strstr(ebuf, "The system cannot find the device specified") != NULL)
return (NULL);
error("%s", ebuf);
}
if (*ebuf)
warning("%s", ebuf);
return (pc);
}
#endif /* HAVE_PCAP_OPEN */
#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;
if (ndo->ndo_snaplen != 0) {
/*
* A snapshot length was explicitly specified;
* use it.
*/
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, timeout);
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));
else if (status > 0)
warning("When trying to set timestamp type '%s' on %s: %s",
pcap_tstamp_type_val_to_name(jflag), 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);
} 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. */
/* FIXME: incrementing the index this way is not going to work well
* when the index is 9 or greater but the only consequence in this
* specific case would be an error message that looks a bit odd.
*/
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));
pcap_close(pc);
return (NULL);
} 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';
/*
* If no snapshot length was specified, or a length of 0 was
* specified, default to 256KB.
*/
if (ndo->ndo_snaplen == 0)
ndo->ndo_snaplen = MAXIMUM_SNAPLEN;
pc = pcap_open_live(device, ndo->ndo_snaplen, !pflag, timeout, 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)
{
int cnt, op, i;
bpf_u_int32 localnet = 0, netmask = 0;
char *cp, *infile, *cmdbuf, *device, *RFileName, *VFileName, *WFileName;
char *endp;
pcap_handler callback;
int dlt;
const char *dlt_name;
struct bpf_program fcode;
#ifndef _WIN32
void (*oldhandler)(int);
#endif
struct dump_info dumpinfo;
u_char *pcap_userdata;
char ebuf[PCAP_ERRBUF_SIZE];
char VFileLine[PATH_MAX + 1];
const char *username = NULL;
#ifndef _WIN32
const char *chroot_dir = NULL;
#endif
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;
int print = 0;
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);
cnt = -1;
device = NULL;
infile = NULL;
RFileName = NULL;
VFileName = NULL;
VFile = NULL;
WFileName = NULL;
dlt = -1;
if ((cp = strrchr(argv[0], PATH_SEPARATOR)) != NULL)
ndo->program_name = program_name = cp + 1;
else
ndo->program_name = program_name = argv[0];
#if defined(HAVE_PCAP_WSOCKINIT)
if (pcap_wsockinit() != 0)
error("Attempting to initialize Winsock failed");
#elif defined(HAVE_WSOCKINIT)
if (wsockinit() != 0)
error("Attempting to initialize Winsock failed");
#endif
/*
* 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);
+ /*
+ * An explicit tzset() call is usually not needed as it happens
+ * implicitly the first time we call localtime() or mktime(),
+ * but in some cases (sandboxing, chroot) this may be too late.
+ */
tzset();
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':
errno = 0;
#ifdef HAVE_PCAP_DUMP_FTELL64
Cflag = strtoint64_t(optarg, &endp, 10);
#else
Cflag = strtol(optarg, &endp, 10);
#endif
if (endp == optarg || *endp != '\0' || errno != 0
|| Cflag <= 0)
error("invalid file size %s", optarg);
/*
* Will multiplying it by 1000000 overflow?
*/
#ifdef HAVE_PCAP_DUMP_FTELL64
if (Cflag > INT64_T_CONSTANT(0x7fffffffffffffff) / 1000000)
#else
if (Cflag > LONG_MAX / 1000000)
#endif
error("file size %s is too large", optarg);
Cflag *= 1000000;
break;
case 'd':
++dflag;
break;
#ifdef HAVE_PCAP_FINDALLDEVS
case 'D':
Dflag++;
break;
#endif
#ifdef HAVE_PCAP_FINDALLDEVS_EX
case OPTION_LIST_REMOTE_INTERFACES:
remote_interfaces_source = optarg;
break;
#endif
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("%s: can't get current time: %s",
__func__, pcap_strerror(errno));
}
break;
case 'h':
print_usage(stdout);
exit_tcpdump(S_SUCCESS);
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 */
lflag = 1;
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' ",
+ (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);
+ error("unknown capture direction '%s'", optarg);
break;
#endif /* HAVE_PCAP_SETDIRECTION */
case 'r':
RFileName = optarg;
break;
case 's':
ndo->ndo_snaplen = (int)strtol(optarg, &end, 0);
if (optarg == end || *end != '\0'
|| ndo->ndo_snaplen < 0 || ndo->ndo_snaplen > MAXIMUM_SNAPLEN)
error("invalid snaplen %s (must be >= 0 and <= %d)",
optarg, 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 if (ascii_strcasecmp(optarg, "ptp") == 0)
ndo->ndo_packettype = PT_PTP;
else if (ascii_strcasecmp(optarg, "someip") == 0)
ndo->ndo_packettype = PT_SOMEIP;
else if (ascii_strcasecmp(optarg, "domain") == 0)
ndo->ndo_packettype = PT_DOMAIN;
else
- error("unknown packet type `%s'", optarg);
+ 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(stdout);
exit_tcpdump(S_SUCCESS);
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
case OPTION_PRINT:
print = 1;
break;
#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
case OPTION_TSTAMP_MICRO:
ndo->ndo_tstamp_precision = PCAP_TSTAMP_PRECISION_MICRO;
break;
case OPTION_TSTAMP_NANO:
ndo->ndo_tstamp_precision = PCAP_TSTAMP_PRECISION_NANO;
break;
#endif
case OPTION_FP_TYPE:
/*
* Print out the type of floating-point arithmetic
* we're doing; it's probably IEEE, unless somebody
* tries to run this on a VAX, but the precision
* may differ (e.g., it might be 32-bit, 64-bit,
* or 80-bit).
*/
float_type_check(0x4e93312d);
return 0;
case OPTION_COUNT:
count_mode = 1;
break;
default:
print_usage(stderr);
exit_tcpdump(S_ERR_HOST_PROGRAM);
/* NOTREACHED */
}
#ifdef HAVE_PCAP_FINDALLDEVS
if (Dflag)
show_devices_and_exit();
#endif
#ifdef HAVE_PCAP_FINDALLDEVS_EX
if (remote_interfaces_source != NULL)
show_remote_devices_and_exit();
#endif
-#if defined(DLT_LINUX_SLL2) && defined(HAVE_PCAP_SET_DATALINK)
-/* Set default linktype DLT_LINUX_SLL2 when capturing on the "any" device */
- if (device != NULL &&
- strncmp (device, "any", strlen("any")) == 0
- && yflag_dlt == -1)
- yflag_dlt = DLT_LINUX_SLL2;
-#endif
-
switch (ndo->ndo_tflag) {
case 0: /* Default */
case 1: /* No time stamp */
case 2: /* Unix timeval style */
case 3: /* Microseconds/nanoseconds since previous packet */
case 4: /* Date + Default */
case 5: /* Microseconds/nanoseconds 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.");
/*
* If we're printing dissected packets to the standard output,
* and either the standard output is a terminal or we're doing
* "line" buffering, set the capture timeout to .1 second rather
* than 1 second, as the user's probably expecting to see packets
* pop up immediately shortly after they arrive.
*
* XXX - would there be some value appropriate for all cases,
* based on, say, the buffer size and packet input rate?
*/
if ((WFileName == NULL || print) && (isatty(1) || lflag))
timeout = 100;
#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;
+ else if (strcmp(username, "root") == 0)
+ username = NULL;
}
#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);
fprintf(stderr, "reading from file %s", RFileName);
if (dlt_name == NULL) {
fprintf(stderr, ", link-type %u", dlt);
} else {
fprintf(stderr, ", link-type %s (%s)", dlt_name,
pcap_datalink_val_to_description(dlt));
}
fprintf(stderr, ", snapshot length %d\n", pcap_snapshot(pd));
#ifdef DLT_LINUX_SLL2
if (dlt == DLT_LINUX_SLL2)
fprintf(stderr, "Warning: interface names might be incorrect\n");
#endif
} else if (dflag && !device) {
int dump_dlt = DLT_EN10MB;
/*
* We're dumping the compiled code without an explicit
* device specification. (If a device is specified, we
* definitely want to open it to use the DLT of that device.)
* Either default to DLT_EN10MB with a warning, or use
* the user-specified value if supplied.
*/
/*
* If no snapshot length was specified, or a length of 0 was
* specified, default to 256KB.
*/
if (ndo->ndo_snaplen == 0)
ndo->ndo_snaplen = MAXIMUM_SNAPLEN;
/*
* If a DLT was specified with the -y flag, use that instead.
*/
if (yflag_dlt != -1)
dump_dlt = yflag_dlt;
else
fprintf(stderr, "Warning: assuming Ethernet\n");
pd = pcap_open_dead(dump_dlt, ndo->ndo_snaplen);
} 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) == -1)
error("%s", ebuf);
if (devlist == NULL)
error("no interfaces available for capture");
device = strdup(devlist->name);
pcap_freealldevs(devlist);
#else /* HAVE_PCAP_FINDALLDEVS */
/*
* Use whatever interface pcap_lookupdev()
* chooses.
*/
device = pcap_lookupdev(ebuf);
if (device == NULL)
error("%s", ebuf);
#endif
}
/*
* 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(device, 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 capture device 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,
pcap_datalink_val_to_name(yflag_dlt));
(void)fflush(stderr);
}
+#if defined(DLT_LINUX_SLL2) && defined(HAVE_PCAP_SET_DATALINK)
+ else {
+ /*
+ * Attempt to set default linktype to
+ * DLT_LINUX_SLL2 when capturing on the
+ * "any" device.
+ *
+ * If the attempt fails, just quietly drive
+ * on; this may be a non-Linux "any" device
+ * that doesn't support DLT_LINUX_SLL2.
+ */
+ if (strcmp(device, "any") == 0) {
+DIAG_OFF_WARN_UNUSED_RESULT
+ (void) pcap_set_datalink(pd, DLT_LINUX_SLL2);
+DIAG_ON_WARN_UNUSED_RESULT
+ }
+ }
+#endif
i = pcap_snapshot(pd);
if (ndo->ndo_snaplen < i) {
if (ndo->ndo_snaplen != 0)
warning("snaplen raised from %d to %d", ndo->ndo_snaplen, i);
ndo->ndo_snaplen = i;
} else if (ndo->ndo_snaplen > i) {
warning("snaplen lowered 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(S_SUCCESS);
}
#ifdef HAVE_CASPER
if (!ndo->ndo_nflag)
capdns = capdns_setup();
#endif /* HAVE_CASPER */
init_print(ndo, localnet, netmask);
#ifndef _WIN32
(void)setsignal(SIGPIPE, cleanup);
(void)setsignal(SIGTERM, cleanup);
#endif /* _WIN32 */
(void)setsignal(SIGINT, cleanup);
#if defined(HAVE_FORK) || defined(HAVE_VFORK)
(void)setsignal(SIGCHLD, child_cleanup);
#endif
/* Cooperate with nohup(1) */
#ifndef _WIN32
+ /*
+ * In illumos /usr/include/sys/iso/signal_iso.h causes Clang to
+ * generate a -Wstrict-prototypes warning here, see [1]. The
+ * __illumos__ macro is available since at least GCC 11 and Clang 13,
+ * see [2].
+ * 1: https://www.illumos.org/issues/16344
+ * 2: https://www.illumos.org/issues/13726
+ */
+#ifdef __illumos__
+ DIAG_OFF_STRICT_PROTOTYPES
+#endif /* __illumos__ */
if ((oldhandler = setsignal(SIGHUP, cleanup)) != SIG_DFL)
+#ifdef __illumos__
+ DIAG_ON_STRICT_PROTOTYPES
+#endif /* __illumos__ */
(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) {
DIAG_OFF_ASSIGN_ENUM
capng_updatev(
CAPNG_ADD,
CAPNG_PERMITTED | CAPNG_EFFECTIVE,
CAP_SETUID,
CAP_SETGID,
-1);
DIAG_ON_ASSIGN_ENUM
}
if (chroot_dir) {
DIAG_OFF_ASSIGN_ENUM
capng_update(
CAPNG_ADD,
CAPNG_PERMITTED | CAPNG_EFFECTIVE,
CAP_SYS_CHROOT
);
DIAG_ON_ASSIGN_ENUM
}
if (WFileName) {
DIAG_OFF_ASSIGN_ENUM
capng_update(
CAPNG_ADD,
CAPNG_PERMITTED | CAPNG_EFFECTIVE,
CAP_DAC_OVERRIDE
);
DIAG_ON_ASSIGN_ENUM
}
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 && pcap_fileno(pd) != -1) {
static const unsigned long cmds[] = { BIOCGSTATS, BIOCROTZBUF };
/*
* The various libpcap devices use a combination of
* read (bpf), ioctl (bpf, netmap), poll (netmap)
* so we add the relevant access rights.
*/
cap_rights_init(&rights, CAP_IOCTL, CAP_READ, CAP_EVENT);
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) {
/* 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);
pdd = 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 (pdd == NULL)
error("%s", pcap_geterr(pd));
#ifdef HAVE_CAPSICUM
set_dumper_capsicum_rights(pdd);
#endif
if (Cflag != 0 || Gflag != 0) {
#ifdef HAVE_CAPSICUM
/*
* basename() and dirname() may modify their input buffer
* and they do since FreeBSD 12.0, but they didn't before.
* Hence use the return value only, but always assume the
* input buffer has been modified and would need to be
* reset before the next use.
*/
char *WFileName_copy;
if ((WFileName_copy = strdup(WFileName)) == NULL) {
error("Unable to allocate memory for file %s",
WFileName);
}
DIAG_OFF_C11_EXTENSIONS
dumpinfo.WFileName = strdup(basename(WFileName_copy));
DIAG_ON_C11_EXTENSIONS
if (dumpinfo.WFileName == NULL) {
error("Unable to allocate memory for file %s",
WFileName);
}
free(WFileName_copy);
if ((WFileName_copy = strdup(WFileName)) == NULL) {
error("Unable to allocate memory for file %s",
WFileName);
}
DIAG_OFF_C11_EXTENSIONS
char *WFileName_dirname = dirname(WFileName_copy);
DIAG_ON_C11_EXTENSIONS
dumpinfo.dirfd = open(WFileName_dirname,
O_DIRECTORY | O_RDONLY);
if (dumpinfo.dirfd < 0) {
error("unable to open directory %s",
WFileName_dirname);
}
free(WFileName_dirname);
free(WFileName_copy);
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.pdd = pdd;
pcap_userdata = (u_char *)&dumpinfo;
} else {
callback = dump_packet;
dumpinfo.WFileName = WFileName;
dumpinfo.pd = pd;
dumpinfo.pdd = pdd;
pcap_userdata = (u_char *)&dumpinfo;
}
if (print) {
dlt = pcap_datalink(pd);
ndo->ndo_if_printer = get_if_printer(dlt);
dumpinfo.ndo = ndo;
} else
dumpinfo.ndo = NULL;
#ifdef HAVE_PCAP_DUMP_FLUSH
if (Uflag)
pcap_dump_flush(pdd);
#endif
} else {
dlt = pcap_datalink(pd);
ndo->ndo_if_printer = get_if_printer(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
#ifdef SIGNAL_FLUSH_PCAP
(void)setsignal(SIGNAL_FLUSH_PCAP, flushpcap);
#endif
if (ndo->ndo_vflag > 0 && WFileName && RFileName == NULL && !print) {
/*
* When capturing to a file, if "--print" wasn't specified,
*"-v" means tcpdump should, once per second,
* "v"erbosely report the number of packets captured.
* Except when reading from a file, because -r, -w and -v
* together used to make a corner case, in which pcap_loop()
* errored due to EINTR (see GH #155 for details).
*/
#ifdef _WIN32
/*
* https://blogs.msdn.microsoft.com/oldnewthing/20151230-00/?p=92741
*
* suggests that this dates back to W2K.
*
* I don't know what a "long wait" is, but we'll assume
* that printing the stats could be a "long wait".
*/
CreateTimerQueueTimer(&timer_handle, NULL,
verbose_stats_dump, NULL, 1000, 1000,
WT_EXECUTEDEFAULT|WT_EXECUTELONGFUNCTION);
setvbuf(stderr, NULL, _IONBF, 0);
#else /* _WIN32 */
/*
* Assume this is UN*X, and that it has setitimer(); that
* dates back to UNIX 95.
*/
struct itimerval timer;
(void)setsignal(SIGALRM, verbose_stats_dump);
timer.it_interval.tv_sec = 1;
timer.it_interval.tv_usec = 0;
timer.it_value.tv_sec = 1;
timer.it_value.tv_usec = 1;
setitimer(ITIMER_REAL, &timer, NULL);
#endif /* _WIN32 */
}
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[v]... 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);
(void)fprintf(stderr, "listening on %s", device);
if (dlt_name == NULL) {
(void)fprintf(stderr, ", link-type %u", dlt);
} else {
(void)fprintf(stderr, ", link-type %s (%s)", dlt_name,
pcap_datalink_val_to_description(dlt));
}
(void)fprintf(stderr, ", snapshot length %d bytes\n", ndo->ndo_snaplen);
(void)fflush(stderr);
}
#ifdef HAVE_CAPSICUM
cansandbox = (VFileName == NULL && zflag == NULL &&
ndo->ndo_espsecret == NULL);
#ifdef HAVE_CASPER
cansandbox = (cansandbox && (ndo->ndo_nflag || capdns != NULL));
#else
cansandbox = (cansandbox && ndo->ndo_nflag);
-#endif /* HAVE_CASPER */
+#endif /* HAVE_CASPER */
cansandbox = (cansandbox && (pcap_fileno(pd) != -1 ||
RFileName != NULL));
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(dlt);
+ /* Free the old filter */
+ pcap_freecode(&fcode);
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);
fprintf(stderr, "reading from file %s", RFileName);
if (dlt_name == NULL) {
fprintf(stderr, ", link-type %u", dlt);
} else {
fprintf(stderr, ", link-type %s (%s)",
dlt_name,
pcap_datalink_val_to_description(dlt));
}
fprintf(stderr, ", snapshot length %d\n", pcap_snapshot(pd));
}
}
}
while (ret != NULL);
if (count_mode && RFileName != NULL)
fprintf(stdout, "%u packet%s\n", packets_captured,
PLURAL_SUFFIX(packets_captured));
free(cmdbuf);
pcap_freecode(&fcode);
exit_tcpdump(status == -1 ? S_ERR_HOST_PROGRAM : S_SUCCESS);
}
/*
* Catch a signal.
*/
static void
(*setsignal (int sig, void (*func)(int)))(int)
{
#ifdef _WIN32
return (signal(sig, func));
#else
struct sigaction old, new;
memset(&new, 0, sizeof(new));
new.sa_handler = func;
if ((sig == SIGCHLD)
# ifdef SIGNAL_REQ_INFO
|| (sig == SIGNAL_REQ_INFO)
# endif
# ifdef SIGNAL_FLUSH_PCAP
|| (sig == SIGNAL_FLUSH_PCAP)
# endif
)
new.sa_flags = SA_RESTART;
if (sigaction(sig, &new, &old) < 0)
+ /* The same workaround as for SIG_DFL above. */
+#ifdef __illumos__
+ DIAG_OFF_STRICT_PROTOTYPES
+#endif /* __illumos__ */
return (SIG_ERR);
+#ifdef __illumos__
+ DIAG_ON_STRICT_PROTOTYPES
+#endif /* __illumos__ */
return (old.sa_handler);
#endif
}
/* make a clean exit on interrupts */
static void
cleanup(int signo _U_)
{
#ifdef _WIN32
if (timer_handle != INVALID_HANDLE_VALUE) {
DeleteTimerQueueTimer(NULL, timer_handle, NULL);
CloseHandle(timer_handle);
timer_handle = INVALID_HANDLE_VALUE;
}
#else /* _WIN32 */
struct itimerval timer;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 0;
timer.it_value.tv_sec = 0;
timer.it_value.tv_usec = 0;
setitimer(ITIMER_REAL, &timer, NULL);
#endif /* _WIN32 */
#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(S_SUCCESS);
#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 void
child_cleanup(int signo _U_)
{
- wait(NULL);
+ while (waitpid(-1, NULL, WNOHANG) >= 0);
}
#endif /* HAVE_FORK && HAVE_VFORK */
static void
info(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(S_ERR_HOST_PROGRAM);
#else
_exit(S_ERR_HOST_PROGRAM);
#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("%s: can't get current_time: %s",
__func__, 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->pdd);
/*
* 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(S_SUCCESS);
/* 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->pdd = pcap_dump_fopen(dump_info->pd, fp);
#else /* !HAVE_CAPSICUM */
dump_info->pdd = 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->pdd == NULL)
error("%s", pcap_geterr(pd));
#ifdef HAVE_CAPSICUM
set_dumper_capsicum_rights(dump_info->pdd);
#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) {
#ifdef HAVE_PCAP_DUMP_FTELL64
int64_t size = pcap_dump_ftell64(dump_info->pdd);
#else
/*
* XXX - this only handles a Cflag value > 2^31-1 on
* LP64 platforms; to handle ILP32 (32-bit UN*X and
* Windows) or LLP64 (64-bit Windows) would require
* a version of libpcap with pcap_dump_ftell64().
*/
long size = pcap_dump_ftell(dump_info->pdd);
#endif
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->pdd);
/*
* 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("%s: malloc", __func__);
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->pdd = pcap_dump_fopen(dump_info->pd, fp);
#else /* !HAVE_CAPSICUM */
dump_info->pdd = 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->pdd == NULL)
error("%s", pcap_geterr(pd));
#ifdef HAVE_CAPSICUM
set_dumper_capsicum_rights(dump_info->pdd);
#endif
}
}
pcap_dump((u_char *)dump_info->pdd, h, sp);
#ifdef HAVE_PCAP_DUMP_FLUSH
if (Uflag)
pcap_dump_flush(dump_info->pdd);
#endif
if (dump_info->ndo != NULL)
pretty_print_packet(dump_info->ndo, h, sp, packets_captured);
--infodelay;
if (infoprint)
info(0);
}
static void
dump_packet(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;
pcap_dump((u_char *)dump_info->pdd, h, sp);
#ifdef HAVE_PCAP_DUMP_FLUSH
if (Uflag)
pcap_dump_flush(dump_info->pdd);
#endif
if (dump_info->ndo != NULL)
pretty_print_packet(dump_info->ndo, h, sp, packets_captured);
--infodelay;
if (infoprint)
info(0);
}
static void
print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
{
++packets_captured;
++infodelay;
if (!count_mode)
pretty_print_packet((netdissect_options *)user, h, sp, packets_captured);
--infodelay;
if (infoprint)
info(0);
}
#ifdef SIGNAL_REQ_INFO
static void
requestinfo(int signo _U_)
{
if (infodelay)
++infoprint;
else
info(0);
}
#endif
#ifdef SIGNAL_FLUSH_PCAP
static void
flushpcap(int signo _U_)
{
if (pdd != NULL)
pcap_dump_flush(pdd);
}
#endif
static void
print_packets_captured (void)
{
static u_int prev_packets_captured, first = 1;
if (infodelay == 0 && (first || packets_captured != prev_packets_captured)) {
fprintf(stderr, "Got %u\r", packets_captured);
first = 0;
prev_packets_captured = packets_captured;
}
}
/*
* Called once each second in verbose mode while dumping to file
*/
#ifdef _WIN32
static void CALLBACK verbose_stats_dump(PVOID param _U_,
BOOLEAN timer_fired _U_)
{
print_packets_captured();
}
#else /* _WIN32 */
static void verbose_stats_dump(int sig _U_)
{
print_packets_captured();
}
#endif /* _WIN32 */
DIAG_OFF_DEPRECATION
static void
print_version(FILE *f)
{
#ifndef HAVE_PCAP_LIB_VERSION
#ifdef HAVE_PCAP_VERSION
extern char pcap_version[];
#else /* HAVE_PCAP_VERSION */
static char pcap_version[] = "unknown";
#endif /* HAVE_PCAP_VERSION */
#endif /* HAVE_PCAP_LIB_VERSION */
const char *smi_version_string;
(void)fprintf(f, "%s version " PACKAGE_VERSION "\n", program_name);
#ifdef HAVE_PCAP_LIB_VERSION
(void)fprintf(f, "%s\n", pcap_lib_version());
#else /* HAVE_PCAP_LIB_VERSION */
(void)fprintf(f, "libpcap version %s\n", pcap_version);
#endif /* HAVE_PCAP_LIB_VERSION */
#if defined(HAVE_LIBCRYPTO) && defined(SSLEAY_VERSION)
(void)fprintf (f, "%s\n", SSLeay_version(SSLEAY_VERSION));
#endif
smi_version_string = nd_smi_version_string();
if (smi_version_string != NULL)
(void)fprintf (f, "SMI-library: %s\n", smi_version_string);
#if defined(__SANITIZE_ADDRESS__)
(void)fprintf (f, "Compiled with AddressSanitizer/GCC.\n");
#elif defined(__has_feature)
# if __has_feature(address_sanitizer)
(void)fprintf (f, "Compiled with AddressSanitizer/Clang.\n");
# elif __has_feature(memory_sanitizer)
(void)fprintf (f, "Compiled with MemorySanitizer/Clang.\n");
# endif
#endif /* __SANITIZE_ADDRESS__ or __has_feature */
+ (void)fprintf (f, "%zu-bit build, %zu-bit time_t\n",
+ sizeof(void *) * 8, sizeof(time_t) * 8);
}
DIAG_ON_DEPRECATION
static void
print_usage(FILE *f)
{
print_version(f);
(void)fprintf(f,
"Usage: %s [-Abd" D_FLAG "efhH" I_FLAG J_FLAG "KlLnNOpqStu" U_FLAG "vxX#]" B_FLAG_USAGE " [ -c count ] [--count]\n", program_name);
(void)fprintf(f,
"\t\t[ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ]\n");
(void)fprintf(f,
"\t\t[ -i interface ]" IMMEDIATE_MODE_USAGE j_FLAG_USAGE "\n");
#ifdef HAVE_PCAP_FINDALLDEVS_EX
(void)fprintf(f,
"\t\t" LIST_REMOTE_INTERFACES_USAGE "\n");
#endif
#ifdef USE_LIBSMI
(void)fprintf(f,
"\t\t" m_FLAG_USAGE "\n");
#endif
(void)fprintf(f,
"\t\t[ -M secret ] [ --number ] [ --print ]" Q_FLAG_USAGE "\n");
(void)fprintf(f,
"\t\t[ -r file ] [ -s snaplen ] [ -T type ] [ --version ]\n");
(void)fprintf(f,
"\t\t[ -V file ] [ -w file ] [ -W filecount ] [ -y datalinktype ]\n");
#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
(void)fprintf(f,
"\t\t[ --time-stamp-precision precision ] [ --micro ] [ --nano ]\n");
#endif
(void)fprintf(f,
"\t\t[ -z postrotate-command ] [ -Z user ] [ expression ]\n");
}
diff --git a/contrib/tcpdump/udp.h b/contrib/tcpdump/udp.h
index e714180ffd97..1eec850268e4 100644
--- a/contrib/tcpdump/udp.h
+++ b/contrib/tcpdump/udp.h
@@ -1,250 +1,250 @@
/*
* Copyright (c) 1982, 1986, 1993
* 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 the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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 BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)udp.h 8.1 (Berkeley) 6/10/93
*/
/*
* Udp protocol header.
* Per RFC 768, September, 1981.
*/
struct udphdr {
nd_uint16_t uh_sport; /* source port */
nd_uint16_t uh_dport; /* destination port */
nd_uint16_t uh_ulen; /* udp length */
nd_uint16_t uh_sum; /* udp checksum */
};
#ifndef NAMESERVER_PORT
#define NAMESERVER_PORT 53
#endif
#ifndef BOOTPS_PORT
#define BOOTPS_PORT 67 /* RFC951 */
#endif
#ifndef BOOTPC_PORT
#define BOOTPC_PORT 68 /* RFC951 */
#endif
#ifndef TFTP_PORT
#define TFTP_PORT 69 /*XXX*/
#endif
#ifndef KERBEROS_PORT
#define KERBEROS_PORT 88 /*XXX*/
#endif
#ifndef SUNRPC_PORT
#define SUNRPC_PORT 111 /*XXX*/
#endif
#ifndef NTP_PORT
#define NTP_PORT 123 /*XXX*/
#endif
#ifndef NETBIOS_NS_PORT
#define NETBIOS_NS_PORT 137 /* RFC 1001, RFC 1002 */
#endif
#ifndef NETBIOS_DGRAM_PORT
#define NETBIOS_DGRAM_PORT 138 /* RFC 1001, RFC 1002 */
#endif
#ifndef SNMP_PORT
#define SNMP_PORT 161 /*XXX*/
#endif
#ifndef SNMPTRAP_PORT
#define SNMPTRAP_PORT 162 /*XXX*/
#endif
#ifndef PTP_EVENT_PORT
-#define PTP_EVENT_PORT 319 /* IANA */
+#define PTP_EVENT_PORT 319 /* IANA */
#endif
#ifndef PTP_GENERAL_PORT
-#define PTP_GENERAL_PORT 320 /* IANA */
+#define PTP_GENERAL_PORT 320 /* IANA */
#endif
#ifndef CISCO_AUTORP_PORT
#define CISCO_AUTORP_PORT 496 /*XXX*/
#endif
#ifndef ISAKMP_PORT
#define ISAKMP_PORT 500 /*XXX*/
#endif
#ifndef SYSLOG_PORT
#define SYSLOG_PORT 514 /* rfc3164 */
#endif
#ifndef RIP_PORT
#define RIP_PORT 520 /*XXX*/
#endif
#ifndef RIPNG_PORT
#define RIPNG_PORT 521 /* RFC 2080 */
#endif
#ifndef TIMED_PORT
#define TIMED_PORT 525 /*XXX*/
#endif
#ifndef DHCP6_SERV_PORT
#define DHCP6_SERV_PORT 546 /*XXX*/
#endif
#ifndef DHCP6_CLI_PORT
#define DHCP6_CLI_PORT 547 /*XXX*/
#endif
#ifndef LDP_PORT
#define LDP_PORT 646
#endif
-#ifndef AQDV_PORT
+#ifndef AODV_PORT
#define AODV_PORT 654 /*XXX*/
#endif
#ifndef OLSR_PORT
#define OLSR_PORT 698 /* rfc3626 */
#endif
#ifndef LMP_PORT
#define LMP_PORT 701 /* rfc4204 */
#endif
#ifndef KERBEROS_SEC_PORT
#define KERBEROS_SEC_PORT 750 /*XXX - Kerberos v4 */
#endif
#ifndef LWRES_PORT
#define LWRES_PORT 921 /*XXX*/
#endif
#ifndef VQP_PORT
#define VQP_PORT 1589 /*XXX*/
#endif
#ifndef RADIUS_PORT
#define RADIUS_PORT 1645 /*XXX*/
#endif
#ifndef RADIUS_ACCOUNTING_PORT
#define RADIUS_ACCOUNTING_PORT 1646
#endif
#ifndef RADIUS_CISCO_COA_PORT
#define RADIUS_CISCO_COA_PORT 1700
#endif
#ifndef L2TP_PORT
#define L2TP_PORT 1701 /*XXX*/
#endif
#ifndef RADIUS_NEW_PORT
#define RADIUS_NEW_PORT 1812 /*XXX*/
#endif
#ifndef RADIUS_NEW_ACCOUNTING_PORT
#define RADIUS_NEW_ACCOUNTING_PORT 1813
#endif
#ifndef HSRP_PORT
#define HSRP_PORT 1985 /*XXX*/
#endif
#ifndef ZEPHYR_SRV_PORT
#define ZEPHYR_SRV_PORT 2103 /*XXX*/
#endif
-#ifndef ZEPHYR_CLI_PORT
+#ifndef ZEPHYR_CLT_PORT
#define ZEPHYR_CLT_PORT 2104 /*XXX*/
#endif
#ifndef VAT_PORT
#define VAT_PORT 3456 /*XXX*/
#endif
#ifndef MPLS_LSP_PING_PORT
#define MPLS_LSP_PING_PORT 3503 /* draft-ietf-mpls-lsp-ping-02.txt */
#endif
-#ifndef BCM_LI_PORT
-#define BCM_LI_PORT 49152 /* SDK default */
-#endif
#ifndef BFD_CONTROL_PORT
#define BFD_CONTROL_PORT 3784 /* RFC 5881 */
#endif
#ifndef BFD_ECHO_PORT
#define BFD_ECHO_PORT 3785 /* RFC 5881 */
#endif
#ifndef RADIUS_COA_PORT
#define RADIUS_COA_PORT 3799 /* RFC 5176 */
#endif
#ifndef LISP_CONTROL_PORT
#define LISP_CONTROL_PORT 4342 /* RFC 6830 */
#endif
#ifndef ISAKMP_PORT_NATT
#define ISAKMP_PORT_NATT 4500 /* rfc3948 */
#endif
#ifndef WB_PORT
#define WB_PORT 4567
#endif
#ifndef BFD_MULTIHOP_PORT
#define BFD_MULTIHOP_PORT 4784 /* RFC 5883 */
#endif
#ifndef VXLAN_PORT
#define VXLAN_PORT 4789 /* RFC 7348 */
#endif
#ifndef VXLAN_GPE_PORT
#define VXLAN_GPE_PORT 4790 /* draft-ietf-nvo3-vxlan-gpe-01 */
#endif
#ifndef SIP_PORT
#define SIP_PORT 5060
#endif
#ifndef MULTICASTDNS_PORT
#define MULTICASTDNS_PORT 5353 /* RFC 6762 */
#endif
#ifndef AHCP_PORT
#define AHCP_PORT 5359 /* draft-chroboczek-ahcp-00 */
#endif
#ifndef GENEVE_PORT
#define GENEVE_PORT 6081 /* draft-gross-geneve-02 */
#endif
#ifndef SFLOW_PORT
#define SFLOW_PORT 6343 /* https://sflow.org/developers/specifications.php */
#endif
#ifndef MPLS_PORT
#define MPLS_PORT 6635 /* RFC 7510 */
#endif
#ifndef BABEL_PORT
#define BABEL_PORT 6696 /* RFC 6126 errata */
#endif
#ifndef BABEL_PORT_OLD
#define BABEL_PORT_OLD 6697 /* RFC 6126 */
#endif
#ifndef BFD_LAG_PORT
#define BFD_LAG_PORT 6784 /* RFC 7310 */
#endif
#ifndef RX_PORT_LOW
#define RX_PORT_LOW 7000 /*XXX*/
#endif
#ifndef RX_PORT_HIGH
#define RX_PORT_HIGH 7009 /*XXX*/
#endif
#ifndef ISAKMP_PORT_USER1
#define ISAKMP_PORT_USER1 7500 /*XXX - nonstandard*/
#endif
#ifndef HNCP_PORT
#define HNCP_PORT 8231 /* RFC 7788 */
#endif
#ifndef OTV_PORT
#define OTV_PORT 8472 /* draft-hasmit-otv-04 */
#endif
#ifndef ISAKMP_PORT_USER2
#define ISAKMP_PORT_USER2 8500 /*XXX - nonstandard*/
#endif
#ifndef LWAPP_DATA_PORT
#define LWAPP_DATA_PORT 12222 /* RFC 5412 */
#endif
#ifndef LWAPP_CONTROL_PORT
#define LWAPP_CONTROL_PORT 12223 /* RFC 5412 */
#endif
#ifndef ZEP_PORT
#define ZEP_PORT 17754 /* XXX */
#endif
#ifndef SOMEIP_PORT
#define SOMEIP_PORT 30490 /* https://www.autosar.org/standards/foundation */
#endif
+#ifndef BCM_LI_PORT
+#define BCM_LI_PORT 49152 /* SDK default */
+#endif
diff --git a/contrib/tcpdump/util-print.c b/contrib/tcpdump/util-print.c
index 0548337860ee..85ec24a33ed2 100644
--- a/contrib/tcpdump/util-print.c
+++ b/contrib/tcpdump/util-print.c
@@ -1,979 +1,986 @@
/*
* 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
* (hannes@gredler.at):
*
* 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 "netdissect-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 "netdissect-ctype.h"
#include "netdissect.h"
#include "extract.h"
#include "ascii_strcasecmp.h"
#include "timeval-operations.h"
#define TOKBUFSIZE 128
enum date_flag { WITHOUT_DATE = 0, WITH_DATE = 1 };
enum time_flag { UTC_TIME = 0, LOCAL_TIME = 1 };
/*
* Print out a character, filtering out the non-printable ones
*/
void
fn_print_char(netdissect_options *ndo, u_char c)
{
if (!ND_ISASCII(c)) {
c = ND_TOASCII(c);
ND_PRINT("M-");
}
if (!ND_ASCII_ISPRINT(c)) {
c ^= 0x40; /* DEL to ?, others to alpha */
ND_PRINT("^");
}
ND_PRINT("%c", c);
}
/*
* Print a null-terminated string, filtering out non-printable characters.
* DON'T USE IT with a pointer on the packet buffer because there is no
* truncation check. For this use, see the nd_printX() functions below.
*/
void
fn_print_str(netdissect_options *ndo, const u_char *s)
{
while (*s != '\0') {
fn_print_char(ndo, *s);
s++;
}
}
/*
* Print out a null-terminated filename (or other ASCII string) from
* a fixed-length field in the packet buffer, or from what remains of
* the packet.
*
* n is the length of the fixed-length field, or the number of bytes
* remaining in the packet based on its on-the-network length.
*
* If ep is non-null, it should point just past the last captured byte
* of the packet, e.g. ndo->ndo_snapend. If ep is NULL, we assume no
* truncation check, other than the checks of the field length/remaining
* packet data length, is needed.
*
* Return the number of bytes of string processed, including the
* terminating null, if not truncated; as the terminating null is
* included in the count, and as there must be a terminating null,
* this will always be non-zero. Return 0 if truncated.
*/
u_int
nd_printztn(netdissect_options *ndo,
const u_char *s, u_int n, const u_char *ep)
{
u_int bytes;
u_char c;
bytes = 0;
for (;;) {
if (n == 0 || (ep != NULL && s >= ep)) {
/*
* Truncated. This includes "no null before we
* got to the end of the fixed-length buffer or
* the end of the packet".
*
* XXX - BOOTP says "null-terminated", which
* means the maximum length of the string, in
* bytes, is 1 less than the size of the buffer,
* as there must always be a terminating null.
*/
bytes = 0;
break;
}
c = GET_U_1(s);
s++;
bytes++;
n--;
if (c == '\0') {
/* End of string */
break;
}
fn_print_char(ndo, c);
}
return(bytes);
}
/*
* Print out a counted filename (or other ASCII string), part of
* the packet buffer.
* If ep is NULL, assume no truncation check is needed.
* Return true if truncated.
* Stop at ep (if given) or after n bytes, whichever is first.
*/
int
nd_printn(netdissect_options *ndo,
const u_char *s, u_int n, const u_char *ep)
{
u_char c;
while (n > 0 && (ep == NULL || s < ep)) {
n--;
c = GET_U_1(s);
s++;
fn_print_char(ndo, c);
}
return (n == 0) ? 0 : 1;
}
+/*
+ * Print a counted filename (or other ASCII string), part of
+ * the packet buffer, filtering out non-printable characters.
+ * Stop if truncated (via GET_U_1/longjmp) or after n bytes,
+ * whichever is first.
+ * The suffix comes from: j:longJmp, n:after N bytes.
+ */
+void
+nd_printjn(netdissect_options *ndo, const u_char *s, u_int n)
+{
+ while (n > 0) {
+ fn_print_char(ndo, GET_U_1(s));
+ n--;
+ s++;
+ }
+}
+
/*
* Print a null-padded filename (or other ASCII string), part of
* the packet buffer, filtering out non-printable characters.
* Stop if truncated (via GET_U_1/longjmp) or after n bytes or before
* the null char, whichever occurs first.
* The suffix comes from: j:longJmp, n:after N bytes, p:null-Padded.
*/
void
nd_printjnp(netdissect_options *ndo, const u_char *s, u_int n)
{
u_char c;
while (n > 0) {
c = GET_U_1(s);
if (c == '\0')
break;
fn_print_char(ndo, c);
n--;
s++;
}
}
/*
* Print the timestamp .FRAC part (Microseconds/nanoseconds)
*/
static void
-ts_frac_print(netdissect_options *ndo, long usec)
+ts_frac_print(netdissect_options *ndo, const struct timeval *tv)
{
#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
switch (ndo->ndo_tstamp_precision) {
case PCAP_TSTAMP_PRECISION_MICRO:
- ND_PRINT(".%06u", (unsigned)usec);
+ ND_PRINT(".%06u", (unsigned)tv->tv_usec);
break;
case PCAP_TSTAMP_PRECISION_NANO:
- ND_PRINT(".%09u", (unsigned)usec);
+ ND_PRINT(".%09u", (unsigned)tv->tv_usec);
break;
default:
ND_PRINT(".{unknown}");
break;
}
#else
- ND_PRINT(".%06u", (unsigned)usec);
+ ND_PRINT(".%06u", (unsigned)tv->tv_usec);
#endif
}
/*
* Print the timestamp as [YY:MM:DD] HH:MM:SS.FRAC.
* if time_flag == LOCAL_TIME print local time else UTC/GMT time
* if date_flag == WITH_DATE print YY:MM:DD before HH:MM:SS.FRAC
*/
static void
-ts_date_hmsfrac_print(netdissect_options *ndo, long sec, long usec,
+ts_date_hmsfrac_print(netdissect_options *ndo, const struct timeval *tv,
enum date_flag date_flag, enum time_flag time_flag)
{
- time_t Time = sec;
struct tm *tm;
char timebuf[32];
const char *timestr;
- if ((unsigned)sec & 0x80000000) {
- ND_PRINT("[Error converting time]");
+ if (tv->tv_sec < 0) {
+ ND_PRINT("[timestamp < 1970-01-01 00:00:00 UTC]");
return;
}
if (time_flag == LOCAL_TIME)
- tm = localtime(&Time);
+ tm = localtime(&tv->tv_sec);
else
- tm = gmtime(&Time);
+ tm = gmtime(&tv->tv_sec);
if (date_flag == WITH_DATE) {
timestr = nd_format_time(timebuf, sizeof(timebuf),
"%Y-%m-%d %H:%M:%S", tm);
} else {
timestr = nd_format_time(timebuf, sizeof(timebuf),
"%H:%M:%S", tm);
}
ND_PRINT("%s", timestr);
- ts_frac_print(ndo, usec);
+ ts_frac_print(ndo, tv);
}
/*
* Print the timestamp - Unix timeval style, as SECS.FRAC.
*/
static void
-ts_unix_print(netdissect_options *ndo, long sec, long usec)
+ts_unix_print(netdissect_options *ndo, const struct timeval *tv)
{
- if ((unsigned)sec & 0x80000000) {
- ND_PRINT("[Error converting time]");
+ if (tv->tv_sec < 0) {
+ ND_PRINT("[timestamp < 1970-01-01 00:00:00 UTC]");
return;
}
- ND_PRINT("%u", (unsigned)sec);
- ts_frac_print(ndo, usec);
+ ND_PRINT("%u", (unsigned)tv->tv_sec);
+ ts_frac_print(ndo, tv);
}
/*
* Print the timestamp
*/
void
ts_print(netdissect_options *ndo,
const struct timeval *tvp)
{
static struct timeval tv_ref;
struct timeval tv_result;
int negative_offset;
int nano_prec;
switch (ndo->ndo_tflag) {
case 0: /* Default */
- ts_date_hmsfrac_print(ndo, tvp->tv_sec, tvp->tv_usec,
- WITHOUT_DATE, LOCAL_TIME);
+ ts_date_hmsfrac_print(ndo, tvp, WITHOUT_DATE, LOCAL_TIME);
ND_PRINT(" ");
break;
case 1: /* No time stamp */
break;
case 2: /* Unix timeval style */
- ts_unix_print(ndo, tvp->tv_sec, tvp->tv_usec);
+ ts_unix_print(ndo, tvp);
ND_PRINT(" ");
break;
case 3: /* Microseconds/nanoseconds since previous packet */
case 5: /* Microseconds/nanoseconds since first packet */
#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
switch (ndo->ndo_tstamp_precision) {
case PCAP_TSTAMP_PRECISION_MICRO:
nano_prec = 0;
break;
case PCAP_TSTAMP_PRECISION_NANO:
nano_prec = 1;
break;
default:
nano_prec = 0;
break;
}
#else
nano_prec = 0;
#endif
if (!(netdissect_timevalisset(&tv_ref)))
tv_ref = *tvp; /* set timestamp for first packet */
negative_offset = netdissect_timevalcmp(tvp, &tv_ref, <);
if (negative_offset)
netdissect_timevalsub(&tv_ref, tvp, &tv_result, nano_prec);
else
netdissect_timevalsub(tvp, &tv_ref, &tv_result, nano_prec);
ND_PRINT((negative_offset ? "-" : " "));
- ts_date_hmsfrac_print(ndo, tv_result.tv_sec, tv_result.tv_usec,
- WITHOUT_DATE, UTC_TIME);
+ ts_date_hmsfrac_print(ndo, &tv_result, WITHOUT_DATE, UTC_TIME);
ND_PRINT(" ");
if (ndo->ndo_tflag == 3)
tv_ref = *tvp; /* set timestamp for previous packet */
break;
case 4: /* Date + Default */
- ts_date_hmsfrac_print(ndo, tvp->tv_sec, tvp->tv_usec,
- WITH_DATE, LOCAL_TIME);
+ ts_date_hmsfrac_print(ndo, tvp, WITH_DATE, LOCAL_TIME);
ND_PRINT(" ");
break;
}
}
/*
* Print an unsigned 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
unsigned_relts_print(netdissect_options *ndo,
uint32_t secs)
{
static const char *lengths[] = {"y", "w", "d", "h", "m", "s"};
static const u_int seconds[] = {31536000, 604800, 86400, 3600, 60, 1};
const char **l = lengths;
const u_int *s = seconds;
if (secs == 0) {
ND_PRINT("0s");
return;
}
while (secs > 0) {
if (secs >= *s) {
ND_PRINT("%u%s", secs / *s, *l);
secs -= (secs / *s) * *s;
}
s++;
l++;
}
}
/*
* Print a signed 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
signed_relts_print(netdissect_options *ndo,
int32_t secs)
{
if (secs < 0) {
ND_PRINT("-");
if (secs == INT32_MIN) {
/*
* -2^31; you can't fit its absolute value into
* a 32-bit signed integer.
*
* Just directly pass said absolute value to
* unsigned_relts_print() directly.
*
* (XXX - does ISO C guarantee that -(-2^n),
* when calculated and cast to an n-bit unsigned
* integer type, will have the value 2^n?)
*/
unsigned_relts_print(ndo, 2147483648U);
} else {
/*
* We now know -secs will fit into an int32_t;
* negate it and pass that to unsigned_relts_print().
*/
unsigned_relts_print(ndo, -secs);
}
return;
}
unsigned_relts_print(ndo, secs);
}
/*
* Format a struct tm with strftime().
* If the pointer to the struct tm is null, that means that the
* routine to convert a time_t to a struct tm failed; the localtime()
* and gmtime() in the Microsoft Visual Studio C library will fail,
* returning null, if the value is before the UNIX Epoch.
*/
const char *
nd_format_time(char *buf, size_t bufsize, const char *format,
const struct tm *timeptr)
{
if (timeptr != NULL) {
if (strftime(buf, bufsize, format, timeptr) != 0)
return (buf);
else
return ("[nd_format_time() buffer is too small]");
} else
return ("[localtime() or gmtime() couldn't convert the date and time]");
}
/* Print the truncated string */
void nd_print_trunc(netdissect_options *ndo)
{
ND_PRINT(" [|%s]", ndo->ndo_protocol);
}
/* Print the protocol name */
void nd_print_protocol(netdissect_options *ndo)
{
ND_PRINT("%s", ndo->ndo_protocol);
}
/* Print the protocol name in caps (uppercases) */
void nd_print_protocol_caps(netdissect_options *ndo)
{
const char *p;
for (p = ndo->ndo_protocol; *p != '\0'; p++)
ND_PRINT("%c", ND_ASCII_TOUPPER(*p));
}
/* Print the invalid string */
void nd_print_invalid(netdissect_options *ndo)
{
ND_PRINT(" (invalid)");
}
/*
* 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, u_int len)
{
u_int len_to_print;
len_to_print = len;
if (!ND_TTEST_LEN(cp, 0)) {
ND_PRINT("%sDissector error: print_unknown_data called with pointer past end of packet",
ident);
return(0);
}
if (ND_BYTES_AVAILABLE_AFTER(cp) < len_to_print)
len_to_print = ND_BYTES_AVAILABLE_AFTER(cp);
hex_print(ndo, ident, cp, len_to_print);
return(1); /* everything is ok */
}
/*
* Convert a token value to a string; use "fmt" if not found.
*/
static const char *
tok2strbuf(const struct tok *lp, const char *fmt,
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.
* Uses tok2strbuf() on one of four local static buffers of size TOKBUFSIZE
* in round-robin fashion.
*/
const char *
tok2str(const struct tok *lp, const char *fmt,
u_int v)
{
static char buf[4][TOKBUFSIZE];
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 separated
* if the s field is positive.
*
* A token matches iff it has one or more bits set and every bit that is set
* in the token is set in v. Consequently, a 0 token never matches.
*/
static char *
bittok2str_internal(const struct tok *lp, const char *fmt,
u_int v, const char *sep)
{
static char buf[1024+1]; /* our string buffer */
char *bufp = buf;
size_t space_left = sizeof(buf), string_size;
const char * sepstr = "";
while (lp != NULL && lp->s != NULL) {
if (lp->v && (v & lp->v) == lp->v) {
/* ok we have found something */
if (space_left <= 1)
return (buf); /* only enough room left for NUL, if that */
string_size = strlcpy(bufp, sepstr, space_left);
if (string_size >= space_left)
return (buf); /* we ran out of room */
bufp += string_size;
space_left -= string_size;
if (space_left <= 1)
return (buf); /* only enough room left for NUL, if that */
string_size = strlcpy(bufp, lp->s, space_left);
if (string_size >= space_left)
return (buf); /* we ran out of room */
bufp += string_size;
space_left -= string_size;
sepstr = sep;
}
lp++;
}
if (bufp == buf)
/* bummer - lets print the "unknown" message as advised in the fmt string if we got one */
(void)snprintf(buf, sizeof(buf), fmt == NULL ? "#%08x" : 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 separated.
*/
char *
bittok2str_nosep(const struct tok *lp, const char *fmt,
u_int v)
{
return (bittok2str_internal(lp, fmt, v, ""));
}
/*
* Convert a bit token value to a string; use "fmt" if not found.
* this is useful for parsing bitfields, the output strings are comma separated.
*/
char *
bittok2str(const struct tok *lp, const char *fmt,
u_int v)
{
return (bittok2str_internal(lp, fmt, v, ", "));
}
/*
* Convert a value to a string using an array; the macro
* tok2strary() in <netdissect.h> is the public interface to
* this function and ensures that the second argument is
* correct for bounds-checking.
*/
const char *
tok2strary_internal(const char **lp, int n, const char *fmt,
int v)
{
static char buf[TOKBUFSIZE];
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);
}
const struct tok *
uint2tokary_internal(const struct uint_tokary dict[], const size_t size,
const u_int val)
{
size_t i;
/* Try a direct lookup before the full scan. */
if (val < size && dict[val].uintval == val)
return dict[val].tokary; /* OK if NULL */
for (i = 0; i < size; i++)
if (dict[i].uintval == val)
return dict[i].tokary; /* OK if NULL */
return NULL;
}
/*
* 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)
{
const 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);
}
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);
}
/*
* 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;
u_char c;
for (; idx < len; idx++) {
if (!ND_TTEST_1(pptr + idx)) {
/* ran past end of captured data */
return (0);
}
c = GET_U_1(pptr + idx);
if (!ND_ISASCII(c)) {
/* not an ASCII character */
return (0);
}
if (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
/* end of token */
break;
}
if (!ND_ASCII_ISPRINT(c)) {
/* 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] = c;
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_1(pptr + idx)) {
/* ran past end of captured data */
break;
}
c = GET_U_1(pptr + idx);
if (c == '\r' || c == '\n') {
/* end of line */
break;
}
if (!ND_ASCII_ISPRINT(c)) {
/* not a printable ASCII character */
break;
}
if (c != ' ' && c != '\t' && c != '\r' && c != '\n') {
/* 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 *prefix,
const u_char *pptr, u_int idx, u_int len)
{
u_int startidx;
u_int linelen;
u_char c;
startidx = idx;
while (idx < len) {
c = GET_U_1(pptr + idx);
if (c == '\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 (c == '\r') {
/* CR - any LF? */
if ((idx+1) >= len) {
/* not in this packet */
return (0);
}
if (GET_U_1(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 (!ND_ASCII_ISPRINT(c) && c != '\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.
+ * in the buffer.
*/
linelen = idx - startidx;
ND_PRINT("%s%.*s", prefix, (int)linelen, pptr + startidx);
- nd_print_trunc(ndo);
return (0);
print:
ND_PRINT("%s%.*s", prefix, (int)linelen, pptr + startidx);
return (idx);
}
/* Assign needed before calling txtproto_print(): ndo->ndo_protocol = "proto" */
void
txtproto_print(netdissect_options *ndo, const u_char *pptr, u_int len,
const char **cmds, u_int flags)
{
u_int idx, eol;
u_char token[MAX_TOKEN+1];
const char *cmd;
int print_this = 0;
if (cmds != NULL) {
/*
* This protocol has more than just request and
* response lines; see whether this looks like a
* request or response and, if so, print it and,
* in verbose mode, print everything after it.
*
* This is for HTTP-like protocols, where we
* want to print requests and responses, but
* don't want to print continuations of request
* or response bodies in packets that don't
* contain the request or response line.
*/
idx = fetch_token(ndo, pptr, 0, len, token, sizeof(token));
if (idx != 0) {
/* Is this a valid request name? */
while ((cmd = *cmds++) != NULL) {
if (ascii_strcasecmp((const char *)token, cmd) == 0) {
/* Yes. */
print_this = 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 (ND_ASCII_ISDIGIT(token[0]) && ND_ASCII_ISDIGIT(token[1]) &&
ND_ASCII_ISDIGIT(token[2]) && token[3] == '\0') {
/* Yes. */
print_this = 1;
}
}
}
} else {
/*
* Either:
*
* 1) 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.
*
* or
*
* 2) This protocol is just text, so that we should
* always, at minimum, print the first line and,
* in verbose mode, print all lines.
*/
print_this = 1;
}
nd_print_protocol_caps(ndo);
if (print_this) {
/*
* In non-verbose mode, just print the protocol, followed
* by the first line.
*
* 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(", length: %u", len);
for (idx = 0;
idx < len && (eol = print_txt_line(ndo, "\n\t", pptr, idx, len)) != 0;
idx = eol)
;
} else {
/*
* Just print the first text line.
*/
print_txt_line(ndo, ": ", pptr, 0, len);
}
}
}
#if (defined(__i386__) || defined(_M_IX86) || defined(__X86__) || defined(__x86_64__) || defined(_M_X64)) || \
(defined(__arm__) || defined(_M_ARM) || defined(__aarch64__)) || \
(defined(__m68k__) && (!defined(__mc68000__) && !defined(__mc68010__))) || \
(defined(__ppc__) || defined(__ppc64__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PPC64)) || \
(defined(__s390__) || defined(__s390x__) || defined(__zarch__)) || \
defined(__vax__)
/*
* The processor natively handles unaligned loads, so just use memcpy()
* and memcmp(), to enable those optimizations.
*
* XXX - are those all the x86 tests we need?
* XXX - do we need to worry about ARMv1 through ARMv5, which didn't
* support unaligned loads, and, if so, do we need to worry about all
* of them, or just some of them, e.g. ARMv5?
* XXX - are those the only 68k tests we need not to generated
* unaligned accesses if the target is the 68000 or 68010?
* XXX - are there any tests we don't need, because some definitions are for
* compilers that also predefine the GCC symbols?
* XXX - do we need to test for both 32-bit and 64-bit versions of those
* architectures in all cases?
*/
#else
/*
* The processor doesn't natively handle unaligned loads,
* and the compiler might "helpfully" optimize memcpy()
* and memcmp(), when handed pointers that would normally
* be properly aligned, into sequences that assume proper
* alignment.
*
* Do copies and compares of possibly-unaligned data by
* calling routines that wrap memcpy() and memcmp(), to
* prevent that 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/usr.sbin/tcpdump/tcpdump/config.h b/usr.sbin/tcpdump/tcpdump/config.h
index 8fc7d8c2523f..5e343d5ed0c3 100644
--- a/usr.sbin/tcpdump/tcpdump/config.h
+++ b/usr.sbin/tcpdump/tcpdump/config.h
@@ -1,295 +1,295 @@
/* 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.ac by autoheader. */
/* Define to 1 if arpa/inet.h declares `ether_ntohost' */
/* #undef ARPA_INET_H_DECLARES_ETHER_NTOHOST */
/* define if you want to build the possibly-buggy SMB printer */
#define ENABLE_SMB 1
/* Define to 1 if you have the `bpf_dump' function. */
#define HAVE_BPF_DUMP 1
/* capsicum support available */
#define HAVE_CAPSICUM 1
/* 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 <cap-ng.h> header file. */
/* #undef HAVE_CAP_NG_H */
/* Define to 1 if you have the `cap_rights_limit' function. */
#define HAVE_CAP_RIGHTS_LIMIT 1
/* Casper library support available */
/* See Makefile */
/* #undef HAVE_CASPER */
/* Define to 1 if you have the declaration of `ether_ntohost' */
/* #undef HAVE_DECL_ETHER_NTOHOST */
/* 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 `EVP_DecryptInit_ex' function. */
#define HAVE_EVP_DECRYPTINIT_EX 1
/* Define to 1 if you have the <fcntl.h> 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 `getservent' function. */
#define HAVE_GETSERVENT 1
/* Define to 1 if you have the <inttypes.h> 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 <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the <net/if.h> header file. */
#define HAVE_NET_IF_H 1
/* Define to 1 if printf(3) does not support the z length modifier. */
/* #undef HAVE_NO_PRINTF_Z */
/* Define to 1 if you have the `openat' function. */
#define HAVE_OPENAT 1
/* Define to 1 if you have the <openssl/evp.h> header file. */
#define HAVE_OPENSSL_EVP_H 1
/* define if the OS provides AF_INET6 and struct in6_addr */
#define HAVE_OS_IPV6_SUPPORT 1
/* 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 `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 to 1 if you have the `pcap_dump_ftell' function. */
#define HAVE_PCAP_DUMP_FTELL 1
/* Define to 1 if you have the `pcap_dump_ftell64' function. */
#define HAVE_PCAP_DUMP_FTELL64 1
/* Define to 1 if you have the `pcap_findalldevs' function. */
#define HAVE_PCAP_FINDALLDEVS 1
/* Define to 1 if you have the `pcap_findalldevs_ex' function. */
/* #undef HAVE_PCAP_FINDALLDEVS_EX */
/* 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 `pcap_open' function. */
/* #undef HAVE_PCAP_OPEN */
/* Define to 1 if you have the <pcap/pcap-inttypes.h> header file. */
#define HAVE_PCAP_PCAP_INTTYPES_H 1
/* 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 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 <rpc/rpcent.h> header file. */
#define HAVE_RPC_RPCENT_H 1
/* Define to 1 if you have the <rpc/rpc.h> 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 <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> 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 <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> 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 <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> 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 <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to 1 if you have the `vfork' function. */
#define HAVE_VFORK 1
/* define if libpcap has yydebug */
/* #undef HAVE_YYDEBUG */
/* 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' */
/* #undef NETINET_IF_ETHER_H_DECLARES_ETHER_NTOHOST */
/* Define to 1 if net/ethernet.h declares `ether_ntohost' */
/* #undef NET_ETHERNET_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 "tcpdump"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "tcpdump 4.99.4"
+#define PACKAGE_STRING "tcpdump 4.99.5"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "tcpdump"
/* Define to the home page for this package. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
-#define PACKAGE_VERSION "4.99.4"
+#define PACKAGE_VERSION "4.99.5"
/* The size of `void *', as computed by sizeof. */
/* #undef SIZEOF_VOID_P */
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Define to 1 if sys/ethernet.h declares `ether_ntohost' */
/* #undef SYS_ETHERNET_H_DECLARES_ETHER_NTOHOST */
/* define if you have ether_ntohost() and it works */
/* #undef USE_ETHER_NTOHOST */
/* 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 */
/* define on AIX to get certain functions */
/* #undef _SUN */
/* 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 `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 wide enough to hold a
pointer, if such a type exists, and if the system does not define it. */
/* #undef uintptr_t */

File Metadata

Mime Type
application/octet-stream
Expires
Fri, Oct 24, 7:36 PM (1 d, 23 h)
Storage Engine
chunks
Storage Format
Chunks
Storage Handle
9Mr9nvk9EnnC
Default Alt Text
(4 MB)

Event Timeline