Index: head/contrib/tcpdump/bootp.h =================================================================== --- head/contrib/tcpdump/bootp.h (revision 285274) +++ head/contrib/tcpdump/bootp.h (nonexistent) @@ -1,230 +0,0 @@ -/* - * 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 { - uint8_t bp_op; /* packet opcode type */ - uint8_t bp_htype; /* hardware addr type */ - uint8_t bp_hlen; /* hardware addr length */ - uint8_t bp_hops; /* gateway hops */ - uint32_t bp_xid; /* transaction ID */ - uint16_t bp_secs; /* seconds since boot began */ - uint16_t bp_flags; /* flags - see bootp_flag_values[] - in print-bootp.c */ - struct in_addr bp_ciaddr; /* client IP address */ - struct in_addr bp_yiaddr; /* 'your' IP address */ - struct in_addr bp_siaddr; /* server IP address */ - struct in_addr bp_giaddr; /* gateway IP address */ - uint8_t bp_chaddr[16]; /* client hardware address */ - uint8_t bp_sname[64]; /* server host name */ - uint8_t bp_file[128]; /* boot file name */ - uint8_t bp_vend[64]; /* vendor-specific area */ -} UNALIGNED; - -/* - * UDP port numbers, server and client. - */ -#define IPPORT_BOOTPS 67 -#define IPPORT_BOOTPC 68 - -#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_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 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) -/* ftp://ftp.isi.edu/.../assignments/bootp-dhcp-extensions */ -#define TAG_USER_CLASS ((uint8_t) 77) -#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_AGENT_MASK ((uint8_t) 84) -#define TAG_TZ_STRING ((uint8_t) 88) -#define TAG_FQDN_OPTION ((uint8_t) 89) -#define TAG_AUTH ((uint8_t) 90) -#define TAG_VINES_SERVERS ((uint8_t) 91) -#define TAG_SERVER_RANK ((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) -#define TAG_6OVER4 ((uint8_t) 96) -#define TAG_PRINTER_NAME ((uint8_t) 100) -#define TAG_MDHCP_SERVER ((uint8_t) 101) -#define TAG_IPX_COMPAT ((uint8_t) 110) -#define TAG_NETINFO_PARENT ((uint8_t) 112) -#define TAG_NETINFO_PARENT_TAG ((uint8_t) 113) -#define TAG_URL ((uint8_t) 114) -#define TAG_FAILOVER ((uint8_t) 115) -#define TAG_EXTENDED_REQUEST ((uint8_t) 126) -#define TAG_EXTENDED_OPTION ((uint8_t) 127) - - -/* 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 - - -/* - * "vendor" data permitted for CMU bootp clients. - */ - -struct cmu_vend { - uint8_t v_magic[4]; /* magic number */ - uint32_t v_flags; /* flags/opcodes, etc. */ - struct in_addr v_smask; /* Subnet mask */ - struct in_addr v_dgate; /* Default gateway */ - struct in_addr v_dns1, v_dns2; /* Domain name servers */ - struct in_addr v_ins1, v_ins2; /* IEN-116 name servers */ - struct in_addr v_ts1, v_ts2; /* Time servers */ - uint8_t v_unused[24]; /* currently unused */ -} UNALIGNED; - - -/* 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 Property changes on: head/contrib/tcpdump/bootp.h ___________________________________________________________________ Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Index: head/contrib/tcpdump/CHANGES =================================================================== --- head/contrib/tcpdump/CHANGES (revision 285274) +++ head/contrib/tcpdump/CHANGES (revision 285275) @@ -1,1105 +1,1136 @@ +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 accomodate 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 - 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 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 typoes, 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 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 dependancy. 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 http://www.ietf.org/internet-drafts/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 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 compliation 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 http://www.rapid7.com/advisories/R7-0017.html 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 . IPv6 mobility updates from Kazushi Sugyo 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 malformed isakmp packets. (reported by iDefense; already fixed in CVS) Fixed infinite loop when parsing malformed BGP packets. Fixed buffer overflow with certain malformed 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 see http://www.tcpdump.org/cvs-log/2002-01-21.10:16:48.html for commit log. 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 SMB printing has much improved bounds checks OUI 0x0000f8 decoded as encapsulated ethernet for Cisco-custom bridging Zephyr support, from Nickolai Zeldovich . Solaris - devices with digits in them. Stefan Hudson IPX socket 0x85be is for Cisco EIGRP over IPX. Improvements to fragmented ESP handling. SCTP support from Armando L. Caro Jr. 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 . 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 . now we are -Wstrict-prototype clean. NetBSD DLT_PPP_ETHER; adapted from Martin Husemann . PPPoE dissector cleaned up. Support for LocalTalk hardware, from Uns Lider . 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 ARCNet support, from NetBSD. HSRP dissector, from Julian Cowley . 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 . PPTP support, from Motonori Shindo . IS-IS over PPP support, from Hannes Gredler . CNFP support for IPv6,format. Harry Raaymakers . 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 dependant 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 - 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 - 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 - bring in code at /afs/transarc.com/public/afs-contrib/tools/tcpdump for parsing AFS3 packets Andrew Tridgell - SMB printing code Love - print-rx.c: add code for printing MakeDir and StoreStatus. Also change date format to the right one. Michael C. Richardson - 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 suport 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 publically 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 . 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. Index: head/contrib/tcpdump/CREDITS =================================================================== --- head/contrib/tcpdump/CREDITS (revision 285274) +++ head/contrib/tcpdump/CREDITS (revision 285275) @@ -1,227 +1,229 @@ This file lists people who have contributed to tcpdump: The current maintainers: Bill Fenner - Denis Ovsienko + Denis Ovsienko Fulvio Risso Guy Harris Hannes Gredler Michael Richardson Francois-Xavier Le Bail Additional people who have contributed patches: Aaron Campbell A Costa Albert Chin Alexandra Kossovsky Alfredo Andres Ananth Suryanarayana Andrea Bittau Andrew Brown Andrew Church Andrew Hintz Andrew Nording Andrew Tridgell Andy Heffernan Anton Bernal Arkadiusz Miskiewicz Armando L. Caro Jr. Arnaldo Carvalho de Melo Atsushi Onoe Baptiste Jonglez Ben Byer Ben Smithurst Bert Vermeulen Bjoern A. Zeeb Bram Brent L. Bates Brian Ginsbach Bruce M. Simpson Carles Kishimoto Bisbe Charles M. Hannum Charlie Lenahan Chris Cogdon Chris G. Demetriou Chris Jepeway Chris Larson Christian Sievers Christophe Rhodes Cliff Frey Craig Rodrigues Crist J. Clark Daniel Hagerty Darren Reed David Binderman David Horn David Smith David Young Dmitrij Tejblum Dmitry Eremin-Solenikov Don Ebright Eddie Kohler Elmar Kirchner Fang Wang Florent Drouin Florian Forster fra Francesco Fondelli Francisco Matias Cuenca-Acuna Francis Dupont Frank Volf Fulvio Risso George Bakos Gerald Combs Gerrit Renker Gert Doering Gilbert Ramirez Jr. Gisle Vanem Greg Minshall Grégoire Henry Gregory Detal Greg Stark Hank Leininger Hannes Viertel Harry Raaymakers Heinz-Ado Arnolds Hendrik Scholz + Herwin Weststrate Ian McDonald Ilpo Järvinen Jacek Tobiasz Jakob Schlyter Jamal Hadi Salim Jan Oravec Jason R. Thorpe Jefferson Ogata Jeffrey Hutzelman Jesper Peterson + Jesse Gross Jim Hutchins João Medeiros Joerg Mayer Jonathan Heusser Jorge Boncompte [DTI2] Jørgen Thomsen Julian Cowley Juliusz Chroboczek Kaarthik Sivakumar Kaladhar Musunuru Karl Norby Kazushi Sugyo Kelly Carmichael Ken Hornstein Kenichi Maehashi Kevin Steves Klaus Klein Kris Kennaway Krzysztof Halasa Larry Lile Lennert Buytenhek Loganaden Velvindron Longinus00 Loris Degioanni Love Hörnquist-Åstrand Lucas C. Villa Real Luis MartinGarcia Maciej W. Rozycki Manu Pathak Marc Abramowitz Marc A. Lehmann Marc Binderberger Mark Ellzey Thomas Marko Kiiskila Markus Schöpflin Marshall Rose Martin Husemann Max Laier Michael A. Meffie III Michael Madore Michael Riepe Michael Shalayeff Michael Shields Michael T. Stolarchuk Michal Sekletar Michele "mydecay" Marchetto Mike Frysinger Minto Jeyananth Monroe Williams Motonori Shindo Nathaniel Couper-Noles Nathan J. Williams Neil T. Spring Nickolai Zeldovich Nicolas Ferrero Niels Provos Noritoshi Demizu Olaf Kirch Ola Martin Lykkja Oleksij Rempel Onno van der Linden Paolo Abeni Pascal Hennequin Pasvorn Boonmark Paul Ferrell Paul Mundt Paul S. Traina Pavlin Radoslavov Pawel Worach Pekka Savola Petar Alilovic Peter Fales Peter Jeremy Peter Volkov Phil Wood Rafal Maszkowski Randy Sofia Raphael Raimbault Rick Cheng Rick Jones Rick Watson Rob Braun Robert Edmonds Roderick Schertler Romain Francoise Ruben Kerkhof Sagun Shakya Sami Farin Scott Mcmillan Scott Rose Sebastian Krahmer Sebastien Raveau Sebastien Vincent Sepherosa Ziehau Seth Webster Shinsuke Suzuki Simon Ruderich Steinar Haug Stephane Bortzmeyer Swaminathan Chandrasekaran Swaathi Vetrivel Takashi Yamamoto Tatuya Jinmei Terry Kennedy Thomas Jacob Timo Koskiahde Tony Li Toshihiro Kanda Udayakumar Uns Lider Victor Oppleman Vyacheslav Trushkin Weesan Lee Wesley Griffin Wesley Shields Wilbert de Graaf Will Drewry William J. Hulley Wim Torfs Yen Yen Lim Yoshifumi Nishida The original LBL crew: Steve McCanne Craig Leres Van Jacobson Past maintainers: Jun-ichiro itojun Hagino Also see: http://www.wide.ad.jp/itojun-award/ Index: head/contrib/tcpdump/INSTALL.txt =================================================================== --- head/contrib/tcpdump/INSTALL.txt (revision 285274) +++ head/contrib/tcpdump/INSTALL.txt (revision 285275) @@ -1,214 +1,213 @@ 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 libpcap; see the README file in this directory for the ftp location. You will need an ANSI C compiler to build tcpdump. The configure script will abort if your compiler is not ANSI compliant. If this happens, use the generally available GNU C compiler (GCC). 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 determine your system attributes and generate an appropriate Makefile from Makefile.in. Now build tcpdump by running "make". If everything builds ok, 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 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. Remember to remove or rename the installed binary when upgrading. If your system is not one which we have tested tcpdump on, you may have to modify the configure script and Makefile.in. Please send us patches for any modifications you need to make. Please see "PLATFORMS" for notes about tested platforms. FILES ----- CHANGES - description of differences between releases CREDITS - people that have helped tcpdump along INSTALL.txt - this file LICENSE - the license under which tcpdump is distributed Makefile.in - compilation rules (input to the configure script) README - description of distribution Readme.Win32 - notes on building tcpdump on Win32 systems (with WinPcap) VERSION - version of this release aclocal.m4 - autoconf macros addrtoname.c - address to hostname routines addrtoname.h - address to hostname definitions ah.h - IPSEC Authentication Header definitions appletalk.h - AppleTalk definitions atime.awk - TCP ack awk script atm.h - ATM traffic type definitions atmuni31.h - ATM Q.2931 definitions -bootp.h - BOOTP definitions 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.in - configure script source ether.h - Ethernet definitions ethertype.h - Ethernet type value definitions extract.h - alignment definitions gmpls.c - GMPLS definitions gmpls.h - GMPLS declarations gmt2local.c - time conversion routines gmt2local.h - time conversion prototypes 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 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_dump_ftell.c - pcap_dump_ftell() implementation, in case libpcap doesn't have it pcap-missing.h - declarations of functions possibly missing from libpcap ppp.h - Point to Point Protocol definitions print-802_11.c - IEEE 802.11 printer routines print-ap1394.c - Apple IP-over-IEEE 1394 printer routines print-ah.c - IPSEC Authentication Header printer routines print-aodv.c - AODV printer routines print-arcnet.c - ARCNET printer routines print-arp.c - Address Resolution Protocol printer routines print-ascii.c - ASCII packet dump routines print-atalk.c - AppleTalk printer routines print-atm.c - ATM printer routines print-beep.c - BEEP printer routines print-bgp.c - Border Gateway Protocol printer routines print-bootp.c - BOOTP and IPv4 DHCP printer routines print-bt.c - Bluetooth printer routines print-cdp.c - Cisco Discovery Protocol printer routines print-chdlc.c - Cisco HDLC printer routines print-cip.c - Classical-IP over ATM routines print-cnfp.c - Cisco NetFlow printer routines print-dccp.c - DCCP printer routines print-decnet.c - DECnet printer routines print-dhcp6.c - IPv6 DHCP printer routines print-domain.c - Domain Name System printer routines print-dvmrp.c - Distance Vector Multicast Routing Protocol printer routines print-eap.c - EAP printer routines print-enc.c - OpenBSD IPsec encapsulation BPF layer printer routines print-egp.c - External Gateway Protocol printer routines print-esp.c - IPSEC Encapsulating Security Payload printer routines print-ether.c - Ethernet printer routines print-fddi.c - Fiber Distributed Data Interface printer routines print-fr.c - Frame Relay printer routines print-frag6.c - IPv6 fragmentation header printer routines print-gre.c - Generic Routing Encapsulation printer routines print-hsrp.c - Cisco Hot Standby Router Protocol printer routines print-icmp.c - Internet Control Message Protocol printer routines print-icmp6.c - IPv6 Internet Control Message Protocol printer routines print-igmp.c - Internet Group Management Protocol printer routines print-igrp.c - Interior Gateway Routing Protocol printer routines print-ip.c - IP printer routines print-ip6.c - IPv6 printer routines print-ip6opts.c - IPv6 header option printer routines print-ipcomp.c - IP Payload Compression Protocol printer routines print-ipx.c - IPX printer routines print-isakmp.c - Internet Security Association and Key Management Protocol print-isoclns.c - ISO CLNS, ESIS, and ISIS printer routines print-krb.c - Kerberos printer routines print-l2tp.c - Layer Two Tunneling Protocol printer routines print-lane.c - ATM LANE printer routines print-llc.c - IEEE 802.2 LLC printer routines print-lspping.c - LSPPING printer routines print-lwres.c - Lightweight Resolver protocol printer routines print-mobile.c - IPv4 mobility printer routines print-mobility.c - IPv6 mobility printer routines print-mpls.c - Multi-Protocol Label Switching printer routines print-msdp.c - Multicast Source Discovery Protocol printer routines print-nfs.c - Network File System printer routines print-ntp.c - Network Time Protocol printer routines print-null.c - BSD loopback device printer routines print-ospf.c - Open Shortest Path First printer routines print-ospf6.c - IPv6 Open Shortest Path First printer routines print-pflog.c - OpenBSD packet filter log file printer routines print-pgm.c - Pragmatic General Multicast printer routines print-pim.c - Protocol Independent Multicast printer routines print-ppp.c - Point to Point Protocol printer routines print-pppoe.c - PPP-over-Ethernet printer routines print-pptp.c - Point-to-Point Tunnelling Protocol printer routines print-radius.c - Radius protocol printer routines print-raw.c - Raw IP printer routines print-rip.c - Routing Information Protocol printer routines print-ripng.c - IPv6 Routing Information Protocol printer routines print-rrcp.c - Realtek Remote Control Protocol routines print-rsvp.c - Resource reSerVation Protocol (RSVP) printer routines print-rt6.c - IPv6 routing header printer routines print-rx.c - AFS RX printer routines print-sctp.c - Stream Control Transmission Protocol printer routines print-sip.c - SIP printer routines print-sl.c - Compressed Serial Line Internet Protocol printer routines print-sll.c - Linux "cooked" capture printer routines print-slow.c - IEEE "slow protocol" (802.3ad) printer routines print-smb.c - SMB/CIFS printer routines print-snmp.c - Simple Network Management Protocol printer routines print-stp.c - IEEE 802.1d spanning tree protocol printer routines print-sunatm.c - SunATM DLPI capture printer routines print-sunrpc.c - Sun Remote Procedure Call printer routines print-symantec.c - Symantec Enterprise Firewall printer routines print-tcp.c - TCP printer routines print-telnet.c - Telnet option printer routines print-tftp.c - Trivial File Transfer Protocol printer routines print-timed.c - BSD time daemon protocol printer routines print-token.c - Token Ring printer routines print-udp.c - UDP printer routines print-usb.c - USB printer routines print-vjc.c - PPP Van Jacobson compression (RFC1144) printer routines print-vrrp.c - Virtual Router Redundancy Protocol print-wb.c - White Board printer routines print-zephyr.c - Zephyr printer routines 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 setsignal.c - OS-independent signal routines setsignal.h - OS-independent signal prototypes 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 strcasecmp.c - missing routine tcp.h - TCP definitions tcpdump.1 - manual entry tcpdump.c - main program udp.h - UDP definitions util.c - utility routines vfprintf.c - emulation routine win32 - headers and routines for building on Win32 systems Index: head/contrib/tcpdump/Makefile.in =================================================================== --- head/contrib/tcpdump/Makefile.in (revision 285274) +++ head/contrib/tcpdump/Makefile.in (revision 285275) @@ -1,451 +1,454 @@ # 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 sbindir = @sbindir@ # Pathname of directory to install the man page mandir = @mandir@ # VPATH srcdir = @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 = setsignal.c tcpdump.c LIBNETDISSECT_SRC=\ addrtoname.c \ af.c \ checksum.c \ cpack.c \ gmpls.c \ gmt2local.c \ in_cksum.c \ ipproto.c \ l2vpn.c \ machdep.c \ nlpid.c \ oui.c \ parsenfsfh.c \ print-802_11.c \ print-802_15_4.c \ print-ah.c \ print-ahcp.c \ print-aodv.c \ print-aoe.c \ print-ap1394.c \ print-arcnet.c \ print-arp.c \ print-ascii.c \ print-atalk.c \ print-atm.c \ print-beep.c \ print-bfd.c \ print-bgp.c \ print-bootp.c \ print-bt.c \ print-calm-fast.c \ print-carp.c \ print-cdp.c \ print-cfm.c \ print-chdlc.c \ print-cip.c \ print-cnfp.c \ print-dccp.c \ print-decnet.c \ print-domain.c \ print-dtp.c \ print-dvmrp.c \ print-eap.c \ print-egp.c \ print-eigrp.c \ print-enc.c \ print-esp.c \ print-ether.c \ print-fddi.c \ print-forces.c \ print-fr.c \ + print-ftp.c \ + print-geneve.c \ print-geonet.c \ print-gre.c \ print-hsrp.c \ + print-http.c \ print-icmp.c \ print-igmp.c \ print-igrp.c \ print-ip.c \ + print-ip6.c \ print-ipcomp.c \ print-ipfc.c \ print-ipnet.c \ print-ipx.c \ print-isakmp.c \ print-isoclns.c \ print-juniper.c \ print-krb.c \ print-l2tp.c \ print-lane.c \ print-ldp.c \ print-llc.c \ print-lldp.c \ print-lmp.c \ print-loopback.c \ print-lspping.c \ print-lwapp.c \ print-lwres.c \ print-m3ua.c \ print-mobile.c \ print-mpcp.c \ print-mpls.c \ print-mptcp.c \ print-msdp.c \ print-msnlb.c \ print-nflog.c \ print-nfs.c \ print-ntp.c \ print-null.c \ print-olsr.c \ print-openflow-1.0.c \ print-openflow.c \ print-ospf.c \ print-otv.c \ print-pgm.c \ print-pim.c \ print-pktap.c \ print-ppi.c \ print-ppp.c \ print-pppoe.c \ print-pptp.c \ print-radius.c \ print-raw.c \ print-rip.c \ print-rpki-rtr.c \ print-rrcp.c \ print-rsvp.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-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-usb.c \ print-vjc.c \ print-vqp.c \ print-vrrp.c \ print-vtp.c \ print-vxlan.c \ print-wb.c \ print-zephyr.c \ print-zeromq.c \ signature.c \ util.c LOCALSRC = @LOCALSRC@ GENSRC = version.c LIBOBJS = @LIBOBJS@ LIBNETDISSECT_OBJ=$(LIBNETDISSECT_SRC:.c=.o) ${LOCALSRC:.c=.o} ${LIBOBJS} LIBNETDISSECT=libnetdissect.a SRC = $(CSRC) $(GENSRC) $(LOCALSRC) $(LIBNETDISSECT_SRC) # We would like to say "OBJ = $(SRC:.c=.o)" but Ultrix's make cannot # hack the extra indirection OBJ = $(CSRC:.c=.o) $(GENSRC:.c=.o) $(LIBNETDISSECT_OBJ) HDR = \ addrtoname.h \ af.h \ ah.h \ appletalk.h \ atm.h \ atmuni31.h \ - bootp.h \ chdlc.h \ cpack.h \ ether.h \ ethertype.h \ extract.h \ getopt_long.h \ gmpls.h \ gmt2local.h \ interface.h \ - interface.h \ ip.h \ ip6.h \ ipproto.h \ l2vpn.h \ llc.h \ machdep.h \ mib.h \ mpls.h \ nameser.h \ netdissect.h \ nfs.h \ nfsfh.h \ nlpid.h \ openflow.h \ ospf.h \ oui.h \ pcap-missing.h \ ppp.h \ rpc_auth.h \ rpc_msg.h \ rpl.h \ setsignal.h \ signature.h \ slcompress.h \ smb.h \ tcp.h \ tcpdump-stdinc.h \ udp.h TAGHDR = \ /usr/include/arpa/tftp.h \ /usr/include/net/if_arp.h \ /usr/include/net/slip.h \ /usr/include/netinet/if_ether.h \ /usr/include/netinet/in.h \ /usr/include/netinet/ip_icmp.h \ /usr/include/netinet/tcp.h \ /usr/include/netinet/udp.h \ /usr/include/protocols/routed.h TAGFILES = $(SRC) $(HDR) $(TAGHDR) CLEANFILES = $(PROG) $(OBJ) $(GENSRC) EXTRA_DIST = \ CHANGES \ CREDITS \ INSTALL.txt \ LICENSE \ Makefile.in \ Makefile-devel-adds \ README.md \ Readme.Win32 \ VERSION \ aclocal.m4 \ atime.awk \ bpf_dump.c \ config.guess \ config.h.in \ config.sub \ configure \ configure.in \ install-sh \ lbl/os-osf4.h \ lbl/os-solaris2.h \ lbl/os-sunos4.h \ lbl/os-ultrix4.h \ makemib \ missing/addrinfo.h \ missing/dlnames.c \ missing/datalinks.c \ missing/getnameinfo.c \ missing/getopt_long.c \ missing/inet_aton.c \ missing/inet_ntop.c \ missing/inet_pton.c \ missing/snprintf.c \ missing/strdup.c \ missing/strlcat.c \ missing/strlcpy.c \ missing/strsep.c \ mkdep \ packetdat.awk \ pcap_dump_ftell.c \ print-babel.c \ print-dhcp6.c \ print-frag6.c \ print-icmp6.c \ - print-ip6.c \ print-ip6opts.c \ print-mobility.c \ print-ospf6.c \ print-pflog.c \ print-ripng.c \ print-rt6.c \ print-smb.c \ send-ack.awk \ smbutil.c \ stime.awk \ strcasecmp.c \ tcpdump.1.in \ vfprintf.c \ win32/Include/w32_fzs.h \ win32/prj/GNUmakefile \ win32/prj/WinDump.dsp \ win32/prj/WinDump.dsw TEST_DIST= `find tests \( -name 'DIFF' -prune \) -o \( -name NEW -prune \) -o -type f \! -name '.*' \! -name '*~' -print` all: $(PROG) $(LIBNETDISSECT) $(PROG): $(OBJ) @V_PCAPDEP@ @rm -f $@ $(CC) $(FULL_CFLAGS) $(LDFLAGS) -o $@ $(OBJ) $(LIBS) $(LIBNETDISSECT): $(LIBNETDISSECT_OBJ) @rm -f $@ $(AR) $(ARFLAGS) $@ $(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 getnameinfo.o: $(srcdir)/missing/getnameinfo.c $(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/getnameinfo.c getopt_long.o: $(srcdir)/missing/getopt_long.c $(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/getopt_long.c inet_pton.o: $(srcdir)/missing/inet_pton.c $(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/inet_pton.c inet_ntop.o: $(srcdir)/missing/inet_ntop.c $(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/inet_ntop.c inet_aton.o: $(srcdir)/missing/inet_aton.c $(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/inet_aton.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 version.o: version.c $(CC) $(FULL_CFLAGS) -c version.c version.c: $(srcdir)/VERSION @rm -f $@ if grep GIT ${srcdir}/VERSION >/dev/null; then \ read ver <${srcdir}/VERSION; \ echo $$ver | tr -d '\012'; \ date +_%Y_%m_%d; \ else \ cat ${srcdir}/VERSION; \ fi | sed -e 's/.*/const char version[] = "&";/' > $@ install: all [ -d $(DESTDIR)$(sbindir) ] || \ (mkdir -p $(DESTDIR)$(sbindir); chmod 755 $(DESTDIR)$(sbindir)) $(INSTALL_PROGRAM) $(PROG) $(DESTDIR)$(sbindir)/$(PROG) $(INSTALL_PROGRAM) $(PROG) $(DESTDIR)$(sbindir)/$(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)$(sbindir)/$(PROG) rm -f $(DESTDIR)$(mandir)/man1/$(PROG).1 lint: $(GENSRC) lint -hbxn $(SRC) | \ grep -v 'struct/union .* never defined' | \ grep -v 'possible pointer alignment problem' clean: rm -f $(CLEANFILES) $(PROG)-`cat VERSION`.tar.gz distclean: rm -f $(CLEANFILES) Makefile config.cache config.log config.status \ config.h gnuc.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 (cd tests && ./TESTrun.sh) tags: $(TAGFILES) ctags -wtd $(TAGFILES) TAGS: $(TAGFILES) etags $(TAGFILES) releasetar: @cwd=`pwd` ; dir=`basename $$cwd` ; name=$(PROG)-`cat VERSION` ; \ mkdir $$name; \ tar cf - $(CSRC) $(HDR) $(LIBNETDISSECT_SRC) $(EXTRA_DIST) $(TEST_DIST) | (cd $$name; tar xf -); \ tar -c -z -f $$name.tar.gz $$name; \ rm -rf $$name testlist: echo $(TEST_DIST) depend: $(GENSRC) $(MKDEP) -c $(CC) -m $(DEPENDENCY_CFLAG) $(DEFS) $(INCLS) $(SRC) Index: head/contrib/tcpdump/VERSION =================================================================== --- head/contrib/tcpdump/VERSION (revision 285274) +++ head/contrib/tcpdump/VERSION (revision 285275) @@ -1 +1 @@ -4.6.2 +4.7.4 Index: head/contrib/tcpdump/addrtoname.c =================================================================== --- head/contrib/tcpdump/addrtoname.c (revision 285274) +++ head/contrib/tcpdump/addrtoname.c (revision 285275) @@ -1,1238 +1,1250 @@ /* * 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 * * $FreeBSD$ */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef HAVE_CAPSICUM #include #include #endif /* HAVE_CAPSICUM */ #include #ifdef USE_ETHER_NTOHOST #ifdef HAVE_NETINET_IF_ETHER_H struct mbuf; /* Squelch compiler warnings on some platforms for */ struct rtentry; /* declarations in */ #include /* for "struct ifnet" in "struct arpcom" on Solaris */ #include #endif /* HAVE_NETINET_IF_ETHER_H */ #ifdef NETINET_ETHER_H_DECLARES_ETHER_NTOHOST #include #endif /* NETINET_ETHER_H_DECLARES_ETHER_NTOHOST */ #if !defined(HAVE_DECL_ETHER_NTOHOST) || !HAVE_DECL_ETHER_NTOHOST #ifndef HAVE_STRUCT_ETHER_ADDR struct ether_addr { unsigned char ether_addr_octet[6]; }; #endif extern int ether_ntohost(char *, const struct ether_addr *); #endif #endif /* USE_ETHER_NTOHOST */ #include #include #include #include #include #include #include "interface.h" #include "addrtoname.h" #include "llc.h" #include "setsignal.h" #include "extract.h" #include "oui.h" #ifndef ETHER_ADDR_LEN #define ETHER_ADDR_LEN 6 #endif /* * hash tables for whatever-to-name translations * * XXX there has to be error checks against strdup(3) failure */ #define HASHNAMESIZE 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]; #if defined(INET6) && defined(WIN32) /* * fake gethostbyaddr for Win2k/XP * gethostbyaddr() returns incorrect value when AF_INET6 is passed * to 3rd argument. * * h_name in struct hostent is only valid. */ static struct hostent * win32_gethostbyaddr(const char *addr, int len, int type) { static struct hostent host; static char hostbuf[NI_MAXHOST]; char hname[NI_MAXHOST]; struct sockaddr_in6 addr6; host.h_name = hostbuf; switch (type) { case AF_INET: return gethostbyaddr(addr, len, type); break; case AF_INET6: memset(&addr6, 0, sizeof(addr6)); addr6.sin6_family = AF_INET6; memcpy(&addr6.sin6_addr, addr, len); if (getnameinfo((struct sockaddr *)&addr6, sizeof(addr6), hname, sizeof(hname), NULL, 0, 0)) { return NULL; } else { strcpy(host.h_name, hname); return &host; } break; default: return NULL; } } #define gethostbyaddr win32_gethostbyaddr #endif /* INET6 & WIN32 */ #ifdef INET6 struct h6namemem { struct in6_addr addr; char *name; struct h6namemem *nxt; }; static struct h6namemem h6nametable[HASHNAMESIZE]; #endif /* INET6 */ struct enamemem { u_short e_addr0; u_short e_addr1; u_short e_addr2; const char *e_name; u_char *e_nsap; /* used only for nsaptable[] */ #define e_bs e_nsap /* for bytestringtable */ struct enamemem *e_nxt; }; static struct enamemem enametable[HASHNAMESIZE]; static struct enamemem nsaptable[HASHNAMESIZE]; static struct enamemem bytestringtable[HASHNAMESIZE]; struct protoidmem { uint32_t p_oui; u_short p_proto; const char *p_name; struct protoidmem *p_nxt; }; static struct protoidmem protoidtable[HASHNAMESIZE]; /* * A faster replacement for inet_ntoa(). */ const char * intoa(uint32_t addr) { register char *cp; register u_int byte; register int n; static char buf[sizeof(".xxx.xxx.xxx.xxx")]; NTOHL(addr); cp = buf + sizeof(buf); *--cp = '\0'; n = 4; do { byte = addr & 0xff; *--cp = byte % 10 + '0'; byte /= 10; if (byte > 0) { *--cp = byte % 10 + '0'; byte /= 10; if (byte > 0) *--cp = byte + '0'; } *--cp = '.'; addr >>= 8; } while (--n > 0); return cp + 1; } static uint32_t f_netmask; static uint32_t f_localnet; #ifdef HAVE_CAPSICUM extern cap_channel_t *capdns; #endif /* * Return a name for the IP address pointed to by ap. This address * is assumed to be in network byte order. * * NOTE: ap is *NOT* necessarily part of the packet data (not even if * this is being called with the "ipaddr_string()" macro), so you * *CANNOT* use the TCHECK{2}/TTEST{2} macros on it. Furthermore, * even in cases where it *is* part of the packet data, the caller * would still have to check for a null return value, even if it's * just printing the return value with "%s" - not all versions of * printf print "(null)" with "%s" and a null pointer, some of them * don't check for a null pointer and crash in that case. * * The callers of this routine should, before handing this routine * a pointer to packet data, be sure that the data is present in * the packet buffer. They should probably do those checks anyway, * as other data at that layer might not be IP addresses, and it * also needs to check whether they're present in the packet buffer. */ const char * getname(netdissect_options *ndo, const u_char *ap) { register struct hostent *hp; uint32_t addr; static struct hnamemem *p; /* static for longjmp() */ memcpy(&addr, ap, sizeof(addr)); p = &hnametable[addr & (HASHNAMESIZE-1)]; for (; p->nxt; p = p->nxt) { if (p->addr == addr) return (p->name); } p->addr = addr; p->nxt = newhnamemem(); /* * Print names unless: * (1) -n was given. * (2) Address is foreign and -f was given. (If -f was not * given, f_netmask and f_localnet are 0 and the test * evaluates to true) */ if (!ndo->ndo_nflag && (addr & f_netmask) == f_localnet) { #ifdef HAVE_CAPSICUM 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 (ndo->ndo_Nflag) { /* Remove domain qualifications */ dotp = strchr(p->name, '.'); if (dotp) *dotp = '\0'; } return (p->name); } } p->name = strdup(intoa(addr)); return (p->name); } #ifdef INET6 /* * Return a name for the IP6 address pointed to by ap. This address * is assumed to be in network byte order. */ const char * getname6(netdissect_options *ndo, const u_char *ap) { register struct hostent *hp; union { struct in6_addr addr; struct for_hash_addr { char fill[14]; uint16_t d; } addra; } addr; static struct h6namemem *p; /* static for longjmp() */ register const char *cp; char ntop_buf[INET6_ADDRSTRLEN]; memcpy(&addr, ap, sizeof(addr)); p = &h6nametable[addr.addra.d & (HASHNAMESIZE-1)]; for (; p->nxt; p = p->nxt) { if (memcmp(&p->addr, &addr, sizeof(addr)) == 0) return (p->name); } p->addr = addr.addr; p->nxt = newh6namemem(); /* * Do not print names if -n was given. */ if (!ndo->ndo_nflag) { #ifdef HAVE_CAPSICUM 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 (ndo->ndo_Nflag) { /* Remove domain qualifications */ dotp = strchr(p->name, '.'); if (dotp) *dotp = '\0'; } return (p->name); } } cp = inet_ntop(AF_INET6, &addr, ntop_buf, sizeof(ntop_buf)); p->name = strdup(cp); return (p->name); } #endif /* INET6 */ static const char hex[] = "0123456789abcdef"; /* Find the hash node that corresponds the ether address 'ep' */ static inline struct enamemem * lookup_emem(const u_char *ep) { register u_int i, j, k; struct enamemem *tp; k = (ep[0] << 8) | ep[1]; j = (ep[2] << 8) | ep[3]; i = (ep[4] << 8) | ep[5]; tp = &enametable[(i ^ j) & (HASHNAMESIZE-1)]; while (tp->e_nxt) if (tp->e_addr0 == i && tp->e_addr1 == j && tp->e_addr2 == k) return tp; else tp = tp->e_nxt; tp->e_addr0 = i; tp->e_addr1 = j; tp->e_addr2 = k; tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp)); if (tp->e_nxt == NULL) error("lookup_emem: calloc"); return tp; } /* * Find the hash node that corresponds to the bytestring 'bs' * with length 'nlen' */ static inline struct enamemem * lookup_bytestring(register const u_char *bs, const unsigned int nlen) { struct enamemem *tp; register u_int i, j, k; if (nlen >= 6) { k = (bs[0] << 8) | bs[1]; j = (bs[2] << 8) | bs[3]; i = (bs[4] << 8) | bs[5]; } else if (nlen >= 4) { k = (bs[0] << 8) | bs[1]; j = (bs[2] << 8) | bs[3]; i = 0; } else i = j = k = 0; tp = &bytestringtable[(i ^ j) & (HASHNAMESIZE-1)]; while (tp->e_nxt) if (tp->e_addr0 == i && tp->e_addr1 == j && tp->e_addr2 == k && memcmp((const char *)bs, (const char *)(tp->e_bs), nlen) == 0) return tp; else tp = tp->e_nxt; tp->e_addr0 = i; tp->e_addr1 = j; tp->e_addr2 = k; tp->e_bs = (u_char *) calloc(1, nlen + 1); if (tp->e_bs == NULL) error("lookup_bytestring: calloc"); memcpy(tp->e_bs, bs, nlen); tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp)); if (tp->e_nxt == NULL) error("lookup_bytestring: calloc"); return tp; } /* Find the hash node that corresponds the NSAP 'nsap' */ static inline struct enamemem * lookup_nsap(register const u_char *nsap) { register u_int i, j, k; unsigned int nlen = *nsap; struct enamemem *tp; const u_char *ensap = nsap + nlen - 6; if (nlen > 6) { k = (ensap[0] << 8) | ensap[1]; j = (ensap[2] << 8) | ensap[3]; i = (ensap[4] << 8) | ensap[5]; } else i = j = k = 0; tp = &nsaptable[(i ^ j) & (HASHNAMESIZE-1)]; while (tp->e_nxt) if (tp->e_addr0 == i && tp->e_addr1 == j && tp->e_addr2 == k && tp->e_nsap[0] == nlen && memcmp((const char *)&(nsap[1]), (char *)&(tp->e_nsap[1]), nlen) == 0) return tp; else tp = tp->e_nxt; tp->e_addr0 = i; tp->e_addr1 = j; tp->e_addr2 = k; tp->e_nsap = (u_char *)malloc(nlen + 1); if (tp->e_nsap == NULL) error("lookup_nsap: malloc"); memcpy((char *)tp->e_nsap, (const char *)nsap, nlen + 1); tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp)); if (tp->e_nxt == NULL) error("lookup_nsap: calloc"); return tp; } /* Find the hash node that corresponds the protoid 'pi'. */ static inline struct protoidmem * lookup_protoid(const u_char *pi) { register u_int i, j; struct protoidmem *tp; /* 5 octets won't be aligned */ i = (((pi[0] << 8) + pi[1]) << 8) + pi[2]; j = (pi[3] << 8) + pi[4]; /* XXX should be endian-insensitive, but do big-endian testing XXX */ tp = &protoidtable[(i ^ j) & (HASHNAMESIZE-1)]; while (tp->p_nxt) if (tp->p_oui == i && tp->p_proto == j) return tp; else tp = tp->p_nxt; tp->p_oui = i; tp->p_proto = j; tp->p_nxt = (struct protoidmem *)calloc(1, sizeof(*tp)); if (tp->p_nxt == NULL) error("lookup_protoid: calloc"); return tp; } const char * etheraddr_string(netdissect_options *ndo, register const u_char *ep) { register int i; register char *cp; register struct enamemem *tp; int oui; char buf[BUFSIZE]; tp = lookup_emem(ep); if (tp->e_name) return (tp->e_name); #ifdef USE_ETHER_NTOHOST if (!ndo->ndo_nflag) { char buf2[BUFSIZE]; /* * We don't cast it to "const struct ether_addr *" * because some systems fail to declare the second * argument as a "const" pointer, even though they * don't modify what it points to. */ if (ether_ntohost(buf2, (struct ether_addr *)ep) == 0) { tp->e_name = strdup(buf2); return (tp->e_name); } } #endif cp = buf; oui = EXTRACT_24BITS(ep); *cp++ = hex[*ep >> 4 ]; *cp++ = hex[*ep++ & 0xf]; for (i = 5; --i >= 0;) { *cp++ = ':'; *cp++ = hex[*ep >> 4 ]; *cp++ = hex[*ep++ & 0xf]; } if (!ndo->ndo_nflag) { snprintf(cp, BUFSIZE - (2 + 5*3), " (oui %s)", tok2str(oui_values, "Unknown", oui)); } else *cp = '\0'; tp->e_name = strdup(buf); return (tp->e_name); } const char * le64addr_string(const u_char *ep) { const unsigned int len = 8; register u_int i; register char *cp; register struct enamemem *tp; char buf[BUFSIZE]; tp = lookup_bytestring(ep, len); if (tp->e_name) return (tp->e_name); cp = buf; for (i = len; i > 0 ; --i) { *cp++ = hex[*(ep + i - 1) >> 4]; *cp++ = hex[*(ep + i - 1) & 0xf]; *cp++ = ':'; } cp --; *cp = '\0'; tp->e_name = strdup(buf); return (tp->e_name); } const char * linkaddr_string(netdissect_options *ndo, const u_char *ep, const unsigned int type, const unsigned int len) { register u_int i; register char *cp; register struct enamemem *tp; if (len == 0) return (""); if (type == LINKADDR_ETHER && len == ETHER_ADDR_LEN) return (etheraddr_string(ndo, ep)); if (type == LINKADDR_FRELAY) - return (q922_string(ep)); + return (q922_string(ndo, ep, len)); tp = lookup_bytestring(ep, len); if (tp->e_name) return (tp->e_name); tp->e_name = cp = (char *)malloc(len*3); if (tp->e_name == NULL) error("linkaddr_string: malloc"); *cp++ = hex[*ep >> 4]; *cp++ = hex[*ep++ & 0xf]; for (i = len-1; i > 0 ; --i) { *cp++ = ':'; *cp++ = hex[*ep >> 4]; *cp++ = hex[*ep++ & 0xf]; } *cp = '\0'; return (tp->e_name); } const char * etherproto_string(u_short port) { register char *cp; register struct hnamemem *tp; register uint32_t i = port; char buf[sizeof("0000")]; for (tp = &eprototable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) if (tp->addr == i) return (tp->name); tp->addr = i; tp->nxt = newhnamemem(); cp = buf; NTOHS(port); *cp++ = hex[port >> 12 & 0xf]; *cp++ = hex[port >> 8 & 0xf]; *cp++ = hex[port >> 4 & 0xf]; *cp++ = hex[port & 0xf]; *cp++ = '\0'; tp->name = strdup(buf); return (tp->name); } const char * protoid_string(register const u_char *pi) { register u_int i, j; register char *cp; register struct protoidmem *tp; char buf[sizeof("00:00:00:00:00")]; tp = lookup_protoid(pi); if (tp->p_name) return tp->p_name; cp = buf; if ((j = *pi >> 4) != 0) *cp++ = hex[j]; *cp++ = hex[*pi++ & 0xf]; for (i = 4; (int)--i >= 0;) { *cp++ = ':'; if ((j = *pi >> 4) != 0) *cp++ = hex[j]; *cp++ = hex[*pi++ & 0xf]; } *cp = '\0'; tp->p_name = strdup(buf); return (tp->p_name); } #define ISONSAP_MAX_LENGTH 20 const char * isonsap_string(const u_char *nsap, register u_int nsap_length) { register u_int nsap_idx; register char *cp; register struct enamemem *tp; if (nsap_length < 1 || nsap_length > ISONSAP_MAX_LENGTH) return ("isonsap_string: illegal length"); tp = lookup_nsap(nsap); 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) error("isonsap_string: malloc"); for (nsap_idx = 0; nsap_idx < nsap_length; nsap_idx++) { *cp++ = hex[*nsap >> 4]; *cp++ = hex[*nsap++ & 0xf]; if (((nsap_idx & 1) == 0) && (nsap_idx + 1 < nsap_length)) { *cp++ = '.'; } } *cp = '\0'; return (tp->e_name); } const char * tcpport_string(u_short port) { register struct hnamemem *tp; register uint32_t i = port; char buf[sizeof("00000")]; for (tp = &tporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) if (tp->addr == i) return (tp->name); tp->addr = i; tp->nxt = newhnamemem(); (void)snprintf(buf, sizeof(buf), "%u", i); tp->name = strdup(buf); return (tp->name); } const char * udpport_string(register u_short port) { register struct hnamemem *tp; register uint32_t i = port; char buf[sizeof("00000")]; for (tp = &uporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) if (tp->addr == i) return (tp->name); tp->addr = i; tp->nxt = newhnamemem(); (void)snprintf(buf, sizeof(buf), "%u", i); tp->name = strdup(buf); return (tp->name); } const char * ipxsap_string(u_short port) { register char *cp; register struct hnamemem *tp; register uint32_t i = port; char buf[sizeof("0000")]; for (tp = &ipxsaptable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) if (tp->addr == i) return (tp->name); tp->addr = i; tp->nxt = newhnamemem(); cp = buf; NTOHS(port); *cp++ = hex[port >> 12 & 0xf]; *cp++ = hex[port >> 8 & 0xf]; *cp++ = hex[port >> 4 & 0xf]; *cp++ = hex[port & 0xf]; *cp++ = '\0'; tp->name = strdup(buf); return (tp->name); } static void init_servarray(netdissect_options *ndo) { struct servent *sv; register struct hnamemem *table; register int i; char buf[sizeof("0000000000")]; while ((sv = getservent()) != NULL) { int port = ntohs(sv->s_port); i = port & (HASHNAMESIZE-1); if (strcmp(sv->s_proto, "tcp") == 0) table = &tporttable[i]; else if (strcmp(sv->s_proto, "udp") == 0) table = &uporttable[i]; else continue; while (table->name) table = table->nxt; if (ndo->ndo_nflag) { (void)snprintf(buf, sizeof(buf), "%d", port); table->name = strdup(buf); } else table->name = strdup(sv->s_name); table->addr = port; table->nxt = newhnamemem(); } endservent(); } /* in libpcap.a (nametoaddr.c) */ #if defined(WIN32) && !defined(USE_STATIC_LIBPCAP) extern __declspec(dllimport) #else extern #endif const struct eproto { const char *s; u_short p; } eproto_db[]; static void init_eprotoarray(void) { register int i; register struct hnamemem *table; for (i = 0; eproto_db[i].s; i++) { int j = htons(eproto_db[i].p) & (HASHNAMESIZE-1); table = &eprototable[j]; while (table->name) table = table->nxt; table->name = eproto_db[i].s; table->addr = htons(eproto_db[i].p); table->nxt = newhnamemem(); } } 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(void) { register int i; register struct protoidmem *tp; const struct protoidlist *pl; u_char protoid[5]; protoid[0] = 0; protoid[1] = 0; protoid[2] = 0; for (i = 0; eproto_db[i].s; i++) { u_short etype = htons(eproto_db[i].p); memcpy((char *)&protoid[3], (char *)&etype, 2); tp = lookup_protoid(protoid); tp->p_name = strdup(eproto_db[i].s); } /* Hardwire some SNAP proto ID names */ for (pl = protoidlist; pl->name != NULL; ++pl) { tp = lookup_protoid(pl->protoid); /* Don't override existing name */ if (tp->p_name != NULL) continue; tp->p_name = pl->name; } } static const struct etherlist { const u_char addr[6]; const char *name; } etherlist[] = { {{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, "Broadcast" }, {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, NULL } }; /* * Initialize the ethers hash table. We take two different approaches * depending on whether or not the system provides the ethers name * service. If it does, we just wire in a few names at startup, * and etheraddr_string() fills in the table on demand. If it doesn't, * then we suck in the entire /etc/ethers file at startup. The idea * is that parsing the local file will be fast, but spinning through * all the ethers entries via NIS & next_etherent might be very slow. * * XXX pcap_next_etherent doesn't belong in the pcap interface, but * since the pcap module already does name-to-address translation, * it's already does most of the work for the ethernet address-to-name * translation, so we just pcap_next_etherent as a convenience. */ static void init_etherarray(void) { register const struct etherlist *el; register struct enamemem *tp; #ifdef USE_ETHER_NTOHOST char name[256]; #else register struct pcap_etherent *ep; register FILE *fp; /* Suck in entire ethers file */ fp = fopen(PCAP_ETHERS_FILE, "r"); if (fp != NULL) { while ((ep = pcap_next_etherent(fp)) != NULL) { tp = lookup_emem(ep->addr); tp->e_name = strdup(ep->name); } (void)fclose(fp); } #endif /* Hardwire some ethernet names */ for (el = etherlist; el->name != NULL; ++el) { tp = lookup_emem(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. * * We don't cast it to "const struct ether_addr *" * because some systems don't modify the Ethernet * address but fail to declare the second argument * as a "const" pointer. */ if (ether_ntohost(name, (struct ether_addr *)el->addr) == 0) { tp->e_name = strdup(name); continue; } #endif tp->e_name = el->name; } } static const struct tok ipxsap_db[] = { { 0x0000, "Unknown" }, { 0x0001, "User" }, { 0x0002, "User Group" }, { 0x0003, "PrintQueue" }, { 0x0004, "FileServer" }, { 0x0005, "JobServer" }, { 0x0006, "Gateway" }, { 0x0007, "PrintServer" }, { 0x0008, "ArchiveQueue" }, { 0x0009, "ArchiveServer" }, { 0x000a, "JobQueue" }, { 0x000b, "Administration" }, { 0x000F, "Novell TI-RPC" }, { 0x0017, "Diagnostics" }, { 0x0020, "NetBIOS" }, { 0x0021, "NAS SNA Gateway" }, { 0x0023, "NACS AsyncGateway" }, { 0x0024, "RemoteBridge/RoutingService" }, { 0x0026, "BridgeServer" }, { 0x0027, "TCP/IP Gateway" }, { 0x0028, "Point-to-point X.25 BridgeServer" }, { 0x0029, "3270 Gateway" }, { 0x002a, "CHI Corp" }, { 0x002c, "PC Chalkboard" }, { 0x002d, "TimeSynchServer" }, { 0x002e, "ARCserve5.0/PalindromeBackup" }, { 0x0045, "DI3270 Gateway" }, { 0x0047, "AdvertisingPrintServer" }, { 0x004a, "NetBlazerModems" }, { 0x004b, "BtrieveVAP" }, { 0x004c, "NetwareSQL" }, { 0x004d, "XtreeNetwork" }, { 0x0050, "BtrieveVAP4.11" }, { 0x0052, "QuickLink" }, { 0x0053, "PrintQueueUser" }, { 0x0058, "Multipoint X.25 Router" }, { 0x0060, "STLB/NLM" }, { 0x0064, "ARCserve" }, { 0x0066, "ARCserve3.0" }, { 0x0072, "WAN CopyUtility" }, { 0x007a, "TES-NetwareVMS" }, { 0x0092, "WATCOM Debugger/EmeraldTapeBackupServer" }, { 0x0095, "DDA OBGYN" }, { 0x0098, "NetwareAccessServer" }, { 0x009a, "Netware for VMS II/NamedPipeServer" }, { 0x009b, "NetwareAccessServer" }, { 0x009e, "PortableNetwareServer/SunLinkNVT" }, { 0x00a1, "PowerchuteAPC UPS" }, { 0x00aa, "LAWserve" }, { 0x00ac, "CompaqIDA StatusMonitor" }, { 0x0100, "PIPE STAIL" }, { 0x0102, "LAN ProtectBindery" }, { 0x0103, "OracleDataBaseServer" }, { 0x0107, "Netware386/RSPX RemoteConsole" }, { 0x010f, "NovellSNA Gateway" }, { 0x0111, "TestServer" }, { 0x0112, "HP PrintServer" }, { 0x0114, "CSA MUX" }, { 0x0115, "CSA LCA" }, { 0x0116, "CSA CM" }, { 0x0117, "CSA SMA" }, { 0x0118, "CSA DBA" }, { 0x0119, "CSA NMA" }, { 0x011a, "CSA SSA" }, { 0x011b, "CSA STATUS" }, { 0x011e, "CSA APPC" }, { 0x0126, "SNA TEST SSA Profile" }, { 0x012a, "CSA TRACE" }, { 0x012b, "NetwareSAA" }, { 0x012e, "IKARUS VirusScan" }, { 0x0130, "CommunicationsExecutive" }, { 0x0133, "NNS DomainServer/NetwareNamingServicesDomain" }, { 0x0135, "NetwareNamingServicesProfile" }, { 0x0137, "Netware386 PrintQueue/NNS PrintQueue" }, { 0x0141, "LAN SpoolServer" }, { 0x0152, "IRMALAN Gateway" }, { 0x0154, "NamedPipeServer" }, { 0x0166, "NetWareManagement" }, { 0x0168, "Intel PICKIT CommServer/Intel CAS TalkServer" }, { 0x0173, "Compaq" }, { 0x0174, "Compaq SNMP Agent" }, { 0x0175, "Compaq" }, { 0x0180, "XTreeServer/XTreeTools" }, { 0x018A, "NASI ServicesBroadcastServer" }, { 0x01b0, "GARP Gateway" }, { 0x01b1, "Binfview" }, { 0x01bf, "IntelLanDeskManager" }, { 0x01ca, "AXTEC" }, { 0x01cb, "ShivaNetModem/E" }, { 0x01cc, "ShivaLanRover/E" }, { 0x01cd, "ShivaLanRover/T" }, { 0x01ce, "ShivaUniversal" }, { 0x01d8, "CastelleFAXPressServer" }, { 0x01da, "CastelleLANPressPrintServer" }, { 0x01dc, "CastelleFAX/Xerox7033 FaxServer/ExcelLanFax" }, { 0x01f0, "LEGATO" }, { 0x01f5, "LEGATO" }, { 0x0233, "NMS Agent/NetwareManagementAgent" }, { 0x0237, "NMS IPX Discovery/LANternReadWriteChannel" }, { 0x0238, "NMS IP Discovery/LANternTrapAlarmChannel" }, { 0x023a, "LANtern" }, { 0x023c, "MAVERICK" }, { 0x023f, "NovellSMDR" }, { 0x024e, "NetwareConnect" }, { 0x024f, "NASI ServerBroadcast Cisco" }, { 0x026a, "NMS ServiceConsole" }, { 0x026b, "TimeSynchronizationServer Netware 4.x" }, { 0x0278, "DirectoryServer Netware 4.x" }, { 0x027b, "NetwareManagementAgent" }, { 0x0280, "Novell File and Printer Sharing Service for PC" }, { 0x0304, "NovellSAA Gateway" }, { 0x0308, "COM/VERMED" }, { 0x030a, "GalacticommWorldgroupServer" }, { 0x030c, "IntelNetport2/HP JetDirect/HP Quicksilver" }, { 0x0320, "AttachmateGateway" }, { 0x0327, "MicrosoftDiagnostiocs" }, { 0x0328, "WATCOM SQL Server" }, { 0x0335, "MultiTechSystems MultisynchCommServer" }, { 0x0343, "Xylogics RemoteAccessServer/LANModem" }, { 0x0355, "ArcadaBackupExec" }, { 0x0358, "MSLCD1" }, { 0x0361, "NETINELO" }, { 0x037e, "Powerchute UPS Monitoring" }, { 0x037f, "ViruSafeNotify" }, { 0x0386, "HP Bridge" }, { 0x0387, "HP Hub" }, { 0x0394, "NetWare SAA Gateway" }, { 0x039b, "LotusNotes" }, { 0x03b7, "CertusAntiVirus" }, { 0x03c4, "ARCserve4.0" }, { 0x03c7, "LANspool3.5" }, { 0x03d7, "LexmarkPrinterServer" }, { 0x03d8, "LexmarkXLE PrinterServer" }, { 0x03dd, "BanyanENS NetwareClient" }, { 0x03de, "GuptaSequelBaseServer/NetWareSQL" }, { 0x03e1, "UnivelUnixware" }, { 0x03e4, "UnivelUnixware" }, { 0x03fc, "IntelNetport" }, { 0x03fd, "PrintServerQueue" }, { 0x040A, "ipnServer" }, { 0x040D, "LVERRMAN" }, { 0x040E, "LVLIC" }, { 0x0414, "NET Silicon (DPI)/Kyocera" }, { 0x0429, "SiteLockVirus" }, { 0x0432, "UFHELPR???" }, { 0x0433, "Synoptics281xAdvancedSNMPAgent" }, { 0x0444, "MicrosoftNT SNA Server" }, { 0x0448, "Oracle" }, { 0x044c, "ARCserve5.01" }, { 0x0457, "CanonGP55" }, { 0x045a, "QMS Printers" }, { 0x045b, "DellSCSI Array" }, { 0x0491, "NetBlazerModems" }, { 0x04ac, "OnTimeScheduler" }, { 0x04b0, "CD-Net" }, { 0x0513, "EmulexNQA" }, { 0x0520, "SiteLockChecks" }, { 0x0529, "SiteLockChecks" }, { 0x052d, "CitrixOS2 AppServer" }, { 0x0535, "Tektronix" }, { 0x0536, "Milan" }, { 0x055d, "Attachmate SNA gateway" }, { 0x056b, "IBM8235 ModemServer" }, { 0x056c, "ShivaLanRover/E PLUS" }, { 0x056d, "ShivaLanRover/T PLUS" }, { 0x0580, "McAfeeNetShield" }, { 0x05B8, "NLM to workstation communication (Revelation Software)" }, { 0x05BA, "CompatibleSystemsRouters" }, { 0x05BE, "CheyenneHierarchicalStorageManager" }, { 0x0606, "JCWatermarkImaging" }, { 0x060c, "AXISNetworkPrinter" }, { 0x0610, "AdaptecSCSIManagement" }, { 0x0621, "IBM AntiVirus" }, { 0x0640, "Windows95 RemoteRegistryService" }, { 0x064e, "MicrosoftIIS" }, { 0x067b, "Microsoft Win95/98 File and Print Sharing for NetWare" }, { 0x067c, "Microsoft Win95/98 File and Print Sharing for NetWare" }, { 0x076C, "Xerox" }, { 0x079b, "ShivaLanRover/E 115" }, { 0x079c, "ShivaLanRover/T 115" }, { 0x07B4, "CubixWorldDesk" }, { 0x07c2, "Quarterdeck IWare Connect V2.x NLM" }, { 0x07c1, "Quarterdeck IWare Connect V3.x NLM" }, { 0x0810, "ELAN License Server Demo" }, { 0x0824, "ShivaLanRoverAccessSwitch/E" }, { 0x086a, "ISSC Collector" }, { 0x087f, "ISSC DAS AgentAIX" }, { 0x0880, "Intel Netport PRO" }, { 0x0881, "Intel Netport PRO" }, { 0x0b29, "SiteLock" }, { 0x0c29, "SiteLockApplications" }, { 0x0c2c, "LicensingServer" }, { 0x2101, "PerformanceTechnologyInstantInternet" }, { 0x2380, "LAI SiteLock" }, { 0x238c, "MeetingMaker" }, { 0x4808, "SiteLockServer/SiteLockMetering" }, { 0x5555, "SiteLockUser" }, { 0x6312, "Tapeware" }, { 0x6f00, "RabbitGateway" }, { 0x7703, "MODEM" }, { 0x8002, "NetPortPrinters" }, { 0x8008, "WordPerfectNetworkVersion" }, { 0x85BE, "Cisco EIGRP" }, { 0x8888, "WordPerfectNetworkVersion/QuickNetworkManagement" }, { 0x9000, "McAfeeNetShield" }, { 0x9604, "CSA-NT_MON" }, { 0xb6a8, "OceanIsleReachoutRemoteControl" }, { 0xf11f, "SiteLockMetering" }, { 0xf1ff, "SiteLock" }, { 0xf503, "Microsoft SQL Server" }, { 0xF905, "IBM TimeAndPlace" }, { 0xfbfb, "TopCallIII FaxServer" }, { 0xffff, "AnyService/Wildcard" }, { 0, (char *)0 } }; static void init_ipxsaparray(void) { register int i; register struct hnamemem *table; for (i = 0; ipxsap_db[i].s != NULL; i++) { int j = htons(ipxsap_db[i].v) & (HASHNAMESIZE-1); table = &ipxsaptable[j]; while (table->name) table = table->nxt; table->name = ipxsap_db[i].s; table->addr = htons(ipxsap_db[i].v); table->nxt = newhnamemem(); } } /* * 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(); init_servarray(ndo); init_eprotoarray(); init_protoidarray(); init_ipxsaparray(); } const char * dnaddr_string(netdissect_options *ndo, u_short dnaddr) { register struct hnamemem *tp; for (tp = &dnaddrtable[dnaddr & (HASHNAMESIZE-1)]; tp->nxt != 0; tp = tp->nxt) if (tp->addr == dnaddr) return (tp->name); tp->addr = dnaddr; tp->nxt = newhnamemem(); if (ndo->ndo_nflag) tp->name = dnnum_string(dnaddr); else tp->name = dnname_string(dnaddr); return(tp->name); } /* Return a zero'ed hnamemem struct and cuts down on calloc() overhead */ struct hnamemem * newhnamemem(void) { register struct hnamemem *p; static struct hnamemem *ptr = NULL; static u_int num = 0; if (num <= 0) { num = 64; ptr = (struct hnamemem *)calloc(num, sizeof (*ptr)); if (ptr == NULL) error("newhnamemem: calloc"); } --num; p = ptr++; return (p); } #ifdef INET6 /* Return a zero'ed h6namemem struct and cuts down on calloc() overhead */ struct h6namemem * newh6namemem(void) { register struct h6namemem *p; static struct h6namemem *ptr = NULL; static u_int num = 0; if (num <= 0) { num = 64; ptr = (struct h6namemem *)calloc(num, sizeof (*ptr)); if (ptr == NULL) error("newh6namemem: calloc"); } --num; p = ptr++; return (p); } #endif /* INET6 */ + +/* Represent TCI part of the 802.1Q 4-octet tag as text. */ +const char * +ieee8021q_tci_string(const uint16_t tci) +{ + static char buf[128]; + snprintf(buf, sizeof(buf), "vlan %u, p %u%s", + tci & 0xfff, + tci >> 13, + (tci & 0x1000) ? ", DEI" : ""); + return buf; +} Index: head/contrib/tcpdump/addrtoname.h =================================================================== --- head/contrib/tcpdump/addrtoname.h (revision 285274) +++ head/contrib/tcpdump/addrtoname.h (revision 285275) @@ -1,58 +1,59 @@ /* * Copyright (c) 1990, 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. */ /* Name to address translation routines. */ enum { LINKADDR_ETHER, LINKADDR_FRELAY, LINKADDR_IEEE1394, LINKADDR_ATM }; #define BUFSIZE 128 extern const char *linkaddr_string(netdissect_options *, const u_char *, const unsigned int, const unsigned int); extern const char *etheraddr_string(netdissect_options *, const u_char *); extern const char *le64addr_string(const u_char *); extern const char *etherproto_string(u_short); extern const char *tcpport_string(u_short); extern const char *udpport_string(u_short); extern const char *isonsap_string(const u_char *, register u_int); extern const char *dnaddr_string(netdissect_options *, u_short); extern const char *protoid_string(const u_char *); extern const char *ipxsap_string(u_short); extern const char *getname(netdissect_options *, const u_char *); #ifdef INET6 extern const char *getname6(netdissect_options *, const u_char *); #endif extern const char *intoa(uint32_t); extern void init_addrtoname(netdissect_options *, uint32_t, uint32_t); extern struct hnamemem *newhnamemem(void); #ifdef INET6 extern struct h6namemem *newh6namemem(void); #endif +extern const char * ieee8021q_tci_string(const uint16_t); #define ipaddr_string(ndo, p) getname(ndo, (const u_char *)(p)) #ifdef INET6 #define ip6addr_string(ndo, p) getname6(ndo, (const u_char *)(p)) #endif Index: head/contrib/tcpdump/config.guess =================================================================== --- head/contrib/tcpdump/config.guess (revision 285274) +++ head/contrib/tcpdump/config.guess (revision 285275) @@ -1,1530 +1,1435 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, -# 2011, 2012 Free Software Foundation, Inc. +# Copyright 1992-2015 Free Software Foundation, Inc. -timestamp='2012-02-10' +timestamp='2015-02-23' # 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 2 of the License, or +# 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 . # # 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. - - -# Originally written by Per Bothner. Please send patches (context -# diff format) to and include a ChangeLog -# entry. +# 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"). # -# This script attempts to guess a canonical system name similar to -# config.sub. If it succeeds, it prints the system name on stdout, and -# exits with 0. Otherwise, it exits with 1. +# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +# +# Please send patches to . + me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -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 ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, -2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 -Free Software Foundation, Inc. +Copyright 1992-2015 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." # 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 trap 'exit 1' 1 2 15 # 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. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { 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) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; 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 ; set_cc_for_build= ;' # 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) >/dev/null 2>&1 ; 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/*) + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + LIBC=gnu + + eval $set_cc_for_build + cat <<-EOF > $dummy.c + #include + #if defined(__UCLIBC__) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc + #else + LIBC=gnu + #endif + EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` + ;; +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". sysctl="sysctl -n hw.machine_arch" - UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ - /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ + /sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || \ + echo unknown)` case "${UNAME_MACHINE_ARCH}" in 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. case "${UNAME_MACHINE_ARCH}" in - arm*|i386|m68k|ns32k|sh3*|sparc|vax) + arm*|earm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $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/[-_].*/\./'` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}" + echo "${machine}-${os}${release}${abi}" exit ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} + exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; *:SolidBSD:*:*) echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; alpha:OSF1:*:*) 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. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; - arm:riscos:*:*|arm:RISCOS:*:*) + arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) echo i386-pc-auroraux${UNAME_RELEASE} exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) eval $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 [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH="x86_64" fi fi echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; 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. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; 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'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit ;; 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) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit ;; # 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:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* 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; } echo mips-mips-riscos${UNAME_RELEASE} exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include 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 echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *: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 [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` + if [ -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 echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 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 [ -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 [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include 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 [ ${HP_ARCH} = "hppa2.0w" ] then eval $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 echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include 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; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; 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*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; 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:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; 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/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 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/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case ${UNAME_PROCESSOR} in amd64) echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; + *:MINGW64*:*) + echo ${UNAME_MACHINE}-pc-mingw64 + exit ;; *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; - i*:MSYS*:*) + *:MSYS*:*) echo ${UNAME_MACHINE}-pc-msys exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; *:Interix*:*) case ${UNAME_MACHINE} in x86) echo i586-pc-interix${UNAME_RELEASE} exit ;; authenticamd | genuineintel | EM64T) echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; IA64) echo ia64-unknown-interix${UNAME_RELEASE} exit ;; esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; 8664:Windows_NT:*) echo x86_64-pc-mks exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; *:GNU:*:*) # the GNU system - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland - echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; aarch64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` 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="libc1" ; else LIBC="" ; fi - echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + if test "$?" = 0 ; then LIBC="gnulibc1" ; fi + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; + arc:Linux:*:* | arceb:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; arm*:Linux:*:*) eval $set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then - echo ${UNAME_MACHINE}-unknown-linux-gnueabi + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi else - echo ${UNAME_MACHINE}-unknown-linux-gnueabihf + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf fi fi exit ;; avr32*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; cris:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-gnu + echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; crisv32:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-gnu + echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; frv:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; hexagon:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:Linux:*:*) - LIBC=gnu - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #ifdef __dietlibc__ - LIBC=dietlibc - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` - echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + echo ${UNAME_MACHINE}-pc-linux-${LIBC} exit ;; ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m32r*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; mips:Linux:*:* | mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=${UNAME_MACHINE}el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=${UNAME_MACHINE} #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } ;; - or32:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + openrisc*:Linux:*:*) + echo or1k-unknown-linux-${LIBC} exit ;; + or32:Linux:*:* | or1k*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; padre:Linux:*:*) - echo sparc-unknown-linux-gnu + echo sparc-unknown-linux-${LIBC} exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-gnu + echo hppa64-unknown-linux-${LIBC} exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-gnu ;; - PA8*) echo hppa2.0-unknown-linux-gnu ;; - *) echo hppa-unknown-linux-gnu ;; + PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; + PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; + *) echo hppa-unknown-linux-${LIBC} ;; esac exit ;; ppc64:Linux:*:*) - echo powerpc64-unknown-linux-gnu + echo powerpc64-unknown-linux-${LIBC} exit ;; ppc:Linux:*:*) - echo powerpc-unknown-linux-gnu + echo powerpc-unknown-linux-${LIBC} exit ;; + ppc64le:Linux:*:*) + echo powerpc64le-unknown-linux-${LIBC} + exit ;; + ppcle:Linux:*:*) + echo powerpcle-unknown-linux-${LIBC} + exit ;; s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux + echo ${UNAME_MACHINE}-ibm-linux-${LIBC} exit ;; sh64*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sh*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; tile*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; vax:Linux:*:*) - echo ${UNAME_MACHINE}-dec-linux-gnu + echo ${UNAME_MACHINE}-dec-linux-${LIBC} exit ;; x86_64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; xtensa*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; 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. echo i386-sequent-sysv4 exit ;; 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. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit ;; 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 echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /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 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit ;; 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 configury will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; 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*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo ${UNAME_MACHINE}-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; + x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux${UNAME_RELEASE} exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux${UNAME_RELEASE} exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux${UNAME_RELEASE} exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown - case $UNAME_PROCESSOR in - i386) - eval $set_cc_for_build - if [ "$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 - UNAME_PROCESSOR="x86_64" - fi - fi ;; - unknown) UNAME_PROCESSOR=powerpc ;; - esac + eval $set_cc_for_build + if test "$UNAME_PROCESSOR" = unknown ; then + UNAME_PROCESSOR=powerpc + fi + if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then + if [ "$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 + fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # Avoid executing cc on OS X 10.9, as it ships with a stub + # that puts up a graphical alert prompting to install + # developer tools. Any system running Mac OS X 10.7 or + # later (Darwin 11 and later) is required to have a 64-bit + # processor. This is not true of the ARM version of Darwin + # that Apple uses in portable devices. + UNAME_PROCESSOR=x86_64 + fi echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NEO-?:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk${UNAME_RELEASE} exit ;; - NSE-?:NONSTOP_KERNEL:*:*) + NSE-*:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit ;; *: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 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; i*86:AROS:*:*) echo ${UNAME_MACHINE}-pc-aros exit ;; x86_64:VMkernel:*:*) echo ${UNAME_MACHINE}-unknown-esx exit ;; esac - -#echo '(No uname command or uname output not recognized.)' 1>&2 -#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 - -eval $set_cc_for_build -cat >$dummy.c < -# include -#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 - printf ("m68k-sony-newsos%s\n", -#ifdef NEWSOS4 - "4" -#else - "" -#endif - ); exit (0); -#endif -#endif - -#if defined (__arm) && defined (__acorn) && defined (__unix) - printf ("arm-acorn-riscix\n"); exit (0); -#endif - -#if defined (hp300) && !defined (hpux) - printf ("m68k-hp-bsd\n"); exit (0); -#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 -# 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 - printf ("vax-dec-ultrix\n"); exit (0); -# 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; } - -# Convex versions that predate uname can use getsysinfo(1) - -if [ -x /usr/convex/getsysinfo ] -then - case `getsysinfo -f cpu_type` in - c1*) - echo c1-convex-bsd - exit ;; - c2*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - c34*) - echo c34-convex-bsd - exit ;; - c38*) - echo c38-convex-bsd - exit ;; - c4*) - echo c4-convex-bsd - exit ;; - esac -fi cat >&2 < in order to provide the needed 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 exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: Index: head/contrib/tcpdump/config.h.in =================================================================== --- head/contrib/tcpdump/config.h.in (revision 285274) +++ head/contrib/tcpdump/config.h.in (revision 285275) @@ -1,384 +1,397 @@ /* config.h.in. Generated from configure.in by autoheader. */ /* define if you have the addrinfo function */ #undef HAVE_ADDRINFO /* Define to 1 if you have the `alarm' function. */ #undef HAVE_ALARM /* 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_rights_init' function. */ -#undef HAVE_CAP_RIGHTS_INIT +/* Define to 1 if you have the header file. */ +#undef HAVE_CAP_NG_H /* Define to 1 if you have the `cap_rights_limit' function. */ #undef HAVE_CAP_RIGHTS_LIMIT /* Define to 1 if you have the declaration of `ether_ntohost', and to 0 if you don't. */ #undef HAVE_DECL_ETHER_NTOHOST /* define if you have the dnet_htoa function */ #undef HAVE_DNET_HTOA /* Define to 1 if you have the `ether_ntohost' function. */ #undef HAVE_ETHER_NTOHOST /* Define to 1 if you have the 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 `getnameinfo' function. */ #undef HAVE_GETNAMEINFO /* Define to 1 if you have the `getopt_long' function. */ #undef HAVE_GETOPT_LONG /* define if you have getrpcbynumber() */ #undef HAVE_GETRPCBYNUMBER /* define if you have the h_errno variable */ #undef HAVE_H_ERRNO /* Define to 1 if you have the 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). */ #undef HAVE_LIBCRYPTO /* Define to 1 if you have the `rpc' library (-lrpc). */ #undef HAVE_LIBRPC /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the header file. */ #undef HAVE_NETDNET_DNETDB_H /* define if you have a dnet_htoa declaration in */ #undef HAVE_NETDNET_DNETDB_H_DNET_HTOA /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_ETHER_H /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_IF_ETHER_H /* Define to 1 if you have the header file. */ #undef HAVE_NET_PFVAR_H /* Define to 1 if you have the `openat' function. */ #undef HAVE_OPENAT /* Define to 1 if you have the header file. */ #undef HAVE_OPENSSL_EVP_H /* if there's an os_proto.h for this platform, to use additional prototypes */ #undef HAVE_OS_PROTO_H /* Define to 1 if you have the header file. */ #undef HAVE_PCAP_BLUETOOTH_H /* Define to 1 if you have the `pcap_breakloop' function. */ #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 if libpcap has pcap_dump_ftell() */ #undef HAVE_PCAP_DUMP_FTELL /* Define to 1 if you have the `pcap_findalldevs' function. */ #undef HAVE_PCAP_FINDALLDEVS /* 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 header file. */ #undef HAVE_PCAP_NFLOG_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_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 to 1 if you have the header file. */ #undef HAVE_PCAP_USB_H /* define if libpcap has pcap_version */ #undef HAVE_PCAP_VERSION /* Define to 1 if you have the `pfopen' function. */ #undef HAVE_PFOPEN /* Define to 1 if you have the header file. */ #undef HAVE_RPC_RPCENT_H /* Define to 1 if you have the 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 `sigaction' function. */ #undef HAVE_SIGACTION /* Define to 1 if you have the `sigset' function. */ #undef HAVE_SIGSET /* Define to 1 if you have the `snprintf' function. */ #undef HAVE_SNPRINTF /* if struct sockaddr has the sa_len member */ #undef HAVE_SOCKADDR_SA_LEN /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the `strcasecmp' function. */ #undef HAVE_STRCASECMP /* Define to 1 if you have the `strdup' function. */ #undef HAVE_STRDUP /* Define to 1 if you have the `strftime' function. */ #undef HAVE_STRFTIME /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the 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 header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the 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 header file. */ #undef HAVE_UNISTD_H /* Define to 1 if you have the `vfork' function. */ #undef HAVE_VFORK /* Define to 1 if you have the `vfprintf' function. */ #undef HAVE_VFPRINTF /* Define to 1 if you have the `vsnprintf' function. */ #undef HAVE_VSNPRINTF /* define if libpcap has yydebug */ #undef HAVE_YYDEBUG /* define if your compiler has __attribute__ */ #undef HAVE___ATTRIBUTE__ /* Define if you enable IPv6 support */ #undef INET6 /* if unaligned access fails */ #undef LBL_ALIGN /* define if you need to include missing/addrinfo.h */ #undef NEED_ADDRINFO_H /* 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 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 /* define if the platform doesn't define PRId64 */ #undef PRId64 /* define if the platform doesn't define PRIo64 */ #undef PRIo64 /* define if the platform doesn't define PRIx64 */ #undef PRIu64 /* define if the platform doesn't define PRIu64 */ #undef PRIx64 /* Define as the return type of signal handlers (`int' or `void'). */ #undef RETSIGTYPE /* return value of signal handlers */ #undef RETSIGVAL /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* define if you want to build the possibly-buggy SMB printer */ #undef TCPDUMP_DO_SMB /* Define to 1 if you can safely include both and . */ #undef TIME_WITH_SYS_TIME /* 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 /* get BSD semantics on Irix */ #undef _BSD_SIGNALS /* define on AIX to get certain functions */ #undef _SUN /* Define for Solaris 2.5.1 so the uint32_t typedef from , , or is not used. If the typedef were allowed, the #define below would cause a syntax error. */ #undef _UINT32_T /* Define for Solaris 2.5.1 so the uint64_t typedef from , , or is not used. If the typedef were allowed, the #define below would cause a syntax error. */ #undef _UINT64_T /* Define for Solaris 2.5.1 so the uint8_t typedef from , , or is not used. If the typedef were allowed, the #define below would cause a syntax error. */ #undef _UINT8_T /* define if your compiler allows __attribute__((format)) without a warning */ #undef __ATTRIBUTE___FORMAT_OK /* define if your compiler allows __attribute__((format)) to be applied to function pointers */ #undef __ATTRIBUTE___FORMAT_OK_FOR_FUNCTION_POINTERS /* define if your compiler allows __attribute__((noreturn)) to be applied to function pointers */ #undef __ATTRIBUTE___NORETURN_OK_FOR_FUNCTION_POINTERS /* 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 the type of a signed integer type of width exactly 16 bits if such a type exists and the standard includes do not define it. */ #undef int16_t /* Define to the type of a signed integer type of width exactly 32 bits if such a type exists and the standard includes do not define it. */ #undef int32_t /* Define to the type of a signed integer type of width exactly 64 bits if such a type exists and the standard includes do not define it. */ #undef int64_t /* Define to the type of a signed integer type of width exactly 8 bits if such a type exists and the standard includes do not define it. */ #undef int8_t /* Define to `uint16_t' if u_int16_t not defined. */ #undef u_int16_t /* Define to `uint32_t' if u_int32_t not defined. */ #undef u_int32_t /* Define to `uint64_t' if u_int64_t not defined. */ #undef u_int64_t /* Define to `uint8_t' if u_int8_t not defined. */ #undef u_int8_t /* Define to the type of an unsigned integer type of width exactly 16 bits if such a type exists and the standard includes do not define it. */ #undef uint16_t /* Define to the type of an unsigned integer type of width exactly 32 bits if such a type exists and the standard includes do not define it. */ #undef uint32_t /* Define to the type of an unsigned integer type of width exactly 64 bits if such a type exists and the standard includes do not define it. */ #undef uint64_t /* Define to the type of an unsigned integer type of width exactly 8 bits if such a type exists and the standard includes do not define it. */ #undef uint8_t + +/* Define to the type of an unsigned integer type wide enough to hold a + pointer, if such a type exists, and if the system does not define it. */ +#undef uintptr_t Index: head/contrib/tcpdump/config.sub =================================================================== --- head/contrib/tcpdump/config.sub (revision 285274) +++ head/contrib/tcpdump/config.sub (revision 285275) @@ -1,1779 +1,1807 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, -# 2011, 2012 Free Software Foundation, Inc. +# Copyright 1992-2015 Free Software Foundation, Inc. -timestamp='2012-04-18' +timestamp='2015-02-22' -# This file is (in principle) common to ALL GNU software. -# The presence of a machine in this file suggests that SOME GNU software -# can handle that machine. It does not imply ALL GNU software can. -# -# 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 2 of the License, or +# 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. +# 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 . # # 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. +# 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 . Submit a context -# diff and a properly formatted GNU ChangeLog entry. +# Please send patches to . # # 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: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD # 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. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -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 ." version="\ GNU config.sub ($timestamp) -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, -2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 -Free Software Foundation, Inc. +Copyright 1992-2015 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." # 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" 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 # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ - linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ - knetbsd*-gnu* | netbsd*-gnu* | \ + linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -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) + -apple | -axis | -knuth | -cray | -microblaze*) os= basic_machine=$1 ;; -bluegene*) os=-cnk ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*178) os=-lynxos178 ;; -lynx*5) os=-lynxos5 ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ - | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ - | be32 | be64 \ + | arc | arceb \ + | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ + | avr | avr32 \ + | be32 | be64 \ | bfin \ - | c4x | clipper \ + | c4x | c8051 | clipper \ | d10v | d30v | dlx | dsp16xx \ | epiphany \ - | fido | fr30 | frv \ + | fido | fr30 | frv | ft32 \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ + | k1om \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | mcore | mep | metag \ + | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ | mips64r5900 | mips64r5900el \ | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r6 | mipsisa32r6el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nds32 | nds32le | nds32be \ - | nios | nios2 \ + | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ - | open8 \ - | or32 \ + | open8 | or1k | or1knd | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pyramid \ + | riscv32 | riscv64 \ | rl78 | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu \ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | visium \ | we32k \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown ;; c54x) basic_machine=tic54x-unknown ;; c55x) basic_machine=tic55x-unknown ;; c6x) basic_machine=tic6x-unknown ;; - m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) + leon|leon[3-9]) + basic_machine=sparc-$basic_machine + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; strongarm | thumb | xscale) basic_machine=arm-unknown ;; xgate) basic_machine=$basic_machine-unknown os=-none ;; xscaleeb) basic_machine=armeb-unknown ;; xscaleel) basic_machine=armel-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) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ - | clipper-* | craynv-* | cydra-* \ + | c8051-* | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ + | k1om-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | microblaze-* | microblazeel-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ | mips64r5900-* | mips64r5900el-* \ | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa32r6-* | mipsisa32r6el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64r6-* | mipsisa64r6el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipsr5900-* | mipsr5900el-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nds32-* | nds32le-* | nds32be-* \ - | nios-* | nios2-* \ + | nios-* | nios2-* | nios2eb-* | nios2el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ + | or1k*-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pyramid-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ | tron-* \ | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ + | visium-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-* | z80-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aros) basic_machine=i386-pc os=-aros ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) basic_machine=powerpc-ibm os=-cnk ;; c54x-*) basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c55x-*) basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c6x-*) basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray os=-unicos ;; cegcc) basic_machine=arm-unknown os=-cegcc ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16 | cr16-*) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dicos) basic_machine=i686-pc os=-dicos ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; + leon-*|leon[3-9]-*) + basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` + ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; - microblaze) + microblaze*) basic_machine=microblaze-xilinx ;; + mingw64) + basic_machine=x86_64-pc + os=-mingw64 + ;; mingw32) - basic_machine=i386-pc + basic_machine=i686-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; + moxiebox) + basic_machine=moxie-unknown + os=-moxiebox + ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; msys) - basic_machine=i386-pc + basic_machine=i686-pc os=-msys ;; mvs) basic_machine=i370-ibm os=-mvs ;; nacl) basic_machine=le32-unknown os=-nacl ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; neo-tandem) basic_machine=neo-tandem ;; nse-tandem) basic_machine=nse-tandem ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; - rdos) + rdos | rdos64) + basic_machine=x86_64-pc + os=-rdos + ;; + rdos32) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh5el) basic_machine=sh5le-unknown ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; strongarm-* | thumb-*) basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tile*) basic_machine=$basic_machine-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; z80-*-coff) basic_machine=z80-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # 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) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then 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 ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ - | -sym* | -kopensolaris* \ + | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ - | -openbsd* | -solidbsd* \ + | -bitrig* | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -linux-gnu* | -linux-android* \ - | -linux-newlib* | -linux-uclibc* \ - | -uxpv* | -beos* | -mpeix* | -udk* \ + | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-musl* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -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 ;; -nsk*) os=-nsk ;; # 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 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; - -kaos*) - os=-kaos - ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -nacl*) ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; 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. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff + ;; + c8051-*) + os=-elf + ;; + hexagon-*) + os=-elf ;; tic54x-*) os=-coff ;; tic55x-*) os=-coff ;; tic6x-*) os=-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 ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-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 ;; *-next) os=-nextstep3 ;; *-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 ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $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 ;; -mvs* | -opened*) vendor=ibm ;; -os400*) 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 basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: Index: head/contrib/tcpdump/configure =================================================================== --- head/contrib/tcpdump/configure (revision 285274) +++ head/contrib/tcpdump/configure (revision 285275) @@ -1,9569 +1,9731 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69. # # # Copyright (C) 1992-1996, 1998-2012 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 : 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 case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi 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 # The user is always right. if test "${PATH_SEPARATOR+set}" != set; 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 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 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 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 : 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 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 : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || 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 : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else 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=. 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 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 : 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 : 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 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 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." else $as_echo "$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_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=$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" | 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 : eval 'as_fn_append () { eval $1+=\$2 }' else 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 : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # 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 fi $as_echo "$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" | 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; } # 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 } 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 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 &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= PACKAGE_TARNAME= PACKAGE_VERSION= PACKAGE_STRING= PACKAGE_BUGREPORT= PACKAGE_URL= ac_unique_file="tcpdump.c" # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" 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 MKDEP DEPENDENCY_CFLAG AR RANLIB PCAP_CONFIG LIBOBJS EGREP GREP CPP 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 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_smb with_user with_chroot with_sandbox_capsicum enable_ipv6 +with_system_libpcap with_crypto +with_cap_ng ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP' # 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' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE}' 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" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$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" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$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 ;; -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" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$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" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$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 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$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 ;; 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 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" | 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 this package 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] --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/PACKAGE] --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 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 OS X --enable-smb enable possibly-buggy SMB printer default=yes --disable-smb disable possibly-buggy SMB printer --enable-ipv6 enable ipv6 (with ipv4) support --disable-ipv6 disable ipv6 support 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 --without-smi don't link with libsmi --with-user=USERNAME drop privileges by default to USERNAME --with-chroot=DIRECTORY when dropping privileges, chroot to DIRECTORY - --with-sandbox-capsicum + --with-sandbox-capsicum use Capsicum security functions [default=yes, if + available] + --with-system-libpcap don't use local pcap library --with-crypto use OpenSSL libcrypto [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 if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor 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|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$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. 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 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 configure generated by GNU Autoconf 2.69 Copyright (C) 2012 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 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 (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 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; 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_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 # ------------------------------------------------------- # 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 () { 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 /* 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 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" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_try_run LINENO # ---------------------- # Try to link 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 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$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 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$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 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 () { 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 /* 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 # 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$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 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 { $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 /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #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_check_decl LINENO SYMBOL VAR INCLUDES # --------------------------------------------- # Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR # accordingly. ac_fn_c_check_decl () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack as_decl_name=`echo $2|sed 's/ *(.*//'` 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 cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { #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 : 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_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 eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof ($2)) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof (($2))) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext 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_type # ac_fn_c_find_intX_t LINENO BITS VAR # ----------------------------------- # Finds a signed integer type with width BITS, setting cache variable VAR # accordingly. ac_fn_c_find_intX_t () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for int$2_t" >&5 $as_echo_n "checking for int$2_t... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" # Order is important - never check a type that is potentially smaller # than half of the expected target width. for ac_type in int$2_t 'int' 'long int' \ 'long long int' 'short int' 'signed char'; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default enum { N = $2 / 2 - 1 }; int main () { static int test_array [1 - 2 * !(0 < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1))]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default enum { N = $2 / 2 - 1 }; int main () { static int test_array [1 - 2 * !(($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1) < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 2))]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else case $ac_type in #( int$2_t) : eval "$3=yes" ;; #( *) : eval "$3=\$ac_type" ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if eval test \"x\$"$3"\" = x"no"; then : else break fi done 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_find_intX_t # ac_fn_c_find_uintX_t LINENO BITS VAR # ------------------------------------ # Finds an unsigned integer type with width BITS, setting cache variable VAR # accordingly. ac_fn_c_find_uintX_t () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uint$2_t" >&5 $as_echo_n "checking for uint$2_t... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" # Order is important - never check a type that is potentially smaller # than half of the expected target width. for ac_type in uint$2_t 'unsigned int' 'unsigned long int' \ 'unsigned long long int' 'unsigned short int' 'unsigned char'; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !((($ac_type) -1 >> ($2 / 2 - 1)) >> ($2 / 2 - 1) == 3)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : case $ac_type in #( uint$2_t) : eval "$3=yes" ;; #( *) : eval "$3=\$ac_type" ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if eval test \"x\$"$3"\" = x"no"; then : else break fi done 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_find_uintX_t 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 $as_me, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _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" 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"` ;; 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=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## 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;} ;; 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 "## ----------------- ## ## 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"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## 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"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## 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" } >&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 # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # 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 elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" 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;} 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;} 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;} 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;} >$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=: ;; ,);; *) 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;} 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;} 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;} 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=$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 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 { $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 ac_build_alias=$build_alias test "x$ac_build_alias" = x && 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 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$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 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 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$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 : 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 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=. 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_SHLICC2="yes" $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 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; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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 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 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=. 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}gcc" $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 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; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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 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=. 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="gcc" $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 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; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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;} 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 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=. 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}cc" $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 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; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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 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=. 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 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 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+' '}$@" 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; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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 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=. 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$ac_prog" $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 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; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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 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=. 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="$ac_prog" $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 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; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi 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;} 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 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; 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 (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 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; 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[^ ]*//'` # 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 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$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; 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 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 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;} 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; } 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; } 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>&5 ac_status=$? $as_echo "$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;} 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; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { 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; } 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 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$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 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$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. 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; } 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 cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; 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 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$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 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;} 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; } 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 cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext 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; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} 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 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 () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF 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 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext 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 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_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include 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]; /* 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 **, 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; } _ACEOF 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 : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext 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 : 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 if test "$GCC" = yes ; then # # -Werror forces warnings to be errors. # ac_lbl_cc_force_warning_errors=-Werror # # Use -ffloat-store so that, on 32-bit x86, we don't # do 80-bit arithmetic with the FPU; that way we should # get the same results for floating-point calculations # on x86-32 and x86-64. # { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -ffloat-store option" >&5 $as_echo_n "checking whether the compiler supports the -ffloat-store option... " >&6; } save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors -ffloat-store" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return 0 ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } CFLAGS="$save_CFLAGS" V_CCOPT="$V_CCOPT -ffloat-store" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } CFLAGS="$save_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext 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 ;; 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 cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { struct a { int b; }; void c(const struct a *) ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_lbl_cc_const_proto=yes else ac_cv_lbl_cc_const_proto=no fi rm -f core conftest.err conftest.$ac_objext 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; } if test $ac_cv_lbl_cc_const_proto = no ; then $as_echo "#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; } save_CFLAGS="$CFLAGS" CFLAGS="$V_CCOPT" if ${ac_cv_lbl_inline+:} false; then : $as_echo_n "(cached) " >&6 else 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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __attribute__" >&5 $as_echo_n "checking for __attribute__... " >&6; } if ${ac_cv___attribute__+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include static void foo(void) __attribute__ ((noreturn)); static void foo(void) { exit(1); } int main(int argc, char **argv) { foo(); } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv___attribute__=yes else ac_cv___attribute__=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test "$ac_cv___attribute__" = "yes"; then $as_echo "#define HAVE___ATTRIBUTE__ 1" >>confdefs.h else # # We can't use __attribute__, so we can't use __attribute__((unused)), # so we define _U_ to an empty string. # V_DEFS="$V_DEFS -D_U_=\"\"" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv___attribute__" >&5 $as_echo "$ac_cv___attribute__" >&6; } if test "$ac_cv___attribute__" = "yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether __attribute__((unused)) can be used without warnings" >&5 $as_echo_n "checking whether __attribute__((unused)) can be used without warnings... " >&6; } if ${ac_cv___attribute___unused+:} false; then : $as_echo_n "(cached) " >&6 else save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main(int argc __attribute((unused)), char **argv __attribute((unused))) { printf("Hello, world!\n"); return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv___attribute___unused=yes else ac_cv___attribute___unused=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi CFLAGS="$save_CFLAGS" if test "$ac_cv___attribute___unused" = "yes"; then V_DEFS="$V_DEFS -D_U_=\"__attribute__((unused))\"" else V_DEFS="$V_DEFS -D_U_=\"\"" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv___attribute___unused" >&5 $as_echo "$ac_cv___attribute___unused" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether __attribute__((noreturn)) can be applied to function pointers without warnings" >&5 $as_echo_n "checking whether __attribute__((noreturn)) can be applied to function pointers without warnings... " >&6; } if ${ac_cv___attribute___noreturn_function_pointer+:} false; then : $as_echo_n "(cached) " >&6 else save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include extern int (*foo)(int i) __attribute__ ((noreturn)); int main(int argc, char **argv) { (*foo)(1); } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv___attribute___noreturn_function_pointer=yes else ac_cv___attribute___noreturn_function_pointer=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi CFLAGS="$save_CFLAGS" if test "$ac_cv___attribute___noreturn_function_pointer" = "yes"; then $as_echo "#define __ATTRIBUTE___NORETURN_OK_FOR_FUNCTION_POINTERS 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv___attribute___noreturn_function_pointer" >&5 $as_echo "$ac_cv___attribute___noreturn_function_pointer" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether __attribute__((format)) can be used without warnings" >&5 $as_echo_n "checking whether __attribute__((format)) can be used without warnings... " >&6; } if ${ac_cv___attribute___format+:} false; then : $as_echo_n "(cached) " >&6 else save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include extern int foo(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); int main(int argc, char **argv) { foo("%s", "test"); } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv___attribute___format=yes else ac_cv___attribute___format=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi CFLAGS="$save_CFLAGS" if test "$ac_cv___attribute___format" = "yes"; then $as_echo "#define __ATTRIBUTE___FORMAT_OK 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv___attribute___format" >&5 $as_echo "$ac_cv___attribute___format" >&6; } if test "$ac_cv___attribute___format" = "yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether __attribute__((format)) can be applied to function pointers" >&5 $as_echo_n "checking whether __attribute__((format)) can be applied to function pointers... " >&6; } if ${ac_cv___attribute___format_function_pointer+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include extern int (*foo)(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); int main(int argc, char **argv) { (*foo)("%s", "test"); } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv___attribute___format_function_pointer=yes else ac_cv___attribute___format_function_pointer=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test "$ac_cv___attribute___format_function_pointer" = "yes"; then $as_echo "#define __ATTRIBUTE___FORMAT_OK_FOR_FUNCTION_POINTERS 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv___attribute___format_function_pointer" >&5 $as_echo "$ac_cv___attribute___format_function_pointer" >&6; } 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 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 to if __STDC__ is defined, since # 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 #else # include #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 _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 to if __STDC__ is defined, since # 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 #else # include #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 _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 #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no 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 _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi 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 _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 #include #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 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 { $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 fi # 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 " 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 done for ac_header in fcntl.h rpc/rpc.h rpc/rpcent.h netdnet/dnetdb.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 done for ac_header in net/pfvar.h do : ac_fn_c_check_header_compile "$LINENO" "net/pfvar.h" "ac_cv_header_net_pfvar_h" "#include #include #include " if test "x$ac_cv_header_net_pfvar_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_NET_PFVAR_H 1 _ACEOF fi done if test "$ac_cv_header_net_pfvar_h" = yes; then LOCALSRC="print-pflog.c $LOCALSRC" fi for ac_header in netinet/if_ether.h do : ac_fn_c_check_header_compile "$LINENO" "netinet/if_ether.h" "ac_cv_header_netinet_if_ether_h" "#include #include " if test "x$ac_cv_header_netinet_if_ether_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_NETINET_IF_ETHER_H 1 _ACEOF fi done if test "$ac_cv_header_netinet_if_ether_h" != yes; then # # The simple test didn't work. # Do we need to include first? # Unset ac_cv_header_netinet_if_ether_h so we don't # treat the previous failure as a cached value and # suppress the next test. # { $as_echo "$as_me:${as_lineno-$LINENO}: Rechecking with some additional includes" >&5 $as_echo "$as_me: Rechecking with some additional includes" >&6;} unset ac_cv_header_netinet_if_ether_h for ac_header in netinet/if_ether.h do : ac_fn_c_check_header_compile "$LINENO" "netinet/if_ether.h" "ac_cv_header_netinet_if_ether_h" "#include #include #include struct mbuf; struct rtentry; #include " if test "x$ac_cv_header_netinet_if_ether_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_NETINET_IF_ETHER_H 1 _ACEOF fi done fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5 $as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; } if ${ac_cv_header_time+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main () { if ((struct tm *) 0) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_time=yes else ac_cv_header_time=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5 $as_echo "$ac_cv_header_time" >&6; } if test $ac_cv_header_time = yes; then $as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h fi case "$host_os" in darwin*) # Check whether --enable-universal was given. if test "${enable_universal+set}" = set; 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 # Check whether --with-smi was given. if test "${with_smi+set}" = set; then : withval=$with_smi; else 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 : # # 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 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 () { return smiInit (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_smi_smiInit=yes else ac_cv_lib_smi_smiInit=no fi rm -f core conftest.err conftest.$ac_objext \ 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 : # # 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; } savedlibs="$LIBS" LIBS="-lsmi $LIBS" 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; } LIBS="$savedlibs" else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* libsmi available check */ #include 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", ¤t, &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 : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define USE_LIBSMI 1" >>confdefs.h else 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; } ;; 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 { $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; } # Check whether --enable-smb was given. if test "${enable_smb+set}" = set; then : enableval=$enable_smb; else enableval=yes fi case "$enableval" in yes) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: The SMB printer may have exploitable buffer overflows!!!" >&5 $as_echo "$as_me: WARNING: The SMB printer may have exploitable buffer overflows!!!" >&2;} $as_echo "#define TCPDUMP_DO_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; } ;; esac # Check whether --with-user was given. if test "${with_user+set}" = set; then : withval=$with_user; 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 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 # Check whether --with-chroot was given. if test "${with_chroot+set}" = set; then : withval=$with_chroot; 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 cat >>confdefs.h <<_ACEOF #define WITH_CHROOT "$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 # Check whether --with-sandbox-capsicum was given. if test "${with_sandbox_capsicum+set}" = set; 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. # -# All of them must be available in order to enable capsicum sandboxing. +# 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 - for ac_func in cap_enter cap_rights_init 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` 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_lbl_capsicum_function_seen=yes else ac_lbl_capsicum_function_not_seen=yes fi done 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; } 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 { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # # We must check this before checking whether to enable IPv6, 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 # 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 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 (); int main () { return gethostbyname (); ; return 0; } _ACEOF for ac_lib in '' 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 fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_gethostbyname+:} false; then : break fi done if ${ac_cv_search_gethostbyname+:} false; then : else ac_cv_search_gethostbyname=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 : 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" 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 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 (); int main () { return gethostbyname (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_socket_gethostbyname=yes else ac_cv_lib_socket_gethostbyname=no fi rm -f core conftest.err conftest.$ac_objext \ 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 : 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 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 () { return socket (); ; return 0; } _ACEOF 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 : ac_cv_search_socket=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_socket+:} false; then : break fi done if ${ac_cv_search_socket+:} false; then : else 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; } ac_res=$ac_cv_search_socket 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 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 () { return socket (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_socket_socket=yes else ac_cv_lib_socket_socket=no fi rm -f core conftest.err conftest.$ac_objext \ 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 : 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 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 () { return putmsg (); ; return 0; } _ACEOF 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 : ac_cv_search_putmsg=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_putmsg+:} false; then : break fi done if ${ac_cv_search_putmsg+:} false; then : else 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; } ac_res=$ac_cv_search_putmsg if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable ipv6" >&5 $as_echo_n "checking whether to enable ipv6... " >&6; } # Check whether --enable-ipv6 was given. if test "${enable_ipv6+set}" = set; then : enableval=$enable_ipv6; case "$enableval" in yes) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - LOCALSRC="print-ip6.c print-ip6opts.c print-mobility.c print-ripng.c print-icmp6.c print-frag6.c print-rt6.c print-ospf6.c print-dhcp6.c print-babel.c $LOCALSRC" + LOCALSRC="print-ip6opts.c print-mobility.c print-ripng.c print-icmp6.c print-frag6.c print-rt6.c print-ospf6.c print-dhcp6.c print-babel.c $LOCALSRC" $as_echo "#define INET6 1" >>confdefs.h ipv6=yes ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ipv6=no ;; esac else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* AF_INET6 available check */ #include #include #include #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 : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - LOCALSRC="print-ip6.c print-ip6opts.c print-mobility.c print-ripng.c print-icmp6.c print-frag6.c print-rt6.c print-ospf6.c print-dhcp6.c print-babel.c $LOCALSRC" + LOCALSRC="print-ip6opts.c print-mobility.c print-ripng.c print-icmp6.c print-frag6.c print-rt6.c print-ospf6.c print-dhcp6.c print-babel.c $LOCALSRC" $as_echo "#define INET6 1" >>confdefs.h ipv6=yes else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ipv6=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi 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; } for i in inria kame linux-glibc linux-libinet6 toshiba v6d zeta; do case $i in inria) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #ifdef IPV6_INRIA_VERSION yes #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "yes" >/dev/null 2>&1; then : ipv6type=$i; CFLAGS="-DINET6 $CFLAGS" fi rm -f conftest* ;; kame) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #ifdef __KAME__ yes #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "yes" >/dev/null 2>&1; then : ipv6type=$i; ipv6lib=inet6; ipv6libdir=/usr/local/v6/lib; ipv6trylibc=yes; CFLAGS="-DINET6 $CFLAGS" fi rm -f conftest* ;; linux-glibc) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #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 : ipv6type=$i; CFLAGS="-DINET6 $CFLAGS" fi rm -f 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="-DINET6 -I/usr/inet6/include $CFLAGS" fi ;; toshiba) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #ifdef _TOSHIBA_INET6 yes #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "yes" >/dev/null 2>&1; then : ipv6type=$i; ipv6lib=inet6; ipv6libdir=/usr/local/v6/lib; CFLAGS="-DINET6 $CFLAGS" fi rm -f conftest* ;; v6d) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #ifdef __V6D__ yes #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $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* ;; zeta) cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #ifdef _ZETA_MINAMI_INET6 yes #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "yes" >/dev/null 2>&1; then : ipv6type=$i; ipv6lib=inet6; ipv6libdir=/usr/local/v6/lib; CFLAGS="-DINET6 $CFLAGS" fi rm -f conftest* ;; esac if test "$ipv6type" != "unknown"; then break fi done { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ipv6type" >&5 $as_echo "$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 if test "$ipv6" = "yes"; then # # XXX - on Tru64 UNIX 5.1, there is no "getaddrinfo()" # function in libc; there are "ngetaddrinfo()" and # "ogetaddrinfo()" functions, and #defines # "getaddrinfo" to be either "ngetaddrinfo" or # "ogetaddrinfo", depending on whether _SOCKADDR_LEN # or _XOPEN_SOURCE_EXTENDED are defined or not. # # So this test doesn't work on Tru64 5.1, and possibly # on other 5.x releases. This causes the configure # script to become confused, and results in libpcap # being unbuildable. # { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing getaddrinfo" >&5 $as_echo_n "checking for library containing getaddrinfo... " >&6; } if ${ac_cv_search_getaddrinfo+:} false; then : $as_echo_n "(cached) " >&6 else 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 getaddrinfo (); int main () { return getaddrinfo (); ; return 0; } _ACEOF 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 : ac_cv_search_getaddrinfo=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_getaddrinfo+:} false; then : break fi done if ${ac_cv_search_getaddrinfo+:} false; then : else ac_cv_search_getaddrinfo=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_getaddrinfo" >&5 $as_echo "$ac_cv_search_getaddrinfo" >&6; } ac_res=$ac_cv_search_getaddrinfo if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking getaddrinfo bug" >&5 $as_echo_n "checking getaddrinfo bug... " >&6; } if ${td_cv_buggygetaddrinfo+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : - td_cv_buggygetaddrinfo=yes + td_cv_buggygetaddrinfo=unknown else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include main() { int passive, gaierr, inet4 = 0, inet6 = 0; struct addrinfo hints, *ai, *aitop; char straddr[INET6_ADDRSTRLEN], strport[16]; for (passive = 0; passive <= 1; passive++) { memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_flags = passive ? AI_PASSIVE : 0; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; if ((gaierr = getaddrinfo(NULL, "54321", &hints, &aitop)) != 0) { (void)gai_strerror(gaierr); goto bad; } for (ai = aitop; ai; ai = ai->ai_next) { if (ai->ai_addr == NULL || ai->ai_addrlen == 0 || getnameinfo(ai->ai_addr, ai->ai_addrlen, straddr, sizeof(straddr), strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { goto bad; } switch (ai->ai_family) { case AF_INET: if (strcmp(strport, "54321") != 0) { goto bad; } if (passive) { if (strcmp(straddr, "0.0.0.0") != 0) { goto bad; } } else { if (strcmp(straddr, "127.0.0.1") != 0) { goto bad; } } inet4++; break; case AF_INET6: if (strcmp(strport, "54321") != 0) { goto bad; } if (passive) { if (strcmp(straddr, "::") != 0) { goto bad; } } else { if (strcmp(straddr, "::1") != 0) { goto bad; } } inet6++; break; case AF_UNSPEC: goto bad; break; #ifdef AF_UNIX case AF_UNIX: #else #ifdef AF_LOCAL case AF_LOCAL: #endif #endif default: /* another family support? */ break; } } } /* supported family should be 2, unsupported family should be 0 */ if (!(inet4 == 0 || inet4 == 2)) goto bad; if (!(inet6 == 0 || inet6 == 2)) goto bad; if (aitop) freeaddrinfo(aitop); exit(0); bad: if (aitop) freeaddrinfo(aitop); exit(1); } _ACEOF if ac_fn_c_try_run "$LINENO"; then : td_cv_buggygetaddrinfo=no else td_cv_buggygetaddrinfo=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 if test "$td_cv_buggygetaddrinfo" = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: good" >&5 $as_echo "good" >&6; } + elif test "$td_cv_buggygetaddrinfo" = unknown; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unknown (cross-compiling)" >&5 +$as_echo "unknown (cross-compiling)" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: buggy" >&5 $as_echo "buggy" >&6; } fi if test "$td_cv_buggygetaddrinfo" = "yes"; then # # XXX - it doesn't appear that "ipv6type" can ever be # set to "linux". Should this be testing for # "linux-glibc", or for that *or* "linux-libinet6"? # If the latter, note that "linux-libinet6" is also # the type given to some non-Linux OSes. # if test "$ipv6type" != "linux"; then echo 'Fatal: You must get working getaddrinfo() function.' echo ' or you can specify "--disable-ipv6"'. exit 1 else echo 'Warning: getaddrinfo() implementation on your system seems be buggy.' echo ' Better upgrade your system library to newest version' echo ' of GNU C library (aka glibc).' fi fi fi ac_fn_c_check_func "$LINENO" "getnameinfo" "ac_cv_func_getnameinfo" if test "x$ac_cv_func_getnameinfo" = xyes; then : $as_echo "#define HAVE_GETNAMEINFO 1" >>confdefs.h else case " $LIBOBJS " in *" getnameinfo.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS getnameinfo.$ac_objext" ;; esac fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dnet_htoa declaration in netdnet/dnetdb.h" >&5 $as_echo_n "checking for dnet_htoa declaration in netdnet/dnetdb.h... " >&6; } if ${td_cv_decl_netdnet_dnetdb_h_dnet_htoa+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "dnet_htoa" >/dev/null 2>&1; then : td_cv_decl_netdnet_dnetdb_h_dnet_htoa=yes else td_cv_decl_netdnet_dnetdb_h_dnet_htoa=no fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $td_cv_decl_netdnet_dnetdb_h_dnet_htoa" >&5 $as_echo "$td_cv_decl_netdnet_dnetdb_h_dnet_htoa" >&6; } if test "$td_cv_decl_netdnet_dnetdb_h_dnet_htoa" = yes; then $as_echo "#define HAVE_NETDNET_DNETDB_H_DNET_HTOA 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for addrinfo" >&5 $as_echo_n "checking for addrinfo... " >&6; } if ${ac_cv_addrinfo+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ # include int main () { struct addrinfo a ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_addrinfo=yes else ac_cv_addrinfo=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_addrinfo" >&5 $as_echo "$ac_cv_addrinfo" >&6; } if test $ac_cv_addrinfo = yes; then $as_echo "#define HAVE_ADDRINFO 1" >>confdefs.h else $as_echo "#define NEED_ADDRINFO_H 1" >>confdefs.h fi if test "$ac_cv_addrinfo" = no; then missing_includes=yes fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for NI_MAXSERV" >&5 $as_echo_n "checking for NI_MAXSERV... " >&6; } if ${ac_cv_maxserv+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #ifdef NI_MAXSERV yes #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "yes" >/dev/null 2>&1; then : ac_cv_maxserv=yes else ac_cv_maxserv=no fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_maxserv" >&5 $as_echo "$ac_cv_maxserv" >&6; } if test $ac_cv_maxserv != yes; then $as_echo "#define NEED_ADDRINFO_H 1" >>confdefs.h fi if test "$ac_cv_maxserv" = no; then missing_includes=yes fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for NI_NAMEREQD" >&5 $as_echo_n "checking for NI_NAMEREQD... " >&6; } if ${ac_cv_namereqd+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #ifdef NI_NOFQDN yes #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "yes" >/dev/null 2>&1; then : ac_cv_namereqd=yes else ac_cv_namereqd=no fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_namereqd" >&5 $as_echo "$ac_cv_namereqd" >&6; } if test $ac_cv_namereqd != yes; then $as_echo "#define NEED_ADDRINFO_H 1" >>confdefs.h fi if test "$ac_cv_namereqd" = no; then missing_includes=yes fi ac_fn_c_check_func "$LINENO" "vfprintf" "ac_cv_func_vfprintf" if test "x$ac_cv_func_vfprintf" = xyes; then : $as_echo "#define HAVE_VFPRINTF 1" >>confdefs.h else case " $LIBOBJS " in *" vfprintf.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS vfprintf.$ac_objext" ;; esac fi ac_fn_c_check_func "$LINENO" "strcasecmp" "ac_cv_func_strcasecmp" if test "x$ac_cv_func_strcasecmp" = xyes; then : $as_echo "#define HAVE_STRCASECMP 1" >>confdefs.h else case " $LIBOBJS " in *" strcasecmp.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS strcasecmp.$ac_objext" ;; esac 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 else 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 else 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 else 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 else case " $LIBOBJS " in *" strsep.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS strsep.$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 else case " $LIBOBJS " in *" getopt_long.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS getopt_long.$ac_objext" ;; esac fi for ac_func in fork vfork strftime 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 done for ac_func in setlinebuf alarm 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 done needsnprintf=no for ac_func in vsnprintf snprintf 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 else needsnprintf=yes fi done if test $needsnprintf = yes; then case " $LIBOBJS " in *" snprintf.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS snprintf.$ac_objext" ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking return type of signal handlers" >&5 $as_echo_n "checking return type of signal handlers... " >&6; } if ${ac_cv_type_signal+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { return *(signal (0, 0)) (0) == 1; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_type_signal=int else ac_cv_type_signal=void fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_signal" >&5 $as_echo "$ac_cv_type_signal" >&6; } cat >>confdefs.h <<_ACEOF #define RETSIGTYPE $ac_cv_type_signal _ACEOF if test "$ac_cv_type_signal" = void ; then $as_echo "#define RETSIGVAL /**/" >>confdefs.h else $as_echo "#define RETSIGVAL (0)" >>confdefs.h fi case "$host_os" in irix*) $as_echo "#define _BSD_SIGNALS 1" >>confdefs.h ;; *) for ac_func in sigaction do : ac_fn_c_check_func "$LINENO" "sigaction" "ac_cv_func_sigaction" if test "x$ac_cv_func_sigaction" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SIGACTION 1 _ACEOF fi done if test $ac_cv_func_sigaction = no ; then for ac_func in sigset do : ac_fn_c_check_func "$LINENO" "sigset" "ac_cv_func_sigset" if test "x$ac_cv_func_sigset" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SIGSET 1 _ACEOF fi done fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dnet_htoa" >&5 $as_echo_n "checking for library containing dnet_htoa... " >&6; } if ${ac_cv_search_dnet_htoa+:} false; then : $as_echo_n "(cached) " >&6 else 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 dnet_htoa (); int main () { return dnet_htoa (); ; return 0; } _ACEOF for ac_lib in '' dnet; 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_dnet_htoa=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_dnet_htoa+:} false; then : break fi done if ${ac_cv_search_dnet_htoa+:} false; then : else ac_cv_search_dnet_htoa=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dnet_htoa" >&5 $as_echo "$ac_cv_search_dnet_htoa" >&6; } ac_res=$ac_cv_search_dnet_htoa if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" $as_echo "#define HAVE_DNET_HTOA 1" >>confdefs.h 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 ac_check_lib_save_LIBS=$LIBS LIBS="-lrpc $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_rpc_main=yes else ac_cv_lib_rpc_main=no fi rm -f core conftest.err conftest.$ac_objext \ 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 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 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 () { return getrpcbynumber (); ; return 0; } _ACEOF 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 : ac_cv_search_getrpcbynumber=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_getrpcbynumber+:} false; then : break fi done if ${ac_cv_search_getrpcbynumber+:} false; then : else 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; } ac_res=$ac_cv_search_getrpcbynumber if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" $as_echo "#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 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; } LIBS="$LIBS $pfopen" fi fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for local pcap library" >&5 + libpcap=FAIL + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for local pcap library" >&5 $as_echo_n "checking for local pcap library... " >&6; } - libpcap=FAIL - lastdir=FAIL - places=`ls $srcdir/.. | sed -e 's,/$,,' -e "s,^,$srcdir/../," | \ - egrep '/libpcap-[0-9]+\.[0-9]+(\.[0-9]*)?([ab][0-9]*|-PRE-GIT)?$'` - places2=`ls .. | sed -e 's,/$,,' -e "s,^,../," | \ - egrep '/libpcap-[0-9]+\.[0-9]+(\.[0-9]*)?([ab][0-9]*|-PRE-GIT)?$'` - 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 - d=$dir - fi - done + +# Check whether --with-system-libpcap was given. +if test "${with_system_libpcap+set}" = set; then : + withval=$with_system_libpcap; +fi + + if test "x$with_system_libpcap" != xyes ; then + lastdir=FAIL + places=`ls $srcdir/.. | sed -e 's,/$,,' -e "s,^,$srcdir/../," | \ + egrep '/libpcap-[0-9]+\.[0-9]+(\.[0-9]*)?([ab][0-9]*|-PRE-GIT)?$'` + places2=`ls .. | sed -e 's,/$,,' -e "s,^,../," | \ + egrep '/libpcap-[0-9]+\.[0-9]+(\.[0-9]*)?([ab][0-9]*|-PRE-GIT)?$'` + 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 + d=$dir + fi + done + fi if test $libpcap = FAIL ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 $as_echo "not found" >&6; } # # Look for 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 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=. 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 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; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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 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=. 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 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; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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;} 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. # # 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` V_INCLS="$cflags $V_INCLS" libpcap=`"$PCAP_CONFIG" --libs` else # # Not found; look for 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 ac_check_lib_save_LIBS=$LIBS LIBS="-lpcap $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pcap_main=yes else ac_cv_lib_pcap_main=no fi rm -f core conftest.err conftest.$ac_objext \ 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 : libpcap="-lpcap" fi if test $libpcap = FAIL ; then as_fn_error $? "see the INSTALL doc 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; } 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; } 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; } fi fi else V_PCAPDEP=$libpcap places=`ls $srcdir/.. | sed -e 's,/$,,' -e "s,^,$srcdir/../," | \ 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]*)?$'` pcapH=FAIL if test -r $d/pcap.h; then pcapH=$d 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 fi V_INCLS="-I$pcapH $V_INCLS" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libpcap" >&5 $as_echo "$libpcap" >&6; } # 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 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 $d 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_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 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; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test -n "$PCAP_CONFIG"; then # # The libpcap directory has a pcap-config script. # Use it to get any additioal libraries needed # to link with the libpcap archive library in # that directory. # # 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!)." # additional_libs=`"$PCAP_CONFIG" --additional-libs --static` libpcap="$libpcap $additional_libs" fi fi LIBS="$libpcap $LIBS" if ! test -n "$PCAP_CONFIG" ; then # # We don't have pcap-config; find out any additional link flags # we need. (If we have 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; } if test -f $pseexe ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "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" ;; esac fi ac_fn_c_check_func "$LINENO" "pcap_loop" "ac_cv_func_pcap_loop" if test "x$ac_cv_func_pcap_loop" = xyes; then : else as_fn_error $? "Report this to tcpdump-workers@lists.tcpdump.org, 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 - 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 : - -$as_echo "#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 - -fi -done - - -else - - case " $LIBOBJS " in - *" datalinks.$ac_objext "* ) ;; - *) LIBOBJS="$LIBOBJS datalinks.$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 - -fi -done - - 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 : - - -$as_echo "#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 : - -$as_echo "#define HAVE_PCAP_DATALINK_VAL_TO_DESCRIPTION 1" >>confdefs.h - -else - - case " $LIBOBJS " in - *" dlnames.$ac_objext "* ) ;; - *) LIBOBJS="$LIBOBJS dlnames.$ac_objext" - ;; -esac - - -fi - - -else - - case " $LIBOBJS " in - *" dlnames.$ac_objext "* ) ;; - *) LIBOBJS="$LIBOBJS dlnames.$ac_objext" - ;; -esac - - -fi - - - 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 - -fi -done - - - 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 - -else - - case " $LIBOBJS " in - *" pcap_dump_ftell.$ac_objext "* ) ;; - *) LIBOBJS="$LIBOBJS pcap_dump_ftell.$ac_objext" - ;; -esac - - -fi - - - # # Check for these after AC_LBL_LIBPCAP, so we link with the appropriate # libraries (e.g., "-lsocket -lnsl" on Solaris). # # We don't use AC_REPLACE_FUNCS because that uses AC_CHECK_FUNCS which # use AC_CHECK_FUNC which doesn't let us specify the right #includes # to make this work on BSD/OS 4.x. BSD/OS 4.x ships with the BIND8 # resolver, and the way it defines inet_{ntop,pton} is rather strange; # it does not ship with a libc symbol "inet_ntop()", it ships with # "_inet_ntop()", and has a #define macro in one of the system headers # to rename it. # { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_ntop" >&5 $as_echo_n "checking for inet_ntop... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { char src[4], dst[128]; inet_ntop(AF_INET, src, dst, sizeof(dst)); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } case " $LIBOBJS " in *" inet_ntop.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS inet_ntop.$ac_objext" ;; esac fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_pton" >&5 $as_echo_n "checking for inet_pton... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { char src[128], dst[4]; inet_pton(AF_INET, src, dst); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } case " $LIBOBJS " in *" inet_pton.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS inet_pton.$ac_objext" ;; esac fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_aton" >&5 $as_echo_n "checking for inet_aton... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main () { char src[128]; struct in_addr dst; inet_aton(src, &dst); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } case " $LIBOBJS " in *" inet_aton.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS inet_aton.$ac_objext" ;; esac fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext # # Check for these after AC_LBL_LIBPCAP, for the same reason. # # You are in a twisty little maze of UN*Xes, all different. # Some might not have ether_ntohost(). # Some might have it, but not declare it in any header file. # Some might have it, but declare it in . # Some might have it, but declare it in # (And some might have it but document it as something declared in # , although appears to work.) # # Before you is a C compiler. # 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 : ac_cv_buggy_ether_ntohost="not while cross-compiling" else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include 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 : ac_cv_buggy_ether_ntohost=no else 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; } if test "$ac_cv_buggy_ether_ntohost" = "no"; then $as_echo "#define USE_ETHER_NTOHOST 1" >>confdefs.h fi fi done if test "$ac_cv_func_ether_ntohost" = yes -a \ "$ac_cv_buggy_ether_ntohost" = "no"; then # # OK, we have ether_ntohost(). Do we have ? # if test "$ac_cv_header_netinet_if_ether_h" = yes; then # # Yes. Does it declare ether_ntohost()? # ac_fn_c_check_decl "$LINENO" "ether_ntohost" "ac_cv_have_decl_ether_ntohost" " #include #include #include #include struct mbuf; struct rtentry; #include #include " if test "x$ac_cv_have_decl_ether_ntohost" = xyes; then : $as_echo "#define NETINET_IF_ETHER_H_DECLARES_ETHER_NTOHOST /**/" >>confdefs.h fi fi # # Did that succeed? # if test "$ac_cv_have_decl_ether_ntohost" != yes; then # # No, how about , as on Linux? # for ac_header in netinet/ether.h do : ac_fn_c_check_header_mongrel "$LINENO" "netinet/ether.h" "ac_cv_header_netinet_ether_h" "$ac_includes_default" if test "x$ac_cv_header_netinet_ether_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_NETINET_ETHER_H 1 _ACEOF fi done if test "$ac_cv_header_netinet_ether_h" = yes; then # # We have it - does it 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" " #include " if test "x$ac_cv_have_decl_ether_ntohost" = xyes; then : $as_echo "#define NETINET_ETHER_H_DECLARES_ETHER_NTOHOST /**/" >>confdefs.h fi fi fi # # Is ether_ntohost() declared? # if test "$ac_cv_have_decl_ether_ntohost" != yes; then # # No, we'll have to declare it ourselves. # Do we have "struct ether_addr"? # ac_fn_c_check_type "$LINENO" "struct ether_addr" "ac_cv_type_struct_ether_addr" " #include #include #include #include struct mbuf; struct rtentry; #include #include " if test "x$ac_cv_type_struct_ether_addr" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRUCT_ETHER_ADDR 1 _ACEOF fi $as_echo "#define HAVE_DECL_ETHER_NTOHOST 0" >>confdefs.h else $as_echo "#define HAVE_DECL_ETHER_NTOHOST 1" >>confdefs.h fi fi # 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 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 () { return dlpi_walk (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dlpi_dlpi_walk=yes else ac_cv_lib_dlpi_dlpi_walk=no fi rm -f core conftest.err conftest.$ac_objext \ 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 : LIBS="$LIBS -ldlpi" LDFLAGS="-L/lib $LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if sockaddr struct has sa_len member" >&5 $as_echo_n "checking if sockaddr struct has sa_len member... " >&6; } if ${ac_cv_sockaddr_has_sa_len+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ # include # include int main () { u_int i = sizeof(((struct sockaddr *)0)->sa_len) ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sockaddr_has_sa_len=yes else ac_cv_sockaddr_has_sa_len=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sockaddr_has_sa_len" >&5 $as_echo "$ac_cv_sockaddr_has_sa_len" >&6; } if test $ac_cv_sockaddr_has_sa_len = yes ; then $as_echo "#define HAVE_SOCKADDR_SA_LEN 1" >>confdefs.h fi if test "$ac_cv_sockaddr_has_sa_len" = no; then missing_includes=yes 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 : + + +$as_echo "#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 + +fi +done + + +else + + case " $LIBOBJS " in + *" datalinks.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS datalinks.$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 + +fi +done + +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 : + + +$as_echo "#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 : + +$as_echo "#define HAVE_PCAP_DATALINK_VAL_TO_DESCRIPTION 1" >>confdefs.h + +else + + case " $LIBOBJS " in + *" dlnames.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS dlnames.$ac_objext" + ;; +esac + + +fi + + +else + + case " $LIBOBJS " in + *" dlnames.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS dlnames.$ac_objext" + ;; +esac + + +fi + + +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 + +fi +done + + +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 + +else + + case " $LIBOBJS " in + *" pcap_dump_ftell.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS pcap_dump_ftell.$ac_objext" + ;; +esac + + +fi + + # # 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 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 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 -for ac_func in pcap_findalldevs pcap_dump_flush pcap_lib_version pcap_setdirection +# +# Check for a miscellaneous collection of functions which we use +# if we have them. +# +for ac_func in pcap_findalldevs pcap_dump_flush pcap_lib_version pcap_setdirection pcap_set_immediate_mode 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 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 " if test "x$ac_cv_type_pcap_if_t" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_PCAP_IF_T 1 _ACEOF fi CPPFLAGS="$savedcppflags" fi 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; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { extern char pcap_version[]; return (int)pcap_version; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_lbl_cv_pcap_version_defined=yes else ac_lbl_cv_pcap_version_defined=no fi rm -f core conftest.err conftest.$ac_objext \ 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 "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define HAVE_PCAP_VERSION 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi { $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; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { extern int pcap_debug; return pcap_debug; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_lbl_cv_pcap_debug_defined=yes else ac_lbl_cv_pcap_debug_defined=no fi rm -f core conftest.err conftest.$ac_objext \ 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; } $as_echo "#define HAVE_PCAP_DEBUG 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { extern int yydebug; return yydebug; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_lbl_cv_yydebug_defined=yes else ac_lbl_cv_yydebug_defined=no fi rm -f core conftest.err conftest.$ac_objext \ 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; } $as_echo "#define HAVE_YYDEBUG 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi 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 else 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 ;; 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 definitions for all the C99 specified-width types # (regardless of whether the environment is a C99 environment or not). # ac_fn_c_find_intX_t "$LINENO" "8" "ac_cv_c_int8_t" case $ac_cv_c_int8_t in #( no|yes) ;; #( *) cat >>confdefs.h <<_ACEOF #define int8_t $ac_cv_c_int8_t _ACEOF ;; esac ac_fn_c_find_intX_t "$LINENO" "16" "ac_cv_c_int16_t" case $ac_cv_c_int16_t in #( no|yes) ;; #( *) cat >>confdefs.h <<_ACEOF #define int16_t $ac_cv_c_int16_t _ACEOF ;; esac ac_fn_c_find_intX_t "$LINENO" "32" "ac_cv_c_int32_t" case $ac_cv_c_int32_t in #( no|yes) ;; #( *) cat >>confdefs.h <<_ACEOF #define int32_t $ac_cv_c_int32_t _ACEOF ;; esac ac_fn_c_find_intX_t "$LINENO" "64" "ac_cv_c_int64_t" case $ac_cv_c_int64_t in #( no|yes) ;; #( *) cat >>confdefs.h <<_ACEOF #define int64_t $ac_cv_c_int64_t _ACEOF ;; esac ac_fn_c_find_uintX_t "$LINENO" "8" "ac_cv_c_uint8_t" case $ac_cv_c_uint8_t in #( no|yes) ;; #( *) $as_echo "#define _UINT8_T 1" >>confdefs.h cat >>confdefs.h <<_ACEOF #define uint8_t $ac_cv_c_uint8_t _ACEOF ;; esac ac_fn_c_find_uintX_t "$LINENO" "16" "ac_cv_c_uint16_t" case $ac_cv_c_uint16_t in #( no|yes) ;; #( *) cat >>confdefs.h <<_ACEOF #define uint16_t $ac_cv_c_uint16_t _ACEOF ;; esac ac_fn_c_find_uintX_t "$LINENO" "32" "ac_cv_c_uint32_t" case $ac_cv_c_uint32_t in #( no|yes) ;; #( *) $as_echo "#define _UINT32_T 1" >>confdefs.h cat >>confdefs.h <<_ACEOF #define uint32_t $ac_cv_c_uint32_t _ACEOF ;; esac ac_fn_c_find_uintX_t "$LINENO" "64" "ac_cv_c_uint64_t" case $ac_cv_c_uint64_t in #( no|yes) ;; #( *) $as_echo "#define _UINT64_T 1" >>confdefs.h cat >>confdefs.h <<_ACEOF #define uint64_t $ac_cv_c_uint64_t _ACEOF ;; esac # +# 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 : + +$as_echo "#define HAVE_UINTPTR_T 1" >>confdefs.h + +else + 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 () +{ +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 : + +cat >>confdefs.h <<_ACEOF +#define uintptr_t $ac_type +_ACEOF + + ac_type= +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + test -z "$ac_type" && break + done +fi + + + +# # 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 " if test "x$ac_cv_type_u_int8_t" = xyes; then : else $as_echo "#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 " if test "x$ac_cv_type_u_int16_t" = xyes; then : else $as_echo "#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 " if test "x$ac_cv_type_u_int32_t" = xyes; then : else $as_echo "#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 " if test "x$ac_cv_type_u_int64_t" = xyes; then : else $as_echo "#define u_int64_t uint64_t" >>confdefs.h fi # # Check for # for ac_header in inttypes.h do : ac_fn_c_check_header_mongrel "$LINENO" "inttypes.h" "ac_cv_header_inttypes_h" "$ac_includes_default" if test "x$ac_cv_header_inttypes_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_INTTYPES_H 1 _ACEOF # # OK, we have inttypes.h, but does it define all the PRI[doxu]64 macros? # Some systems have an inttypes.h that doesn't define all of them. # { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether inttypes.h defines the PRI[doxu]64 macros" >&5 $as_echo_n "checking whether inttypes.h defines the PRI[doxu]64 macros... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include main() { printf("%" PRId64 "\n", (uint64_t)1); printf("%" PRIo64 "\n", (uint64_t)1); printf("%" PRIx64 "\n", (uint64_t)1); printf("%" PRIu64 "\n", (uint64_t)1); } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } ac_lbl_inttypes_h_defines_formats=yes else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ac_lbl_inttypes_h_defines_formats=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext else # # We don't have inttypes.h, so it obviously can't define those # macros. # ac_lbl_inttypes_h_defines_formats=no fi done if test "$ac_lbl_inttypes_h_defines_formats" = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether %lx can be used to format 64-bit integers" >&5 $as_echo_n "checking whether %lx can be used to format 64-bit integers... " >&6; } if test "$cross_compiling" = yes; then : { { $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 test program while cross compiling See \`config.log' for more details" "$LINENO" 5; } else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ # ifdef HAVE_INTTYPES_H #include # endif #include #include main() { uint64_t t = 1; char strbuf[16+1]; sprintf(strbuf, "%016lx", t << 32); if (strcmp(strbuf, "0000000100000000") == 0) exit(0); else exit(1); } _ACEOF if ac_fn_c_try_run "$LINENO"; then : $as_echo "#define PRId64 \"ld\"" >>confdefs.h $as_echo "#define PRIo64 \"lo\"" >>confdefs.h $as_echo "#define PRIx64 \"lx\"" >>confdefs.h $as_echo "#define PRIu64 \"lu\"" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether %llx can be used to format 64-bit integers" >&5 $as_echo_n "checking whether %llx can be used to format 64-bit integers... " >&6; } if test "$cross_compiling" = yes; then : { { $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 test program while cross compiling See \`config.log' for more details" "$LINENO" 5; } else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ # ifdef HAVE_INTTYPES_H #include # endif #include #include main() { uint64_t t = 1; char strbuf[16+1]; sprintf(strbuf, "%016llx", t << 32); if (strcmp(strbuf, "0000000100000000") == 0) exit(0); else exit(1); } _ACEOF if ac_fn_c_try_run "$LINENO"; then : $as_echo "#define PRId64 \"lld\"" >>confdefs.h $as_echo "#define PRIo64 \"llo\"" >>confdefs.h $as_echo "#define PRIx64 \"llx\"" >>confdefs.h $as_echo "#define PRIu64 \"llu\"" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether %Lx can be used to format 64-bit integers" >&5 $as_echo_n "checking whether %Lx can be used to format 64-bit integers... " >&6; } if test "$cross_compiling" = yes; then : { { $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 test program while cross compiling See \`config.log' for more details" "$LINENO" 5; } else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ # ifdef HAVE_INTTYPES_H #include # endif #include #include main() { uint64_t t = 1; char strbuf[16+1]; sprintf(strbuf, "%016Lx", t << 32); if (strcmp(strbuf, "0000000100000000") == 0) exit(0); else exit(1); } _ACEOF if ac_fn_c_try_run "$LINENO"; then : $as_echo "#define PRId64 \"Ld\"" >>confdefs.h $as_echo "#define PRIo64 \"Lo\"" >>confdefs.h $as_echo "#define PRIx64 \"Lx\"" >>confdefs.h $as_echo "#define PRIu64 \"Lu\"" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether %qx can be used to format 64-bit integers" >&5 $as_echo_n "checking whether %qx can be used to format 64-bit integers... " >&6; } if test "$cross_compiling" = yes; then : { { $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 test program while cross compiling See \`config.log' for more details" "$LINENO" 5; } else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ # ifdef HAVE_INTTYPES_H #include # endif #include #include main() { uint64_t t = 1; char strbuf[16+1]; sprintf(strbuf, "%016qx", t << 32); if (strcmp(strbuf, "0000000100000000") == 0) exit(0); else exit(1); } _ACEOF if ac_fn_c_try_run "$LINENO"; then : $as_echo "#define PRId64 \"qd\"" >>confdefs.h $as_echo "#define PRIo64 \"qo\"" >>confdefs.h $as_echo "#define PRIx64 \"qx\"" >>confdefs.h $as_echo "#define PRIu64 \"qu\"" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "neither %llx nor %Lx nor %qx worked on a 64-bit integer" "$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 fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi # # Check for some headers introduced in later versions of libpcap # and used by some printers. # # Those headers use the {u_}intN_t types, so we must do this after # we check for what's needed to get them defined. # savedcppflags="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $V_INCLS" for ac_header in pcap/bluetooth.h do : ac_fn_c_check_header_compile "$LINENO" "pcap/bluetooth.h" "ac_cv_header_pcap_bluetooth_h" "#include \"tcpdump-stdinc.h\" " if test "x$ac_cv_header_pcap_bluetooth_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_PCAP_BLUETOOTH_H 1 _ACEOF fi done for ac_header in pcap/nflog.h do : ac_fn_c_check_header_compile "$LINENO" "pcap/nflog.h" "ac_cv_header_pcap_nflog_h" "#include \"tcpdump-stdinc.h\" " if test "x$ac_cv_header_pcap_nflog_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_PCAP_NFLOG_H 1 _ACEOF fi done for ac_header in pcap/usb.h do : ac_fn_c_check_header_compile "$LINENO" "pcap/usb.h" "ac_cv_header_pcap_usb_h" "#include \"tcpdump-stdinc.h\" " if test "x$ac_cv_header_pcap_usb_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_PCAP_USB_H 1 _ACEOF fi done CPPFLAGS="$savedcppflags" 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 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=. 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_RANLIB="${ac_tool_prefix}ranlib" $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 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; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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 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=. 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_RANLIB="ranlib" $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 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; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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;} 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 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=. 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_AR="${ac_tool_prefix}ar" $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 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; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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 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=. 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_AR="ar" $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 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; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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;} 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 -Wall option" >&5 $as_echo_n "checking whether the compiler supports the -Wall option... " >&6; } save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors -Wall" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return 0 ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } CFLAGS="$save_CFLAGS" V_CCOPT="$V_CCOPT -Wall" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } CFLAGS="$save_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $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; } save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors -Wmissing-prototypes" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return 0 ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } CFLAGS="$save_CFLAGS" V_CCOPT="$V_CCOPT -Wmissing-prototypes" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } CFLAGS="$save_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $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; } save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors -Wstrict-prototypes" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return 0 ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } CFLAGS="$save_CFLAGS" V_CCOPT="$V_CCOPT -Wstrict-prototypes" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } CFLAGS="$save_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $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; } save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors -Wwrite-strings" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return 0 ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } CFLAGS="$save_CFLAGS" V_CCOPT="$V_CCOPT -Wwrite-strings" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } CFLAGS="$save_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $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; } save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors -Wpointer-arith" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return 0 ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } CFLAGS="$save_CFLAGS" V_CCOPT="$V_CCOPT -Wpointer-arith" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } CFLAGS="$save_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $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; } save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors -W" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { return 0 ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } CFLAGS="$save_CFLAGS" V_CCOPT="$V_CCOPT -W" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } CFLAGS="$save_CFLAGS" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext 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; } 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 echo "$CC" $ac_lbl_dependency_flag conftest.c >&5 if "$CC" $ac_lbl_dependency_flag conftest.c >/dev/null 2>&1; 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; } DEPENDENCY_CFLAG="$ac_lbl_dependency_flag" MKDEP='${srcdir}/mkdep' else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "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; } # # 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 else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: can't find $name" >&5 $as_echo "$as_me: WARNING: can't find $name" >&2;} fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if sockaddr struct has the sa_len member" >&5 $as_echo_n "checking if sockaddr struct has the sa_len member... " >&6; } if ${ac_cv_lbl_sockaddr_has_sa_len+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ # include # include int main () { u_int i = sizeof(((struct sockaddr *)0)->sa_len) ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_lbl_sockaddr_has_sa_len=yes else ac_cv_lbl_sockaddr_has_sa_len=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_sockaddr_has_sa_len" >&5 $as_echo "$ac_cv_lbl_sockaddr_has_sa_len" >&6; } if test $ac_cv_lbl_sockaddr_has_sa_len = yes ; then $as_echo "#define HAVE_SOCKADDR_SA_LEN 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if unaligned accesses fail" >&5 $as_echo_n "checking if unaligned accesses fail... " >&6; } if ${ac_cv_lbl_unaligned_fail+:} false; then : $as_echo_n "(cached) " >&6 else case "$host_cpu" in # # These are CPU types where: # # the CPU faults on an unaligned access, but at least some # OSes that support that CPU catch the fault and simulate # the unaligned access (e.g., Alpha/{Digital,Tru64} UNIX) - # the simulation is slow, so we don't want to use it; # # the CPU, I infer (from the old # # XXX: should also check that they don't do weird things (like on arm) # # comment) doesn't fault on unaligned accesses, but doesn't # do a normal unaligned fetch, either (e.g., presumably, ARM); # # for whatever reason, the test program doesn't work # (this has been claimed to be the case for several of those # CPUs - I don't know what the problem is; the problem # was reported as "the test program dumps core" for SuperH, # but that's what the test program is *supposed* to do - # it dumps core before it writes anything, so the test # for an empty output file should find an empty output # file and conclude that unaligned accesses don't work). # # This run-time test won't work if you're cross-compiling, so # in order to support cross-compiling for a particular CPU, # we have to wire in the list of CPU types anyway, as far as # I know, so perhaps we should just have a set of CPUs on # which we know it doesn't work, a set of CPUs on which we # know it does work, and have the script just fail on other # cpu types and update it when such a failure occurs. # alpha*|arm*|bfin*|hp*|mips*|sh*|sparc*|ia64|nv1) ac_cv_lbl_unaligned_fail=yes ;; *) cat >conftest.c < # include # include unsigned char a[5] = { 1, 2, 3, 4, 5 }; main() { unsigned int i; pid_t pid; int status; /* avoid "core dumped" message */ pid = fork(); if (pid < 0) exit(2); if (pid > 0) { /* parent */ pid = waitpid(pid, &status, 0); if (pid < 0) exit(3); exit(!WIFEXITED(status)); } /* child */ i = *(unsigned int *)&a[1]; printf("%d\n", i); exit(0); } EOF ${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS \ conftest.c $LIBS >/dev/null 2>&1 if test ! -x conftest ; then ac_cv_lbl_unaligned_fail=yes else ./conftest >conftest.out if test ! -s conftest.out ; then ac_cv_lbl_unaligned_fail=yes else ac_cv_lbl_unaligned_fail=no fi fi rm -f -r conftest* core core.conftest ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_unaligned_fail" >&5 $as_echo "$ac_cv_lbl_unaligned_fail" >&6; } if test $ac_cv_lbl_unaligned_fail = yes ; then $as_echo "#define LBL_ALIGN 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for h_errno" >&5 $as_echo_n "checking for h_errno... " >&6; } if ${ac_cv_var_h_errno+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ # include # include int main () { int foo = h_errno; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_var_h_errno=yes else ac_cv_var_h_errno=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_var_h_errno" >&5 $as_echo "$ac_cv_var_h_errno" >&6; } if test "$ac_cv_var_h_errno" = "yes"; then $as_echo "#define HAVE_H_ERRNO 1" >>confdefs.h fi # Check for OpenSSL libcrypto { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use OpenSSL libcrypto" >&5 $as_echo_n "checking whether to use OpenSSL 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 : withval=$with_crypto; if test $withval = no then want_libcrypto=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } elif test $withval = yes then want_libcrypto=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi else # # Use libcrypto if it's present, otherwise don't. # want_libcrypto=ifavailable { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, if available" >&5 $as_echo "yes, if available" >&6; } fi if test "$want_libcrypto" != "no"; 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 else ac_check_lib_save_LIBS=$LIBS LIBS="-lcrypto $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 DES_cbc_encrypt (); int main () { return DES_cbc_encrypt (); ; 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 fi rm -f core conftest.err conftest.$ac_objext \ 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" fi 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 +_ACEOF + +fi + +done + +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; } +# 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 : + 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; } + elif test $withval = yes + then + want_libcap_ng=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + fi + +else + + # + # 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; } + +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 + 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 () +{ +return capng_change_id (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_cap_ng_capng_change_id=yes +else + ac_cv_lib_cap_ng_capng_change_id=no +fi +rm -f core conftest.err conftest.$ac_objext \ + 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 + + 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 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), # 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; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else 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]/* | \ /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 test $ac_prog = install && 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 # 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" && 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" 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 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; } # 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_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;} ;; 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 || &/ 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;} 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;} 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"` # 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;} 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 : 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 case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi 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 # The user is always right. if test "${PATH_SEPARATOR+set}" != set; 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 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 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 fi $as_echo "$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 : eval 'as_fn_append () { eval $1+=\$2 }' else 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 : eval 'as_fn_arith () { as_val=$(( $* )) }' else 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" | 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 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 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=$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" | 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 $as_me, which was generated by GNU Autoconf 2.69. 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 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ config.status configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 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 ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$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"` ;; '') 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"` ;; 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 ;; -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 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" } >&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" ;; "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 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` 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 ' >$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 ' >$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 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' `' 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;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$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" | 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|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$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;} _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' 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' 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 */" \ && 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;} 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 */" \ && 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;} ;; esac case $ac_file$ac_mode in "default-1":C) if test -f .devel; then echo timestamp > stamp-h cat Makefile-devel-adds >> Makefile make depend 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;} fi exit 0 Index: head/contrib/tcpdump/configure.in =================================================================== --- head/contrib/tcpdump/configure.in (revision 285274) +++ head/contrib/tcpdump/configure.in (revision 285275) @@ -1,1075 +1,1174 @@ 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 # # http://ftp.gnu.org/gnu/config/README # # for the URLs to use to fetch new versions of config.guess and # config.sub. # AC_PREREQ(2.61) AC_INIT(tcpdump.c) AC_CANONICAL_HOST AC_LBL_C_INIT_BEFORE_CC(V_INCLS) AC_PROG_CC AC_LBL_C_INIT(V_CCOPT, V_INCLS) AC_LBL_C_INLINE AC_C___ATTRIBUTE__ if test "$ac_cv___attribute__" = "yes"; then AC_C___ATTRIBUTE___UNUSED AC_C___ATTRIBUTE___NORETURN_FUNCTION_POINTER AC_C___ATTRIBUTE___FORMAT if test "$ac_cv___attribute___format" = "yes"; then AC_C___ATTRIBUTE___FORMAT_FUNCTION_POINTER fi fi AC_CHECK_HEADERS(fcntl.h rpc/rpc.h rpc/rpcent.h netdnet/dnetdb.h) AC_CHECK_HEADERS(net/pfvar.h, , , [#include #include #include ]) if test "$ac_cv_header_net_pfvar_h" = yes; then LOCALSRC="print-pflog.c $LOCALSRC" fi AC_CHECK_HEADERS(netinet/if_ether.h, , , [#include #include ]) if test "$ac_cv_header_netinet_if_ether_h" != yes; then # # The simple test didn't work. # Do we need to include first? # Unset ac_cv_header_netinet_if_ether_h so we don't # treat the previous failure as a cached value and # suppress the next test. # AC_MSG_NOTICE([Rechecking with some additional includes]) unset ac_cv_header_netinet_if_ether_h AC_CHECK_HEADERS(netinet/if_ether.h, , , [#include #include #include struct mbuf; struct rtentry; #include ]) fi AC_HEADER_TIME case "$host_os" in darwin*) AC_ARG_ENABLE(universal, AC_HELP_STRING([--disable-universal],[don't build universal on OS X])) 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 AC_ARG_WITH(smi, [ --with-smi link with libsmi (allows to load MIBs on the fly to decode SNMP packets. [default=yes] --without-smi don't link with libsmi],, 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( [ /* libsmi available check */ #include 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", ¤t, &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 possibly-buggy SMB printer]) AC_ARG_ENABLE(smb, [ --enable-smb enable possibly-buggy SMB printer [default=yes] --disable-smb disable possibly-buggy SMB printer],, enableval=yes) case "$enableval" in yes) AC_MSG_RESULT(yes) AC_WARN([The SMB printer may have exploitable buffer overflows!!!]) AC_DEFINE(TCPDUMP_DO_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(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(sandbox-capsicum, [ --with-sandbox-capsicum ]) +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. # -# All of them must be available in order to enable capsicum sandboxing. +# 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 - AC_CHECK_FUNCS(cap_enter cap_rights_init cap_rights_limit cap_ioctls_limit openat, + 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) 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 # # We must check this before checking whether to enable IPv6, because, # on some platforms (such as SunOS 5.x), the test program requires # the extra networking libraries. # AC_LBL_LIBRARY_NET AC_MSG_CHECKING([whether to enable ipv6]) AC_ARG_ENABLE(ipv6, [ --enable-ipv6 enable ipv6 (with ipv4) support --disable-ipv6 disable ipv6 support], [ case "$enableval" in yes) AC_MSG_RESULT(yes) - LOCALSRC="print-ip6.c print-ip6opts.c print-mobility.c print-ripng.c print-icmp6.c print-frag6.c print-rt6.c print-ospf6.c print-dhcp6.c print-babel.c $LOCALSRC" + LOCALSRC="print-ip6opts.c print-mobility.c print-ripng.c print-icmp6.c print-frag6.c print-rt6.c print-ospf6.c print-dhcp6.c print-babel.c $LOCALSRC" AC_DEFINE(INET6, 1, [Define if you enable IPv6 support]) ipv6=yes ;; *) AC_MSG_RESULT(no) ipv6=no ;; esac ], AC_COMPILE_IFELSE( [ AC_LANG_SOURCE( [[/* AF_INET6 available check */ #include #include #include #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) - LOCALSRC="print-ip6.c print-ip6opts.c print-mobility.c print-ripng.c print-icmp6.c print-frag6.c print-rt6.c print-ospf6.c print-dhcp6.c print-babel.c $LOCALSRC" + LOCALSRC="print-ip6opts.c print-mobility.c print-ripng.c print-icmp6.c print-frag6.c print-rt6.c print-ospf6.c print-dhcp6.c print-babel.c $LOCALSRC" AC_DEFINE(INET6, 1, [Define if you enable IPv6 support]) ipv6=yes], [ AC_MSG_RESULT(no) ipv6=no], [ 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 #ifdef IPV6_INRIA_VERSION yes #endif], [ipv6type=$i; CFLAGS="-DINET6 $CFLAGS"]) ;; kame) dnl http://www.kame.net/ AC_EGREP_CPP(yes, [#include #ifdef __KAME__ yes #endif], [ipv6type=$i; ipv6lib=inet6; ipv6libdir=/usr/local/v6/lib; ipv6trylibc=yes; CFLAGS="-DINET6 $CFLAGS"]) ;; linux-glibc) dnl http://www.v6.linux.or.jp/ AC_EGREP_CPP(yes, [#include #if defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1 yes #endif], [ipv6type=$i; CFLAGS="-DINET6 $CFLAGS"]) ;; 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="-DINET6 -I/usr/inet6/include $CFLAGS" fi ;; toshiba) AC_EGREP_CPP(yes, [#include #ifdef _TOSHIBA_INET6 yes #endif], [ipv6type=$i; ipv6lib=inet6; ipv6libdir=/usr/local/v6/lib; CFLAGS="-DINET6 $CFLAGS"]) ;; v6d) AC_EGREP_CPP(yes, [#include #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 #ifdef _ZETA_MINAMI_INET6 yes #endif], [ipv6type=$i; ipv6lib=inet6; ipv6libdir=/usr/local/v6/lib; CFLAGS="-DINET6 $CFLAGS"]) ;; 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 if test "$ipv6" = "yes"; then # # XXX - on Tru64 UNIX 5.1, there is no "getaddrinfo()" # function in libc; there are "ngetaddrinfo()" and # "ogetaddrinfo()" functions, and #defines # "getaddrinfo" to be either "ngetaddrinfo" or # "ogetaddrinfo", depending on whether _SOCKADDR_LEN # or _XOPEN_SOURCE_EXTENDED are defined or not. # # So this test doesn't work on Tru64 5.1, and possibly # on other 5.x releases. This causes the configure # script to become confused, and results in libpcap # being unbuildable. # AC_SEARCH_LIBS(getaddrinfo, socket, [dnl AC_MSG_CHECKING(getaddrinfo bug) AC_CACHE_VAL(td_cv_buggygetaddrinfo, [AC_TRY_RUN([ #include #include #include #include #include main() { int passive, gaierr, inet4 = 0, inet6 = 0; struct addrinfo hints, *ai, *aitop; char straddr[INET6_ADDRSTRLEN], strport[16]; for (passive = 0; passive <= 1; passive++) { memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_flags = passive ? AI_PASSIVE : 0; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; if ((gaierr = getaddrinfo(NULL, "54321", &hints, &aitop)) != 0) { (void)gai_strerror(gaierr); goto bad; } for (ai = aitop; ai; ai = ai->ai_next) { if (ai->ai_addr == NULL || ai->ai_addrlen == 0 || getnameinfo(ai->ai_addr, ai->ai_addrlen, straddr, sizeof(straddr), strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { goto bad; } switch (ai->ai_family) { case AF_INET: if (strcmp(strport, "54321") != 0) { goto bad; } if (passive) { if (strcmp(straddr, "0.0.0.0") != 0) { goto bad; } } else { if (strcmp(straddr, "127.0.0.1") != 0) { goto bad; } } inet4++; break; case AF_INET6: if (strcmp(strport, "54321") != 0) { goto bad; } if (passive) { if (strcmp(straddr, "::") != 0) { goto bad; } } else { if (strcmp(straddr, "::1") != 0) { goto bad; } } inet6++; break; case AF_UNSPEC: goto bad; break; #ifdef AF_UNIX case AF_UNIX: #else #ifdef AF_LOCAL case AF_LOCAL: #endif #endif default: /* another family support? */ break; } } } /* supported family should be 2, unsupported family should be 0 */ if (!(inet4 == 0 || inet4 == 2)) goto bad; if (!(inet6 == 0 || inet6 == 2)) goto bad; if (aitop) freeaddrinfo(aitop); exit(0); bad: if (aitop) freeaddrinfo(aitop); exit(1); } ], td_cv_buggygetaddrinfo=no, td_cv_buggygetaddrinfo=yes, - td_cv_buggygetaddrinfo=yes)]) + td_cv_buggygetaddrinfo=unknown)]) if test "$td_cv_buggygetaddrinfo" = no; then AC_MSG_RESULT(good) + elif test "$td_cv_buggygetaddrinfo" = unknown; then + AC_MSG_RESULT([unknown (cross-compiling)]) else AC_MSG_RESULT(buggy) fi if test "$td_cv_buggygetaddrinfo" = "yes"; then # # XXX - it doesn't appear that "ipv6type" can ever be # set to "linux". Should this be testing for # "linux-glibc", or for that *or* "linux-libinet6"? # If the latter, note that "linux-libinet6" is also # the type given to some non-Linux OSes. # if test "$ipv6type" != "linux"; then echo 'Fatal: You must get working getaddrinfo() function.' echo ' or you can specify "--disable-ipv6"'. exit 1 else echo 'Warning: getaddrinfo() implementation on your system seems be buggy.' echo ' Better upgrade your system library to newest version' echo ' of GNU C library (aka glibc).' fi fi ]) AC_REPLACE_FUNCS(getnameinfo) fi AC_CACHE_CHECK([for dnet_htoa declaration in netdnet/dnetdb.h], [td_cv_decl_netdnet_dnetdb_h_dnet_htoa], [AC_EGREP_HEADER(dnet_htoa, netdnet/dnetdb.h, td_cv_decl_netdnet_dnetdb_h_dnet_htoa=yes, td_cv_decl_netdnet_dnetdb_h_dnet_htoa=no)]) if test "$td_cv_decl_netdnet_dnetdb_h_dnet_htoa" = yes; then AC_DEFINE(HAVE_NETDNET_DNETDB_H_DNET_HTOA, 1, [define if you have a dnet_htoa declaration in ]) fi dnl dnl Checks for addrinfo structure AC_STRUCT_ADDRINFO(ac_cv_addrinfo) if test "$ac_cv_addrinfo" = no; then missing_includes=yes fi dnl dnl Checks for NI_MAXSERV AC_NI_MAXSERV(ac_cv_maxserv) if test "$ac_cv_maxserv" = no; then missing_includes=yes fi dnl dnl Checks for NI_NAMEREQD AC_NI_NAMEREQD(ac_cv_namereqd) if test "$ac_cv_namereqd" = no; then missing_includes=yes fi AC_REPLACE_FUNCS(vfprintf strcasecmp strlcat strlcpy strdup strsep getopt_long) AC_CHECK_FUNCS(fork vfork strftime) AC_CHECK_FUNCS(setlinebuf alarm) needsnprintf=no AC_CHECK_FUNCS(vsnprintf snprintf,, [needsnprintf=yes]) if test $needsnprintf = yes; then AC_LIBOBJ(snprintf) fi AC_LBL_TYPE_SIGNAL AC_SEARCH_LIBS(dnet_htoa, dnet, AC_DEFINE(HAVE_DNET_HTOA, 1, [define if you have the dnet_htoa function])) 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()])) dnl AC_CHECK_LIB(z, uncompress) dnl AC_CHECK_HEADERS(zlib.h) 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). # # We don't use AC_REPLACE_FUNCS because that uses AC_CHECK_FUNCS which # use AC_CHECK_FUNC which doesn't let us specify the right #includes # to make this work on BSD/OS 4.x. BSD/OS 4.x ships with the BIND8 # resolver, and the way it defines inet_{ntop,pton} is rather strange; # it does not ship with a libc symbol "inet_ntop()", it ships with # "_inet_ntop()", and has a #define macro in one of the system headers # to rename it. # dnl AC_TRY_COMPILE(inet_ntop inet_pton inet_aton) AC_MSG_CHECKING(for inet_ntop) AC_TRY_LINK([#include #include #include #include ], [char src[4], dst[128]; inet_ntop(AF_INET, src, dst, sizeof(dst));], [AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no) AC_LIBOBJ(inet_ntop)]) AC_MSG_CHECKING(for inet_pton) AC_TRY_LINK([#include #include #include #include ], [char src[128], dst[4]; inet_pton(AF_INET, src, dst);], [AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no) AC_LIBOBJ(inet_pton)]) AC_MSG_CHECKING(for inet_aton) AC_TRY_LINK([#include #include #include ], [char src[128]; struct in_addr dst; inet_aton(src, &dst);], [AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no) AC_LIBOBJ(inet_aton)]) # # Check for these after AC_LBL_LIBPCAP, for the same reason. # # You are in a twisty little maze of UN*Xes, all different. # Some might not have ether_ntohost(). # Some might have it, but not declare it in any header file. # Some might have it, but declare it in . # Some might have it, but declare it in # (And some might have it but document it as something declared in # , although appears to work.) # # 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([ #include #include #include #include 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(). Do we have ? # if test "$ac_cv_header_netinet_if_ether_h" = yes; then # # Yes. Does it declare 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 #include #include #include struct mbuf; struct rtentry; #include #include ]) fi # # Did that succeed? # if test "$ac_cv_have_decl_ether_ntohost" != yes; then # # No, how about , as on Linux? # AC_CHECK_HEADERS(netinet/ether.h) if test "$ac_cv_header_netinet_ether_h" = yes; then # # We have it - does it 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,, [Define to 1 if netinet/ether.h declares `ether_ntohost']) ],, [ #include ]) fi fi # # Is ether_ntohost() declared? # if test "$ac_cv_have_decl_ether_ntohost" != yes; then # # No, we'll have to declare it ourselves. # Do we have "struct ether_addr"? # AC_CHECK_TYPES(struct ether_addr,,, [ #include #include #include #include struct mbuf; struct rtentry; #include #include ]) AC_DEFINE(HAVE_DECL_ETHER_NTOHOST, 0, [Define to 1 if you have the declaration of `ether_ntohost', and to 0 if you don't.]) else AC_DEFINE(HAVE_DECL_ETHER_NTOHOST, 1, [Define to 1 if you have the declaration of `ether_ntohost', and to 0 if you don't.]) fi fi # libdlpi is needed for Solaris 11 and later. AC_CHECK_LIB(dlpi, dlpi_walk, LIBS="$LIBS -ldlpi" LDFLAGS="-L/lib $LDFLAGS", ,-L/lib) dnl portability macros for getaddrinfo/getnameinfo dnl dnl Check for sa_len AC_CHECK_SA_LEN(ac_cv_sockaddr_has_sa_len) if test "$ac_cv_sockaddr_has_sa_len" = no; then missing_includes=yes fi +dnl +dnl Check for "pcap_list_datalinks()", "pcap_set_datalink()", +dnl and "pcap_datalink_name_to_val()", and use substitute versions +dnl if they're not present. +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) + ]) +AC_CHECK_FUNCS(pcap_set_datalink) +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_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) + +dnl +dnl Check for "pcap_dump_ftell()" and use a substitute version +dnl if it's not present. +dnl +AC_CHECK_FUNC(pcap_dump_ftell, + AC_DEFINE(HAVE_PCAP_DUMP_FTELL, 1, + [define if libpcap has pcap_dump_ftell()]), + [ + AC_LIBOBJ(pcap_dump_ftell) + ]) + # # 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 -AC_CHECK_FUNCS(pcap_findalldevs pcap_dump_flush pcap_lib_version pcap_setdirection) +# +# Check for a miscellaneous collection of functions which we use +# if we have them. +# +AC_CHECK_FUNCS(pcap_findalldevs pcap_dump_flush pcap_lib_version pcap_setdirection pcap_set_immediate_mode) if test $ac_cv_func_pcap_findalldevs = "yes" ; then dnl Check for Mac OS X, which may ship pcap.h from 0.6 but libpcap may dnl be 0.8; this means that lib has pcap_findalldevs but header doesn't dnl have pcap_if_t. savedcppflags="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $V_INCLS" AC_CHECK_TYPES(pcap_if_t, , , [#include ]) CPPFLAGS="$savedcppflags" fi if test $ac_cv_func_pcap_lib_version = "no" ; then AC_MSG_CHECKING(whether pcap_version is defined by libpcap) AC_TRY_LINK([], [ extern char pcap_version[]; return (int)pcap_version; ], 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_MSG_RESULT(yes) AC_DEFINE(HAVE_PCAP_VERSION, 1, [define if libpcap has pcap_version]) else AC_MSG_RESULT(no) fi fi AC_MSG_CHECKING(whether pcap_debug is defined by libpcap) AC_TRY_LINK([], [ extern int pcap_debug; return pcap_debug; ], 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([], [ extern int yydebug; return yydebug; ], 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 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 definitions for all the C99 specified-width types # (regardless of whether the environment is a C99 environment or not). # AC_TYPE_INT8_T AC_TYPE_INT16_T AC_TYPE_INT32_T AC_TYPE_INT64_T AC_TYPE_UINT8_T AC_TYPE_UINT16_T AC_TYPE_UINT32_T AC_TYPE_UINT64_T # +# 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 + +# # 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 ]) 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 ]) 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 ]) 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 ]) # # Check for # AC_CHECK_HEADERS(inttypes.h, [ # # OK, we have inttypes.h, but does it define all the PRI[doxu]64 macros? # Some systems have an inttypes.h that doesn't define all of them. # AC_MSG_CHECKING([[whether inttypes.h defines the PRI[doxu]64 macros]]) AC_COMPILE_IFELSE( [ AC_LANG_SOURCE( [[ #include #include #include main() { printf("%" PRId64 "\n", (uint64_t)1); printf("%" PRIo64 "\n", (uint64_t)1); printf("%" PRIx64 "\n", (uint64_t)1); printf("%" PRIu64 "\n", (uint64_t)1); } ]]) ], [ AC_MSG_RESULT(yes) ac_lbl_inttypes_h_defines_formats=yes ], [ AC_MSG_RESULT(no) ac_lbl_inttypes_h_defines_formats=no ]) ], [ # # We don't have inttypes.h, so it obviously can't define those # macros. # ac_lbl_inttypes_h_defines_formats=no ]) if test "$ac_lbl_inttypes_h_defines_formats" = no; then AC_LBL_CHECK_64BIT_FORMAT(l, [ AC_LBL_CHECK_64BIT_FORMAT(ll, [ AC_LBL_CHECK_64BIT_FORMAT(L, [ AC_LBL_CHECK_64BIT_FORMAT(q, [ AC_MSG_ERROR([neither %llx nor %Lx nor %qx worked on a 64-bit integer]) ]) ]) ]) ]) fi # # Check for some headers introduced in later versions of libpcap # and used by some printers. # # Those headers use the {u_}intN_t types, so we must do this after # we check for what's needed to get them defined. # savedcppflags="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $V_INCLS" AC_CHECK_HEADERS(pcap/bluetooth.h,,,[#include "tcpdump-stdinc.h"]) AC_CHECK_HEADERS(pcap/nflog.h,,,[#include "tcpdump-stdinc.h"]) AC_CHECK_HEADERS(pcap/usb.h,,,[#include "tcpdump-stdinc.h"]) CPPFLAGS="$savedcppflags" AC_PROG_RANLIB AC_CHECK_TOOL([AR], [ar]) AC_LBL_DEVEL(V_CCOPT) AC_LBL_SOCKADDR_SA_LEN AC_LBL_UNALIGNED_ACCESS AC_VAR_H_ERRNO # Check for OpenSSL libcrypto AC_MSG_CHECKING(whether to use OpenSSL libcrypto) # Specify location for both includes and libraries. want_libcrypto=ifavailable AC_ARG_WITH(crypto, AS_HELP_STRING([--with-crypto], [use OpenSSL libcrypto @<:@default=yes, if available@:>@]), [ if test $withval = no then want_libcrypto=no AC_MSG_RESULT(no) elif test $withval = yes then want_libcrypto=yes AC_MSG_RESULT(yes) fi ],[ # # Use libcrypto if it's present, otherwise don't. # want_libcrypto=ifavailable AC_MSG_RESULT([yes, if available]) ]) if test "$want_libcrypto" != "no"; then AC_CHECK_LIB(crypto, DES_cbc_encrypt) AC_CHECK_HEADERS(openssl/evp.h) +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 echo timestamp > stamp-h cat Makefile-devel-adds >> Makefile make depend fi]) AC_OUTPUT(Makefile tcpdump.1) exit 0 Index: head/contrib/tcpdump/extract.h =================================================================== --- head/contrib/tcpdump/extract.h (revision 285274) +++ head/contrib/tcpdump/extract.h (revision 285275) @@ -1,217 +1,217 @@ /* * 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. */ /* * Macros to extract possibly-unaligned big-endian integral values. */ #ifdef LBL_ALIGN /* * The processor doesn't natively handle unaligned loads. */ #if defined(__GNUC__) && defined(HAVE___ATTRIBUTE__) && \ (defined(__alpha) || defined(__alpha__) || \ defined(__mips) || defined(__mips__)) /* * This is a GCC-compatible compiler and we have __attribute__, which * we assume that mean we have __attribute__((packed)), and this is * MIPS or Alpha, which has instructions that can help when doing * unaligned loads. * * 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 apppears 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 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 { uint32_t val; } __attribute__((packed)) unaligned_uint32_t; static inline uint16_t EXTRACT_16BITS(const void *p) { return ((uint16_t)ntohs(((const unaligned_uint16_t *)(p))->val)); } static inline uint32_t EXTRACT_32BITS(const void *p) { return ((uint32_t)ntohl(((const unaligned_uint32_t *)(p))->val)); } static inline uint64_t EXTRACT_64BITS(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)); } #else /* have to do it a byte at a time */ /* * 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. */ #define EXTRACT_16BITS(p) \ - ((uint16_t)((uint16_t)*((const uint8_t *)(p) + 0) << 8 | \ - (uint16_t)*((const uint8_t *)(p) + 1))) + ((uint16_t)(((uint16_t)(*((const uint8_t *)(p) + 0)) << 8) | \ + ((uint16_t)(*((const uint8_t *)(p) + 1)) << 0))) #define EXTRACT_32BITS(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))) + ((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_64BITS(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))) + ((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))) #endif /* must special-case unaligned accesses */ #else /* LBL_ALIGN */ /* * The processor natively handles unaligned loads, so we can just * cast the pointer and fetch through it. */ static inline uint16_t EXTRACT_16BITS(const void *p) { return ((uint16_t)ntohs(*(const uint16_t *)(p))); } static inline uint32_t EXTRACT_32BITS(const void *p) { return ((uint32_t)ntohl(*(const uint32_t *)(p))); } static inline uint64_t EXTRACT_64BITS(const void *p) { return ((uint64_t)(((uint64_t)ntohl(*((const uint32_t *)(p) + 0))) << 32 | \ ((uint64_t)ntohl(*((const uint32_t *)(p) + 1))) << 0)); } #endif /* LBL_ALIGN */ #define EXTRACT_24BITS(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))) + ((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_40BITS(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))) + ((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_48BITS(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))) + ((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_56BITS(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))) + ((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))) /* * Macros to extract possibly-unaligned little-endian integral values. * XXX - do loads on little-endian machines that support unaligned loads? */ #define EXTRACT_LE_8BITS(p) (*(p)) #define EXTRACT_LE_16BITS(p) \ - ((uint16_t)((uint16_t)*((const uint8_t *)(p) + 1) << 8 | \ - (uint16_t)*((const uint8_t *)(p) + 0))) + ((uint16_t)(((uint16_t)(*((const uint8_t *)(p) + 1)) << 8) | \ + ((uint16_t)(*((const uint8_t *)(p) + 0)) << 0))) #define EXTRACT_LE_32BITS(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))) + ((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_24BITS(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))) + ((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_64BITS(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))) + ((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))) Index: head/contrib/tcpdump/interface.h =================================================================== --- head/contrib/tcpdump/interface.h (revision 285274) +++ head/contrib/tcpdump/interface.h (revision 285275) @@ -1,218 +1,229 @@ /* * 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 /* snprintf et al */ #include #if HAVE_STDINT_H #include #endif #if !defined(HAVE_SNPRINTF) int snprintf(char *, size_t, const char *, ...) #ifdef __ATTRIBUTE___FORMAT_OK __attribute__((format(printf, 3, 4))) #endif /* __ATTRIBUTE___FORMAT_OK */ ; #endif /* !defined(HAVE_SNPRINTF) */ #if !defined(HAVE_VSNPRINTF) int vsnprintf(char *, size_t, const char *, va_list) #ifdef __ATTRIBUTE___FORMAT_OK __attribute__((format(printf, 3, 0))) #endif /* __ATTRIBUTE___FORMAT_OK */ ; #endif /* !defined(HAVE_VSNPRINTF) */ #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 #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 ESRC(ep) ((ep)->ether_shost) #define EDST(ep) ((ep)->ether_dhost) #ifndef NTOHL #define NTOHL(x) (x) = ntohl(x) #define NTOHS(x) (x) = ntohs(x) #define HTONL(x) (x) = htonl(x) #define HTONS(x) (x) = htons(x) #endif #endif extern char *program_name; /* used to generate self-identifying messages */ extern int32_t thiszone; /* seconds offset from gmt to local time */ /* * True if "l" bytes of "var" were captured. * * The "snapend - (l) <= snapend" checks to make sure "l" isn't so large * that "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 + * + * http://www.kb.cert.org/vuls/id/162289 */ -#define TTEST2(var, l) (snapend - (l) <= snapend && \ - (const u_char *)&(var) <= snapend - (l)) +#define TTEST2(var, l) \ + ((uintptr_t)snapend - (l) <= (uintptr_t)snapend && \ + (uintptr_t)&(var) <= (uintptr_t)snapend - (l)) /* True if "var" was captured */ #define TTEST(var) TTEST2(var, sizeof(var)) /* Bail if "l" bytes of "var" were not captured */ #define TCHECK2(var, l) if (!TTEST2(var, l)) goto trunc /* Bail if "var" was not captured */ #define TCHECK(var) TCHECK2(var, sizeof(var)) extern int mask2plen(uint32_t); 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) extern void error(const char *, ...) __attribute__((noreturn)) #ifdef __ATTRIBUTE___FORMAT_OK __attribute__((format (printf, 1, 2))) #endif /* __ATTRIBUTE___FORMAT_OK */ ; extern void warning(const char *, ...) #ifdef __ATTRIBUTE___FORMAT_OK __attribute__((format (printf, 1, 2))) #endif /* __ATTRIBUTE___FORMAT_OK */ ; extern char *read_infile(char *); extern char *copy_argv(char **); extern const char *dnname_string(u_short); extern const char *dnnum_string(u_short); /* 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); /* The printer routines. */ #include -extern char *q922_string(const u_char *); extern char *smb_errstr(int, int); extern const char *nt_errstr(uint32_t); #ifdef INET6 extern int mask62plen(const u_char *); #endif /*INET6*/ 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); #ifndef HAVE_BPF_DUMP struct bpf_program; extern void bpf_dump(const struct bpf_program *, int); #endif #include "netdissect.h" /* forward compatibility */ #ifndef NETDISSECT_REWORKED extern netdissect_options *gndo; #define bflag gndo->ndo_bflag #define eflag gndo->ndo_eflag #define fflag gndo->ndo_fflag #define jflag gndo->ndo_jflag #define Kflag gndo->ndo_Kflag #define nflag gndo->ndo_nflag #define Nflag gndo->ndo_Nflag #define Oflag gndo->ndo_Oflag #define pflag gndo->ndo_pflag #define qflag gndo->ndo_qflag #define Rflag gndo->ndo_Rflag #define sflag gndo->ndo_sflag #define Sflag gndo->ndo_Sflag #define tflag gndo->ndo_tflag #define Uflag gndo->ndo_Uflag #define uflag gndo->ndo_uflag #define vflag gndo->ndo_vflag #define xflag gndo->ndo_xflag #define Xflag gndo->ndo_Xflag #define Cflag gndo->ndo_Cflag #define Gflag gndo->ndo_Gflag #define Aflag gndo->ndo_Aflag #define Bflag gndo->ndo_Bflag #define Iflag gndo->ndo_Iflag #define suppress_default_print gndo->ndo_suppress_default_print #define packettype gndo->ndo_packettype #define sigsecret gndo->ndo_sigsecret #define Wflag gndo->ndo_Wflag #define WflagChars gndo->ndo_WflagChars #define Cflag_count gndo->ndo_Cflag_count #define Gflag_count gndo->ndo_Gflag_count #define Gflag_time gndo->ndo_Gflag_time #define Hflag gndo->ndo_Hflag #define snaplen gndo->ndo_snaplen #define snapend gndo->ndo_snapend extern void default_print(const u_char *, u_int); #endif Index: head/contrib/tcpdump/ip.h =================================================================== --- head/contrib/tcpdump/ip.h (revision 285274) +++ head/contrib/tcpdump/ip.h (revision 285275) @@ -1,164 +1,166 @@ /* * 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 TCPDUMP_IP_H #define TCPDUMP_IP_H +#include "tcpdump-stdinc.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 { uint8_t ip_vhl; /* header length, version */ #define IP_V(ip) (((ip)->ip_vhl & 0xf0) >> 4) #define IP_HL(ip) ((ip)->ip_vhl & 0x0f) uint8_t ip_tos; /* type of service */ uint16_t ip_len; /* total length */ uint16_t ip_id; /* identification */ uint16_t ip_off; /* fragment offset field */ #define IP_DF 0x4000 /* dont fragment flag */ #define IP_MF 0x2000 /* more fragments flag */ #define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ uint8_t ip_ttl; /* time to live */ uint8_t ip_p; /* protocol */ uint16_t ip_sum; /* checksum */ struct in_addr ip_src,ip_dst; /* source and dest address */ } UNALIGNED; #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 { uint8_t ipt_code; /* IPOPT_TS */ uint8_t ipt_len; /* size of structure (variable) */ uint8_t ipt_ptr; /* index of current entry */ 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 { uint32_t ipt_time[1]; struct ipt_ta { struct in_addr ipt_addr; uint32_t ipt_time; } ipt_ta[1]; } ipt_timestamp; } UNALIGNED; /* 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 /* TCPDUMP_IP_H */ Index: head/contrib/tcpdump/machdep.c =================================================================== --- head/contrib/tcpdump/machdep.c (revision 285274) +++ head/contrib/tcpdump/machdep.c (revision 285275) @@ -1,65 +1,74 @@ /* * 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 /* * XXX - all we need, on platforms other than DEC OSF/1 (a/k/a Digital UNIX, * a/k/a Tru64 UNIX), is "size_t", which is a standard C type; what do we * need to do to get it defined? This is clearly wrong, as we shouldn't * have to include UNIX or Windows system header files to get it. */ #include #ifndef HAVE___ATTRIBUTE__ #define __attribute__(x) #endif /* HAVE___ATTRIBUTE__ */ #ifdef __osf__ #include #include #if !defined(HAVE_SNPRINTF) int snprintf(char *, size_t, const char *, ...) #ifdef __ATTRIBUTE___FORMAT_OK __attribute__((format(printf, 3, 4))) #endif /* __ATTRIBUTE___FORMAT_OK */ ; #endif /* !defined(HAVE_SNPRINTF) */ #endif /* __osf__ */ #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); } Index: head/contrib/tcpdump/missing/strsep.c =================================================================== --- head/contrib/tcpdump/missing/strsep.c (revision 285274) +++ head/contrib/tcpdump/missing/strsep.c (revision 285275) @@ -1,78 +1,80 @@ /*- * 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 #endif #include #include +#include "interface.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) { register char *s; register const char *spanp; register 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 */ } Index: head/contrib/tcpdump/mkdep =================================================================== --- head/contrib/tcpdump/mkdep (revision 285274) +++ head/contrib/tcpdump/mkdep (revision 285275) @@ -1,115 +1,112 @@ #!/bin/sh - # # 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 # -PATH=/bin:/usr/bin:/usr/ucb:/usr/local:/usr/local/bin -export PATH - MAKE=Makefile # default makefile name is "Makefile" CC=cc # default C compiler is "cc" DEPENDENCY_CFLAG=-M # default dependency-generation flag is -M 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 ;; *) break ;; esac done if [ $# = 0 ] ; then echo 'usage: mkdep [-p] [-c cc] [-f makefile] [-m dependency-cflag] [flags] file ...' exit 1 fi if [ ! -w $MAKE ]; then echo "mkdep: no writeable file \"$MAKE\"" exit 1 fi TMP=/tmp/mkdep$$ trap 'rm -f $TMP ; exit 1' 1 2 3 13 15 cp $MAKE ${MAKE}.bak sed -e '/DO NOT DELETE THIS LINE/,$d' < $MAKE > $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. # # egrep '^#include[ ]*".*"' /dev/null $* | # sed -e 's/:[^"]*"\([^"]*\)".*/: \1/' -e 's/\.c/.o/' | # XXX this doesn't work with things like "-DDECLWAITSTATUS=union\ wait" $CC $DEPENDENCY_CFLAG $* | sed " s; \./; ;g $SED" | awk '{ if ($1 != prev) { if (rec != "") print rec; rec = $0; prev = $1; } else { if (length(rec $2) > 78) { print rec; rec = $0; } else rec = rec " " $2 } } END { print rec }' >> $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 exit 0 Index: head/contrib/tcpdump/netdissect.h =================================================================== --- head/contrib/tcpdump/netdissect.h (revision 285274) +++ head/contrib/tcpdump/netdissect.h (revision 285275) @@ -1,601 +1,634 @@ /* * Copyright (c) 1988-1997 * The Regents of the University of California. All rights reserved. * * Copyright (c) 1998-2012 Michael Richardson * 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 #ifndef HAVE___ATTRIBUTE__ #define __attribute__(x) #endif /* snprintf et al */ #include #include "ip.h" /* struct ip for nextproto4_cksum() */ #if !defined(HAVE_SNPRINTF) int snprintf (char *str, size_t sz, const char *format, ...) #ifdef __ATTRIBUTE___FORMAT_OK __attribute__((format (printf, 3, 4))) #endif /* __ATTRIBUTE___FORMAT_OK */ ; #endif /* !defined(HAVE_SNPRINTF) */ #if !defined(HAVE_VSNPRINTF) int vsnprintf (char *str, size_t sz, const char *format, va_list ap) #ifdef __ATTRIBUTE___FORMAT_OK __attribute__((format (printf, 3, 0))) #endif /* __ATTRIBUTE___FORMAT_OK */ ; #endif /* !defined(HAVE_SNPRINTF) */ #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 */ }; #define TOKBUFSIZE 128 extern const char *tok2strbuf(const struct tok *, const char *, u_int, char *buf, size_t bufsize); /* tok2str is deprecated */ -extern const char *tok2str(const struct tok *, const char *, int); -extern char *bittok2str(const struct tok *, const char *, int); -extern char *bittok2str_nosep(const struct tok *, const char *, int); +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); typedef struct netdissect_options netdissect_options; struct netdissect_options { int ndo_aflag; /* translate network and broadcast addresses */ 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 TCP 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_Rflag; /* print sequence # field in AH/ESP*/ int ndo_sflag; /* use the libsmi to translate OIDs */ int ndo_Sflag; /* print raw TCP sequence numbers */ int ndo_tflag; /* print packet arrival time */ int ndo_Uflag; /* "unbuffered" output of dump files */ int ndo_uflag; /* Print undecoded NFS handles */ int ndo_vflag; /* verbose */ 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_Bflag; /* buffer size */ int ndo_Iflag; /* rfmon (monitor) mode */ int ndo_Oflag; /* run filter code optimizer */ int ndo_dlt; /* if != -1, ask libpcap for the DLT it names*/ int ndo_jflag; /* packet time stamp source */ int ndo_pflag; /* don't go promiscuous */ + int ndo_immediate; /* use immediate mode */ int ndo_Cflag; /* rotate dump files after this many bytes */ int ndo_Cflag_count; /* Keep track of which file number we're writing */ int ndo_Gflag; /* rotate dump files after this many seconds */ int ndo_Gflag_count; /* number of files created with Gflag rotation */ time_t ndo_Gflag_time; /* The last time_t the dump file was rotated. */ int ndo_Wflag; /* recycle output files after this number of files */ int ndo_WflagChars; int ndo_Hflag; /* dissect 802.11s draft mesh standard */ 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 *ndo_dltname; 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 */ struct esp_algorithm *ndo_espsecret_xform; /* cache of decoded */ char *ndo_espsecret_key; int ndo_packettype; /* as specified by -T */ char *ndo_program_name; /*used to generate self-identifying messages */ int32_t ndo_thiszone; /* seconds offset from gmt to local time */ int ndo_snaplen; /*global pointers to beginning and end of current packet (during printing) */ const u_char *ndo_packetp; const u_char *ndo_snapend; /* bookkeeping for ^T output */ int ndo_infodelay; /* pointer to void function to output stuff */ void (*ndo_default_print)(netdissect_options *, register const u_char *bp, register u_int length); + + /* pointer to function to print ^T output */ void (*ndo_info)(netdissect_options *, int verbose); + /* pointer to function to do regular output */ int (*ndo_printf)(netdissect_options *, const char *fmt, ...) #ifdef __ATTRIBUTE___FORMAT_OK_FOR_FUNCTION_POINTERS __attribute__ ((format (printf, 2, 3))) #endif ; + /* pointer to function to output errors */ void (*ndo_error)(netdissect_options *, const char *fmt, ...) #ifdef __ATTRIBUTE___NORETURN_OK_FOR_FUNCTION_POINTERS __attribute__ ((noreturn)) #endif /* __ATTRIBUTE___NORETURN_OK_FOR_FUNCTION_POINTERS */ #ifdef __ATTRIBUTE___FORMAT_OK_FOR_FUNCTION_POINTERS __attribute__ ((format (printf, 2, 3))) #endif /* __ATTRIBUTE___FORMAT_OK_FOR_FUNCTION_POINTERS */ ; + /* pointer to function to output warnings */ void (*ndo_warning)(netdissect_options *, const char *fmt, ...) #ifdef __ATTRIBUTE___FORMAT_OK_FOR_FUNCTION_POINTERS __attribute__ ((format (printf, 2, 3))) #endif ; }; #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 */ #ifndef min #define min(a,b) ((a)>(b)?(b):(a)) #endif #ifndef max #define max(a,b) ((b)>(a)?(b):(a)) #endif /* * 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: * * http://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? */ #define MAXIMUM_SNAPLEN 262144 /* * The default snapshot length is the maximum. */ #define DEFAULT_SNAPLEN MAXIMUM_SNAPLEN #define ESRC(ep) ((ep)->ether_shost) #define EDST(ep) ((ep)->ether_dhost) #ifndef NTOHL #define NTOHL(x) (x) = ntohl(x) #define NTOHS(x) (x) = ntohs(x) #define HTONL(x) (x) = htonl(x) #define HTONS(x) (x) = htons(x) #endif /* * True if "l" bytes of "var" 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 + * + * http://www.kb.cert.org/vuls/id/162289 */ -#define ND_TTEST2(var, l) (ndo->ndo_snapend - (l) <= ndo->ndo_snapend && \ - (const u_char *)&(var) <= ndo->ndo_snapend - (l)) +#define ND_TTEST2(var, l) \ + ((l) >= 0 && \ + ((uintptr_t)ndo->ndo_snapend - (l) <= (uintptr_t)ndo->ndo_snapend && \ + (uintptr_t)&(var) <= (uintptr_t)ndo->ndo_snapend - (l))) /* True if "var" was captured */ #define ND_TTEST(var) ND_TTEST2(var, sizeof(var)) /* Bail if "l" bytes of "var" were not captured */ #define ND_TCHECK2(var, l) if (!ND_TTEST2(var, l)) goto trunc /* Bail if "var" was not captured */ #define ND_TCHECK(var) ND_TCHECK2(var, sizeof(var)) #define ND_PRINT(STUFF) (*ndo->ndo_printf)STUFF #define ND_DEFAULTPRINT(ap, length) (*ndo->ndo_default_print)(ndo, ap, length) extern void ts_print(netdissect_options *, const struct timeval *); extern void relts_print(netdissect_options *, int); extern int fn_print(netdissect_options *, const u_char *, const u_char *); extern int fn_printn(netdissect_options *, const u_char *, u_int, const u_char *); extern int fn_printzp(netdissect_options *, const u_char *, u_int, const u_char *); -extern const char *tok2str(const struct tok *, const char *, 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 *, const char **, u_int); + #if 0 extern char *read_infile(netdissect_options *, char *); extern char *copy_argv(netdissect_options *, char **); #endif /* * Locale-independent macros for testing character properties and * stripping the 8th bit from characters. Assumed to be handed * a value between 0 and 255, i.e. don't hand them a char, as * those might be in the range -128 to 127. */ #define ND_ISASCII(c) (!((c) & 0x80)) /* value is an ASCII code point */ #define ND_ISPRINT(c) ((c) >= 0x20 && (c) <= 0x7E) #define ND_ISGRAPH(c) ((c) > 0x20 && (c) <= 0x7E) #define ND_TOASCII(c) ((c) & 0x7F) extern void safeputchar(netdissect_options *, const u_char); extern void safeputs(netdissect_options *, const u_char *, const u_int); #ifdef LBL_ALIGN /* * 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)) #else /* * The procesor natively handles unaligned loads, so just use memcpy() * and memcmp(), to enable those optimizations. */ #define UNALIGNED_MEMCPY(p, q, l) memcpy((p), (q), (l)) #define UNALIGNED_MEMCMP(p, q, l) memcmp((p), (q), (l)) #endif #define PLURAL_SUFFIX(n) \ (((n) != 1) ? "s" : "") #if 0 extern const char *dnname_string(netdissect_options *, u_short); extern const char *dnnum_string(netdissect_options *, u_short); #endif /* The printer routines. */ #include +extern char *q922_string(netdissect_options *ndo, const u_char *, u_int); + typedef u_int (*if_ndo_printer)(struct netdissect_options *ndo, const struct pcap_pkthdr *, const u_char *); typedef u_int (*if_printer)(const struct pcap_pkthdr *, const u_char *); extern if_ndo_printer lookup_ndo_printer(int); extern if_printer lookup_printer(int); extern void eap_print(netdissect_options *,const u_char *, u_int); extern int esp_print(netdissect_options *, const u_char *bp, const int length, const u_char *bp2, int *nhdr, int *padlen); extern void arp_print(netdissect_options *,const u_char *, u_int, u_int); extern void tipc_print(netdissect_options *, const u_char *, u_int, u_int); extern void msnlb_print(netdissect_options *, const u_char *); extern void icmp6_print(netdissect_options *ndo, const u_char *, u_int, const u_char *, 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 *); extern void ip_print(netdissect_options *,const u_char *, u_int); extern void ip_print_inner(netdissect_options *ndo, const u_char *bp, u_int length, u_int nh, const u_char *bp2); extern void rrcp_print(netdissect_options *,const u_char *, u_int); extern void loopback_print(netdissect_options *, const u_char *, const u_int); extern void carp_print(netdissect_options *, const u_char *, u_int, int); extern void ether_print(netdissect_options *, const u_char *, u_int, u_int, void (*)(netdissect_options *, const u_char *), const u_char *); extern u_int ether_if_print(netdissect_options *, const struct pcap_pkthdr *,const u_char *); extern u_int netanalyzer_if_print(netdissect_options *, const struct pcap_pkthdr *,const u_char *); extern u_int netanalyzer_transparent_if_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern int ethertype_print(netdissect_options *,u_short, const u_char *, u_int, u_int); extern int print_unknown_data(netdissect_options *,const u_char *, const char *,int); extern void ascii_print(netdissect_options *, const u_char *, u_int); extern void hex_print_with_offset(netdissect_options *, const char *ident, const u_char *cp, u_int, u_int); extern void hex_print(netdissect_options *,const char *ident, const u_char *cp,u_int); extern void hex_and_ascii_print_with_offset(netdissect_options *, const char *, const u_char *, u_int, u_int); extern void hex_and_ascii_print(netdissect_options *, const char *, const u_char *, u_int); extern int ah_print(netdissect_options *, register const u_char *); extern void beep_print(netdissect_options *, const u_char *, u_int); extern void dtp_print(netdissect_options *, const u_char *, u_int); extern u_int cip_if_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern int ipcomp_print(netdissect_options *, register const u_char *, int *); extern u_int ipfc_if_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern void udld_print(netdissect_options *, const u_char *, u_int); extern void hsrp_print(netdissect_options *, const u_char *, u_int); extern void igrp_print(netdissect_options *, const u_char *, u_int); extern void msdp_print(netdissect_options *, const u_char *, u_int); extern u_int null_if_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern void mobile_print(netdissect_options *, const u_char *, u_int); extern u_int ap1394_if_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern u_int bt_if_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern void lane_print(netdissect_options *, const u_char *, u_int, u_int); extern u_int lane_if_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern void otv_print(netdissect_options *, const u_char *, u_int); extern void ahcp_print(netdissect_options *, const u_char *, const u_int); extern void vxlan_print(netdissect_options *, const u_char *, u_int); extern u_int arcnet_if_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern u_int arcnet_linux_if_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern void bfd_print(netdissect_options *, const u_char *, u_int, u_int); extern void gre_print(netdissect_options *, const u_char *, u_int); extern int vjc_print(netdissect_options *, register const char *, u_short); extern void ipN_print(netdissect_options *, const u_char *, u_int); extern u_int raw_if_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern u_int usb_linux_48_byte_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern u_int usb_linux_64_byte_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern u_int symantec_if_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern u_int chdlc_if_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern u_int chdlc_print(netdissect_options *, register const u_char *, u_int); extern void zmtp1_print(netdissect_options *, const u_char *, u_int); extern void zmtp1_print_datagram(netdissect_options *, const u_char *, const u_int); extern void ipx_print(netdissect_options *, const u_char *, u_int); extern void mpls_print(netdissect_options *, const u_char *, u_int); extern u_int pppoe_print(netdissect_options *, const u_char *, u_int); extern u_int pppoe_if_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern void sunrpcrequest_print(netdissect_options *, const u_char *, u_int, const u_char *); extern u_int pflog_if_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern u_int token_print(netdissect_options *, const u_char *, u_int, u_int); extern u_int token_if_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern void vqp_print(netdissect_options *, register const u_char *, register u_int); extern void zephyr_print(netdissect_options *, const u_char *, int); extern void fddi_print(netdissect_options *, const u_char *, u_int, u_int); extern u_int fddi_if_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern void mpcp_print(netdissect_options *, const u_char *, u_int); extern void rpki_rtr_print(netdissect_options *, const u_char *, u_int); extern u_int sll_if_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern void dccp_print(netdissect_options *, const u_char *, const u_char *, u_int); extern int llc_print(netdissect_options *, const u_char *, u_int, u_int, const u_char *, const u_char *, u_short *); extern int snap_print(netdissect_options *, const u_char *, u_int, u_int, u_int); extern void eigrp_print(netdissect_options *, const u_char *, u_int); extern void stp_print(netdissect_options *, const u_char *, u_int); extern void l2tp_print(netdissect_options *, const u_char *, u_int); extern void udp_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 void openflow_print(netdissect_options *, const u_char *, const u_int); extern void telnet_print(netdissect_options *, const u_char *, u_int); extern void slow_print(netdissect_options *, const u_char *, u_int); extern void radius_print(netdissect_options *, const u_char *, u_int); extern void lmp_print(netdissect_options *, const u_char *, u_int); extern u_int fr_print(netdissect_options *, register const u_char *, u_int); extern u_int mfr_print(netdissect_options *, register const u_char *, u_int); extern u_int fr_if_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern u_int mfr_if_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern void q933_print(netdissect_options *, const u_char *, u_int); extern void igmp_print(netdissect_options *, const u_char *, u_int); extern void rip_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 pgm_print(netdissect_options *, const u_char *, u_int, const u_char *); extern void pptp_print(netdissect_options *, const u_char *); extern void ldp_print(netdissect_options *, const u_char *, u_int); extern void wb_print(netdissect_options *, const void *, u_int); extern int oam_print(netdissect_options *, const u_char *, u_int, u_int); extern void atm_print(netdissect_options *, u_int, u_int, u_int, const u_char *, u_int, u_int); extern u_int sunatm_if_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern u_int atm_if_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern void vtp_print(netdissect_options *, const u_char *, u_int); extern int mptcp_print(netdissect_options *, const u_char *, u_int, u_char); extern void ntp_print(netdissect_options *, const u_char *, u_int); -extern void cnfp_print(netdissect_options *, const u_char *, const u_char *); +extern void cnfp_print(netdissect_options *, const u_char *); extern void dvmrp_print(netdissect_options *, const u_char *, u_int); extern void egp_print(netdissect_options *, const u_char *, u_int); extern u_int enc_if_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern u_int sl_if_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern u_int sl_bsdos_if_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern void tftp_print(netdissect_options *, const u_char *, u_int); extern void vrrp_print(netdissect_options *, const u_char *, u_int, const u_char *, int); extern void pimv1_print(netdissect_options *, const u_char *, u_int); extern void cisco_autorp_print(netdissect_options *, const u_char *, u_int); extern void pim_print(netdissect_options *, const u_char *, u_int, u_int); extern const u_char * ns_nprint (netdissect_options *, register const u_char *, register const u_char *); extern void ns_print(netdissect_options *, const u_char *, u_int, int); extern void bootp_print(netdissect_options *, const u_char *, u_int); extern void sflow_print(netdissect_options *, const u_char *, u_int); extern void aodv_print(netdissect_options *, const u_char *, u_int, int); extern void sctp_print(netdissect_options *, const u_char *, const u_char *, u_int); extern char *bgp_vpn_rd_print (netdissect_options *, const u_char *); extern void bgp_print(netdissect_options *, const u_char *, int); extern void olsr_print(netdissect_options *, const u_char *, u_int, int); extern void forces_print(netdissect_options *, const u_char *, u_int); extern void lspping_print(netdissect_options *, const u_char *, u_int); extern void isoclns_print(netdissect_options *, const u_char *, u_int, u_int); extern void krb_print(netdissect_options *, const u_char *); extern void cdp_print(netdissect_options *, const u_char *, u_int, u_int); extern void atalk_print(netdissect_options *, const u_char *, u_int); extern u_int ltalk_if_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern u_int llap_print(netdissect_options *, const u_char *, u_int); extern void aarp_print(netdissect_options *, const u_char *, u_int); extern u_int juniper_atm1_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern u_int juniper_atm2_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern u_int juniper_mfr_print(netdissect_options *, const struct pcap_pkthdr *, register const u_char *); extern u_int juniper_mlfr_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern u_int juniper_mlppp_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern u_int juniper_pppoe_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern u_int juniper_pppoe_atm_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern u_int juniper_ggsn_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern u_int juniper_es_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern u_int juniper_monitor_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern u_int juniper_services_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern u_int juniper_ether_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern u_int juniper_ppp_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern u_int juniper_frelay_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern u_int juniper_chdlc_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern void snmp_print(netdissect_options *, const u_char *, u_int); extern void rx_print(netdissect_options *, register const u_char *, int, int, int, u_char *); extern void nfsreply_print(netdissect_options *, const u_char *, u_int, const u_char *); extern void nfsreply_print_noaddr(netdissect_options *, const u_char *, u_int, const u_char *); extern void nfsreq_print_noaddr(netdissect_options *, const u_char *, u_int, const u_char *); extern void sip_print(netdissect_options *, const u_char *, u_int); extern void syslog_print(netdissect_options *, const u_char *, u_int); extern void lwres_print(netdissect_options *, const u_char *, u_int); extern void cfm_print(netdissect_options *, const u_char *, u_int); extern void nbt_tcp_print(netdissect_options *, const u_char *, int); extern void nbt_udp137_print(netdissect_options *, const u_char *, int); extern void nbt_udp138_print(netdissect_options *, const u_char *, int); extern void smb_tcp_print(netdissect_options *, const u_char *, int); extern void netbeui_print(netdissect_options *, u_short, const u_char *, int); extern void ipx_netbios_print(netdissect_options *, const u_char *, u_int); extern void print_data(netdissect_options *, const unsigned char *, int); extern void decnet_print(netdissect_options *, const u_char *, u_int, u_int); extern void tcp_print(netdissect_options *, const u_char *, u_int, const u_char *, int); extern void ospf_print(netdissect_options *, const u_char *, u_int, const u_char *); extern int ospf_print_te_lsa(netdissect_options *, const uint8_t *, u_int); extern int ospf_print_grace_lsa(netdissect_options *, const uint8_t *, u_int); extern u_int ppp_print(netdissect_options *, register const u_char *, u_int); extern u_int ppp_if_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern u_int ppp_hdlc_if_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern u_int ppp_bsdos_if_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern void lldp_print(netdissect_options *, const u_char *, u_int); extern void rsvp_print(netdissect_options *, const u_char *, u_int); extern void timed_print(netdissect_options *, const u_char *); extern void m3ua_print(netdissect_options *, const u_char *, const u_int); extern void aoe_print(netdissect_options *, const u_char *, const u_int); +extern void ftp_print(netdissect_options *, const u_char *, u_int); +extern void http_print(netdissect_options *, const u_char *, u_int); +extern void rtsp_print(netdissect_options *, const u_char *, u_int); +extern void smtp_print(netdissect_options *, const u_char *, u_int); +extern void geneve_print(netdissect_options *, const u_char *, u_int); extern void pfsync_ip_print(netdissect_options *, const u_char *, u_int); /* stuff that has not yet been rototiled */ #if 0 extern void ascii_print(netdissect_options *,u_int); extern void default_print(netdissect_options *,const u_char *, u_int); extern char *smb_errstr(netdissect_options *,int, int); extern const char *nt_errstr(netdissect_options *, uint32_t); #endif extern u_int ipnet_if_print(netdissect_options *,const struct pcap_pkthdr *, const u_char *); extern u_int ppi_if_print(netdissect_options *,const struct pcap_pkthdr *, const u_char *); extern u_int nflog_if_print(netdissect_options *,const struct pcap_pkthdr *, const u_char *); extern u_int ieee802_15_4_if_print(netdissect_options *,const struct pcap_pkthdr *, const u_char *); extern u_int pktap_if_print(netdissect_options *,const struct pcap_pkthdr *, const u_char *); extern u_int ieee802_11_radio_if_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern u_int ieee802_11_if_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern u_int ieee802_11_radio_avs_if_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); extern u_int prism_if_print(netdissect_options *, const struct pcap_pkthdr *, const u_char *); -#ifdef INET6 extern void ip6_print(netdissect_options *,const u_char *, u_int); +#ifdef INET6 extern int frag6_print(netdissect_options *, const u_char *, const u_char *); extern int rt6_print(netdissect_options *, const u_char *, const u_char *); extern int hbhopt_print(netdissect_options *, const u_char *); extern int dstopt_print(netdissect_options *, const u_char *); extern void ripng_print(netdissect_options *, const u_char *, unsigned int); extern int mobility_print(netdissect_options *, const u_char *, const u_char *); extern void dhcp6_print(netdissect_options *, const u_char *, u_int); extern void ospf6_print(netdissect_options *, const u_char *, u_int); extern void babel_print(netdissect_options *, const u_char *, u_int); #endif /*INET6*/ #if 0 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); #endif extern int nextproto4_cksum(netdissect_options *ndo, const struct ip *, const uint8_t *, u_int, u_int, u_int); extern int decode_prefix4(netdissect_options *ndo, const u_char *, u_int, char *, u_int); #ifdef INET6 extern int decode_prefix6(netdissect_options *ndo, const u_char *, u_int, char *, u_int); #endif extern void esp_print_decodesecret(netdissect_options *ndo); extern int esp_print_decrypt_buffer_by_ikev2(netdissect_options *ndo, int initiator, u_char spii[8], u_char spir[8], u_char *buf, u_char *end); extern void geonet_print(netdissect_options *ndo,const u_char *eth_hdr,const u_char *geo_pck, u_int len); extern void calm_fast_print(netdissect_options *ndo,const u_char *eth_hdr,const u_char *calm_pck, u_int len); #endif /* netdissect_h */ Index: head/contrib/tcpdump/openflow.h =================================================================== --- head/contrib/tcpdump/openflow.h (revision 285274) +++ head/contrib/tcpdump/openflow.h (revision 285275) @@ -1,40 +1,51 @@ /* * 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. */ /* OpenFlow: protocol between controller and datapath. */ /* for netdissect_options */ #include "netdissect.h" #define OF_HEADER_LEN 8 +#define ONF_EXP_ONF 0x4f4e4600 +#define ONF_EXP_BUTE 0xff000001 +#define ONF_EXP_NOVIFLOW 0xff000002 +#define ONF_EXP_L3 0xff000003 +#define ONF_EXP_L4L7 0xff000004 +#define ONF_EXP_WMOB 0xff000005 +#define ONF_EXP_FABS 0xff000006 +#define ONF_EXP_OTRANS 0xff000007 +extern const struct tok onf_exp_str[]; + /* * Routines to print packets for various versions of OpenFlow. */ extern const u_char *of10_header_body_print(netdissect_options *ndo, const u_char *, const u_char *, const uint8_t, const uint16_t, const uint32_t); +extern const char * of_vendor_name(const uint32_t); Index: head/contrib/tcpdump/oui.c =================================================================== --- head/contrib/tcpdump/oui.c (revision 285274) +++ head/contrib/tcpdump/oui.c (revision 285275) @@ -1,95 +1,104 @@ /* * 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@juniper.net) */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "interface.h" #include "oui.h" /* FIXME complete OUI list using a script */ const struct tok oui_values[] = { { OUI_ENCAP_ETHER, "Ethernet" }, { OUI_CISCO, "Cisco" }, { 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" }, { 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_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_CISCO_VPN3000, "Cisco VPN 3000"}, { SMI_COSINE, "CoSine Communications"}, { SMI_NETSCREEN, "Netscreen"}, { SMI_SHASTA, "Shasta"}, { SMI_NOMADIX, "Nomadix"}, { SMI_SIEMENS, "Siemens"}, { SMI_CABLELABS, "CableLabs"}, { SMI_UNISPHERE, "Unisphere Networks"}, { SMI_CISCO_BBSM, "Cisco BBSM"}, { SMI_THE3GPP2, "3rd Generation Partnership Project 2 (3GPP2)"}, { SMI_IP_UNPLUGGED, "ipUnplugged"}, { SMI_ISSANNI, "Issanni Communications"}, { SMI_QUINTUM, "Quintum"}, { SMI_INTERLINK, "Interlink"}, { SMI_COLUBRIS, "Colubris"}, { SMI_COLUMBIA_UNIVERSITY, "Columbia University"}, { SMI_THE3GPP, "3GPP"}, { SMI_GEMTEK_SYSTEMS, "Gemtek-Systems"}, { SMI_WIFI_ALLIANCE, "Wi-Fi Alliance"}, { 0, NULL} }; Index: head/contrib/tcpdump/oui.h =================================================================== --- head/contrib/tcpdump/oui.h (revision 285274) +++ head/contrib/tcpdump/oui.h (revision 285275) @@ -1,81 +1,90 @@ /* * 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@juniper.net) */ extern const struct tok oui_values[]; extern const struct tok smi_values[]; #define OUI_ENCAP_ETHER 0x000000 /* encapsulated Ethernet */ #define OUI_CISCO 0x00000c /* Cisco protocols */ #define OUI_NORTEL 0x000081 /* Nortel SONMP */ #define OUI_CISCO_90 0x0000f8 /* Cisco bridging */ #define OUI_RFC2684 0x0080c2 /* RFC 2427/2684 bridged Ethernet */ #define OUI_ATM_FORUM 0x00A03E /* ATM Forum */ #define OUI_CABLE_BPDU 0x00E02F /* DOCSIS spanning tree BPDU */ #define OUI_APPLETALK 0x080007 /* Appletalk */ #define OUI_JUNIPER 0x009069 /* Juniper */ #define OUI_HP 0x080009 /* Hewlett-Packard */ #define OUI_IEEE_8021_PRIVATE 0x0080c2 /* IEEE 802.1 Organisation Specific - Annex F */ #define OUI_IEEE_8023_PRIVATE 0x00120f /* IEEE 802.3 Organisation Specific - Annex G */ #define OUI_TIA 0x0012bb /* TIA - Telecommunications Industry Association - ANSI/TIA-1057- 2006 */ #define OUI_DCBX 0x001B21 /* DCBX */ +#define OUI_NICIRA 0x002320 /* Nicira Networks */ +#define OUI_BSN 0x5c16c7 /* Big Switch Networks */ +#define OUI_VELLO 0xb0d2f5 /* Vello Systems */ +#define OUI_HP2 0x002481 /* HP too */ +#define OUI_HPLABS 0x0004ea /* HP-Labs */ +#define OUI_INFOBLOX 0x748771 /* Infoblox Inc */ +#define OUI_ONLAB 0xa42305 /* Open Networking Lab */ +#define OUI_FREESCALE 0x00049f /* Freescale */ +#define OUI_NETRONOME 0x0015ad /* Netronome */ /* * These are SMI Network Management Private Enterprise Codes for * organizations; see * * http://www.iana.org/assignments/enterprise-numbers * * for a list. * * List taken from Ethereal's epan/sminmpec.h. */ #define SMI_IETF 0 /* reserved - used by the IETF in L2TP? */ #define SMI_ACC 5 #define SMI_CISCO 9 #define SMI_HEWLETT_PACKARD 11 #define SMI_SUN_MICROSYSTEMS 42 #define SMI_MERIT 61 #define SMI_SHIVA 166 #define SMI_ERICSSON 193 #define SMI_CISCO_VPN5000 255 #define SMI_LIVINGSTON 307 #define SMI_MICROSOFT 311 #define SMI_3COM 429 #define SMI_ASCEND 529 #define SMI_BAY 1584 #define SMI_FOUNDRY 1991 #define SMI_VERSANET 2180 #define SMI_REDBACK 2352 #define SMI_JUNIPER 2636 #define SMI_APTIS 2637 #define SMI_CISCO_VPN3000 3076 #define SMI_COSINE 3085 #define SMI_SHASTA 3199 #define SMI_NETSCREEN 3224 #define SMI_NOMADIX 3309 #define SMI_SIEMENS 4329 #define SMI_CABLELABS 4491 #define SMI_UNISPHERE 4874 #define SMI_CISCO_BBSM 5263 #define SMI_THE3GPP2 5535 #define SMI_IP_UNPLUGGED 5925 #define SMI_ISSANNI 5948 #define SMI_QUINTUM 6618 #define SMI_INTERLINK 6728 #define SMI_COLUBRIS 8744 #define SMI_COLUMBIA_UNIVERSITY 11862 #define SMI_THE3GPP 10415 #define SMI_GEMTEK_SYSTEMS 10529 #define SMI_WIFI_ALLIANCE 14122 Index: head/contrib/tcpdump/print-ahcp.c =================================================================== --- head/contrib/tcpdump/print-ahcp.c (revision 285274) +++ head/contrib/tcpdump/print-ahcp.c (revision 285275) @@ -1,413 +1,421 @@ /* * This module implements decoding of AHCP (Ad Hoc Configuration Protocol) based * on draft-chroboczek-ahcp-00 and source code of ahcpd-0.53. * * * 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. */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "interface.h" #include "extract.h" #include "addrtoname.h" static const char tstr[] = " [|ahcp]"; static const char cstr[] = "(corrupt)"; #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 int -ahcp_time_print(netdissect_options *ndo, const u_char *cp, const u_char *ep) { +ahcp_time_print(netdissect_options *ndo, const u_char *cp, const u_char *ep) +{ time_t t; struct tm *tm; char buf[BUFSIZE]; if (cp + 4 != ep) goto corrupt; ND_TCHECK2(*cp, 4); t = EXTRACT_32BITS(cp); if (NULL == (tm = gmtime(&t))) ND_PRINT((ndo, ": gmtime() error")); else if (0 == strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm)) ND_PRINT((ndo, ": strftime() error")); else ND_PRINT((ndo, ": %s UTC", buf)); return 0; corrupt: ND_PRINT((ndo, ": %s", cstr)); ND_TCHECK2(*cp, ep - cp); return 0; trunc: ND_PRINT((ndo, "%s", tstr)); return -1; } static int -ahcp_seconds_print(netdissect_options *ndo, const u_char *cp, const u_char *ep) { +ahcp_seconds_print(netdissect_options *ndo, const u_char *cp, const u_char *ep) +{ if (cp + 4 != ep) goto corrupt; ND_TCHECK2(*cp, 4); ND_PRINT((ndo, ": %us", EXTRACT_32BITS(cp))); return 0; corrupt: ND_PRINT((ndo, ": %s", cstr)); ND_TCHECK2(*cp, ep - cp); return 0; trunc: ND_PRINT((ndo, "%s", tstr)); return -1; } static int -ahcp_ipv6_addresses_print(netdissect_options *ndo, const u_char *cp, const u_char *ep) { +ahcp_ipv6_addresses_print(netdissect_options *ndo, const u_char *cp, const u_char *ep) +{ const char *sep = ": "; while (cp < ep) { if (cp + 16 > ep) goto corrupt; ND_TCHECK2(*cp, 16); #ifdef INET6 ND_PRINT((ndo, "%s%s", sep, ip6addr_string(ndo, cp))); #else ND_PRINT((ndo, "%s(compiled w/o IPv6)", sep)); #endif /* INET6 */ cp += 16; sep = ", "; } return 0; corrupt: ND_PRINT((ndo, ": %s", cstr)); ND_TCHECK2(*cp, ep - cp); return 0; trunc: ND_PRINT((ndo, "%s", tstr)); return -1; } static int -ahcp_ipv4_addresses_print(netdissect_options *ndo, const u_char *cp, const u_char *ep) { +ahcp_ipv4_addresses_print(netdissect_options *ndo, const u_char *cp, const u_char *ep) +{ const char *sep = ": "; while (cp < ep) { if (cp + 4 > ep) goto corrupt; ND_TCHECK2(*cp, 4); ND_PRINT((ndo, "%s%s", sep, ipaddr_string(ndo, cp))); cp += 4; sep = ", "; } return 0; corrupt: ND_PRINT((ndo, ": %s", cstr)); ND_TCHECK2(*cp, ep - cp); return 0; trunc: ND_PRINT((ndo, "%s", tstr)); return -1; } static int -ahcp_ipv6_prefixes_print(netdissect_options *ndo, const u_char *cp, const u_char *ep) { +ahcp_ipv6_prefixes_print(netdissect_options *ndo, const u_char *cp, const u_char *ep) +{ const char *sep = ": "; while (cp < ep) { if (cp + 17 > ep) goto corrupt; ND_TCHECK2(*cp, 17); #ifdef INET6 ND_PRINT((ndo, "%s%s/%u", sep, ip6addr_string(ndo, cp), *(cp + 16))); #else ND_PRINT((ndo, "%s(compiled w/o IPv6)/%u", sep, *(cp + 16))); #endif /* INET6 */ cp += 17; sep = ", "; } return 0; corrupt: ND_PRINT((ndo, ": %s", cstr)); ND_TCHECK2(*cp, ep - cp); return 0; trunc: ND_PRINT((ndo, "%s", tstr)); return -1; } static int -ahcp_ipv4_prefixes_print(netdissect_options *ndo, const u_char *cp, const u_char *ep) { +ahcp_ipv4_prefixes_print(netdissect_options *ndo, const u_char *cp, const u_char *ep) +{ const char *sep = ": "; while (cp < ep) { if (cp + 5 > ep) goto corrupt; ND_TCHECK2(*cp, 5); ND_PRINT((ndo, "%s%s/%u", sep, ipaddr_string(ndo, cp), *(cp + 4))); cp += 5; sep = ", "; } return 0; corrupt: ND_PRINT((ndo, ": %s", cstr)); ND_TCHECK2(*cp, ep - cp); return 0; trunc: ND_PRINT((ndo, "%s", tstr)); return -1; } /* Data decoders signal truncated data with -1. */ static int (* const data_decoders[AHCP1_OPT_MAX + 1])(netdissect_options *, const u_char *, const u_char *) = { /* [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, const u_char *ep) { +ahcp1_options_print(netdissect_options *ndo, const u_char *cp, const u_char *ep) +{ uint8_t option_no, option_len; while (cp < ep) { /* Option no */ ND_TCHECK2(*cp, 1); option_no = *cp; cp += 1; ND_PRINT((ndo, "\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 (cp + 1 > ep) goto corrupt; ND_TCHECK2(*cp, 1); option_len = *cp; cp += 1; if (cp + option_len > ep) goto corrupt; /* Value */ if (option_no <= AHCP1_OPT_MAX && data_decoders[option_no] != NULL) { if (data_decoders[option_no](ndo, cp, cp + option_len) < 0) break; /* truncated and already marked up */ } else { ND_PRINT((ndo, " (Length %u)", option_len)); ND_TCHECK2(*cp, option_len); } cp += option_len; } return; corrupt: ND_PRINT((ndo, " %s", cstr)); ND_TCHECK2(*cp, ep - cp); return; trunc: ND_PRINT((ndo, "%s", tstr)); } static void -ahcp1_body_print(netdissect_options *ndo, const u_char *cp, const u_char *ep) { +ahcp1_body_print(netdissect_options *ndo, const u_char *cp, const u_char *ep) +{ uint8_t type, mbz; uint16_t body_len; if (cp + AHCP1_BODY_MIN_LEN > ep) goto corrupt; /* Type */ ND_TCHECK2(*cp, 1); type = *cp; cp += 1; /* MBZ */ ND_TCHECK2(*cp, 1); mbz = *cp; cp += 1; /* Length */ ND_TCHECK2(*cp, 2); body_len = EXTRACT_16BITS(cp); cp += 2; if (ndo->ndo_vflag) { ND_PRINT((ndo, "\n\t%s", tok2str(ahcp1_msg_str, "Unknown-%u", type))); if (mbz != 0) ND_PRINT((ndo, ", MBZ %u", mbz)); ND_PRINT((ndo, ", Length %u", body_len)); } if (cp + body_len > ep) goto corrupt; /* Options */ if (ndo->ndo_vflag >= 2) ahcp1_options_print(ndo, cp, cp + body_len); /* not ep (ignore extra data) */ else ND_TCHECK2(*cp, body_len); return; corrupt: ND_PRINT((ndo, " %s", cstr)); ND_TCHECK2(*cp, ep - cp); return; trunc: ND_PRINT((ndo, "%s", tstr)); } void -ahcp_print(netdissect_options *ndo, const u_char *cp, const u_int len) { +ahcp_print(netdissect_options *ndo, const u_char *cp, const u_int len) +{ const u_char *ep = cp + len; uint8_t version; ND_PRINT((ndo, "AHCP")); if (len < 2) goto corrupt; /* Magic */ ND_TCHECK2(*cp, 1); if (*cp != AHCP_MAGIC_NUMBER) goto corrupt; cp += 1; /* Version */ ND_TCHECK2(*cp, 1); version = *cp; cp += 1; switch (version) { case AHCP_VERSION_1: { ND_PRINT((ndo, " Version 1")); if (len < AHCP1_HEADER_FIX_LEN) goto corrupt; if (!ndo->ndo_vflag) { ND_TCHECK2(*cp, AHCP1_HEADER_FIX_LEN - 2); cp += AHCP1_HEADER_FIX_LEN - 2; } else { /* Hopcount */ ND_TCHECK2(*cp, 1); ND_PRINT((ndo, "\n\tHopcount %u", *cp)); cp += 1; /* Original Hopcount */ ND_TCHECK2(*cp, 1); ND_PRINT((ndo, ", Original Hopcount %u", *cp)); cp += 1; /* Nonce */ ND_TCHECK2(*cp, 4); ND_PRINT((ndo, ", Nonce 0x%08x", EXTRACT_32BITS(cp))); cp += 4; /* Source Id */ ND_TCHECK2(*cp, 8); ND_PRINT((ndo, ", Source Id %s", linkaddr_string(ndo, cp, 0, 8))); cp += 8; /* Destination Id */ ND_TCHECK2(*cp, 8); ND_PRINT((ndo, ", Destination Id %s", linkaddr_string(ndo, cp, 0, 8))); cp += 8; } /* Body */ ahcp1_body_print(ndo, cp, ep); break; } default: ND_PRINT((ndo, " Version %u (unknown)", version)); break; } return; corrupt: ND_PRINT((ndo, " %s", cstr)); ND_TCHECK2(*cp, ep - cp); return; trunc: ND_PRINT((ndo, "%s", tstr)); } - Index: head/contrib/tcpdump/print-aodv.c =================================================================== --- head/contrib/tcpdump/print-aodv.c (revision 285274) +++ head/contrib/tcpdump/print-aodv.c (revision 285275) @@ -1,620 +1,585 @@ /* * Copyright (c) 2003 Bruce M. Simpson * 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. */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include -/* for offsetof */ -#include - #include "interface.h" #include "addrtoname.h" #include "extract.h" /* must come after interface.h */ struct aodv_rreq { uint8_t rreq_type; /* AODV message type (1) */ uint8_t rreq_flags; /* various flags */ uint8_t rreq_zero0; /* reserved, set to zero */ uint8_t rreq_hops; /* number of hops from originator */ uint32_t rreq_id; /* request ID */ uint32_t rreq_da; /* destination IPv4 address */ uint32_t rreq_ds; /* destination sequence number */ uint32_t rreq_oa; /* originator IPv4 address */ uint32_t rreq_os; /* originator sequence number */ }; #ifdef INET6 struct aodv_rreq6 { uint8_t rreq_type; /* AODV message type (1) */ uint8_t rreq_flags; /* various flags */ uint8_t rreq_zero0; /* reserved, set to zero */ uint8_t rreq_hops; /* number of hops from originator */ uint32_t rreq_id; /* request ID */ struct in6_addr rreq_da; /* destination IPv6 address */ uint32_t rreq_ds; /* destination sequence number */ struct in6_addr rreq_oa; /* originator IPv6 address */ uint32_t rreq_os; /* originator sequence number */ }; struct aodv_rreq6_draft_01 { uint8_t rreq_type; /* AODV message type (16) */ uint8_t rreq_flags; /* various flags */ uint8_t rreq_zero0; /* reserved, set to zero */ uint8_t rreq_hops; /* number of hops from originator */ uint32_t rreq_id; /* request ID */ uint32_t rreq_ds; /* destination sequence number */ uint32_t rreq_os; /* originator sequence number */ struct in6_addr rreq_da; /* destination IPv6 address */ struct in6_addr rreq_oa; /* originator IPv6 address */ }; #endif #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 { uint8_t rrep_type; /* AODV message type (2) */ uint8_t rrep_flags; /* various flags */ uint8_t rrep_ps; /* prefix size */ uint8_t rrep_hops; /* number of hops from o to d */ uint32_t rrep_da; /* destination IPv4 address */ uint32_t rrep_ds; /* destination sequence number */ uint32_t rrep_oa; /* originator IPv4 address */ uint32_t rrep_life; /* lifetime of this route */ }; #ifdef INET6 struct aodv_rrep6 { uint8_t rrep_type; /* AODV message type (2) */ uint8_t rrep_flags; /* various flags */ uint8_t rrep_ps; /* prefix size */ uint8_t rrep_hops; /* number of hops from o to d */ struct in6_addr rrep_da; /* destination IPv6 address */ uint32_t rrep_ds; /* destination sequence number */ struct in6_addr rrep_oa; /* originator IPv6 address */ uint32_t rrep_life; /* lifetime of this route */ }; struct aodv_rrep6_draft_01 { uint8_t rrep_type; /* AODV message type (17) */ uint8_t rrep_flags; /* various flags */ uint8_t rrep_ps; /* prefix size */ uint8_t rrep_hops; /* number of hops from o to d */ uint32_t rrep_ds; /* destination sequence number */ struct in6_addr rrep_da; /* destination IPv6 address */ struct in6_addr rrep_oa; /* originator IPv6 address */ uint32_t rrep_life; /* lifetime of this route */ }; #endif #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 { uint32_t u_da; /* IPv4 address */ uint32_t u_ds; /* sequence number */ }; #ifdef INET6 struct rerr_unreach6 { struct in6_addr u_da; /* IPv6 address */ uint32_t u_ds; /* sequence number */ }; struct rerr_unreach6_draft_01 { struct in6_addr u_da; /* IPv6 address */ uint32_t u_ds; /* sequence number */ }; #endif struct aodv_rerr { uint8_t rerr_type; /* AODV message type (3 or 18) */ uint8_t rerr_flags; /* various flags */ uint8_t rerr_zero0; /* reserved, set to zero */ uint8_t rerr_dc; /* destination count */ - union { - struct rerr_unreach dest[1]; -#ifdef INET6 - struct rerr_unreach6 dest6[1]; - struct rerr_unreach6_draft_01 dest6_draft_01[1]; -#endif - } r; }; #define RERR_NODELETE 0x80 /* don't delete the link */ #define RERR_FLAGS_MASK 0x80 /* mask for rerr_flags */ struct aodv_rrep_ack { uint8_t ra_type; uint8_t ra_zero0; }; -union aodv { - struct aodv_rreq rreq; - struct aodv_rrep rrep; - struct aodv_rerr rerr; - struct aodv_rrep_ack rrep_ack; -#ifdef INET6 - struct aodv_rreq6 rreq6; - struct aodv_rreq6_draft_01 rreq6_draft_01; - struct aodv_rrep6 rrep6; - struct aodv_rrep6_draft_01 rrep6_draft_01; -#endif -}; - #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 { uint8_t type; /* extension type */ uint8_t length; /* extension length */ }; struct aodv_hello { struct aodv_ext eh; /* extension header */ uint8_t interval[4]; /* 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) { - u_int i; const struct aodv_hello *ah; switch (ep->type) { case AODV_EXT_HELLO: - if (ndo->ndo_snapend < (u_char *) ep) { - ND_PRINT((ndo, " [|hello]")); - return; - } - i = min(length, (u_int)(ndo->ndo_snapend - (u_char *)ep)); - if (i < sizeof(struct aodv_hello)) { - ND_PRINT((ndo, " [|hello]")); - return; - } - i -= sizeof(struct aodv_hello); - ah = (void *)ep; + ah = (const struct aodv_hello *)(const void *)ep; + ND_TCHECK(*ah); + if (length < sizeof(struct aodv_hello)) + goto trunc; ND_PRINT((ndo, "\n\text HELLO %ld ms", (unsigned long)EXTRACT_32BITS(&ah->interval))); break; default: ND_PRINT((ndo, "\n\text %u %u", ep->type, ep->length)); break; } + return; + +trunc: + ND_PRINT((ndo, " [|hello]")); } static void -aodv_rreq(netdissect_options *ndo, - const union aodv *ap, const u_char *dat, u_int length) +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; - if (ndo->ndo_snapend < dat) { - ND_PRINT((ndo, " [|aodv]")); - return; - } - i = min(length, (u_int)(ndo->ndo_snapend - dat)); - if (i < sizeof(ap->rreq)) { - ND_PRINT((ndo, " [|rreq]")); - return; - } - i -= sizeof(ap->rreq); + ND_TCHECK(*ap); + if (length < sizeof(*ap)) + goto trunc; ND_PRINT((ndo, " rreq %u %s%s%s%s%shops %u id 0x%08lx\n" "\tdst %s seq %lu src %s seq %lu", length, - ap->rreq.rreq_type & RREQ_JOIN ? "[J]" : "", - ap->rreq.rreq_type & RREQ_REPAIR ? "[R]" : "", - ap->rreq.rreq_type & RREQ_GRAT ? "[G]" : "", - ap->rreq.rreq_type & RREQ_DEST ? "[D]" : "", - ap->rreq.rreq_type & RREQ_UNKNOWN ? "[U] " : " ", - ap->rreq.rreq_hops, - (unsigned long)EXTRACT_32BITS(&ap->rreq.rreq_id), - ipaddr_string(ndo, &ap->rreq.rreq_da), - (unsigned long)EXTRACT_32BITS(&ap->rreq.rreq_ds), - ipaddr_string(ndo, &ap->rreq.rreq_oa), - (unsigned long)EXTRACT_32BITS(&ap->rreq.rreq_os))); + ap->rreq_type & RREQ_JOIN ? "[J]" : "", + ap->rreq_type & RREQ_REPAIR ? "[R]" : "", + ap->rreq_type & RREQ_GRAT ? "[G]" : "", + ap->rreq_type & RREQ_DEST ? "[D]" : "", + ap->rreq_type & RREQ_UNKNOWN ? "[U] " : " ", + ap->rreq_hops, + (unsigned long)EXTRACT_32BITS(&ap->rreq_id), + ipaddr_string(ndo, &ap->rreq_da), + (unsigned long)EXTRACT_32BITS(&ap->rreq_ds), + ipaddr_string(ndo, &ap->rreq_oa), + (unsigned long)EXTRACT_32BITS(&ap->rreq_os))); + i = length - sizeof(*ap); if (i >= sizeof(struct aodv_ext)) - aodv_extension(ndo, (void *)(&ap->rreq + 1), i); + aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i); + return; + +trunc: + ND_PRINT((ndo, " [|rreq")); } static void -aodv_rrep(netdissect_options *ndo, - const union aodv *ap, const u_char *dat, u_int length) +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; - if (ndo->ndo_snapend < dat) { - ND_PRINT((ndo, " [|aodv]")); - return; - } - i = min(length, (u_int)(ndo->ndo_snapend - dat)); - if (i < sizeof(ap->rrep)) { - ND_PRINT((ndo, " [|rrep]")); - return; - } - i -= sizeof(ap->rrep); + ND_TCHECK(*ap); + if (length < sizeof(*ap)) + goto trunc; ND_PRINT((ndo, " rrep %u %s%sprefix %u hops %u\n" "\tdst %s dseq %lu src %s %lu ms", length, - ap->rrep.rrep_type & RREP_REPAIR ? "[R]" : "", - ap->rrep.rrep_type & RREP_ACK ? "[A] " : " ", - ap->rrep.rrep_ps & RREP_PREFIX_MASK, - ap->rrep.rrep_hops, - ipaddr_string(ndo, &ap->rrep.rrep_da), - (unsigned long)EXTRACT_32BITS(&ap->rrep.rrep_ds), - ipaddr_string(ndo, &ap->rrep.rrep_oa), - (unsigned long)EXTRACT_32BITS(&ap->rrep.rrep_life))); + ap->rrep_type & RREP_REPAIR ? "[R]" : "", + ap->rrep_type & RREP_ACK ? "[A] " : " ", + ap->rrep_ps & RREP_PREFIX_MASK, + ap->rrep_hops, + ipaddr_string(ndo, &ap->rrep_da), + (unsigned long)EXTRACT_32BITS(&ap->rrep_ds), + ipaddr_string(ndo, &ap->rrep_oa), + (unsigned long)EXTRACT_32BITS(&ap->rrep_life))); + i = length - sizeof(*ap); if (i >= sizeof(struct aodv_ext)) - aodv_extension(ndo, (void *)(&ap->rrep + 1), i); + aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i); + return; + +trunc: + ND_PRINT((ndo, " [|rreq")); } static void -aodv_rerr(netdissect_options *ndo, - const union aodv *ap, const u_char *dat, u_int length) +aodv_rerr(netdissect_options *ndo, const u_char *dat, u_int length) { - u_int i; - const struct rerr_unreach *dp = NULL; - int n, trunc; + u_int i, dc; + const struct aodv_rerr *ap = (const struct aodv_rerr *)dat; + const struct rerr_unreach *dp; - if (ndo->ndo_snapend < dat) { - ND_PRINT((ndo, " [|aodv]")); - return; - } - i = min(length, (u_int)(ndo->ndo_snapend - dat)); - if (i < offsetof(struct aodv_rerr, r)) { - ND_PRINT((ndo, " [|rerr]")); - return; - } - i -= offsetof(struct aodv_rerr, r); - dp = &ap->rerr.r.dest[0]; - n = ap->rerr.rerr_dc * sizeof(ap->rerr.r.dest[0]); + ND_TCHECK(*ap); + if (length < sizeof(*ap)) + goto trunc; ND_PRINT((ndo, " rerr %s [items %u] [%u]:", - ap->rerr.rerr_flags & RERR_NODELETE ? "[D]" : "", - ap->rerr.rerr_dc, length)); - trunc = n - (i/sizeof(ap->rerr.r.dest[0])); - for (; i >= sizeof(ap->rerr.r.dest[0]); - ++dp, i -= sizeof(ap->rerr.r.dest[0])) { + ap->rerr_flags & RERR_NODELETE ? "[D]" : "", + ap->rerr_dc, length)); + dp = (struct rerr_unreach *)(dat + sizeof(*ap)); + i = length - sizeof(*ap); + for (dc = ap->rerr_dc; dc != 0; dc--) { + ND_TCHECK(*dp); + if (i < sizeof(*dp)) + goto trunc; ND_PRINT((ndo, " {%s}(%ld)", ipaddr_string(ndo, &dp->u_da), (unsigned long)EXTRACT_32BITS(&dp->u_ds))); + dp++; + i -= sizeof(*dp); } - if (trunc) - ND_PRINT((ndo, "[|rerr]")); + return; + +trunc: + ND_PRINT((ndo, "[|rerr]")); } static void #ifdef INET6 -aodv_v6_rreq(netdissect_options *ndo, - const union aodv *ap, const u_char *dat, u_int length) +aodv_v6_rreq(netdissect_options *ndo, const u_char *dat, u_int length) #else -aodv_v6_rreq(netdissect_options *ndo, - const union aodv *ap _U_, const u_char *dat _U_, u_int length) +aodv_v6_rreq(netdissect_options *ndo, const u_char *dat _U_, u_int length) #endif { #ifdef INET6 u_int i; + const struct aodv_rreq6 *ap = (const struct aodv_rreq6 *)dat; - if (ndo->ndo_snapend < dat) { - ND_PRINT((ndo, " [|aodv]")); - return; - } - i = min(length, (u_int)(ndo->ndo_snapend - dat)); - if (i < sizeof(ap->rreq6)) { - ND_PRINT((ndo, " [|rreq6]")); - return; - } - i -= sizeof(ap->rreq6); + ND_TCHECK(*ap); + if (length < sizeof(*ap)) + goto trunc; ND_PRINT((ndo, " v6 rreq %u %s%s%s%s%shops %u id 0x%08lx\n" "\tdst %s seq %lu src %s seq %lu", length, - ap->rreq6.rreq_type & RREQ_JOIN ? "[J]" : "", - ap->rreq6.rreq_type & RREQ_REPAIR ? "[R]" : "", - ap->rreq6.rreq_type & RREQ_GRAT ? "[G]" : "", - ap->rreq6.rreq_type & RREQ_DEST ? "[D]" : "", - ap->rreq6.rreq_type & RREQ_UNKNOWN ? "[U] " : " ", - ap->rreq6.rreq_hops, - (unsigned long)EXTRACT_32BITS(&ap->rreq6.rreq_id), - ip6addr_string(ndo, &ap->rreq6.rreq_da), - (unsigned long)EXTRACT_32BITS(&ap->rreq6.rreq_ds), - ip6addr_string(ndo, &ap->rreq6.rreq_oa), - (unsigned long)EXTRACT_32BITS(&ap->rreq6.rreq_os))); + ap->rreq_type & RREQ_JOIN ? "[J]" : "", + ap->rreq_type & RREQ_REPAIR ? "[R]" : "", + ap->rreq_type & RREQ_GRAT ? "[G]" : "", + ap->rreq_type & RREQ_DEST ? "[D]" : "", + ap->rreq_type & RREQ_UNKNOWN ? "[U] " : " ", + ap->rreq_hops, + (unsigned long)EXTRACT_32BITS(&ap->rreq_id), + ip6addr_string(ndo, &ap->rreq_da), + (unsigned long)EXTRACT_32BITS(&ap->rreq_ds), + ip6addr_string(ndo, &ap->rreq_oa), + (unsigned long)EXTRACT_32BITS(&ap->rreq_os))); + i = length - sizeof(*ap); if (i >= sizeof(struct aodv_ext)) - aodv_extension(ndo, (void *)(&ap->rreq6 + 1), i); + aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i); + return; + +trunc: + ND_PRINT((ndo, " [|rreq")); #else ND_PRINT((ndo, " v6 rreq %u", length)); #endif } static void #ifdef INET6 -aodv_v6_rrep(netdissect_options *ndo, - const union aodv *ap, const u_char *dat, u_int length) +aodv_v6_rrep(netdissect_options *ndo, const u_char *dat, u_int length) #else -aodv_v6_rrep(netdissect_options *ndo, - const union aodv *ap _U_, const u_char *dat _U_, u_int length) +aodv_v6_rrep(netdissect_options *ndo, const u_char *dat _U_, u_int length) #endif { #ifdef INET6 u_int i; + const struct aodv_rrep6 *ap = (const struct aodv_rrep6 *)dat; - if (ndo->ndo_snapend < dat) { - ND_PRINT((ndo, " [|aodv]")); - return; - } - i = min(length, (u_int)(ndo->ndo_snapend - dat)); - if (i < sizeof(ap->rrep6)) { - ND_PRINT((ndo, " [|rrep6]")); - return; - } - i -= sizeof(ap->rrep6); + ND_TCHECK(*ap); + if (length < sizeof(*ap)) + goto trunc; ND_PRINT((ndo, " rrep %u %s%sprefix %u hops %u\n" "\tdst %s dseq %lu src %s %lu ms", length, - ap->rrep6.rrep_type & RREP_REPAIR ? "[R]" : "", - ap->rrep6.rrep_type & RREP_ACK ? "[A] " : " ", - ap->rrep6.rrep_ps & RREP_PREFIX_MASK, - ap->rrep6.rrep_hops, - ip6addr_string(ndo, &ap->rrep6.rrep_da), - (unsigned long)EXTRACT_32BITS(&ap->rrep6.rrep_ds), - ip6addr_string(ndo, &ap->rrep6.rrep_oa), - (unsigned long)EXTRACT_32BITS(&ap->rrep6.rrep_life))); + ap->rrep_type & RREP_REPAIR ? "[R]" : "", + ap->rrep_type & RREP_ACK ? "[A] " : " ", + ap->rrep_ps & RREP_PREFIX_MASK, + ap->rrep_hops, + ip6addr_string(ndo, &ap->rrep_da), + (unsigned long)EXTRACT_32BITS(&ap->rrep_ds), + ip6addr_string(ndo, &ap->rrep_oa), + (unsigned long)EXTRACT_32BITS(&ap->rrep_life))); + i = length - sizeof(*ap); if (i >= sizeof(struct aodv_ext)) - aodv_extension(ndo, (void *)(&ap->rrep6 + 1), i); + aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i); + return; + +trunc: + ND_PRINT((ndo, " [|rreq")); #else ND_PRINT((ndo, " rrep %u", length)); #endif } static void #ifdef INET6 -aodv_v6_rerr(netdissect_options *ndo, - const union aodv *ap, u_int length) +aodv_v6_rerr(netdissect_options *ndo, const u_char *dat, u_int length) #else -aodv_v6_rerr(netdissect_options *ndo, - const union aodv *ap _U_, u_int length) +aodv_v6_rerr(netdissect_options *ndo, const u_char *dat _U_, u_int length) #endif { #ifdef INET6 - const struct rerr_unreach6 *dp6 = NULL; - int i, j, n, trunc; + u_int i, dc; + const struct aodv_rerr *ap = (const struct aodv_rerr *)dat; + const struct rerr_unreach6 *dp6; - i = length - offsetof(struct aodv_rerr, r); - j = sizeof(ap->rerr.r.dest6[0]); - dp6 = &ap->rerr.r.dest6[0]; - n = ap->rerr.rerr_dc * j; + ND_TCHECK(*ap); + if (length < sizeof(*ap)) + goto trunc; ND_PRINT((ndo, " rerr %s [items %u] [%u]:", - ap->rerr.rerr_flags & RERR_NODELETE ? "[D]" : "", - ap->rerr.rerr_dc, length)); - trunc = n - (i/j); - for (; i -= j >= 0; ++dp6) { + ap->rerr_flags & RERR_NODELETE ? "[D]" : "", + ap->rerr_dc, length)); + dp6 = (struct rerr_unreach6 *)(void *)(ap + 1); + i = length - sizeof(*ap); + for (dc = ap->rerr_dc; dc != 0; dc--) { + ND_TCHECK(*dp6); + if (i < sizeof(*dp6)) + goto trunc; ND_PRINT((ndo, " {%s}(%ld)", ip6addr_string(ndo, &dp6->u_da), (unsigned long)EXTRACT_32BITS(&dp6->u_ds))); + dp6++; + i -= sizeof(*dp6); } - if (trunc) - ND_PRINT((ndo, "[|rerr]")); + return; + +trunc: + ND_PRINT((ndo, "[|rerr]")); #else ND_PRINT((ndo, " rerr %u", length)); #endif } static void #ifdef INET6 -aodv_v6_draft_01_rreq(netdissect_options *ndo, - const union aodv *ap, const u_char *dat, u_int length) +aodv_v6_draft_01_rreq(netdissect_options *ndo, const u_char *dat, u_int length) #else -aodv_v6_draft_01_rreq(netdissect_options *ndo, - const union aodv *ap _U_, const u_char *dat _U_, - u_int length) +aodv_v6_draft_01_rreq(netdissect_options *ndo, const u_char *dat _U_, u_int length) #endif { #ifdef INET6 u_int i; + const struct aodv_rreq6_draft_01 *ap = (const struct aodv_rreq6_draft_01 *)dat; - if (ndo->ndo_snapend < dat) { - ND_PRINT((ndo, " [|aodv]")); - return; - } - i = min(length, (u_int)(ndo->ndo_snapend - dat)); - if (i < sizeof(ap->rreq6_draft_01)) { - ND_PRINT((ndo, " [|rreq6]")); - return; - } - i -= sizeof(ap->rreq6_draft_01); + ND_TCHECK(*ap); + if (length < sizeof(*ap)) + goto trunc; ND_PRINT((ndo, " rreq %u %s%s%s%s%shops %u id 0x%08lx\n" "\tdst %s seq %lu src %s seq %lu", length, - ap->rreq6_draft_01.rreq_type & RREQ_JOIN ? "[J]" : "", - ap->rreq6_draft_01.rreq_type & RREQ_REPAIR ? "[R]" : "", - ap->rreq6_draft_01.rreq_type & RREQ_GRAT ? "[G]" : "", - ap->rreq6_draft_01.rreq_type & RREQ_DEST ? "[D]" : "", - ap->rreq6_draft_01.rreq_type & RREQ_UNKNOWN ? "[U] " : " ", - ap->rreq6_draft_01.rreq_hops, - (unsigned long)EXTRACT_32BITS(&ap->rreq6_draft_01.rreq_id), - ip6addr_string(ndo, &ap->rreq6_draft_01.rreq_da), - (unsigned long)EXTRACT_32BITS(&ap->rreq6_draft_01.rreq_ds), - ip6addr_string(ndo, &ap->rreq6_draft_01.rreq_oa), - (unsigned long)EXTRACT_32BITS(&ap->rreq6_draft_01.rreq_os))); + ap->rreq_type & RREQ_JOIN ? "[J]" : "", + ap->rreq_type & RREQ_REPAIR ? "[R]" : "", + ap->rreq_type & RREQ_GRAT ? "[G]" : "", + ap->rreq_type & RREQ_DEST ? "[D]" : "", + ap->rreq_type & RREQ_UNKNOWN ? "[U] " : " ", + ap->rreq_hops, + (unsigned long)EXTRACT_32BITS(&ap->rreq_id), + ip6addr_string(ndo, &ap->rreq_da), + (unsigned long)EXTRACT_32BITS(&ap->rreq_ds), + ip6addr_string(ndo, &ap->rreq_oa), + (unsigned long)EXTRACT_32BITS(&ap->rreq_os))); + i = length - sizeof(*ap); if (i >= sizeof(struct aodv_ext)) - aodv_extension(ndo, (void *)(&ap->rreq6_draft_01 + 1), i); + aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i); + return; + +trunc: + ND_PRINT((ndo, " [|rreq")); #else ND_PRINT((ndo, " rreq %u", length)); #endif } static void #ifdef INET6 -aodv_v6_draft_01_rrep(netdissect_options *ndo, - const union aodv *ap, const u_char *dat, u_int length) +aodv_v6_draft_01_rrep(netdissect_options *ndo, const u_char *dat, u_int length) #else -aodv_v6_draft_01_rrep(netdissect_options *ndo, - const union aodv *ap _U_, const u_char *dat _U_, - u_int length) +aodv_v6_draft_01_rrep(netdissect_options *ndo, const u_char *dat _U_, u_int length) #endif { #ifdef INET6 u_int i; + const struct aodv_rrep6_draft_01 *ap = (const struct aodv_rrep6_draft_01 *)dat; - if (ndo->ndo_snapend < dat) { - ND_PRINT((ndo, " [|aodv]")); - return; - } - i = min(length, (u_int)(ndo->ndo_snapend - dat)); - if (i < sizeof(ap->rrep6_draft_01)) { - ND_PRINT((ndo, " [|rrep6]")); - return; - } - i -= sizeof(ap->rrep6_draft_01); + ND_TCHECK(*ap); + if (length < sizeof(*ap)) + goto trunc; ND_PRINT((ndo, " rrep %u %s%sprefix %u hops %u\n" "\tdst %s dseq %lu src %s %lu ms", length, - ap->rrep6_draft_01.rrep_type & RREP_REPAIR ? "[R]" : "", - ap->rrep6_draft_01.rrep_type & RREP_ACK ? "[A] " : " ", - ap->rrep6_draft_01.rrep_ps & RREP_PREFIX_MASK, - ap->rrep6_draft_01.rrep_hops, - ip6addr_string(ndo, &ap->rrep6_draft_01.rrep_da), - (unsigned long)EXTRACT_32BITS(&ap->rrep6_draft_01.rrep_ds), - ip6addr_string(ndo, &ap->rrep6_draft_01.rrep_oa), - (unsigned long)EXTRACT_32BITS(&ap->rrep6_draft_01.rrep_life))); + ap->rrep_type & RREP_REPAIR ? "[R]" : "", + ap->rrep_type & RREP_ACK ? "[A] " : " ", + ap->rrep_ps & RREP_PREFIX_MASK, + ap->rrep_hops, + ip6addr_string(ndo, &ap->rrep_da), + (unsigned long)EXTRACT_32BITS(&ap->rrep_ds), + ip6addr_string(ndo, &ap->rrep_oa), + (unsigned long)EXTRACT_32BITS(&ap->rrep_life))); + i = length - sizeof(*ap); if (i >= sizeof(struct aodv_ext)) - aodv_extension(ndo, (void *)(&ap->rrep6_draft_01 + 1), i); + aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i); + return; + +trunc: + ND_PRINT((ndo, " [|rreq")); #else ND_PRINT((ndo, " rrep %u", length)); #endif } static void #ifdef INET6 -aodv_v6_draft_01_rerr(netdissect_options *ndo, - const union aodv *ap, u_int length) +aodv_v6_draft_01_rerr(netdissect_options *ndo, const u_char *dat, u_int length) #else -aodv_v6_draft_01_rerr(netdissect_options *ndo, - const union aodv *ap _U_, u_int length) +aodv_v6_draft_01_rerr(netdissect_options *ndo, const u_char *dat _U_, u_int length) #endif { #ifdef INET6 - const struct rerr_unreach6_draft_01 *dp6 = NULL; - int i, j, n, trunc; + u_int i, dc; + const struct aodv_rerr *ap = (const struct aodv_rerr *)dat; + const struct rerr_unreach6_draft_01 *dp6; - i = length - offsetof(struct aodv_rerr, r); - j = sizeof(ap->rerr.r.dest6_draft_01[0]); - dp6 = &ap->rerr.r.dest6_draft_01[0]; - n = ap->rerr.rerr_dc * j; + ND_TCHECK(*ap); + if (length < sizeof(*ap)) + goto trunc; ND_PRINT((ndo, " rerr %s [items %u] [%u]:", - ap->rerr.rerr_flags & RERR_NODELETE ? "[D]" : "", - ap->rerr.rerr_dc, length)); - trunc = n - (i/j); - for (; i -= j >= 0; ++dp6) { + ap->rerr_flags & RERR_NODELETE ? "[D]" : "", + ap->rerr_dc, length)); + dp6 = (struct rerr_unreach6_draft_01 *)(void *)(ap + 1); + i = length - sizeof(*ap); + for (dc = ap->rerr_dc; dc != 0; dc--) { + ND_TCHECK(*dp6); + if (i < sizeof(*dp6)) + goto trunc; ND_PRINT((ndo, " {%s}(%ld)", ip6addr_string(ndo, &dp6->u_da), (unsigned long)EXTRACT_32BITS(&dp6->u_ds))); + dp6++; + i -= sizeof(*dp6); } - if (trunc) - ND_PRINT((ndo, "[|rerr]")); + return; + +trunc: + ND_PRINT((ndo, "[|rerr]")); #else ND_PRINT((ndo, " rerr %u", length)); #endif } void aodv_print(netdissect_options *ndo, const u_char *dat, u_int length, int is_ip6) { - const union aodv *ap; + uint8_t msg_type; - ap = (union aodv *)dat; - if (ndo->ndo_snapend < dat) { - ND_PRINT((ndo, " [|aodv]")); - return; - } - if (min(length, (u_int)(ndo->ndo_snapend - dat)) < sizeof(ap->rrep_ack)) { - ND_PRINT((ndo, " [|aodv]")); - return; - } + /* + * The message type is the first byte; make sure we have it + * and then fetch it. + */ + ND_TCHECK(*dat); + msg_type = *dat; ND_PRINT((ndo, " aodv")); - switch (ap->rerr.rerr_type) { + switch (msg_type) { case AODV_RREQ: if (is_ip6) - aodv_v6_rreq(ndo, ap, dat, length); + aodv_v6_rreq(ndo, dat, length); else - aodv_rreq(ndo, ap, dat, length); + aodv_rreq(ndo, dat, length); break; case AODV_RREP: if (is_ip6) - aodv_v6_rrep(ndo, ap, dat, length); + aodv_v6_rrep(ndo, dat, length); else - aodv_rrep(ndo, ap, dat, length); + aodv_rrep(ndo, dat, length); break; case AODV_RERR: if (is_ip6) - aodv_v6_rerr(ndo, ap, length); + aodv_v6_rerr(ndo, dat, length); else - aodv_rerr(ndo, ap, dat, length); + aodv_rerr(ndo, dat, length); break; case AODV_RREP_ACK: ND_PRINT((ndo, " rrep-ack %u", length)); break; case AODV_V6_DRAFT_01_RREQ: - aodv_v6_draft_01_rreq(ndo, ap, dat, length); + aodv_v6_draft_01_rreq(ndo, dat, length); break; case AODV_V6_DRAFT_01_RREP: - aodv_v6_draft_01_rrep(ndo, ap, dat, length); + aodv_v6_draft_01_rrep(ndo, dat, length); break; case AODV_V6_DRAFT_01_RERR: - aodv_v6_draft_01_rerr(ndo, ap, length); + aodv_v6_draft_01_rerr(ndo, dat, length); break; case AODV_V6_DRAFT_01_RREP_ACK: ND_PRINT((ndo, " rrep-ack %u", length)); break; default: - ND_PRINT((ndo, " %u %u", ap->rreq.rreq_type, length)); + ND_PRINT((ndo, " type %u %u", msg_type, length)); } + return; + +trunc: + ND_PRINT((ndo, " [|aodv]")); } Index: head/contrib/tcpdump/print-arcnet.c =================================================================== --- head/contrib/tcpdump/print-arcnet.c (revision 285274) +++ head/contrib/tcpdump/print-arcnet.c (revision 285275) @@ -1,361 +1,359 @@ /* * 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 */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "interface.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 { uint8_t arc_shost; uint8_t arc_dhost; uint8_t arc_type; /* * only present for newstyle encoding with LL fragmentation. * Don't use sizeof(anything), use ARC_HDR{,NEW}LEN instead. */ uint8_t arc_flag; uint16_t arc_seqid; /* * only present in exception packets (arc_flag == 0xff) */ uint8_t arc_type2; /* same as arc_type */ uint8_t arc_flag2; /* real flag value */ 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 { uint8_t arc_shost; uint8_t arc_dhost; uint16_t arc_offset; uint8_t arc_type; /* * only present for newstyle encoding with LL fragmentation. * Don't use sizeof(anything), use ARC_LINUX_HDR{,NEW}LEN * instead. */ uint8_t arc_flag; 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, 0 } }; static inline void arcnet_print(netdissect_options *ndo, const u_char *bp, u_int length, int phds, int flag, u_int seqid) { const struct arc_header *ap; const char *arctypename; ap = (const struct arc_header *)bp; if (ndo->ndo_qflag) { ND_PRINT((ndo, "%02x %02x %d: ", ap->arc_shost, ap->arc_dhost, length)); return; } arctypename = tok2str(arctypemap, "%02x", ap->arc_type); if (!phds) { ND_PRINT((ndo, "%02x %02x %s %d: ", ap->arc_shost, ap->arc_dhost, arctypename, length)); return; } if (flag == 0) { ND_PRINT((ndo, "%02x %02x %s seqid %04x %d: ", ap->arc_shost, ap->arc_dhost, arctypename, seqid, length)); return; } if (flag & 1) ND_PRINT((ndo, "%02x %02x %s seqid %04x " "(first of %d fragments) %d: ", ap->arc_shost, ap->arc_dhost, arctypename, seqid, (flag + 3) / 2, length)); else ND_PRINT((ndo, "%02x %02x %s seqid %04x " "(fragment %d) %d: ", ap->arc_shost, 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. */ u_int 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, flag = 0, archdrlen = 0; u_int seqid = 0; u_char arc_type; - if (caplen < ARC_HDRLEN) { + if (caplen < ARC_HDRLEN || length < ARC_HDRLEN) { ND_PRINT((ndo, "[|arcnet]")); return (caplen); } ap = (const struct arc_header *)p; arc_type = 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) { + if (caplen < ARC_HDRNEWLEN || length < ARC_HDRNEWLEN) { arcnet_print(ndo, p, length, 0, 0, 0); ND_PRINT((ndo, "[|phds]")); return (caplen); } if (ap->arc_flag == 0xff) { - if (caplen < ARC_HDRNEWLEN_EXC) { + if (caplen < ARC_HDRNEWLEN_EXC || length < ARC_HDRNEWLEN_EXC) { arcnet_print(ndo, p, length, 0, 0, 0); ND_PRINT((ndo, "[|phds extended]")); return (caplen); } flag = ap->arc_flag2; seqid = EXTRACT_16BITS(&ap->arc_seqid2); archdrlen = ARC_HDRNEWLEN_EXC; } else { flag = ap->arc_flag; seqid = EXTRACT_16BITS(&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. */ return (archdrlen); } if (!arcnet_encap_print(ndo, arc_type, p, length, caplen)) ND_DEFAULTPRINT(p, caplen); return (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. */ u_int 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; - if (caplen < ARC_LINUX_HDRLEN) { + if (caplen < ARC_LINUX_HDRLEN || length < ARC_LINUX_HDRLEN) { ND_PRINT((ndo, "[|arcnet]")); return (caplen); } ap = (const struct arc_linux_header *)p; arc_type = ap->arc_type; switch (arc_type) { default: archdrlen = ARC_LINUX_HDRNEWLEN; - if (caplen < ARC_LINUX_HDRNEWLEN) { + if (caplen < ARC_LINUX_HDRNEWLEN || length < ARC_LINUX_HDRNEWLEN) { ND_PRINT((ndo, "[|arcnet]")); return (caplen); } 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); return (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); -#ifdef INET6 case ARCTYPE_INET6: ip6_print(ndo, p, length); return (1); -#endif /*INET6*/ 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((ndo, "et1 ")); atalk_print(ndo, p, length); return (1); case ARCTYPE_IPX: ipx_print(ndo, p, length); return (1); default: return (0); } } /* * Local Variables: * c-style: bsd * End: */ Index: head/contrib/tcpdump/print-arp.c =================================================================== --- head/contrib/tcpdump/print-arp.c (revision 285274) +++ head/contrib/tcpdump/print-arp.c (revision 285275) @@ -1,416 +1,416 @@ /* * 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. * * $FreeBSD$ */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "interface.h" #include "addrtoname.h" #include "ether.h" #include "ethertype.h" #include "extract.h" /* must come after interface.h */ static const char tstr[] = "[|ARP]"; /* * 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 { u_short 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 */ u_short ar_pro; /* format of protocol address */ u_char ar_hln; /* length of hardware address */ u_char ar_pln; /* length of protocol address */ u_short 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 valif for ATM ARP */ /* * The remaining fields are variable in size, * according to the sizes above. */ #ifdef COMMENT_ONLY u_char ar_sha[]; /* sender hardware address */ u_char ar_spa[]; /* sender protocol address */ u_char ar_tha[]; /* target hardware address */ u_char 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))+ (ap)->ar_hln) #define ar_tha(ap) (((const u_char *)((ap)+1))+ (ap)->ar_hln+(ap)->ar_pln) #define ar_tpa(ap) (((const u_char *)((ap)+1))+2*(ap)->ar_hln+(ap)->ar_pln) }; #define ARP_HDRLEN 8 #define HRD(ap) EXTRACT_16BITS(&(ap)->ar_hrd) #define HRD_LEN(ap) ((ap)->ar_hln) #define PROTO_LEN(ap) ((ap)->ar_pln) #define OP(ap) EXTRACT_16BITS(&(ap)->ar_op) #define PRO(ap) EXTRACT_16BITS(&(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" }, { 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 { u_short aar_hrd; /* format of hardware address */ u_short aar_pro; /* format of protocol address */ u_char aar_shtl; /* length of source ATM number */ u_char 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 */ u_short aar_op; /* same as regular ARP */ u_char aar_spln; /* length of source protocol address */ u_char aar_thtl; /* length of target ATM number */ u_char aar_tstl; /* length of target ATM subaddress */ u_char aar_tpln; /* length of target protocol address */ /* * The remaining fields are variable in size, * according to the sizes above. */ #ifdef COMMENT_ONLY u_char aar_sha[]; /* source ATM number */ u_char aar_ssa[]; /* source ATM subaddress */ u_char aar_spa[]; /* sender protocol address */ u_char aar_tha[]; /* target ATM number */ u_char aar_tsa[]; /* target ATM subaddress */ u_char aar_tpa[]; /* target protocol address */ #endif #define ATMHRD(ap) EXTRACT_16BITS(&(ap)->aar_hrd) #define ATMSHRD_LEN(ap) ((ap)->aar_shtl & ATMARP_LEN_MASK) #define ATMSSLN(ap) ((ap)->aar_sstl & ATMARP_LEN_MASK) #define ATMSPROTO_LEN(ap) ((ap)->aar_spln) #define ATMOP(ap) EXTRACT_16BITS(&(ap)->aar_op) #define ATMPRO(ap) EXTRACT_16BITS(&(ap)->aar_pro) #define ATMTHRD_LEN(ap) ((ap)->aar_thtl & ATMARP_LEN_MASK) #define ATMTSLN(ap) ((ap)->aar_tstl & ATMARP_LEN_MASK) #define ATMTPROTO_LEN(ap) ((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 u_char ezero[6]; 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((ndo, "")); else { ND_PRINT((ndo, "%s", linkaddr_string(ndo, ha, LINKADDR_ATM, ha_len))); if (srca_len != 0) ND_PRINT((ndo, ",%s", linkaddr_string(ndo, srca, LINKADDR_ATM, srca_len))); } } 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(*ap); hrd = ATMHRD(ap); pro = ATMPRO(ap); op = ATMOP(ap); if (!ND_TTEST2(*aar_tpa(ap), ATMTPROTO_LEN(ap))) { ND_PRINT((ndo, "%s", tstr)); ND_DEFAULTPRINT((const u_char *)ap, length); return; } if (!ndo->ndo_eflag) { ND_PRINT((ndo, "ARP, ")); } if ((pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL) || ATMSPROTO_LEN(ap) != 4 || ATMTPROTO_LEN(ap) != 4 || ndo->ndo_vflag) { ND_PRINT((ndo, "%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 know about the address formats */ if (!ndo->ndo_vflag) { goto out; } } /* print operation */ ND_PRINT((ndo, "%s%s ", ndo->ndo_vflag ? ", " : "", tok2str(arpop_values, "Unknown (%u)", op))); switch (op) { case ARPOP_REQUEST: ND_PRINT((ndo, "who-has %s", ipaddr_string(ndo, ATMTPA(ap)))); if (ATMTHRD_LEN(ap) != 0) { ND_PRINT((ndo, " (")); atmarp_addr_print(ndo, ATMTHA(ap), ATMTHRD_LEN(ap), ATMTSA(ap), ATMTSLN(ap)); ND_PRINT((ndo, ")")); } ND_PRINT((ndo, "tell %s", ipaddr_string(ndo, ATMSPA(ap)))); break; case ARPOP_REPLY: ND_PRINT((ndo, "%s is-at ", ipaddr_string(ndo, ATMSPA(ap)))); atmarp_addr_print(ndo, ATMSHA(ap), ATMSHRD_LEN(ap), ATMSSA(ap), ATMSSLN(ap)); break; case ARPOP_INVREQUEST: ND_PRINT((ndo, "who-is ")); atmarp_addr_print(ndo, ATMTHA(ap), ATMTHRD_LEN(ap), ATMTSA(ap), ATMTSLN(ap)); ND_PRINT((ndo, " 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((ndo, "at %s", ipaddr_string(ndo, ATMSPA(ap)))); break; case ARPOP_NAK: ND_PRINT((ndo, "for %s", ipaddr_string(ndo, ATMSPA(ap)))); break; default: ND_DEFAULTPRINT((const u_char *)ap, caplen); return; } out: ND_PRINT((ndo, ", length %u", length)); return; trunc: ND_PRINT((ndo, "%s", tstr)); } 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; ap = (const struct arp_pkthdr *)bp; ND_TCHECK(*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 linkaddr_string(ndo, ) 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; } if (!ND_TTEST2(*ar_tpa(ap), PROTO_LEN(ap))) { ND_PRINT((ndo, "%s", tstr)); ND_DEFAULTPRINT((const u_char *)ap, length); return; } if (!ndo->ndo_eflag) { ND_PRINT((ndo, "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((ndo, "%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 know about the address formats */ if (!ndo->ndo_vflag) { goto out; } } /* print operation */ ND_PRINT((ndo, "%s%s ", ndo->ndo_vflag ? ", " : "", tok2str(arpop_values, "Unknown (%u)", op))); switch (op) { case ARPOP_REQUEST: ND_PRINT((ndo, "who-has %s", ipaddr_string(ndo, TPA(ap)))); if (memcmp((const char *)ezero, (const char *)THA(ap), HRD_LEN(ap)) != 0) ND_PRINT((ndo, " (%s)", linkaddr_string(ndo, THA(ap), linkaddr, HRD_LEN(ap)))); ND_PRINT((ndo, " tell %s", ipaddr_string(ndo, SPA(ap)))); break; case ARPOP_REPLY: ND_PRINT((ndo, "%s is-at %s", ipaddr_string(ndo, SPA(ap)), linkaddr_string(ndo, SHA(ap), linkaddr, HRD_LEN(ap)))); break; case ARPOP_REVREQUEST: ND_PRINT((ndo, "who-is %s tell %s", linkaddr_string(ndo, THA(ap), linkaddr, HRD_LEN(ap)), linkaddr_string(ndo, SHA(ap), linkaddr, HRD_LEN(ap)))); break; case ARPOP_REVREPLY: ND_PRINT((ndo, "%s at %s", linkaddr_string(ndo, THA(ap), linkaddr, HRD_LEN(ap)), ipaddr_string(ndo, TPA(ap)))); break; case ARPOP_INVREQUEST: ND_PRINT((ndo, "who-is %s tell %s", linkaddr_string(ndo, THA(ap), linkaddr, HRD_LEN(ap)), linkaddr_string(ndo, SHA(ap), linkaddr, HRD_LEN(ap)))); break; case ARPOP_INVREPLY: ND_PRINT((ndo,"%s at %s", - linkaddr_string(ndo, THA(ap), linkaddr, HRD_LEN(ap)), - ipaddr_string(ndo, TPA(ap)))); + linkaddr_string(ndo, SHA(ap), linkaddr, HRD_LEN(ap)), + ipaddr_string(ndo, SPA(ap)))); break; default: ND_DEFAULTPRINT((const u_char *)ap, caplen); return; } out: ND_PRINT((ndo, ", length %u", length)); return; trunc: ND_PRINT((ndo, "%s", tstr)); } /* * Local Variables: * c-style: bsd * End: */ Index: head/contrib/tcpdump/print-ascii.c =================================================================== --- head/contrib/tcpdump/print-ascii.c (revision 285274) +++ head/contrib/tcpdump/print-ascii.c (revision 285275) @@ -1,196 +1,208 @@ /* $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. */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "interface.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; register u_char s; + caplength = (ndo->ndo_snapend >= cp) ? ndo->ndo_snapend - cp : 0; + if (length > caplength) + length = caplength; ND_PRINT((ndo, "\n")); while (length > 0) { s = *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 && *cp != '\n') ND_PRINT((ndo, ".")); } else { if (!ND_ISGRAPH(s) && (s != '\t' && s != ' ' && s != '\n')) ND_PRINT((ndo, ".")); else ND_PRINT((ndo, "%c", s)); } } } void hex_and_ascii_print_with_offset(netdissect_options *ndo, register const char *ident, register const u_char *cp, register u_int length, register u_int oset) { + u_int caplength; register u_int i; register int s1, s2; register int nshorts; char hexstuff[HEXDUMP_SHORTS_PER_LINE*HEXDUMP_HEXSTUFF_PER_SHORT+1], *hsp; char asciistuff[ASCII_LINELENGTH+1], *asp; + caplength = (ndo->ndo_snapend >= cp) ? ndo->ndo_snapend - cp : 0; + if (length > caplength) + length = caplength; nshorts = length / sizeof(u_short); i = 0; hsp = hexstuff; asp = asciistuff; while (--nshorts >= 0) { s1 = *cp++; s2 = *cp++; (void)snprintf(hsp, sizeof(hexstuff) - (hsp - hexstuff), " %02x%02x", s1, s2); hsp += HEXDUMP_HEXSTUFF_PER_SHORT; *(asp++) = (ND_ISGRAPH(s1) ? s1 : '.'); *(asp++) = (ND_ISGRAPH(s2) ? s2 : '.'); i++; if (i >= HEXDUMP_SHORTS_PER_LINE) { *hsp = *asp = '\0'; ND_PRINT((ndo, "%s0x%04x: %-*s %s", ident, oset, HEXDUMP_HEXSTUFF_PER_LINE, hexstuff, asciistuff)); i = 0; hsp = hexstuff; asp = asciistuff; oset += HEXDUMP_BYTES_PER_LINE; } } if (length & 1) { s1 = *cp++; (void)snprintf(hsp, sizeof(hexstuff) - (hsp - hexstuff), " %02x", s1); hsp += 3; *(asp++) = (ND_ISGRAPH(s1) ? s1 : '.'); ++i; } if (i > 0) { *hsp = *asp = '\0'; ND_PRINT((ndo, "%s0x%04x: %-*s %s", ident, oset, HEXDUMP_HEXSTUFF_PER_LINE, hexstuff, asciistuff)); } } void hex_and_ascii_print(netdissect_options *ndo, register const char *ident, register const u_char *cp, register 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; register u_int i, s; register int nshorts; + caplength = (ndo->ndo_snapend >= cp) ? ndo->ndo_snapend - cp : 0; + if (length > caplength) + length = caplength; nshorts = (u_int) length / sizeof(u_short); i = 0; while (--nshorts >= 0) { if ((i++ % 8) == 0) { ND_PRINT((ndo,"%s0x%04x: ", ident, oset)); oset += HEXDUMP_BYTES_PER_LINE; } s = *cp++; ND_PRINT((ndo," %02x%02x", s, *cp++)); } if (length & 1) { if ((i % 8) == 0) ND_PRINT((ndo,"%s0x%04x: ", ident, oset)); ND_PRINT((ndo," %02x", *cp)); } } /* * just for completeness */ 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 */ Index: head/contrib/tcpdump/print-atm.c =================================================================== --- head/contrib/tcpdump/print-atm.c (revision 285274) +++ head/contrib/tcpdump/print-atm.c (revision 285275) @@ -1,463 +1,463 @@ /* * 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. * * $FreeBSD$ */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "interface.h" #include "extract.h" #include "addrtoname.h" #include "atm.h" #include "atmuni31.h" #include "llc.h" static const char tstr[] = "[|atm]"; #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 tok *oam_functype_values[16] = { NULL, oam_fm_functype_values, /* 1 */ oam_pm_functype_values, /* 2 */ NULL, NULL, NULL, NULL, NULL, oam_ad_functype_values, /* 8 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL }; /* * Print an RFC 1483 LLC-encapsulated ATM frame. */ static void atm_llc_print(netdissect_options *ndo, const u_char *p, int length, int caplen) { u_short extracted_ethertype; if (!llc_print(ndo, p, length, caplen, NULL, NULL, &extracted_ethertype)) { /* ether_type not known, print raw packet */ if (extracted_ethertype) { ND_PRINT((ndo, "(LLC %s) ", etherproto_string(htons(extracted_ethertype)))); } if (!ndo->ndo_suppress_default_print) ND_DEFAULTPRINT(p, caplen); } } /* * 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. */ u_int 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; if (caplen < 1 || length < 1) { ND_PRINT((ndo, "%s", tstr)); return (caplen); } /* Cisco Style NLPID ? */ if (*p == LLC_UI) { if (ndo->ndo_eflag) ND_PRINT((ndo, "CNLPID ")); isoclns_print(ndo, p + 1, length - 1, caplen - 1); return hdrlen; } /* * Must have at least a DSAP, an SSAP, and the first byte of the * control field. */ if (caplen < 3 || length < 3) { ND_PRINT((ndo, "%s", tstr)); return (caplen); } /* * 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 = EXTRACT_24BITS(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 (caplen < 20 || length < 20) { ND_PRINT((ndo, "%s", tstr)); return (caplen); } if (ndo->ndo_eflag) ND_PRINT((ndo, "%08x%08x %08x%08x ", EXTRACT_32BITS(p), EXTRACT_32BITS(p+4), EXTRACT_32BITS(p+8), EXTRACT_32BITS(p+12))); p += 20; length -= 20; caplen -= 20; hdrlen += 20; } atm_llc_print(ndo, p, length, caplen); return (hdrlen); } /* * 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, int caplen) { uint32_t call_ref; if (caplen < PROTO_POS) { ND_PRINT((ndo, "%s", tstr)); return; } if (p[PROTO_POS] == Q2931) { /* * protocol:Q.2931 for User to Network Interface * (UNI 3.1) signalling */ ND_PRINT((ndo, "Q.2931")); if (caplen < MSG_TYPE_POS) { ND_PRINT((ndo, " %s", tstr)); return; } ND_PRINT((ndo, ":%s ", tok2str(msgtype2str, "msgtype#%d", 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 = EXTRACT_24BITS(&p[CALL_REF_POS]); ND_PRINT((ndo, "CALL_REF:0x%06x", call_ref)); } else { /* SCCOP with some unknown protocol atop it */ ND_PRINT((ndo, "SSCOP, proto %d ", 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) { if (ndo->ndo_eflag) ND_PRINT((ndo, "VPI:%u VCI:%u ", vpi, vci)); if (vpi == 0) { switch (vci) { case VCI_PPC: sig_print(ndo, p, caplen); return; case VCI_BCC: ND_PRINT((ndo, "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((ndo, "meta: ")); return; case VCI_ILMIC: ND_PRINT((ndo, "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 { uint8_t loopback_indicator; uint8_t correlation_tag[4]; uint8_t loopback_id[12]; uint8_t source_id[12]; uint8_t unused[16]; }; struct oam_fm_ais_rdi_t { uint8_t failure_type; uint8_t failure_location[16]; uint8_t unused[28]; }; int oam_print (netdissect_options *ndo, - const u_char *p, u_int length, u_int hec) { - + 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; union { const struct oam_fm_loopback_t *oam_fm_loopback; const struct oam_fm_ais_rdi_t *oam_fm_ais_rdi; } oam_ptr; cell_header = EXTRACT_32BITS(p+hec); cell_type = ((*(p+ATM_HDR_LEN_NOHEC+hec))>>4) & 0x0f; func_type = (*(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((ndo, "%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 1; } ND_PRINT((ndo, "\n\tcell-type %s (%u)", tok2str(oam_celltype_values, "unknown", cell_type), cell_type)); if (oam_functype_values[cell_type] == NULL) ND_PRINT((ndo, ", func-type unknown (%u)", func_type)); else ND_PRINT((ndo, ", func-type %s (%u)", tok2str(oam_functype_values[cell_type],"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_PRINT((ndo, "\n\tLoopback-Indicator %s, Correlation-Tag 0x%08x", tok2str(oam_fm_loopback_indicator_values, "Unknown", oam_ptr.oam_fm_loopback->loopback_indicator & OAM_FM_LOOPBACK_INDICATOR_MASK), EXTRACT_32BITS(&oam_ptr.oam_fm_loopback->correlation_tag))); ND_PRINT((ndo, "\n\tLocation-ID ")); for (idx = 0; idx < sizeof(oam_ptr.oam_fm_loopback->loopback_id); idx++) { if (idx % 2) { ND_PRINT((ndo, "%04x ", EXTRACT_16BITS(&oam_ptr.oam_fm_loopback->loopback_id[idx]))); } } ND_PRINT((ndo, "\n\tSource-ID ")); for (idx = 0; idx < sizeof(oam_ptr.oam_fm_loopback->source_id); idx++) { if (idx % 2) { ND_PRINT((ndo, "%04x ", EXTRACT_16BITS(&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_PRINT((ndo, "\n\tFailure-type 0x%02x", oam_ptr.oam_fm_ais_rdi->failure_type)); ND_PRINT((ndo, "\n\tLocation-ID ")); for (idx = 0; idx < sizeof(oam_ptr.oam_fm_ais_rdi->failure_location); idx++) { if (idx % 2) { ND_PRINT((ndo, "%04x ", EXTRACT_16BITS(&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 = EXTRACT_16BITS(p + OAM_CELLTYPE_FUNCTYPE_LEN + OAM_FUNCTION_SPECIFIC_LEN) & OAM_CRC10_MASK; cksum_shouldbe = verify_crc10_cksum(0, p, OAM_PAYLOAD_LEN); ND_PRINT((ndo, "\n\tcksum 0x%03x (%scorrect)", cksum, cksum_shouldbe == 0 ? "" : "in")); return 1; } Index: head/contrib/tcpdump/print-babel.c =================================================================== --- head/contrib/tcpdump/print-babel.c (revision 285274) +++ head/contrib/tcpdump/print-babel.c (revision 285275) @@ -1,603 +1,606 @@ /* * 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. */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "interface.h" #include "addrtoname.h" #include "extract.h" static const char tstr[] = "[|babel]"; 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) { + const u_char *cp, u_int length) +{ ND_PRINT((ndo, "babel")); ND_TCHECK2(*cp, 4); if(cp[0] != 42) { ND_PRINT((ndo, " malformed header")); return; } else { ND_PRINT((ndo, " %d", cp[1])); } switch(cp[1]) { case 2: babel_print_v2(ndo, cp, length); break; default: ND_PRINT((ndo, " unknown version")); break; } return; trunc: ND_PRINT((ndo, " %s", tstr)); return; } /* 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_REQUEST 9 #define MESSAGE_MH_REQUEST 10 #define MESSAGE_TSPC 11 #define MESSAGE_HMAC 12 /* sub-TLVs */ #define MESSAGE_SUB_PAD1 0 #define MESSAGE_SUB_PADN 1 #define MESSAGE_SUB_DIVERSITY 2 #define MESSAGE_SUB_TIMESTAMP 3 /* Diversity sub-TLV channel codes */ static const struct tok diversity_str[] = { { 0, "reserved" }, { 255, "all" }, { 0, NULL } }; static const char * format_id(const u_char *id) { static char buf[25]; snprintf(buf, 25, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", id[0], id[1], id[2], id[3], id[4], id[5], id[6], 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]; if(plen >= 96 && memcmp(prefix, v4prefix, 12) == 0) snprintf(buf, 50, "%s/%u", ipaddr_string(ndo, prefix + 12), plen - 96); else #ifdef INET6 snprintf(buf, 50, "%s/%u", ip6addr_string(ndo, prefix), plen); #else snprintf(buf, 50, "IPv6 addresses not supported"); #endif buf[49] = '\0'; return buf; } static const char * format_address(netdissect_options *ndo, const u_char *prefix) { if(memcmp(prefix, v4prefix, 12) == 0) return ipaddr_string(ndo, prefix + 12); else #ifdef INET6 return ip6addr_string(ndo, prefix); #else return "IPv6 addresses not supported"; #endif } 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 interferring 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) { + 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 = *cp++; if(subtype == MESSAGE_SUB_PAD1) { ND_PRINT((ndo, " sub-pad1")); continue; } if(cp == ep) goto corrupt; sublen = *cp++; if(cp + sublen > ep) goto corrupt; switch(subtype) { case MESSAGE_SUB_PADN: ND_PRINT((ndo, " sub-padn")); cp += sublen; break; case MESSAGE_SUB_DIVERSITY: ND_PRINT((ndo, " sub-diversity")); if (sublen == 0) { ND_PRINT((ndo, " empty")); break; } sep = " "; while(sublen--) { ND_PRINT((ndo, "%s%s", sep, tok2str(diversity_str, "%u", *cp++))); sep = "-"; } if(tlv_type != MESSAGE_UPDATE) ND_PRINT((ndo, " (bogus)")); break; case MESSAGE_SUB_TIMESTAMP: ND_PRINT((ndo, " sub-timestamp")); if(tlv_type == MESSAGE_HELLO) { if(sublen < 4) goto corrupt; t1 = EXTRACT_32BITS(cp); ND_PRINT((ndo, " %s", format_timestamp(t1))); } else if(tlv_type == MESSAGE_IHU) { if(sublen < 8) goto corrupt; t1 = EXTRACT_32BITS(cp); ND_PRINT((ndo, " %s", format_timestamp(t1))); t2 = EXTRACT_32BITS(cp + 4); ND_PRINT((ndo, "|%s", format_timestamp(t2))); } else ND_PRINT((ndo, " (bogus)")); cp += sublen; break; default: ND_PRINT((ndo, " sub-unknown-0x%02x", subtype)); cp += sublen; } /* switch */ } /* while */ return; corrupt: ND_PRINT((ndo, " (corrupt)")); } #define ICHECK(i, l) \ if ((i) + (l) > bodylen || (i) + (l) > length) goto corrupt; static void babel_print_v2(netdissect_options *ndo, - const u_char *cp, u_int length) { + const u_char *cp, u_int length) +{ u_int i; u_short bodylen; 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}; ND_TCHECK2(*cp, 4); if (length < 4) goto corrupt; bodylen = EXTRACT_16BITS(cp + 2); ND_PRINT((ndo, " (%u)", bodylen)); /* Process the TLVs in the body */ i = 0; while(i < bodylen) { const u_char *message; u_int type, len; message = cp + 4 + i; ND_TCHECK2(*message, 1); if((type = message[0]) == MESSAGE_PAD1) { ND_PRINT((ndo, ndo->ndo_vflag ? "\n\tPad 1" : " pad1")); i += 1; continue; } ND_TCHECK2(*message, 2); ICHECK(i, 2); len = message[1]; ND_TCHECK2(*message, 2 + len); ICHECK(i, 2 + len); switch(type) { case MESSAGE_PADN: { if (!ndo->ndo_vflag) ND_PRINT((ndo, " padN")); else ND_PRINT((ndo, "\n\tPad %d", len + 2)); } break; case MESSAGE_ACK_REQ: { u_short nonce, interval; if (!ndo->ndo_vflag) ND_PRINT((ndo, " ack-req")); else { ND_PRINT((ndo, "\n\tAcknowledgment Request ")); if(len < 6) goto corrupt; nonce = EXTRACT_16BITS(message + 4); interval = EXTRACT_16BITS(message + 6); ND_PRINT((ndo, "%04x %s", nonce, format_interval(interval))); } } break; case MESSAGE_ACK: { u_short nonce; if (!ndo->ndo_vflag) ND_PRINT((ndo, " ack")); else { ND_PRINT((ndo, "\n\tAcknowledgment ")); if(len < 2) goto corrupt; nonce = EXTRACT_16BITS(message + 2); ND_PRINT((ndo, "%04x", nonce)); } } break; case MESSAGE_HELLO: { u_short seqno, interval; if (!ndo->ndo_vflag) ND_PRINT((ndo, " hello")); else { ND_PRINT((ndo, "\n\tHello ")); if(len < 6) goto corrupt; seqno = EXTRACT_16BITS(message + 4); interval = EXTRACT_16BITS(message + 6); ND_PRINT((ndo, "seqno %u interval %s", seqno, format_interval(interval))); /* Extra data. */ if(len > 6) subtlvs_print(ndo, message + 8, message + 2 + len, type); } } break; case MESSAGE_IHU: { unsigned short txcost, interval; if (!ndo->ndo_vflag) ND_PRINT((ndo, " ihu")); else { u_char address[16]; int rc; ND_PRINT((ndo, "\n\tIHU ")); if(len < 6) goto corrupt; txcost = EXTRACT_16BITS(message + 4); interval = EXTRACT_16BITS(message + 6); rc = network_address(message[2], message + 8, len - 6, address); if(rc < 0) { ND_PRINT((ndo, "%s", tstr)); break; } ND_PRINT((ndo, "%s txcost %u interval %s", format_address(ndo, address), txcost, 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((ndo, " router-id")); else { ND_PRINT((ndo, "\n\tRouter Id")); if(len < 10) goto corrupt; ND_PRINT((ndo, " %s", format_id(message + 4))); } } break; case MESSAGE_NH: { if (!ndo->ndo_vflag) ND_PRINT((ndo, " nh")); else { int rc; u_char nh[16]; ND_PRINT((ndo, "\n\tNext Hop")); if(len < 2) goto corrupt; rc = network_address(message[2], message + 4, len - 2, nh); if(rc < 0) goto corrupt; ND_PRINT((ndo, " %s", format_address(ndo, nh))); } } break; case MESSAGE_UPDATE: { if (!ndo->ndo_vflag) { ND_PRINT((ndo, " update")); if(len < 1) ND_PRINT((ndo, "/truncated")); else ND_PRINT((ndo, "%s%s%s", (message[3] & 0x80) ? "/prefix": "", (message[3] & 0x40) ? "/id" : "", (message[3] & 0x3f) ? "/unknown" : "")); } else { u_short interval, seqno, metric; u_char plen; int rc; u_char prefix[16]; ND_PRINT((ndo, "\n\tUpdate")); if(len < 10) goto corrupt; plen = message[4] + (message[2] == 1 ? 96 : 0); rc = network_prefix(message[2], message[4], message[5], message + 12, message[2] == 1 ? v4_prefix : v6_prefix, len - 10, prefix); if(rc < 0) goto corrupt; interval = EXTRACT_16BITS(message + 6); seqno = EXTRACT_16BITS(message + 8); metric = EXTRACT_16BITS(message + 10); ND_PRINT((ndo, "%s%s%s %s metric %u seqno %u interval %s", (message[3] & 0x80) ? "/prefix": "", (message[3] & 0x40) ? "/id" : "", (message[3] & 0x3f) ? "/unknown" : "", format_prefix(ndo, prefix, plen), metric, seqno, format_interval_update(interval))); if(message[3] & 0x80) { if(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_REQUEST: { if (!ndo->ndo_vflag) ND_PRINT((ndo, " request")); else { int rc; u_char prefix[16], plen; ND_PRINT((ndo, "\n\tRequest ")); if(len < 2) goto corrupt; plen = message[3] + (message[2] == 1 ? 96 : 0); rc = network_prefix(message[2], message[3], 0, message + 4, NULL, len - 2, prefix); if(rc < 0) goto corrupt; ND_PRINT((ndo, "for %s", message[2] == 0 ? "any" : format_prefix(ndo, prefix, plen))); } } break; case MESSAGE_MH_REQUEST : { if (!ndo->ndo_vflag) ND_PRINT((ndo, " mh-request")); else { int rc; u_short seqno; u_char prefix[16], plen; ND_PRINT((ndo, "\n\tMH-Request ")); if(len < 14) goto corrupt; seqno = EXTRACT_16BITS(message + 4); rc = network_prefix(message[2], message[3], 0, message + 16, NULL, len - 14, prefix); if(rc < 0) goto corrupt; plen = message[3] + (message[2] == 1 ? 96 : 0); ND_PRINT((ndo, "(%u hops) for %s seqno %u id %s", message[6], format_prefix(ndo, prefix, plen), seqno, format_id(message + 8))); } } break; case MESSAGE_TSPC : if (!ndo->ndo_vflag) ND_PRINT((ndo, " tspc")); else { ND_PRINT((ndo, "\n\tTS/PC ")); if(len < 6) goto corrupt; ND_PRINT((ndo, "timestamp %u packetcounter %u", EXTRACT_32BITS (message + 4), EXTRACT_16BITS(message + 2))); } break; case MESSAGE_HMAC : { if (!ndo->ndo_vflag) ND_PRINT((ndo, " hmac")); else { unsigned j; ND_PRINT((ndo, "\n\tHMAC ")); if(len < 18) goto corrupt; ND_PRINT((ndo, "key-id %u digest-%u ", EXTRACT_16BITS(message + 2), len - 2)); for (j = 0; j < len - 2; j++) ND_PRINT((ndo, "%02X", message[4 + j])); } } break; default: if (!ndo->ndo_vflag) ND_PRINT((ndo, " unknown")); else ND_PRINT((ndo, "\n\tUnknown message type %d", type)); } i += len + 2; } return; trunc: ND_PRINT((ndo, " %s", tstr)); return; corrupt: ND_PRINT((ndo, " (corrupt)")); return; } Index: head/contrib/tcpdump/print-bgp.c =================================================================== --- head/contrib/tcpdump/print-bgp.c (revision 285274) +++ head/contrib/tcpdump/print-bgp.c (revision 285275) @@ -1,2780 +1,2783 @@ /* * 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@juniper.net) for more * complete BGP support. */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "interface.h" #include "addrtoname.h" #include "extract.h" #include "af.h" #include "l2vpn.h" struct bgp { uint8_t bgp_marker[16]; uint16_t bgp_len; 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 { uint8_t bgpo_marker[16]; uint16_t bgpo_len; uint8_t bgpo_type; uint8_t bgpo_version; uint16_t bgpo_myas; uint16_t bgpo_holdtime; uint32_t bgpo_id; uint8_t bgpo_optlen; /* options should follow */ }; #define BGP_OPEN_SIZE 29 /* unaligned */ struct bgp_opt { uint8_t bgpopt_type; 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 { uint8_t bgpn_marker[16]; uint16_t bgpn_len; uint8_t bgpn_type; uint8_t bgpn_major; uint8_t bgpn_minor; }; #define BGP_NOTIFICATION_SIZE 21 /* unaligned */ struct bgp_route_refresh { uint8_t bgp_marker[16]; uint16_t len; uint8_t type; uint8_t afi[2]; /* the compiler messes this structure up */ uint8_t res; /* when doing misaligned sequences of int8 and int16 */ uint8_t safi; /* afi should be int16 - so we have to access it using */ }; /* EXTRACT_16BITS(&bgp_route_refresh->afi) (sigh) */ #define BGP_ROUTE_REFRESH_SIZE 23 #define bgp_attr_lenlen(flags, p) \ (((flags) & 0x10) ? 2 : 1) #define bgp_attr_len(flags, p) \ (((flags) & 0x10) ? EXTRACT_16BITS(p) : *(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 /* RFC1998 */ #define BGPTYPE_CLUSTER_LIST 10 /* RFC1998 */ #define BGPTYPE_DPA 11 /* draft-ietf-idr-bgp-dpa */ #define BGPTYPE_ADVERTISERS 12 /* RFC1863 */ #define BGPTYPE_RCID_PATH 13 /* RFC1863 */ #define BGPTYPE_MP_REACH_NLRI 14 /* RFC2283 */ #define BGPTYPE_MP_UNREACH_NLRI 15 /* RFC2283 */ #define BGPTYPE_EXTD_COMMUNITIES 16 /* draft-ietf-idr-bgp-ext-communities */ #define BGPTYPE_AS4_PATH 17 /* RFC4893 */ #define BGPTYPE_AGGREGATOR4 18 /* RFC4893 */ #define BGPTYPE_PMSI_TUNNEL 22 /* draft-ietf-l3vpn-2547bis-mcast-bgp-02.txt */ #define BGPTYPE_ATTR_SET 128 /* draft-marques-ppvpn-ibgp */ #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_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 #define BGP_CAPCODE_RR 2 #define BGP_CAPCODE_ORF 3 /* XXX */ #define BGP_CAPCODE_RESTART 64 /* draft-ietf-idr-restart-05 */ #define BGP_CAPCODE_AS_NEW 65 /* XXX */ #define BGP_CAPCODE_DYN_CAP 67 /* XXX */ #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_RESTART, "Graceful Restart"}, { BGP_CAPCODE_AS_NEW, "32-Bit AS Number"}, { BGP_CAPCODE_DYN_CAP, "Dynamic Capability"}, { 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} }; /* draft-ietf-idr-cease-subcode-02 */ #define BGP_NOTIFY_MINOR_CEASE_MAXPRFX 1 static const struct tok bgp_notify_minor_cease_values[] = { { BGP_NOTIFY_MINOR_CEASE_MAXPRFX, "Maximum Number of Prefixes Reached"}, { 2, "Administratively Shutdown"}, { 3, "Peer Unconfigured"}, { 4, "Administratively 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_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} }; /* Subsequent address family identifier, RFC2283 section 7 */ #define SAFNUM_RES 0 #define SAFNUM_UNICAST 1 #define SAFNUM_MULTICAST 2 #define SAFNUM_UNIMULTICAST 3 /* labeled BGP RFC3107 */ #define SAFNUM_LABUNICAST 4 /* draft-ietf-l3vpn-2547bis-mcast-bgp-02.txt */ #define SAFNUM_MULTICAST_VPN 5 #define SAFNUM_TUNNEL 64 /* XXX */ #define SAFNUM_VPLS 65 /* XXX */ /* draft-nalawade-idr-mdt-safi-03 */ #define SAFNUM_MDT 66 /* Section 4.3.4 of draft-rosen-rfc2547bis-03.txt */ #define SAFNUM_VPNUNICAST 128 #define SAFNUM_VPNMULTICAST 129 #define SAFNUM_VPNUNIMULTICAST 130 /* draft-marques-ppvpn-rt-constrain-01.txt */ #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_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 - draft-ietf-idr-bgp-ext-communities-05 */ #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 compatability */ #define BGP_EXT_COM_VPN_ORIGIN3 0x0205 /* duplicate - keep for backwards compatability */ #define BGP_EXT_COM_VPN_ORIGIN4 0x8005 /* duplicate - keep for backwards compatability */ #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 compatability */ #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 compatability */ #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) */ /* http://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_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}, }; /* 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 }, }; #define TOKBUFSIZE 128 static char astostr[20]; /* * 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, int 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, u_int buflen) { struct in_addr addr; u_int plen, plenbytes; ND_TCHECK(pptr[0]); ITEMCHECK(1); plen = pptr[0]; if (32 < plen) return -1; itemlen -= 1; memset(&addr, 0, sizeof(addr)); plenbytes = (plen + 7) / 8; ND_TCHECK2(pptr[1], plenbytes); ITEMCHECK(plenbytes); memcpy(&addr, &pptr[1], plenbytes); if (plen % 8) { ((u_char *)&addr)[plenbytes - 1] &= ((0xff00 >> (plen % 8)) & 0xff); } snprintf(buf, buflen, "%s/%d", getname(ndo, (u_char *)&addr), plen); return 1 + plenbytes; trunc: return -2; badtlv: return -3; } static int decode_labeled_prefix4(netdissect_options *ndo, const u_char *pptr, u_int itemlen, char *buf, u_int buflen) { struct in_addr addr; u_int plen, plenbytes; /* prefix length and label = 4 bytes */ ND_TCHECK2(pptr[0], 4); ITEMCHECK(4); plen = pptr[0]; /* 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 a single BGP message + 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; ND_TCHECK2(pptr[4], plenbytes); ITEMCHECK(plenbytes); memcpy(&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/%d, label:%u %s", getname(ndo, (u_char *)&addr), plen, EXTRACT_24BITS(pptr+1)>>4, ((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 dependend on address length. */ static char * bgp_vpn_ip_print(netdissect_options *ndo, - const u_char *pptr, u_int addr_length) { + 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(struct in_addr) << 3): /* 32 */ ND_TCHECK2(pptr[0], sizeof(struct in_addr)); snprintf(pos, sizeof(addr), "%s", ipaddr_string(ndo, pptr)); break; #ifdef INET6 case (sizeof(struct in6_addr) << 3): /* 128 */ ND_TCHECK2(pptr[0], sizeof(struct in6_addr)); snprintf(pos, sizeof(addr), "%s", ip6addr_string(ndo, pptr)); break; #endif default: snprintf(pos, sizeof(addr), "bogus address length %u", addr_length); break; } pos += strlen(pos); trunc: *(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 int bgp_vpn_sg_print(netdissect_options *ndo, - const u_char *pptr, char *buf, u_int buflen) { - + const u_char *pptr, char *buf, u_int buflen) +{ uint8_t addr_length; u_int total_length, offset; total_length = 0; /* Source address length, encoded in bits */ ND_TCHECK2(pptr[0], 1); addr_length = *pptr++; /* Source address */ ND_TCHECK2(pptr[0], (addr_length >> 3)); total_length += (addr_length >> 3) + 1; offset = 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 */ ND_TCHECK2(pptr[0], 1); addr_length = *pptr++; /* Group address */ ND_TCHECK2(pptr[0], (addr_length >> 3)); total_length += (addr_length >> 3) + 1; offset = 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); } /* RDs and RTs share the same semantics * we use bgp_vpn_rd_print for * printing route targets inside a NLRI */ char * bgp_vpn_rd_print(netdissect_options *ndo, - const u_char *pptr) { - + const u_char *pptr) +{ /* allocate space for the largest possible string */ static char rd[sizeof("xxxxxxxxxx:xxxxx (xxx.xxx.xxx.xxx:xxxxx)")]; char *pos = rd; /* ok lets load the RD format */ switch (EXTRACT_16BITS(pptr)) { /* 2-byte-AS:number fmt*/ case 0: snprintf(pos, sizeof(rd) - (pos - rd), "%u:%u (= %u.%u.%u.%u)", EXTRACT_16BITS(pptr+2), EXTRACT_32BITS(pptr+4), *(pptr+4), *(pptr+5), *(pptr+6), *(pptr+7)); break; /* IP-address:AS fmt*/ case 1: snprintf(pos, sizeof(rd) - (pos - rd), "%u.%u.%u.%u:%u", *(pptr+2), *(pptr+3), *(pptr+4), *(pptr+5), EXTRACT_16BITS(pptr+6)); break; /* 4-byte-AS:number fmt*/ case 2: snprintf(pos, sizeof(rd) - (pos - rd), "%s:%u (%u.%u.%u.%u:%u)", as_printf(ndo, astostr, sizeof(astostr), EXTRACT_32BITS(pptr+2)), EXTRACT_16BITS(pptr+6), *(pptr+2), *(pptr+3), *(pptr+4), *(pptr+5), EXTRACT_16BITS(pptr+6)); break; default: snprintf(pos, sizeof(rd) - (pos - rd), "unknown RD format"); break; } pos += strlen(pos); *(pos) = '\0'; return (rd); } static int decode_rt_routing_info(netdissect_options *ndo, const u_char *pptr, char *buf, u_int buflen) { uint8_t route_target[8]; u_int plen; ND_TCHECK(pptr[0]); plen = pptr[0]; /* get prefix length */ - if (0 == plen) - return 1; /* default route target */ + if (0 == plen) { + snprintf(buf, buflen, "default route target"); + return 1; + } if (32 > plen) return -1; plen-=32; /* adjust prefix length */ if (64 < plen) return -1; memset(&route_target, 0, sizeof(route_target)); ND_TCHECK2(pptr[1], (plen + 7) / 8); memcpy(&route_target, &pptr[1], (plen + 7) / 8); if (plen % 8) { ((u_char *)&route_target)[(plen + 7) / 8 - 1] &= ((0xff00 >> (plen % 8)) & 0xff); } snprintf(buf, buflen, "origin AS: %s, route target %s", as_printf(ndo, astostr, sizeof(astostr), EXTRACT_32BITS(pptr+1)), bgp_vpn_rd_print(ndo, (u_char *)&route_target)); return 5 + (plen + 7) / 8; trunc: return -2; } static int decode_labeled_vpn_prefix4(netdissect_options *ndo, const u_char *pptr, char *buf, u_int buflen) { struct in_addr addr; u_int plen; ND_TCHECK(pptr[0]); plen = pptr[0]; /* 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)); ND_TCHECK2(pptr[12], (plen + 7) / 8); memcpy(&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/%d, label:%u %s", bgp_vpn_rd_print(ndo, pptr+4), getname(ndo, (u_char *)&addr), plen, EXTRACT_24BITS(pptr+1)>>4, ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" ); return 12 + (plen + 7) / 8; trunc: return -2; } /* * +-------------------------------+ * | | * | 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, u_int buflen) { const u_char *rd; const u_char *vpn_ip; ND_TCHECK(pptr[0]); /* if the NLRI is not predefined length, quit.*/ if (*pptr != MDT_VPN_NLRI_LEN * 8) return -1; pptr++; /* RD */ ND_TCHECK2(pptr[0], 8); rd = pptr; pptr+=8; /* IPv4 address */ ND_TCHECK2(pptr[0], sizeof(struct in_addr)); vpn_ip = pptr; pptr+=sizeof(struct in_addr); /* MDT Group Address */ ND_TCHECK2(pptr[0], sizeof(struct in_addr)); snprintf(buf, buflen, "RD: %s, VPN IP Address: %s, MC Group Address: %s", bgp_vpn_rd_print(ndo, rd), ipaddr_string(ndo, vpn_ip), ipaddr_string(ndo, 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"}, }; static int decode_multicast_vpn(netdissect_options *ndo, const u_char *pptr, char *buf, u_int buflen) { uint8_t route_type, route_length, addr_length, sg_length; u_int offset; ND_TCHECK2(pptr[0], 2); route_type = *pptr++; route_length = *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_TCHECK2(pptr[0], BGP_VPN_RD_LEN); offset = 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_TCHECK2(pptr[0], BGP_VPN_RD_LEN + 4); offset = strlen(buf); snprintf(buf + offset, buflen - offset, ", RD: %s, Source-AS %s", bgp_vpn_rd_print(ndo, pptr), as_printf(ndo, astostr, sizeof(astostr), EXTRACT_32BITS(pptr + BGP_VPN_RD_LEN))); break; case BGP_MULTICAST_VPN_ROUTE_TYPE_S_PMSI: ND_TCHECK2(pptr[0], BGP_VPN_RD_LEN); offset = 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_TCHECK2(pptr[0], addr_length); offset = 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_TCHECK2(pptr[0], BGP_VPN_RD_LEN); offset = 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_TCHECK2(pptr[0], BGP_VPN_RD_LEN); offset = strlen(buf); snprintf(buf + offset, buflen - offset, ", RD: %s, Source-AS %s", bgp_vpn_rd_print(ndo, pptr), as_printf(ndo, astostr, sizeof(astostr), EXTRACT_32BITS(pptr + BGP_VPN_RD_LEN))); pptr += BGP_VPN_RD_LEN; 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, strlen) \ if (strlen<0) \ buflen=0; \ else if ((u_int)strlen>buflen) \ buflen=0; \ else { \ buflen-=strlen; \ buf+=strlen; \ } static int decode_labeled_vpn_l2(netdissect_options *ndo, const u_char *pptr, char *buf, u_int buflen) { int plen,tlen,strlen,tlv_type,tlv_len,ttlv_len; ND_TCHECK2(pptr[0], 2); plen=EXTRACT_16BITS(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_TCHECK2(pptr[0],12); buf[0]='\0'; strlen=snprintf(buf, buflen, "RD: %s, BGPNH: %s", bgp_vpn_rd_print(ndo, pptr), /* need something like getname(ndo, ) here */ getname(ndo, pptr+8) ); UPDATE_BUF_BUFLEN(buf, buflen, strlen); pptr+=12; tlen-=12; return plen; } else if (plen>17) { /* assume old format */ /* RD, ID, LBLKOFF, LBLBASE */ ND_TCHECK2(pptr[0],15); buf[0]='\0'; strlen=snprintf(buf, buflen, "RD: %s, CE-ID: %u, Label-Block Offset: %u, Label Base %u", bgp_vpn_rd_print(ndo, pptr), EXTRACT_16BITS(pptr+8), EXTRACT_16BITS(pptr+10), EXTRACT_24BITS(pptr+12)>>4); /* the label is offsetted by 4 bits so lets shift it right */ UPDATE_BUF_BUFLEN(buf, buflen, strlen); pptr+=15; tlen-=15; /* ok now the variable part - lets read out TLVs*/ while (tlen>0) { if (tlen < 3) return -1; ND_TCHECK2(pptr[0], 3); tlv_type=*pptr++; tlv_len=EXTRACT_16BITS(pptr); ttlv_len=tlv_len; pptr+=2; switch(tlv_type) { case 1: if (buflen!=0) { strlen=snprintf(buf,buflen, "\n\t\tcircuit status vector (%u) length: %u: 0x", tlv_type, tlv_len); UPDATE_BUF_BUFLEN(buf, buflen, strlen); } ttlv_len=ttlv_len/8+1; /* how many bytes do we need to read ? */ while (ttlv_len>0) { ND_TCHECK(pptr[0]); if (buflen!=0) { strlen=snprintf(buf,buflen, "%02x",*pptr++); UPDATE_BUF_BUFLEN(buf, buflen, strlen); } ttlv_len--; } break; default: if (buflen!=0) { strlen=snprintf(buf,buflen, "\n\t\tunknown TLV #%u, length: %u", tlv_type, tlv_len); UPDATE_BUF_BUFLEN(buf, buflen, strlen); } break; } tlen-=(tlv_len<<3); /* the tlv-length is expressed in bits so lets shift it right */ } return plen+2; } else { /* complain bitterly ? */ /* fall through */ goto trunc; } trunc: return -2; } #ifdef INET6 int decode_prefix6(netdissect_options *ndo, const u_char *pd, u_int itemlen, char *buf, u_int buflen) { struct in6_addr addr; u_int plen, plenbytes; ND_TCHECK(pd[0]); ITEMCHECK(1); plen = pd[0]; if (128 < plen) return -1; itemlen -= 1; memset(&addr, 0, sizeof(addr)); plenbytes = (plen + 7) / 8; ND_TCHECK2(pd[1], plenbytes); ITEMCHECK(plenbytes); memcpy(&addr, &pd[1], plenbytes); if (plen % 8) { addr.s6_addr[plenbytes - 1] &= ((0xff00 >> (plen % 8)) & 0xff); } snprintf(buf, buflen, "%s/%d", getname6(ndo, (u_char *)&addr), plen); return 1 + plenbytes; trunc: return -2; badtlv: return -3; } static int decode_labeled_prefix6(netdissect_options *ndo, const u_char *pptr, u_int itemlen, char *buf, u_int buflen) { struct in6_addr addr; u_int plen, plenbytes; /* prefix length and label = 4 bytes */ ND_TCHECK2(pptr[0], 4); ITEMCHECK(4); plen = pptr[0]; /* 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; ND_TCHECK2(pptr[4], plenbytes); memcpy(&addr, &pptr[4], plenbytes); if (plen % 8) { addr.s6_addr[plenbytes - 1] &= ((0xff00 >> (plen % 8)) & 0xff); } /* the label may get offsetted by 4 bits so lets shift it right */ snprintf(buf, buflen, "%s/%d, label:%u %s", getname6(ndo, (u_char *)&addr), plen, EXTRACT_24BITS(pptr+1)>>4, ((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, u_int buflen) { struct in6_addr addr; u_int plen; ND_TCHECK(pptr[0]); plen = pptr[0]; /* 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)); ND_TCHECK2(pptr[12], (plen + 7) / 8); memcpy(&addr, &pptr[12], (plen + 7) / 8); if (plen % 8) { addr.s6_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/%d, label:%u %s", bgp_vpn_rd_print(ndo, pptr+4), getname6(ndo, (u_char *)&addr), plen, EXTRACT_24BITS(pptr+1)>>4, ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" ); return 12 + (plen + 7) / 8; trunc: return -2; } #endif static int decode_clnp_prefix(netdissect_options *ndo, const u_char *pptr, char *buf, u_int buflen) { uint8_t addr[19]; u_int plen; ND_TCHECK(pptr[0]); plen = pptr[0]; /* get prefix length */ if (152 < plen) return -1; memset(&addr, 0, sizeof(addr)); ND_TCHECK2(pptr[4], (plen + 7) / 8); memcpy(&addr, &pptr[4], (plen + 7) / 8); if (plen % 8) { addr[(plen + 7) / 8 - 1] &= ((0xff00 >> (plen % 8)) & 0xff); } snprintf(buf, buflen, "%s/%d", isonsap_string(addr,(plen + 7) / 8), plen); return 1 + (plen + 7) / 8; trunc: return -2; } static int decode_labeled_vpn_clnp_prefix(netdissect_options *ndo, const u_char *pptr, char *buf, u_int buflen) { uint8_t addr[19]; u_int plen; ND_TCHECK(pptr[0]); plen = pptr[0]; /* 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)); ND_TCHECK2(pptr[12], (plen + 7) / 8); memcpy(&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/%d, label:%u %s", bgp_vpn_rd_print(ndo, pptr+4), isonsap_string(addr,(plen + 7) / 8), plen, EXTRACT_24BITS(pptr+1)>>4, ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" ); return 12 + (plen + 7) / 8; trunc: return -2; } /* * 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 int bgp_attr_get_as_size(netdissect_options *ndo, uint8_t bgpa_type, const u_char *pptr, 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) { ND_TCHECK(tptr[0]); /* * If we do not find a valid segment type, our guess might be wrong. */ if (tptr[0] < BGP_AS_SEG_TYPE_MIN || tptr[0] > BGP_AS_SEG_TYPE_MAX) { goto trunc; } ND_TCHECK(tptr[1]); tptr += 2 + 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 * there was not enough data, it will crib and end the parse anyways. */ return 4; } static int bgp_attr_print(netdissect_options *ndo, u_int atype, const u_char *pptr, u_int len) { int i; uint16_t af; uint8_t safi, snpa, nhlen; union { /* copy buffer for bandwidth values */ float f; uint32_t i; } bw; int advance; u_int tlen; const u_char *tptr; char buf[MAXHOSTNAMELEN + 100]; char tokbuf[TOKBUFSIZE]; int as_size; tptr = pptr; tlen=len; switch (atype) { case BGPTYPE_ORIGIN: if (len != 1) ND_PRINT((ndo, "invalid len")); else { ND_TCHECK(*tptr); ND_PRINT((ndo, "%s", tok2strbuf(bgp_origin_values, "Unknown Origin Typecode", tptr[0], tokbuf, sizeof(tokbuf)))); } break; /* * Process AS4 byte path and AS2 byte path attributes here. */ case BGPTYPE_AS4_PATH: case BGPTYPE_AS_PATH: if (len % 2) { ND_PRINT((ndo, "invalid len")); break; } if (!len) { ND_PRINT((ndo, "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_TCHECK(tptr[0]); ND_PRINT((ndo, "%s", tok2strbuf(bgp_as_path_segment_open_values, "?", tptr[0], tokbuf, sizeof(tokbuf)))); for (i = 0; i < tptr[1] * as_size; i += as_size) { ND_TCHECK2(tptr[2 + i], as_size); ND_PRINT((ndo, "%s ", as_printf(ndo, astostr, sizeof(astostr), as_size == 2 ? EXTRACT_16BITS(&tptr[2 + i]) : EXTRACT_32BITS(&tptr[2 + i])))); } ND_TCHECK(tptr[0]); ND_PRINT((ndo, "%s", tok2strbuf(bgp_as_path_segment_close_values, "?", tptr[0], tokbuf, sizeof(tokbuf)))); ND_TCHECK(tptr[1]); tptr += 2 + tptr[1] * as_size; } break; case BGPTYPE_NEXT_HOP: if (len != 4) ND_PRINT((ndo, "invalid len")); else { ND_TCHECK2(tptr[0], 4); ND_PRINT((ndo, "%s", getname(ndo, tptr))); } break; case BGPTYPE_MULTI_EXIT_DISC: case BGPTYPE_LOCAL_PREF: if (len != 4) ND_PRINT((ndo, "invalid len")); else { ND_TCHECK2(tptr[0], 4); ND_PRINT((ndo, "%u", EXTRACT_32BITS(tptr))); } break; case BGPTYPE_ATOMIC_AGGREGATE: if (len != 0) ND_PRINT((ndo, "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((ndo, "invalid len")); break; } ND_TCHECK2(tptr[0], len); if (len == 6) { ND_PRINT((ndo, " AS #%s, origin %s", as_printf(ndo, astostr, sizeof(astostr), EXTRACT_16BITS(tptr)), getname(ndo, tptr + 2))); } else { ND_PRINT((ndo, " AS #%s, origin %s", as_printf(ndo, astostr, sizeof(astostr), EXTRACT_32BITS(tptr)), getname(ndo, tptr + 4))); } break; case BGPTYPE_AGGREGATOR4: if (len != 8) { ND_PRINT((ndo, "invalid len")); break; } ND_TCHECK2(tptr[0], 8); ND_PRINT((ndo, " AS #%s, origin %s", as_printf(ndo, astostr, sizeof(astostr), EXTRACT_32BITS(tptr)), getname(ndo, tptr + 4))); break; case BGPTYPE_COMMUNITIES: if (len % 4) { ND_PRINT((ndo, "invalid len")); break; } while (tlen>0) { uint32_t comm; ND_TCHECK2(tptr[0], 4); comm = EXTRACT_32BITS(tptr); switch (comm) { case BGP_COMMUNITY_NO_EXPORT: ND_PRINT((ndo, " NO_EXPORT")); break; case BGP_COMMUNITY_NO_ADVERT: ND_PRINT((ndo, " NO_ADVERTISE")); break; case BGP_COMMUNITY_NO_EXPORT_SUBCONFED: ND_PRINT((ndo, " NO_EXPORT_SUBCONFED")); break; default: ND_PRINT((ndo, "%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((ndo, "invalid len")); break; } ND_TCHECK2(tptr[0], 4); ND_PRINT((ndo, "%s",getname(ndo, tptr))); break; case BGPTYPE_CLUSTER_LIST: if (len % 4) { ND_PRINT((ndo, "invalid len")); break; } while (tlen>0) { ND_TCHECK2(tptr[0], 4); ND_PRINT((ndo, "%s%s", getname(ndo, tptr), (tlen>4) ? ", " : "")); tlen -=4; tptr +=4; } break; case BGPTYPE_MP_REACH_NLRI: ND_TCHECK2(tptr[0], 3); af = EXTRACT_16BITS(tptr); safi = tptr[2]; ND_PRINT((ndo, "\n\t AFI: %s (%u), %sSAFI: %s (%u)", tok2strbuf(af_values, "Unknown AFI", af, tokbuf, sizeof(tokbuf)), af, (safi>128) ? "vendor specific " : "", /* 128 is meanwhile wellknown */ tok2strbuf(bgp_safi_values, "Unknown SAFI", safi, tokbuf, sizeof(tokbuf)), 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): #ifdef INET6 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): #endif 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_TCHECK2(tptr[0], tlen); ND_PRINT((ndo, "\n\t no AFI %u / SAFI %u decoder", af, safi)); if (ndo->ndo_vflag <= 1) print_unknown_data(ndo, tptr, "\n\t ", tlen); goto done; break; } tptr +=3; ND_TCHECK(tptr[0]); nhlen = tptr[0]; tlen = nhlen; tptr++; if (tlen) { int nnh = 0; ND_PRINT((ndo, "\n\t nexthop: ")); while (tlen > 0) { if ( nnh++ > 0 ) { ND_PRINT((ndo, ", " )); } 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 (tlen < (int)sizeof(struct in_addr)) { ND_PRINT((ndo, "invalid len")); tlen = 0; } else { ND_TCHECK2(tptr[0], sizeof(struct in_addr)); ND_PRINT((ndo, "%s",getname(ndo, tptr))); tlen -= sizeof(struct in_addr); tptr += sizeof(struct in_addr); } break; case (AFNUM_INET<<8 | SAFNUM_VPNUNICAST): case (AFNUM_INET<<8 | SAFNUM_VPNMULTICAST): case (AFNUM_INET<<8 | SAFNUM_VPNUNIMULTICAST): if (tlen < (int)(sizeof(struct in_addr)+BGP_VPN_RD_LEN)) { ND_PRINT((ndo, "invalid len")); tlen = 0; } else { ND_TCHECK2(tptr[0], sizeof(struct in_addr)+BGP_VPN_RD_LEN); ND_PRINT((ndo, "RD: %s, %s", bgp_vpn_rd_print(ndo, tptr), getname(ndo, tptr+BGP_VPN_RD_LEN))); tlen -= (sizeof(struct in_addr)+BGP_VPN_RD_LEN); tptr += (sizeof(struct in_addr)+BGP_VPN_RD_LEN); } break; #ifdef INET6 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 (tlen < (int)sizeof(struct in6_addr)) { ND_PRINT((ndo, "invalid len")); tlen = 0; } else { ND_TCHECK2(tptr[0], sizeof(struct in6_addr)); ND_PRINT((ndo, "%s", getname6(ndo, tptr))); tlen -= sizeof(struct in6_addr); tptr += sizeof(struct in6_addr); } break; case (AFNUM_INET6<<8 | SAFNUM_VPNUNICAST): case (AFNUM_INET6<<8 | SAFNUM_VPNMULTICAST): case (AFNUM_INET6<<8 | SAFNUM_VPNUNIMULTICAST): if (tlen < (int)(sizeof(struct in6_addr)+BGP_VPN_RD_LEN)) { ND_PRINT((ndo, "invalid len")); tlen = 0; } else { ND_TCHECK2(tptr[0], sizeof(struct in6_addr)+BGP_VPN_RD_LEN); ND_PRINT((ndo, "RD: %s, %s", bgp_vpn_rd_print(ndo, tptr), getname6(ndo, tptr+BGP_VPN_RD_LEN))); tlen -= (sizeof(struct in6_addr)+BGP_VPN_RD_LEN); tptr += (sizeof(struct in6_addr)+BGP_VPN_RD_LEN); } break; #endif 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 (tlen < (int)sizeof(struct in_addr)) { ND_PRINT((ndo, "invalid len")); tlen = 0; } else { ND_TCHECK2(tptr[0], sizeof(struct in_addr)); ND_PRINT((ndo, "%s", getname(ndo, tptr))); tlen -= (sizeof(struct in_addr)); tptr += (sizeof(struct in_addr)); } break; case (AFNUM_NSAP<<8 | SAFNUM_UNICAST): case (AFNUM_NSAP<<8 | SAFNUM_MULTICAST): case (AFNUM_NSAP<<8 | SAFNUM_UNIMULTICAST): ND_TCHECK2(tptr[0], tlen); ND_PRINT((ndo, "%s", isonsap_string(tptr, tlen))); tptr += tlen; tlen = 0; break; case (AFNUM_NSAP<<8 | SAFNUM_VPNUNICAST): case (AFNUM_NSAP<<8 | SAFNUM_VPNMULTICAST): case (AFNUM_NSAP<<8 | SAFNUM_VPNUNIMULTICAST): if (tlen < BGP_VPN_RD_LEN+1) { ND_PRINT((ndo, "invalid len")); tlen = 0; } else { ND_TCHECK2(tptr[0], tlen); ND_PRINT((ndo, "RD: %s, %s", bgp_vpn_rd_print(ndo, tptr), isonsap_string(tptr+BGP_VPN_RD_LEN,tlen-BGP_VPN_RD_LEN))); /* rfc986 mapped IPv4 address ? */ if (EXTRACT_32BITS(tptr+BGP_VPN_RD_LEN) == 0x47000601) ND_PRINT((ndo, " = %s", getname(ndo, tptr+BGP_VPN_RD_LEN+4))); #ifdef INET6 /* rfc1888 mapped IPv6 address ? */ else if (EXTRACT_24BITS(tptr+BGP_VPN_RD_LEN) == 0x350000) ND_PRINT((ndo, " = %s", getname6(ndo, tptr+BGP_VPN_RD_LEN+3))); #endif tptr += tlen; tlen = 0; } break; default: ND_TCHECK2(tptr[0], tlen); ND_PRINT((ndo, "no AFI %u/SAFI %u decoder", af, safi)); if (ndo->ndo_vflag <= 1) print_unknown_data(ndo, tptr, "\n\t ", tlen); tptr += tlen; tlen = 0; goto done; break; } } } ND_PRINT((ndo, ", nh-length: %u", nhlen)); tptr += tlen; ND_TCHECK(tptr[0]); snpa = tptr[0]; tptr++; if (snpa) { ND_PRINT((ndo, "\n\t %u SNPA", snpa)); for (/*nothing*/; snpa > 0; snpa--) { ND_TCHECK(tptr[0]); ND_PRINT((ndo, "\n\t %d bytes", tptr[0])); tptr += tptr[0] + 1; } } else { ND_PRINT((ndo, ", no SNPA")); } while (len - (tptr - pptr) > 0) { switch (af<<8 | safi) { case (AFNUM_INET<<8 | SAFNUM_UNICAST): case (AFNUM_INET<<8 | SAFNUM_MULTICAST): case (AFNUM_INET<<8 | SAFNUM_UNIMULTICAST): advance = decode_prefix4(ndo, tptr, len, buf, sizeof(buf)); if (advance == -1) ND_PRINT((ndo, "\n\t (illegal prefix length)")); else if (advance == -2) goto trunc; else if (advance == -3) break; /* bytes left, but not enough */ else ND_PRINT((ndo, "\n\t %s", buf)); break; case (AFNUM_INET<<8 | SAFNUM_LABUNICAST): advance = decode_labeled_prefix4(ndo, tptr, len, buf, sizeof(buf)); if (advance == -1) ND_PRINT((ndo, "\n\t (illegal prefix length)")); else if (advance == -2) goto trunc; else if (advance == -3) break; /* bytes left, but not enough */ else ND_PRINT((ndo, "\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, sizeof(buf)); if (advance == -1) ND_PRINT((ndo, "\n\t (illegal prefix length)")); else if (advance == -2) goto trunc; else ND_PRINT((ndo, "\n\t %s", buf)); break; case (AFNUM_INET<<8 | SAFNUM_RT_ROUTING_INFO): advance = decode_rt_routing_info(ndo, tptr, buf, sizeof(buf)); if (advance == -1) ND_PRINT((ndo, "\n\t (illegal prefix length)")); else if (advance == -2) goto trunc; else ND_PRINT((ndo, "\n\t %s", buf)); break; case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN): /* fall through */ case (AFNUM_INET6<<8 | SAFNUM_MULTICAST_VPN): advance = decode_multicast_vpn(ndo, tptr, buf, sizeof(buf)); if (advance == -1) ND_PRINT((ndo, "\n\t (illegal prefix length)")); else if (advance == -2) goto trunc; else ND_PRINT((ndo, "\n\t %s", buf)); break; case (AFNUM_INET<<8 | SAFNUM_MDT): advance = decode_mdt_vpn_nlri(ndo, tptr, buf, sizeof(buf)); if (advance == -1) ND_PRINT((ndo, "\n\t (illegal prefix length)")); else if (advance == -2) goto trunc; else ND_PRINT((ndo, "\n\t %s", buf)); break; #ifdef INET6 case (AFNUM_INET6<<8 | SAFNUM_UNICAST): case (AFNUM_INET6<<8 | SAFNUM_MULTICAST): case (AFNUM_INET6<<8 | SAFNUM_UNIMULTICAST): advance = decode_prefix6(ndo, tptr, len, buf, sizeof(buf)); if (advance == -1) ND_PRINT((ndo, "\n\t (illegal prefix length)")); else if (advance == -2) goto trunc; else if (advance == -3) break; /* bytes left, but not enough */ else ND_PRINT((ndo, "\n\t %s", buf)); break; case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST): advance = decode_labeled_prefix6(ndo, tptr, len, buf, sizeof(buf)); if (advance == -1) ND_PRINT((ndo, "\n\t (illegal prefix length)")); else if (advance == -2) goto trunc; else if (advance == -3) break; /* bytes left, but not enough */ else ND_PRINT((ndo, "\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, sizeof(buf)); if (advance == -1) ND_PRINT((ndo, "\n\t (illegal prefix length)")); else if (advance == -2) goto trunc; else ND_PRINT((ndo, "\n\t %s", buf)); break; #endif 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, sizeof(buf)); if (advance == -1) ND_PRINT((ndo, "\n\t (illegal length)")); else if (advance == -2) goto trunc; else ND_PRINT((ndo, "\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, sizeof(buf)); if (advance == -1) ND_PRINT((ndo, "\n\t (illegal prefix length)")); else if (advance == -2) goto trunc; else ND_PRINT((ndo, "\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, sizeof(buf)); if (advance == -1) ND_PRINT((ndo, "\n\t (illegal prefix length)")); else if (advance == -2) goto trunc; else ND_PRINT((ndo, "\n\t %s", buf)); break; default: ND_TCHECK2(*tptr,tlen); ND_PRINT((ndo, "\n\t no AFI %u / SAFI %u decoder", af, safi)); if (ndo->ndo_vflag <= 1) print_unknown_data(ndo, tptr, "\n\t ", tlen); advance = 0; tptr = pptr + len; break; } if (advance < 0) break; tptr += advance; } done: break; case BGPTYPE_MP_UNREACH_NLRI: ND_TCHECK2(tptr[0], BGP_MP_NLRI_MINSIZE); af = EXTRACT_16BITS(tptr); safi = tptr[2]; ND_PRINT((ndo, "\n\t AFI: %s (%u), %sSAFI: %s (%u)", tok2strbuf(af_values, "Unknown AFI", af, tokbuf, sizeof(tokbuf)), af, (safi>128) ? "vendor specific " : "", /* 128 is meanwhile wellknown */ tok2strbuf(bgp_safi_values, "Unknown SAFI", safi, tokbuf, sizeof(tokbuf)), safi)); if (len == BGP_MP_NLRI_MINSIZE) ND_PRINT((ndo, "\n\t End-of-Rib Marker (empty NLRI)")); tptr += 3; while (len - (tptr - pptr) > 0) { switch (af<<8 | safi) { case (AFNUM_INET<<8 | SAFNUM_UNICAST): case (AFNUM_INET<<8 | SAFNUM_MULTICAST): case (AFNUM_INET<<8 | SAFNUM_UNIMULTICAST): advance = decode_prefix4(ndo, tptr, len, buf, sizeof(buf)); if (advance == -1) ND_PRINT((ndo, "\n\t (illegal prefix length)")); else if (advance == -2) goto trunc; else if (advance == -3) break; /* bytes left, but not enough */ else ND_PRINT((ndo, "\n\t %s", buf)); break; case (AFNUM_INET<<8 | SAFNUM_LABUNICAST): advance = decode_labeled_prefix4(ndo, tptr, len, buf, sizeof(buf)); if (advance == -1) ND_PRINT((ndo, "\n\t (illegal prefix length)")); else if (advance == -2) goto trunc; else if (advance == -3) break; /* bytes left, but not enough */ else ND_PRINT((ndo, "\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, sizeof(buf)); if (advance == -1) ND_PRINT((ndo, "\n\t (illegal prefix length)")); else if (advance == -2) goto trunc; else ND_PRINT((ndo, "\n\t %s", buf)); break; #ifdef INET6 case (AFNUM_INET6<<8 | SAFNUM_UNICAST): case (AFNUM_INET6<<8 | SAFNUM_MULTICAST): case (AFNUM_INET6<<8 | SAFNUM_UNIMULTICAST): advance = decode_prefix6(ndo, tptr, len, buf, sizeof(buf)); if (advance == -1) ND_PRINT((ndo, "\n\t (illegal prefix length)")); else if (advance == -2) goto trunc; else if (advance == -3) break; /* bytes left, but not enough */ else ND_PRINT((ndo, "\n\t %s", buf)); break; case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST): advance = decode_labeled_prefix6(ndo, tptr, len, buf, sizeof(buf)); if (advance == -1) ND_PRINT((ndo, "\n\t (illegal prefix length)")); else if (advance == -2) goto trunc; else if (advance == -3) break; /* bytes left, but not enough */ else ND_PRINT((ndo, "\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, sizeof(buf)); if (advance == -1) ND_PRINT((ndo, "\n\t (illegal prefix length)")); else if (advance == -2) goto trunc; else ND_PRINT((ndo, "\n\t %s", buf)); break; #endif 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, sizeof(buf)); if (advance == -1) ND_PRINT((ndo, "\n\t (illegal length)")); else if (advance == -2) goto trunc; else ND_PRINT((ndo, "\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, sizeof(buf)); if (advance == -1) ND_PRINT((ndo, "\n\t (illegal prefix length)")); else if (advance == -2) goto trunc; else ND_PRINT((ndo, "\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, sizeof(buf)); if (advance == -1) ND_PRINT((ndo, "\n\t (illegal prefix length)")); else if (advance == -2) goto trunc; else ND_PRINT((ndo, "\n\t %s", buf)); break; case (AFNUM_INET<<8 | SAFNUM_MDT): advance = decode_mdt_vpn_nlri(ndo, tptr, buf, sizeof(buf)); if (advance == -1) ND_PRINT((ndo, "\n\t (illegal prefix length)")); else if (advance == -2) goto trunc; else ND_PRINT((ndo, "\n\t %s", buf)); break; case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN): /* fall through */ case (AFNUM_INET6<<8 | SAFNUM_MULTICAST_VPN): advance = decode_multicast_vpn(ndo, tptr, buf, sizeof(buf)); if (advance == -1) ND_PRINT((ndo, "\n\t (illegal prefix length)")); else if (advance == -2) goto trunc; else ND_PRINT((ndo, "\n\t %s", buf)); break; default: ND_TCHECK2(*(tptr-3),tlen); ND_PRINT((ndo, "no AFI %u / SAFI %u decoder", af, safi)); if (ndo->ndo_vflag <= 1) print_unknown_data(ndo, tptr-3, "\n\t ", tlen); advance = 0; tptr = pptr + len; break; } if (advance < 0) break; tptr += advance; } break; case BGPTYPE_EXTD_COMMUNITIES: if (len % 8) { ND_PRINT((ndo, "invalid len")); break; } while (tlen>0) { uint16_t extd_comm; ND_TCHECK2(tptr[0], 2); extd_comm=EXTRACT_16BITS(tptr); ND_PRINT((ndo, "\n\t %s (0x%04x), Flags [%s]", tok2strbuf(bgp_extd_comm_subtype_values, "unknown extd community typecode", extd_comm, tokbuf, sizeof(tokbuf)), extd_comm, bittok2str(bgp_extd_comm_flag_values, "none", extd_comm))); ND_TCHECK2(*(tptr+2), 6); switch(extd_comm) { case BGP_EXT_COM_RT_0: case BGP_EXT_COM_RO_0: case BGP_EXT_COM_L2VPN_RT_0: ND_PRINT((ndo, ": %u:%u (= %s)", EXTRACT_16BITS(tptr+2), EXTRACT_32BITS(tptr+4), getname(ndo, tptr+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((ndo, ": %s:%u", getname(ndo, tptr+2), EXTRACT_16BITS(tptr+6))); break; case BGP_EXT_COM_RT_2: case BGP_EXT_COM_RO_2: ND_PRINT((ndo, ": %s:%u", as_printf(ndo, astostr, sizeof(astostr), EXTRACT_32BITS(tptr+2)), EXTRACT_16BITS(tptr+6))); break; case BGP_EXT_COM_LINKBAND: bw.i = EXTRACT_32BITS(tptr+2); ND_PRINT((ndo, ": 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((ndo, "%s", getname(ndo, tptr+2))); break; case BGP_EXT_COM_OSPF_RTYPE: case BGP_EXT_COM_OSPF_RTYPE2: ND_PRINT((ndo, ": area:%s, router-type:%s, metric-type:%s%s", getname(ndo, tptr+2), tok2strbuf(bgp_extd_comm_ospf_rtype_values, "unknown (0x%02x)", *(tptr+6), tokbuf, sizeof(tokbuf)), (*(tptr+7) & BGP_OSPF_RTYPE_METRIC_TYPE) ? "E2" : "", ((*(tptr+6) == BGP_OSPF_RTYPE_EXT) || (*(tptr+6) == BGP_OSPF_RTYPE_NSSA)) ? "E1" : "")); break; case BGP_EXT_COM_L2INFO: ND_PRINT((ndo, ": %s Control Flags [0x%02x]:MTU %u", tok2strbuf(l2vpn_encaps_values, "unknown encaps", *(tptr+2), tokbuf, sizeof(tokbuf)), *(tptr+3), EXTRACT_16BITS(tptr+4))); break; case BGP_EXT_COM_SOURCE_AS: ND_PRINT((ndo, ": AS %u", EXTRACT_16BITS(tptr+2))); break; default: ND_TCHECK2(*tptr,8); print_unknown_data(ndo, tptr, "\n\t ", 8); break; } tlen -=8; tptr +=8; } break; case BGPTYPE_PMSI_TUNNEL: { uint8_t tunnel_type, flags; tunnel_type = *(tptr+1); flags = *tptr; tlen = len; ND_TCHECK2(tptr[0], 5); ND_PRINT((ndo, "\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), EXTRACT_24BITS(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_TCHECK2(tptr[0], 8); ND_PRINT((ndo, "\n\t Sender %s, P-Group %s", ipaddr_string(ndo, tptr), ipaddr_string(ndo, tptr+4))); break; case BGP_PMSI_TUNNEL_PIM_SSM: ND_TCHECK2(tptr[0], 8); ND_PRINT((ndo, "\n\t Root-Node %s, P-Group %s", ipaddr_string(ndo, tptr), ipaddr_string(ndo, tptr+4))); break; case BGP_PMSI_TUNNEL_INGRESS: ND_TCHECK2(tptr[0], 4); ND_PRINT((ndo, "\n\t Tunnel-Endpoint %s", ipaddr_string(ndo, tptr))); break; case BGP_PMSI_TUNNEL_LDP_P2MP: /* fall through */ case BGP_PMSI_TUNNEL_LDP_MP2MP: ND_TCHECK2(tptr[0], 8); ND_PRINT((ndo, "\n\t Root-Node %s, LSP-ID 0x%08x", ipaddr_string(ndo, tptr), EXTRACT_32BITS(tptr+4))); break; case BGP_PMSI_TUNNEL_RSVP_P2MP: ND_TCHECK2(tptr[0], 8); ND_PRINT((ndo, "\n\t Extended-Tunnel-ID %s, P2MP-ID 0x%08x", ipaddr_string(ndo, tptr), EXTRACT_32BITS(tptr+4))); break; default: if (ndo->ndo_vflag <= 1) { print_unknown_data(ndo, tptr, "\n\t ", tlen); } } break; } case BGPTYPE_ATTR_SET: ND_TCHECK2(tptr[0], 4); if (len < 4) goto trunc; ND_PRINT((ndo, "\n\t Origin AS: %s", as_printf(ndo, astostr, sizeof(astostr), EXTRACT_32BITS(tptr)))); tptr+=4; len -=4; while (len) { u_int aflags, atype, alenlen, alen; ND_TCHECK2(tptr[0], 2); if (len < 2) goto trunc; aflags = *tptr; atype = *(tptr + 1); tptr += 2; len -= 2; alenlen = bgp_attr_lenlen(aflags, tptr); ND_TCHECK2(tptr[0], alenlen); if (len < alenlen) goto trunc; alen = bgp_attr_len(aflags, tptr); tptr += alenlen; len -= alenlen; ND_PRINT((ndo, "\n\t %s (%u), length: %u", tok2strbuf(bgp_attr_values, "Unknown Attribute", atype, tokbuf, sizeof(tokbuf)), atype, alen)); if (aflags) { ND_PRINT((ndo, ", Flags [%s%s%s%s", aflags & 0x80 ? "O" : "", aflags & 0x40 ? "T" : "", aflags & 0x20 ? "P" : "", aflags & 0x10 ? "E" : "")); if (aflags & 0xf) ND_PRINT((ndo, "+%x", aflags & 0xf)); ND_PRINT((ndo, "]: ")); } /* FIXME check for recursion */ if (!bgp_attr_print(ndo, atype, tptr, alen)) return 0; tptr += alen; len -= alen; } break; default: ND_TCHECK2(*pptr,len); ND_PRINT((ndo, "\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; } if (ndo->ndo_vflag > 1 && len) { /* omit zero length attributes*/ ND_TCHECK2(*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, int caps_len) { char tokbuf[TOKBUFSIZE]; char tokbuf2[TOKBUFSIZE]; int cap_type, cap_len, tcap_len, cap_offset; int i = 0; while (i < caps_len) { ND_TCHECK2(opt[i], BGP_CAP_HEADER_SIZE); cap_type=opt[i]; cap_len=opt[i+1]; tcap_len=cap_len; ND_PRINT((ndo, "\n\t %s (%u), length: %u", tok2strbuf(bgp_capcode_values, "Unknown", cap_type, tokbuf, sizeof(tokbuf)), cap_type, cap_len)); ND_TCHECK2(opt[i+2], cap_len); switch (cap_type) { case BGP_CAPCODE_MP: ND_PRINT((ndo, "\n\t\tAFI %s (%u), SAFI %s (%u)", tok2strbuf(af_values, "Unknown", EXTRACT_16BITS(opt+i+2), tokbuf, sizeof(tokbuf)), EXTRACT_16BITS(opt+i+2), tok2strbuf(bgp_safi_values, "Unknown", opt[i+5], tokbuf, sizeof(tokbuf)), opt[i+5])); break; case BGP_CAPCODE_RESTART: ND_PRINT((ndo, "\n\t\tRestart Flags: [%s], Restart Time %us", ((opt[i+2])&0x80) ? "R" : "none", EXTRACT_16BITS(opt+i+2)&0xfff)); tcap_len-=2; cap_offset=4; while(tcap_len>=4) { ND_PRINT((ndo, "\n\t\t AFI %s (%u), SAFI %s (%u), Forwarding state preserved: %s", tok2strbuf(af_values,"Unknown", EXTRACT_16BITS(opt+i+cap_offset), tokbuf, sizeof(tokbuf)), EXTRACT_16BITS(opt+i+cap_offset), tok2strbuf(bgp_safi_values,"Unknown", opt[i+cap_offset+2], tokbuf2, sizeof(tokbuf2)), opt[i+cap_offset+2], ((opt[i+cap_offset+3])&0x80) ? "yes" : "no" )); tcap_len-=4; cap_offset+=4; } break; case BGP_CAPCODE_RR: case BGP_CAPCODE_RR_CISCO: break; case BGP_CAPCODE_AS_NEW: /* * Extract the 4 byte AS number encoded. */ if (cap_len == 4) { ND_PRINT((ndo, "\n\t\t 4 Byte AS %s", as_printf(ndo, astostr, sizeof(astostr), EXTRACT_32BITS(opt + i + 2)))); } break; default: ND_PRINT((ndo, "\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((ndo, "[|BGP]")); } static void bgp_open_print(netdissect_options *ndo, const u_char *dat, int length) { struct bgp_open bgpo; struct bgp_opt bgpopt; const u_char *opt; int i; char tokbuf[TOKBUFSIZE]; ND_TCHECK2(dat[0], BGP_OPEN_SIZE); memcpy(&bgpo, dat, BGP_OPEN_SIZE); ND_PRINT((ndo, "\n\t Version %d, ", bgpo.bgpo_version)); ND_PRINT((ndo, "my AS %s, ", as_printf(ndo, astostr, sizeof(astostr), ntohs(bgpo.bgpo_myas)))); ND_PRINT((ndo, "Holdtime %us, ", ntohs(bgpo.bgpo_holdtime))); ND_PRINT((ndo, "ID %s", getname(ndo, (u_char *)&bgpo.bgpo_id))); ND_PRINT((ndo, "\n\t Optional parameters, length: %u", bgpo.bgpo_optlen)); /* some little sanity checking */ if (length < bgpo.bgpo_optlen+BGP_OPEN_SIZE) return; /* ugly! */ opt = &((const struct bgp_open *)dat)->bgpo_optlen; opt++; i = 0; while (i < bgpo.bgpo_optlen) { ND_TCHECK2(opt[i], BGP_OPT_SIZE); memcpy(&bgpopt, &opt[i], BGP_OPT_SIZE); if (i + 2 + bgpopt.bgpopt_len > bgpo.bgpo_optlen) { ND_PRINT((ndo, "\n\t Option %d, length: %u", bgpopt.bgpopt_type, bgpopt.bgpopt_len)); break; } ND_PRINT((ndo, "\n\t Option %s (%u), length: %u", tok2strbuf(bgp_opt_values,"Unknown", bgpopt.bgpopt_type, tokbuf, sizeof(tokbuf)), bgpopt.bgpopt_type, bgpopt.bgpopt_len)); /* now let's decode the options we know*/ switch(bgpopt.bgpopt_type) { case BGP_OPT_CAP: bgp_capabilities_print(ndo, &opt[i+BGP_OPT_SIZE], bgpopt.bgpopt_len); break; case BGP_OPT_AUTH: default: ND_PRINT((ndo, "\n\t no decoder for option %u", bgpopt.bgpopt_type)); break; } i += BGP_OPT_SIZE + bgpopt.bgpopt_len; } return; trunc: ND_PRINT((ndo, "[|BGP]")); } static void bgp_update_print(netdissect_options *ndo, const u_char *dat, int length) { struct bgp bgp; const u_char *p; int withdrawn_routes_len; int len; int i; char tokbuf[TOKBUFSIZE]; #ifndef INET6 char buf[MAXHOSTNAMELEN + 100]; int wpfx; #endif ND_TCHECK2(dat[0], BGP_SIZE); if (length < BGP_SIZE) goto trunc; memcpy(&bgp, dat, BGP_SIZE); p = dat + BGP_SIZE; /*XXX*/ length -= BGP_SIZE; /* Unfeasible routes */ ND_TCHECK2(p[0], 2); if (length < 2) goto trunc; withdrawn_routes_len = EXTRACT_16BITS(p); p += 2; length -= 2; if (withdrawn_routes_len) { /* * 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_TCHECK2(p[0], withdrawn_routes_len); if (length < withdrawn_routes_len) goto trunc; #ifdef INET6 ND_PRINT((ndo, "\n\t Withdrawn routes: %d bytes", withdrawn_routes_len)); p += withdrawn_routes_len; length -= withdrawn_routes_len; #else if (withdrawn_routes_len < 2) goto trunc; length -= 2; withdrawn_routes_len -= 2; ND_PRINT((ndo, "\n\t Withdrawn routes:")); while(withdrawn_routes_len > 0) { wpfx = decode_prefix4(ndo, p, withdrawn_routes_len, buf, sizeof(buf)); if (wpfx == -1) { ND_PRINT((ndo, "\n\t (illegal prefix length)")); break; } else if (wpfx == -2) goto trunc; else if (wpfx == -3) goto trunc; /* bytes left, but not enough */ else { ND_PRINT((ndo, "\n\t %s", buf)); p += wpfx; length -= wpfx; withdrawn_routes_len -= wpfx; } } #endif } ND_TCHECK2(p[0], 2); if (length < 2) goto trunc; len = EXTRACT_16BITS(p); p += 2; length -= 2; if (withdrawn_routes_len == 0 && len == 0 && length == 0) { /* No withdrawn routes, no path attributes, no NLRI */ ND_PRINT((ndo, "\n\t End-of-Rib Marker (empty NLRI)")); return; } if (len) { /* do something more useful!*/ while (len) { int aflags, atype, alenlen, alen; ND_TCHECK2(p[0], 2); if (len < 2) goto trunc; if (length < 2) goto trunc; aflags = *p; atype = *(p + 1); p += 2; len -= 2; length -= 2; alenlen = bgp_attr_lenlen(aflags, p); ND_TCHECK2(p[0], alenlen); if (len < alenlen) goto trunc; if (length < alenlen) goto trunc; alen = bgp_attr_len(aflags, p); p += alenlen; len -= alenlen; length -= alenlen; ND_PRINT((ndo, "\n\t %s (%u), length: %u", tok2strbuf(bgp_attr_values, "Unknown Attribute", atype, tokbuf, sizeof(tokbuf)), atype, alen)); if (aflags) { ND_PRINT((ndo, ", Flags [%s%s%s%s", aflags & 0x80 ? "O" : "", aflags & 0x40 ? "T" : "", aflags & 0x20 ? "P" : "", aflags & 0x10 ? "E" : "")); if (aflags & 0xf) ND_PRINT((ndo, "+%x", aflags & 0xf)); ND_PRINT((ndo, "]: ")); } if (len < alen) goto trunc; if (length < alen) goto trunc; if (!bgp_attr_print(ndo, atype, p, alen)) goto trunc; p += alen; len -= alen; length -= alen; } } if (length) { /* * XXX - what if they're using the "Advertisement of * Multiple Paths in BGP" feature: * * https://datatracker.ietf.org/doc/draft-ietf-idr-add-paths/ * * http://tools.ietf.org/html/draft-ietf-idr-add-paths-06 */ ND_PRINT((ndo, "\n\t Updated routes:")); while (length) { char buf[MAXHOSTNAMELEN + 100]; i = decode_prefix4(ndo, p, length, buf, sizeof(buf)); if (i == -1) { ND_PRINT((ndo, "\n\t (illegal prefix length)")); break; } else if (i == -2) goto trunc; else if (i == -3) goto trunc; /* bytes left, but not enough */ else { ND_PRINT((ndo, "\n\t %s", buf)); p += i; length -= i; } } } return; trunc: ND_PRINT((ndo, "[|BGP]")); } static void bgp_notification_print(netdissect_options *ndo, const u_char *dat, int length) { struct bgp_notification bgpn; const u_char *tptr; char tokbuf[TOKBUFSIZE]; char tokbuf2[TOKBUFSIZE]; ND_TCHECK2(dat[0], BGP_NOTIFICATION_SIZE); memcpy(&bgpn, dat, BGP_NOTIFICATION_SIZE); /* some little sanity checking */ if (length= BGP_NOTIFICATION_SIZE + 7) { tptr = dat + BGP_NOTIFICATION_SIZE; ND_TCHECK2(*tptr, 7); ND_PRINT((ndo, ", AFI %s (%u), SAFI %s (%u), Max Prefixes: %u", tok2strbuf(af_values, "Unknown", EXTRACT_16BITS(tptr), tokbuf, sizeof(tokbuf)), EXTRACT_16BITS(tptr), tok2strbuf(bgp_safi_values, "Unknown", *(tptr+2), tokbuf2, sizeof(tokbuf)), *(tptr+2), EXTRACT_32BITS(tptr+3))); } break; default: break; } return; trunc: ND_PRINT((ndo, "[|BGP]")); } static void bgp_route_refresh_print(netdissect_options *ndo, - const u_char *pptr, int len) { - + const u_char *pptr, int len) +{ const struct bgp_route_refresh *bgp_route_refresh_header; char tokbuf[TOKBUFSIZE]; char tokbuf2[TOKBUFSIZE]; ND_TCHECK2(pptr[0], BGP_ROUTE_REFRESH_SIZE); /* some little sanity checking */ if (lenafi), tokbuf, sizeof(tokbuf)), EXTRACT_16BITS(&bgp_route_refresh_header->afi), tok2strbuf(bgp_safi_values,"Unknown", bgp_route_refresh_header->safi, tokbuf2, sizeof(tokbuf2)), bgp_route_refresh_header->safi)); if (ndo->ndo_vflag > 1) { ND_TCHECK2(*pptr, len); print_unknown_data(ndo, pptr, "\n\t ", len); } return; trunc: ND_PRINT((ndo, "[|BGP]")); } static int bgp_header_print(netdissect_options *ndo, const u_char *dat, int length) { struct bgp bgp; char tokbuf[TOKBUFSIZE]; ND_TCHECK2(dat[0], BGP_SIZE); memcpy(&bgp, dat, BGP_SIZE); ND_PRINT((ndo, "\n\t%s Message (%u), length: %u", tok2strbuf(bgp_msg_values, "Unknown", bgp.bgp_type, tokbuf, sizeof(tokbuf)), bgp.bgp_type, length)); switch (bgp.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_TCHECK2(*dat, length); ND_PRINT((ndo, "\n\t no Message %u decoder", bgp.bgp_type)); print_unknown_data(ndo, dat, "\n\t ", length); break; } return 1; trunc: ND_PRINT((ndo, "[|BGP]")); return 0; } void bgp_print(netdissect_options *ndo, const u_char *dat, int length) { const u_char *p; const u_char *ep; const u_char *start; const u_char marker[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }; struct bgp bgp; uint16_t hlen; char tokbuf[TOKBUFSIZE]; ep = dat + length; if (ndo->ndo_snapend < dat + length) ep = ndo->ndo_snapend; - ND_PRINT((ndo, ": BGP, length: %u", length)); + ND_PRINT((ndo, ": BGP")); if (ndo->ndo_vflag < 1) /* lets be less chatty */ return; p = dat; start = p; while (p < ep) { if (!ND_TTEST2(p[0], 1)) break; if (p[0] != 0xff) { p++; continue; } if (!ND_TTEST2(p[0], sizeof(marker))) break; if (memcmp(p, marker, sizeof(marker)) != 0) { p++; continue; } /* found BGP header */ ND_TCHECK2(p[0], BGP_SIZE); /*XXX*/ memcpy(&bgp, p, BGP_SIZE); if (start != p) ND_PRINT((ndo, " [|BGP]")); hlen = ntohs(bgp.bgp_len); if (hlen < BGP_SIZE) { ND_PRINT((ndo, "\n[|BGP Bogus header length %u < %u]", hlen, BGP_SIZE)); break; } if (ND_TTEST2(p[0], hlen)) { if (!bgp_header_print(ndo, p, hlen)) return; p += hlen; start = p; } else { ND_PRINT((ndo, "\n[|BGP %s]", tok2strbuf(bgp_msg_values, "Unknown Message Type", bgp.bgp_type, tokbuf, sizeof(tokbuf)))); break; } } return; trunc: ND_PRINT((ndo, " [|BGP]")); } /* * Local Variables: * c-style: whitesmith * c-basic-offset: 4 * End: */ Index: head/contrib/tcpdump/print-bootp.c =================================================================== --- head/contrib/tcpdump/print-bootp.c (revision 285274) +++ head/contrib/tcpdump/print-bootp.c (revision 285275) @@ -1,825 +1,1090 @@ /* * 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. * * Format and print bootp packets. * * $FreeBSD$ */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "interface.h" #include "addrtoname.h" #include "extract.h" -#include "bootp.h" static const char tstr[] = " [|bootp]"; +/* + * 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 { + uint8_t bp_op; /* packet opcode type */ + uint8_t bp_htype; /* hardware addr type */ + uint8_t bp_hlen; /* hardware addr length */ + uint8_t bp_hops; /* gateway hops */ + uint32_t bp_xid; /* transaction ID */ + uint16_t bp_secs; /* seconds since boot began */ + uint16_t bp_flags; /* flags - see bootp_flag_values[] + in print-bootp.c */ + struct in_addr bp_ciaddr; /* client IP address */ + struct in_addr bp_yiaddr; /* 'your' IP address */ + struct in_addr bp_siaddr; /* server IP address */ + struct in_addr bp_giaddr; /* gateway IP address */ + uint8_t bp_chaddr[16]; /* client hardware address */ + uint8_t bp_sname[64]; /* server host name */ + uint8_t bp_file[128]; /* boot file name */ + uint8_t bp_vend[64]; /* vendor-specific area */ +} UNALIGNED; + +#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_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) +/* RFC 5859 - TFTP Server Address Option for DHCPv4 */ +#define TAG_TFTP_SERVER_ADDRESS ((uint8_t) 150) +/* ftp://ftp.isi.edu/.../assignments/bootp-dhcp-extensions */ +#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_AGENT_MASK ((uint8_t) 84) +#define TAG_TZ_STRING ((uint8_t) 88) +#define TAG_FQDN_OPTION ((uint8_t) 89) +#define TAG_AUTH ((uint8_t) 90) +#define TAG_VINES_SERVERS ((uint8_t) 91) +#define TAG_SERVER_RANK ((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) +#define TAG_6OVER4 ((uint8_t) 96) +#define TAG_PRINTER_NAME ((uint8_t) 100) +#define TAG_MDHCP_SERVER ((uint8_t) 101) +#define TAG_IPX_COMPAT ((uint8_t) 110) +#define TAG_NETINFO_PARENT ((uint8_t) 112) +#define TAG_NETINFO_PARENT_TAG ((uint8_t) 113) +#define TAG_URL ((uint8_t) 114) +#define TAG_FAILOVER ((uint8_t) 115) +#define TAG_EXTENDED_REQUEST ((uint8_t) 126) +#define TAG_EXTENDED_OPTION ((uint8_t) 127) + +/* 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 + +/* + * "vendor" data permitted for CMU bootp clients. + */ + +struct cmu_vend { + uint8_t v_magic[4]; /* magic number */ + uint32_t v_flags; /* flags/opcodes, etc. */ + struct in_addr v_smask; /* Subnet mask */ + struct in_addr v_dgate; /* Default gateway */ + struct in_addr v_dns1, v_dns2; /* Domain name servers */ + struct in_addr v_ins1, v_ins2; /* IEN-116 name servers */ + struct in_addr v_ts1, v_ts2; /* Time servers */ + uint8_t v_unused[24]; /* currently unused */ +} UNALIGNED; + + +/* 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} + { 0x8000, "Broadcast" }, + { 0, NULL} }; static const struct tok bootp_op_values[] = { - { BOOTPREQUEST, "Request" }, - { BOOTPREPLY, "Reply" }, - { 0, NULL} + { BOOTPREQUEST, "Request" }, + { BOOTPREPLY, "Reply" }, + { 0, NULL} }; /* * Print bootp requests */ void bootp_print(netdissect_options *ndo, - register const u_char *cp, u_int length) + register const u_char *cp, u_int length) { register const struct bootp *bp; static const u_char vm_cmu[4] = VM_CMU; static const u_char vm_rfc1048[4] = VM_RFC1048; bp = (const struct bootp *)cp; ND_TCHECK(bp->bp_op); ND_PRINT((ndo, "BOOTP/DHCP, %s", - tok2str(bootp_op_values, "unknown (0x%02x)", bp->bp_op))); + tok2str(bootp_op_values, "unknown (0x%02x)", bp->bp_op))); if (bp->bp_htype == 1 && bp->bp_hlen == 6 && bp->bp_op == BOOTPREQUEST) { ND_TCHECK2(bp->bp_chaddr[0], 6); ND_PRINT((ndo, " from %s", etheraddr_string(ndo, bp->bp_chaddr))); } ND_PRINT((ndo, ", length %u", length)); if (!ndo->ndo_vflag) return; ND_TCHECK(bp->bp_secs); /* The usual hardware address type is 1 (10Mb Ethernet) */ if (bp->bp_htype != 1) ND_PRINT((ndo, ", htype %d", bp->bp_htype)); /* The usual length for 10Mb Ethernet address is 6 bytes */ if (bp->bp_htype != 1 || bp->bp_hlen != 6) ND_PRINT((ndo, ", hlen %d", bp->bp_hlen)); /* Only print interesting fields */ if (bp->bp_hops) ND_PRINT((ndo, ", hops %d", bp->bp_hops)); if (EXTRACT_32BITS(&bp->bp_xid)) ND_PRINT((ndo, ", xid 0x%x", EXTRACT_32BITS(&bp->bp_xid))); if (EXTRACT_16BITS(&bp->bp_secs)) ND_PRINT((ndo, ", secs %d", EXTRACT_16BITS(&bp->bp_secs))); ND_PRINT((ndo, ", Flags [%s]", - bittok2str(bootp_flag_values, "none", EXTRACT_16BITS(&bp->bp_flags)))); + bittok2str(bootp_flag_values, "none", EXTRACT_16BITS(&bp->bp_flags)))); if (ndo->ndo_vflag > 1) ND_PRINT((ndo, " (0x%04x)", EXTRACT_16BITS(&bp->bp_flags))); /* Client's ip address */ ND_TCHECK(bp->bp_ciaddr); if (EXTRACT_32BITS(&bp->bp_ciaddr.s_addr)) ND_PRINT((ndo, "\n\t Client-IP %s", ipaddr_string(ndo, &bp->bp_ciaddr))); /* 'your' ip address (bootp client) */ ND_TCHECK(bp->bp_yiaddr); if (EXTRACT_32BITS(&bp->bp_yiaddr.s_addr)) ND_PRINT((ndo, "\n\t Your-IP %s", ipaddr_string(ndo, &bp->bp_yiaddr))); /* Server's ip address */ ND_TCHECK(bp->bp_siaddr); if (EXTRACT_32BITS(&bp->bp_siaddr.s_addr)) ND_PRINT((ndo, "\n\t Server-IP %s", ipaddr_string(ndo, &bp->bp_siaddr))); /* Gateway's ip address */ ND_TCHECK(bp->bp_giaddr); if (EXTRACT_32BITS(&bp->bp_giaddr.s_addr)) ND_PRINT((ndo, "\n\t Gateway-IP %s", ipaddr_string(ndo, &bp->bp_giaddr))); /* Client's Ethernet address */ if (bp->bp_htype == 1 && bp->bp_hlen == 6) { ND_TCHECK2(bp->bp_chaddr[0], 6); ND_PRINT((ndo, "\n\t Client-Ethernet-Address %s", etheraddr_string(ndo, bp->bp_chaddr))); } ND_TCHECK2(bp->bp_sname[0], 1); /* check first char only */ if (*bp->bp_sname) { ND_PRINT((ndo, "\n\t sname \"")); if (fn_print(ndo, bp->bp_sname, ndo->ndo_snapend)) { ND_PRINT((ndo, "\"")); ND_PRINT((ndo, "%s", tstr + 1)); return; } ND_PRINT((ndo, "\"")); } ND_TCHECK2(bp->bp_file[0], 1); /* check first char only */ if (*bp->bp_file) { ND_PRINT((ndo, "\n\t file \"")); if (fn_print(ndo, bp->bp_file, ndo->ndo_snapend)) { ND_PRINT((ndo, "\"")); ND_PRINT((ndo, "%s", tstr + 1)); return; } ND_PRINT((ndo, "\"")); } /* Decode the vendor buffer */ ND_TCHECK(bp->bp_vend[0]); if (memcmp((const char *)bp->bp_vend, vm_rfc1048, - sizeof(uint32_t)) == 0) + sizeof(uint32_t)) == 0) rfc1048_print(ndo, bp->bp_vend); else if (memcmp((const char *)bp->bp_vend, vm_cmu, - sizeof(uint32_t)) == 0) + sizeof(uint32_t)) == 0) cmu_print(ndo, bp->bp_vend); else { uint32_t ul; ul = EXTRACT_32BITS(&bp->bp_vend); if (ul != 0) ND_PRINT((ndo, "\n\t Vendor-#0x%x", ul)); } return; trunc: ND_PRINT((ndo, "%s", tstr)); } /* * 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-seperated decimal bytes (variable length) * x - colon-seperated 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_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 5859 - TFTP Server Address Option for DHCPv4 */ + { TAG_TFTP_SERVER_ADDRESS, "iTFTP-Server-Address" }, /* http://www.iana.org/assignments/bootp-dhcp-extensions/index.htm */ - { TAG_USER_CLASS, "aCLASS" }, { TAG_SLP_NAMING_AUTH, "aSLP-NA" }, { TAG_CLIENT_FQDN, "$FQDN" }, { TAG_AGENT_CIRCUIT, "$Agent-Information" }, { TAG_AGENT_REMOTE, "bARMT" }, { TAG_AGENT_MASK, "bAMSK" }, { TAG_TZ_STRING, "aTZSTR" }, { TAG_FQDN_OPTION, "bFQDNS" }, /* XXX 'b' */ { TAG_AUTH, "bAUTH" }, /* XXX 'b' */ { TAG_VINES_SERVERS, "iVINES" }, { TAG_SERVER_RANK, "sRANK" }, { TAG_CLIENT_ARCH, "sARCH" }, { TAG_CLIENT_NDI, "bNDI" }, /* XXX 'b' */ { TAG_CLIENT_GUID, "bGUID" }, /* XXX 'b' */ { TAG_LDAP_URL, "aLDAP" }, { TAG_6OVER4, "i6o4" }, { TAG_PRINTER_NAME, "aPRTR" }, { TAG_MDHCP_SERVER, "bMDHCP" }, /* XXX 'b' */ { TAG_IPX_COMPAT, "bIPX" }, /* XXX 'b' */ { TAG_NETINFO_PARENT, "iNI" }, { TAG_NETINFO_PARENT_TAG, "aNITAG" }, { TAG_URL, "aURL" }, { TAG_FAILOVER, "bFAIL" }, /* XXX 'b' */ - { 0, NULL } + { 0, NULL } }; /* 2-byte extended tags */ static const struct tok xtag2str[] = { - { 0, NULL } + { 0, NULL } }; /* DHCP "options overload" types */ static const struct tok oo2str[] = { - { 1, "file" }, - { 2, "sname" }, - { 3, "file+sname" }, - { 0, NULL } + { 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 } + { 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 } + { 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" }, - { 0, NULL } + { DHCPDISCOVER, "Discover" }, + { DHCPOFFER, "Offer" }, + { DHCPREQUEST, "Request" }, + { DHCPDECLINE, "Decline" }, + { DHCPACK, "ACK" }, + { DHCPNAK, "NACK" }, + { DHCPRELEASE, "Release" }, + { DHCPINFORM, "Inform" }, + { 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 */ +#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 } + { 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, - register const u_char *bp) + register const u_char *bp) { register uint16_t tag; register u_int len; register const char *cp; register char c; int first, idx; uint32_t ul; uint16_t us; uint8_t uc, subopt, suboptlen; ND_PRINT((ndo, "\n\t Vendor-rfc1048 Extensions")); /* Step over magic cookie */ ND_PRINT((ndo, "\n\t Magic Cookie 0x%08x", EXTRACT_32BITS(bp))); bp += sizeof(int32_t); /* Loop while we there is a tag left in the buffer */ while (ND_TTEST2(*bp, 1)) { tag = *bp++; if (tag == TAG_PAD && ndo->ndo_vflag < 3) continue; if (tag == TAG_END && ndo->ndo_vflag < 3) return; if (tag == TAG_EXTENDED_OPTION) { ND_TCHECK2(*(bp + 1), 2); tag = EXTRACT_16BITS(bp + 1); /* XXX we don't know yet if the IANA will * preclude overlap of 1-byte and 2-byte spaces. * If not, we need to offset tag after this step. */ cp = tok2str(xtag2str, "?xT%u", tag); } else cp = tok2str(tag2str, "?T%u", tag); c = *cp++; if (tag == TAG_PAD || tag == TAG_END) len = 0; else { /* Get the length; check for truncation */ ND_TCHECK2(*bp, 1); len = *bp++; } ND_PRINT((ndo, "\n\t %s Option %u, length %u%s", cp, tag, len, - len > 0 ? ": " : "")); + len > 0 ? ": " : "")); if (tag == TAG_PAD && ndo->ndo_vflag > 2) { u_int ntag = 1; while (ND_TTEST2(*bp, 1) && *bp == TAG_PAD) { bp++; ntag++; } if (ntag > 1) ND_PRINT((ndo, ", occurs %u", ntag)); } if (!ND_TTEST2(*bp, len)) { ND_PRINT((ndo, "[|rfc1048 %u]", len)); return; } if (tag == TAG_DHCP_MESSAGE && len == 1) { uc = *bp++; ND_PRINT((ndo, "%s", tok2str(dhcp_msg_values, "Unknown (%u)", uc))); continue; } if (tag == TAG_PARM_REQUEST) { idx = 0; while (len-- > 0) { uc = *bp++; cp = tok2str(tag2str, "?Option %u", uc); if (idx % 4 == 0) ND_PRINT((ndo, "\n\t ")); else ND_PRINT((ndo, ", ")); ND_PRINT((ndo, "%s", cp + 1)); idx++; } continue; } if (tag == TAG_EXTENDED_REQUEST) { first = 1; while (len > 1) { len -= 2; us = EXTRACT_16BITS(bp); bp += 2; cp = tok2str(xtag2str, "?xT%u", us); if (!first) ND_PRINT((ndo, "+")); ND_PRINT((ndo, "%s", cp + 1)); first = 0; } 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((ndo, "\"")); if (fn_printn(ndo, bp, len, ndo->ndo_snapend)) { ND_PRINT((ndo, "\"")); goto trunc; } ND_PRINT((ndo, "\"")); bp += len; len = 0; break; case 'i': case 'l': case 'L': /* ip addresses/32-bit words */ while (len >= sizeof(ul)) { if (!first) ND_PRINT((ndo, ",")); ul = EXTRACT_32BITS(bp); if (c == 'i') { ul = htonl(ul); ND_PRINT((ndo, "%s", ipaddr_string(ndo, &ul))); } else if (c == 'L') ND_PRINT((ndo, "%d", ul)); else ND_PRINT((ndo, "%u", ul)); bp += sizeof(ul); len -= sizeof(ul); first = 0; } break; case 'p': /* IP address pairs */ while (len >= 2*sizeof(ul)) { if (!first) ND_PRINT((ndo, ",")); memcpy((char *)&ul, (const char *)bp, sizeof(ul)); ND_PRINT((ndo, "(%s:", ipaddr_string(ndo, &ul))); bp += sizeof(ul); memcpy((char *)&ul, (const char *)bp, sizeof(ul)); ND_PRINT((ndo, "%s)", ipaddr_string(ndo, &ul))); bp += sizeof(ul); len -= 2*sizeof(ul); first = 0; } break; case 's': /* shorts */ while (len >= sizeof(us)) { if (!first) ND_PRINT((ndo, ",")); us = EXTRACT_16BITS(bp); ND_PRINT((ndo, "%u", us)); bp += sizeof(us); len -= sizeof(us); first = 0; } break; case 'B': /* boolean */ while (len > 0) { if (!first) ND_PRINT((ndo, ",")); switch (*bp) { case 0: ND_PRINT((ndo, "N")); break; case 1: ND_PRINT((ndo, "Y")); break; default: ND_PRINT((ndo, "%u?", *bp)); break; } ++bp; --len; first = 0; } break; case 'b': case 'x': default: /* Bytes */ while (len > 0) { if (!first) ND_PRINT((ndo, c == 'x' ? ":" : ".")); if (c == 'x') ND_PRINT((ndo, "%02x", *bp)); else ND_PRINT((ndo, "%u", *bp)); ++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((ndo, "ERROR: option %u len %u < 1 bytes", - TAG_NETBIOS_NODE, len)); + if (len < 1) { + ND_PRINT((ndo, "ERROR: length < 1 bytes")); break; } tag = *bp++; --len; ND_PRINT((ndo, "%s", tok2str(nbo2str, NULL, tag))); break; case TAG_OPT_OVERLOAD: /* this option should be at least 1 byte long */ - if (len < 1) { - ND_PRINT((ndo, "ERROR: option %u len %u < 1 bytes", - TAG_OPT_OVERLOAD, len)); + if (len < 1) { + ND_PRINT((ndo, "ERROR: length < 1 bytes")); break; } tag = *bp++; --len; ND_PRINT((ndo, "%s", tok2str(oo2str, NULL, tag))); break; case TAG_CLIENT_FQDN: /* this option should be at least 3 bytes long */ - if (len < 3) { - ND_PRINT((ndo, "ERROR: option %u len %u < 3 bytes", - TAG_CLIENT_FQDN, len)); + if (len < 3) { + ND_PRINT((ndo, "ERROR: length < 3 bytes")); bp += len; len = 0; break; } if (*bp) ND_PRINT((ndo, "[%s] ", client_fqdn_flags(*bp))); bp++; if (*bp || *(bp+1)) ND_PRINT((ndo, "%u/%u ", *bp, *(bp+1))); bp += 2; ND_PRINT((ndo, "\"")); if (fn_printn(ndo, bp, len - 3, ndo->ndo_snapend)) { ND_PRINT((ndo, "\"")); goto trunc; } ND_PRINT((ndo, "\"")); bp += len - 3; len = 0; break; case TAG_CLIENT_ID: - { int type; + { + int type; /* this option should be at least 1 byte long */ - if (len < 1) { - ND_PRINT((ndo, "ERROR: option %u len %u < 1 bytes", - TAG_CLIENT_ID, len)); + if (len < 1) { + ND_PRINT((ndo, "ERROR: length < 1 bytes")); break; } type = *bp++; len--; if (type == 0) { ND_PRINT((ndo, "\"")); if (fn_printn(ndo, bp, len, ndo->ndo_snapend)) { ND_PRINT((ndo, "\"")); goto trunc; } ND_PRINT((ndo, "\"")); bp += len; len = 0; break; } else { ND_PRINT((ndo, "%s ", tok2str(arp2str, "hardware-type %u,", type))); while (len > 0) { if (!first) ND_PRINT((ndo, ":")); ND_PRINT((ndo, "%02x", *bp)); ++bp; --len; first = 0; } } break; } case TAG_AGENT_CIRCUIT: while (len >= 2) { subopt = *bp++; suboptlen = *bp++; len -= 2; if (suboptlen > len) { ND_PRINT((ndo, "\n\t %s SubOption %u, length %u: length goes past end of option", - tok2str(agent_suboption_values, "Unknown", subopt), - subopt, - suboptlen)); + tok2str(agent_suboption_values, "Unknown", subopt), + subopt, + suboptlen)); bp += len; len = 0; break; } ND_PRINT((ndo, "\n\t %s SubOption %u, length %u: ", - tok2str(agent_suboption_values, "Unknown", subopt), - subopt, - suboptlen)); + 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: - fn_printn(ndo, bp, suboptlen, NULL); + if (fn_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; + } + 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((ndo, "ERROR: option %u len %u < 5 bytes", - TAG_CLASSLESS_STATIC_RT, len)); + if (len < 5) { + ND_PRINT((ndo, "ERROR: length < 5 bytes")); bp += len; len = 0; break; } while (len > 0) { if (!first) ND_PRINT((ndo, ",")); mask_width = *bp++; len--; /* mask_width <= 32 */ if (mask_width > 32) { - ND_PRINT((ndo, "[ERROR: Mask width (%d) > 32]", mask_width)); + ND_PRINT((ndo, "[ERROR: Mask width (%d) > 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((ndo, "[ERROR: Remaining length (%u) < %u bytes]", len, significant_octets + 4)); + ND_PRINT((ndo, "[ERROR: Remaining length (%u) < %u bytes]", len, significant_octets + 4)); bp += len; len = 0; break; } ND_PRINT((ndo, "(")); if (mask_width == 0) ND_PRINT((ndo, "default")); else { for (i = 0; i < significant_octets ; i++) { if (i > 0) ND_PRINT((ndo, ".")); ND_PRINT((ndo, "%d", *bp++)); } for (i = significant_octets ; i < 4 ; i++) ND_PRINT((ndo, ".0")); ND_PRINT((ndo, "/%d", mask_width)); } memcpy((char *)&ul, (const char *)bp, sizeof(ul)); ND_PRINT((ndo, ":%s)", ipaddr_string(ndo, &ul))); bp += sizeof(ul); len -= (significant_octets + 4); first = 0; } - } - break; + break; + } + case TAG_USER_CLASS: + { + u_int suboptnumber = 1; + + first = 1; + if (len < 2) { + ND_PRINT((ndo, "ERROR: length < 2 bytes")); + bp += len; + len = 0; + break; + } + while (len > 0) { + suboptlen = *bp++; + len--; + ND_PRINT((ndo, "\n\t ")); + ND_PRINT((ndo, "instance#%u: ", suboptnumber)); + if (suboptlen == 0) { + ND_PRINT((ndo, "ERROR: suboption length must be non-zero")); + bp += len; + len = 0; + break; + } + if (len < suboptlen) { + ND_PRINT((ndo, "ERROR: malformed option")); + bp += len; + len = 0; + break; + } + ND_PRINT((ndo, "\"")); + if (fn_printn(ndo, bp, suboptlen, ndo->ndo_snapend)) { + ND_PRINT((ndo, "\"")); + goto trunc; + } + ND_PRINT((ndo, "\"")); + ND_PRINT((ndo, ", length %d", suboptlen)); + suboptnumber++; + len -= suboptlen; + bp += suboptlen; + } + break; + } + default: ND_PRINT((ndo, "[unknown special tag %u, size %u]", - tag, len)); + tag, len)); bp += len; len = 0; break; } break; } /* Data left over? */ if (len) { ND_PRINT((ndo, "\n\t trailing data length %u", len)); bp += len; } } return; trunc: ND_PRINT((ndo, "|[rfc1048]")); } static void cmu_print(netdissect_options *ndo, - register const u_char *bp) + register const u_char *bp) { register const struct cmu_vend *cmu; #define PRINTCMUADDR(m, s) { ND_TCHECK(cmu->m); \ if (cmu->m.s_addr != 0) \ ND_PRINT((ndo, " %s:%s", s, ipaddr_string(ndo, &cmu->m.s_addr))); } ND_PRINT((ndo, " vend-cmu")); cmu = (const struct cmu_vend *)bp; /* Only print if there are unknown bits */ ND_TCHECK(cmu->v_flags); if ((cmu->v_flags & ~(VF_SMASK)) != 0) ND_PRINT((ndo, " F:0x%x", cmu->v_flags)); PRINTCMUADDR(v_dgate, "DG"); PRINTCMUADDR(v_smask, cmu->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((ndo, "%s", tstr)); #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; } Index: head/contrib/tcpdump/print-cdp.c =================================================================== --- head/contrib/tcpdump/print-cdp.c (revision 285274) +++ head/contrib/tcpdump/print-cdp.c (revision 285275) @@ -1,369 +1,405 @@ /* * 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: * http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/frames.htm */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "interface.h" #include "addrtoname.h" #include "extract.h" /* must come after interface.h */ #include "nlpid.h" static const char tstr[] = "[|cdp]"; -#define CDP_HEADER_LEN 4 +#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_tlv_values[] = { { 0x01, "Device-ID"}, { 0x02, "Address"}, { 0x03, "Port-ID"}, { 0x04, "Capability"}, { 0x05, "Version String"}, { 0x06, "Platform"}, { 0x07, "Prefixes"}, { 0x08, "Protocol-Hello option"}, { 0x09, "VTP Management Domain"}, { 0x0a, "Native VLAN ID"}, { 0x0b, "Duplex"}, { 0x0e, "ATA-186 VoIP VLAN request"}, { 0x0f, "ATA-186 VoIP VLAN assignment"}, { 0x10, "power consumption"}, { 0x11, "MTU"}, { 0x12, "AVVID trust bitmap"}, { 0x13, "AVVID untrusted ports CoS"}, { 0x14, "System Name"}, { 0x15, "System Object ID (not decoded)"}, { 0x16, "Management Addresses"}, { 0x17, "Physical Location"}, { 0, NULL} }; 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 int cdp_print_addr(netdissect_options *, const u_char *, int); static int cdp_print_prefixes(netdissect_options *, const u_char *, int); static unsigned long cdp_get_number(const u_char *, int); void cdp_print(netdissect_options *ndo, const u_char *pptr, u_int length, u_int caplen) { int type, len, i, j; - const u_char *tptr; + const u_char *tptr; if (caplen < CDP_HEADER_LEN) { ND_PRINT((ndo, "%s", tstr)); return; } - tptr = pptr; /* temporary pointer */ + tptr = pptr; /* temporary pointer */ ND_TCHECK2(*tptr, CDP_HEADER_LEN); - ND_PRINT((ndo, "CDPv%u, ttl: %us", *tptr, *(tptr + 1))); + ND_PRINT((ndo, "CDPv%u, ttl: %us", *(tptr + CDP_HEADER_VERSION_OFFSET), + *(tptr + CDP_HEADER_TTL_OFFSET))); if (ndo->ndo_vflag) - ND_PRINT((ndo, ", checksum: %u (unverified), length %u", EXTRACT_16BITS(tptr), length)); + ND_PRINT((ndo, ", checksum: 0x%04x (unverified), length %u", EXTRACT_16BITS(tptr+CDP_HEADER_CHECKSUM_OFFSET), length)); tptr += CDP_HEADER_LEN; while (tptr < (pptr+length)) { - ND_TCHECK2(*tptr, 4); /* read out Type and Length */ - type = EXTRACT_16BITS(tptr); - len = EXTRACT_16BITS(tptr+2); /* object length includes the 4 bytes header length */ - tptr += 4; - len -= 4; + ND_TCHECK2(*tptr, CDP_TLV_HEADER_LEN); /* read out Type and Length */ + type = EXTRACT_16BITS(tptr+CDP_TLV_TYPE_OFFSET); + len = EXTRACT_16BITS(tptr+CDP_TLV_LEN_OFFSET); /* object length includes the 4 bytes header length */ + if (len < CDP_TLV_HEADER_LEN) { + if (ndo->ndo_vflag) + ND_PRINT((ndo, "\n\t%s (0x%02x), TLV length: %u byte%s (too short)", + tok2str(cdp_tlv_values,"unknown field type", type), + type, + len, + PLURAL_SUFFIX(len))); /* plural */ + else + ND_PRINT((ndo, ", %s TLV length %u too short", + tok2str(cdp_tlv_values,"unknown field type", type), + len)); + break; + } + tptr += CDP_TLV_HEADER_LEN; + len -= CDP_TLV_HEADER_LEN; ND_TCHECK2(*tptr, len); - if (ndo->ndo_vflag || type == 1) { /* in non-verbose mode just print Device-ID */ + if (ndo->ndo_vflag || type == 1) { /* in non-verbose mode just print Device-ID */ - if (ndo->ndo_vflag) - ND_PRINT((ndo, "\n\t%s (0x%02x), length: %u byte%s: ", - tok2str(cdp_tlv_values,"unknown field type", type), - type, - len, - PLURAL_SUFFIX(len))); /* plural */ + if (ndo->ndo_vflag) + ND_PRINT((ndo, "\n\t%s (0x%02x), value length: %u byte%s: ", + tok2str(cdp_tlv_values,"unknown field type", type), + type, + len, + PLURAL_SUFFIX(len))); /* plural */ - switch (type) { + switch (type) { - case 0x01: /* Device-ID */ - if (!ndo->ndo_vflag) - ND_PRINT((ndo, ", Device-ID ")); - ND_PRINT((ndo, "'")); - fn_printn(ndo, tptr, len, NULL); - ND_PRINT((ndo, "'")); + case 0x01: /* Device-ID */ + if (!ndo->ndo_vflag) + ND_PRINT((ndo, ", Device-ID ")); + ND_PRINT((ndo, "'")); + (void)fn_printn(ndo, tptr, len, NULL); + ND_PRINT((ndo, "'")); break; - case 0x02: /* Address */ - if (cdp_print_addr(ndo, tptr, len) < 0) - goto trunc; + case 0x02: /* Address */ + if (cdp_print_addr(ndo, tptr, len) < 0) + goto trunc; break; - case 0x03: /* Port-ID */ - ND_PRINT((ndo, "'")); - fn_printn(ndo, tptr, len, NULL); - ND_PRINT((ndo, "'")); + case 0x03: /* Port-ID */ + ND_PRINT((ndo, "'")); + (void)fn_printn(ndo, tptr, len, NULL); + ND_PRINT((ndo, "'")); break; - case 0x04: /* Capabilities */ + case 0x04: /* Capabilities */ + if (len < 4) + goto trunc; ND_PRINT((ndo, "(0x%08x): %s", - EXTRACT_32BITS(tptr), - bittok2str(cdp_capability_values, "none", EXTRACT_32BITS(tptr)))); + EXTRACT_32BITS(tptr), + bittok2str(cdp_capability_values, "none", EXTRACT_32BITS(tptr)))); break; - case 0x05: /* Version */ - ND_PRINT((ndo, "\n\t ")); - for (i=0;i 1) { ND_PRINT((ndo, "/")); - fn_printn(ndo, tptr + 1, len - 1, NULL); - } + (void)fn_printn(ndo, tptr + 1, len - 1, NULL); + } break; - default: - print_unknown_data(ndo, tptr, "\n\t ", len); + default: + print_unknown_data(ndo, tptr, "\n\t ", len); break; - } - } - /* avoid infinite loop */ - if (len == 0) - break; + } + } tptr = tptr+len; } - if (ndo->ndo_vflag < 1) - ND_PRINT((ndo, ", length %u", caplen)); + if (ndo->ndo_vflag < 1) + ND_PRINT((ndo, ", length %u", caplen)); return; trunc: ND_PRINT((ndo, "%s", tstr)); } /* * 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 int cdp_print_addr(netdissect_options *ndo, - const u_char * p, int l) + const u_char * p, int l) { int pt, pl, al, num; const u_char *endp = p + l; #ifdef INET6 static const u_char prot_ipv6[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x86, 0xdd }; #endif - ND_TCHECK2(*p, 2); + ND_TCHECK2(*p, 4); + if (p + 4 > endp) + goto trunc; num = EXTRACT_32BITS(p); p += 4; while (p < endp && num >= 0) { ND_TCHECK2(*p, 2); if (p + 2 > endp) goto trunc; pt = p[0]; /* type of "protocol" field */ pl = p[1]; /* length of "protocol" field */ p += 2; ND_TCHECK2(p[pl], 2); if (p + pl + 2 > endp) goto trunc; al = EXTRACT_16BITS(&p[pl]); /* address length */ if (pt == PT_NLPID && pl == 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 += 3; ND_TCHECK2(*p, 4); if (p + 4 > endp) goto trunc; ND_PRINT((ndo, "IPv4 (%u) %s", num, ipaddr_string(ndo, p))); p += 4; } #ifdef INET6 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 += 10; ND_TCHECK2(*p, al); if (p + al > endp) goto trunc; ND_PRINT((ndo, "IPv6 (%u) %s", num, ip6addr_string(ndo, p))); p += al; } #endif else { /* * Generic case: just print raw data */ ND_TCHECK2(*p, pl); if (p + pl > endp) goto trunc; ND_PRINT((ndo, "pt=0x%02x, pl=%d, pb=", *(p - 2), pl)); while (pl-- > 0) ND_PRINT((ndo, " %02x", *p++)); ND_TCHECK2(*p, 2); if (p + 2 > endp) goto trunc; al = (*p << 8) + *(p + 1); ND_PRINT((ndo, ", al=%d, a=", al)); p += 2; ND_TCHECK2(*p, al); if (p + al > endp) goto trunc; while (al-- > 0) ND_PRINT((ndo, " %02x", *p++)); } num--; if (num) ND_PRINT((ndo, " ")); } return 0; trunc: return -1; } static int cdp_print_prefixes(netdissect_options *ndo, - const u_char * p, int l) + const u_char * p, int l) { if (l % 5) goto trunc; ND_PRINT((ndo, " IPv4 Prefixes (%d):", l / 5)); while (l > 0) { ND_PRINT((ndo, " %u.%u.%u.%u/%u", p[0], p[1], p[2], p[3], p[4])); l -= 5; p += 5; } return 0; trunc: return -1; } /* read in a -byte number, MSB first * (of course this can handle max sizeof(long)) */ static unsigned long cdp_get_number(const u_char * p, int l) { unsigned long res=0; while( l>0 ) { res = (res<<8) + *p; p++; l--; } return res; } Index: head/contrib/tcpdump/print-cfm.c =================================================================== --- head/contrib/tcpdump/print-cfm.c (revision 285274) +++ head/contrib/tcpdump/print-cfm.c (revision 285275) @@ -1,636 +1,637 @@ /* * 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 Connectivity Fault Management Protocols as per 802.1ag. * * Original code by Hannes Gredler (hannes@juniper.net) */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "interface.h" #include "extract.h" #include "ether.h" #include "addrtoname.h" #include "oui.h" #include "af.h" struct cfm_common_header_t { uint8_t mdlevel_version; uint8_t opcode; uint8_t flags; 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, "Continouity 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 { uint8_t sequence[4]; uint8_t ma_epi[2]; uint8_t md_nameformat; uint8_t md_namelength; uint8_t md_name[46]; /* md name and short ma name */ uint8_t reserved_itu[16]; uint8_t reserved[6]; }; /* * Timer Bases for the CCM Interval field. * Expressed in units of seconds. */ const float ccm_interval_base[8] = {0, 0.003333, 0.01, 0.1, 1, 10, 60, 600}; #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 { uint8_t transaction_id[4]; uint8_t reserved[4]; }; struct cfm_ltm_t { uint8_t transaction_id[4]; uint8_t egress_id[8]; uint8_t ttl; uint8_t original_mac[ETHER_ADDR_LEN]; uint8_t target_mac[ETHER_ADDR_LEN]; uint8_t reserved[3]; }; static const struct tok cfm_ltm_flag_values[] = { { 0x80, "Use Forwarding-DB only"}, { 0, NULL} }; struct cfm_ltr_t { uint8_t transaction_id[4]; uint8_t last_egress_id[8]; uint8_t next_egress_id[8]; uint8_t ttl; uint8_t replay_action; uint8_t reserved[6]; }; 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 { uint8_t type; uint8_t length[2]; }; /* 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_mgmt_addr_print(netdissect_options *ndo, - register const u_char *tptr) { - + register const u_char *tptr) +{ u_int mgmt_addr_type; u_int hexdump = FALSE; /* * Altough AFIs are tpically 2 octects wide, * 802.1ab specifies that this field width * is only once octet */ mgmt_addr_type = *tptr; ND_PRINT((ndo, "\n\t Management Address Type %s (%u)", tok2str(af_values, "Unknown", mgmt_addr_type), mgmt_addr_type)); /* * Resolve the passed in Address. */ switch(mgmt_addr_type) { case AFNUM_INET: ND_PRINT((ndo, ", %s", ipaddr_string(ndo, tptr + 1))); break; #ifdef INET6 case AFNUM_INET6: ND_PRINT((ndo, ", %s", ip6addr_string(ndo, tptr + 1))); break; #endif default: hexdump = TRUE; break; } return hexdump; } /* * The egress-ID string is a 16-Bit string plus a MAC address. */ static const char * -cfm_egress_id_string(netdissect_options *ndo, register const u_char *tptr) { +cfm_egress_id_string(netdissect_options *ndo, register const u_char *tptr) +{ static char egress_id_buffer[80]; snprintf(egress_id_buffer, sizeof(egress_id_buffer), "MAC 0x%4x-%s", EXTRACT_16BITS(tptr), etheraddr_string(ndo, tptr+2)); return egress_id_buffer; } void cfm_print(netdissect_options *ndo, - register const u_char *pptr, register u_int length) { - + register const u_char *pptr, register u_int length) +{ const struct cfm_common_header_t *cfm_common_header; const struct cfm_tlv_header_t *cfm_tlv_header; const uint8_t *tptr, *tlv_ptr, *ma_name, *ma_nameformat, *ma_namelength; 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; tptr=pptr; cfm_common_header = (const struct cfm_common_header_t *)pptr; ND_TCHECK(*cfm_common_header); /* * Sanity checking of the header. */ if (CFM_EXTRACT_VERSION(cfm_common_header->mdlevel_version) != CFM_VERSION) { ND_PRINT((ndo, "CFMv%u not supported, length %u", CFM_EXTRACT_VERSION(cfm_common_header->mdlevel_version), length)); return; } ND_PRINT((ndo, "CFMv%u %s, MD Level %u, length %u", CFM_EXTRACT_VERSION(cfm_common_header->mdlevel_version), tok2str(cfm_opcode_values, "unknown (%u)", cfm_common_header->opcode), CFM_EXTRACT_MD_LEVEL(cfm_common_header->mdlevel_version), length)); /* * In non-verbose mode just print the opcode and md-level. */ if (ndo->ndo_vflag < 1) { return; } ND_PRINT((ndo, "\n\tFirst TLV offset %u", cfm_common_header->first_tlv_offset)); tptr += sizeof(const struct cfm_common_header_t); tlen = length - sizeof(struct cfm_common_header_t); switch (cfm_common_header->opcode) { case CFM_OPCODE_CCM: msg_ptr.cfm_ccm = (const struct cfm_ccm_t *)tptr; ccm_interval = CFM_EXTRACT_CCM_INTERVAL(cfm_common_header->flags); ND_PRINT((ndo, ", Flags [CCM Interval %u%s]", ccm_interval, cfm_common_header->flags & CFM_CCM_RDI_FLAG ? ", RDI" : "")); /* * Resolve the CCM interval field. */ if (ccm_interval) { ND_PRINT((ndo, "\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((ndo, "\n\t Sequence Number 0x%08x, MA-End-Point-ID 0x%04x", EXTRACT_32BITS(msg_ptr.cfm_ccm->sequence), EXTRACT_16BITS(msg_ptr.cfm_ccm->ma_epi))); /* * Resolve the MD fields. */ ND_PRINT((ndo, "\n\t MD Name Format %s (%u), MD Name length %u", tok2str(cfm_md_nameformat_values, "Unknown", msg_ptr.cfm_ccm->md_nameformat), msg_ptr.cfm_ccm->md_nameformat, msg_ptr.cfm_ccm->md_namelength)); if (msg_ptr.cfm_ccm->md_nameformat != CFM_CCM_MD_FORMAT_NONE) { ND_PRINT((ndo, "\n\t MD Name: ")); switch (msg_ptr.cfm_ccm->md_nameformat) { case CFM_CCM_MD_FORMAT_DNS: case CFM_CCM_MD_FORMAT_CHAR: safeputs(ndo, msg_ptr.cfm_ccm->md_name, msg_ptr.cfm_ccm->md_namelength); break; case CFM_CCM_MD_FORMAT_MAC: ND_PRINT((ndo, "\n\t MAC %s", etheraddr_string(ndo, msg_ptr.cfm_ccm->md_name))); break; /* FIXME add printers for those MD formats - hexdump for now */ case CFM_CCM_MA_FORMAT_8021: default: print_unknown_data(ndo, msg_ptr.cfm_ccm->md_name, "\n\t ", msg_ptr.cfm_ccm->md_namelength); } } /* * Resolve the MA fields. */ ma_nameformat = msg_ptr.cfm_ccm->md_name + msg_ptr.cfm_ccm->md_namelength; ma_namelength = msg_ptr.cfm_ccm->md_name + msg_ptr.cfm_ccm->md_namelength + 1; ma_name = msg_ptr.cfm_ccm->md_name + msg_ptr.cfm_ccm->md_namelength + 2; ND_PRINT((ndo, "\n\t MA Name-Format %s (%u), MA name length %u", tok2str(cfm_ma_nameformat_values, "Unknown", *ma_nameformat), *ma_nameformat, *ma_namelength)); ND_PRINT((ndo, "\n\t MA Name: ")); switch (*ma_nameformat) { case CFM_CCM_MA_FORMAT_CHAR: safeputs(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; ND_PRINT((ndo, ", Flags [%s]", bittok2str(cfm_ltm_flag_values, "none", cfm_common_header->flags))); ND_PRINT((ndo, "\n\t Transaction-ID 0x%08x, Egress-ID %s, ttl %u", EXTRACT_32BITS(msg_ptr.cfm_ltm->transaction_id), cfm_egress_id_string(ndo, msg_ptr.cfm_ltm->egress_id), msg_ptr.cfm_ltm->ttl)); ND_PRINT((ndo, "\n\t Original-MAC %s, Target-MAC %s", etheraddr_string(ndo, msg_ptr.cfm_ltm->original_mac), etheraddr_string(ndo, msg_ptr.cfm_ltm->target_mac))); break; case CFM_OPCODE_LTR: msg_ptr.cfm_ltr = (const struct cfm_ltr_t *)tptr; ND_PRINT((ndo, ", Flags [%s]", bittok2str(cfm_ltr_flag_values, "none", cfm_common_header->flags))); ND_PRINT((ndo, "\n\t Transaction-ID 0x%08x, Last-Egress-ID %s", EXTRACT_32BITS(msg_ptr.cfm_ltr->transaction_id), cfm_egress_id_string(ndo, msg_ptr.cfm_ltr->last_egress_id))); ND_PRINT((ndo, "\n\t Next-Egress-ID %s, ttl %u", cfm_egress_id_string(ndo, msg_ptr.cfm_ltr->next_egress_id), msg_ptr.cfm_ltr->ttl)); ND_PRINT((ndo, "\n\t Replay-Action %s (%u)", tok2str(cfm_ltr_replay_action_values, "Unknown", msg_ptr.cfm_ltr->replay_action), 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: if (tlen > cfm_common_header->first_tlv_offset) { print_unknown_data(ndo, tptr, "\n\t ", tlen - cfm_common_header->first_tlv_offset); } break; } /* * Sanity check for not walking off. */ if (tlen <= cfm_common_header->first_tlv_offset) { return; } tptr += cfm_common_header->first_tlv_offset; tlen -= cfm_common_header->first_tlv_offset; while (tlen > 0) { cfm_tlv_header = (const struct cfm_tlv_header_t *)tptr; /* Enough to read the tlv type ? */ ND_TCHECK2(*tptr, 1); cfm_tlv_type=cfm_tlv_header->type; if (cfm_tlv_type != CFM_TLV_END) { /* did we capture enough for fully decoding the object header ? */ ND_TCHECK2(*tptr, sizeof(struct cfm_tlv_header_t)); cfm_tlv_len=EXTRACT_16BITS(&cfm_tlv_header->length); } else { cfm_tlv_len = 0; } ND_PRINT((ndo, "\n\t%s TLV (0x%02x), length %u", tok2str(cfm_tlv_values, "Unknown", cfm_tlv_type), cfm_tlv_type, cfm_tlv_len)); /* sanity check for not walking off and infinite loop check. */ if ((cfm_tlv_type != CFM_TLV_END) && ((cfm_tlv_len + sizeof(struct cfm_tlv_header_t) > tlen) || (!cfm_tlv_len))) { print_unknown_data(ndo, tptr, "\n\t ", tlen); return; } tptr += sizeof(struct cfm_tlv_header_t); tlen -= sizeof(struct cfm_tlv_header_t); tlv_ptr = tptr; /* did we capture enough for fully decoding the object ? */ if (cfm_tlv_type != CFM_TLV_END) { ND_TCHECK2(*tptr, cfm_tlv_len); } hexdump = FALSE; switch(cfm_tlv_type) { case CFM_TLV_END: /* we are done - bail out */ return; case CFM_TLV_PORT_STATUS: ND_PRINT((ndo, ", Status: %s (%u)", tok2str(cfm_tlv_port_status_values, "Unknown", *tptr), *tptr)); break; case CFM_TLV_INTERFACE_STATUS: ND_PRINT((ndo, ", Status: %s (%u)", tok2str(cfm_tlv_interface_status_values, "Unknown", *tptr), *tptr)); break; case CFM_TLV_PRIVATE: ND_PRINT((ndo, ", Vendor: %s (%u), Sub-Type %u", tok2str(oui_values,"Unknown", EXTRACT_24BITS(tptr)), EXTRACT_24BITS(tptr), *(tptr + 3))); hexdump = TRUE; break; case CFM_TLV_SENDER_ID: { u_int chassis_id_type, chassis_id_length; u_int mgmt_addr_length; /* * Check if there is a Chassis-ID. */ chassis_id_length = *tptr; if (chassis_id_length > tlen) { hexdump = TRUE; break; } tptr++; tlen--; if (chassis_id_length) { chassis_id_type = *tptr; ND_PRINT((ndo, "\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)); switch (chassis_id_type) { case CFM_CHASSIS_ID_MAC_ADDRESS: ND_PRINT((ndo, "\n\t MAC %s", etheraddr_string(ndo, tptr + 1))); break; case CFM_CHASSIS_ID_NETWORK_ADDRESS: hexdump |= cfm_mgmt_addr_print(ndo, tptr); 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: safeputs(ndo, tptr + 1, chassis_id_length); break; default: hexdump = TRUE; break; } } tptr += chassis_id_length; tlen -= chassis_id_length; /* * Check if there is a Management Address. */ mgmt_addr_length = *tptr; if (mgmt_addr_length > tlen) { hexdump = TRUE; break; } tptr++; tlen--; if (mgmt_addr_length) { hexdump |= cfm_mgmt_addr_print(ndo, tptr); } 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); tptr+=cfm_tlv_len; tlen-=cfm_tlv_len; } return; trunc: ND_PRINT((ndo, "\n\t\t packet exceeded snapshot")); } Index: head/contrib/tcpdump/print-chdlc.c =================================================================== --- head/contrib/tcpdump/print-chdlc.c (revision 285274) +++ head/contrib/tcpdump/print-chdlc.c (revision 285275) @@ -1,206 +1,205 @@ /* * 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. */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "interface.h" #include "addrtoname.h" #include "ethertype.h" #include "extract.h" #include "chdlc.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 */ u_int chdlc_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, register const u_char *p) { register u_int length = h->len; register u_int caplen = h->caplen; if (caplen < CHDLC_HDRLEN) { ND_PRINT((ndo, "[|chdlc]")); return (caplen); } return (chdlc_print(ndo, p,length)); } u_int -chdlc_print(netdissect_options *ndo, register const u_char *p, u_int length) { +chdlc_print(netdissect_options *ndo, register const u_char *p, u_int length) +{ u_int proto; proto = EXTRACT_16BITS(&p[2]); if (ndo->ndo_eflag) { ND_PRINT((ndo, "%s, ethertype %s (0x%04x), length %u: ", tok2str(chdlc_cast_values, "0x%02x", p[0]), tok2str(ethertype_values, "Unknown", proto), proto, length)); } length -= CHDLC_HDRLEN; p += CHDLC_HDRLEN; switch (proto) { case ETHERTYPE_IP: ip_print(ndo, p, length); break; -#ifdef INET6 case ETHERTYPE_IPV6: ip6_print(ndo, p, length); break; -#endif case CHDLC_TYPE_SLARP: chdlc_slarp_print(ndo, p, length); break; #if 0 case CHDLC_TYPE_CDP: chdlc_cdp_print(p, length); break; #endif 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 (*(p+1) == 0x81 || *(p+1) == 0x82 || *(p+1) == 0x83) isoclns_print(ndo, p + 1, length - 1, length - 1); else isoclns_print(ndo, p, length, length); break; default: if (!ndo->ndo_eflag) ND_PRINT((ndo, "unknown CHDLC protocol (0x%04x)", proto)); break; } return (CHDLC_HDRLEN); } /* * The fixed-length portion of a SLARP packet. */ struct cisco_slarp { uint8_t code[4]; #define SLARP_REQUEST 0 #define SLARP_REPLY 1 #define SLARP_KEEPALIVE 2 union { struct { uint8_t addr[4]; uint8_t mask[4]; } addr; struct { uint8_t myseq[4]; uint8_t yourseq[4]; uint8_t rel[2]; } 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; ND_PRINT((ndo, "SLARP (length: %u), ",length)); if (length < SLARP_MIN_LEN) goto trunc; slarp = (const struct cisco_slarp *)cp; ND_TCHECK2(*slarp, SLARP_MIN_LEN); switch (EXTRACT_32BITS(&slarp->code)) { case SLARP_REQUEST: ND_PRINT((ndo, "request")); /* * At least according to William "Chops" Westfield's * message in * * http://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((ndo, "reply %s/%s", ipaddr_string(ndo, &slarp->un.addr.addr), ipaddr_string(ndo, &slarp->un.addr.mask))); break; case SLARP_KEEPALIVE: ND_PRINT((ndo, "keepalive: mineseen=0x%08x, yourseen=0x%08x, reliability=0x%04x", EXTRACT_32BITS(&slarp->un.keep.myseq), EXTRACT_32BITS(&slarp->un.keep.yourseq), EXTRACT_16BITS(&slarp->un.keep.rel))); if (length >= SLARP_MAX_LEN) { /* uptime-stamp is optional */ cp += SLARP_MIN_LEN; ND_TCHECK2(*cp, 4); sec = EXTRACT_32BITS(cp) / 1000; min = sec / 60; sec -= min * 60; hrs = min / 60; min -= hrs * 60; days = hrs / 24; hrs -= days * 24; ND_PRINT((ndo, ", link uptime=%ud%uh%um%us",days,hrs,min,sec)); } break; default: ND_PRINT((ndo, "0x%02x unknown", EXTRACT_32BITS(&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((ndo, ", (trailing junk: %d bytes)", length - SLARP_MAX_LEN)); if (ndo->ndo_vflag > 1) print_unknown_data(ndo,cp+4,"\n\t",length-4); return; trunc: ND_PRINT((ndo, "[|slarp]")); } /* * Local Variables: * c-style: whitesmith * c-basic-offset: 8 * End: */ Index: head/contrib/tcpdump/print-cnfp.c =================================================================== --- head/contrib/tcpdump/print-cnfp.c (revision 285274) +++ head/contrib/tcpdump/print-cnfp.c (revision 285275) @@ -1,187 +1,476 @@ /* $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. */ -/* Cisco NetFlow protocol */ +/* + * Cisco NetFlow protocol + * + * See + * + * http://www.cisco.com/c/en/us/td/docs/net_mgmt/netflow_collection_engine/3-6/user/guide/format.html#wp1005892 + */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "interface.h" #include "addrtoname.h" #include "extract.h" #include "tcp.h" #include "ipproto.h" -struct nfhdr { - uint32_t ver_cnt; /* version [15], and # of records */ +struct nfhdr_v1 { + uint16_t version; /* version number */ + uint16_t count; /* # of records */ uint32_t msys_uptime; uint32_t utc_sec; uint32_t utc_nsec; +}; + +struct nfrec_v1 { + struct in_addr src_ina; + struct in_addr dst_ina; + struct in_addr nhop_ina; + uint16_t input; /* SNMP index of input interface */ + uint16_t output; /* SNMP index of output interface */ + uint32_t packets; /* packets in the flow */ + uint32_t octets; /* layer 3 octets in the packets of the flow */ + uint32_t start_time; /* sys_uptime value at start of flow */ + uint32_t last_time; /* sys_uptime value when last packet of flow was received */ + uint16_t srcport; /* TCP/UDP source port or equivalent */ + uint16_t dstport; /* TCP/UDP source port or equivalent */ + uint16_t pad1; /* pad */ + uint8_t proto; /* IP protocol type */ + uint8_t tos; /* IP type of service */ + uint8_t tcp_flags; /* cumulative OR of TCP flags */ + uint8_t pad[3]; /* padding */ + uint32_t reserved; /* unused */ +}; + +struct nfhdr_v5 { + uint16_t version; /* version number */ + uint16_t count; /* # of records */ + uint32_t msys_uptime; + uint32_t utc_sec; + uint32_t utc_nsec; + uint32_t sequence; /* flow sequence number */ + uint8_t engine_type; /* type of flow-switching engine */ + uint8_t engine_id; /* slot number of the flow-switching engine */ + uint16_t sampling_interval; /* sampling mode and interval */ +}; + +struct nfrec_v5 { + struct in_addr src_ina; + struct in_addr dst_ina; + struct in_addr nhop_ina; + uint16_t input; /* SNMP index of input interface */ + uint16_t output; /* SNMP index of output interface */ + uint32_t packets; /* packets in the flow */ + uint32_t octets; /* layer 3 octets in the packets of the flow */ + uint32_t start_time; /* sys_uptime value at start of flow */ + uint32_t last_time; /* sys_uptime value when last packet of flow was received */ + uint16_t srcport; /* TCP/UDP source port or equivalent */ + uint16_t dstport; /* TCP/UDP source port or equivalent */ + uint8_t pad1; /* pad */ + uint8_t tcp_flags; /* cumulative OR of TCP flags */ + uint8_t proto; /* IP protocol type */ + uint8_t tos; /* IP type of service */ + uint16_t src_as; /* AS number of the source */ + uint16_t dst_as; /* AS number of the destination */ + uint8_t src_mask; /* source address mask bits */ + uint8_t dst_mask; /* destination address prefix mask bits */ + uint16_t pad2; + struct in_addr peer_nexthop; /* v6: IP address of the nexthop within the peer (FIB)*/ +}; + +struct nfhdr_v6 { + uint16_t version; /* version number */ + uint16_t count; /* # of records */ + uint32_t msys_uptime; + uint32_t utc_sec; + uint32_t utc_nsec; uint32_t sequence; /* v5 flow sequence number */ uint32_t reserved; /* v5 only */ }; -struct nfrec { +struct nfrec_v6 { struct in_addr src_ina; struct in_addr dst_ina; struct in_addr nhop_ina; - uint32_t ifaces; /* src,dst ifaces */ - uint32_t packets; - uint32_t octets; - uint32_t start_time; /* sys_uptime value */ - uint32_t last_time; /* sys_uptime value */ - uint32_t ports; /* src,dst ports */ - uint32_t proto_tos; /* proto, tos, pad, flags(v5) */ - uint32_t asses; /* v1: flags; v5: src,dst AS */ - uint32_t masks; /* src,dst addr prefix; v6: encaps */ + uint16_t input; /* SNMP index of input interface */ + uint16_t output; /* SNMP index of output interface */ + uint32_t packets; /* packets in the flow */ + uint32_t octets; /* layer 3 octets in the packets of the flow */ + uint32_t start_time; /* sys_uptime value at start of flow */ + uint32_t last_time; /* sys_uptime value when last packet of flow was received */ + uint16_t srcport; /* TCP/UDP source port or equivalent */ + uint16_t dstport; /* TCP/UDP source port or equivalent */ + uint8_t pad1; /* pad */ + uint8_t tcp_flags; /* cumulative OR of TCP flags */ + uint8_t proto; /* IP protocol type */ + uint8_t tos; /* IP type of service */ + uint16_t src_as; /* AS number of the source */ + uint16_t dst_as; /* AS number of the destination */ + uint8_t src_mask; /* source address mask bits */ + uint8_t dst_mask; /* destination address prefix mask bits */ + uint16_t flags; struct in_addr peer_nexthop; /* v6: IP address of the nexthop within the peer (FIB)*/ }; -void -cnfp_print(netdissect_options *ndo, - const u_char *cp, const u_char *bp _U_) +static void +cnfp_v1_print(netdissect_options *ndo, const u_char *cp) { - register const struct nfhdr *nh; - register const struct nfrec *nr; + register const struct nfhdr_v1 *nh; + register const struct nfrec_v1 *nr; struct protoent *pent; int nrecs, ver; #if 0 time_t t; #endif - nh = (const struct nfhdr *)cp; + nh = (const struct nfhdr_v1 *)cp; + ND_TCHECK(*nh); - if ((const u_char *)(nh + 1) > ndo->ndo_snapend) - return; - - nrecs = EXTRACT_32BITS(&nh->ver_cnt) & 0xffff; - ver = (EXTRACT_32BITS(&nh->ver_cnt) & 0xffff0000) >> 16; + ver = EXTRACT_16BITS(&nh->version); + nrecs = EXTRACT_32BITS(&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 = EXTRACT_32BITS(&nh->utc_sec); #endif ND_PRINT((ndo, "NetFlow v%x, %u.%03u uptime, %u.%09u, ", ver, EXTRACT_32BITS(&nh->msys_uptime)/1000, EXTRACT_32BITS(&nh->msys_uptime)%1000, EXTRACT_32BITS(&nh->utc_sec), EXTRACT_32BITS(&nh->utc_nsec))); - if (ver == 5 || ver == 6) { - ND_PRINT((ndo, "#%u, ", EXTRACT_32BITS(&nh->sequence))); - nr = (const struct nfrec *)&nh[1]; - ndo->ndo_snaplen -= 24; - } else { - nr = (const struct nfrec *)&nh->sequence; - ndo->ndo_snaplen -= 16; - } + nr = (const struct nfrec_v1 *)&nh[1]; ND_PRINT((ndo, "%2u recs", nrecs)); - for (; nrecs-- && (const u_char *)(nr + 1) <= ndo->ndo_snapend; nr++) { + for (; nrecs != 0; nr++, nrecs--) { char buf[20]; char asbuf[20]; + /* + * Make sure we have the entire record. + */ + ND_TCHECK(*nr); ND_PRINT((ndo, "\n started %u.%03u, last %u.%03u", EXTRACT_32BITS(&nr->start_time)/1000, EXTRACT_32BITS(&nr->start_time)%1000, EXTRACT_32BITS(&nr->last_time)/1000, EXTRACT_32BITS(&nr->last_time)%1000)); asbuf[0] = buf[0] = '\0'; - if (ver == 5 || ver == 6) { - snprintf(buf, sizeof(buf), "/%u", - (EXTRACT_32BITS(&nr->masks) >> 24) & 0xff); - snprintf(asbuf, sizeof(asbuf), ":%u", - (EXTRACT_32BITS(&nr->asses) >> 16) & 0xffff); - } ND_PRINT((ndo, "\n %s%s%s:%u ", intoa(nr->src_ina.s_addr), buf, asbuf, - EXTRACT_32BITS(&nr->ports) >> 16)); + EXTRACT_16BITS(&nr->srcport))); - if (ver == 5 || ver ==6) { - snprintf(buf, sizeof(buf), "/%d", - (EXTRACT_32BITS(&nr->masks) >> 16) & 0xff); - snprintf(asbuf, sizeof(asbuf), ":%u", - EXTRACT_32BITS(&nr->asses) & 0xffff); + ND_PRINT((ndo, "> %s%s%s:%u ", intoa(nr->dst_ina.s_addr), buf, asbuf, + EXTRACT_16BITS(&nr->dstport))); + + ND_PRINT((ndo, ">> %s\n ", intoa(nr->nhop_ina.s_addr))); + + pent = getprotobynumber(nr->proto); + if (!pent || ndo->ndo_nflag) + ND_PRINT((ndo, "%u ", nr->proto)); + else + ND_PRINT((ndo, "%s ", pent->p_name)); + + /* tcp flags for tcp only */ + if (pent && pent->p_proto == IPPROTO_TCP) { + int flags; + flags = nr->tcp_flags; + ND_PRINT((ndo, "%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((ndo, "tos %u, %u (%u octets) %s", + nr->tos, + EXTRACT_32BITS(&nr->packets), + EXTRACT_32BITS(&nr->octets), buf)); + } + return; + +trunc: + ND_PRINT((ndo, "[|cnfp]")); + return; +} + +static void +cnfp_v5_print(netdissect_options *ndo, const u_char *cp) +{ + register const struct nfhdr_v5 *nh; + register const struct nfrec_v5 *nr; + struct protoent *pent; + int nrecs, ver; +#if 0 + time_t t; +#endif + + nh = (const struct nfhdr_v5 *)cp; + ND_TCHECK(*nh); + + ver = EXTRACT_16BITS(&nh->version); + nrecs = EXTRACT_32BITS(&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 = EXTRACT_32BITS(&nh->utc_sec); +#endif + + ND_PRINT((ndo, "NetFlow v%x, %u.%03u uptime, %u.%09u, ", ver, + EXTRACT_32BITS(&nh->msys_uptime)/1000, + EXTRACT_32BITS(&nh->msys_uptime)%1000, + EXTRACT_32BITS(&nh->utc_sec), EXTRACT_32BITS(&nh->utc_nsec))); + + ND_PRINT((ndo, "#%u, ", EXTRACT_32BITS(&nh->sequence))); + nr = (const struct nfrec_v5 *)&nh[1]; + + ND_PRINT((ndo, "%2u recs", nrecs)); + + for (; nrecs != 0; nr++, nrecs--) { + char buf[20]; + char asbuf[20]; + + /* + * Make sure we have the entire record. + */ + ND_TCHECK(*nr); + ND_PRINT((ndo, "\n started %u.%03u, last %u.%03u", + EXTRACT_32BITS(&nr->start_time)/1000, + EXTRACT_32BITS(&nr->start_time)%1000, + EXTRACT_32BITS(&nr->last_time)/1000, + EXTRACT_32BITS(&nr->last_time)%1000)); + + asbuf[0] = buf[0] = '\0'; + snprintf(buf, sizeof(buf), "/%u", nr->src_mask); + snprintf(asbuf, sizeof(asbuf), ":%u", + EXTRACT_16BITS(&nr->src_as)); + ND_PRINT((ndo, "\n %s%s%s:%u ", intoa(nr->src_ina.s_addr), buf, asbuf, + EXTRACT_16BITS(&nr->srcport))); + + snprintf(buf, sizeof(buf), "/%d", nr->dst_mask); + snprintf(asbuf, sizeof(asbuf), ":%u", + EXTRACT_16BITS(&nr->dst_as)); ND_PRINT((ndo, "> %s%s%s:%u ", intoa(nr->dst_ina.s_addr), buf, asbuf, - EXTRACT_32BITS(&nr->ports) & 0xffff)); + EXTRACT_16BITS(&nr->dstport))); ND_PRINT((ndo, ">> %s\n ", intoa(nr->nhop_ina.s_addr))); - pent = getprotobynumber((EXTRACT_32BITS(&nr->proto_tos) >> 8) & 0xff); + pent = getprotobynumber(nr->proto); if (!pent || ndo->ndo_nflag) - ND_PRINT((ndo, "%u ", - (EXTRACT_32BITS(&nr->proto_tos) >> 8) & 0xff)); + ND_PRINT((ndo, "%u ", nr->proto)); else ND_PRINT((ndo, "%s ", pent->p_name)); /* tcp flags for tcp only */ if (pent && pent->p_proto == IPPROTO_TCP) { int flags; - if (ver == 1) - flags = (EXTRACT_32BITS(&nr->asses) >> 24) & 0xff; - else - flags = (EXTRACT_32BITS(&nr->proto_tos) >> 16) & 0xff; + flags = nr->tcp_flags; ND_PRINT((ndo, "%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'; - if (ver == 6) { - snprintf(buf, sizeof(buf), "(%u<>%u encaps)", - (EXTRACT_32BITS(&nr->masks) >> 8) & 0xff, - (EXTRACT_32BITS(&nr->masks)) & 0xff); + ND_PRINT((ndo, "tos %u, %u (%u octets) %s", + nr->tos, + EXTRACT_32BITS(&nr->packets), + EXTRACT_32BITS(&nr->octets), buf)); + } + return; + +trunc: + ND_PRINT((ndo, "[|cnfp]")); + return; +} + +static void +cnfp_v6_print(netdissect_options *ndo, const u_char *cp) +{ + register const struct nfhdr_v6 *nh; + register const struct nfrec_v6 *nr; + struct protoent *pent; + int nrecs, ver; +#if 0 + time_t t; +#endif + + nh = (const struct nfhdr_v6 *)cp; + ND_TCHECK(*nh); + + ver = EXTRACT_16BITS(&nh->version); + nrecs = EXTRACT_32BITS(&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 = EXTRACT_32BITS(&nh->utc_sec); +#endif + + ND_PRINT((ndo, "NetFlow v%x, %u.%03u uptime, %u.%09u, ", ver, + EXTRACT_32BITS(&nh->msys_uptime)/1000, + EXTRACT_32BITS(&nh->msys_uptime)%1000, + EXTRACT_32BITS(&nh->utc_sec), EXTRACT_32BITS(&nh->utc_nsec))); + + ND_PRINT((ndo, "#%u, ", EXTRACT_32BITS(&nh->sequence))); + nr = (const struct nfrec_v6 *)&nh[1]; + + ND_PRINT((ndo, "%2u recs", nrecs)); + + for (; nrecs != 0; nr++, nrecs--) { + char buf[20]; + char asbuf[20]; + + /* + * Make sure we have the entire record. + */ + ND_TCHECK(*nr); + ND_PRINT((ndo, "\n started %u.%03u, last %u.%03u", + EXTRACT_32BITS(&nr->start_time)/1000, + EXTRACT_32BITS(&nr->start_time)%1000, + EXTRACT_32BITS(&nr->last_time)/1000, + EXTRACT_32BITS(&nr->last_time)%1000)); + + asbuf[0] = buf[0] = '\0'; + snprintf(buf, sizeof(buf), "/%u", nr->src_mask); + snprintf(asbuf, sizeof(asbuf), ":%u", + EXTRACT_16BITS(&nr->src_as)); + ND_PRINT((ndo, "\n %s%s%s:%u ", intoa(nr->src_ina.s_addr), buf, asbuf, + EXTRACT_16BITS(&nr->srcport))); + + snprintf(buf, sizeof(buf), "/%d", nr->dst_mask); + snprintf(asbuf, sizeof(asbuf), ":%u", + EXTRACT_16BITS(&nr->dst_as)); + ND_PRINT((ndo, "> %s%s%s:%u ", intoa(nr->dst_ina.s_addr), buf, asbuf, + EXTRACT_16BITS(&nr->dstport))); + + ND_PRINT((ndo, ">> %s\n ", intoa(nr->nhop_ina.s_addr))); + + pent = getprotobynumber(nr->proto); + if (!pent || ndo->ndo_nflag) + ND_PRINT((ndo, "%u ", nr->proto)); + else + ND_PRINT((ndo, "%s ", pent->p_name)); + + /* tcp flags for tcp only */ + if (pent && pent->p_proto == IPPROTO_TCP) { + int flags; + flags = nr->tcp_flags; + ND_PRINT((ndo, "%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)", + (EXTRACT_16BITS(&nr->flags) >> 8) & 0xff, + (EXTRACT_16BITS(&nr->flags)) & 0xff); ND_PRINT((ndo, "tos %u, %u (%u octets) %s", - EXTRACT_32BITS(&nr->proto_tos) & 0xff, + nr->tos, EXTRACT_32BITS(&nr->packets), EXTRACT_32BITS(&nr->octets), buf)); } + return; + +trunc: + ND_PRINT((ndo, "[|cnfp]")); + return; +} + +void +cnfp_print(netdissect_options *ndo, const u_char *cp) +{ + int ver; + + /* + * First 2 bytes are the version number. + */ + ND_TCHECK2(*cp, 2); + ver = EXTRACT_16BITS(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((ndo, "NetFlow v%x", ver)); + break; + } + return; + +trunc: + ND_PRINT((ndo, "[|cnfp]")); + return; } Index: head/contrib/tcpdump/print-dccp.c =================================================================== --- head/contrib/tcpdump/print-dccp.c (revision 285274) +++ head/contrib/tcpdump/print-dccp.c (revision 285275) @@ -1,636 +1,671 @@ /* * 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 */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "interface.h" #include "addrtoname.h" #include "extract.h" /* must come after interface.h */ #include "ip.h" #ifdef INET6 #include "ip6.h" #endif #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 { uint16_t dccph_sport, dccph_dport; uint8_t dccph_doff; uint8_t dccph_ccval_cscov; uint16_t dccph_checksum; uint8_t dccph_xtr; uint8_t dccph_seq[3]; } UNALIGNED; /** * 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 { uint16_t dccph_sport, dccph_dport; uint8_t dccph_doff; uint8_t dccph_ccval_cscov; uint16_t dccph_checksum; uint8_t dccph_xtr; uint8_t reserved; uint8_t dccph_seq[6]; } UNALIGNED; #define DCCPH_CCVAL(dh) (((dh)->dccph_ccval_cscov >> 4) & 0xF) #define DCCPH_CSCOV(dh) (((dh)->dccph_ccval_cscov) & 0xF) #define DCCPH_X(dh) ((dh)->dccph_xtr & 1) #define DCCPH_TYPE(dh) (((dh)->dccph_xtr >> 1) & 0xF) /** * struct dccp_hdr_request - Conection initiation request header * * @dccph_req_service - Service to which the client app wants to connect */ struct dccp_hdr_request { uint32_t dccph_req_service; } UNALIGNED; /** * struct dccp_hdr_response - Conection 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 { uint8_t dccph_resp_ack[8]; /* always 8 bytes */ uint32_t dccph_resp_service; } UNALIGNED; /** * 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 { uint8_t dccph_reset_ack[8]; /* always 8 bytes */ uint8_t dccph_reset_code, dccph_reset_data[3]; } UNALIGNED; 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, - DCCP_PKT_INVALID + 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 tstr[] = "[|dccp]"; 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 inline u_int dccp_csum_coverage(const struct dccp_hdr* dh, u_int len) { u_int cov; if (DCCPH_CSCOV(dh) == 0) return len; cov = (dh->dccph_doff + DCCPH_CSCOV(dh) - 1) * sizeof(uint32_t); return (cov > len)? len : cov; } static int 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 *)(void *)dh, len, dccp_csum_coverage(dh, len), IPPROTO_DCCP); } #ifdef INET6 static int dccp6_cksum(const struct ip6_hdr *ip6, const struct dccp_hdr *dh, u_int len) { return nextproto6_cksum(ip6, (const uint8_t *)(void *)dh, len, dccp_csum_coverage(dh, len), IPPROTO_DCCP); } #endif 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(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 = EXTRACT_48BITS(dhx->dccph_seq); } else { seqno = EXTRACT_24BITS(dh->dccph_seq); } return seqno; } static inline unsigned int dccp_basic_hdr_len(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(dh); uint64_t ackno; if (DCCPH_X(dh) != 0) { ND_TCHECK2(*ackp, 8); ackno = EXTRACT_48BITS(ackp + 2); } else { ND_TCHECK2(*ackp, 4); ackno = EXTRACT_24BITS(ackp + 1); } ND_PRINT((ndo, "(ack=%" PRIu64 ") ", ackno)); trunc: return; } static 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 - lenght of ip packet */ void dccp_print(netdissect_options *ndo, const u_char *bp, const u_char *data2, - u_int len) + u_int len) { const struct dccp_hdr *dh; const struct ip *ip; #ifdef INET6 const struct ip6_hdr *ip6; #endif const u_char *cp; u_short sport, dport; u_int hlen; u_int fixed_hdrlen; + uint8_t dccph_type; dh = (const struct dccp_hdr *)bp; ip = (struct ip *)data2; #ifdef INET6 if (IP_V(ip) == 6) ip6 = (const struct ip6_hdr *)data2; else ip6 = NULL; #endif /*INET6*/ /* make sure we have enough data to look at the X bit */ cp = (const u_char *)(dh + 1); if (cp > ndo->ndo_snapend) { ND_PRINT((ndo, "[Invalid packet|dccp]")); return; } if (len < sizeof(struct dccp_hdr)) { ND_PRINT((ndo, "truncated-dccp - %u bytes missing!", - len - (u_int)sizeof(struct dccp_hdr))); + len - (u_int)sizeof(struct dccp_hdr))); return; } /* get the length of the generic header */ fixed_hdrlen = dccp_basic_hdr_len(dh); if (len < fixed_hdrlen) { ND_PRINT((ndo, "truncated-dccp - %u bytes missing!", - len - fixed_hdrlen)); + len - fixed_hdrlen)); return; } ND_TCHECK2(*dh, fixed_hdrlen); sport = EXTRACT_16BITS(&dh->dccph_sport); dport = EXTRACT_16BITS(&dh->dccph_dport); hlen = dh->dccph_doff * 4; #ifdef INET6 if (ip6) { ND_PRINT((ndo, "%s.%d > %s.%d: ", - ip6addr_string(ndo, &ip6->ip6_src), sport, - ip6addr_string(ndo, &ip6->ip6_dst), dport)); + ip6addr_string(ndo, &ip6->ip6_src), sport, + ip6addr_string(ndo, &ip6->ip6_dst), dport)); } else #endif /*INET6*/ { ND_PRINT((ndo, "%s.%d > %s.%d: ", - ipaddr_string(ndo, &ip->ip_src), sport, - ipaddr_string(ndo, &ip->ip_dst), dport)); + ipaddr_string(ndo, &ip->ip_src), sport, + ipaddr_string(ndo, &ip->ip_dst), dport)); } + ND_PRINT((ndo, "DCCP")); + if (ndo->ndo_qflag) { ND_PRINT((ndo, " %d", len - hlen)); if (hlen > len) { - ND_PRINT((ndo, "dccp [bad hdr length %u - too long, > %u]", - hlen, len)); + ND_PRINT((ndo, " [bad hdr length %u - too long, > %u]", + hlen, len)); } return; } /* other variables in generic header */ if (ndo->ndo_vflag) { - ND_PRINT((ndo, "CCVal %d, CsCov %d, ", DCCPH_CCVAL(dh), DCCPH_CSCOV(dh))); + ND_PRINT((ndo, " (CCVal %d, CsCov %d, ", DCCPH_CCVAL(dh), DCCPH_CSCOV(dh))); } /* checksum calculation */ if (ndo->ndo_vflag && ND_TTEST2(bp[0], len)) { uint16_t sum = 0, dccp_sum; dccp_sum = EXTRACT_16BITS(&dh->dccph_checksum); ND_PRINT((ndo, "cksum 0x%04x ", dccp_sum)); if (IP_V(ip) == 4) sum = dccp_cksum(ndo, ip, dh, len); #ifdef INET6 else if (IP_V(ip) == 6) sum = dccp6_cksum(ip6, dh, len); #endif if (sum != 0) - ND_PRINT((ndo, "(incorrect -> 0x%04x), ",in_cksum_shouldbe(dccp_sum, sum))); + ND_PRINT((ndo, "(incorrect -> 0x%04x)",in_cksum_shouldbe(dccp_sum, sum))); else - ND_PRINT((ndo, "(correct), ")); + ND_PRINT((ndo, "(correct)")); } - switch (DCCPH_TYPE(dh)) { + if (ndo->ndo_vflag) + ND_PRINT((ndo, ")")); + ND_PRINT((ndo, " ")); + + dccph_type = DCCPH_TYPE(dh); + switch (dccph_type) { case DCCP_PKT_REQUEST: { struct dccp_hdr_request *dhr = (struct dccp_hdr_request *)(bp + fixed_hdrlen); fixed_hdrlen += 4; if (len < fixed_hdrlen) { - ND_PRINT((ndo, "truncated-dccp request - %u bytes missing!", - len - fixed_hdrlen)); + ND_PRINT((ndo, "truncated-%s - %u bytes missing!", + tok2str(dccp_pkt_type_str, "", dccph_type), + len - fixed_hdrlen)); return; } ND_TCHECK(*dhr); - ND_PRINT((ndo, "request (service=%d) ", - EXTRACT_32BITS(&dhr->dccph_req_service))); + ND_PRINT((ndo, "%s (service=%d) ", + tok2str(dccp_pkt_type_str, "", dccph_type), + EXTRACT_32BITS(&dhr->dccph_req_service))); break; } case DCCP_PKT_RESPONSE: { struct dccp_hdr_response *dhr = (struct dccp_hdr_response *)(bp + fixed_hdrlen); fixed_hdrlen += 12; if (len < fixed_hdrlen) { - ND_PRINT((ndo, "truncated-dccp response - %u bytes missing!", - len - fixed_hdrlen)); + ND_PRINT((ndo, "truncated-%s - %u bytes missing!", + tok2str(dccp_pkt_type_str, "", dccph_type), + len - fixed_hdrlen)); return; } ND_TCHECK(*dhr); - ND_PRINT((ndo, "response (service=%d) ", - EXTRACT_32BITS(&dhr->dccph_resp_service))); + ND_PRINT((ndo, "%s (service=%d) ", + tok2str(dccp_pkt_type_str, "", dccph_type), + EXTRACT_32BITS(&dhr->dccph_resp_service))); break; } case DCCP_PKT_DATA: - ND_PRINT((ndo, "data ")); + ND_PRINT((ndo, "%s ", tok2str(dccp_pkt_type_str, "", dccph_type))); break; case DCCP_PKT_ACK: { fixed_hdrlen += 8; if (len < fixed_hdrlen) { - ND_PRINT((ndo, "truncated-dccp ack - %u bytes missing!", - len - fixed_hdrlen)); + ND_PRINT((ndo, "truncated-%s - %u bytes missing!", + tok2str(dccp_pkt_type_str, "", dccph_type), + len - fixed_hdrlen)); return; } - ND_PRINT((ndo, "ack ")); + ND_PRINT((ndo, "%s ", tok2str(dccp_pkt_type_str, "", dccph_type))); break; } case DCCP_PKT_DATAACK: { fixed_hdrlen += 8; if (len < fixed_hdrlen) { - ND_PRINT((ndo, "truncated-dccp dataack - %u bytes missing!", - len - fixed_hdrlen)); + ND_PRINT((ndo, "truncated-%s - %u bytes missing!", + tok2str(dccp_pkt_type_str, "", dccph_type), + len - fixed_hdrlen)); return; } - ND_PRINT((ndo, "dataack ")); + ND_PRINT((ndo, "%s ", tok2str(dccp_pkt_type_str, "", dccph_type))); break; } case DCCP_PKT_CLOSEREQ: fixed_hdrlen += 8; if (len < fixed_hdrlen) { - ND_PRINT((ndo, "truncated-dccp closereq - %u bytes missing!", - len - fixed_hdrlen)); + ND_PRINT((ndo, "truncated-%s - %u bytes missing!", + tok2str(dccp_pkt_type_str, "", dccph_type), + len - fixed_hdrlen)); return; } - ND_PRINT((ndo, "closereq ")); + ND_PRINT((ndo, "%s ", tok2str(dccp_pkt_type_str, "", dccph_type))); break; case DCCP_PKT_CLOSE: fixed_hdrlen += 8; if (len < fixed_hdrlen) { - ND_PRINT((ndo, "truncated-dccp close - %u bytes missing!", - len - fixed_hdrlen)); + ND_PRINT((ndo, "truncated-%s - %u bytes missing!", + tok2str(dccp_pkt_type_str, "", dccph_type), + len - fixed_hdrlen)); return; } - ND_PRINT((ndo, "close ")); + ND_PRINT((ndo, "%s ", tok2str(dccp_pkt_type_str, "", dccph_type))); break; case DCCP_PKT_RESET: { struct dccp_hdr_reset *dhr = (struct dccp_hdr_reset *)(bp + fixed_hdrlen); fixed_hdrlen += 12; if (len < fixed_hdrlen) { - ND_PRINT((ndo, "truncated-dccp reset - %u bytes missing!", - len - fixed_hdrlen)); + ND_PRINT((ndo, "truncated-%s - %u bytes missing!", + tok2str(dccp_pkt_type_str, "", dccph_type), + len - fixed_hdrlen)); return; } ND_TCHECK(*dhr); - ND_PRINT((ndo, "reset (code=%s) ", - dccp_reset_code(dhr->dccph_reset_code))); + ND_PRINT((ndo, "%s (code=%s) ", + tok2str(dccp_pkt_type_str, "", dccph_type), + dccp_reset_code(dhr->dccph_reset_code))); break; } case DCCP_PKT_SYNC: fixed_hdrlen += 8; if (len < fixed_hdrlen) { - ND_PRINT((ndo, "truncated-dccp sync - %u bytes missing!", - len - fixed_hdrlen)); + ND_PRINT((ndo, "truncated-%s - %u bytes missing!", + tok2str(dccp_pkt_type_str, "", dccph_type), + len - fixed_hdrlen)); return; } - ND_PRINT((ndo, "sync ")); + ND_PRINT((ndo, "%s ", tok2str(dccp_pkt_type_str, "", dccph_type))); break; case DCCP_PKT_SYNCACK: fixed_hdrlen += 8; if (len < fixed_hdrlen) { - ND_PRINT((ndo, "truncated-dccp syncack - %u bytes missing!", - len - fixed_hdrlen)); + ND_PRINT((ndo, "truncated-%s - %u bytes missing!", + tok2str(dccp_pkt_type_str, "", dccph_type), + len - fixed_hdrlen)); return; } - ND_PRINT((ndo, "syncack ")); + ND_PRINT((ndo, "%s ", tok2str(dccp_pkt_type_str, "", dccph_type))); break; default: - ND_PRINT((ndo, "invalid ")); + ND_PRINT((ndo, "%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((ndo, "seq %" PRIu64, dccp_seqno(bp))); /* process options */ if (hlen > fixed_hdrlen){ const u_char *cp; u_int optlen; cp = bp + fixed_hdrlen; ND_PRINT((ndo, " <")); 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((ndo, ", ")); } ND_PRINT((ndo, ">")); } return; trunc: ND_PRINT((ndo, "%s", tstr)); return; } 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 } + { 0, NULL } }; static int dccp_print_option(netdissect_options *ndo, const u_char *option, u_int hlen) { uint8_t optlen, i; ND_TCHECK(*option); if (*option >= 32) { ND_TCHECK(*(option+1)); optlen = *(option +1); if (optlen < 2) { if (*option >= 128) ND_PRINT((ndo, "CCID option %u optlen too short", *option)); else ND_PRINT((ndo, "%s optlen too short", - tok2str(dccp_option_values, "Option %u", *option))); + tok2str(dccp_option_values, "Option %u", *option))); return 0; } } else optlen = 1; if (hlen < optlen) { if (*option >= 128) ND_PRINT((ndo, "CCID option %u optlen goes past header length", - *option)); + *option)); else ND_PRINT((ndo, "%s optlen goes past header length", - tok2str(dccp_option_values, "Option %u", *option))); + tok2str(dccp_option_values, "Option %u", *option))); return 0; } ND_TCHECK2(*option, optlen); if (*option >= 128) { ND_PRINT((ndo, "CCID option %d", *option)); switch (optlen) { case 4: ND_PRINT((ndo, " %u", EXTRACT_16BITS(option + 2))); break; case 6: ND_PRINT((ndo, " %u", EXTRACT_32BITS(option + 2))); break; default: break; } } else { ND_PRINT((ndo, "%s", tok2str(dccp_option_values, "Option %u", *option))); switch (*option) { case 32: case 33: case 34: case 35: if (optlen < 3) { ND_PRINT((ndo, " optlen too short")); return optlen; } if (*(option + 2) < 10){ ND_PRINT((ndo, " %s", dccp_feature_nums[*(option + 2)])); for (i = 0; i < optlen - 3; i++) ND_PRINT((ndo, " %d", *(option + 3 + i))); } break; case 36: if (optlen > 2) { ND_PRINT((ndo, " 0x")); for (i = 0; i < optlen - 2; i++) ND_PRINT((ndo, "%02x", *(option + 2 + i))); } break; case 37: for (i = 0; i < optlen - 2; i++) ND_PRINT((ndo, " %d", *(option + 2 + i))); break; case 38: if (optlen > 2) { ND_PRINT((ndo, " 0x")); for (i = 0; i < optlen - 2; i++) ND_PRINT((ndo, "%02x", *(option + 2 + i))); } break; case 39: if (optlen > 2) { ND_PRINT((ndo, " 0x")); for (i = 0; i < optlen - 2; i++) ND_PRINT((ndo, "%02x", *(option + 2 + i))); } break; case 40: if (optlen > 2) { ND_PRINT((ndo, " 0x")); for (i = 0; i < optlen - 2; i++) ND_PRINT((ndo, "%02x", *(option + 2 + i))); } break; case 41: if (optlen == 4) ND_PRINT((ndo, " %u", EXTRACT_32BITS(option + 2))); else ND_PRINT((ndo, " optlen != 4")); break; case 42: if (optlen == 4) ND_PRINT((ndo, " %u", EXTRACT_32BITS(option + 2))); else ND_PRINT((ndo, " optlen != 4")); break; case 43: if (optlen == 6) ND_PRINT((ndo, " %u", EXTRACT_32BITS(option + 2))); else if (optlen == 4) ND_PRINT((ndo, " %u", EXTRACT_16BITS(option + 2))); else ND_PRINT((ndo, " optlen != 4 or 6")); break; case 44: if (optlen > 2) { ND_PRINT((ndo, " ")); for (i = 0; i < optlen - 2; i++) ND_PRINT((ndo, "%02x", *(option + 2 + i))); } break; } } return optlen; trunc: ND_PRINT((ndo, "%s", tstr)); return 0; } Index: head/contrib/tcpdump/print-decnet.c =================================================================== --- head/contrib/tcpdump/print-decnet.c (revision 285274) +++ head/contrib/tcpdump/print-decnet.c (revision 285275) @@ -1,1340 +1,1345 @@ /* * 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. */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include struct mbuf; struct rtentry; #ifdef HAVE_NETDNET_DNETDB_H #include #endif #include #include #include #include "extract.h" #include "interface.h" #include "addrtoname.h" static const char tstr[] = "[|decnet]"; #ifndef WIN32 typedef uint8_t byte[1]; /* single byte field */ #else /* * the keyword 'byte' generates conflicts in Windows */ typedef unsigned char Byte[1]; /* single byte field */ #define byte Byte #endif /* WIN32 */ typedef uint8_t word[2]; /* 2 byte field */ typedef uint8_t longword[4]; /* 4 bytes field */ /* * Definitions for DECNET Phase IV protocol headers */ union etheraddress { uint8_t dne_addr[6]; /* full ethernet address */ struct { uint8_t dne_hiord[4]; /* DECnet HIORD prefix */ uint8_t dne_nodeaddr[2]; /* DECnet node address */ } dne_remote; }; typedef union etheraddress 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 DN_MAXADDL 20 /* max size of DECnet address */ struct dn_naddr { uint16_t a_len; /* length of address */ uint8_t a_addr[DN_MAXADDL]; /* address as bytes */ }; /* * 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 initmsgIII /* phase III initialization message */ { byte inIII_flags; /* route flags */ word inIII_src; /* source node address */ byte inIII_info; /* routing layer information */ word inIII_blksize; /* maximum data link block size */ byte inIII_vers; /* version number */ byte inIII_eco; /* ECO number */ byte inIII_ueco; /* user ECO number */ byte inIII_rsvd; /* reserved image field */ }; 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_CRYPTSER 020 /* cryptographic services requested */ #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 *, int); static int print_l1_routes(netdissect_options *, const char *, u_int); static int print_l2_routes(netdissect_options *, const char *, u_int); static void print_i_info(netdissect_options *, int); static int print_elist(const char *, u_int); static int print_nsp(netdissect_options *, const u_char *, u_int); static void print_reason(netdissect_options *, int); #ifdef PRINT_NSPDATA static void pdata(netdissect_options *, u_char *, u_int); #endif #ifndef HAVE_NETDNET_DNETDB_H_DNET_HTOA extern char *dnet_htoa(struct dn_naddr *); #endif void decnet_print(netdissect_options *ndo, register const u_char *ap, register u_int length, register u_int caplen) { register const union routehdr *rhp; register int mflags; int dst, src, hops; u_int nsplen, pktlen; const u_char *nspp; if (length < sizeof(struct shorthdr)) { ND_PRINT((ndo, "%s", tstr)); return; } ND_TCHECK2(*ap, sizeof(short)); pktlen = EXTRACT_LE_16BITS(ap); if (pktlen < sizeof(struct shorthdr)) { ND_PRINT((ndo, "%s", tstr)); return; } if (pktlen > length) { ND_PRINT((ndo, "%s", tstr)); return; } length = pktlen; rhp = (const union routehdr *)&(ap[sizeof(short)]); ND_TCHECK(rhp->rh_short.sh_flags); mflags = EXTRACT_LE_8BITS(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((ndo, "[pad:%d] ", padlen)); if (length < padlen + 2) { ND_PRINT((ndo, "%s", tstr)); return; } ND_TCHECK2(ap[sizeof(short)], padlen); ap += padlen; length -= padlen; caplen -= padlen; rhp = (const union routehdr *)&(ap[sizeof(short)]); mflags = EXTRACT_LE_8BITS(rhp->rh_short.sh_flags); } if (mflags & RMF_FVER) { ND_PRINT((ndo, "future-version-decnet")); ND_DEFAULTPRINT(ap, min(length, caplen)); return; } /* is it a control message? */ if (mflags & RMF_CTLMSG) { if (!print_decnet_ctlmsg(ndo, rhp, length, caplen)) goto trunc; return; } switch (mflags & RMF_MASK) { case RMF_LONG: if (length < sizeof(struct longhdr)) { ND_PRINT((ndo, "%s", tstr)); return; } ND_TCHECK(rhp->rh_long); dst = EXTRACT_LE_16BITS(rhp->rh_long.lg_dst.dne_remote.dne_nodeaddr); src = EXTRACT_LE_16BITS(rhp->rh_long.lg_src.dne_remote.dne_nodeaddr); hops = EXTRACT_LE_8BITS(rhp->rh_long.lg_visits); nspp = &(ap[sizeof(short) + sizeof(struct longhdr)]); nsplen = length - sizeof(struct longhdr); break; case RMF_SHORT: ND_TCHECK(rhp->rh_short); dst = EXTRACT_LE_16BITS(rhp->rh_short.sh_dst); src = EXTRACT_LE_16BITS(rhp->rh_short.sh_src); hops = (EXTRACT_LE_8BITS(rhp->rh_short.sh_visits) & VIS_MASK)+1; nspp = &(ap[sizeof(short) + sizeof(struct shorthdr)]); nsplen = length - sizeof(struct shorthdr); break; default: ND_PRINT((ndo, "unknown message flags under mask")); ND_DEFAULTPRINT((u_char *)ap, min(length, caplen)); return; } ND_PRINT((ndo, "%s > %s %d ", dnaddr_string(ndo, src), dnaddr_string(ndo, dst), pktlen)); if (ndo->ndo_vflag) { if (mflags & RMF_RQR) ND_PRINT((ndo, "RQR ")); if (mflags & RMF_RTS) ND_PRINT((ndo, "RTS ")); if (mflags & RMF_IE) ND_PRINT((ndo, "IE ")); ND_PRINT((ndo, "%d hops ", hops)); } if (!print_nsp(ndo, nspp, nsplen)) goto trunc; return; trunc: ND_PRINT((ndo, "%s", tstr)); return; } static int print_decnet_ctlmsg(netdissect_options *ndo, register const union routehdr *rhp, u_int length, u_int caplen) { int mflags = EXTRACT_LE_8BITS(rhp->rh_short.sh_flags); register union controlmsg *cmp = (union controlmsg *)rhp; int src, dst, info, blksize, eco, ueco, hello, other, vers; etheraddr srcea, rtea; int priority; char *rhpx = (char *)rhp; int ret; switch (mflags & RMF_CTLMASK) { case RMF_INIT: ND_PRINT((ndo, "init ")); if (length < sizeof(struct initmsg)) goto trunc; ND_TCHECK(cmp->cm_init); src = EXTRACT_LE_16BITS(cmp->cm_init.in_src); info = EXTRACT_LE_8BITS(cmp->cm_init.in_info); blksize = EXTRACT_LE_16BITS(cmp->cm_init.in_blksize); vers = EXTRACT_LE_8BITS(cmp->cm_init.in_vers); eco = EXTRACT_LE_8BITS(cmp->cm_init.in_eco); ueco = EXTRACT_LE_8BITS(cmp->cm_init.in_ueco); hello = EXTRACT_LE_16BITS(cmp->cm_init.in_hello); print_t_info(ndo, info); ND_PRINT((ndo, "src %sblksize %d vers %d eco %d ueco %d hello %d", dnaddr_string(ndo, src), blksize, vers, eco, ueco, hello)); ret = 1; break; case RMF_VER: ND_PRINT((ndo, "verification ")); if (length < sizeof(struct verifmsg)) goto trunc; ND_TCHECK(cmp->cm_ver); src = EXTRACT_LE_16BITS(cmp->cm_ver.ve_src); other = EXTRACT_LE_8BITS(cmp->cm_ver.ve_fcnval); ND_PRINT((ndo, "src %s fcnval %o", dnaddr_string(ndo, src), other)); ret = 1; break; case RMF_TEST: ND_PRINT((ndo, "test ")); if (length < sizeof(struct testmsg)) goto trunc; ND_TCHECK(cmp->cm_test); src = EXTRACT_LE_16BITS(cmp->cm_test.te_src); other = EXTRACT_LE_8BITS(cmp->cm_test.te_data); ND_PRINT((ndo, "src %s data %o", dnaddr_string(ndo, src), other)); ret = 1; break; case RMF_L1ROUT: ND_PRINT((ndo, "lev-1-routing ")); if (length < sizeof(struct l1rout)) goto trunc; ND_TCHECK(cmp->cm_l1rou); src = EXTRACT_LE_16BITS(cmp->cm_l1rou.r1_src); ND_PRINT((ndo, "src %s ", dnaddr_string(ndo, src))); ret = print_l1_routes(ndo, &(rhpx[sizeof(struct l1rout)]), length - sizeof(struct l1rout)); break; case RMF_L2ROUT: ND_PRINT((ndo, "lev-2-routing ")); if (length < sizeof(struct l2rout)) goto trunc; ND_TCHECK(cmp->cm_l2rout); src = EXTRACT_LE_16BITS(cmp->cm_l2rout.r2_src); ND_PRINT((ndo, "src %s ", dnaddr_string(ndo, src))); ret = print_l2_routes(ndo, &(rhpx[sizeof(struct l2rout)]), length - sizeof(struct l2rout)); break; case RMF_RHELLO: ND_PRINT((ndo, "router-hello ")); if (length < sizeof(struct rhellomsg)) goto trunc; ND_TCHECK(cmp->cm_rhello); vers = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_vers); eco = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_eco); ueco = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_ueco); memcpy((char *)&srcea, (char *)&(cmp->cm_rhello.rh_src), sizeof(srcea)); src = EXTRACT_LE_16BITS(srcea.dne_remote.dne_nodeaddr); info = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_info); blksize = EXTRACT_LE_16BITS(cmp->cm_rhello.rh_blksize); priority = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_priority); hello = EXTRACT_LE_16BITS(cmp->cm_rhello.rh_hello); print_i_info(ndo, info); ND_PRINT((ndo, "vers %d eco %d ueco %d src %s blksize %d pri %d hello %d", vers, eco, ueco, dnaddr_string(ndo, src), blksize, priority, hello)); ret = print_elist(&(rhpx[sizeof(struct rhellomsg)]), length - sizeof(struct rhellomsg)); break; case RMF_EHELLO: ND_PRINT((ndo, "endnode-hello ")); if (length < sizeof(struct ehellomsg)) goto trunc; ND_TCHECK(cmp->cm_ehello); vers = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_vers); eco = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_eco); ueco = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_ueco); memcpy((char *)&srcea, (char *)&(cmp->cm_ehello.eh_src), sizeof(srcea)); src = EXTRACT_LE_16BITS(srcea.dne_remote.dne_nodeaddr); info = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_info); blksize = EXTRACT_LE_16BITS(cmp->cm_ehello.eh_blksize); /*seed*/ memcpy((char *)&rtea, (char *)&(cmp->cm_ehello.eh_router), sizeof(rtea)); dst = EXTRACT_LE_16BITS(rtea.dne_remote.dne_nodeaddr); hello = EXTRACT_LE_16BITS(cmp->cm_ehello.eh_hello); other = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_data); print_i_info(ndo, info); ND_PRINT((ndo, "vers %d eco %d ueco %d src %s blksize %d rtr %s hello %d data %o", vers, eco, ueco, dnaddr_string(ndo, src), blksize, dnaddr_string(ndo, dst), hello, other)); ret = 1; break; default: ND_PRINT((ndo, "unknown control message")); ND_DEFAULTPRINT((u_char *)rhp, min(length, caplen)); ret = 1; break; } return (ret); trunc: return (0); } static void print_t_info(netdissect_options *ndo, int info) { int ntype = info & 3; switch (ntype) { case 0: ND_PRINT((ndo, "reserved-ntype? ")); break; case TI_L2ROUT: ND_PRINT((ndo, "l2rout ")); break; case TI_L1ROUT: ND_PRINT((ndo, "l1rout ")); break; case TI_ENDNODE: ND_PRINT((ndo, "endnode ")); break; } if (info & TI_VERIF) ND_PRINT((ndo, "verif ")); if (info & TI_BLOCK) ND_PRINT((ndo, "blo ")); } static int print_l1_routes(netdissect_options *ndo, const char *rp, u_int len) { int count; int id; int info; /* The last short is a checksum */ while (len > (3 * sizeof(short))) { ND_TCHECK2(*rp, 3 * sizeof(short)); count = EXTRACT_LE_16BITS(rp); if (count > 1024) return (1); /* seems to be bogus from here on */ rp += sizeof(short); len -= sizeof(short); id = EXTRACT_LE_16BITS(rp); rp += sizeof(short); len -= sizeof(short); info = EXTRACT_LE_16BITS(rp); rp += sizeof(short); len -= sizeof(short); ND_PRINT((ndo, "{ids %d-%d cost %d hops %d} ", id, id + count, RI_COST(info), RI_HOPS(info))); } return (1); trunc: return (0); } static int print_l2_routes(netdissect_options *ndo, const char *rp, u_int len) { int count; int area; int info; /* The last short is a checksum */ while (len > (3 * sizeof(short))) { ND_TCHECK2(*rp, 3 * sizeof(short)); count = EXTRACT_LE_16BITS(rp); if (count > 1024) return (1); /* seems to be bogus from here on */ rp += sizeof(short); len -= sizeof(short); area = EXTRACT_LE_16BITS(rp); rp += sizeof(short); len -= sizeof(short); info = EXTRACT_LE_16BITS(rp); rp += sizeof(short); len -= sizeof(short); ND_PRINT((ndo, "{areas %d-%d cost %d hops %d} ", area, area + count, RI_COST(info), RI_HOPS(info))); } return (1); trunc: return (0); } static void print_i_info(netdissect_options *ndo, int info) { int ntype = info & II_TYPEMASK; switch (ntype) { case 0: ND_PRINT((ndo, "reserved-ntype? ")); break; case II_L2ROUT: ND_PRINT((ndo, "l2rout ")); break; case II_L1ROUT: ND_PRINT((ndo, "l1rout ")); break; case II_ENDNODE: ND_PRINT((ndo, "endnode ")); break; } if (info & II_VERIF) ND_PRINT((ndo, "verif ")); if (info & II_NOMCAST) ND_PRINT((ndo, "nomcast ")); if (info & II_BLOCK) ND_PRINT((ndo, "blo ")); } static int print_elist(const char *elp _U_, u_int len _U_) { /* Not enough examples available for me to debug this */ return (1); } static int print_nsp(netdissect_options *ndo, const u_char *nspp, u_int nsplen) { const struct nsphdr *nsphp = (struct nsphdr *)nspp; int dst, src, flags; if (nsplen < sizeof(struct nsphdr)) goto trunc; ND_TCHECK(*nsphp); flags = EXTRACT_LE_8BITS(nsphp->nh_flags); dst = EXTRACT_LE_16BITS(nsphp->nh_dst); src = EXTRACT_LE_16BITS(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((ndo, "data %d>%d ", src, dst)); { struct seghdr *shp = (struct seghdr *)nspp; int ack; #ifdef PRINT_NSPDATA u_char *dp; #endif u_int data_off = sizeof(struct minseghdr); if (nsplen < data_off) goto trunc; ND_TCHECK(shp->sh_seq[0]); ack = EXTRACT_LE_16BITS(shp->sh_seq[0]); if (ack & SGQ_ACK) { /* acknum field */ if ((ack & SGQ_NAK) == SGQ_NAK) ND_PRINT((ndo, "nak %d ", ack & SGQ_MASK)); else ND_PRINT((ndo, "ack %d ", ack & SGQ_MASK)); data_off += sizeof(short); if (nsplen < data_off) goto trunc; ND_TCHECK(shp->sh_seq[1]); ack = EXTRACT_LE_16BITS(shp->sh_seq[1]); if (ack & SGQ_OACK) { /* ackoth field */ if ((ack & SGQ_ONAK) == SGQ_ONAK) ND_PRINT((ndo, "onak %d ", ack & SGQ_MASK)); else ND_PRINT((ndo, "oack %d ", ack & SGQ_MASK)); data_off += sizeof(short); if (nsplen < data_off) goto trunc; ND_TCHECK(shp->sh_seq[2]); ack = EXTRACT_LE_16BITS(shp->sh_seq[2]); } } ND_PRINT((ndo, "seg %d ", ack & SGQ_MASK)); #ifdef PRINT_NSPDATA if (nsplen > data_off) { dp = &(nspp[data_off]); ND_TCHECK2(*dp, nsplen - data_off); pdata(ndo, dp, nsplen - data_off); } #endif } break; case MFS_ILS+MFS_INT: ND_PRINT((ndo, "intr ")); { struct seghdr *shp = (struct seghdr *)nspp; int ack; #ifdef PRINT_NSPDATA u_char *dp; #endif u_int data_off = sizeof(struct minseghdr); if (nsplen < data_off) goto trunc; ND_TCHECK(shp->sh_seq[0]); ack = EXTRACT_LE_16BITS(shp->sh_seq[0]); if (ack & SGQ_ACK) { /* acknum field */ if ((ack & SGQ_NAK) == SGQ_NAK) ND_PRINT((ndo, "nak %d ", ack & SGQ_MASK)); else ND_PRINT((ndo, "ack %d ", ack & SGQ_MASK)); data_off += sizeof(short); if (nsplen < data_off) goto trunc; ND_TCHECK(shp->sh_seq[1]); ack = EXTRACT_LE_16BITS(shp->sh_seq[1]); if (ack & SGQ_OACK) { /* ackdat field */ if ((ack & SGQ_ONAK) == SGQ_ONAK) ND_PRINT((ndo, "nakdat %d ", ack & SGQ_MASK)); else ND_PRINT((ndo, "ackdat %d ", ack & SGQ_MASK)); data_off += sizeof(short); if (nsplen < data_off) goto trunc; ND_TCHECK(shp->sh_seq[2]); ack = EXTRACT_LE_16BITS(shp->sh_seq[2]); } } ND_PRINT((ndo, "seg %d ", ack & SGQ_MASK)); #ifdef PRINT_NSPDATA if (nsplen > data_off) { dp = &(nspp[data_off]); ND_TCHECK2(*dp, nsplen - data_off); pdata(ndo, dp, nsplen - data_off); } #endif } break; case MFS_ILS: ND_PRINT((ndo, "link-service %d>%d ", src, dst)); { struct seghdr *shp = (struct seghdr *)nspp; struct lsmsg *lsmp = (struct lsmsg *)&(nspp[sizeof(struct seghdr)]); int ack; int lsflags, fcval; if (nsplen < sizeof(struct seghdr) + sizeof(struct lsmsg)) goto trunc; ND_TCHECK(shp->sh_seq[0]); ack = EXTRACT_LE_16BITS(shp->sh_seq[0]); if (ack & SGQ_ACK) { /* acknum field */ if ((ack & SGQ_NAK) == SGQ_NAK) ND_PRINT((ndo, "nak %d ", ack & SGQ_MASK)); else ND_PRINT((ndo, "ack %d ", ack & SGQ_MASK)); ND_TCHECK(shp->sh_seq[1]); ack = EXTRACT_LE_16BITS(shp->sh_seq[1]); if (ack & SGQ_OACK) { /* ackdat field */ if ((ack & SGQ_ONAK) == SGQ_ONAK) ND_PRINT((ndo, "nakdat %d ", ack & SGQ_MASK)); else ND_PRINT((ndo, "ackdat %d ", ack & SGQ_MASK)); ND_TCHECK(shp->sh_seq[2]); ack = EXTRACT_LE_16BITS(shp->sh_seq[2]); } } ND_PRINT((ndo, "seg %d ", ack & SGQ_MASK)); ND_TCHECK(*lsmp); lsflags = EXTRACT_LE_8BITS(lsmp->ls_lsflags); fcval = EXTRACT_LE_8BITS(lsmp->ls_fcval); switch (lsflags & LSI_MASK) { case LSI_DATA: ND_PRINT((ndo, "dat seg count %d ", fcval)); switch (lsflags & LSM_MASK) { case LSM_NOCHANGE: break; case LSM_DONOTSEND: ND_PRINT((ndo, "donotsend-data ")); break; case LSM_SEND: ND_PRINT((ndo, "send-data ")); break; default: ND_PRINT((ndo, "reserved-fcmod? %x", lsflags)); break; } break; case LSI_INTR: ND_PRINT((ndo, "intr req count %d ", fcval)); break; default: ND_PRINT((ndo, "reserved-fcval-int? %x", lsflags)); break; } } break; default: ND_PRINT((ndo, "reserved-subtype? %x %d > %d", flags, src, dst)); break; } break; case MFT_ACK: switch (flags & NSP_SUBMASK) { case MFS_DACK: ND_PRINT((ndo, "data-ack %d>%d ", src, dst)); { struct ackmsg *amp = (struct ackmsg *)nspp; int ack; if (nsplen < sizeof(struct ackmsg)) goto trunc; ND_TCHECK(*amp); ack = EXTRACT_LE_16BITS(amp->ak_acknum[0]); if (ack & SGQ_ACK) { /* acknum field */ if ((ack & SGQ_NAK) == SGQ_NAK) ND_PRINT((ndo, "nak %d ", ack & SGQ_MASK)); else ND_PRINT((ndo, "ack %d ", ack & SGQ_MASK)); ack = EXTRACT_LE_16BITS(amp->ak_acknum[1]); if (ack & SGQ_OACK) { /* ackoth field */ if ((ack & SGQ_ONAK) == SGQ_ONAK) ND_PRINT((ndo, "onak %d ", ack & SGQ_MASK)); else ND_PRINT((ndo, "oack %d ", ack & SGQ_MASK)); } } } break; case MFS_IACK: ND_PRINT((ndo, "ils-ack %d>%d ", src, dst)); { struct ackmsg *amp = (struct ackmsg *)nspp; int ack; if (nsplen < sizeof(struct ackmsg)) goto trunc; ND_TCHECK(*amp); ack = EXTRACT_LE_16BITS(amp->ak_acknum[0]); if (ack & SGQ_ACK) { /* acknum field */ if ((ack & SGQ_NAK) == SGQ_NAK) ND_PRINT((ndo, "nak %d ", ack & SGQ_MASK)); else ND_PRINT((ndo, "ack %d ", ack & SGQ_MASK)); ND_TCHECK(amp->ak_acknum[1]); ack = EXTRACT_LE_16BITS(amp->ak_acknum[1]); if (ack & SGQ_OACK) { /* ackdat field */ if ((ack & SGQ_ONAK) == SGQ_ONAK) ND_PRINT((ndo, "nakdat %d ", ack & SGQ_MASK)); else ND_PRINT((ndo, "ackdat %d ", ack & SGQ_MASK)); } } } break; case MFS_CACK: ND_PRINT((ndo, "conn-ack %d", dst)); break; default: ND_PRINT((ndo, "reserved-acktype? %x %d > %d", 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((ndo, "conn-initiate ")); else ND_PRINT((ndo, "retrans-conn-initiate ")); ND_PRINT((ndo, "%d>%d ", src, dst)); { struct cimsg *cimp = (struct cimsg *)nspp; int services, info, segsize; #ifdef PRINT_NSPDATA u_char *dp; #endif if (nsplen < sizeof(struct cimsg)) goto trunc; ND_TCHECK(*cimp); services = EXTRACT_LE_8BITS(cimp->ci_services); info = EXTRACT_LE_8BITS(cimp->ci_info); segsize = EXTRACT_LE_16BITS(cimp->ci_segsize); switch (services & COS_MASK) { case COS_NONE: break; case COS_SEGMENT: ND_PRINT((ndo, "seg ")); break; case COS_MESSAGE: ND_PRINT((ndo, "msg ")); break; case COS_CRYPTSER: ND_PRINT((ndo, "crypt ")); break; } switch (info & COI_MASK) { case COI_32: ND_PRINT((ndo, "ver 3.2 ")); break; case COI_31: ND_PRINT((ndo, "ver 3.1 ")); break; case COI_40: ND_PRINT((ndo, "ver 4.0 ")); break; case COI_41: ND_PRINT((ndo, "ver 4.1 ")); break; } ND_PRINT((ndo, "segsize %d ", segsize)); #ifdef PRINT_NSPDATA if (nsplen > sizeof(struct cimsg)) { dp = &(nspp[sizeof(struct cimsg)]); ND_TCHECK2(*dp, nsplen - sizeof(struct cimsg)); pdata(ndo, dp, nsplen - sizeof(struct cimsg)); } #endif } break; case MFS_CC: ND_PRINT((ndo, "conn-confirm %d>%d ", src, dst)); { struct ccmsg *ccmp = (struct ccmsg *)nspp; int services, info; u_int segsize, optlen; #ifdef PRINT_NSPDATA u_char *dp; #endif if (nsplen < sizeof(struct ccmsg)) goto trunc; ND_TCHECK(*ccmp); services = EXTRACT_LE_8BITS(ccmp->cc_services); info = EXTRACT_LE_8BITS(ccmp->cc_info); segsize = EXTRACT_LE_16BITS(ccmp->cc_segsize); optlen = EXTRACT_LE_8BITS(ccmp->cc_optlen); switch (services & COS_MASK) { case COS_NONE: break; case COS_SEGMENT: ND_PRINT((ndo, "seg ")); break; case COS_MESSAGE: ND_PRINT((ndo, "msg ")); break; case COS_CRYPTSER: ND_PRINT((ndo, "crypt ")); break; } switch (info & COI_MASK) { case COI_32: ND_PRINT((ndo, "ver 3.2 ")); break; case COI_31: ND_PRINT((ndo, "ver 3.1 ")); break; case COI_40: ND_PRINT((ndo, "ver 4.0 ")); break; case COI_41: ND_PRINT((ndo, "ver 4.1 ")); break; } ND_PRINT((ndo, "segsize %d ", segsize)); if (optlen) { ND_PRINT((ndo, "optlen %d ", optlen)); #ifdef PRINT_NSPDATA if (optlen > nsplen - sizeof(struct ccmsg)) goto trunc; dp = &(nspp[sizeof(struct ccmsg)]); ND_TCHECK2(*dp, optlen); pdata(ndo, dp, optlen); #endif } } break; case MFS_DI: ND_PRINT((ndo, "disconn-initiate %d>%d ", src, dst)); { struct dimsg *dimp = (struct dimsg *)nspp; int reason; u_int optlen; #ifdef PRINT_NSPDATA u_char *dp; #endif if (nsplen < sizeof(struct dimsg)) goto trunc; ND_TCHECK(*dimp); reason = EXTRACT_LE_16BITS(dimp->di_reason); optlen = EXTRACT_LE_8BITS(dimp->di_optlen); print_reason(ndo, reason); if (optlen) { ND_PRINT((ndo, "optlen %d ", optlen)); #ifdef PRINT_NSPDATA if (optlen > nsplen - sizeof(struct dimsg)) goto trunc; dp = &(nspp[sizeof(struct dimsg)]); ND_TCHECK2(*dp, optlen); pdata(ndo, dp, optlen); #endif } } break; case MFS_DC: ND_PRINT((ndo, "disconn-confirm %d>%d ", src, dst)); { struct dcmsg *dcmp = (struct dcmsg *)nspp; int reason; ND_TCHECK(*dcmp); reason = EXTRACT_LE_16BITS(dcmp->dc_reason); print_reason(ndo, reason); } break; default: ND_PRINT((ndo, "reserved-ctltype? %x %d > %d", flags, src, dst)); break; } break; default: ND_PRINT((ndo, "reserved-type? %x %d > %d", flags, src, dst)); break; } return (1); trunc: 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, register int reason) { ND_PRINT((ndo, "%s ", tok2str(reason2str, "reason-%d", reason))); } const char * dnnum_string(u_short dnaddr) { char *str; size_t siz; int area = (u_short)(dnaddr & AREAMASK) >> AREASHIFT; int node = dnaddr & NODEMASK; str = (char *)malloc(siz = sizeof("00.0000")); if (str == NULL) error("dnnum_string: malloc"); snprintf(str, siz, "%d.%d", area, node); return(str); } const char * dnname_string(u_short dnaddr) { #ifdef HAVE_DNET_HTOA struct dn_naddr dna; + char *dnname; dna.a_len = sizeof(short); memcpy((char *)dna.a_addr, (char *)&dnaddr, sizeof(short)); - return (strdup(dnet_htoa(&dna))); + dnname = dnet_htoa(&dna); + if(dnname != NULL) + return (strdup(dnname)); + else + return(dnnum_string(dnaddr)); #else return(dnnum_string(dnaddr)); /* punt */ #endif } #ifdef PRINT_NSPDATA static void pdata(netdissect_options *ndo, u_char *dp, u_int maxlen) { char c; u_int x = maxlen; while (x-- > 0) { c = *dp++; safeputchar(ndo, c); } } #endif Index: head/contrib/tcpdump/print-eigrp.c =================================================================== --- head/contrib/tcpdump/print-eigrp.c (revision 285274) +++ head/contrib/tcpdump/print-eigrp.c (revision 285275) @@ -1,474 +1,474 @@ /* * Copyright (c) 1998-2004 Hannes Gredler * 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. */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "interface.h" #include "extract.h" #include "addrtoname.h" /* * packet format documented at * http://www.rhyshaden.com/eigrp.htm */ struct eigrp_common_header { uint8_t version; uint8_t opcode; uint8_t checksum[2]; uint8_t flags[4]; uint8_t seq[4]; uint8_t ack[4]; uint8_t asn[4]; }; #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" }, { 0, NULL} }; struct eigrp_tlv_header { uint8_t type[2]; uint8_t length[2]; }; #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 { uint8_t k1; uint8_t k2; uint8_t k3; uint8_t k4; uint8_t k5; uint8_t res; uint8_t holdtime[2]; }; struct eigrp_tlv_sw_version_t { uint8_t ios_major; uint8_t ios_minor; uint8_t eigrp_major; uint8_t eigrp_minor; }; struct eigrp_tlv_ip_int_t { uint8_t nexthop[4]; uint8_t delay[4]; uint8_t bandwidth[4]; uint8_t mtu[3]; uint8_t hopcount; uint8_t reliability; uint8_t load; uint8_t reserved[2]; uint8_t plen; uint8_t destination; /* variable length [1-4] bytes encoding */ }; struct eigrp_tlv_ip_ext_t { uint8_t nexthop[4]; uint8_t origin_router[4]; uint8_t origin_as[4]; uint8_t tag[4]; uint8_t metric[4]; uint8_t reserved[2]; uint8_t proto_id; uint8_t flags; uint8_t delay[4]; uint8_t bandwidth[4]; uint8_t mtu[3]; uint8_t hopcount; uint8_t reliability; uint8_t load; uint8_t reserved2[2]; uint8_t plen; uint8_t destination; /* variable length [1-4] bytes encoding */ }; struct eigrp_tlv_at_cable_setup_t { uint8_t cable_start[2]; uint8_t cable_end[2]; uint8_t router_id[4]; }; struct eigrp_tlv_at_int_t { uint8_t nexthop[4]; uint8_t delay[4]; uint8_t bandwidth[4]; uint8_t mtu[3]; uint8_t hopcount; uint8_t reliability; uint8_t load; uint8_t reserved[2]; uint8_t cable_start[2]; uint8_t cable_end[2]; }; struct eigrp_tlv_at_ext_t { uint8_t nexthop[4]; uint8_t origin_router[4]; uint8_t origin_as[4]; uint8_t tag[4]; uint8_t proto_id; uint8_t flags; uint8_t metric[2]; uint8_t delay[4]; uint8_t bandwidth[4]; uint8_t mtu[3]; uint8_t hopcount; uint8_t reliability; uint8_t load; uint8_t reserved2[2]; uint8_t cable_start[2]; uint8_t cable_end[2]; }; 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, register const u_char *pptr, register u_int len) { - +eigrp_print(netdissect_options *ndo, register const u_char *pptr, register 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; tptr=pptr; eigrp_com_header = (const struct eigrp_common_header *)pptr; ND_TCHECK(*eigrp_com_header); /* * Sanity checking of the header. */ if (eigrp_com_header->version != EIGRP_VERSION) { ND_PRINT((ndo, "EIGRP version %u packet not supported",eigrp_com_header->version)); return; } /* in non-verbose mode just lets print the basic Message Type*/ if (ndo->ndo_vflag < 1) { ND_PRINT((ndo, "EIGRP %s, length: %u", tok2str(eigrp_opcode_values, "unknown (%u)",eigrp_com_header->opcode), len)); return; } /* ok they seem to want to know everything - lets fully decode it */ tlen=len-sizeof(struct eigrp_common_header); /* FIXME print other header info */ ND_PRINT((ndo, "\n\tEIGRP v%u, opcode: %s (%u), chksum: 0x%04x, Flags: [%s]\n\tseq: 0x%08x, ack: 0x%08x, AS: %u, length: %u", eigrp_com_header->version, tok2str(eigrp_opcode_values, "unknown, type: %u",eigrp_com_header->opcode), eigrp_com_header->opcode, EXTRACT_16BITS(&eigrp_com_header->checksum), tok2str(eigrp_common_header_flag_values, "none", EXTRACT_32BITS(&eigrp_com_header->flags)), EXTRACT_32BITS(&eigrp_com_header->seq), EXTRACT_32BITS(&eigrp_com_header->ack), EXTRACT_32BITS(&eigrp_com_header->asn), tlen)); tptr+=sizeof(const struct eigrp_common_header); while(tlen>0) { /* did we capture enough for fully decoding the object header ? */ ND_TCHECK2(*tptr, sizeof(struct eigrp_tlv_header)); eigrp_tlv_header = (const struct eigrp_tlv_header *)tptr; eigrp_tlv_len=EXTRACT_16BITS(&eigrp_tlv_header->length); eigrp_tlv_type=EXTRACT_16BITS(&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((ndo, "\n\t %s TLV (0x%04x), length: %u", tok2str(eigrp_tlv_values, "Unknown", eigrp_tlv_type), eigrp_tlv_type, eigrp_tlv_len)); 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_TCHECK2(*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; ND_PRINT((ndo, "\n\t holdtime: %us, k1 %u, k2 %u, k3 %u, k4 %u, k5 %u", EXTRACT_16BITS(tlv_ptr.eigrp_tlv_general_parm->holdtime), tlv_ptr.eigrp_tlv_general_parm->k1, tlv_ptr.eigrp_tlv_general_parm->k2, tlv_ptr.eigrp_tlv_general_parm->k3, tlv_ptr.eigrp_tlv_general_parm->k4, 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; ND_PRINT((ndo, "\n\t IOS version: %u.%u, EIGRP version %u.%u", tlv_ptr.eigrp_tlv_sw_version->ios_major, tlv_ptr.eigrp_tlv_sw_version->ios_minor, tlv_ptr.eigrp_tlv_sw_version->eigrp_major, 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; bit_length = tlv_ptr.eigrp_tlv_ip_int->plen; if (bit_length > 32) { ND_PRINT((ndo, "\n\t illegal prefix length %u",bit_length)); break; } byte_length = (bit_length + 7) / 8; /* variable length encoding */ memset(prefix, 0, 4); memcpy(prefix,&tlv_ptr.eigrp_tlv_ip_int->destination,byte_length); ND_PRINT((ndo, "\n\t IPv4 prefix: %15s/%u, nexthop: ", ipaddr_string(ndo, prefix), bit_length)); if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_int->nexthop) == 0) ND_PRINT((ndo, "self")); else ND_PRINT((ndo, "%s",ipaddr_string(ndo, &tlv_ptr.eigrp_tlv_ip_int->nexthop))); ND_PRINT((ndo, "\n\t delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u", (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_int->delay)/100), EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_int->bandwidth), EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_ip_int->mtu), tlv_ptr.eigrp_tlv_ip_int->hopcount, tlv_ptr.eigrp_tlv_ip_int->reliability, 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; bit_length = tlv_ptr.eigrp_tlv_ip_ext->plen; if (bit_length > 32) { ND_PRINT((ndo, "\n\t illegal prefix length %u",bit_length)); break; } byte_length = (bit_length + 7) / 8; /* variable length encoding */ memset(prefix, 0, 4); memcpy(prefix,&tlv_ptr.eigrp_tlv_ip_ext->destination,byte_length); ND_PRINT((ndo, "\n\t IPv4 prefix: %15s/%u, nexthop: ", ipaddr_string(ndo, prefix), bit_length)); if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_ext->nexthop) == 0) ND_PRINT((ndo, "self")); else ND_PRINT((ndo, "%s",ipaddr_string(ndo, &tlv_ptr.eigrp_tlv_ip_ext->nexthop))); ND_PRINT((ndo, "\n\t origin-router %s, origin-as %u, origin-proto %s, flags [0x%02x], tag 0x%08x, metric %u", ipaddr_string(ndo, tlv_ptr.eigrp_tlv_ip_ext->origin_router), EXTRACT_32BITS(tlv_ptr.eigrp_tlv_ip_ext->origin_as), tok2str(eigrp_ext_proto_id_values,"unknown",tlv_ptr.eigrp_tlv_ip_ext->proto_id), tlv_ptr.eigrp_tlv_ip_ext->flags, EXTRACT_32BITS(tlv_ptr.eigrp_tlv_ip_ext->tag), EXTRACT_32BITS(tlv_ptr.eigrp_tlv_ip_ext->metric))); ND_PRINT((ndo, "\n\t delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u", (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_ext->delay)/100), EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_ext->bandwidth), EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_ip_ext->mtu), tlv_ptr.eigrp_tlv_ip_ext->hopcount, tlv_ptr.eigrp_tlv_ip_ext->reliability, 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; ND_PRINT((ndo, "\n\t Cable-range: %u-%u, Router-ID %u", EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_cable_setup->cable_start), EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_cable_setup->cable_end), EXTRACT_32BITS(&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; ND_PRINT((ndo, "\n\t Cable-Range: %u-%u, nexthop: ", EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->cable_start), EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->cable_end))); if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_int->nexthop) == 0) ND_PRINT((ndo, "self")); else ND_PRINT((ndo, "%u.%u", EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->nexthop), EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->nexthop[2]))); ND_PRINT((ndo, "\n\t delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u", (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_int->delay)/100), EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_int->bandwidth), EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_at_int->mtu), tlv_ptr.eigrp_tlv_at_int->hopcount, tlv_ptr.eigrp_tlv_at_int->reliability, 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; ND_PRINT((ndo, "\n\t Cable-Range: %u-%u, nexthop: ", EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->cable_start), EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->cable_end))); if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_ext->nexthop) == 0) ND_PRINT((ndo, "self")); else ND_PRINT((ndo, "%u.%u", EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->nexthop), EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->nexthop[2]))); ND_PRINT((ndo, "\n\t origin-router %u, origin-as %u, origin-proto %s, flags [0x%02x], tag 0x%08x, metric %u", EXTRACT_32BITS(tlv_ptr.eigrp_tlv_at_ext->origin_router), EXTRACT_32BITS(tlv_ptr.eigrp_tlv_at_ext->origin_as), tok2str(eigrp_ext_proto_id_values,"unknown",tlv_ptr.eigrp_tlv_at_ext->proto_id), tlv_ptr.eigrp_tlv_at_ext->flags, EXTRACT_32BITS(tlv_ptr.eigrp_tlv_at_ext->tag), EXTRACT_16BITS(tlv_ptr.eigrp_tlv_at_ext->metric))); ND_PRINT((ndo, "\n\t delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u", (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_ext->delay)/100), EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_ext->bandwidth), EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_at_ext->mtu), tlv_ptr.eigrp_tlv_at_ext->hopcount, tlv_ptr.eigrp_tlv_at_ext->reliability, 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((ndo, "\n\t\t packet exceeded snapshot")); } Index: head/contrib/tcpdump/print-enc.c =================================================================== --- head/contrib/tcpdump/print-enc.c (revision 285274) +++ head/contrib/tcpdump/print-enc.c (revision 285275) @@ -1,137 +1,137 @@ /* $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. */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "interface.h" #include "extract.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 { uint32_t af; uint32_t spi; uint32_t flags; }; #define ENC_PRINT_TYPE(wh, xf, nam) \ if ((wh) & (xf)) { \ ND_PRINT((ndo, "%s%s", nam, (wh) == (xf) ? "): " : ",")); \ (wh) &= ~(xf); \ } u_int enc_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, register const u_char *p) { register u_int length = h->len; register u_int caplen = h->caplen; int flags; const struct enchdr *hdr; if (caplen < ENC_HDRLEN) { ND_PRINT((ndo, "[|enc]")); goto out; } hdr = (struct enchdr *)p; flags = hdr->flags; if (flags == 0) ND_PRINT((ndo, "(unprotected): ")); else ND_PRINT((ndo, "(")); ENC_PRINT_TYPE(flags, M_AUTH, "authentic"); ENC_PRINT_TYPE(flags, M_CONF, "confidential"); /* ENC_PRINT_TYPE(flags, M_TUNNEL, "tunnel"); */ ND_PRINT((ndo, "SPI 0x%08x: ", EXTRACT_32BITS(&hdr->spi))); length -= ENC_HDRLEN; caplen -= ENC_HDRLEN; p += ENC_HDRLEN; switch (hdr->af) { case AF_INET: ip_print(ndo, p, length); break; -#ifdef INET6 +#ifdef AF_INET6 case AF_INET6: ip6_print(ndo, p, length); break; -#endif /*INET6*/ +#endif } out: return (ENC_HDRLEN); } /* * Local Variables: * c-style: whitesmith * c-basic-offset: 8 * End: */ Index: head/contrib/tcpdump/print-ether.c =================================================================== --- head/contrib/tcpdump/print-ether.c (revision 285274) +++ head/contrib/tcpdump/print-ether.c (revision 285275) @@ -1,452 +1,447 @@ /* * 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. * * $FreeBSD$ */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "interface.h" #include "extract.h" #include "addrtoname.h" #include "ethertype.h" #include "ether.h" 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_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_RRCP, "RRCP" }, { ETHERTYPE_MS_NLB_HB, "MS NLB heartbeat" }, { ETHERTYPE_JUMBO, "Jumbo" }, { 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" }, { 0, NULL} }; static inline void ether_hdr_print(netdissect_options *ndo, const u_char *bp, u_int length) { register const struct ether_header *ep; uint16_t ether_type; ep = (const struct ether_header *)bp; ND_PRINT((ndo, "%s > %s", etheraddr_string(ndo, ESRC(ep)), etheraddr_string(ndo, EDST(ep)))); ether_type = EXTRACT_16BITS(&ep->ether_type); if (!ndo->ndo_qflag) { if (ether_type <= ETHERMTU) ND_PRINT((ndo, ", 802.3")); else ND_PRINT((ndo, ", ethertype %s (0x%04x)", tok2str(ethertype_values,"Unknown", ether_type), ether_type)); } else { if (ether_type <= ETHERMTU) ND_PRINT((ndo, ", 802.3")); else ND_PRINT((ndo, ", %s", tok2str(ethertype_values,"Unknown Ethertype (0x%04x)", ether_type))); } ND_PRINT((ndo, ", length %u: ", length)); } /* * 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. */ void 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) { struct ether_header *ep; u_int orig_length; u_short ether_type; u_short extracted_ether_type; if (caplen < ETHER_HDRLEN || length < ETHER_HDRLEN) { ND_PRINT((ndo, "[|ether]")); return; } if (ndo->ndo_eflag) { if (print_encap_header != NULL) (*print_encap_header)(ndo, encap_header_arg); ether_hdr_print(ndo, p, length); } orig_length = length; length -= ETHER_HDRLEN; caplen -= ETHER_HDRLEN; ep = (struct ether_header *)p; p += ETHER_HDRLEN; ether_type = EXTRACT_16BITS(&ep->ether_type); recurse: /* * Is it (gag) an 802.3 encapsulation? */ if (ether_type <= ETHERMTU) { /* Try to print the LLC-layer header & higher layers */ if (llc_print(ndo, p, length, caplen, ESRC(ep), EDST(ep), &extracted_ether_type) == 0) { /* ether_type not known, print raw packet */ if (!ndo->ndo_eflag) { if (print_encap_header != NULL) (*print_encap_header)(ndo, encap_header_arg); ether_hdr_print(ndo, (u_char *)ep, orig_length); } if (!ndo->ndo_suppress_default_print) ND_DEFAULTPRINT(p, caplen); } } else if (ether_type == ETHERTYPE_8021Q || ether_type == ETHERTYPE_8021Q9100 || ether_type == ETHERTYPE_8021Q9200 || ether_type == ETHERTYPE_8021QinQ) { /* * Print VLAN information, and then go back and process * the enclosed type field. */ if (caplen < 4 || length < 4) { ND_PRINT((ndo, "[|vlan]")); return; } if (ndo->ndo_eflag) { uint16_t tag = EXTRACT_16BITS(p); - ND_PRINT((ndo, "vlan %u, p %u%s, ", - tag & 0xfff, - tag >> 13, - (tag & 0x1000) ? ", CFI" : "")); + ND_PRINT((ndo, "%s, ", ieee8021q_tci_string(tag))); } ether_type = EXTRACT_16BITS(p + 2); if (ndo->ndo_eflag && ether_type > ETHERMTU) ND_PRINT((ndo, "ethertype %s, ", tok2str(ethertype_values,"0x%04x", ether_type))); p += 4; length -= 4; caplen -= 4; goto recurse; } else if (ether_type == ETHERTYPE_JUMBO) { /* * Alteon jumbo frames. * See * * http://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 */ if (llc_print(ndo, p, length, caplen, ESRC(ep), EDST(ep), &extracted_ether_type) == 0) { /* ether_type not known, print raw packet */ if (!ndo->ndo_eflag) { if (print_encap_header != NULL) (*print_encap_header)(ndo, encap_header_arg); ether_hdr_print(ndo, (u_char *)ep, orig_length); } if (!ndo->ndo_suppress_default_print) ND_DEFAULTPRINT(p, caplen); } } else { if (ethertype_print(ndo, ether_type, p, length, caplen) == 0) { /* ether_type not known, print raw packet */ if (!ndo->ndo_eflag) { if (print_encap_header != NULL) (*print_encap_header)(ndo, encap_header_arg); ether_hdr_print(ndo, (u_char *)ep, 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. */ u_int ether_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { ether_print(ndo, p, h->len, h->caplen, NULL, NULL); return (ETHER_HDRLEN); } /* * 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. * * This is for DLT_NETANALYZER, which has a 4-byte pseudo-header * before the Ethernet header. */ u_int 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. */ if (h->len < 4 || h->caplen < 4) { ND_PRINT((ndo, "[|netanalyzer]")); return (h->caplen); } /* Skip the pseudo-header. */ ether_print(ndo, p + 4, h->len - 4, h->caplen - 4, NULL, NULL); return (4 + ETHER_HDRLEN); } /* * 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. * * 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. */ u_int 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. */ if (h->len < 12 || h->caplen < 12) { ND_PRINT((ndo, "[|netanalyzer-transparent]")); return (h->caplen); } /* Skip the pseudo-header, preamble, and SOF. */ ether_print(ndo, p + 12, h->len - 12, h->caplen - 12, NULL, NULL); return (12 + ETHER_HDRLEN); } /* * 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) { switch (ether_type) { case ETHERTYPE_IP: ip_print(ndo, p, length); return (1); -#ifdef INET6 case ETHERTYPE_IPV6: ip6_print(ndo, p, length); return (1); -#endif /*INET6*/ 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((ndo, "et1 ")); atalk_print(ndo, p, length); return (1); case ETHERTYPE_AARP: aarp_print(ndo, p, length); return (1); case ETHERTYPE_IPX: ND_PRINT((ndo, "(NOV-ETHII) ")); ipx_print(ndo, p, length); return (1); case ETHERTYPE_ISO: isoclns_print(ndo, p + 1, length - 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: eap_print(ndo, p, length); return (1); case ETHERTYPE_RRCP: rrcp_print(ndo, p - 14 , length + 14); return (1); case ETHERTYPE_PPP: if (length) { ND_PRINT((ndo, ": ")); 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_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-14, p, length); return (1); case ETHERTYPE_CALM_FAST: calm_fast_print(ndo, p-14, p, length); return (1); case ETHERTYPE_AOE: aoe_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); } } /* * Local Variables: * c-style: whitesmith * c-basic-offset: 8 * End: */ Index: head/contrib/tcpdump/print-forces.c =================================================================== --- head/contrib/tcpdump/print-forces.c (revision 285274) +++ head/contrib/tcpdump/print-forces.c (revision 285275) @@ -1,1761 +1,1760 @@ /* * 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 * */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "interface.h" #include "extract.h" static const char tstr[] = "[|forces]"; /* - * Per draft-ietf-forces-protocol-22 -*/ + * RFC5810: Forwarding and Control Element Separation (ForCES) Protocol + */ #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, register const u_char * pptr, register 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 inline 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 inline 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 { uint8_t fm_vrsvd; /* version and reserved */ #define ForCES_V(forcesh) ((forcesh)->fm_vrsvd >> 4) uint8_t fm_tom; /* type of message */ uint16_t fm_len; /* total length * 4 bytes */ #define ForCES_BLN(forcesh) ((uint32_t)(EXTRACT_16BITS(&(forcesh)->fm_len) << 2)) uint32_t fm_sid; /* Source ID */ #define ForCES_SID(forcesh) EXTRACT_32BITS(&(forcesh)->fm_sid) uint32_t fm_did; /* Destination ID */ #define ForCES_DID(forcesh) EXTRACT_32BITS(&(forcesh)->fm_did) uint8_t fm_cor[8]; /* correlator */ uint32_t fm_flags; /* flags */ #define ForCES_ACK(forcesh) ((EXTRACT_32BITS(&(forcesh)->fm_flags)&0xC0000000) >> 30) #define ForCES_PRI(forcesh) ((EXTRACT_32BITS(&(forcesh)->fm_flags)&0x38000000) >> 27) #define ForCES_RS1(forcesh) ((EXTRACT_32BITS(&(forcesh)->fm_flags)&0x07000000) >> 24) #define ForCES_EM(forcesh) ((EXTRACT_32BITS(&(forcesh)->fm_flags)&0x00C00000) >> 22) #define ForCES_AT(forcesh) ((EXTRACT_32BITS(&(forcesh)->fm_flags)&0x00200000) >> 21) #define ForCES_TP(forcesh) ((EXTRACT_32BITS(&(forcesh)->fm_flags)&0x00180000) >> 19) #define ForCES_RS2(forcesh) ((EXTRACT_32BITS(&(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 */ +/* http://www.iana.org/assignments/forces/forces.xhtml#oper-tlv-types */ enum { - F_OP_RSV, - F_OP_SET, - F_OP_SETPROP, - F_OP_SETRESP, - F_OP_SETPRESP, - F_OP_DEL, - F_OP_DELRESP, - F_OP_GET, - F_OP_GETPROP, - F_OP_GETRESP, - F_OP_GETPRESP, - F_OP_REPORT, - F_OP_COMMIT, - F_OP_RCOMMIT, - F_OP_RTRCOMP, + 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, register const u_char * pptr, register u_int len, uint16_t op_msk, int indent); }; static int genoptlv_print(netdissect_options *, register const u_char * pptr, register u_int len, uint16_t op_msk, int indent); static int recpdoptlv_print(netdissect_options *, register const u_char * pptr, register u_int len, uint16_t op_msk, int indent); static int invoptlv_print(netdissect_options *, register const u_char * pptr, register u_int len, uint16_t op_msk, int indent); #define OP_MIN_SIZ 8 struct pathdata_h { uint16_t pflags; 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 inline 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 char ind_buf[IND_SIZE]; static inline 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 inline int op_valid(uint16_t op, uint16_t mask) { int opb = 1 << (op - 1); if (op == 0) return 0; if (opb & mask) return 1; /* 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 inline 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 { uint32_t type; uint32_t length; }; struct forces_tlv { uint16_t type; uint16_t length; }; #define F_ALN_LEN(len) ( ((len)+ForCES_ALNL-1) & ~(ForCES_ALNL-1) ) #define GET_TOP_TLV(fhdr) ((struct forces_tlv *)((fhdr) + sizeof (struct forcesh))) #define TLV_SET_LEN(len) (F_ALN_LEN(TLV_HDRL) + (len)) #define TLV_ALN_LEN(len) F_ALN_LEN(TLV_SET_LEN(len)) #define TLV_RDAT_LEN(tlv) ((int)(EXTRACT_16BITS(&(tlv)->length) - TLV_SET_LEN(0)) #define TLV_DATA(tlvp) ((void*)(((char*)(tlvp)) + TLV_SET_LEN(0))) #define GO_NXT_TLV(tlv,rlen) ((rlen) -= F_ALN_LEN(EXTRACT_16BITS(&(tlv)->length)), \ (struct forces_tlv*)(((char*)(tlv)) \ + F_ALN_LEN(EXTRACT_16BITS(&(tlv)->length)))) #define ILV_SET_LEN(len) (F_ALN_LEN(ILV_HDRL) + (len)) #define ILV_ALN_LEN(len) F_ALN_LEN(ILV_SET_LEN(len)) #define ILV_RDAT_LEN(ilv) ((int)(EXTRACT_32BITS(&(ilv)->length)) - ILV_SET_LEN(0)) #define ILV_DATA(ilvp) ((void*)(((char*)(ilvp)) + ILV_SET_LEN(0))) #define GO_NXT_ILV(ilv,rlen) ((rlen) -= F_ALN_LEN(EXTRACT_32BITS(&(ilv)->length)), \ (struct forces_ilv *)(((char*)(ilv)) \ + F_ALN_LEN(EXTRACT_32BITS(&(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 inline u_int tlv_valid(const struct forces_tlv *tlv, u_int rlen) { if (rlen < TLV_HDRL) return INVALID_RLEN; if (EXTRACT_16BITS(&tlv->length) < TLV_HDRL) return INVALID_STLN; if (EXTRACT_16BITS(&tlv->length) > rlen) return INVALID_LTLN; if (rlen < F_ALN_LEN(EXTRACT_16BITS(&tlv->length))) return INVALID_ALEN; return 0; } static inline int ilv_valid(const struct forces_ilv *ilv, u_int rlen) { if (rlen < ILV_HDRL) return INVALID_RLEN; if (EXTRACT_32BITS(&ilv->length) < ILV_HDRL) return INVALID_STLN; if (EXTRACT_32BITS(&ilv->length) > rlen) return INVALID_LTLN; if (rlen < F_ALN_LEN(EXTRACT_32BITS(&ilv->length))) return INVALID_ALEN; return 0; } static int lfbselect_print(netdissect_options *, register const u_char * pptr, register u_int len, uint16_t op_msk, int indent); static int redirect_print(netdissect_options *, register const u_char * pptr, register u_int len, uint16_t op_msk, int indent); static int asrtlv_print(netdissect_options *, register const u_char * pptr, register u_int len, uint16_t op_msk, int indent); static int asttlv_print(netdissect_options *, register const u_char * pptr, register u_int len, uint16_t op_msk, int indent); struct forces_lfbsh { uint32_t class; 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 inline 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 *, register const u_char * pptr, register 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 inline int pd_valid(uint16_t pd) { if (pd >= F_TLV_PDAT && pd <= F_TLV_REST) return 1; return 0; } static inline 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((ndo, "Based on flags expected KEYINFO TLV!\n")); } } else { if (!(msk & omsk)) { ND_PRINT((ndo, "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 { uint8_t result; uint8_t resv1; uint16_t resv2; }; static int prestlv_print(netdissect_options *, register const u_char * pptr, register u_int len, uint16_t op_msk, int indent); static int pkeyitlv_print(netdissect_options *, register const u_char * pptr, register u_int len, uint16_t op_msk, int indent); static int fdatatlv_print(netdissect_options *, register const u_char * pptr, register u_int len, uint16_t op_msk, int indent); static int sdatatlv_print(netdissect_options *, register const u_char * pptr, register 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 inline 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, register const u_char * pptr, register u_int len, uint16_t op_msk _U_, int indent) { const struct forces_tlv *tlv = (struct forces_tlv *)pptr; register const u_char *tdp = (u_char *) TLV_DATA(tlv); struct res_val *r = (struct res_val *)tdp; u_int dlen; /* * pdatacnt_print() has ensured that len (the TLV length) * >= TLV_HDRL. */ dlen = len - TLV_HDRL; if (dlen != RESLEN) { ND_PRINT((ndo, "illegal RESULT-TLV: %d bytes!\n", dlen)); return -1; } ND_TCHECK(*r); if (r->result >= 0x18 && r->result <= 0xFE) { ND_PRINT((ndo, "illegal reserved result code: 0x%x!\n", r->result)); return -1; } if (ndo->ndo_vflag >= 3) { char *ib = indent_pr(indent, 0); ND_PRINT((ndo, "%s Result: %s (code 0x%x)\n", ib, tok2str(ForCES_errs, NULL, r->result), r->result)); } return 0; trunc: ND_PRINT((ndo, "%s", tstr)); return -1; } static int fdatatlv_print(netdissect_options *ndo, register const u_char * pptr, register u_int len, uint16_t op_msk _U_, int indent) { const struct forces_tlv *tlv = (struct forces_tlv *)pptr; u_int rlen; register const u_char *tdp = (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(*tlv); type = EXTRACT_16BITS(&tlv->type); if (type != F_TLV_FULD) { ND_PRINT((ndo, "Error: expecting FULLDATA!\n")); return -1; } if (ndo->ndo_vflag >= 3) { char *ib = indent_pr(indent + 2, 1); ND_PRINT((ndo, "%s[", &ib[1])); hex_print_with_offset(ndo, ib, tdp, rlen, 0); ND_PRINT((ndo, "\n%s]\n", &ib[1])); } return 0; trunc: ND_PRINT((ndo, "%s", tstr)); return -1; } static int sdatailv_print(netdissect_options *ndo, register const u_char * pptr, register u_int len, uint16_t op_msk _U_, int indent) { u_int rlen; const struct forces_ilv *ilv = (struct forces_ilv *)pptr; int invilv; if (len < ILV_HDRL) { ND_PRINT((ndo, "Error: BAD SPARSEDATA-TLV!\n")); return -1; } rlen = len; indent += 1; while (rlen != 0) { #if 0 ND_PRINT((ndo, "Jamal - outstanding length <%d>\n", rlen)); #endif char *ib = indent_pr(indent, 1); register const u_char *tdp = (u_char *) ILV_DATA(ilv); ND_TCHECK(*ilv); invilv = ilv_valid(ilv, rlen); if (invilv) { ND_PRINT((ndo, "%s[", &ib[1])); hex_print_with_offset(ndo, ib, tdp, rlen, 0); ND_PRINT((ndo, "\n%s]\n", &ib[1])); return -1; } if (ndo->ndo_vflag >= 3) { int ilvl = EXTRACT_32BITS(&ilv->length); ND_PRINT((ndo, "\n%s ILV: type %x length %d\n", &ib[1], EXTRACT_32BITS(&ilv->type), ilvl)); hex_print_with_offset(ndo, "\t\t[", tdp, ilvl-ILV_HDRL, 0); } ilv = GO_NXT_ILV(ilv, rlen); } return 0; trunc: ND_PRINT((ndo, "%s", tstr)); return -1; } static int sdatatlv_print(netdissect_options *ndo, register const u_char * pptr, register u_int len, uint16_t op_msk, int indent) { const struct forces_tlv *tlv = (struct forces_tlv *)pptr; u_int rlen; register const u_char *tdp = (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(*tlv); type = EXTRACT_16BITS(&tlv->type); if (type != F_TLV_SPAD) { ND_PRINT((ndo, "Error: expecting SPARSEDATA!\n")); return -1; } return sdatailv_print(ndo, tdp, rlen, op_msk, indent); trunc: ND_PRINT((ndo, "%s", tstr)); return -1; } static int pkeyitlv_print(netdissect_options *ndo, register const u_char * pptr, register u_int len, uint16_t op_msk, int indent) { const struct forces_tlv *tlv = (struct forces_tlv *)pptr; register const u_char *tdp = (u_char *) TLV_DATA(tlv); register const u_char *dp = tdp + 4; const struct forces_tlv *kdtlv = (struct forces_tlv *)dp; uint32_t id; char *ib = indent_pr(indent, 0); uint16_t type, tll; u_int invtlv; ND_TCHECK(*tdp); id = EXTRACT_32BITS(tdp); ND_PRINT((ndo, "%sKeyinfo: Key 0x%x\n", ib, id)); ND_TCHECK(*kdtlv); type = EXTRACT_16BITS(&kdtlv->type); invtlv = tlv_valid(kdtlv, len); if (invtlv) { ND_PRINT((ndo, "%s TLV type 0x%x len %d\n", tok2str(ForCES_TLV_err, NULL, invtlv), type, EXTRACT_16BITS(&kdtlv->length))); 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 = EXTRACT_16BITS(&kdtlv->length); dp = (u_char *) TLV_DATA(kdtlv); return fdatatlv_print(ndo, dp, tll, op_msk, indent); trunc: ND_PRINT((ndo, "%s", tstr)); return -1; } #define PTH_DESC_SIZE 12 static int pdatacnt_print(netdissect_options *ndo, register const u_char * pptr, register 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((ndo, "%sTABLE APPEND\n", ib)); } for (i = 0; i < IDcnt; i++) { ND_TCHECK2(*pptr, 4); if (len < 4) goto trunc; id = EXTRACT_32BITS(pptr); if (ndo->ndo_vflag >= 3) ND_PRINT((ndo, "%sID#%02u: %d\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((ndo, "pathlength %d with key/range too short %d\n", len, PTH_DESC_SIZE)); return -1; } pptr += sizeof(struct forces_tlv); len -= sizeof(struct forces_tlv); starti = EXTRACT_32BITS(pptr); pptr += 4; len -= 4; endi = EXTRACT_32BITS(pptr); pptr += 4; len -= 4; if (ndo->ndo_vflag >= 3) ND_PRINT((ndo, "%sTable range: [%d,%d]\n", ib, starti, endi)); } if (op_msk & B_KEYIN) { struct forces_tlv *keytlv; uint16_t tll; if (len < PTH_DESC_SIZE) { ND_PRINT((ndo, "pathlength %d with key/range too short %d\n", len, PTH_DESC_SIZE)); return -1; } /* skip keyid */ pptr += 4; len -= 4; keytlv = (struct forces_tlv *)pptr; /* skip header */ pptr += sizeof(struct forces_tlv); len -= sizeof(struct forces_tlv); /* skip key content */ tll = EXTRACT_16BITS(&keytlv->length); if (tll < TLV_HDRL) { ND_PRINT((ndo, "key content length %u < %u\n", tll, TLV_HDRL)); return -1; } tll -= TLV_HDRL; if (len < tll) { ND_PRINT((ndo, "key content too short\n")); return -1; } pptr += tll; len -= tll; } } if (len) { const struct forces_tlv *pdtlv = (struct forces_tlv *)pptr; uint16_t type; uint16_t tll; int pad = 0; u_int aln; u_int invtlv; ND_TCHECK(*pdtlv); type = EXTRACT_16BITS(&pdtlv->type); invtlv = tlv_valid(pdtlv, len); if (invtlv) { ND_PRINT((ndo, "%s Outstanding bytes %d for TLV type 0x%x TLV len %d\n", tok2str(ForCES_TLV_err, NULL, invtlv), len, type, EXTRACT_16BITS(&pdtlv->length))); 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 = EXTRACT_16BITS(&pdtlv->length) - TLV_HDRL; aln = F_ALN_LEN(EXTRACT_16BITS(&pdtlv->length)); if (aln > EXTRACT_16BITS(&pdtlv->length)) { if (aln > len) { ND_PRINT((ndo, "Invalid padded pathdata TLV type 0x%x len %d missing %d pad bytes\n", type, EXTRACT_16BITS(&pdtlv->length), aln - len)); } else { pad = aln - EXTRACT_16BITS(&pdtlv->length); } } 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((ndo, "%s %s (Length %d DataLen %d pad %d Bytes)\n", ib, ops->s, EXTRACT_16BITS(&pdtlv->length), tll, pad)); else ND_PRINT((ndo, "%s %s (Length %d DataLen %d Bytes)\n", ib, ops->s, EXTRACT_16BITS(&pdtlv->length), 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((ndo, "Invalid path data content type 0x%x len %d\n", type, EXTRACT_16BITS(&pdtlv->length))); pd_err: if (EXTRACT_16BITS(&pdtlv->length)) { hex_print_with_offset(ndo, "Bad Data val\n\t [", pptr, len, 0); ND_PRINT((ndo, "]\n")); return -1; } } } return len; trunc: ND_PRINT((ndo, "%s", tstr)); return -1; } static int pdata_print(netdissect_options *ndo, register const u_char * pptr, register u_int len, uint16_t op_msk, int indent) { const struct pathdata_h *pdh = (struct pathdata_h *)pptr; char *ib = indent_pr(indent, 0); u_int minsize = 0; int more_pd = 0; uint16_t idcnt = 0; ND_TCHECK(*pdh); if (len < sizeof(struct pathdata_h)) goto trunc; if (ndo->ndo_vflag >= 3) { ND_PRINT((ndo, "\n%sPathdata: Flags 0x%x ID count %d\n", ib, EXTRACT_16BITS(&pdh->pflags), EXTRACT_16BITS(&pdh->pIDcnt))); } if (EXTRACT_16BITS(&pdh->pflags) & F_SELKEY) { op_msk |= B_KEYIN; } /* Table GET Range operation */ if (EXTRACT_16BITS(&pdh->pflags) & F_SELTABRANGE) { op_msk |= B_TRNG; } /* Table SET append operation */ if (EXTRACT_16BITS(&pdh->pflags) & F_TABAPPEND) { op_msk |= B_APPND; } pptr += sizeof(struct pathdata_h); len -= sizeof(struct pathdata_h); idcnt = EXTRACT_16BITS(&pdh->pIDcnt); minsize = idcnt * 4; if (len < minsize) { ND_PRINT((ndo, "\t\t\ttruncated IDs expected %uB got %uB\n", minsize, len)); hex_print_with_offset(ndo, "\t\t\tID Data[", pptr, len, 0); ND_PRINT((ndo, "]\n")); return -1; } if ((op_msk & B_TRNG) && (op_msk & B_KEYIN)) { ND_PRINT((ndo, "\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((ndo, "%s", tstr)); return -1; } static int genoptlv_print(netdissect_options *ndo, register const u_char * pptr, register u_int len, uint16_t op_msk, int indent) { const struct forces_tlv *pdtlv = (struct forces_tlv *)pptr; uint16_t type; int tll; u_int invtlv; char *ib = indent_pr(indent, 0); ND_TCHECK(*pdtlv); type = EXTRACT_16BITS(&pdtlv->type); tll = EXTRACT_16BITS(&pdtlv->length) - TLV_HDRL; invtlv = tlv_valid(pdtlv, len); ND_PRINT((ndo, "genoptlvprint - %s TLV type 0x%x len %d\n", tok2str(ForCES_TLV, NULL, type), type, EXTRACT_16BITS(&pdtlv->length))); 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). */ register const u_char *dp = (u_char *) TLV_DATA(pdtlv); if (!ttlv_valid(type)) { ND_PRINT((ndo, "%s TLV type 0x%x len %d\n", tok2str(ForCES_TLV_err, NULL, invtlv), type, EXTRACT_16BITS(&pdtlv->length))); return -1; } if (ndo->ndo_vflag >= 3) ND_PRINT((ndo, "%s%s, length %d (data length %d Bytes)", ib, tok2str(ForCES_TLV, NULL, type), EXTRACT_16BITS(&pdtlv->length), tll)); return pdata_print(ndo, dp, tll, op_msk, indent + 1); } else { ND_PRINT((ndo, "\t\t\tInvalid ForCES TLV type=%x", type)); return -1; } trunc: ND_PRINT((ndo, "%s", tstr)); return -1; } static int recpdoptlv_print(netdissect_options *ndo, register const u_char * pptr, register u_int len, uint16_t op_msk, int indent) { const struct forces_tlv *pdtlv = (struct forces_tlv *)pptr; int tll; u_int invtlv; uint16_t type; register const u_char *dp; char *ib; while (len != 0) { ND_TCHECK(*pdtlv); invtlv = tlv_valid(pdtlv, 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 = EXTRACT_16BITS(&pdtlv->type); dp = (u_char *) TLV_DATA(pdtlv); tll = EXTRACT_16BITS(&pdtlv->length) - TLV_HDRL; if (ndo->ndo_vflag >= 3) ND_PRINT((ndo, "%s%s, length %d (data encapsulated %d Bytes)", ib, tok2str(ForCES_TLV, NULL, type), EXTRACT_16BITS(&pdtlv->length), EXTRACT_16BITS(&pdtlv->length) - TLV_HDRL)); if (pdata_print(ndo, dp, tll, op_msk, indent + 1) == -1) return -1; pdtlv = GO_NXT_TLV(pdtlv, len); } if (len) { ND_PRINT((ndo, "\n\t\tMessy PATHDATA TLV header, type (0x%x)\n\t\texcess of %d Bytes ", EXTRACT_16BITS(&pdtlv->type), len - EXTRACT_16BITS(&pdtlv->length))); return -1; } return 0; trunc: ND_PRINT((ndo, "%s", tstr)); return -1; } static int invoptlv_print(netdissect_options *ndo, register const u_char * pptr, register u_int len, uint16_t op_msk _U_, int indent) { char *ib = indent_pr(indent, 1); if (ndo->ndo_vflag >= 3) { ND_PRINT((ndo, "%sData[", &ib[1])); hex_print_with_offset(ndo, ib, pptr, len, 0); ND_PRINT((ndo, "%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; register const u_char *dp = (u_char *) TLV_DATA(otlv); uint16_t type; int tll; char *ib = indent_pr(indent, 0); const struct optlv_h *ops; /* * lfbselect_print() has ensured that EXTRACT_16BITS(&otlv->length) * >= TLV_HDRL. */ ND_TCHECK(*otlv); type = EXTRACT_16BITS(&otlv->type); tll = EXTRACT_16BITS(&otlv->length) - TLV_HDRL; ops = get_forces_optlv_h(type); if (ndo->ndo_vflag >= 3) { ND_PRINT((ndo, "%sOper TLV %s(0x%x) length %d\n", ib, ops->s, type, EXTRACT_16BITS(&otlv->length))); } - /* empty TLVs like COMMIT and TRCOMMIT are empty, we stop here .. */ - if (!ops->flags & ZERO_TTLV) { - if (tll != 0) /* instead of "if (tll)" - for readability .. */ - ND_PRINT((ndo, "%s: Illegal - MUST be empty\n", ops->s)); - return rc; - } /* rest of ops must at least have 12B {pathinfo} */ if (tll < OP_MIN_SIZ) { ND_PRINT((ndo, "\t\tOper TLV %s(0x%x) length %d\n", ops->s, type, EXTRACT_16BITS(&otlv->length))); ND_PRINT((ndo, "\t\tTruncated data size %d minimum required %d\n", tll, OP_MIN_SIZ)); return invoptlv_print(ndo, dp, tll, ops->op_msk, indent); } - rc = ops->print(ndo, dp, tll, ops->op_msk, indent + 1); + /* XXX - do anything with ops->flags? */ + if(ops->print) { + rc = ops->print(ndo, dp, tll, ops->op_msk, indent + 1); + } return rc; trunc: ND_PRINT((ndo, "%s", tstr)); return -1; } #define ASTDLN 4 #define ASTMCD 255 static int asttlv_print(netdissect_options *ndo, register const u_char * pptr, register 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((ndo, "illegal ASTresult-TLV: %d bytes!\n", dlen)); return -1; } ND_TCHECK2(*pptr, 4); rescode = EXTRACT_32BITS(pptr); if (rescode > ASTMCD) { ND_PRINT((ndo, "illegal ASTresult result code: %d!\n", rescode)); return -1; } if (ndo->ndo_vflag >= 3) { ND_PRINT((ndo, "Teardown reason:\n%s", ib)); switch (rescode) { case 0: ND_PRINT((ndo, "Normal Teardown")); break; case 1: ND_PRINT((ndo, "Loss of Heartbeats")); break; case 2: ND_PRINT((ndo, "Out of bandwidth")); break; case 3: ND_PRINT((ndo, "Out of Memory")); break; case 4: ND_PRINT((ndo, "Application Crash")); break; default: ND_PRINT((ndo, "Unknown Teardown reason")); break; } ND_PRINT((ndo, "(%x)\n%s", rescode, ib)); } return 0; trunc: ND_PRINT((ndo, "%s", tstr)); return -1; } #define ASRDLN 4 #define ASRMCD 3 static int asrtlv_print(netdissect_options *ndo, register const u_char * pptr, register 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((ndo, "illegal ASRresult-TLV: %d bytes!\n", dlen)); return -1; } ND_TCHECK2(*pptr, 4); rescode = EXTRACT_32BITS(pptr); if (rescode > ASRMCD) { ND_PRINT((ndo, "illegal ASRresult result code: %d!\n", rescode)); return -1; } if (ndo->ndo_vflag >= 3) { ND_PRINT((ndo, "\n%s", ib)); switch (rescode) { case 0: ND_PRINT((ndo, "Success ")); break; case 1: ND_PRINT((ndo, "FE ID invalid ")); break; case 2: ND_PRINT((ndo, "permission denied ")); break; default: ND_PRINT((ndo, "Unknown ")); break; } ND_PRINT((ndo, "(%x)\n%s", rescode, ib)); } return 0; trunc: ND_PRINT((ndo, "%s", tstr)); return -1; } #if 0 /* * XXX - not used. */ static int gentltlv_print(netdissect_options *ndo, register const u_char * pptr _U_, register 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((ndo, "truncated TLV: %d bytes missing! ", 4 - dlen)); return -1; } return 0; } #endif #define RD_MIN 8 static int print_metailv(netdissect_options *ndo, register 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 = (struct forces_ilv *)pptr; /* * print_metatlv() has ensured that len (what remains in the * ILV) >= ILV_HDRL. */ rlen = EXTRACT_32BITS(&ilv->length) - ILV_HDRL; ND_TCHECK(*ilv); ND_PRINT((ndo, "%sMetaID 0x%x length %d\n", ib, EXTRACT_32BITS(&ilv->type), EXTRACT_32BITS(&ilv->length))); if (ndo->ndo_vflag >= 3) { hex_print_with_offset(ndo, "\t\t[", ILV_DATA(ilv), rlen, 0); ND_PRINT((ndo, " ]\n")); } return 0; trunc: ND_PRINT((ndo, "%s", tstr)); return -1; } static int print_metatlv(netdissect_options *ndo, register const u_char * pptr, register 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 = (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((ndo, "\n%s METADATA length %d \n", ib, rlen)); while (rlen != 0) { ND_TCHECK(*ilv); invilv = ilv_valid(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, (u_char *) ilv, 0, indent + 1); ilv = GO_NXT_ILV(ilv, rlen); } return 0; trunc: ND_PRINT((ndo, "%s", tstr)); return -1; } static int print_reddata(netdissect_options *ndo, register const u_char * pptr, register u_int len, uint16_t op_msk _U_, int indent _U_) { u_int dlen; char *ib = indent_pr(indent, 0); u_int rlen; dlen = len - TLV_HDRL; rlen = dlen; ND_PRINT((ndo, "\n%s Redirect Data length %d \n", ib, rlen)); if (ndo->ndo_vflag >= 3) { ND_PRINT((ndo, "\t\t[")); hex_print_with_offset(ndo, "\n\t\t", pptr, rlen, 0); ND_PRINT((ndo, "\n\t\t]")); } return 0; } static int redirect_print(netdissect_options *ndo, register const u_char * pptr, register u_int len, uint16_t op_msk _U_, int indent) { const struct forces_tlv *tlv = (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((ndo, "\n\t\ttruncated Redirect TLV: %d bytes missing! ", RD_MIN - dlen)); return -1; } rlen = dlen; indent += 1; while (rlen != 0) { ND_TCHECK(*tlv); invtlv = tlv_valid(tlv, rlen); if (invtlv) { ND_PRINT((ndo, "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 (EXTRACT_16BITS(&tlv->type) == F_TLV_METD) { print_metatlv(ndo, (u_char *) TLV_DATA(tlv), EXTRACT_16BITS(&tlv->length), 0, indent); } else if ((EXTRACT_16BITS(&tlv->type) == F_TLV_REDD)) { print_reddata(ndo, (u_char *) TLV_DATA(tlv), EXTRACT_16BITS(&tlv->length), 0, indent); } else { ND_PRINT((ndo, "Unknown REDIRECT TLV 0x%x len %d\n", EXTRACT_16BITS(&tlv->type), EXTRACT_16BITS(&tlv->length))); } tlv = GO_NXT_TLV(tlv, rlen); } if (rlen) { ND_PRINT((ndo, "\n\t\tMessy Redirect TLV header, type (0x%x)\n\t\texcess of %d Bytes ", EXTRACT_16BITS(&tlv->type), rlen - EXTRACT_16BITS(&tlv->length))); return -1; } return 0; trunc: ND_PRINT((ndo, "%s", tstr)); return -1; } #define OP_OFF 8 #define OP_MIN 12 static int lfbselect_print(netdissect_options *ndo, register const u_char * pptr, register 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((ndo, "\n\t\ttruncated lfb selector: %d 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(*lfbs); if (ndo->ndo_vflag >= 3) { ND_PRINT((ndo, "\n%s%s(Classid %x) instance %x\n", ib, tok2str(ForCES_LFBs, NULL, EXTRACT_32BITS(&lfbs->class)), EXTRACT_32BITS(&lfbs->class), EXTRACT_32BITS(&lfbs->instance))); } otlv = (struct forces_tlv *)(lfbs + 1); indent += 1; while (rlen != 0) { ND_TCHECK(*otlv); invtlv = tlv_valid(otlv, 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(EXTRACT_16BITS(&otlv->type), op_msk)) { otlv_print(ndo, otlv, 0, indent); } else { if (ndo->ndo_vflag < 3) ND_PRINT((ndo, "\n")); ND_PRINT((ndo, "\t\tINValid oper-TLV type 0x%x length %d for this ForCES message\n", EXTRACT_16BITS(&otlv->type), EXTRACT_16BITS(&otlv->length))); invoptlv_print(ndo, (u_char *)otlv, rlen, 0, indent); } otlv = GO_NXT_TLV(otlv, rlen); } if (rlen) { ND_PRINT((ndo, "\n\t\tMessy oper TLV header, type (0x%x)\n\t\texcess of %d Bytes ", EXTRACT_16BITS(&otlv->type), rlen - EXTRACT_16BITS(&otlv->length))); return -1; } return 0; trunc: ND_PRINT((ndo, "%s", tstr)); return -1; } static int forces_type_print(netdissect_options *ndo, register const u_char * pptr, const struct forcesh *fhdr _U_, register u_int mlen, const struct tom_h *tops) { const struct forces_tlv *tltlv; u_int rlen; u_int invtlv; int rc = 0; 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((ndo, "<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((ndo, "\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) { ND_TCHECK(*tltlv); invtlv = tlv_valid(tltlv, 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(EXTRACT_16BITS(&tltlv->type))) { ND_PRINT((ndo, "\n\tInvalid ForCES Top TLV type=0x%x", EXTRACT_16BITS(&tltlv->type))); return -1; } if (ndo->ndo_vflag >= 3) ND_PRINT((ndo, "\t%s, length %d (data length %d Bytes)", tok2str(ForCES_TLV, NULL, EXTRACT_16BITS(&tltlv->type)), EXTRACT_16BITS(&tltlv->length), EXTRACT_16BITS(&tltlv->length) - TLV_HDRL)); rc = tops->print(ndo, (u_char *) TLV_DATA(tltlv), EXTRACT_16BITS(&tltlv->length), 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((ndo, "\tMess TopTLV header: min %u, total %d advertised %d ", TLV_HDRL, rlen, EXTRACT_16BITS(&tltlv->length))); return -1; } return 0; trunc: ND_PRINT((ndo, "%s", tstr)); return -1; } void forces_print(netdissect_options *ndo, register const u_char * pptr, register u_int len) { const struct forcesh *fhdr; u_int mlen; uint32_t flg_raw; const struct tom_h *tops; int rc = 0; fhdr = (const struct forcesh *)pptr; ND_TCHECK(*fhdr); if (!tom_valid(fhdr->fm_tom)) { ND_PRINT((ndo, "Invalid ForCES message type %d\n", fhdr->fm_tom)); goto error; } mlen = ForCES_BLN(fhdr); tops = get_forces_tom(fhdr->fm_tom); if (tops->v == TOM_RSVD) { ND_PRINT((ndo, "\n\tUnknown ForCES message type=0x%x", fhdr->fm_tom)); goto error; } ND_PRINT((ndo, "\n\tForCES %s ", tops->s)); if (!ForCES_HLN_VALID(mlen, len)) { ND_PRINT((ndo, "Illegal ForCES pkt len - min %u, total recvd %d, advertised %d ", ForCES_HDRL, len, ForCES_BLN(fhdr))); goto error; } ND_TCHECK2(*(pptr + 20), 4); flg_raw = EXTRACT_32BITS(pptr + 20); if (ndo->ndo_vflag >= 1) { ND_PRINT((ndo, "\n\tForCES Version %d len %uB flags 0x%08x ", ForCES_V(fhdr), mlen, flg_raw)); ND_PRINT((ndo, "\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)), EXTRACT_64BITS(fhdr->fm_cor))); } if (ndo->ndo_vflag >= 2) { ND_PRINT((ndo, "\n\tForCES flags:\n\t %s(0x%x), prio=%d, %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((ndo, "\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_with_offset(ndo, "\n\t[", pptr, len, 0); ND_PRINT((ndo, "\n\t]")); return; } if (ndo->ndo_vflag >= 4) { ND_PRINT((ndo, "\n\t Raw ForCES message\n\t [")); hex_print_with_offset(ndo, "\n\t ", pptr, len, 0); ND_PRINT((ndo, "\n\t ]")); } ND_PRINT((ndo, "\n")); return; trunc: ND_PRINT((ndo, "%s", tstr)); } /* * Local Variables: * c-style: whitesmith * c-basic-offset: 8 * End: */ Index: head/contrib/tcpdump/print-fr.c =================================================================== --- head/contrib/tcpdump/print-fr.c (revision 285274) +++ head/contrib/tcpdump/print-fr.c (revision 285275) @@ -1,894 +1,931 @@ /* * 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. * * $FreeBSD$ */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "interface.h" #include "addrtoname.h" #include "ethertype.h" +#include "llc.h" #include "nlpid.h" #include "extract.h" #include "oui.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 0 on success +/* 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_addr(const u_char *p, u_int *dlci, - u_int *addr_len, uint8_t *flags) +static int parse_q922_addr(netdissect_options *ndo, + const u_char *p, u_int *dlci, + u_int *addr_len, uint8_t *flags, u_int length) { - if ((p[0] & FR_EA_BIT)) + if (!ND_TTEST(p[0]) || length < 1) return -1; + if ((p[0] & FR_EA_BIT)) + return 0; + if (!ND_TTEST(p[1]) || length < 2) + return -1; *addr_len = 2; *dlci = ((p[0] & 0xFC) << 2) | ((p[1] & 0xF0) >> 4); flags[0] = p[0] & 0x02; /* populate the first flag fields */ flags[1] = p[1] & 0x0c; flags[2] = 0; /* clear the rest of the flags */ flags[3] = 0; if (p[1] & FR_EA_BIT) - return 0; /* 2-byte Q.922 address */ + return 1; /* 2-byte Q.922 address */ p += 2; + length -= 2; + if (!ND_TTEST(p[0]) || length < 1) + return -1; (*addr_len)++; /* 3- or 4-byte Q.922 address */ if ((p[0] & FR_EA_BIT) == 0) { *dlci = (*dlci << 7) | (p[0] >> 1); (*addr_len)++; /* 4-byte Q.922 address */ p++; + length--; } + if (!ND_TTEST(p[0]) || length < 1) + return -1; if ((p[0] & FR_EA_BIT) == 0) - return -1; /* more than 4 bytes of Q.922 address? */ + return 0; /* more than 4 bytes of Q.922 address? */ flags[3] = p[0] & 0x02; *dlci = (*dlci << 6) | (p[0] >> 2); - return 0; + return 1; } -char *q922_string(const u_char *p) { +char * +q922_string(netdissect_options *ndo, const u_char *p, u_int length) +{ static u_int dlci, addr_len; static uint8_t flags[4]; static char buffer[sizeof("DLCI xxxxxxxxxx")]; memset(buffer, 0, sizeof(buffer)); - if (parse_q922_addr(p, &dlci, &addr_len, flags) == 0){ + if (parse_q922_addr(ndo, p, &dlci, &addr_len, flags, length) == 1){ snprintf(buffer, sizeof(buffer), "DLCI %u", dlci); } 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 u_int -fr_hdrlen(const u_char *p, u_int addr_len) -{ - if (!p[addr_len + 1] /* pad exist */) - return addr_len + 1 /* UI */ + 1 /* pad */ + 1 /* NLPID */; - else - return addr_len + 1 /* UI */ + 1 /* NLPID */; -} - static void fr_hdr_print(netdissect_options *ndo, int length, u_int addr_len, u_int dlci, uint8_t *flags, uint16_t nlpid) { if (ndo->ndo_qflag) { ND_PRINT((ndo, "Q.922, DLCI %u, length %u: ", dlci, length)); } else { if (nlpid <= 0xff) /* if its smaller than 256 then its a NLPID */ ND_PRINT((ndo, "Q.922, hdr-len %u, DLCI %u, Flags [%s], NLPID %s (0x%02x), length %u: ", addr_len, dlci, bittok2str(fr_header_flag_values, "none", EXTRACT_32BITS(flags)), tok2str(nlpid_values,"unknown", nlpid), nlpid, length)); else /* must be an ethertype */ ND_PRINT((ndo, "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", EXTRACT_32BITS(flags)), tok2str(ethertype_values, "unknown", nlpid), nlpid, length)); } } u_int fr_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, register const u_char *p) { register u_int length = h->len; register u_int caplen = h->caplen; ND_TCHECK2(*p, 4); /* minimum frame header length */ if ((length = fr_print(ndo, p, length)) == 0) return (0); else return length; trunc: ND_PRINT((ndo, "[|fr]")); return caplen; } u_int fr_print(netdissect_options *ndo, register 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; uint8_t flags[4]; - if (parse_q922_addr(p, &dlci, &addr_len, flags)) { + ret = parse_q922_addr(ndo, p, &dlci, &addr_len, flags, length); + if (ret == -1) + goto trunc; + if (ret == 0) { ND_PRINT((ndo, "Q.922, invalid address")); return 0; } - ND_TCHECK2(*p, addr_len+1+1); - hdr_len = fr_hdrlen(p, addr_len); - ND_TCHECK2(*p, hdr_len); + ND_TCHECK(p[addr_len]); + if (length < addr_len + 1) + goto trunc; - if (p[addr_len] != 0x03 && dlci != 0) { + if (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_TTEST2(p[addr_len], 2) || length < addr_len + 2) { + /* no Ethertype */ + ND_PRINT((ndo, "UI %02x! ", p[addr_len])); + } else { + extracted_ethertype = EXTRACT_16BITS(p+addr_len); - /* lets figure out if we have cisco style encapsulation: */ - extracted_ethertype = EXTRACT_16BITS(p+addr_len); + if (ndo->ndo_eflag) + fr_hdr_print(ndo, length, addr_len, dlci, + flags, extracted_ethertype); - 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, - length-addr_len-ETHERTYPE_LEN) == 0) - /* ether_type not known, probably it wasn't one */ - ND_PRINT((ndo, "UI %02x! ", p[addr_len])); - else - return hdr_len; + if (ethertype_print(ndo, extracted_ethertype, + p+addr_len+ETHERTYPE_LEN, + length-addr_len-ETHERTYPE_LEN, + length-addr_len-ETHERTYPE_LEN) == 0) + /* ether_type not known, probably it wasn't one */ + ND_PRINT((ndo, "UI %02x! ", p[addr_len])); + else + return addr_len + 2; + } } - if (!p[addr_len + 1]) { /* pad byte should be used with 3-byte Q.922 */ + ND_TCHECK(p[addr_len+1]); + if (length < addr_len + 2) + goto trunc; + + if (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((ndo, "Pad! ")); - } else if (addr_len == 3) - ND_PRINT((ndo, "No 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((ndo, "No pad! ")); + hdr_len = addr_len + 1 /* UI */ + 1 /* NLPID */; + } + ND_TCHECK(p[hdr_len - 1]); + if (length < hdr_len) + goto trunc; nlpid = 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; -#ifdef INET6 case NLPID_IP6: ip6_print(ndo, p, length); break; -#endif + case NLPID_CLNP: case NLPID_ESIS: case NLPID_ISIS: isoclns_print(ndo, p - 1, length + 1, length + 1); /* OSI printers need the NLPID field */ break; case NLPID_SNAP: if (snap_print(ndo, p, length, length, 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((ndo, "[|fr]")); return 0; } u_int mfr_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, register const u_char *p) { register u_int length = h->len; register u_int caplen = h->caplen; ND_TCHECK2(*p, 2); /* minimum frame header length */ if ((length = mfr_print(ndo, p, length)) == 0) return (0); else return length; trunc: ND_PRINT((ndo, "[|mfr]")); return caplen; } #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, register 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 | * +----+----+----+----+----+----+----+----+ */ ND_TCHECK2(*p, 4); /* minimum frame header length */ if ((p[0] & MFR_BEC_MASK) == MFR_CTRL_FRAME && p[1] == 0) { ND_PRINT((ndo, "FRF.16 Control, Flags [%s], %s, length %u", bittok2str(frf_flag_values,"none",(p[0] & MFR_BEC_MASK)), tok2str(mfr_ctrl_msg_values,"Unknown Message (0x%02x)",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_TCHECK2(*tptr, sizeof(struct ie_tlv_header_t)); ie_type=tptr[0]; ie_len=tptr[1]; ND_PRINT((ndo, "\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_TCHECK2(*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: ND_PRINT((ndo, "0x%08x", EXTRACT_32BITS(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 (*(tptr+idx) != 0) /* don't print null termination */ safeputchar(ndo, *(tptr + idx)); else break; } break; case MFR_CTRL_IE_TIMESTAMP: if (ie_len == sizeof(struct timeval)) { ts_print(ndo, (const struct timeval *)tptr); break; } /* fall through and hexdump if no unix timestamp */ /* * 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 = (p[0]&0x1e)<<7 | p[1]; /* whole packet or first fragment ? */ if ((p[0] & MFR_BEC_MASK) == MFR_FRAG_FRAME || (p[0] & MFR_BEC_MASK) == MFR_B_BIT) { ND_PRINT((ndo, "FRF.16 Frag, seq %u, Flags [%s], ", sequence_num, bittok2str(frf_flag_values,"none",(p[0] & 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((ndo, "FRF.16 Frag, seq %u, Flags [%s]", sequence_num, bittok2str(frf_flag_values,"none",(p[0] & MFR_BEC_MASK)))); print_unknown_data(ndo, p, "\n\t", length); return hdr_len; trunc: ND_PRINT((ndo, "[|mfr]")); 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) { - + const u_char *p, u_int length) +{ uint16_t sequence_num, flags; flags = p[0]&MFR_BEC_MASK; sequence_num = (p[0]&0x1e)<<7 | p[1]; ND_PRINT((ndo, "FRF.15, seq 0x%03x, Flags [%s],%s Fragmentation, length %u", sequence_num, bittok2str(frf_flag_values,"none",flags), p[0]&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 wether we want to print * another Q.922 header */ } /* * 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 MSG_ANSI_LOCKING_SHIFT 0x95 #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_codeset5[] = { { 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 codepages - currently we only support codepage 1,5 */ static const struct tok *fr_q933_ie_codesets[] = { NULL, fr_q933_ie_values_codeset5, NULL, NULL, NULL, fr_q933_ie_values_codeset5, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; static int fr_q933_print_ie_codeset5(netdissect_options *ndo, const struct ie_tlv_header_t *ie_p, const u_char *p); typedef int (*codeset_pr_func_t)(netdissect_options *, const struct ie_tlv_header_t *ie_p, const u_char *p); /* array of 16 codepages - currently we only support codepage 1,5 */ static const codeset_pr_func_t fr_q933_print_ie_codeset[] = { NULL, fr_q933_print_ie_codeset5, NULL, NULL, NULL, fr_q933_print_ie_codeset5, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; void q933_print(netdissect_options *ndo, const u_char *p, u_int length) { const u_char *ptemp = p; struct ie_tlv_header_t *ie_p; int olen; int is_ansi = 0; u_int codeset; u_int ie_is_known = 0; if (length < 9) { /* shortest: Q.933a LINK VERIFY */ ND_PRINT((ndo, "[|q.933]")); return; } codeset = p[2]&0x0f; /* extract the codeset */ if (p[2] == MSG_ANSI_LOCKING_SHIFT) { is_ansi = 1; } ND_PRINT((ndo, "%s", ndo->ndo_eflag ? "" : "Q.933, ")); /* printing out header part */ ND_PRINT((ndo, "%s, codeset %u", is_ansi ? "ANSI" : "CCITT", codeset)); if (p[0]) { ND_PRINT((ndo, ", Call Ref: 0x%02x", p[0])); } if (ndo->ndo_vflag) { ND_PRINT((ndo, ", %s (0x%02x), length %u", tok2str(fr_q933_msg_values, "unknown message", p[1]), p[1], length)); } else { ND_PRINT((ndo, ", %s", tok2str(fr_q933_msg_values, "unknown message 0x%02x", p[1]))); } olen = length; /* preserve the original length for non verbose mode */ if (length < (u_int)(2 - is_ansi)) { ND_PRINT((ndo, "[|q.933]")); return; } length -= 2 + is_ansi; ptemp += 2 + is_ansi; /* Loop through the rest of IE */ while (length > sizeof(struct ie_tlv_header_t)) { ie_p = (struct ie_tlv_header_t *)ptemp; if (length < sizeof(struct ie_tlv_header_t) || length < sizeof(struct ie_tlv_header_t) + ie_p->ie_len) { if (ndo->ndo_vflag) { /* not bark if there is just a trailer */ ND_PRINT((ndo, "\n[|q.933]")); } else { ND_PRINT((ndo, ", length %u", olen)); } return; } /* lets do the full IE parsing only in verbose mode * however some IEs (DLCI Status, Link Verify) * are also interestting in non-verbose mode */ if (ndo->ndo_vflag) { ND_PRINT((ndo, "\n\t%s IE (0x%02x), length %u: ", tok2str(fr_q933_ie_codesets[codeset], "unknown", ie_p->ie_type), ie_p->ie_type, ie_p->ie_len)); } /* sanity check */ if (ie_p->ie_type == 0 || ie_p->ie_len == 0) { return; } if (fr_q933_print_ie_codeset[codeset] != NULL) { ie_is_known = fr_q933_print_ie_codeset[codeset](ndo, ie_p, ptemp); } if (ndo->ndo_vflag >= 1 && !ie_is_known) { print_unknown_data(ndo, ptemp+2, "\n\t", ie_p->ie_len); } /* do we want to see a hexdump of the IE ? */ if (ndo->ndo_vflag> 1 && ie_is_known) { print_unknown_data(ndo, ptemp+2, "\n\t ", ie_p->ie_len); } length = length - ie_p->ie_len - 2; ptemp = ptemp + ie_p->ie_len + 2; } if (!ndo->ndo_vflag) { ND_PRINT((ndo, ", length %u", olen)); } } static int fr_q933_print_ie_codeset5(netdissect_options *ndo, const struct ie_tlv_header_t *ie_p, const u_char *p) { u_int dlci; switch (ie_p->ie_type) { case FR_LMI_ANSI_REPORT_TYPE_IE: /* fall through */ case FR_LMI_CCITT_REPORT_TYPE_IE: if (ndo->ndo_vflag) { ND_PRINT((ndo, "%s (%u)", tok2str(fr_lmi_report_type_ie_values,"unknown",p[2]), p[2])); } 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((ndo, ", ")); } ND_PRINT((ndo, "TX Seq: %3d, RX Seq: %3d", p[2], p[3])); return 1; case FR_LMI_ANSI_PVC_STATUS_IE: /* fall through */ case FR_LMI_CCITT_PVC_STATUS_IE: if (!ndo->ndo_vflag) { ND_PRINT((ndo, ", ")); } /* now parse the DLCI information element. */ if ((ie_p->ie_len < 3) || (p[2] & 0x80) || ((ie_p->ie_len == 3) && !(p[3] & 0x80)) || ((ie_p->ie_len == 4) && ((p[3] & 0x80) || !(p[4] & 0x80))) || ((ie_p->ie_len == 5) && ((p[3] & 0x80) || (p[4] & 0x80) || !(p[5] & 0x80))) || (ie_p->ie_len > 5) || !(p[ie_p->ie_len + 1] & 0x80)) { ND_PRINT((ndo, "Invalid DLCI IE")); } dlci = ((p[2] & 0x3F) << 4) | ((p[3] & 0x78) >> 3); if (ie_p->ie_len == 4) { dlci = (dlci << 6) | ((p[4] & 0x7E) >> 1); } else if (ie_p->ie_len == 5) { dlci = (dlci << 13) | (p[4] & 0x7F) | ((p[5] & 0x7E) >> 1); } ND_PRINT((ndo, "DLCI %u: status %s%s", dlci, p[ie_p->ie_len + 1] & 0x8 ? "New, " : "", p[ie_p->ie_len + 1] & 0x2 ? "Active" : "Inactive")); return 1; } return 0; } /* * Local Variables: * c-style: whitesmith * c-basic-offset: 8 * End: */ Index: head/contrib/tcpdump/print-ftp.c =================================================================== --- head/contrib/tcpdump/print-ftp.c (nonexistent) +++ head/contrib/tcpdump/print-ftp.c (revision 285275) @@ -0,0 +1,35 @@ +/* + * 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 lint +static const char rcsid[] _U_ = + "@(#) $Header$"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include +#include + +#include "netdissect.h" +#include "extract.h" + +void +ftp_print(netdissect_options *ndo, const u_char *pptr, u_int len) +{ + txtproto_print(ndo, pptr, len, "ftp", NULL, 0); +} Property changes on: head/contrib/tcpdump/print-ftp.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/contrib/tcpdump/print-geneve.c =================================================================== --- head/contrib/tcpdump/print-geneve.c (nonexistent) +++ head/contrib/tcpdump/print-geneve.c (revision 285275) @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2014 VMware, Inc. All Rights Reserved. + * + * Jesse Gross + * + * 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. + */ + +#define NETDISSECT_REWORKED +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "interface.h" +#include "extract.h" +#include "ethertype.h" + +/* + * Geneve header, draft-gross-geneve-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 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |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) +{ + if (opt_class <= 0xff) + return "Standard"; + else if (opt_class == 0xffff) + return "Experimental"; + else + 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((ndo, "%s", sep)); + sep = ", "; + + opt_class = EXTRACT_16BITS(bp); + opt_type = *(bp + 2); + opt_len = 4 + ((*(bp + 3) & OPT_LEN_MASK) * 4); + + ND_PRINT((ndo, "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((ndo, " [bad length]")); + return; + } + + if (ndo->ndo_vflag > 1 && opt_len > 4) { + uint32_t *print_data = (uint32_t *)(bp + 4); + int i; + + ND_PRINT((ndo, " data")); + + for (i = 4; i < opt_len; i += 4) { + ND_PRINT((ndo, " %08x", EXTRACT_32BITS(print_data))); + print_data++; + } + } + + bp += opt_len; + len -= opt_len; + } +} + +void +geneve_print(netdissect_options *ndo, const u_char *bp, u_int len) +{ + uint8_t ver_opt; + uint version; + uint8_t flags; + uint16_t prot; + uint32_t vni; + uint8_t reserved; + u_int opts_len; + + ND_PRINT((ndo, "Geneve")); + + ND_TCHECK2(*bp, 8); + + ver_opt = *bp; + bp += 1; + len -= 1; + + version = ver_opt >> VER_SHIFT; + if (version != 0) { + ND_PRINT((ndo, " ERROR: unknown-version %u", version)); + return; + } + + flags = *bp; + bp += 1; + len -= 1; + + prot = EXTRACT_16BITS(bp); + bp += 2; + len -= 2; + + vni = EXTRACT_24BITS(bp); + bp += 3; + len -= 3; + + reserved = *bp; + bp += 1; + len -= 1; + + ND_PRINT((ndo, ", Flags [%s]", + bittok2str_nosep(geneve_flag_values, "none", flags))); + ND_PRINT((ndo, ", vni 0x%x", vni)); + + if (reserved) + ND_PRINT((ndo, ", rsvd 0x%x", reserved)); + + if (ndo->ndo_eflag) + ND_PRINT((ndo, ", 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((ndo, " truncated-geneve - %u bytes missing", + len - opts_len)); + return; + } + + ND_TCHECK2(*bp, opts_len); + + if (opts_len > 0) { + ND_PRINT((ndo, ", options [")); + + if (ndo->ndo_vflag) + geneve_opts_print(ndo, bp, opts_len); + else + ND_PRINT((ndo, "%u bytes", opts_len)); + + ND_PRINT((ndo, "]")); + } + + bp += opts_len; + len -= opts_len; + + if (ndo->ndo_vflag < 1) + ND_PRINT((ndo, ": ")); + else + ND_PRINT((ndo, "\n\t")); + + if (ethertype_print(ndo, prot, bp, len, len) == 0) { + if (prot == ETHERTYPE_TEB) + ether_print(ndo, bp, len, len, NULL, NULL); + else + ND_PRINT((ndo, "geneve-proto-0x%x", prot)); + } + + return; + +trunc: + ND_PRINT((ndo, " [|geneve]")); +} Property changes on: head/contrib/tcpdump/print-geneve.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/contrib/tcpdump/print-geonet.c =================================================================== --- head/contrib/tcpdump/print-geonet.c (revision 285274) +++ head/contrib/tcpdump/print-geonet.c (revision 285275) @@ -1,247 +1,279 @@ /* * 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) */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "interface.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 length) + const u_char *bp) { int version; int msg_type; const char *msg_type_str; - if (length <= 2) { - return; - } - /* Assuming ItsDpuHeader */ version = bp[0]; msg_type = bp[1]; msg_type_str = tok2str(msg_type_values, "unknown (%u)", msg_type); ND_PRINT((ndo, "; ItsPduHeader v:%d t:%d-%s", version, msg_type, msg_type_str)); } static void print_btp(netdissect_options *ndo, const u_char *bp) { uint16_t dest = EXTRACT_16BITS(bp+0); uint16_t src = EXTRACT_16BITS(bp+2); ND_PRINT((ndo, "; BTP Dst:%u Src:%u", dest, src)); } -static void +static int print_long_pos_vector(netdissect_options *ndo, const u_char *bp) { uint32_t lat, lon; ND_PRINT((ndo, "GN_ADDR:%s ", linkaddr_string (ndo, bp, 0, GEONET_ADDR_LEN))); + if (!ND_TTEST2(*(bp+12), 8)) + return (-1); lat = EXTRACT_32BITS(bp+12); ND_PRINT((ndo, "lat:%d ", lat)); lon = EXTRACT_32BITS(bp+16); ND_PRINT((ndo, "lon:%d", lon)); + return (0); } /* * 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 *eth, const u_char *bp, u_int length) { + int version; + int next_hdr; + int hdr_type; + int hdr_subtype; + uint16_t payload_length; + int hop_limit; + const char *next_hdr_txt = "Unknown"; + const char *hdr_type_txt = "Unknown"; + int hdr_size = -1; + ND_PRINT((ndo, "GeoNet src:%s; ", etheraddr_string(ndo, eth+6))); - if (length >= 36) { - /* Process Common Header */ - int version = bp[0] >> 4; - int next_hdr = bp[0] & 0x0f; - int hdr_type = bp[1] >> 4; - int hdr_subtype = bp[1] & 0x0f; - uint16_t payload_length = EXTRACT_16BITS(bp+4); - int hop_limit = bp[7]; - const char *next_hdr_txt = "Unknown"; - const char *hdr_type_txt = "Unknown"; - int hdr_size = -1; + /* Process Common Header */ + if (length < 36) + goto malformed; + + ND_TCHECK2(*bp, 7); + version = bp[0] >> 4; + next_hdr = bp[0] & 0x0f; + hdr_type = bp[1] >> 4; + hdr_subtype = bp[1] & 0x0f; + payload_length = EXTRACT_16BITS(bp+4); + hop_limit = 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 (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; - } + 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((ndo, "v:%d ", version)); - ND_PRINT((ndo, "NH:%d-%s ", next_hdr, next_hdr_txt)); - ND_PRINT((ndo, "HT:%d-%d-%s ", hdr_type, hdr_subtype, hdr_type_txt)); - ND_PRINT((ndo, "HopLim:%d ", hop_limit)); - ND_PRINT((ndo, "Payload:%d ", payload_length)); - print_long_pos_vector(ndo, bp + 8); + ND_PRINT((ndo, "v:%d ", version)); + ND_PRINT((ndo, "NH:%d-%s ", next_hdr, next_hdr_txt)); + ND_PRINT((ndo, "HT:%d-%d-%s ", hdr_type, hdr_subtype, hdr_type_txt)); + ND_PRINT((ndo, "HopLim:%d ", hop_limit)); + ND_PRINT((ndo, "Payload:%d ", payload_length)); + if (print_long_pos_vector(ndo, bp + 8) == -1) + goto trunc; - /* Skip Common Header */ - length -= 36; - bp += 36; + /* Skip Common Header */ + length -= 36; + bp += 36; - /* Process Extended Headers */ - switch (hdr_type) { + /* 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) + goto malformed; + ND_TCHECK2(*bp, hdr_size); + length -= hdr_size; + bp += hdr_size; + switch (next_hdr) { 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; + case 1: + case 2: /* BTP A/B */ + if (length < 4) + goto malformed; + ND_TCHECK2(*bp, 4); + 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? + */ + ND_TCHECK2(*bp, 2); + print_btp_body(ndo, bp); } break; - case 4: switch (hdr_subtype) { - case 0: /* GeoBroadcastCircle */ - break; - case 1: /* GeoBroadcastRect */ - break; - case 2: /* GeoBroadcastElipse */ - break; - } + case 3: /* IPv6 */ 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) { - length -= hdr_size; - bp += hdr_size; - switch (next_hdr) { - case 0: /* Any */ - break; - case 1: - case 2: /* BTP A/B */ - print_btp(ndo, bp); - length -= 4; - bp += 4; - print_btp_body(ndo, bp, length); - break; - case 3: /* IPv6 */ - break; - } - } - } else { - ND_PRINT((ndo, "Malformed (small) ")); } /* Print user data part */ if (ndo->ndo_vflag) ND_DEFAULTPRINT(bp, length); + return; + +malformed: + ND_PRINT((ndo, " Malformed (small) ")); + /* XXX - print the remaining data as hex? */ + return; + +trunc: + ND_PRINT((ndo, "[|geonet]")); } /* * Local Variables: * c-style: whitesmith * c-basic-offset: 8 * End: */ Index: head/contrib/tcpdump/print-gre.c =================================================================== --- head/contrib/tcpdump/print-gre.c (revision 285274) +++ head/contrib/tcpdump/print-gre.c (revision 285275) @@ -1,398 +1,396 @@ /* $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. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Jason L. Wright * 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. */ /* * tcpdump filter for GRE - Generic Routing Encapsulation * RFC1701 (GRE), RFC1702 (GRE IPv4), and RFC2637 (Enhanced GRE) */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "interface.h" #include "extract.h" #include "ethertype.h" static const char tstr[] = "[|gre]"; #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_RECRS 0x0700 /* recursion count */ #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_RECRS, "recursion count"}, { GRE_AP, "ack present"}, { 0, NULL } }; #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 void gre_sre_print(netdissect_options *, uint16_t, uint8_t, uint8_t, const u_char *, u_int); static void gre_sre_ip_print(netdissect_options *, uint8_t, uint8_t, const u_char *, u_int); static void 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; if (len < 2) { ND_PRINT((ndo, "%s", tstr)); return; } vers = EXTRACT_16BITS(bp) & GRE_VERS_MASK; ND_PRINT((ndo, "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((ndo, " ERROR: unknown-version")); break; } } static void gre_print_0(netdissect_options *ndo, const u_char *bp, u_int length) { u_int len = length; uint16_t flags, prot; flags = EXTRACT_16BITS(bp); if (ndo->ndo_vflag) ND_PRINT((ndo, ", Flags [%s]", bittok2str(gre_flag_values,"none",flags))); len -= 2; bp += 2; if (len < 2) goto trunc; prot = EXTRACT_16BITS(bp); len -= 2; bp += 2; if ((flags & GRE_CP) | (flags & GRE_RP)) { if (len < 2) goto trunc; if (ndo->ndo_vflag) ND_PRINT((ndo, ", sum 0x%x", EXTRACT_16BITS(bp))); bp += 2; len -= 2; if (len < 2) goto trunc; ND_PRINT((ndo, ", off 0x%x", EXTRACT_16BITS(bp))); bp += 2; len -= 2; } if (flags & GRE_KP) { if (len < 4) goto trunc; ND_PRINT((ndo, ", key=0x%x", EXTRACT_32BITS(bp))); bp += 4; len -= 4; } if (flags & GRE_SP) { if (len < 4) goto trunc; ND_PRINT((ndo, ", seq %u", EXTRACT_32BITS(bp))); bp += 4; len -= 4; } if (flags & GRE_RP) { for (;;) { uint16_t af; uint8_t sreoff; uint8_t srelen; if (len < 4) goto trunc; af = EXTRACT_16BITS(bp); sreoff = *(bp + 2); srelen = *(bp + 3); bp += 4; len -= 4; if (af == 0 && srelen == 0) break; gre_sre_print(ndo, af, sreoff, srelen, bp, len); if (len < srelen) goto trunc; bp += srelen; len -= srelen; } } if (ndo->ndo_eflag) ND_PRINT((ndo, ", proto %s (0x%04x)", tok2str(ethertype_values,"unknown",prot), prot)); ND_PRINT((ndo, ", length %u",length)); if (ndo->ndo_vflag < 1) ND_PRINT((ndo, ": ")); /* put in a colon as protocol demarc */ else ND_PRINT((ndo, "\n\t")); /* if verbose go multiline */ switch (prot) { case ETHERTYPE_IP: ip_print(ndo, bp, len); break; -#ifdef INET6 case ETHERTYPE_IPV6: ip6_print(ndo, bp, len); break; -#endif 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, len); break; case ETHERTYPE_TEB: ether_print(ndo, bp, len, len, NULL, NULL); break; default: ND_PRINT((ndo, "gre-proto-0x%x", prot)); } return; trunc: ND_PRINT((ndo, "%s", tstr)); } static void gre_print_1(netdissect_options *ndo, const u_char *bp, u_int length) { u_int len = length; uint16_t flags, prot; flags = EXTRACT_16BITS(bp); len -= 2; bp += 2; if (ndo->ndo_vflag) ND_PRINT((ndo, ", Flags [%s]", bittok2str(gre_flag_values,"none",flags))); if (len < 2) goto trunc; prot = EXTRACT_16BITS(bp); len -= 2; bp += 2; if (flags & GRE_KP) { uint32_t k; if (len < 4) goto trunc; k = EXTRACT_32BITS(bp); ND_PRINT((ndo, ", call %d", k & 0xffff)); len -= 4; bp += 4; } if (flags & GRE_SP) { if (len < 4) goto trunc; ND_PRINT((ndo, ", seq %u", EXTRACT_32BITS(bp))); bp += 4; len -= 4; } if (flags & GRE_AP) { if (len < 4) goto trunc; ND_PRINT((ndo, ", ack %u", EXTRACT_32BITS(bp))); bp += 4; len -= 4; } if ((flags & GRE_SP) == 0) ND_PRINT((ndo, ", no-payload")); if (ndo->ndo_eflag) ND_PRINT((ndo, ", proto %s (0x%04x)", tok2str(ethertype_values,"unknown",prot), prot)); ND_PRINT((ndo, ", length %u",length)); if ((flags & GRE_SP) == 0) return; if (ndo->ndo_vflag < 1) ND_PRINT((ndo, ": ")); /* put in a colon as protocol demarc */ else ND_PRINT((ndo, "\n\t")); /* if verbose go multiline */ switch (prot) { case ETHERTYPE_PPP: ppp_print(ndo, bp, len); break; default: ND_PRINT((ndo, "gre-proto-0x%x", prot)); break; } return; trunc: ND_PRINT((ndo, "%s", tstr)); } static void gre_sre_print(netdissect_options *ndo, uint16_t af, uint8_t sreoff, uint8_t srelen, const u_char *bp, u_int len) { switch (af) { case GRESRE_IP: ND_PRINT((ndo, ", (rtaf=ip")); gre_sre_ip_print(ndo, sreoff, srelen, bp, len); ND_PRINT((ndo, ") ")); break; case GRESRE_ASN: ND_PRINT((ndo, ", (rtaf=asn")); gre_sre_asn_print(ndo, sreoff, srelen, bp, len); ND_PRINT((ndo, ") ")); break; default: ND_PRINT((ndo, ", (rtaf=0x%x) ", af)); } } static void gre_sre_ip_print(netdissect_options *ndo, uint8_t sreoff, uint8_t srelen, const u_char *bp, u_int len) { struct in_addr a; const u_char *up = bp; if (sreoff & 3) { ND_PRINT((ndo, ", badoffset=%u", sreoff)); return; } if (srelen & 3) { ND_PRINT((ndo, ", badlength=%u", srelen)); return; } if (sreoff >= srelen) { ND_PRINT((ndo, ", badoff/len=%u/%u", sreoff, srelen)); return; } for (;;) { if (len < 4 || srelen == 0) return; memcpy(&a, bp, sizeof(a)); ND_PRINT((ndo, " %s%s", ((bp - up) == sreoff) ? "*" : "", inet_ntoa(a))); bp += 4; len -= 4; srelen -= 4; } } static void 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((ndo, ", badoffset=%u", sreoff)); return; } if (srelen & 1) { ND_PRINT((ndo, ", badlength=%u", srelen)); return; } if (sreoff >= srelen) { ND_PRINT((ndo, ", badoff/len=%u/%u", sreoff, srelen)); return; } for (;;) { if (len < 2 || srelen == 0) return; ND_PRINT((ndo, " %s%x", ((bp - up) == sreoff) ? "*" : "", EXTRACT_16BITS(bp))); bp += 2; len -= 2; srelen -= 2; } } Index: head/contrib/tcpdump/print-http.c =================================================================== --- head/contrib/tcpdump/print-http.c (nonexistent) +++ head/contrib/tcpdump/print-http.c (revision 285275) @@ -0,0 +1,80 @@ +/* + * 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 lint +static const char rcsid[] _U_ = + "@(#) $Header$"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include +#include + +#include "interface.h" +#include "extract.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) +{ + txtproto_print(ndo, pptr, len, "http", httpcmds, RESP_CODE_SECOND_TOKEN); +} Property changes on: head/contrib/tcpdump/print-http.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/contrib/tcpdump/print-icmp.c =================================================================== --- head/contrib/tcpdump/print-icmp.c (revision 285274) +++ head/contrib/tcpdump/print-icmp.c (revision 285275) @@ -1,700 +1,699 @@ /* * 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. * * $FreeBSD$ */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "interface.h" #include "addrtoname.h" #include "extract.h" /* must come after interface.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 { uint8_t icmp_type; /* type of message, see below */ uint8_t icmp_code; /* type sub code */ uint16_t icmp_cksum; /* ones complement cksum of struct */ union { uint8_t ih_pptr; /* ICMP_PARAMPROB */ struct in_addr ih_gwaddr; /* ICMP_REDIRECT */ struct ih_idseq { uint16_t icd_id; uint16_t icd_seq; } ih_idseq; 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 { uint32_t its_otime; uint32_t its_rtime; uint32_t its_ttime; } id_ts; struct id_ip { struct ip idi_ip; /* options and then 64 bits of data */ } id_ip; uint32_t id_mask; uint8_t 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 }; #define ICMP_MPLS_EXT_EXTRACT_VERSION(x) (((x)&0xf0)>>4) #define ICMP_MPLS_EXT_VERSION 2 /* * Lower bounds on packet lengths for various types. * For the error advice packets must first insure that the * packet is large enought 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_INFOTYPE(type) \ - ((type) == ICMP_ECHOREPLY || (type) == ICMP_ECHO || \ - (type) == ICMP_ROUTERADVERT || (type) == ICMP_ROUTERSOLICIT || \ - (type) == ICMP_TSTAMP || (type) == ICMP_TSTAMPREPLY || \ - (type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \ - (type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY) +#define ICMP_ERRTYPE(type) \ + ((type) == ICMP_UNREACH || (type) == ICMP_SOURCEQUENCH || \ + (type) == ICMP_REDIRECT || (type) == ICMP_TIMXCEED || \ + (type) == ICMP_PARAMPROB) #define ICMP_MPLS_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 } }; /* Formats for most of the ICMP_UNREACH codes */ static const struct tok unreach2str[] = { { ICMP_UNREACH_NET, "net %s unreachable" }, { ICMP_UNREACH_HOST, "host %s unreachable" }, { ICMP_UNREACH_SRCFAIL, "%s unreachable - source route failed" }, { ICMP_UNREACH_NET_UNKNOWN, "net %s unreachable - unknown" }, { ICMP_UNREACH_HOST_UNKNOWN, "host %s unreachable - unknown" }, { ICMP_UNREACH_ISOLATED, "%s unreachable - source host isolated" }, { ICMP_UNREACH_NET_PROHIB, "net %s unreachable - admin prohibited" }, { ICMP_UNREACH_HOST_PROHIB, "host %s unreachable - admin prohibited" }, { ICMP_UNREACH_TOSNET, "net %s unreachable - tos prohibited" }, { ICMP_UNREACH_TOSHOST, "host %s unreachable - tos prohibited" }, { ICMP_UNREACH_FILTER_PROHIB, "host %s unreachable - admin prohibited filter" }, { ICMP_UNREACH_HOST_PRECEDENCE, "host %s unreachable - host precedence violation" }, { ICMP_UNREACH_PRECEDENCE_CUTOFF, "host %s unreachable - precedence cutoff" }, { 0, NULL } }; /* Formats for the ICMP_REDIRECT codes */ static const struct tok type2str[] = { { ICMP_REDIRECT_NET, "redirect %s to net %s" }, { ICMP_REDIRECT_HOST, "redirect %s to host %s" }, { ICMP_REDIRECT_TOSNET, "redirect-tos %s to net %s" }, { ICMP_REDIRECT_TOSHOST, "redirect-tos %s to host %s" }, { 0, NULL } }; /* rfc1191 */ struct mtu_discovery { uint16_t unused; uint16_t nexthopmtu; }; /* rfc1256 */ struct ih_rdiscovery { uint8_t ird_addrnum; uint8_t ird_addrsiz; uint16_t ird_lifetime; }; struct id_rdiscovery { uint32_t ird_addr; uint32_t ird_pref; }; /* * draft-bonica-internet-icmp-08 * * The Destination Unreachable, Time Exceeded * and Parameter Problem messages are slighly changed as per * the above draft. A new Length field gets added to give * the caller an idea about the length of the piggypacked * IP packet before the MPLS 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 { uint8_t icmp_type; uint8_t icmp_code; uint8_t icmp_checksum[2]; uint8_t icmp_reserved; uint8_t icmp_length; uint8_t icmp_reserved2[2]; uint8_t icmp_ext_legacy_header[128]; /* extension header starts 128 bytes after ICMP header */ uint8_t icmp_ext_version_res[2]; uint8_t icmp_ext_checksum[2]; uint8_t icmp_ext_data[1]; }; struct icmp_mpls_ext_object_header_t { uint8_t length[2]; uint8_t class_num; uint8_t ctype; }; static const struct tok icmp_mpls_ext_obj_values[] = { { 1, "MPLS Stack Entry" }, { 2, "Extended Payload" }, { 0, NULL} }; /* prototypes */ const char *icmp_tstamp_print(u_int); /* print the milliseconds since midnight UTC */ const char * -icmp_tstamp_print(u_int tstamp) { +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; const struct icmp_ext_t *ext_dp; const struct ip *ip; const char *str, *fmt; const struct ip *oip; const struct udphdr *ouh; const uint8_t *obj_tptr; uint32_t raw_label; const u_char *snapend_save; const struct icmp_mpls_ext_object_header_t *icmp_mpls_ext_object_header; u_int hlen, dport, mtu, obj_tlen, obj_class_num, obj_ctype; char buf[MAXHOSTNAMELEN + 100]; struct cksum_vec vec[1]; dp = (struct icmp *)bp; ext_dp = (struct icmp_ext_t *)bp; ip = (struct ip *)bp2; str = buf; ND_TCHECK(dp->icmp_code); switch (dp->icmp_type) { case ICMP_ECHO: case ICMP_ECHOREPLY: ND_TCHECK(dp->icmp_seq); (void)snprintf(buf, sizeof(buf), "echo %s, id %u, seq %u", dp->icmp_type == ICMP_ECHO ? "request" : "reply", EXTRACT_16BITS(&dp->icmp_id), EXTRACT_16BITS(&dp->icmp_seq)); break; case ICMP_UNREACH: ND_TCHECK(dp->icmp_ip.ip_dst); switch (dp->icmp_code) { case ICMP_UNREACH_PROTOCOL: ND_TCHECK(dp->icmp_ip.ip_p); (void)snprintf(buf, sizeof(buf), "%s protocol %d unreachable", ipaddr_string(ndo, &dp->icmp_ip.ip_dst), dp->icmp_ip.ip_p); break; case ICMP_UNREACH_PORT: ND_TCHECK(dp->icmp_ip.ip_p); oip = &dp->icmp_ip; hlen = IP_HL(oip) * 4; ouh = (struct udphdr *)(((u_char *)oip) + hlen); ND_TCHECK(ouh->uh_dport); dport = EXTRACT_16BITS(&ouh->uh_dport); switch (oip->ip_p) { case IPPROTO_TCP: (void)snprintf(buf, sizeof(buf), "%s tcp port %s unreachable", ipaddr_string(ndo, &oip->ip_dst), tcpport_string(dport)); break; case IPPROTO_UDP: (void)snprintf(buf, sizeof(buf), "%s udp port %s unreachable", ipaddr_string(ndo, &oip->ip_dst), udpport_string(dport)); break; default: (void)snprintf(buf, sizeof(buf), "%s protocol %d port %d unreachable", ipaddr_string(ndo, &oip->ip_dst), oip->ip_p, dport); break; } break; case ICMP_UNREACH_NEEDFRAG: { register const struct mtu_discovery *mp; mp = (struct mtu_discovery *)(u_char *)&dp->icmp_void; mtu = EXTRACT_16BITS(&mp->nexthopmtu); if (mtu) { (void)snprintf(buf, sizeof(buf), "%s unreachable - need to frag (mtu %d)", ipaddr_string(ndo, &dp->icmp_ip.ip_dst), mtu); } else { (void)snprintf(buf, sizeof(buf), "%s unreachable - need to frag", ipaddr_string(ndo, &dp->icmp_ip.ip_dst)); } } break; default: fmt = tok2str(unreach2str, "#%d %%s unreachable", dp->icmp_code); (void)snprintf(buf, sizeof(buf), fmt, ipaddr_string(ndo, &dp->icmp_ip.ip_dst)); break; } break; case ICMP_REDIRECT: ND_TCHECK(dp->icmp_ip.ip_dst); fmt = tok2str(type2str, "redirect-#%d %%s to net %%s", dp->icmp_code); (void)snprintf(buf, sizeof(buf), fmt, ipaddr_string(ndo, &dp->icmp_ip.ip_dst), ipaddr_string(ndo, &dp->icmp_gwaddr)); break; case ICMP_ROUTERADVERT: { register const struct ih_rdiscovery *ihp; register const struct id_rdiscovery *idp; u_int lifetime, num, size; (void)snprintf(buf, sizeof(buf), "router advertisement"); cp = buf + strlen(buf); ihp = (struct ih_rdiscovery *)&dp->icmp_void; ND_TCHECK(*ihp); (void)strncpy(cp, " lifetime ", sizeof(buf) - (cp - buf)); cp = buf + strlen(buf); lifetime = EXTRACT_16BITS(&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 = ihp->ird_addrnum; (void)snprintf(cp, sizeof(buf) - (cp - buf), " %d:", num); cp = buf + strlen(buf); size = ihp->ird_addrsiz; if (size != 2) { (void)snprintf(cp, sizeof(buf) - (cp - buf), " [size %d]", size); break; } idp = (struct id_rdiscovery *)&dp->icmp_data; while (num-- > 0) { ND_TCHECK(*idp); (void)snprintf(cp, sizeof(buf) - (cp - buf), " {%s %u}", ipaddr_string(ndo, &idp->ird_addr), EXTRACT_32BITS(&idp->ird_pref)); cp = buf + strlen(buf); ++idp; } } break; case ICMP_TIMXCEED: ND_TCHECK(dp->icmp_ip.ip_dst); switch (dp->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-#%d", dp->icmp_code); break; } break; case ICMP_PARAMPROB: if (dp->icmp_code) (void)snprintf(buf, sizeof(buf), "parameter problem - code %d", dp->icmp_code); else { ND_TCHECK(dp->icmp_pptr); (void)snprintf(buf, sizeof(buf), "parameter problem - octet %d", dp->icmp_pptr); } break; case ICMP_MASKREPLY: ND_TCHECK(dp->icmp_mask); (void)snprintf(buf, sizeof(buf), "address mask is 0x%08x", EXTRACT_32BITS(&dp->icmp_mask)); break; case ICMP_TSTAMP: ND_TCHECK(dp->icmp_seq); (void)snprintf(buf, sizeof(buf), "time stamp query id %u seq %u", EXTRACT_16BITS(&dp->icmp_id), EXTRACT_16BITS(&dp->icmp_seq)); break; case ICMP_TSTAMPREPLY: ND_TCHECK(dp->icmp_ttime); (void)snprintf(buf, sizeof(buf), "time stamp reply id %u seq %u: org %s", EXTRACT_16BITS(&dp->icmp_id), EXTRACT_16BITS(&dp->icmp_seq), icmp_tstamp_print(EXTRACT_32BITS(&dp->icmp_otime))); (void)snprintf(buf+strlen(buf),sizeof(buf)-strlen(buf),", recv %s", icmp_tstamp_print(EXTRACT_32BITS(&dp->icmp_rtime))); (void)snprintf(buf+strlen(buf),sizeof(buf)-strlen(buf),", xmit %s", icmp_tstamp_print(EXTRACT_32BITS(&dp->icmp_ttime))); break; default: str = tok2str(icmp2str, "type-#%d", dp->icmp_type); break; } ND_PRINT((ndo, "ICMP %s, length %u", str, plen)); if (ndo->ndo_vflag && !fragmented) { /* don't attempt checksumming if this is a frag */ uint16_t sum, icmp_sum; struct cksum_vec vec[1]; if (ND_TTEST2(*bp, plen)) { vec[0].ptr = (const uint8_t *)(void *)dp; vec[0].len = plen; sum = in_cksum(vec, 1); if (sum != 0) { icmp_sum = EXTRACT_16BITS(&dp->icmp_cksum); ND_PRINT((ndo, " (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 overidden in the IP printer. */ - if (ndo->ndo_vflag >= 1 && !ICMP_INFOTYPE(dp->icmp_type)) { + if (ndo->ndo_vflag >= 1 && ICMP_ERRTYPE(dp->icmp_type)) { bp += 8; ND_PRINT((ndo, "\n\t")); ip = (struct ip *)bp; ndo->ndo_snaplen = ndo->ndo_snapend - bp; snapend_save = ndo->ndo_snapend; ip_print(ndo, bp, EXTRACT_16BITS(&ip->ip_len)); ndo->ndo_snapend = snapend_save; } /* * Attempt to decode the MPLS extensions only for some ICMP types. */ if (ndo->ndo_vflag >= 1 && plen > ICMP_EXTD_MINLEN && ICMP_MPLS_EXT_TYPE(dp->icmp_type)) { ND_TCHECK(*ext_dp); /* * Check first if the mpls 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 (!ext_dp->icmp_length) { vec[0].ptr = (const uint8_t *)(void *)&ext_dp->icmp_ext_version_res; vec[0].len = plen - ICMP_EXTD_MINLEN; if (in_cksum(vec, 1)) { return; } } ND_PRINT((ndo, "\n\tMPLS extension v%u", ICMP_MPLS_EXT_EXTRACT_VERSION(*(ext_dp->icmp_ext_version_res)))); /* * Sanity checking of the header. */ if (ICMP_MPLS_EXT_EXTRACT_VERSION(*(ext_dp->icmp_ext_version_res)) != ICMP_MPLS_EXT_VERSION) { ND_PRINT((ndo, " packet not supported")); return; } hlen = plen - ICMP_EXTD_MINLEN; vec[0].ptr = (const uint8_t *)(void *)&ext_dp->icmp_ext_version_res; vec[0].len = hlen; ND_PRINT((ndo, ", checksum 0x%04x (%scorrect), length %u", EXTRACT_16BITS(ext_dp->icmp_ext_checksum), in_cksum(vec, 1) ? "in" : "", hlen)); hlen -= 4; /* subtract common header size */ obj_tptr = (uint8_t *)ext_dp->icmp_ext_data; while (hlen > sizeof(struct icmp_mpls_ext_object_header_t)) { icmp_mpls_ext_object_header = (struct icmp_mpls_ext_object_header_t *)obj_tptr; ND_TCHECK(*icmp_mpls_ext_object_header); obj_tlen = EXTRACT_16BITS(icmp_mpls_ext_object_header->length); obj_class_num = icmp_mpls_ext_object_header->class_num; obj_ctype = icmp_mpls_ext_object_header->ctype; obj_tptr += sizeof(struct icmp_mpls_ext_object_header_t); ND_PRINT((ndo, "\n\t %s Object (%u), Class-Type: %u, length %u", tok2str(icmp_mpls_ext_obj_values,"unknown",obj_class_num), obj_class_num, obj_ctype, obj_tlen)); hlen-=sizeof(struct icmp_mpls_ext_object_header_t); /* length field includes tlv header */ /* infinite loop protection */ if ((obj_class_num == 0) || (obj_tlen < sizeof(struct icmp_mpls_ext_object_header_t))) { return; } obj_tlen-=sizeof(struct icmp_mpls_ext_object_header_t); switch (obj_class_num) { case 1: switch(obj_ctype) { case 1: ND_TCHECK2(*obj_tptr, 4); raw_label = EXTRACT_32BITS(obj_tptr); ND_PRINT((ndo, "\n\t label %u, exp %u", MPLS_LABEL(raw_label), MPLS_EXP(raw_label))); if (MPLS_STACK(raw_label)) ND_PRINT((ndo, ", [S]")); ND_PRINT((ndo, ", ttl %u", MPLS_TTL(raw_label))); break; default: print_unknown_data(ndo, obj_tptr, "\n\t ", obj_tlen); } break; /* * FIXME those are the defined objects that lack a decoder * you are welcome to contribute code ;-) */ case 2: 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((ndo, "[|icmp]")); } /* * Local Variables: * c-style: whitesmith * c-basic-offset: 8 * End: */ Index: head/contrib/tcpdump/print-icmp6.c =================================================================== --- head/contrib/tcpdump/print-icmp6.c (revision 285274) +++ head/contrib/tcpdump/print-icmp6.c (revision 285275) @@ -1,1974 +1,1974 @@ /* * 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. */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef INET6 #include #include #include #include "interface.h" #include "addrtoname.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 { uint8_t icmp6_type; /* type field */ uint8_t icmp6_code; /* code field */ uint16_t icmp6_cksum; /* checksum field */ union { uint32_t icmp6_un_data32[1]; /* type-specific field */ uint16_t icmp6_un_data16[2]; /* type-specific field */ uint8_t icmp6_un_data8[4]; /* 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_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 */ #define ICMP6_NI_REPLY 140 /* node information reply */ #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_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; struct in6_addr 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; uint32_t nd_ra_reachable; /* reachable time */ 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 /* * 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; struct in6_addr 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; struct in6_addr 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; struct in6_addr nd_rd_target; /* target address */ struct in6_addr 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 */ uint8_t nd_opt_type; 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 */ uint8_t nd_opt_pi_type; uint8_t nd_opt_pi_len; uint8_t nd_opt_pi_prefix_len; uint8_t nd_opt_pi_flags_reserved; uint8_t nd_opt_pi_valid_time[4]; uint8_t nd_opt_pi_preferred_time[4]; uint8_t nd_opt_pi_reserved2[4]; struct in6_addr 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 */ uint8_t nd_opt_rh_type; uint8_t nd_opt_rh_len; uint16_t nd_opt_rh_reserved1; uint32_t nd_opt_rh_reserved2; /* followed by IP header and data */ }; struct nd_opt_mtu { /* MTU option */ uint8_t nd_opt_mtu_type; uint8_t nd_opt_mtu_len; uint16_t nd_opt_mtu_reserved; uint32_t nd_opt_mtu_mtu; }; struct nd_opt_rdnss { /* RDNSS RFC 6106 5.1 */ uint8_t nd_opt_rdnss_type; uint8_t nd_opt_rdnss_len; uint16_t nd_opt_rdnss_reserved; uint32_t nd_opt_rdnss_lifetime; struct in6_addr nd_opt_rdnss_addr[1]; /* variable-length */ }; struct nd_opt_dnssl { /* DNSSL RFC 6106 5.2 */ uint8_t nd_opt_dnssl_type; uint8_t nd_opt_dnssl_len; uint16_t nd_opt_dnssl_reserved; uint32_t nd_opt_dnssl_lifetime; /* followed by list of DNS search domains, variable-length */ }; struct nd_opt_advinterval { /* Advertisement interval option */ uint8_t nd_opt_adv_type; uint8_t nd_opt_adv_len; uint16_t nd_opt_adv_reserved; uint32_t nd_opt_adv_interval; }; struct nd_opt_homeagent_info { /* Home Agent info */ uint8_t nd_opt_hai_type; uint8_t nd_opt_hai_len; uint16_t nd_opt_hai_reserved; int16_t nd_opt_hai_preference; uint16_t nd_opt_hai_lifetime; }; struct nd_opt_route_info { /* route info */ uint8_t nd_opt_rti_type; uint8_t nd_opt_rti_len; uint8_t nd_opt_rti_prefixlen; uint8_t nd_opt_rti_flags; uint32_t nd_opt_rti_lifetime; /* prefix follows */ }; /* * icmp6 namelookup */ struct icmp6_namelookup { struct icmp6_hdr icmp6_nl_hdr; uint8_t icmp6_nl_nonce[8]; int32_t icmp6_nl_ttl; #if 0 uint8_t icmp6_nl_len; uint8_t icmp6_nl_name[3]; #endif /* could be followed by options */ }; /* * icmp6 node information */ struct icmp6_nodeinfo { struct icmp6_hdr icmp6_ni_hdr; uint8_t 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 */ #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 */ /* network endian */ #define NI_SUPTYPE_FLAG_COMPRESS ((uint16_t)htons(0x1)) #define NI_FQDN_FLAG_VALIDTTL ((uint16_t)htons(0x1)) /* network endian */ #define NI_NODEADDR_FLAG_TRUNCATE ((uint16_t)htons(0x1)) #define NI_NODEADDR_FLAG_ALL ((uint16_t)htons(0x2)) #define NI_NODEADDR_FLAG_COMPAT ((uint16_t)htons(0x4)) #define NI_NODEADDR_FLAG_LINKLOCAL ((uint16_t)htons(0x8)) #define NI_NODEADDR_FLAG_SITELOCAL ((uint16_t)htons(0x10)) #define NI_NODEADDR_FLAG_GLOBAL ((uint16_t)htons(0x20)) #define NI_NODEADDR_FLAG_ANYCAST ((uint16_t)htons(0x40)) /* just experimental. not in spec */ struct ni_reply_fqdn { uint32_t ni_fqdn_ttl; /* TTL */ uint8_t ni_fqdn_namelen; /* length in octets of the FQDN */ uint8_t 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; uint8_t rr_segnum; uint8_t rr_flags; uint16_t rr_maxdelay; 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 */ uint8_t rpm_code; uint8_t rpm_len; uint8_t rpm_ordinal; uint8_t rpm_matchlen; uint8_t rpm_minlen; uint8_t rpm_maxlen; uint16_t rpm_reserved; struct in6_addr 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 */ uint8_t rpu_uselen; uint8_t rpu_keeplen; uint8_t rpu_ramask; uint8_t rpu_raflags; uint32_t rpu_vltime; uint32_t rpu_pltime; uint32_t rpu_flags; struct in6_addr 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 */ uint16_t rrr_flags; uint8_t rrr_ordinal; uint8_t rrr_matchedlen; uint32_t rrr_ifid; struct in6_addr 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 void 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 *); #ifndef abs #define abs(a) ((0 < (a)) ? (a) : -(a)) #endif #include "rpl.h" 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"}, { 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((ndo,":")); ND_PRINT((ndo,"%02x", *q++)); l--; } } static int icmp6_cksum(const struct ip6_hdr *ip6, const struct icmp6_hdr *icp, u_int len) { return nextproto6_cksum(ip6, (const uint8_t *)(void *)icp, len, len, IPPROTO_ICMPV6); } 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}, }; const struct tok rpl_subopt_values[] = { { RPL_OPT_PAD0, "pad0"}, { 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_format_dagid(char dagid_str[65], const u_char *dagid) { char *d = dagid_str; int i; for(i=0;i<16;i++) { if(isprint(dagid[i])) { *d++ = dagid[i]; } else { - snprintf(d,4,"0x%02x", dagid[i]); + snprintf(d,5,"0x%02x", dagid[i]); /* 4 + null char */ d += 4; } } *d++ = '\0'; } static void rpl_dio_printopt(netdissect_options *ndo, const struct rpl_dio_genoption *opt, u_int length) { if(length < RPL_DIO_GENOPTION_LEN) return; length -= RPL_DIO_GENOPTION_LEN; ND_TCHECK(opt->rpl_dio_len); while((opt->rpl_dio_type == RPL_OPT_PAD0 && (u_char *)opt < ndo->ndo_snapend) || ND_TTEST2(*opt,(opt->rpl_dio_len+2))) { unsigned int optlen = opt->rpl_dio_len+2; if(opt->rpl_dio_type == RPL_OPT_PAD0) { optlen = 1; ND_PRINT((ndo, " opt:pad0")); } else { ND_PRINT((ndo, " opt:%s len:%u ", tok2str(rpl_subopt_values, "%subopt:%u", opt->rpl_dio_type), optlen)); if(ndo->ndo_vflag > 2) { unsigned int paylen = opt->rpl_dio_len; if(paylen > length) paylen = length; hex_print(ndo, " ", ((uint8_t *)opt) + RPL_DIO_GENOPTION_LEN, /* content of DIO option */ paylen); } } opt = (struct rpl_dio_genoption *)(((char *)opt) + optlen); length -= optlen; } return; trunc: ND_PRINT((ndo," [|truncated]")); return; } static void rpl_dio_print(netdissect_options *ndo, const u_char *bp, u_int length) { const struct nd_rpl_dio *dio = (struct nd_rpl_dio *)bp; char dagid_str[65]; ND_TCHECK(*dio); rpl_format_dagid(dagid_str, dio->rpl_dagid); ND_PRINT((ndo, " [dagid:%s,seq:%u,instance:%u,rank:%u,%smop:%s,prf:%u]", dagid_str, dio->rpl_dtsn, dio->rpl_instanceid, EXTRACT_16BITS(&dio->rpl_dagrank), RPL_DIO_GROUNDED(dio->rpl_mopprf) ? "grounded,":"", tok2str(rpl_mop_values, "mop%u", RPL_DIO_MOP(dio->rpl_mopprf)), RPL_DIO_PRF(dio->rpl_mopprf))); if(ndo->ndo_vflag > 1) { struct rpl_dio_genoption *opt = (struct rpl_dio_genoption *)&dio[1]; rpl_dio_printopt(ndo, opt, length); } return; trunc: ND_PRINT((ndo," [|truncated]")); return; } static void rpl_dao_print(netdissect_options *ndo, const u_char *bp, u_int length) { const struct nd_rpl_dao *dao = (struct nd_rpl_dao *)bp; char dagid_str[65]; ND_TCHECK(*dao); if (length < ND_RPL_DAO_MIN_LEN) goto tooshort; strcpy(dagid_str,""); bp += ND_RPL_DAO_MIN_LEN; length -= ND_RPL_DAO_MIN_LEN; if(RPL_DAO_D(dao->rpl_flags)) { ND_TCHECK2(dao->rpl_dagid, DAGID_LEN); if (length < DAGID_LEN) goto tooshort; rpl_format_dagid(dagid_str, dao->rpl_dagid); bp += DAGID_LEN; length -= DAGID_LEN; } ND_PRINT((ndo, " [dagid:%s,seq:%u,instance:%u%s%s,%02x]", dagid_str, dao->rpl_daoseq, dao->rpl_instanceid, RPL_DAO_K(dao->rpl_flags) ? ",acK":"", RPL_DAO_D(dao->rpl_flags) ? ",Dagid":"", dao->rpl_flags)); if(ndo->ndo_vflag > 1) { const struct rpl_dio_genoption *opt = (struct rpl_dio_genoption *)bp; rpl_dio_printopt(ndo, opt, length); } return; trunc: ND_PRINT((ndo," [|truncated]")); return; tooshort: ND_PRINT((ndo," [|length too short]")); return; } static void rpl_daoack_print(netdissect_options *ndo, const u_char *bp, u_int length) { const struct nd_rpl_daoack *daoack = (struct nd_rpl_daoack *)bp; char dagid_str[65]; ND_TCHECK2(*daoack, ND_RPL_DAOACK_MIN_LEN); if (length < ND_RPL_DAOACK_MIN_LEN) goto tooshort; strcpy(dagid_str,""); bp += ND_RPL_DAOACK_MIN_LEN; length -= ND_RPL_DAOACK_MIN_LEN; if(RPL_DAOACK_D(daoack->rpl_flags)) { ND_TCHECK2(daoack->rpl_dagid, 16); if (length < DAGID_LEN) goto tooshort; rpl_format_dagid(dagid_str, daoack->rpl_dagid); bp += DAGID_LEN; length -= DAGID_LEN; } ND_PRINT((ndo, " [dagid:%s,seq:%u,instance:%u,status:%u]", dagid_str, daoack->rpl_daoseq, daoack->rpl_instanceid, daoack->rpl_status)); /* no officially defined options for DAOACK, but print any we find */ if(ndo->ndo_vflag > 1) { const struct rpl_dio_genoption *opt = (struct rpl_dio_genoption *)bp; rpl_dio_printopt(ndo, opt, length); } return; trunc: ND_PRINT((ndo," [|dao-truncated]")); return; tooshort: ND_PRINT((ndo," [|dao-length too short]")); return; } static void rpl_print(netdissect_options *ndo, const struct icmp6_hdr *hdr, const u_char *bp, u_int length) { int secured = hdr->icmp6_code & 0x80; int basecode= hdr->icmp6_code & 0x7f; if(secured) { ND_PRINT((ndo, ", (SEC) [worktodo]")); /* XXX * the next header pointer needs to move forward to * skip the secure part. */ return; } else { ND_PRINT((ndo, ", (CLR)")); } switch(basecode) { case ND_RPL_DAG_IS: ND_PRINT((ndo, "DODAG Information Solicitation")); if(ndo->ndo_vflag) { } break; case ND_RPL_DAG_IO: ND_PRINT((ndo, "DODAG Information Object")); if(ndo->ndo_vflag) { rpl_dio_print(ndo, bp, length); } break; case ND_RPL_DAO: ND_PRINT((ndo, "Destination Advertisement Object")); if(ndo->ndo_vflag) { rpl_dao_print(ndo, bp, length); } break; case ND_RPL_DAO_ACK: ND_PRINT((ndo, "Destination Advertisement Object Ack")); if(ndo->ndo_vflag) { rpl_daoack_print(ndo, bp, length); } break; default: ND_PRINT((ndo, "RPL message, unknown code %u",hdr->icmp6_code)); break; } return; #if 0 trunc: ND_PRINT((ndo," [|truncated]")); 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; const struct ip6_hdr *ip; const struct ip6_hdr *oip; const struct udphdr *ouh; int dport; const u_char *ep; u_int prot; dp = (struct icmp6_hdr *)bp; ip = (struct ip6_hdr *)bp2; oip = (struct ip6_hdr *)(dp + 1); /* 'ep' points to the end of available data. */ ep = ndo->ndo_snapend; ND_TCHECK(dp->icmp6_cksum); if (ndo->ndo_vflag && !fragmented) { uint16_t sum, udp_sum; if (ND_TTEST2(bp[0], length)) { udp_sum = EXTRACT_16BITS(&dp->icmp6_cksum); sum = icmp6_cksum(ip, dp, length); if (sum != 0) ND_PRINT((ndo,"[bad icmp6 cksum 0x%04x -> 0x%04x!] ", udp_sum, in_cksum_shouldbe(udp_sum, sum))); else ND_PRINT((ndo,"[icmp6 sum ok] ")); } } ND_PRINT((ndo,"ICMP6, %s", tok2str(icmp6_type_values,"unknown icmp6 type (%u)",dp->icmp6_type))); /* display cosmetics: print the packet length for printer that use the vflag now */ if (ndo->ndo_vflag && (dp->icmp6_type == ND_ROUTER_SOLICIT || dp->icmp6_type == ND_ROUTER_ADVERT || dp->icmp6_type == ND_NEIGHBOR_ADVERT || dp->icmp6_type == ND_NEIGHBOR_SOLICIT || dp->icmp6_type == ND_REDIRECT || dp->icmp6_type == ICMP6_HADISCOV_REPLY || dp->icmp6_type == ICMP6_MOBILEPREFIX_ADVERT )) ND_PRINT((ndo,", length %u", length)); switch (dp->icmp6_type) { case ICMP6_DST_UNREACH: ND_TCHECK(oip->ip6_dst); ND_PRINT((ndo,", %s", tok2str(icmp6_dst_unreach_code_values,"unknown unreach code (%u)",dp->icmp6_code))); switch (dp->icmp6_code) { case ICMP6_DST_UNREACH_NOROUTE: /* fall through */ case ICMP6_DST_UNREACH_ADMIN: case ICMP6_DST_UNREACH_ADDR: ND_PRINT((ndo," %s",ip6addr_string(ndo, &oip->ip6_dst))); break; case ICMP6_DST_UNREACH_BEYONDSCOPE: ND_PRINT((ndo," %s, source address %s", ip6addr_string(ndo, &oip->ip6_dst), ip6addr_string(ndo, &oip->ip6_src))); break; case ICMP6_DST_UNREACH_NOPORT: if ((ouh = get_upperlayer(ndo, (u_char *)oip, &prot)) == NULL) goto trunc; dport = EXTRACT_16BITS(&ouh->uh_dport); switch (prot) { case IPPROTO_TCP: ND_PRINT((ndo,", %s tcp port %s", ip6addr_string(ndo, &oip->ip6_dst), tcpport_string(dport))); break; case IPPROTO_UDP: ND_PRINT((ndo,", %s udp port %s", ip6addr_string(ndo, &oip->ip6_dst), udpport_string(dport))); break; default: ND_PRINT((ndo,", %s protocol %d port %d unreachable", ip6addr_string(ndo, &oip->ip6_dst), oip->ip6_nxt, 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_TCHECK(dp->icmp6_mtu); ND_PRINT((ndo,", mtu %u", EXTRACT_32BITS(&dp->icmp6_mtu))); break; case ICMP6_TIME_EXCEEDED: ND_TCHECK(oip->ip6_dst); switch (dp->icmp6_code) { case ICMP6_TIME_EXCEED_TRANSIT: ND_PRINT((ndo," for %s", ip6addr_string(ndo, &oip->ip6_dst))); break; case ICMP6_TIME_EXCEED_REASSEMBLY: ND_PRINT((ndo," (reassembly)")); break; default: ND_PRINT((ndo,", unknown code (%u)", dp->icmp6_code)); break; } break; case ICMP6_PARAM_PROB: ND_TCHECK(oip->ip6_dst); switch (dp->icmp6_code) { case ICMP6_PARAMPROB_HEADER: ND_PRINT((ndo,", erroneous - octet %u", EXTRACT_32BITS(&dp->icmp6_pptr))); break; case ICMP6_PARAMPROB_NEXTHEADER: ND_PRINT((ndo,", next header - octet %u", EXTRACT_32BITS(&dp->icmp6_pptr))); break; case ICMP6_PARAMPROB_OPTION: ND_PRINT((ndo,", option - octet %u", EXTRACT_32BITS(&dp->icmp6_pptr))); break; default: ND_PRINT((ndo,", code-#%d", dp->icmp6_code)); break; } break; case ICMP6_ECHO_REQUEST: case ICMP6_ECHO_REPLY: ND_TCHECK(dp->icmp6_seq); ND_PRINT((ndo,", seq %u", EXTRACT_16BITS(&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((ndo," v2")); mldv2_query_print(ndo, (const u_char *)dp, length); } else { ND_PRINT((ndo," 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) { icmp6_opt_print(ndo, (const u_char *)dp + RTSOLLEN, length - RTSOLLEN); } break; case ND_ROUTER_ADVERT: #define RTADVLEN 16 if (ndo->ndo_vflag) { struct nd_router_advert *p; p = (struct nd_router_advert *)dp; ND_TCHECK(p->nd_ra_retransmit); ND_PRINT((ndo,"\n\thop limit %u, Flags [%s]" \ ", pref %s, router lifetime %us, reachable time %us, retrans time %us", (u_int)p->nd_ra_curhoplimit, bittok2str(icmp6_opt_ra_flag_values,"none",(p->nd_ra_flags_reserved)), get_rtpref(p->nd_ra_flags_reserved), EXTRACT_16BITS(&p->nd_ra_router_lifetime), EXTRACT_32BITS(&p->nd_ra_reachable), EXTRACT_32BITS(&p->nd_ra_retransmit))); icmp6_opt_print(ndo, (const u_char *)dp + RTADVLEN, length - RTADVLEN); } break; case ND_NEIGHBOR_SOLICIT: { struct nd_neighbor_solicit *p; p = (struct nd_neighbor_solicit *)dp; ND_TCHECK(p->nd_ns_target); ND_PRINT((ndo,", who has %s", ip6addr_string(ndo, &p->nd_ns_target))); if (ndo->ndo_vflag) { #define NDSOLLEN 24 icmp6_opt_print(ndo, (const u_char *)dp + NDSOLLEN, length - NDSOLLEN); } } break; case ND_NEIGHBOR_ADVERT: { struct nd_neighbor_advert *p; p = (struct nd_neighbor_advert *)dp; ND_TCHECK(p->nd_na_target); ND_PRINT((ndo,", tgt is %s", ip6addr_string(ndo, &p->nd_na_target))); if (ndo->ndo_vflag) { ND_PRINT((ndo,", Flags [%s]", bittok2str(icmp6_nd_na_flag_values, "none", EXTRACT_32BITS(&p->nd_na_flags_reserved)))); #define NDADVLEN 24 icmp6_opt_print(ndo, (const u_char *)dp + NDADVLEN, length - NDADVLEN); #undef NDADVLEN } } break; case ND_REDIRECT: #define RDR(i) ((struct nd_redirect *)(i)) ND_TCHECK(RDR(dp)->nd_rd_dst); ND_PRINT((ndo,", %s", getname6(ndo, (const u_char *)&RDR(dp)->nd_rd_dst))); ND_TCHECK(RDR(dp)->nd_rd_target); ND_PRINT((ndo," to %s", getname6(ndo, (const u_char*)&RDR(dp)->nd_rd_target))); #define REDIRECTLEN 40 if (ndo->ndo_vflag) { icmp6_opt_print(ndo, (const u_char *)dp + REDIRECTLEN, length - REDIRECTLEN); } break; #undef REDIRECTLEN #undef RDR 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_TCHECK(dp->icmp6_data16[0]); ND_PRINT((ndo,", id 0x%04x", EXTRACT_16BITS(&dp->icmp6_data16[0]))); break; case ICMP6_HADISCOV_REPLY: if (ndo->ndo_vflag) { struct in6_addr *in6; u_char *cp; ND_TCHECK(dp->icmp6_data16[0]); ND_PRINT((ndo,", id 0x%04x", EXTRACT_16BITS(&dp->icmp6_data16[0]))); cp = (u_char *)dp + length; in6 = (struct in6_addr *)(dp + 1); for (; (u_char *)in6 < cp; in6++) { ND_TCHECK(*in6); ND_PRINT((ndo,", %s", ip6addr_string(ndo, in6))); } } break; case ICMP6_MOBILEPREFIX_ADVERT: if (ndo->ndo_vflag) { ND_TCHECK(dp->icmp6_data16[0]); ND_PRINT((ndo,", id 0x%04x", EXTRACT_16BITS(&dp->icmp6_data16[0]))); if (dp->icmp6_data16[1] & 0xc0) ND_PRINT((ndo," ")); if (dp->icmp6_data16[1] & 0x80) ND_PRINT((ndo,"M")); if (dp->icmp6_data16[1] & 0x40) ND_PRINT((ndo,"O")); #define MPADVLEN 8 icmp6_opt_print(ndo, (const u_char *)dp + MPADVLEN, length - MPADVLEN); } break; case ND_RPL_MESSAGE: /* plus 4, because struct icmp6_hdr contains 4 bytes of icmp payload */ rpl_print(ndo, dp, &dp->icmp6_data8[0], length-sizeof(struct icmp6_hdr)+4); break; default: ND_PRINT((ndo,", length %u", length)); if (ndo->ndo_vflag <= 1) print_unknown_data(ndo, bp,"\n\t", length); return; } if (!ndo->ndo_vflag) ND_PRINT((ndo,", length %u", length)); return; trunc: ND_PRINT((ndo, "[|icmp6]")); } 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 = (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(ip6->ip6_nxt)) return NULL; nh = ip6->ip6_nxt; hlen = sizeof(struct ip6_hdr); while (bp < ep) { bp += hlen; switch(nh) { case IPPROTO_UDP: case IPPROTO_TCP: uh = (struct udphdr *)bp; if (ND_TTEST(uh->uh_dport)) { *prot = nh; return(uh); } else return(NULL); /* NOTREACHED */ case IPPROTO_HOPOPTS: case IPPROTO_DSTOPTS: case IPPROTO_ROUTING: hbh = (struct ip6_hbh *)bp; if (!ND_TTEST(hbh->ip6h_len)) return(NULL); nh = hbh->ip6h_nxt; hlen = (hbh->ip6h_len + 1) << 3; break; case IPPROTO_FRAGMENT: /* this should be odd, but try anyway */ fragh = (struct ip6_frag *)bp; if (!ND_TTEST(fragh->ip6f_offlg)) return(NULL); /* fragments with non-zero offset are meaningless */ if ((EXTRACT_16BITS(&fragh->ip6f_offlg) & IP6F_OFF_MASK) != 0) return(NULL); nh = fragh->ip6f_nxt; hlen = sizeof(struct ip6_frag); break; case IPPROTO_AH: ah = (struct ah *)bp; if (!ND_TTEST(ah->ah_len)) return(NULL); nh = ah->ah_nxt; hlen = (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 void icmp6_opt_print(netdissect_options *ndo, const u_char *bp, int resid) { const struct nd_opt_hdr *op; 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; struct in6_addr in6, *in6p; size_t l; u_int i; #define ECHECK(var) if ((u_char *)&(var) > ep - sizeof(var)) return cp = bp; /* 'ep' points to the end of available data. */ ep = ndo->ndo_snapend; while (cp < ep) { op = (struct nd_opt_hdr *)cp; ECHECK(op->nd_opt_len); if (resid <= 0) return; if (op->nd_opt_len == 0) goto trunc; if (cp + (op->nd_opt_len << 3) > ep) goto trunc; ND_PRINT((ndo,"\n\t %s option (%u), length %u (%u): ", tok2str(icmp6_opt_values, "unknown", op->nd_opt_type), op->nd_opt_type, op->nd_opt_len << 3, op->nd_opt_len)); switch (op->nd_opt_type) { case ND_OPT_SOURCE_LINKADDR: l = (op->nd_opt_len << 3) - 2; print_lladdr(ndo, cp + 2, l); break; case ND_OPT_TARGET_LINKADDR: l = (op->nd_opt_len << 3) - 2; print_lladdr(ndo, cp + 2, l); break; case ND_OPT_PREFIX_INFORMATION: opp = (struct nd_opt_prefix_info *)op; ND_TCHECK(opp->nd_opt_pi_prefix); ND_PRINT((ndo,"%s/%u%s, Flags [%s], valid time %s", ip6addr_string(ndo, &opp->nd_opt_pi_prefix), opp->nd_opt_pi_prefix_len, (op->nd_opt_len != 4) ? "badlen" : "", bittok2str(icmp6_opt_pi_flag_values, "none", opp->nd_opt_pi_flags_reserved), get_lifetime(EXTRACT_32BITS(&opp->nd_opt_pi_valid_time)))); ND_PRINT((ndo,", pref. time %s", get_lifetime(EXTRACT_32BITS(&opp->nd_opt_pi_preferred_time)))); break; case ND_OPT_REDIRECTED_HEADER: print_unknown_data(ndo, bp,"\n\t ",op->nd_opt_len<<3); /* xxx */ break; case ND_OPT_MTU: opm = (struct nd_opt_mtu *)op; ND_TCHECK(opm->nd_opt_mtu_mtu); ND_PRINT((ndo," %u%s", EXTRACT_32BITS(&opm->nd_opt_mtu_mtu), (op->nd_opt_len != 1) ? "bad option length" : "" )); break; case ND_OPT_RDNSS: oprd = (struct nd_opt_rdnss *)op; l = (op->nd_opt_len - 1) / 2; ND_PRINT((ndo," lifetime %us,", EXTRACT_32BITS(&oprd->nd_opt_rdnss_lifetime))); for (i = 0; i < l; i++) { ND_TCHECK(oprd->nd_opt_rdnss_addr[i]); ND_PRINT((ndo," addr: %s", ip6addr_string(ndo, &oprd->nd_opt_rdnss_addr[i]))); } break; case ND_OPT_DNSSL: opds = (struct nd_opt_dnssl *)op; ND_PRINT((ndo," lifetime %us, domain(s):", EXTRACT_32BITS(&opds->nd_opt_dnssl_lifetime))); domp = cp + 8; /* domain names, variable-sized, RFC1035-encoded */ while (domp < cp + (op->nd_opt_len << 3) && *domp != '\0') { ND_PRINT((ndo, " ")); if ((domp = ns_nprint (ndo, domp, bp)) == NULL) goto trunc; } break; case ND_OPT_ADVINTERVAL: opa = (struct nd_opt_advinterval *)op; ND_TCHECK(opa->nd_opt_adv_interval); ND_PRINT((ndo," %ums", EXTRACT_32BITS(&opa->nd_opt_adv_interval))); break; case ND_OPT_HOMEAGENT_INFO: oph = (struct nd_opt_homeagent_info *)op; ND_TCHECK(oph->nd_opt_hai_lifetime); ND_PRINT((ndo," preference %u, lifetime %u", EXTRACT_16BITS(&oph->nd_opt_hai_preference), EXTRACT_16BITS(&oph->nd_opt_hai_lifetime))); break; case ND_OPT_ROUTE_INFO: opri = (struct nd_opt_route_info *)op; ND_TCHECK(opri->nd_opt_rti_lifetime); memset(&in6, 0, sizeof(in6)); in6p = (struct in6_addr *)(opri + 1); switch (op->nd_opt_len) { case 1: break; case 2: ND_TCHECK2(*in6p, 8); memcpy(&in6, opri + 1, 8); break; case 3: ND_TCHECK(*in6p); memcpy(&in6, opri + 1, sizeof(in6)); break; default: goto trunc; } ND_PRINT((ndo," %s/%u", ip6addr_string(ndo, &in6), opri->nd_opt_rti_prefixlen)); ND_PRINT((ndo,", pref=%s", get_rtpref(opri->nd_opt_rti_flags))); ND_PRINT((ndo,", lifetime=%s", get_lifetime(EXTRACT_32BITS(&opri->nd_opt_rti_lifetime)))); break; default: if (ndo->ndo_vflag <= 1) { print_unknown_data(ndo,cp+2,"\n\t ", (op->nd_opt_len << 3) - 2); /* skip option header */ return; } break; } /* do we want to see an additional hexdump ? */ if (ndo->ndo_vflag> 1) print_unknown_data(ndo, cp+2,"\n\t ", (op->nd_opt_len << 3) - 2); /* skip option header */ cp += op->nd_opt_len << 3; resid -= op->nd_opt_len << 3; } return; trunc: ND_PRINT((ndo, "[ndp opt]")); return; #undef ECHECK } static void mld6_print(netdissect_options *ndo, const u_char *bp) { const struct mld6_hdr *mp = (struct mld6_hdr *)bp; const u_char *ep; /* 'ep' points to the end of available data. */ ep = ndo->ndo_snapend; if ((u_char *)mp + sizeof(*mp) > ep) return; ND_PRINT((ndo,"max resp delay: %d ", EXTRACT_16BITS(&mp->mld6_maxdelay))); ND_PRINT((ndo,"addr: %s", ip6addr_string(ndo, &mp->mld6_addr))); } static void mldv2_report_print(netdissect_options *ndo, const u_char *bp, u_int len) { struct icmp6_hdr *icp = (struct icmp6_hdr *) bp; u_int group, nsrcs, ngroups; u_int i, j; /* Minimum len is 8 */ if (len < 8) { ND_PRINT((ndo," [invalid len %d]", len)); return; } ND_TCHECK(icp->icmp6_data16[1]); ngroups = EXTRACT_16BITS(&icp->icmp6_data16[1]); ND_PRINT((ndo,", %d 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((ndo," [invalid number of groups]")); return; } ND_TCHECK2(bp[group + 4], sizeof(struct in6_addr)); ND_PRINT((ndo," [gaddr %s", ip6addr_string(ndo, &bp[group + 4]))); ND_PRINT((ndo," %s", tok2str(mldv2report2str, " [v2-report-#%d]", bp[group]))); nsrcs = (bp[group + 2] << 8) + bp[group + 3]; /* Check the number of sources and print them */ if (len < group + 20 + (nsrcs * sizeof(struct in6_addr))) { ND_PRINT((ndo," [invalid number of sources %d]", nsrcs)); return; } if (ndo->ndo_vflag == 1) ND_PRINT((ndo,", %d source(s)", nsrcs)); else { /* Print the sources */ ND_PRINT((ndo," {")); for (j = 0; j < nsrcs; j++) { ND_TCHECK2(bp[group + 20 + j * sizeof(struct in6_addr)], sizeof(struct in6_addr)); ND_PRINT((ndo," %s", ip6addr_string(ndo, &bp[group + 20 + j * sizeof(struct in6_addr)]))); } ND_PRINT((ndo," }")); } /* Next group record */ group += 20 + nsrcs * sizeof(struct in6_addr); ND_PRINT((ndo,"]")); } } return; trunc: ND_PRINT((ndo,"[|icmp6]")); return; } static void mldv2_query_print(netdissect_options *ndo, const u_char *bp, u_int len) { struct icmp6_hdr *icp = (struct icmp6_hdr *) bp; u_int mrc; int mrt, qqi; u_int nsrcs; register u_int i; /* Minimum len is 28 */ if (len < 28) { ND_PRINT((ndo," [invalid len %d]", len)); return; } ND_TCHECK(icp->icmp6_data16[0]); mrc = EXTRACT_16BITS(&icp->icmp6_data16[0]); if (mrc < 32768) { mrt = mrc; } else { mrt = ((mrc & 0x0fff) | 0x1000) << (((mrc & 0x7000) >> 12) + 3); } if (ndo->ndo_vflag) { ND_PRINT((ndo," [max resp delay=%d]", mrt)); } ND_TCHECK2(bp[8], sizeof(struct in6_addr)); ND_PRINT((ndo," [gaddr %s", ip6addr_string(ndo, &bp[8]))); if (ndo->ndo_vflag) { ND_TCHECK(bp[25]); if (bp[24] & 0x08) { ND_PRINT((ndo," sflag")); } if (bp[24] & 0x07) { ND_PRINT((ndo," robustness=%d", bp[24] & 0x07)); } if (bp[25] < 128) { qqi = bp[25]; } else { qqi = ((bp[25] & 0x0f) | 0x10) << (((bp[25] & 0x70) >> 4) + 3); } ND_PRINT((ndo," qqi=%d", qqi)); } ND_TCHECK2(bp[26], 2); nsrcs = EXTRACT_16BITS(&bp[26]); if (nsrcs > 0) { if (len < 28 + nsrcs * sizeof(struct in6_addr)) ND_PRINT((ndo," [invalid number of sources]")); else if (ndo->ndo_vflag > 1) { ND_PRINT((ndo," {")); for (i = 0; i < nsrcs; i++) { ND_TCHECK2(bp[28 + i * sizeof(struct in6_addr)], sizeof(struct in6_addr)); ND_PRINT((ndo," %s", ip6addr_string(ndo, &bp[28 + i * sizeof(struct in6_addr)]))); } ND_PRINT((ndo," }")); } else ND_PRINT((ndo,", %d source(s)", nsrcs)); } ND_PRINT((ndo,"]")); return; trunc: ND_PRINT((ndo,"[|icmp6]")); return; } static void dnsname_print(netdissect_options *ndo, const u_char *cp, const u_char *ep) { int i; /* DNS name decoding - no decompression */ ND_PRINT((ndo,", \"")); while (cp < ep) { i = *cp++; if (i) { if (i > ep - cp) { ND_PRINT((ndo,"???")); break; } while (i-- && cp < ep) { safeputchar(ndo, *cp); cp++; } if (cp + 1 < ep && *cp) ND_PRINT((ndo,".")); } else { if (cp == ep) { /* FQDN */ ND_PRINT((ndo,".")); } else if (cp + 1 == ep && *cp == '\0') { /* truncated */ } else { /* invalid */ ND_PRINT((ndo,"???")); } break; } } ND_PRINT((ndo,"\"")); } 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 = (struct icmp6_hdr *)bp; ni6 = (struct icmp6_nodeinfo *)bp; siz = ep - bp; switch (ni6->ni_type) { case ICMP6_NI_QUERY: if (siz == sizeof(*dp) + 4) { /* KAME who-are-you */ ND_PRINT((ndo," who-are-you request")); break; } ND_PRINT((ndo," node information query")); ND_TCHECK2(*dp, sizeof(*ni6)); ni6 = (struct icmp6_nodeinfo *)dp; ND_PRINT((ndo," (")); /*)*/ switch (EXTRACT_16BITS(&ni6->ni_qtype)) { case NI_QTYPE_NOOP: ND_PRINT((ndo,"noop")); break; case NI_QTYPE_SUPTYPES: ND_PRINT((ndo,"supported qtypes")); i = EXTRACT_16BITS(&ni6->ni_flags); if (i) ND_PRINT((ndo," [%s]", (i & 0x01) ? "C" : "")); break; case NI_QTYPE_FQDN: ND_PRINT((ndo,"DNS name")); break; case NI_QTYPE_NODEADDR: ND_PRINT((ndo,"node addresses")); i = ni6->ni_flags; if (!i) break; /* NI_NODEADDR_FLAG_TRUNCATE undefined for query */ ND_PRINT((ndo," [%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((ndo,"unknown")); break; } if (ni6->ni_qtype == NI_QTYPE_NOOP || ni6->ni_qtype == NI_QTYPE_SUPTYPES) { if (siz != sizeof(*ni6)) if (ndo->ndo_vflag) ND_PRINT((ndo,", invalid len")); /*(*/ ND_PRINT((ndo,")")); break; } /* XXX backward compat, icmp-name-lookup-03 */ if (siz == sizeof(*ni6)) { ND_PRINT((ndo,", 03 draft")); /*(*/ ND_PRINT((ndo,")")); break; } switch (ni6->ni_code) { case ICMP6_NI_SUBJ_IPV6: if (!ND_TTEST2(*dp, sizeof(*ni6) + sizeof(struct in6_addr))) break; if (siz != sizeof(*ni6) + sizeof(struct in6_addr)) { if (ndo->ndo_vflag) ND_PRINT((ndo,", invalid subject len")); break; } ND_PRINT((ndo,", subject=%s", getname6(ndo, (const u_char *)(ni6 + 1)))); break; case ICMP6_NI_SUBJ_FQDN: ND_PRINT((ndo,", subject=DNS name")); cp = (const u_char *)(ni6 + 1); if (cp[0] == ep - cp - 1) { /* icmp-name-lookup-03, pascal string */ if (ndo->ndo_vflag) ND_PRINT((ndo,", 03 draft")); cp++; ND_PRINT((ndo,", \"")); while (cp < ep) { safeputchar(ndo, *cp); cp++; } ND_PRINT((ndo,"\"")); } else dnsname_print(ndo, cp, ep); break; case ICMP6_NI_SUBJ_IPV4: if (!ND_TTEST2(*dp, sizeof(*ni6) + sizeof(struct in_addr))) break; if (siz != sizeof(*ni6) + sizeof(struct in_addr)) { if (ndo->ndo_vflag) ND_PRINT((ndo,", invalid subject len")); break; } ND_PRINT((ndo,", subject=%s", getname(ndo, (const u_char *)(ni6 + 1)))); break; default: ND_PRINT((ndo,", unknown subject")); break; } /*(*/ ND_PRINT((ndo,")")); break; case ICMP6_NI_REPLY: if (icmp6len > siz) { ND_PRINT((ndo,"[|icmp6: node information reply]")); break; } needcomma = 0; ni6 = (struct icmp6_nodeinfo *)dp; ND_PRINT((ndo," node information reply")); ND_PRINT((ndo," (")); /*)*/ switch (ni6->ni_code) { case ICMP6_NI_SUCCESS: if (ndo->ndo_vflag) { ND_PRINT((ndo,"success")); needcomma++; } break; case ICMP6_NI_REFUSED: ND_PRINT((ndo,"refused")); needcomma++; if (siz != sizeof(*ni6)) if (ndo->ndo_vflag) ND_PRINT((ndo,", invalid length")); break; case ICMP6_NI_UNKNOWN: ND_PRINT((ndo,"unknown")); needcomma++; if (siz != sizeof(*ni6)) if (ndo->ndo_vflag) ND_PRINT((ndo,", invalid length")); break; } if (ni6->ni_code != ICMP6_NI_SUCCESS) { /*(*/ ND_PRINT((ndo,")")); break; } switch (EXTRACT_16BITS(&ni6->ni_qtype)) { case NI_QTYPE_NOOP: if (needcomma) ND_PRINT((ndo,", ")); ND_PRINT((ndo,"noop")); if (siz != sizeof(*ni6)) if (ndo->ndo_vflag) ND_PRINT((ndo,", invalid length")); break; case NI_QTYPE_SUPTYPES: if (needcomma) ND_PRINT((ndo,", ")); ND_PRINT((ndo,"supported qtypes")); i = EXTRACT_16BITS(&ni6->ni_flags); if (i) ND_PRINT((ndo," [%s]", (i & 0x01) ? "C" : "")); break; case NI_QTYPE_FQDN: if (needcomma) ND_PRINT((ndo,", ")); ND_PRINT((ndo,"DNS name")); cp = (const u_char *)(ni6 + 1) + 4; if (cp[0] == ep - cp - 1) { /* icmp-name-lookup-03, pascal string */ if (ndo->ndo_vflag) ND_PRINT((ndo,", 03 draft")); cp++; ND_PRINT((ndo,", \"")); while (cp < ep) { safeputchar(ndo, *cp); cp++; } ND_PRINT((ndo,"\"")); } else dnsname_print(ndo, cp, ep); if ((EXTRACT_16BITS(&ni6->ni_flags) & 0x01) != 0) ND_PRINT((ndo," [TTL=%u]", *(uint32_t *)(ni6 + 1))); break; case NI_QTYPE_NODEADDR: if (needcomma) ND_PRINT((ndo,", ")); ND_PRINT((ndo,"node addresses")); i = sizeof(*ni6); while (i < siz) { if (i + sizeof(struct in6_addr) + sizeof(int32_t) > siz) break; ND_PRINT((ndo," %s", getname6(ndo, bp + i))); i += sizeof(struct in6_addr); ND_PRINT((ndo,"(%d)", (int32_t)EXTRACT_32BITS(bp + i))); i += sizeof(int32_t); } i = ni6->ni_flags; if (!i) break; ND_PRINT((ndo," [%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((ndo,", ")); ND_PRINT((ndo,"unknown")); break; } /*(*/ ND_PRINT((ndo,")")); break; } return; trunc: ND_PRINT((ndo, "[|icmp6]")); } 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; struct rr_pco_match *match; struct rr_pco_use *use; char hbuf[NI_MAXHOST]; int n; if (ep < bp) return; rr6 = (struct icmp6_router_renum *)bp; cp = (const char *)(rr6 + 1); ND_TCHECK(rr6->rr_reserved); switch (rr6->rr_code) { case ICMP6_ROUTER_RENUMBERING_COMMAND: ND_PRINT((ndo,"router renum: command")); break; case ICMP6_ROUTER_RENUMBERING_RESULT: ND_PRINT((ndo,"router renum: result")); break; case ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET: ND_PRINT((ndo,"router renum: sequence number reset")); break; default: ND_PRINT((ndo,"router renum: code-#%d", rr6->rr_code)); break; } ND_PRINT((ndo,", seq=%u", EXTRACT_32BITS(&rr6->rr_seqnum))); if (ndo->ndo_vflag) { #define F(x, y) ((rr6->rr_flags) & (x) ? (y) : "") ND_PRINT((ndo,"[")); /*]*/ if (rr6->rr_flags) { ND_PRINT((ndo,"%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((ndo,"seg=%u,", rr6->rr_segnum)); ND_PRINT((ndo,"maxdelay=%u", EXTRACT_16BITS(&rr6->rr_maxdelay))); if (rr6->rr_reserved) ND_PRINT((ndo,"rsvd=0x%x", EXTRACT_32BITS(&rr6->rr_reserved))); /*[*/ ND_PRINT((ndo,"]")); #undef F } if (rr6->rr_code == ICMP6_ROUTER_RENUMBERING_COMMAND) { match = (struct rr_pco_match *)cp; cp = (const char *)(match + 1); ND_TCHECK(match->rpm_prefix); if (ndo->ndo_vflag > 1) ND_PRINT((ndo,"\n\t")); else ND_PRINT((ndo," ")); ND_PRINT((ndo,"match(")); /*)*/ switch (match->rpm_code) { case RPM_PCO_ADD: ND_PRINT((ndo,"add")); break; case RPM_PCO_CHANGE: ND_PRINT((ndo,"change")); break; case RPM_PCO_SETGLOBAL: ND_PRINT((ndo,"setglobal")); break; default: ND_PRINT((ndo,"#%u", match->rpm_code)); break; } if (ndo->ndo_vflag) { ND_PRINT((ndo,",ord=%u", match->rpm_ordinal)); ND_PRINT((ndo,",min=%u", match->rpm_minlen)); ND_PRINT((ndo,",max=%u", match->rpm_maxlen)); } if (inet_ntop(AF_INET6, &match->rpm_prefix, hbuf, sizeof(hbuf))) ND_PRINT((ndo,",%s/%u", hbuf, match->rpm_matchlen)); else ND_PRINT((ndo,",?/%u", match->rpm_matchlen)); /*(*/ ND_PRINT((ndo,")")); n = match->rpm_len - 3; if (n % 4) goto trunc; n /= 4; while (n-- > 0) { use = (struct rr_pco_use *)cp; cp = (const char *)(use + 1); ND_TCHECK(use->rpu_prefix); if (ndo->ndo_vflag > 1) ND_PRINT((ndo,"\n\t")); else ND_PRINT((ndo," ")); ND_PRINT((ndo,"use(")); /*)*/ if (use->rpu_flags) { #define F(x, y) ((use->rpu_flags) & (x) ? (y) : "") ND_PRINT((ndo,"%s%s,", F(ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME, "V"), F(ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME, "P"))); #undef F } if (ndo->ndo_vflag) { ND_PRINT((ndo,"mask=0x%x,", use->rpu_ramask)); ND_PRINT((ndo,"raflags=0x%x,", use->rpu_raflags)); if (~use->rpu_vltime == 0) ND_PRINT((ndo,"vltime=infty,")); else ND_PRINT((ndo,"vltime=%u,", EXTRACT_32BITS(&use->rpu_vltime))); if (~use->rpu_pltime == 0) ND_PRINT((ndo,"pltime=infty,")); else ND_PRINT((ndo,"pltime=%u,", EXTRACT_32BITS(&use->rpu_pltime))); } if (inet_ntop(AF_INET6, &use->rpu_prefix, hbuf, sizeof(hbuf))) ND_PRINT((ndo,"%s/%u/%u", hbuf, use->rpu_uselen, use->rpu_keeplen)); else ND_PRINT((ndo,"?/%u/%u", use->rpu_uselen, use->rpu_keeplen)); /*(*/ ND_PRINT((ndo,")")); } } return; trunc: ND_PRINT((ndo,"[|icmp6]")); } #endif /* INET6 */ /* * Local Variables: * c-style: whitesmith * c-basic-offset: 8 * End: */ Index: head/contrib/tcpdump/print-ip.c =================================================================== --- head/contrib/tcpdump/print-ip.c (revision 285274) +++ head/contrib/tcpdump/print-ip.c (revision 285275) @@ -1,717 +1,714 @@ /* * 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. * * $FreeBSD$ */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "interface.h" #include "addrtoname.h" #include "extract.h" /* must come after interface.h */ #include "ip.h" #include "ipproto.h" static const char tstr[] = "[|ip]"; 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 void ip_printroute(netdissect_options *ndo, register const u_char *cp, u_int length) { register u_int ptr; register u_int len; if (length < 3) { ND_PRINT((ndo, " [bad length %u]", length)); return; } if ((length + 1) & 3) ND_PRINT((ndo, " [bad length %u]", length)); ptr = cp[2] - 1; if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1) ND_PRINT((ndo, " [bad ptr %u]", cp[2])); for (len = 3; len < length; len += 4) { ND_PRINT((ndo, " %s", ipaddr_string(ndo, &cp[len]))); if (ptr > len) ND_PRINT((ndo, ",")); } } /* * 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) { int length; int len; const u_char *cp; uint32_t retval; cp = (const u_char *)(ip + 1); length = (IP_HL(ip) << 2) - sizeof(struct ip); for (; length > 0; cp += len, length -= len) { int tt; ND_TCHECK(*cp); tt = *cp; if (tt == IPOPT_EOL) break; else if (tt == IPOPT_NOP) len = 1; else { ND_TCHECK(cp[1]); len = cp[1]; if (len < 2) break; } ND_TCHECK2(*cp, len); switch (tt) { case IPOPT_SSRR: case IPOPT_LSRR: if (len < 7) break; UNALIGNED_MEMCPY(&retval, cp + len - 4, 4); return retval; } } trunc: UNALIGNED_MEMCPY(&retval, &ip->ip_dst.s_addr, sizeof(uint32_t)); return retval; } /* * Compute a V4-style checksum by building a pseudoheader. */ int nextproto4_cksum(netdissect_options *ndo, const struct ip *ip, const uint8_t *data, u_int len, u_int covlen, u_int next_proto) { struct phdr { uint32_t src; uint32_t dst; u_char mbz; u_char 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; UNALIGNED_MEMCPY(&ph.src, &ip->ip_src.s_addr, sizeof(uint32_t)); if (IP_HL(ip) == 5) UNALIGNED_MEMCPY(&ph.dst, &ip->ip_dst.s_addr, sizeof(uint32_t)); 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 void ip_printts(netdissect_options *ndo, register const u_char *cp, u_int length) { register u_int ptr; register u_int len; int hoplen; const char *type; if (length < 4) { ND_PRINT((ndo, "[bad length %u]", length)); return; } ND_PRINT((ndo, " TS{")); hoplen = ((cp[3]&0xF) != IPOPT_TS_TSONLY) ? 8 : 4; if ((length - 4) & (hoplen-1)) ND_PRINT((ndo, "[bad length %u]", length)); ptr = cp[2] - 1; len = 0; if (ptr < 4 || ((ptr - 4) & (hoplen-1)) || ptr > length + 1) ND_PRINT((ndo, "[bad ptr %u]", cp[2])); switch (cp[3]&0xF) { case IPOPT_TS_TSONLY: ND_PRINT((ndo, "TSONLY")); break; case IPOPT_TS_TSANDADDR: ND_PRINT((ndo, "TS+ADDR")); break; /* * prespecified should really be 3, but some ones might send 2 * instead, and the IPOPT_TS_PRESPEC constant can apparently * have both values, so we have to hard-code it here. */ case 2: ND_PRINT((ndo, "PRESPEC2.0")); break; case 3: /* IPOPT_TS_PRESPEC */ ND_PRINT((ndo, "PRESPEC")); break; default: ND_PRINT((ndo, "[bad ts type %d]", cp[3]&0xF)); goto done; } type = " "; for (len = 4; len < length; len += hoplen) { if (ptr == len) type = " ^ "; ND_PRINT((ndo, "%s%d@%s", type, EXTRACT_32BITS(&cp[len+hoplen-4]), hoplen!=8 ? "" : ipaddr_string(ndo, &cp[len]))); type = " "; } done: ND_PRINT((ndo, "%s", ptr == len ? " ^ " : "")); if (cp[3]>>4) ND_PRINT((ndo, " [%d hops not recorded]} ", cp[3]>>4)); else ND_PRINT((ndo, "}")); } /* * print IP options. */ static void ip_optprint(netdissect_options *ndo, register const u_char *cp, u_int length) { register u_int option_len; const char *sep = ""; for (; length > 0; cp += option_len, length -= option_len) { u_int option_code; ND_PRINT((ndo, "%s", sep)); sep = ","; ND_TCHECK(*cp); option_code = *cp; ND_PRINT((ndo, "%s", tok2str(ip_option_values,"unknown %u",option_code))); if (option_code == IPOPT_NOP || option_code == IPOPT_EOL) option_len = 1; else { ND_TCHECK(cp[1]); option_len = cp[1]; if (option_len < 2) { ND_PRINT((ndo, " [bad length %u]", option_len)); return; } } if (option_len > length) { ND_PRINT((ndo, " [bad length %u]", option_len)); return; } ND_TCHECK2(*cp, option_len); switch (option_code) { case IPOPT_EOL: return; case IPOPT_TS: ip_printts(ndo, cp, option_len); break; case IPOPT_RR: /* fall through */ case IPOPT_SSRR: case IPOPT_LSRR: ip_printroute(ndo, cp, option_len); break; case IPOPT_RA: if (option_len < 4) { ND_PRINT((ndo, " [bad length %u]", option_len)); break; } ND_TCHECK(cp[3]); if (EXTRACT_16BITS(&cp[2]) != 0) ND_PRINT((ndo, " value %u", EXTRACT_16BITS(&cp[2]))); break; case IPOPT_NOP: /* nothing to print - fall through */ case IPOPT_SECURITY: default: break; } } return; trunc: ND_PRINT((ndo, "%s", tstr)); } #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 } }; struct ip_print_demux_state { const struct ip *ip; const u_char *cp; u_int len, off; u_char nh; int advance; }; static void ip_print_demux(netdissect_options *ndo, struct ip_print_demux_state *ipds) { struct protoent *proto; struct cksum_vec vec[1]; again: switch (ipds->nh) { case IPPROTO_AH: ipds->nh = *ipds->cp; ipds->advance = ah_print(ndo, ipds->cp); if (ipds->advance <= 0) break; ipds->cp += ipds->advance; ipds->len -= ipds->advance; goto again; case IPPROTO_ESP: { int enh, padlen; ipds->advance = esp_print(ndo, ipds->cp, ipds->len, (const u_char *)ipds->ip, &enh, &padlen); if (ipds->advance <= 0) break; ipds->cp += ipds->advance; ipds->len -= ipds->advance + padlen; ipds->nh = enh & 0xff; goto again; } case IPPROTO_IPCOMP: { int enh; ipds->advance = ipcomp_print(ndo, ipds->cp, &enh); if (ipds->advance <= 0) break; ipds->cp += ipds->advance; ipds->len -= ipds->advance; ipds->nh = enh & 0xff; goto again; } case IPPROTO_SCTP: sctp_print(ndo, ipds->cp, (const u_char *)ipds->ip, ipds->len); break; case IPPROTO_DCCP: dccp_print(ndo, ipds->cp, (const u_char *)ipds->ip, ipds->len); break; case IPPROTO_TCP: /* pass on the MF bit plus the offset to detect fragments */ tcp_print(ndo, ipds->cp, ipds->len, (const u_char *)ipds->ip, ipds->off & (IP_MF|IP_OFFMASK)); break; case IPPROTO_UDP: /* pass on the MF bit plus the offset to detect fragments */ udp_print(ndo, ipds->cp, ipds->len, (const u_char *)ipds->ip, ipds->off & (IP_MF|IP_OFFMASK)); break; case IPPROTO_ICMP: /* pass on the MF bit plus the offset to detect fragments */ icmp_print(ndo, ipds->cp, ipds->len, (const u_char *)ipds->ip, ipds->off & (IP_MF|IP_OFFMASK)); 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 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, ipds->cp, ipds->len); break; case IPPROTO_EIGRP: eigrp_print(ndo, ipds->cp, ipds->len); break; case IPPROTO_ND: ND_PRINT((ndo, " nd %d", ipds->len)); break; case IPPROTO_EGP: egp_print(ndo, ipds->cp, ipds->len); break; case IPPROTO_OSPF: ospf_print(ndo, ipds->cp, ipds->len, (const u_char *)ipds->ip); break; case IPPROTO_IGMP: igmp_print(ndo, ipds->cp, ipds->len); break; case IPPROTO_IPV4: /* DVMRP multicast tunnel (ip-in-ip encapsulation) */ ip_print(ndo, ipds->cp, ipds->len); if (! ndo->ndo_vflag) { ND_PRINT((ndo, " (ipip-proto-4)")); return; } break; -#ifdef INET6 case IPPROTO_IPV6: /* ip6-in-ip encapsulation */ ip6_print(ndo, ipds->cp, ipds->len); break; -#endif /*INET6*/ case IPPROTO_RSVP: rsvp_print(ndo, ipds->cp, ipds->len); break; case IPPROTO_GRE: /* do it */ gre_print(ndo, ipds->cp, ipds->len); break; case IPPROTO_MOBILE: mobile_print(ndo, ipds->cp, ipds->len); break; case IPPROTO_PIM: vec[0].ptr = ipds->cp; vec[0].len = ipds->len; pim_print(ndo, ipds->cp, ipds->len, in_cksum(vec, 1)); break; case IPPROTO_VRRP: if (ndo->ndo_packettype == PT_CARP) { if (ndo->ndo_vflag) ND_PRINT((ndo, "carp %s > %s: ", ipaddr_string(ndo, &ipds->ip->ip_src), ipaddr_string(ndo, &ipds->ip->ip_dst))); carp_print(ndo, ipds->cp, ipds->len, ipds->ip->ip_ttl); } else { if (ndo->ndo_vflag) ND_PRINT((ndo, "vrrp %s > %s: ", ipaddr_string(ndo, &ipds->ip->ip_src), ipaddr_string(ndo, &ipds->ip->ip_dst))); vrrp_print(ndo, ipds->cp, ipds->len, (const u_char *)ipds->ip, ipds->ip->ip_ttl); } break; case IPPROTO_PGM: pgm_print(ndo, ipds->cp, ipds->len, (const u_char *)ipds->ip); break; #if defined(HAVE_NET_PFVAR_H) case IPPROTO_PFSYNC: pfsync_ip_print(ndo, ipds->cp, ipds->len); break; #endif default: if (ndo->ndo_nflag==0 && (proto = getprotobynumber(ipds->nh)) != NULL) ND_PRINT((ndo, " %s", proto->p_name)); else ND_PRINT((ndo, " ip-proto-%d", ipds->nh)); ND_PRINT((ndo, " %d", ipds->len)); break; } } void ip_print_inner(netdissect_options *ndo, const u_char *bp, u_int length, u_int nh, const u_char *bp2) { struct ip_print_demux_state ipd; ipd.ip = (const struct ip *)bp2; ipd.cp = bp; ipd.len = length; ipd.off = 0; ipd.nh = nh; ipd.advance = 0; ip_print_demux(ndo, &ipd); } /* * print an IP datagram. */ void ip_print(netdissect_options *ndo, const u_char *bp, u_int length) { struct ip_print_demux_state ipd; struct ip_print_demux_state *ipds=&ipd; const u_char *ipend; u_int hlen; struct cksum_vec vec[1]; uint16_t sum, ip_sum; struct protoent *proto; ipds->ip = (const struct ip *)bp; ND_TCHECK(ipds->ip->ip_vhl); if (IP_V(ipds->ip) != 4) { /* print version if != 4 */ - ND_PRINT((ndo, "IP%u ", IP_V(ipds->ip))); if (IP_V(ipds->ip) == 6) - ND_PRINT((ndo, ", wrong link-layer encapsulation")); + ND_PRINT((ndo, "IP6, wrong link-layer encapsulation ")); + else + ND_PRINT((ndo, "IP%u ", IP_V(ipds->ip))); } else if (!ndo->ndo_eflag) ND_PRINT((ndo, "IP ")); ND_TCHECK(*ipds->ip); if (length < sizeof (struct ip)) { ND_PRINT((ndo, "truncated-ip %u", length)); return; } hlen = IP_HL(ipds->ip) * 4; if (hlen < sizeof (struct ip)) { ND_PRINT((ndo, "bad-hlen %u", hlen)); return; } ipds->len = EXTRACT_16BITS(&ipds->ip->ip_len); if (length < ipds->len) ND_PRINT((ndo, "truncated-ip - %u bytes missing! ", ipds->len - length)); if (ipds->len < hlen) { #ifdef GUESS_TSO if (ipds->len) { ND_PRINT((ndo, "bad-len %u", ipds->len)); return; } else { /* we guess that it is a TSO send */ ipds->len = length; } #else ND_PRINT((ndo, "bad-len %u", ipds->len)); return; #endif /* GUESS_TSO */ } /* * Cut off the snapshot length to the end of the IP payload. */ ipend = bp + ipds->len; if (ipend < ndo->ndo_snapend) ndo->ndo_snapend = ipend; ipds->len -= hlen; ipds->off = EXTRACT_16BITS(&ipds->ip->ip_off); if (ndo->ndo_vflag) { ND_PRINT((ndo, "(tos 0x%x", (int)ipds->ip->ip_tos)); /* ECN bits */ if (ipds->ip->ip_tos & 0x03) { switch (ipds->ip->ip_tos & 0x03) { case 1: ND_PRINT((ndo, ",ECT(1)")); break; case 2: ND_PRINT((ndo, ",ECT(0)")); break; case 3: ND_PRINT((ndo, ",CE")); } } if (ipds->ip->ip_ttl >= 1) ND_PRINT((ndo, ", ttl %u", ipds->ip->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((ndo, ", id %u, offset %u, flags [%s], proto %s (%u)", EXTRACT_16BITS(&ipds->ip->ip_id), (ipds->off & 0x1fff) * 8, bittok2str(ip_frag_values, "none", ipds->off&0xe000), tok2str(ipproto_values,"unknown",ipds->ip->ip_p), ipds->ip->ip_p)); ND_PRINT((ndo, ", length %u", EXTRACT_16BITS(&ipds->ip->ip_len))); if ((hlen - sizeof(struct ip)) > 0) { ND_PRINT((ndo, ", options (")); ip_optprint(ndo, (u_char *)(ipds->ip + 1), hlen - sizeof(struct ip)); ND_PRINT((ndo, ")")); } if (!ndo->ndo_Kflag && (u_char *)ipds->ip + hlen <= ndo->ndo_snapend) { vec[0].ptr = (const uint8_t *)(void *)ipds->ip; vec[0].len = hlen; sum = in_cksum(vec, 1); if (sum != 0) { ip_sum = EXTRACT_16BITS(&ipds->ip->ip_sum); ND_PRINT((ndo, ", bad cksum %x (->%x)!", ip_sum, in_cksum_shouldbe(ip_sum, sum))); } } ND_PRINT((ndo, ")\n ")); } /* * If this is fragment zero, hand it to the next higher * level protocol. */ if ((ipds->off & 0x1fff) == 0) { ipds->cp = (const u_char *)ipds->ip + hlen; ipds->nh = ipds->ip->ip_p; if (ipds->nh != IPPROTO_TCP && ipds->nh != IPPROTO_UDP && ipds->nh != IPPROTO_SCTP && ipds->nh != IPPROTO_DCCP) { ND_PRINT((ndo, "%s > %s: ", ipaddr_string(ndo, &ipds->ip->ip_src), ipaddr_string(ndo, &ipds->ip->ip_dst))); } ip_print_demux(ndo, ipds); } else { /* Ultra quiet now means that all this stuff should be suppressed */ if (ndo->ndo_qflag > 1) return; /* * if this isn't the first frag, we're missing the * next level protocol header. print the ip addr * and the protocol. */ if (ipds->off & 0x1fff) { ND_PRINT((ndo, "%s > %s:", ipaddr_string(ndo, &ipds->ip->ip_src), ipaddr_string(ndo, &ipds->ip->ip_dst))); if (!ndo->ndo_nflag && (proto = getprotobynumber(ipds->ip->ip_p)) != NULL) ND_PRINT((ndo, " %s", proto->p_name)); else ND_PRINT((ndo, " ip-proto-%d", ipds->ip->ip_p)); } } return; trunc: ND_PRINT((ndo, "%s", tstr)); return; } void ipN_print(netdissect_options *ndo, register const u_char *bp, register u_int length) { struct ip hdr; if (length < 4) { ND_PRINT((ndo, "truncated-ip %d", length)); return; } memcpy (&hdr, bp, 4); switch (IP_V(&hdr)) { case 4: ip_print (ndo, bp, length); return; -#ifdef INET6 case 6: ip6_print (ndo, bp, length); return; -#endif default: ND_PRINT((ndo, "unknown ip %d", IP_V(&hdr))); return; } } /* * Local Variables: * c-style: whitesmith * c-basic-offset: 8 * End: */ Index: head/contrib/tcpdump/print-ip6.c =================================================================== --- head/contrib/tcpdump/print-ip6.c (revision 285274) +++ head/contrib/tcpdump/print-ip6.c (revision 285275) @@ -1,271 +1,279 @@ /* * 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. * * $FreeBSD$ */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif -#ifdef INET6 - #include #include #include "interface.h" #include "addrtoname.h" #include "extract.h" +#ifdef INET6 + #include "ip6.h" #include "ipproto.h" /* * Compute a V6-style checksum by building a pseudoheader. */ int nextproto6_cksum(const struct ip6_hdr *ip6, const uint8_t *data, u_int len, u_int covlen, u_int next_proto) { struct { struct in6_addr ph_src; struct in6_addr ph_dst; uint32_t ph_len; uint8_t ph_zero[3]; uint8_t ph_nxt; } ph; struct cksum_vec vec[2]; /* pseudo-header */ memset(&ph, 0, sizeof(ph)); UNALIGNED_MEMCPY(&ph.ph_src, &ip6->ip6_src, sizeof (struct in6_addr)); UNALIGNED_MEMCPY(&ph.ph_dst, &ip6->ip6_dst, sizeof (struct in6_addr)); 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) { register const struct ip6_hdr *ip6; register int advance; u_int len; const u_char *ipend; register const u_char *cp; register u_int payload_len; int nh; int fragmented = 0; u_int flow; ip6 = (const struct ip6_hdr *)bp; ND_TCHECK(*ip6); if (length < sizeof (struct ip6_hdr)) { ND_PRINT((ndo, "truncated-ip6 %u", length)); return; } if (!ndo->ndo_eflag) ND_PRINT((ndo, "IP6 ")); if (IP6_VERSION(ip6) != 6) { ND_PRINT((ndo,"version error: %u != 6", IP6_VERSION(ip6))); return; } payload_len = EXTRACT_16BITS(&ip6->ip6_plen); len = payload_len + sizeof(struct ip6_hdr); if (length < len) ND_PRINT((ndo, "truncated-ip6 - %u bytes missing!", len - length)); if (ndo->ndo_vflag) { flow = EXTRACT_32BITS(&ip6->ip6_flow); ND_PRINT((ndo, "(")); #if 0 /* rfc1883 */ if (flow & 0x0f000000) ND_PRINT((ndo, "pri 0x%02x, ", (flow & 0x0f000000) >> 24)); if (flow & 0x00ffffff) ND_PRINT((ndo, "flowlabel 0x%06x, ", flow & 0x00ffffff)); #else /* RFC 2460 */ if (flow & 0x0ff00000) ND_PRINT((ndo, "class 0x%02x, ", (flow & 0x0ff00000) >> 20)); if (flow & 0x000fffff) ND_PRINT((ndo, "flowlabel 0x%05x, ", flow & 0x000fffff)); #endif ND_PRINT((ndo, "hlim %u, next-header %s (%u) payload length: %u) ", ip6->ip6_hlim, tok2str(ipproto_values,"unknown",ip6->ip6_nxt), ip6->ip6_nxt, payload_len)); } /* * Cut off the snapshot length to the end of the IP payload. */ ipend = bp + len; if (ipend < ndo->ndo_snapend) ndo->ndo_snapend = ipend; cp = (const u_char *)ip6; advance = sizeof(struct ip6_hdr); nh = ip6->ip6_nxt; while (cp < ndo->ndo_snapend && advance > 0) { cp += advance; len -= advance; if (cp == (const u_char *)(ip6 + 1) && nh != IPPROTO_TCP && nh != IPPROTO_UDP && nh != IPPROTO_DCCP && nh != IPPROTO_SCTP) { ND_PRINT((ndo, "%s > %s: ", ip6addr_string(ndo, &ip6->ip6_src), ip6addr_string(ndo, &ip6->ip6_dst))); } switch (nh) { case IPPROTO_HOPOPTS: advance = hbhopt_print(ndo, cp); nh = *cp; break; case IPPROTO_DSTOPTS: advance = dstopt_print(ndo, cp); nh = *cp; break; case IPPROTO_FRAGMENT: advance = frag6_print(ndo, cp, (const u_char *)ip6); if (ndo->ndo_snapend <= cp + advance) return; nh = *cp; fragmented = 1; break; case IPPROTO_MOBILITY_OLD: case IPPROTO_MOBILITY: /* * XXX - we don't use "advance"; the current * "Mobility Support in IPv6" draft * (draft-ietf-mobileip-ipv6-24) says that * the next header field in a mobility header * should be IPPROTO_NONE, but speaks of * the possiblity of a future extension in * which payload can be piggybacked atop a * mobility header. */ advance = mobility_print(ndo, cp, (const u_char *)ip6); nh = *cp; return; case IPPROTO_ROUTING: advance = rt6_print(ndo, cp, (const u_char *)ip6); nh = *cp; break; case IPPROTO_SCTP: sctp_print(ndo, cp, (const u_char *)ip6, len); return; case IPPROTO_DCCP: dccp_print(ndo, cp, (const u_char *)ip6, len); return; case IPPROTO_TCP: tcp_print(ndo, cp, len, (const u_char *)ip6, fragmented); return; case IPPROTO_UDP: udp_print(ndo, cp, len, (const u_char *)ip6, fragmented); return; case IPPROTO_ICMPV6: icmp6_print(ndo, cp, len, (const u_char *)ip6, fragmented); return; case IPPROTO_AH: advance = ah_print(ndo, cp); nh = *cp; break; case IPPROTO_ESP: { int enh, padlen; advance = esp_print(ndo, cp, len, (const u_char *)ip6, &enh, &padlen); nh = enh & 0xff; len -= padlen; break; } case IPPROTO_IPCOMP: { int enh; advance = ipcomp_print(ndo, cp, &enh); nh = enh & 0xff; break; } case IPPROTO_PIM: pim_print(ndo, cp, len, nextproto6_cksum(ip6, cp, len, len, IPPROTO_PIM)); return; case IPPROTO_OSPF: ospf6_print(ndo, cp, len); return; case IPPROTO_IPV6: ip6_print(ndo, cp, len); return; case IPPROTO_IPV4: ip_print(ndo, cp, len); return; case IPPROTO_PGM: pgm_print(ndo, cp, len, (const u_char *)ip6); return; case IPPROTO_GRE: gre_print(ndo, cp, len); return; case IPPROTO_RSVP: rsvp_print(ndo, cp, len); return; case IPPROTO_NONE: ND_PRINT((ndo, "no next header")); return; default: ND_PRINT((ndo, "ip-proto-%d %d", nh, len)); return; } } return; trunc: ND_PRINT((ndo, "[|ip6]")); +} + +#else /* INET6 */ + +void +ip6_print(netdissect_options *ndo, const u_char *bp _U_, u_int length) +{ + ND_PRINT((ndo, "IP6, length: %u (printing not supported)", length)); } #endif /* INET6 */ Index: head/contrib/tcpdump/print-ipnet.c =================================================================== --- head/contrib/tcpdump/print-ipnet.c (revision 285274) +++ head/contrib/tcpdump/print-ipnet.c (revision 285275) @@ -1,118 +1,116 @@ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "interface.h" typedef struct ipnet_hdr { uint8_t iph_version; uint8_t iph_family; uint16_t iph_htype; uint32_t iph_pktlen; uint32_t iph_ifindex; uint32_t iph_grifindex; uint32_t iph_zsrc; 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 inline 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((ndo, "%d > %d", hdr->iph_zsrc, hdr->iph_zdst)); if (!ndo->ndo_qflag) { ND_PRINT((ndo,", family %s (%d)", tok2str(ipnet_values, "Unknown", hdr->iph_family), hdr->iph_family)); } else { ND_PRINT((ndo,", %s", tok2str(ipnet_values, "Unknown Ethertype (0x%04x)", hdr->iph_family))); } ND_PRINT((ndo, ", length %u: ", length)); } static void ipnet_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen) { ipnet_hdr_t *hdr; if (caplen < sizeof(ipnet_hdr_t)) { ND_PRINT((ndo, "[|ipnet]")); return; } if (ndo->ndo_eflag) ipnet_hdr_print(ndo, p, length); length -= sizeof(ipnet_hdr_t); caplen -= sizeof(ipnet_hdr_t); hdr = (ipnet_hdr_t *)p; p += sizeof(ipnet_hdr_t); switch (hdr->iph_family) { case IPH_AF_INET: ip_print(ndo, p, length); break; -#ifdef INET6 case IPH_AF_INET6: ip6_print(ndo, p, length); break; -#endif /*INET6*/ default: if (!ndo->ndo_eflag) ipnet_hdr_print(ndo, (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. */ u_int ipnet_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { ipnet_print(ndo, p, h->len, h->caplen); return (sizeof(ipnet_hdr_t)); } /* * Local Variables: * c-style: whitesmith * c-basic-offset: 8 * End: */ #endif /* DLT_IPNET */ Index: head/contrib/tcpdump/print-isoclns.c =================================================================== --- head/contrib/tcpdump/print-isoclns.c (revision 285274) +++ head/contrib/tcpdump/print-isoclns.c (revision 285275) @@ -1,3107 +1,3120 @@ /* * 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@juniper.net) for more * complete IS-IS & CLNP support. * * $FreeBSD$ */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "interface.h" #include "addrtoname.h" #include "ether.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 ETHER_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_ISNEIGH_VARLEN 7 /* iso10589 */ #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_LSP_BUFFERSIZE 14 /* iso10589 rev2 */ #define ISIS_TLV_LSP_BUFFERSIZE_MINLEN 2 #define ISIS_TLV_EXT_IS_REACH 22 /* draft-ietf-isis-traffic-05 */ #define ISIS_TLV_IS_ALIAS_ID 24 /* draft-ietf-isis-ext-lsp-frags-02 */ #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_IDRP_INFO_MINLEN 1 #define ISIS_TLV_IPADDR 132 /* rfc1195 */ #define ISIS_TLV_IPAUTH 133 /* rfc1195 */ #define ISIS_TLV_TE_ROUTER_ID 134 /* draft-ietf-isis-traffic-05 */ #define ISIS_TLV_EXTD_IP_REACH 135 /* draft-ietf-isis-traffic-05 */ #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_MT_SUPPORTED_MINLEN 2 #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_IIH_SEQNR_MINLEN 4 #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_ISNEIGH_VARLEN, "IS Neighbor(s) (variable length)"}, { ISIS_TLV_PADDING, "Padding"}, { ISIS_TLV_LSP, "LSP entries"}, { ISIS_TLV_AUTH, "Authentication"}, { ISIS_TLV_CHECKSUM, "Checksum"}, { 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_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_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 } }; #define ISIS_SUBTLV_EXT_IS_REACH_ADMIN_GROUP 3 /* draft-ietf-isis-traffic-05 */ #define ISIS_SUBTLV_EXT_IS_REACH_LINK_LOCAL_REMOTE_ID 4 /* rfc4205 */ #define ISIS_SUBTLV_EXT_IS_REACH_LINK_REMOTE_ID 5 /* draft-ietf-isis-traffic-05 */ #define ISIS_SUBTLV_EXT_IS_REACH_IPV4_INTF_ADDR 6 /* draft-ietf-isis-traffic-05 */ #define ISIS_SUBTLV_EXT_IS_REACH_IPV4_NEIGHBOR_ADDR 8 /* draft-ietf-isis-traffic-05 */ #define ISIS_SUBTLV_EXT_IS_REACH_MAX_LINK_BW 9 /* draft-ietf-isis-traffic-05 */ #define ISIS_SUBTLV_EXT_IS_REACH_RESERVABLE_BW 10 /* draft-ietf-isis-traffic-05 */ #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 /* draft-ietf-isis-traffic-05 */ #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_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_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_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_MGMT_PREFIX_COLOR, "Management Prefix Color" }, { 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 } }; #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 { uint8_t format_id; uint8_t name[32]; uint8_t revision_lvl[2]; uint8_t digest[16]; }; struct isis_subtlv_spb_mcid { struct isis_spb_mcid mcid; struct isis_spb_mcid aux_mcid; }; struct isis_subtlv_spb_instance { uint8_t cist_root_id[8]; uint8_t cist_external_root_path_cost[4]; uint8_t bridge_priority[2]; uint8_t spsourceid[4]; 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) ((x)&0x4) #define ISIS_MASK_LSP_ISTYPE_BITS(x) ((x)&0x3) #define ISIS_MASK_LSP_PARTITION_BIT(x) ((x)&0x80) #define ISIS_MASK_LSP_ATT_BITS(x) ((x)&0x78) #define ISIS_MASK_LSP_ATT_ERROR_BIT(x) ((x)&0x40) #define ISIS_MASK_LSP_ATT_EXPENSE_BIT(x) ((x)&0x20) #define ISIS_MASK_LSP_ATT_DELAY_BIT(x) ((x)&0x10) #define ISIS_MASK_LSP_ATT_DEFAULT_BIT(x) ((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) ((x)&0x80) #define ISIS_LSP_TLV_METRIC_IE(x) ((x)&0x40) #define ISIS_LSP_TLV_METRIC_UPDOWN(x) ((x)&0x80) #define ISIS_LSP_TLV_METRIC_VALUE(x) ((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[] = { { ISIS_PTP_ADJ_UP, "Up" }, { ISIS_PTP_ADJ_INIT, "Initializing" }, { ISIS_PTP_ADJ_DOWN, "Down" }, { 0, NULL} }; struct isis_tlv_ptp_adj { uint8_t adjacency_state; uint8_t extd_local_circuit_id[4]; uint8_t neighbor_sysid[SYSTEM_ID_LEN]; uint8_t neighbor_extd_local_circuit_id[4]; }; static void osi_print_cksum(netdissect_options *, const uint8_t *pptr, uint16_t checksum, u_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 { uint8_t metric_default; uint8_t metric_delay; uint8_t metric_expense; uint8_t metric_error; }; struct isis_tlv_is_reach { struct isis_metric_block isis_metric_block; uint8_t neighbor_nodeid[NODE_ID_LEN]; }; struct isis_tlv_es_reach { struct isis_metric_block isis_metric_block; uint8_t neighbor_sysid[SYSTEM_ID_LEN]; }; struct isis_tlv_ip_reach { struct isis_metric_block isis_metric_block; uint8_t prefix[4]; uint8_t mask[4]; }; 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 { uint8_t nlpid; uint8_t fixed_len; uint8_t version; /* Protocol version */ uint8_t id_length; uint8_t pdu_type; /* 3 MSbits are reserved */ uint8_t pdu_version; /* Packet format version */ uint8_t reserved; uint8_t max_area; }; struct isis_iih_lan_header { uint8_t circuit_type; uint8_t source_id[SYSTEM_ID_LEN]; uint8_t holding_time[2]; uint8_t pdu_len[2]; uint8_t priority; uint8_t lan_id[NODE_ID_LEN]; }; struct isis_iih_ptp_header { uint8_t circuit_type; uint8_t source_id[SYSTEM_ID_LEN]; uint8_t holding_time[2]; uint8_t pdu_len[2]; uint8_t circuit_id; }; struct isis_lsp_header { uint8_t pdu_len[2]; uint8_t remaining_lifetime[2]; uint8_t lsp_id[LSP_ID_LEN]; uint8_t sequence_number[4]; uint8_t checksum[2]; uint8_t typeblock; }; struct isis_csnp_header { uint8_t pdu_len[2]; uint8_t source_id[NODE_ID_LEN]; uint8_t start_lsp_id[LSP_ID_LEN]; uint8_t end_lsp_id[LSP_ID_LEN]; }; struct isis_psnp_header { uint8_t pdu_len[2]; uint8_t source_id[NODE_ID_LEN]; }; struct isis_tlv_lsp { uint8_t remaining_lifetime[2]; uint8_t lsp_id[LSP_ID_LEN]; uint8_t sequence_number[4]; uint8_t checksum[2]; }; #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 uint8_t *p, u_int length, u_int caplen) { if (caplen <= 1) { /* enough bytes on the wire ? */ ND_PRINT((ndo, "|OSI")); return; } if (ndo->ndo_eflag) ND_PRINT((ndo, "OSI NLPID %s (0x%02x): ", tok2str(nlpid_values, "Unknown", *p), *p)); switch (*p) { case NLPID_CLNP: if (!clnp_print(ndo, p, length)) print_unknown_data(ndo, p, "\n\t", caplen); 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", caplen); break; case NLPID_NULLNS: ND_PRINT((ndo, "%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; -#ifdef INET6 case NLPID_IP6: ip6_print(ndo, p + 1, length - 1); break; -#endif case NLPID_PPP: ppp_print(ndo, p + 1, length - 1); break; default: if (!ndo->ndo_eflag) ND_PRINT((ndo, "OSI NLPID 0x%02x unknown", *p)); ND_PRINT((ndo, "%slength: %u", ndo->ndo_eflag ? "" : ", ", length)); if (caplen > 1) print_unknown_data(ndo, p, "\n\t", caplen); 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 { uint8_t nlpid; uint8_t length_indicator; uint8_t version; uint8_t lifetime; /* units of 500ms */ uint8_t type; uint8_t segment_length[2]; uint8_t cksum[2]; }; struct clnp_segment_header_t { uint8_t data_unit_id[2]; uint8_t segment_offset[2]; uint8_t total_length[2]; }; /* * 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,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_major,rfd_error_minor; clnp_header = (const struct clnp_header_t *) pptr; ND_TCHECK(*clnp_header); li = clnp_header->length_indicator; optr = pptr; if (!ndo->ndo_eflag) ND_PRINT((ndo, "CLNP")); /* * Sanity checking of the header. */ if (clnp_header->version != CLNP_VERSION) { ND_PRINT((ndo, "version %d packet not supported", clnp_header->version)); return (0); } /* FIXME further header sanity checking */ clnp_pdu_type = clnp_header->type & CLNP_PDU_TYPE_MASK; clnp_flags = clnp_header->type & CLNP_FLAG_MASK; pptr += sizeof(struct clnp_header_t); li -= sizeof(struct clnp_header_t); dest_address_length = *pptr; dest_address = pptr + 1; pptr += (1 + dest_address_length); li -= (1 + dest_address_length); source_address_length = *pptr; source_address = pptr +1; pptr += (1 + source_address_length); li -= (1 + source_address_length); if (ndo->ndo_vflag < 1) { ND_PRINT((ndo, "%s%s > %s, %s, length %u", ndo->ndo_eflag ? "" : ", ", isonsap_string(source_address, source_address_length), isonsap_string(dest_address, dest_address_length), tok2str(clnp_pdu_values,"unknown (%u)",clnp_pdu_type), length)); return (1); } ND_PRINT((ndo, "%slength %u", ndo->ndo_eflag ? "" : ", ", length)); ND_PRINT((ndo, "\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), clnp_header->length_indicator, clnp_header->version, clnp_header->lifetime/2, (clnp_header->lifetime%2)*5, EXTRACT_16BITS(clnp_header->segment_length), EXTRACT_16BITS(clnp_header->cksum))); osi_print_cksum(ndo, optr, EXTRACT_16BITS(clnp_header->cksum), 7, clnp_header->length_indicator); ND_PRINT((ndo, "\n\tFlags [%s]", bittok2str(clnp_flag_values, "none", clnp_flags))); ND_PRINT((ndo, "\n\tsource address (length %u): %s\n\tdest address (length %u): %s", source_address_length, isonsap_string(source_address, source_address_length), dest_address_length, isonsap_string(dest_address, dest_address_length))); if (clnp_flags & CLNP_SEGMENT_PART) { clnp_segment_header = (const struct clnp_segment_header_t *) pptr; ND_TCHECK(*clnp_segment_header); ND_PRINT((ndo, "\n\tData Unit ID: 0x%04x, Segment Offset: %u, Total PDU Length: %u", EXTRACT_16BITS(clnp_segment_header->data_unit_id), EXTRACT_16BITS(clnp_segment_header->segment_offset), EXTRACT_16BITS(clnp_segment_header->total_length))); pptr+=sizeof(const struct clnp_segment_header_t); li-=sizeof(const struct clnp_segment_header_t); } /* now walk the options */ while (li >= 2) { u_int op, opli; const uint8_t *tptr; ND_TCHECK2(*pptr, 2); if (li < 2) { ND_PRINT((ndo, ", bad opts/li")); return (0); } op = *pptr++; opli = *pptr++; li -= 2; ND_TCHECK2(*pptr, opli); if (opli > li) { ND_PRINT((ndo, ", opt (%d) too long", op)); return (0); } li -= opli; tptr = pptr; tlen = opli; ND_PRINT((ndo, "\n\t %s Option #%u, length %u, value: ", tok2str(clnp_option_values,"Unknown",op), op, opli)); switch (op) { case CLNP_OPTION_ROUTE_RECORDING: /* those two options share the format */ case CLNP_OPTION_SOURCE_ROUTING: ND_PRINT((ndo, "%s %s", tok2str(clnp_option_sr_rr_values,"Unknown",*tptr), tok2str(clnp_option_sr_rr_string_values, "Unknown Option %u", op))); nsap_offset=*(tptr+1); if (nsap_offset == 0) { ND_PRINT((ndo, " Bad NSAP offset (0)")); break; } nsap_offset-=1; /* offset to nsap list */ if (nsap_offset > tlen) { ND_PRINT((ndo, " Bad NSAP offset (past end of option)")); break; } tptr+=nsap_offset; tlen-=nsap_offset; while (tlen > 0) { source_address_length=*tptr; if (tlen < source_address_length+1) { ND_PRINT((ndo, "\n\t NSAP address goes past end of option")); break; } if (source_address_length > 0) { source_address=(tptr+1); ND_TCHECK2(*source_address, source_address_length); ND_PRINT((ndo, "\n\t NSAP address (length %u): %s", source_address_length, isonsap_string(source_address, source_address_length))); } tlen-=source_address_length+1; } break; case CLNP_OPTION_PRIORITY: ND_PRINT((ndo, "0x%1x", *tptr&0x0f)); break; case CLNP_OPTION_QOS_MAINTENANCE: ND_PRINT((ndo, "\n\t Format Code: %s", tok2str(clnp_option_scope_values, "Reserved", *tptr&CLNP_OPTION_SCOPE_MASK))); if ((*tptr&CLNP_OPTION_SCOPE_MASK) == CLNP_OPTION_SCOPE_GLOBAL) ND_PRINT((ndo, "\n\t QoS Flags [%s]", bittok2str(clnp_option_qos_global_values, "none", *tptr&CLNP_OPTION_OPTION_QOS_MASK))); break; case CLNP_OPTION_SECURITY: ND_PRINT((ndo, "\n\t Format Code: %s, Security-Level %u", tok2str(clnp_option_scope_values,"Reserved",*tptr&CLNP_OPTION_SCOPE_MASK), *(tptr+1))); break; case CLNP_OPTION_DISCARD_REASON: rfd_error_major = (*tptr&0xf0) >> 4; rfd_error_minor = *tptr&0x0f; ND_PRINT((ndo, "\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((ndo, "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: ND_TCHECK(*pptr); if (*(pptr) == NLPID_CLNP) { ND_PRINT((ndo, "\n\t-----original packet-----\n\t")); /* FIXME recursion protection */ clnp_print(ndo, pptr, length - clnp_header->length_indicator); break; } case CLNP_PDU_DT: case CLNP_PDU_MD: case CLNP_PDU_ERQ: default: /* dump the PDU specific data */ if (length-(pptr-optr) > 0) { ND_PRINT((ndo, "\n\t undecoded non-header data, length %u", length-clnp_header->length_indicator)); print_unknown_data(ndo, pptr, "\n\t ", length - (pptr - optr)); } } return (1); trunc: ND_PRINT((ndo, "[|clnp]")); 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 { uint8_t nlpid; uint8_t length_indicator; uint8_t version; uint8_t reserved; uint8_t type; uint8_t holdtime[2]; uint8_t cksum[2]; }; static void esis_print(netdissect_options *ndo, const uint8_t *pptr, u_int length) { const uint8_t *optr; u_int li,esis_pdu_type,source_address_length, source_address_number; const struct esis_header_t *esis_header; if (!ndo->ndo_eflag) ND_PRINT((ndo, "ES-IS")); if (length <= 2) { ND_PRINT((ndo, ndo->ndo_qflag ? "bad pkt!" : "no header at all!")); return; } esis_header = (const struct esis_header_t *) pptr; ND_TCHECK(*esis_header); li = esis_header->length_indicator; optr = pptr; /* * Sanity checking of the header. */ if (esis_header->nlpid != NLPID_ESIS) { ND_PRINT((ndo, " nlpid 0x%02x packet not supported", esis_header->nlpid)); return; } if (esis_header->version != ESIS_VERSION) { ND_PRINT((ndo, " version %d packet not supported", esis_header->version)); return; } if (li > length) { ND_PRINT((ndo, " length indicator(%d) > PDU size (%d)!", li, length)); return; } if (li < sizeof(struct esis_header_t) + 2) { ND_PRINT((ndo, " length indicator < min PDU size %d:", li)); - while (--length != 0) + while (pptr < ndo->ndo_snapend) ND_PRINT((ndo, "%02X", *pptr++)); return; } esis_pdu_type = esis_header->type & ESIS_PDU_TYPE_MASK; if (ndo->ndo_vflag < 1) { ND_PRINT((ndo, "%s%s, length %u", ndo->ndo_eflag ? "" : ", ", tok2str(esis_pdu_values,"unknown type (%u)",esis_pdu_type), length)); return; } else ND_PRINT((ndo, "%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((ndo, ", v: %u%s", esis_header->version, esis_header->version == ESIS_VERSION ? "" : "unsupported" )); ND_PRINT((ndo, ", checksum: 0x%04x", EXTRACT_16BITS(esis_header->cksum))); osi_print_cksum(ndo, pptr, EXTRACT_16BITS(esis_header->cksum), 7, li); ND_PRINT((ndo, ", holding time: %us, length indicator: %u", EXTRACT_16BITS(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(*pptr); if (li < 1) { ND_PRINT((ndo, ", bad redirect/li")); return; } dstl = *pptr; pptr++; li--; ND_TCHECK2(*pptr, dstl); if (li < dstl) { ND_PRINT((ndo, ", bad redirect/li")); return; } dst = pptr; pptr += dstl; li -= dstl; ND_PRINT((ndo, "\n\t %s", isonsap_string(dst, dstl))); ND_TCHECK(*pptr); if (li < 1) { ND_PRINT((ndo, ", bad redirect/li")); return; } snpal = *pptr; pptr++; li--; ND_TCHECK2(*pptr, snpal); if (li < snpal) { ND_PRINT((ndo, ", bad redirect/li")); return; } snpa = pptr; pptr += snpal; li -= snpal; ND_TCHECK(*pptr); if (li < 1) { ND_PRINT((ndo, ", bad redirect/li")); return; } netal = *pptr; pptr++; ND_TCHECK2(*pptr, netal); if (li < netal) { ND_PRINT((ndo, ", bad redirect/li")); return; } neta = pptr; pptr += netal; li -= netal; if (netal == 0) ND_PRINT((ndo, "\n\t %s", etheraddr_string(ndo, snpa))); else ND_PRINT((ndo, "\n\t %s", isonsap_string(neta, netal))); break; } case ESIS_PDU_ESH: ND_TCHECK(*pptr); if (li < 1) { ND_PRINT((ndo, ", bad esh/li")); return; } source_address_number = *pptr; pptr++; li--; ND_PRINT((ndo, "\n\t Number of Source Addresses: %u", source_address_number)); while (source_address_number > 0) { ND_TCHECK(*pptr); if (li < 1) { ND_PRINT((ndo, ", bad esh/li")); return; } source_address_length = *pptr; pptr++; li--; ND_TCHECK2(*pptr, source_address_length); if (li < source_address_length) { ND_PRINT((ndo, ", bad esh/li")); return; } ND_PRINT((ndo, "\n\t NET (length: %u): %s", source_address_length, isonsap_string(pptr, source_address_length))); pptr += source_address_length; li -= source_address_length; source_address_number--; } break; case ESIS_PDU_ISH: { ND_TCHECK(*pptr); if (li < 1) { ND_PRINT((ndo, ", bad ish/li")); return; } source_address_length = *pptr; pptr++; li--; ND_TCHECK2(*pptr, source_address_length); if (li < source_address_length) { ND_PRINT((ndo, ", bad ish/li")); return; } ND_PRINT((ndo, "\n\t NET (length: %u): %s", source_address_length, isonsap_string(pptr, source_address_length))); pptr += source_address_length; li -= source_address_length; break; } default: if (ndo->ndo_vflag <= 1) { if (pptr < ndo->ndo_snapend) print_unknown_data(ndo, pptr, "\n\t ", ndo->ndo_snapend - pptr); } return; } /* now walk the options */ while (li != 0) { u_int op, opli; const uint8_t *tptr; if (li < 2) { ND_PRINT((ndo, ", bad opts/li")); return; } ND_TCHECK2(*pptr, 2); op = *pptr++; opli = *pptr++; li -= 2; if (opli > li) { ND_PRINT((ndo, ", opt (%d) too long", op)); return; } li -= opli; tptr = pptr; ND_PRINT((ndo, "\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_TCHECK2(*pptr, 2); ND_PRINT((ndo, "%us", EXTRACT_16BITS(tptr))); } else ND_PRINT((ndo, "(bad length)")); break; case ESIS_OPTION_PROTOCOLS: while (opli>0) { ND_TCHECK(*pptr); ND_PRINT((ndo, "%s (0x%02x)", tok2str(nlpid_values, "unknown", *tptr), *tptr)); if (opli>1) /* further NPLIDs ? - put comma */ ND_PRINT((ndo, ", ")); 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; } trunc: return; } static void isis_print_mcid(netdissect_options *ndo, const struct isis_spb_mcid *mcid) { int i; ND_PRINT((ndo, "ID: %d, Name: ", mcid->format_id)); for(i=0; i<32; i++) { ND_PRINT((ndo, "%c", mcid->name[i])); if(mcid->name[i] == '\0') break; } ND_PRINT((ndo, "\n\t Lvl: %d", EXTRACT_16BITS(mcid->revision_lvl))); ND_PRINT((ndo, ", Digest: ")); for(i=0;i<16;i++) ND_PRINT((ndo, "%.2x ", mcid->digest[i])); } static int isis_print_mt_port_cap_subtlv(netdissect_options *ndo, const uint8_t *tptr, int len) { int stlv_type, stlv_len; const struct isis_subtlv_spb_mcid *subtlv_spb_mcid; int i; while (len > 0) { stlv_type = *(tptr++); stlv_len = *(tptr++); /* first lets see if we know the subTLVs name*/ ND_PRINT((ndo, "\n\t %s subTLV #%u, length: %u", tok2str(isis_mt_port_cap_subtlv_values, "unknown", stlv_type), stlv_type, stlv_len)); /*len -= TLV_TYPE_LEN_OFFSET;*/ len = len -2; switch (stlv_type) { case ISIS_SUBTLV_SPB_MCID: { if (!ND_TTEST2(*(tptr), ISIS_SUBTLV_SPB_MCID_MIN_LEN)) goto trunctlv; subtlv_spb_mcid = (struct isis_subtlv_spb_mcid *)tptr; ND_PRINT((ndo, "\n\t MCID: ")); isis_print_mcid(ndo, &(subtlv_spb_mcid->mcid)); /*tptr += SPB_MCID_MIN_LEN; len -= SPB_MCID_MIN_LEN; */ ND_PRINT((ndo, "\n\t AUX-MCID: ")); isis_print_mcid(ndo, &(subtlv_spb_mcid->aux_mcid)); /*tptr += SPB_MCID_MIN_LEN; len -= SPB_MCID_MIN_LEN; */ tptr = tptr + sizeof(struct isis_subtlv_spb_mcid); len = len - sizeof(struct isis_subtlv_spb_mcid); break; } case ISIS_SUBTLV_SPB_DIGEST: { if (!ND_TTEST2(*(tptr), ISIS_SUBTLV_SPB_DIGEST_MIN_LEN)) goto trunctlv; ND_PRINT((ndo, "\n\t RES: %d V: %d A: %d D: %d", (*(tptr) >> 5), (((*tptr)>> 4) & 0x01), ((*(tptr) >> 2) & 0x03), ((*tptr) & 0x03))); tptr++; ND_PRINT((ndo, "\n\t Digest: ")); for(i=1;i<=8; i++) { ND_PRINT((ndo, "%08x ", EXTRACT_32BITS(tptr))); if (i%4 == 0 && i != 8) ND_PRINT((ndo, "\n\t ")); tptr = tptr + 4; } len = len - ISIS_SUBTLV_SPB_DIGEST_MIN_LEN; break; } case ISIS_SUBTLV_SPB_BVID: { if (!ND_TTEST2(*(tptr), stlv_len)) goto trunctlv; while (len) { if (!ND_TTEST2(*(tptr), ISIS_SUBTLV_SPB_BVID_MIN_LEN)) goto trunctlv; ND_PRINT((ndo, "\n\t ECT: %08x", EXTRACT_32BITS(tptr))); tptr = tptr+4; ND_PRINT((ndo, " BVID: %d, U:%01x M:%01x ", (EXTRACT_16BITS (tptr) >> 4) , (EXTRACT_16BITS (tptr) >> 3) & 0x01, (EXTRACT_16BITS (tptr) >> 2) & 0x01)); tptr = tptr + 2; len = len - ISIS_SUBTLV_SPB_BVID_MIN_LEN; } break; } default: break; } } return 0; trunctlv: ND_PRINT((ndo, "\n\t\t packet exceeded snapshot")); return(1); } static int isis_print_mt_capability_subtlv(netdissect_options *ndo, const uint8_t *tptr, int len) { int stlv_type, stlv_len, tmp; while (len > 0) { stlv_type = *(tptr++); stlv_len = *(tptr++); /* first lets see if we know the subTLVs name*/ ND_PRINT((ndo, "\n\t %s subTLV #%u, length: %u", tok2str(isis_mt_capability_subtlv_values, "unknown", stlv_type), stlv_type, stlv_len)); len = len - 2; switch (stlv_type) { case ISIS_SUBTLV_SPB_INSTANCE: if (!ND_TTEST2(*(tptr), ISIS_SUBTLV_SPB_INSTANCE_MIN_LEN)) goto trunctlv; ND_PRINT((ndo, "\n\t CIST Root-ID: %08x", EXTRACT_32BITS(tptr))); tptr = tptr+4; ND_PRINT((ndo, " %08x", EXTRACT_32BITS(tptr))); tptr = tptr+4; ND_PRINT((ndo, ", Path Cost: %08x", EXTRACT_32BITS(tptr))); tptr = tptr+4; ND_PRINT((ndo, ", Prio: %d", EXTRACT_16BITS(tptr))); tptr = tptr + 2; ND_PRINT((ndo, "\n\t RES: %d", EXTRACT_16BITS(tptr) >> 5)); ND_PRINT((ndo, ", V: %d", (EXTRACT_16BITS(tptr) >> 4) & 0x0001)); ND_PRINT((ndo, ", SPSource-ID: %d", (EXTRACT_32BITS(tptr) & 0x000fffff))); tptr = tptr+4; ND_PRINT((ndo, ", No of Trees: %x", *(tptr))); tmp = *(tptr++); len = len - ISIS_SUBTLV_SPB_INSTANCE_MIN_LEN; while (tmp) { if (!ND_TTEST2(*(tptr), ISIS_SUBTLV_SPB_INSTANCE_VLAN_TUPLE_LEN)) goto trunctlv; ND_PRINT((ndo, "\n\t U:%d, M:%d, A:%d, RES:%d", *(tptr) >> 7, (*(tptr) >> 6) & 0x01, (*(tptr) >> 5) & 0x01, (*(tptr) & 0x1f))); tptr++; ND_PRINT((ndo, ", ECT: %08x", EXTRACT_32BITS(tptr))); tptr = tptr + 4; ND_PRINT((ndo, ", BVID: %d, SPVID: %d", (EXTRACT_24BITS(tptr) >> 12) & 0x000fff, EXTRACT_24BITS(tptr) & 0x000fff)); tptr = tptr + 3; len = len - ISIS_SUBTLV_SPB_INSTANCE_VLAN_TUPLE_LEN; tmp--; } break; case ISIS_SUBTLV_SPBM_SI: if (!ND_TTEST2(*(tptr), 6)) goto trunctlv; ND_PRINT((ndo, "\n\t BMAC: %08x", EXTRACT_32BITS(tptr))); tptr = tptr+4; ND_PRINT((ndo, "%04x", EXTRACT_16BITS(tptr))); tptr = tptr+2; ND_PRINT((ndo, ", RES: %d, VID: %d", EXTRACT_16BITS(tptr) >> 12, (EXTRACT_16BITS(tptr)) & 0x0fff)); tptr = tptr+2; len = len - 8; stlv_len = stlv_len - 8; while (stlv_len) { ND_PRINT((ndo, "\n\t T: %d, R: %d, RES: %d, ISID: %d", (EXTRACT_32BITS(tptr) >> 31), (EXTRACT_32BITS(tptr) >> 30) & 0x01, (EXTRACT_32BITS(tptr) >> 24) & 0x03f, (EXTRACT_32BITS(tptr)) & 0x0ffffff)); tptr = tptr + 4; len = len - 4; stlv_len = stlv_len - 4; } break; default: break; } } return 0; trunctlv: ND_PRINT((ndo, "\n\t\t packet exceeded snapshot")); return(1); } /* shared routine for printing system, node and lsp-ids */ static char * isis_print_id(const uint8_t *cp, int id_len) { int i; static char id[sizeof("xxxx.xxxx.xxxx.yy-zz")]; char *pos = id; for (i = 1; i <= SYSTEM_ID_LEN; i++) { snprintf(pos, sizeof(id) - (pos - id), "%02x", *cp++); pos += strlen(pos); if (i == 2 || i == 4) *pos++ = '.'; } if (id_len >= NODE_ID_LEN) { snprintf(pos, sizeof(id) - (pos - id), ".%02x", *cp++); pos += strlen(pos); } if (id_len == LSP_ID_LEN) snprintf(pos, sizeof(id) - (pos - id), "-%02x", *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((ndo, ", Default Metric: %d, %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((ndo, "\n\t\t Delay Metric: %d, %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((ndo, "\n\t\t Expense Metric: %d, %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((ndo, "\n\t\t Error Metric: %d, %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, 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((ndo, "short IPv4 Reachability (%d vs %lu)", length, (unsigned long)sizeof(*tlv_ip_reach))); return (0); } if (!ND_TTEST(*tlv_ip_reach)) return (0); prefix_len = mask2plen(EXTRACT_32BITS(tlv_ip_reach->mask)); if (prefix_len == -1) ND_PRINT((ndo, "%sIPv4 prefix: %s mask %s", ident, ipaddr_string(ndo, (tlv_ip_reach->prefix)), ipaddr_string(ndo, (tlv_ip_reach->mask)))); else ND_PRINT((ndo, "%sIPv4 prefix: %15s/%u", ident, ipaddr_string(ndo, (tlv_ip_reach->prefix)), prefix_len)); ND_PRINT((ndo, ", 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((ndo, "%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((ndo, "%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((ndo, "%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); } /* * 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, int subt, int subl, - const char *ident) { - + const char *ident) +{ /* first lets see if we know the subTLVs name*/ ND_PRINT((ndo, "%s%s subTLV #%u, length: %u", ident, tok2str(isis_ext_ip_reach_subtlv_values, "unknown", subt), subt, subl)); if (!ND_TTEST2(*tptr,subl)) goto trunctlv; 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((ndo, ", 0x%08x (=%u)", EXTRACT_32BITS(tptr), EXTRACT_32BITS(tptr))); tptr+=4; subl-=4; } break; case ISIS_SUBTLV_EXTD_IP_REACH_ADMIN_TAG64: while (subl >= 8) { ND_PRINT((ndo, ", 0x%08x%08x", EXTRACT_32BITS(tptr), EXTRACT_32BITS(tptr+4))); tptr+=8; subl-=8; } break; default: if (!print_unknown_data(ndo, tptr, "\n\t\t ", subl)) return(0); break; } return(1); trunctlv: ND_PRINT((ndo, "%spacket exceeded snapshot", ident)); return(0); } /* * this is the common IS-REACH subTLV decoder it is called * from isis_print_ext_is_reach() */ static int isis_print_is_reach_subtlv(netdissect_options *ndo, const uint8_t *tptr, u_int subt, u_int subl, - const char *ident) { - + const char *ident) +{ u_int te_class,priority_level,gmpls_switch_cap; union { /* int to float conversion buffer for several subTLVs */ float f; uint32_t i; } bw; /* first lets see if we know the subTLVs name*/ ND_PRINT((ndo, "%s%s subTLV #%u, length: %u", ident, tok2str(isis_ext_is_reach_subtlv_values, "unknown", subt), subt, subl)); if (!ND_TTEST2(*tptr,subl)) goto trunctlv; switch(subt) { 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 (subl >= 4) { ND_PRINT((ndo, ", 0x%08x", EXTRACT_32BITS(tptr))); if (subl == 8) /* rfc4205 */ ND_PRINT((ndo, ", 0x%08x", EXTRACT_32BITS(tptr+4))); } break; case ISIS_SUBTLV_EXT_IS_REACH_IPV4_INTF_ADDR: case ISIS_SUBTLV_EXT_IS_REACH_IPV4_NEIGHBOR_ADDR: if (subl >= sizeof(struct in_addr)) ND_PRINT((ndo, ", %s", ipaddr_string(ndo, tptr))); break; case ISIS_SUBTLV_EXT_IS_REACH_MAX_LINK_BW : case ISIS_SUBTLV_EXT_IS_REACH_RESERVABLE_BW: if (subl >= 4) { bw.i = EXTRACT_32BITS(tptr); ND_PRINT((ndo, ", %.3f Mbps", bw.f * 8 / 1000000)); } break; case ISIS_SUBTLV_EXT_IS_REACH_UNRESERVED_BW : if (subl >= 32) { for (te_class = 0; te_class < 8; te_class++) { bw.i = EXTRACT_32BITS(tptr); ND_PRINT((ndo, "%s TE-Class %u: %.3f Mbps", ident, te_class, bw.f * 8 / 1000000)); tptr+=4; } } break; case ISIS_SUBTLV_EXT_IS_REACH_BW_CONSTRAINTS: /* fall through */ case ISIS_SUBTLV_EXT_IS_REACH_BW_CONSTRAINTS_OLD: ND_PRINT((ndo, "%sBandwidth Constraints Model ID: %s (%u)", ident, tok2str(diffserv_te_bc_values, "unknown", *tptr), *tptr)); tptr++; /* decode BCs until the subTLV ends */ for (te_class = 0; te_class < (subl-1)/4; te_class++) { bw.i = EXTRACT_32BITS(tptr); ND_PRINT((ndo, "%s Bandwidth constraint CT%u: %.3f Mbps", ident, te_class, bw.f * 8 / 1000000)); tptr+=4; } break; case ISIS_SUBTLV_EXT_IS_REACH_TE_METRIC: if (subl >= 3) ND_PRINT((ndo, ", %u", EXTRACT_24BITS(tptr))); break; case ISIS_SUBTLV_EXT_IS_REACH_LINK_ATTRIBUTE: if (subl == 2) { ND_PRINT((ndo, ", [ %s ] (0x%04x)", bittok2str(isis_subtlv_link_attribute_values, "Unknown", EXTRACT_16BITS(tptr)), EXTRACT_16BITS(tptr))); } break; case ISIS_SUBTLV_EXT_IS_REACH_LINK_PROTECTION_TYPE: if (subl >= 2) { ND_PRINT((ndo, ", %s, Priority %u", bittok2str(gmpls_link_prot_values, "none", *tptr), *(tptr+1))); } break; case ISIS_SUBTLV_SPB_METRIC: if (subl >= 6) { ND_PRINT((ndo, ", LM: %u", EXTRACT_24BITS(tptr))); tptr=tptr+3; ND_PRINT((ndo, ", P: %u", *(tptr))); tptr++; ND_PRINT((ndo, ", P-ID: %u", EXTRACT_16BITS(tptr))); } break; case ISIS_SUBTLV_EXT_IS_REACH_INTF_SW_CAP_DESCR: if (subl >= 36) { gmpls_switch_cap = *tptr; ND_PRINT((ndo, "%s Interface Switching Capability:%s", ident, tok2str(gmpls_switch_cap_values, "Unknown", gmpls_switch_cap))); ND_PRINT((ndo, ", LSP Encoding: %s", tok2str(gmpls_encoding_values, "Unknown", *(tptr + 1)))); tptr+=4; ND_PRINT((ndo, "%s Max LSP Bandwidth:", ident)); for (priority_level = 0; priority_level < 8; priority_level++) { bw.i = EXTRACT_32BITS(tptr); ND_PRINT((ndo, "%s priority level %d: %.3f Mbps", ident, priority_level, bw.f * 8 / 1000000)); tptr+=4; } subl-=36; switch (gmpls_switch_cap) { case GMPLS_PSC1: case GMPLS_PSC2: case GMPLS_PSC3: case GMPLS_PSC4: bw.i = EXTRACT_32BITS(tptr); ND_PRINT((ndo, "%s Min LSP Bandwidth: %.3f Mbps", ident, bw.f * 8 / 1000000)); ND_PRINT((ndo, "%s Interface MTU: %u", ident, EXTRACT_16BITS(tptr + 4))); break; case GMPLS_TSC: bw.i = EXTRACT_32BITS(tptr); ND_PRINT((ndo, "%s Min LSP Bandwidth: %.3f Mbps", ident, bw.f * 8 / 1000000)); ND_PRINT((ndo, "%s Indication %s", ident, tok2str(gmpls_switch_cap_tsc_indication_values, "Unknown (%u)", *(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(subl>0){ if (!print_unknown_data(ndo, tptr, "\n\t\t ", subl)) return(0); } } } break; default: if (!print_unknown_data(ndo, tptr, "\n\t\t ", subl)) return(0); break; } return(1); trunctlv: ND_PRINT((ndo, "%spacket exceeded snapshot", ident)); 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, int tlv_type) { - + const uint8_t *tptr, const char *ident, int tlv_type) +{ char ident_buffer[20]; int subtlv_type,subtlv_len,subtlv_sum_len; int proc_bytes = 0; /* how many bytes did we process ? */ if (!ND_TTEST2(*tptr, NODE_ID_LEN)) return(0); ND_PRINT((ndo, "%sIS Neighbor: %s", ident, isis_print_id(tptr, NODE_ID_LEN))); tptr+=(NODE_ID_LEN); if (tlv_type != ISIS_TLV_IS_ALIAS_ID) { /* the Alias TLV Metric field is implicit 0 */ if (!ND_TTEST2(*tptr, 3)) /* and is therefore skipped */ return(0); ND_PRINT((ndo, ", Metric: %d", EXTRACT_24BITS(tptr))); tptr+=3; } if (!ND_TTEST2(*tptr, 1)) return(0); subtlv_sum_len=*(tptr++); /* read out subTLV length */ proc_bytes=NODE_ID_LEN+3+1; ND_PRINT((ndo, ", %ssub-TLVs present",subtlv_sum_len ? "" : "no ")); if (subtlv_sum_len) { ND_PRINT((ndo, " (%u)", subtlv_sum_len)); while (subtlv_sum_len>0) { if (!ND_TTEST2(*tptr,2)) return(0); subtlv_type=*(tptr++); subtlv_len=*(tptr++); /* prepend the ident string */ snprintf(ident_buffer, sizeof(ident_buffer), "%s ",ident); if (!isis_print_is_reach_subtlv(ndo, tptr, subtlv_type, subtlv_len, ident_buffer)) return(0); tptr+=subtlv_len; subtlv_sum_len-=(subtlv_len+2); proc_bytes+=(subtlv_len+2); } } return(proc_bytes); } /* * this is the common Multi Topology ID decoder * it is called from various MT-TLVs (222,229,235,237) */ static int isis_print_mtid(netdissect_options *ndo, - const uint8_t *tptr, const char *ident) { - + const uint8_t *tptr, const char *ident) +{ if (!ND_TTEST2(*tptr, 2)) return(0); ND_PRINT((ndo, "%s%s", ident, tok2str(isis_mt_values, "Reserved for IETF Consensus", ISIS_MASK_MTID(EXTRACT_16BITS(tptr))))); ND_PRINT((ndo, " Topology (0x%03x), Flags: [%s]", ISIS_MASK_MTID(EXTRACT_16BITS(tptr)), bittok2str(isis_mt_flag_values, "none",ISIS_MASK_MTFLAGS(EXTRACT_16BITS(tptr))))); return(2); } /* * 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 int isis_print_extd_ip_reach(netdissect_options *ndo, - const uint8_t *tptr, const char *ident, uint16_t afi) { - + const uint8_t *tptr, const char *ident, uint16_t afi) +{ char ident_buffer[20]; #ifdef INET6 uint8_t prefix[sizeof(struct in6_addr)]; /* shared copy buffer for IPv4 and IPv6 prefixes */ #else uint8_t prefix[sizeof(struct in_addr)]; /* shared copy buffer for IPv4 prefixes */ #endif u_int metric, status_byte, bit_length, byte_length, sublen, processed, subtlvtype, subtlvlen; if (!ND_TTEST2(*tptr, 4)) return (0); metric = EXTRACT_32BITS(tptr); processed=4; tptr+=4; if (afi == AF_INET) { if (!ND_TTEST2(*tptr, 1)) /* fetch status byte */ return (0); status_byte=*(tptr++); bit_length = status_byte&0x3f; if (bit_length > 32) { ND_PRINT((ndo, "%sIPv4 prefix: bad bit length %u", ident, bit_length)); return (0); } processed++; #ifdef INET6 } else if (afi == AF_INET6) { if (!ND_TTEST2(*tptr, 1)) /* fetch status & prefix_len byte */ return (0); status_byte=*(tptr++); bit_length=*(tptr++); if (bit_length > 128) { ND_PRINT((ndo, "%sIPv6 prefix: bad bit length %u", ident, bit_length)); return (0); } processed+=2; #endif } else return (0); /* somebody is fooling us */ byte_length = (bit_length + 7) / 8; /* prefix has variable length encoding */ if (!ND_TTEST2(*tptr, byte_length)) return (0); memset(prefix, 0, sizeof prefix); /* clear the copy buffer */ memcpy(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((ndo, "%sIPv4 prefix: %15s/%u", ident, ipaddr_string(ndo, prefix), bit_length)); #ifdef INET6 if (afi == AF_INET6) ND_PRINT((ndo, "%sIPv6 prefix: %s/%u", ident, ip6addr_string(ndo, prefix), bit_length)); #endif ND_PRINT((ndo, ", 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((ndo, ", sub-TLVs present")); #ifdef INET6 if (afi == AF_INET6) ND_PRINT((ndo, ", %s%s", ISIS_MASK_TLV_EXTD_IP6_IE(status_byte) ? "External" : "Internal", ISIS_MASK_TLV_EXTD_IP6_SUBTLV(status_byte) ? ", sub-TLVs present" : "")); #endif if ((afi == AF_INET && ISIS_MASK_TLV_EXTD_IP_SUBTLV(status_byte)) #ifdef INET6 || (afi == AF_INET6 && ISIS_MASK_TLV_EXTD_IP6_SUBTLV(status_byte)) #endif ) { /* 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 */ if (!ND_TTEST2(*tptr, 1)) return (0); sublen=*(tptr++); processed+=sublen+1; ND_PRINT((ndo, " (%u)", sublen)); /* print out subTLV length */ while (sublen>0) { if (!ND_TTEST2(*tptr,2)) return (0); subtlvtype=*(tptr++); subtlvlen=*(tptr++); /* prepend the ident 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); } /* * isis_print * Decode IS-IS packets. Return 0 on error. */ 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; 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 pdu_type, max_area, id_length, tlv_type, tlv_len, tmp, alen, lan_alen, prefix_len; uint8_t ext_is_len, ext_ip_len, mt_len; const uint8_t *optr, *pptr, *tptr; u_short packet_len,pdu_len, key_id; u_int i,vendor_id; int sigcheck; 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(*isis_header); 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 = (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((ndo, "IS-IS")); /* * Sanity checking of the header. */ if (isis_header->version != ISIS_VERSION) { ND_PRINT((ndo, "version %d packet not supported", isis_header->version)); return (0); } if ((isis_header->id_length != SYSTEM_ID_LEN) && (isis_header->id_length != 0)) { ND_PRINT((ndo, "system ID length of %d is not supported", isis_header->id_length)); return (0); } if (isis_header->pdu_version != ISIS_VERSION) { ND_PRINT((ndo, "version %d packet not supported", isis_header->pdu_version)); return (0); } max_area = isis_header->max_area; switch(max_area) { case 0: max_area = 3; /* silly shit */ break; case 255: ND_PRINT((ndo, "bad packet -- 255 areas")); return (0); default: break; } id_length = isis_header->id_length; switch(id_length) { case 0: id_length = 6; /* silly shit again */ break; case 1: /* 1-8 are valid sys-ID lenghts */ case 2: case 3: case 4: case 5: case 6: case 7: case 8: break; case 255: id_length = 0; /* entirely useless */ break; default: break; } /* toss any non 6-byte sys-ID len PDUs */ if (id_length != 6 ) { ND_PRINT((ndo, "bad packet -- illegal sys-ID length (%u)", id_length)); return (0); } pdu_type=isis_header->pdu_type; /* in non-verbose mode print the basic PDU Type plus PDU specific brief information*/ if (ndo->ndo_vflag < 1) { ND_PRINT((ndo, "%s%s", ndo->ndo_eflag ? "" : ", ", tok2str(isis_pdu_values, "unknown PDU-Type %u", pdu_type))); switch (pdu_type) { case ISIS_PDU_L1_LAN_IIH: case ISIS_PDU_L2_LAN_IIH: ND_PRINT((ndo, ", src-id %s", isis_print_id(header_iih_lan->source_id, SYSTEM_ID_LEN))); ND_PRINT((ndo, ", lan-id %s, prio %u", isis_print_id(header_iih_lan->lan_id,NODE_ID_LEN), header_iih_lan->priority)); break; case ISIS_PDU_PTP_IIH: ND_PRINT((ndo, ", src-id %s", isis_print_id(header_iih_ptp->source_id, SYSTEM_ID_LEN))); break; case ISIS_PDU_L1_LSP: case ISIS_PDU_L2_LSP: ND_PRINT((ndo, ", lsp-id %s, seq 0x%08x, lifetime %5us", isis_print_id(header_lsp->lsp_id, LSP_ID_LEN), EXTRACT_32BITS(header_lsp->sequence_number), EXTRACT_16BITS(header_lsp->remaining_lifetime))); break; case ISIS_PDU_L1_CSNP: case ISIS_PDU_L2_CSNP: ND_PRINT((ndo, ", src-id %s", isis_print_id(header_csnp->source_id, NODE_ID_LEN))); break; case ISIS_PDU_L1_PSNP: case ISIS_PDU_L2_PSNP: ND_PRINT((ndo, ", src-id %s", isis_print_id(header_psnp->source_id, NODE_ID_LEN))); break; } ND_PRINT((ndo, ", length %u", length)); return(1); } /* ok they seem to want to know everything - lets fully decode it */ ND_PRINT((ndo, "%slength %u", ndo->ndo_eflag ? "" : ", ", length)); ND_PRINT((ndo, "\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), isis_header->fixed_len, isis_header->version, isis_header->pdu_version, id_length, isis_header->id_length, max_area, isis_header->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 (isis_header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_LAN_HEADER_SIZE)) { ND_PRINT((ndo, ", bogus fixed header length %u should be %lu", isis_header->fixed_len, (unsigned long)ISIS_IIH_LAN_HEADER_SIZE)); return (0); } pdu_len=EXTRACT_16BITS(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_TCHECK(*header_iih_lan); ND_PRINT((ndo, "\n\t source-id: %s, holding time: %us, Flags: [%s]", isis_print_id(header_iih_lan->source_id,SYSTEM_ID_LEN), EXTRACT_16BITS(header_iih_lan->holding_time), tok2str(isis_iih_circuit_type_values, "unknown circuit type 0x%02x", header_iih_lan->circuit_type))); ND_PRINT((ndo, "\n\t lan-id: %s, Priority: %u, PDU length: %u", isis_print_id(header_iih_lan->lan_id, NODE_ID_LEN), (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); } 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 (isis_header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_IIH_PTP_HEADER_SIZE)) { ND_PRINT((ndo, ", bogus fixed header length %u should be %lu", isis_header->fixed_len, (unsigned long)ISIS_IIH_PTP_HEADER_SIZE)); return (0); } pdu_len=EXTRACT_16BITS(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_TCHECK(*header_iih_ptp); ND_PRINT((ndo, "\n\t source-id: %s, holding time: %us, Flags: [%s]", isis_print_id(header_iih_ptp->source_id,SYSTEM_ID_LEN), EXTRACT_16BITS(header_iih_ptp->holding_time), tok2str(isis_iih_circuit_type_values, "unknown circuit type 0x%02x", header_iih_ptp->circuit_type))); ND_PRINT((ndo, "\n\t circuit-id: 0x%02x, PDU length: %u", 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); } 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 (isis_header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_LSP_HEADER_SIZE)) { ND_PRINT((ndo, ", bogus fixed header length %u should be %lu", isis_header->fixed_len, (unsigned long)ISIS_LSP_HEADER_SIZE)); return (0); } pdu_len=EXTRACT_16BITS(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_TCHECK(*header_lsp); ND_PRINT((ndo, "\n\t lsp-id: %s, seq: 0x%08x, lifetime: %5us\n\t chksum: 0x%04x", isis_print_id(header_lsp->lsp_id, LSP_ID_LEN), EXTRACT_32BITS(header_lsp->sequence_number), EXTRACT_16BITS(header_lsp->remaining_lifetime), EXTRACT_16BITS(header_lsp->checksum))); osi_print_cksum(ndo, (uint8_t *)header_lsp->lsp_id, EXTRACT_16BITS(header_lsp->checksum), 12, length-12); /* * Clear checksum and lifetime prior to signature verification. */ header_lsp->checksum[0] = 0; header_lsp->checksum[1] = 0; header_lsp->remaining_lifetime[0] = 0; header_lsp->remaining_lifetime[1] = 0; ND_PRINT((ndo, ", 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((ndo, "%s", ISIS_MASK_LSP_ATT_DEFAULT_BIT(header_lsp->typeblock) ? "default " : "")); ND_PRINT((ndo, "%s", ISIS_MASK_LSP_ATT_DELAY_BIT(header_lsp->typeblock) ? "delay " : "")); ND_PRINT((ndo, "%s", ISIS_MASK_LSP_ATT_EXPENSE_BIT(header_lsp->typeblock) ? "expense " : "")); ND_PRINT((ndo, "%s", ISIS_MASK_LSP_ATT_ERROR_BIT(header_lsp->typeblock) ? "error " : "")); ND_PRINT((ndo, "ATT bit set, ")); } ND_PRINT((ndo, "%s", ISIS_MASK_LSP_PARTITION_BIT(header_lsp->typeblock) ? "P bit set, " : "")); ND_PRINT((ndo, "%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); } 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 (isis_header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_CSNP_HEADER_SIZE)) { ND_PRINT((ndo, ", bogus fixed header length %u should be %lu", isis_header->fixed_len, (unsigned long)ISIS_CSNP_HEADER_SIZE)); return (0); } pdu_len=EXTRACT_16BITS(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_TCHECK(*header_csnp); ND_PRINT((ndo, "\n\t source-id: %s, PDU length: %u", isis_print_id(header_csnp->source_id, NODE_ID_LEN), pdu_len)); ND_PRINT((ndo, "\n\t start lsp-id: %s", isis_print_id(header_csnp->start_lsp_id, LSP_ID_LEN))); ND_PRINT((ndo, "\n\t end lsp-id: %s", isis_print_id(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); } 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 (isis_header->fixed_len != (ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE)) { ND_PRINT((ndo, "- bogus fixed header length %u should be %lu", isis_header->fixed_len, (unsigned long)ISIS_PSNP_HEADER_SIZE)); return (0); } pdu_len=EXTRACT_16BITS(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_TCHECK(*header_psnp); ND_PRINT((ndo, "\n\t source-id: %s, PDU length: %u", isis_print_id(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); } packet_len -= (ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE); pptr = p + (ISIS_COMMON_HEADER_SIZE+ISIS_PSNP_HEADER_SIZE); break; default: - if (!print_unknown_data(ndo, pptr, "\n\t ", length)) - return(0); + (void)print_unknown_data(ndo, pptr, "\n\t ", length); return (0); } /* * Now print the TLV's. */ while (packet_len >= 2) { if (pptr == ndo->ndo_snapend) { return (1); } if (!ND_TTEST2(*pptr, 2)) { ND_PRINT((ndo, "\n\t\t packet exceeded snapshot (%ld) bytes", (long)(pptr - ndo->ndo_snapend))); return (1); } tlv_type = *pptr++; tlv_len = *pptr++; tmp =tlv_len; /* copy temporary len & pointer to packet data */ tptr = pptr; packet_len -= 2; if (tlv_len > packet_len) { break; } /* first lets see if we know the TLVs name*/ ND_PRINT((ndo, "\n\t %s TLV #%u, length: %u", tok2str(isis_tlv_values, "unknown", tlv_type), tlv_type, tlv_len)); if (tlv_len == 0) /* something is malformed */ continue; /* now check if we have a decoder otherwise do a hexdump at the end*/ switch (tlv_type) { case ISIS_TLV_AREA_ADDR: if (!ND_TTEST2(*tptr, 1)) goto trunctlv; alen = *tptr++; while (tmp && alen < tmp) { ND_PRINT((ndo, "\n\t Area address (length: %u): %s", alen, isonsap_string(tptr, alen))); tptr += alen; tmp -= alen + 1; if (tmp==0) /* if this is the last area address do not attemt a boundary check */ break; if (!ND_TTEST2(*tptr, 1)) goto trunctlv; alen = *tptr++; } break; case ISIS_TLV_ISNEIGH: while (tmp >= ETHER_ADDR_LEN) { if (!ND_TTEST2(*tptr, ETHER_ADDR_LEN)) goto trunctlv; ND_PRINT((ndo, "\n\t SNPA: %s", isis_print_id(tptr, ETHER_ADDR_LEN))); tmp -= ETHER_ADDR_LEN; tptr += ETHER_ADDR_LEN; } break; case ISIS_TLV_ISNEIGH_VARLEN: if (!ND_TTEST2(*tptr, 1) || tmp < 3) /* min. TLV length */ goto trunctlv; lan_alen = *tptr++; /* LAN address length */ if (lan_alen == 0) { ND_PRINT((ndo, "\n\t LAN address length 0 bytes (invalid)")); break; } tmp --; ND_PRINT((ndo, "\n\t LAN address length %u bytes ", lan_alen)); while (tmp >= lan_alen) { if (!ND_TTEST2(*tptr, lan_alen)) goto trunctlv; ND_PRINT((ndo, "\n\t\tIS Neighbor: %s", isis_print_id(tptr, lan_alen))); tmp -= lan_alen; tptr +=lan_alen; } break; case ISIS_TLV_PADDING: break; case ISIS_TLV_MT_IS_REACH: mt_len = isis_print_mtid(ndo, tptr, "\n\t "); if (mt_len == 0) /* did something go wrong ? */ goto trunctlv; tptr+=mt_len; tmp-=mt_len; while (tmp >= 2+NODE_ID_LEN+3+1) { ext_is_len = isis_print_ext_is_reach(ndo, tptr, "\n\t ", tlv_type); if (ext_is_len == 0) /* did something go wrong ? */ goto trunctlv; tmp-=ext_is_len; tptr+=ext_is_len; } break; case ISIS_TLV_IS_ALIAS_ID: while (tmp >= NODE_ID_LEN+1) { /* is it worth attempting a decode ? */ ext_is_len = isis_print_ext_is_reach(ndo, tptr, "\n\t ", tlv_type); if (ext_is_len == 0) /* did something go wrong ? */ goto trunctlv; tmp-=ext_is_len; tptr+=ext_is_len; } break; case ISIS_TLV_EXT_IS_REACH: while (tmp >= NODE_ID_LEN+3+1) { /* is it worth attempting a decode ? */ ext_is_len = isis_print_ext_is_reach(ndo, tptr, "\n\t ", tlv_type); if (ext_is_len == 0) /* did something go wrong ? */ goto trunctlv; tmp-=ext_is_len; tptr+=ext_is_len; } break; case ISIS_TLV_IS_REACH: if (!ND_TTEST2(*tptr,1)) /* check if there is one byte left to read out the virtual flag */ goto trunctlv; ND_PRINT((ndo, "\n\t %s", tok2str(isis_is_reach_virtual_values, "bogus virtual flag 0x%02x", *tptr++))); tlv_is_reach = (const struct isis_tlv_is_reach *)tptr; while (tmp >= sizeof(struct isis_tlv_is_reach)) { if (!ND_TTEST(*tlv_is_reach)) goto trunctlv; ND_PRINT((ndo, "\n\t IS Neighbor: %s", isis_print_id(tlv_is_reach->neighbor_nodeid, NODE_ID_LEN))); isis_print_metric_block(ndo, &tlv_is_reach->isis_metric_block); tmp -= 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 (tmp >= sizeof(struct isis_tlv_es_reach)) { if (!ND_TTEST(*tlv_es_reach)) goto trunctlv; ND_PRINT((ndo, "\n\t ES Neighbor: %s", isis_print_id(tlv_es_reach->neighbor_sysid, SYSTEM_ID_LEN))); isis_print_metric_block(ndo, &tlv_es_reach->isis_metric_block); tmp -= 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 (tmp>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 trunctlv; tptr+=ext_ip_len; tmp-=ext_ip_len; } break; case ISIS_TLV_MT_IP_REACH: mt_len = isis_print_mtid(ndo, tptr, "\n\t "); if (mt_len == 0) { /* did something go wrong ? */ goto trunctlv; } tptr+=mt_len; tmp-=mt_len; while (tmp>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 trunctlv; tptr+=ext_ip_len; tmp-=ext_ip_len; } break; #ifdef INET6 case ISIS_TLV_IP6_REACH: while (tmp>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 trunctlv; tptr+=ext_ip_len; tmp-=ext_ip_len; } break; case ISIS_TLV_MT_IP6_REACH: mt_len = isis_print_mtid(ndo, tptr, "\n\t "); if (mt_len == 0) { /* did something go wrong ? */ goto trunctlv; } tptr+=mt_len; tmp-=mt_len; while (tmp>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 trunctlv; tptr+=ext_ip_len; tmp-=ext_ip_len; } break; case ISIS_TLV_IP6ADDR: while (tmp>=sizeof(struct in6_addr)) { if (!ND_TTEST2(*tptr, sizeof(struct in6_addr))) goto trunctlv; ND_PRINT((ndo, "\n\t IPv6 interface address: %s", ip6addr_string(ndo, tptr))); tptr += sizeof(struct in6_addr); tmp -= sizeof(struct in6_addr); } break; #endif case ISIS_TLV_AUTH: if (!ND_TTEST2(*tptr, 1)) goto trunctlv; ND_PRINT((ndo, "\n\t %s: ", tok2str(isis_subtlv_auth_values, "unknown Authentication type 0x%02x", *tptr))); switch (*tptr) { case ISIS_SUBTLV_AUTH_SIMPLE: for(i=1;i=1) { if (!ND_TTEST2(*tptr, 1)) goto trunctlv; ND_PRINT((ndo, "\n\t Adjacency State: %s (%u)", tok2str(isis_ptp_adjancey_values, "unknown", *tptr), *tptr)); tmp--; } if(tmp>sizeof(tlv_ptp_adj->extd_local_circuit_id)) { if (!ND_TTEST2(tlv_ptp_adj->extd_local_circuit_id, sizeof(tlv_ptp_adj->extd_local_circuit_id))) goto trunctlv; ND_PRINT((ndo, "\n\t Extended Local circuit-ID: 0x%08x", EXTRACT_32BITS(tlv_ptp_adj->extd_local_circuit_id))); tmp-=sizeof(tlv_ptp_adj->extd_local_circuit_id); } if(tmp>=SYSTEM_ID_LEN) { if (!ND_TTEST2(tlv_ptp_adj->neighbor_sysid, SYSTEM_ID_LEN)) goto trunctlv; ND_PRINT((ndo, "\n\t Neighbor System-ID: %s", isis_print_id(tlv_ptp_adj->neighbor_sysid, SYSTEM_ID_LEN))); tmp-=SYSTEM_ID_LEN; } if(tmp>=sizeof(tlv_ptp_adj->neighbor_extd_local_circuit_id)) { if (!ND_TTEST2(tlv_ptp_adj->neighbor_extd_local_circuit_id, sizeof(tlv_ptp_adj->neighbor_extd_local_circuit_id))) goto trunctlv; ND_PRINT((ndo, "\n\t Neighbor Extended Local circuit-ID: 0x%08x", EXTRACT_32BITS(tlv_ptp_adj->neighbor_extd_local_circuit_id))); } break; case ISIS_TLV_PROTOCOLS: ND_PRINT((ndo, "\n\t NLPID(s): ")); while (tmp>0) { if (!ND_TTEST2(*(tptr), 1)) goto trunctlv; ND_PRINT((ndo, "%s (0x%02x)", tok2str(nlpid_values, "unknown", *tptr), *tptr)); if (tmp>1) /* further NPLIDs ? - put comma */ ND_PRINT((ndo, ", ")); tptr++; tmp--; } break; case ISIS_TLV_MT_PORT_CAP: { if (!ND_TTEST2(*(tptr), 2)) goto trunctlv; ND_PRINT((ndo, "\n\t RES: %d, MTID(s): %d", (EXTRACT_16BITS (tptr) >> 12), (EXTRACT_16BITS (tptr) & 0x0fff))); tmp = tmp-2; tptr = tptr+2; if (tmp) isis_print_mt_port_cap_subtlv(ndo, tptr, tmp); break; } case ISIS_TLV_MT_CAPABILITY: if (!ND_TTEST2(*(tptr), 2)) goto trunctlv; ND_PRINT((ndo, "\n\t O: %d, RES: %d, MTID(s): %d", (EXTRACT_16BITS(tptr) >> 15) & 0x01, (EXTRACT_16BITS(tptr) >> 12) & 0x07, EXTRACT_16BITS(tptr) & 0x0fff)); tmp = tmp-2; tptr = tptr+2; if (tmp) isis_print_mt_capability_subtlv(ndo, tptr, tmp); break; case ISIS_TLV_TE_ROUTER_ID: if (!ND_TTEST2(*pptr, sizeof(struct in_addr))) goto trunctlv; ND_PRINT((ndo, "\n\t Traffic Engineering Router ID: %s", ipaddr_string(ndo, pptr))); break; case ISIS_TLV_IPADDR: while (tmp>=sizeof(struct in_addr)) { if (!ND_TTEST2(*tptr, sizeof(struct in_addr))) goto trunctlv; ND_PRINT((ndo, "\n\t IPv4 interface address: %s", ipaddr_string(ndo, tptr))); tptr += sizeof(struct in_addr); tmp -= sizeof(struct in_addr); } break; case ISIS_TLV_HOSTNAME: ND_PRINT((ndo, "\n\t Hostname: ")); while (tmp>0) { if (!ND_TTEST2(*tptr, 1)) goto trunctlv; ND_PRINT((ndo, "%c", *tptr++)); tmp--; } break; case ISIS_TLV_SHARED_RISK_GROUP: if (tmp < NODE_ID_LEN) break; if (!ND_TTEST2(*tptr, NODE_ID_LEN)) goto trunctlv; ND_PRINT((ndo, "\n\t IS Neighbor: %s", isis_print_id(tptr, NODE_ID_LEN))); tptr+=(NODE_ID_LEN); tmp-=(NODE_ID_LEN); if (tmp < 1) break; if (!ND_TTEST2(*tptr, 1)) goto trunctlv; ND_PRINT((ndo, ", Flags: [%s]", ISIS_MASK_TLV_SHARED_RISK_GROUP(*tptr++) ? "numbered" : "unnumbered")); tmp--; if (tmp < sizeof(struct in_addr)) break; if (!ND_TTEST2(*tptr, sizeof(struct in_addr))) goto trunctlv; ND_PRINT((ndo, "\n\t IPv4 interface address: %s", ipaddr_string(ndo, tptr))); tptr+=sizeof(struct in_addr); tmp-=sizeof(struct in_addr); if (tmp < sizeof(struct in_addr)) break; if (!ND_TTEST2(*tptr, sizeof(struct in_addr))) goto trunctlv; ND_PRINT((ndo, "\n\t IPv4 neighbor address: %s", ipaddr_string(ndo, tptr))); tptr+=sizeof(struct in_addr); tmp-=sizeof(struct in_addr); while (tmp>=4) { if (!ND_TTEST2(*tptr, 4)) goto trunctlv; ND_PRINT((ndo, "\n\t Link-ID: 0x%08x", EXTRACT_32BITS(tptr))); tptr+=4; tmp-=4; } break; case ISIS_TLV_LSP: tlv_lsp = (const struct isis_tlv_lsp *)tptr; while(tmp>=sizeof(struct isis_tlv_lsp)) { if (!ND_TTEST((tlv_lsp->lsp_id)[LSP_ID_LEN-1])) goto trunctlv; ND_PRINT((ndo, "\n\t lsp-id: %s", isis_print_id(tlv_lsp->lsp_id, LSP_ID_LEN))); if (!ND_TTEST2(tlv_lsp->sequence_number, 4)) goto trunctlv; ND_PRINT((ndo, ", seq: 0x%08x", EXTRACT_32BITS(tlv_lsp->sequence_number))); if (!ND_TTEST2(tlv_lsp->remaining_lifetime, 2)) goto trunctlv; ND_PRINT((ndo, ", lifetime: %5ds", EXTRACT_16BITS(tlv_lsp->remaining_lifetime))); if (!ND_TTEST2(tlv_lsp->checksum, 2)) goto trunctlv; ND_PRINT((ndo, ", chksum: 0x%04x", EXTRACT_16BITS(tlv_lsp->checksum))); tmp-=sizeof(struct isis_tlv_lsp); tlv_lsp++; } break; case ISIS_TLV_CHECKSUM: if (tmp < ISIS_TLV_CHECKSUM_MINLEN) break; if (!ND_TTEST2(*tptr, ISIS_TLV_CHECKSUM_MINLEN)) goto trunctlv; ND_PRINT((ndo, "\n\t checksum: 0x%04x ", EXTRACT_16BITS(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, EXTRACT_16BITS(tptr), tptr-optr, length); break; case ISIS_TLV_MT_SUPPORTED: if (tmp < ISIS_TLV_MT_SUPPORTED_MINLEN) break; while (tmp>1) { /* length can only be a multiple of 2, otherwise there is something broken -> so decode down until length is 1 */ if (tmp!=1) { mt_len = isis_print_mtid(ndo, tptr, "\n\t "); if (mt_len == 0) /* did something go wrong ? */ goto trunctlv; tptr+=mt_len; tmp-=mt_len; } else { ND_PRINT((ndo, "\n\t malformed MT-ID")); break; } } break; case ISIS_TLV_RESTART_SIGNALING: /* first attempt to decode the flags */ if (tmp < ISIS_TLV_RESTART_SIGNALING_FLAGLEN) break; if (!ND_TTEST2(*tptr, ISIS_TLV_RESTART_SIGNALING_FLAGLEN)) goto trunctlv; ND_PRINT((ndo, "\n\t Flags [%s]", bittok2str(isis_restart_flag_values, "none", *tptr))); tptr+=ISIS_TLV_RESTART_SIGNALING_FLAGLEN; tmp-=ISIS_TLV_RESTART_SIGNALING_FLAGLEN; /* is there anything other than the flags field? */ if (tmp == 0) break; if (tmp < ISIS_TLV_RESTART_SIGNALING_HOLDTIMELEN) break; if (!ND_TTEST2(*tptr, ISIS_TLV_RESTART_SIGNALING_HOLDTIMELEN)) goto trunctlv; ND_PRINT((ndo, ", Remaining holding time %us", EXTRACT_16BITS(tptr))); tptr+=ISIS_TLV_RESTART_SIGNALING_HOLDTIMELEN; tmp-=ISIS_TLV_RESTART_SIGNALING_HOLDTIMELEN; /* is there an additional sysid field present ?*/ if (tmp == SYSTEM_ID_LEN) { if (!ND_TTEST2(*tptr, SYSTEM_ID_LEN)) goto trunctlv; ND_PRINT((ndo, ", for %s", isis_print_id(tptr,SYSTEM_ID_LEN))); } break; case ISIS_TLV_IDRP_INFO: if (tmp < ISIS_TLV_IDRP_INFO_MINLEN) break; if (!ND_TTEST2(*tptr, ISIS_TLV_IDRP_INFO_MINLEN)) goto trunctlv; ND_PRINT((ndo, "\n\t Inter-Domain Information Type: %s", tok2str(isis_subtlv_idrp_values, "Unknown (0x%02x)", *tptr))); switch (*tptr++) { case ISIS_SUBTLV_IDRP_ASN: if (!ND_TTEST2(*tptr, 2)) /* fetch AS number */ goto trunctlv; ND_PRINT((ndo, "AS Number: %u", EXTRACT_16BITS(tptr))); break; case ISIS_SUBTLV_IDRP_LOCAL: case ISIS_SUBTLV_IDRP_RES: default: if (!print_unknown_data(ndo, tptr, "\n\t ", tlv_len - 1)) return(0); break; } break; case ISIS_TLV_LSP_BUFFERSIZE: if (tmp < ISIS_TLV_LSP_BUFFERSIZE_MINLEN) break; if (!ND_TTEST2(*tptr, ISIS_TLV_LSP_BUFFERSIZE_MINLEN)) goto trunctlv; ND_PRINT((ndo, "\n\t LSP Buffersize: %u", EXTRACT_16BITS(tptr))); break; case ISIS_TLV_PART_DIS: while (tmp >= SYSTEM_ID_LEN) { if (!ND_TTEST2(*tptr, SYSTEM_ID_LEN)) goto trunctlv; ND_PRINT((ndo, "\n\t %s", isis_print_id(tptr, SYSTEM_ID_LEN))); tptr+=SYSTEM_ID_LEN; tmp-=SYSTEM_ID_LEN; } break; case ISIS_TLV_PREFIX_NEIGH: if (tmp < sizeof(struct isis_metric_block)) break; if (!ND_TTEST2(*tptr, sizeof(struct isis_metric_block))) goto trunctlv; ND_PRINT((ndo, "\n\t Metric Block")); isis_print_metric_block(ndo, (const struct isis_metric_block *)tptr); tptr+=sizeof(struct isis_metric_block); tmp-=sizeof(struct isis_metric_block); while(tmp>0) { if (!ND_TTEST2(*tptr, 1)) goto trunctlv; prefix_len=*tptr++; /* read out prefix length in semioctets*/ if (prefix_len < 2) { ND_PRINT((ndo, "\n\t\tAddress: prefix length %u < 2", prefix_len)); break; } tmp--; if (tmp < prefix_len/2) break; if (!ND_TTEST2(*tptr, prefix_len / 2)) goto trunctlv; ND_PRINT((ndo, "\n\t\tAddress: %s/%u", isonsap_string(tptr, prefix_len / 2), prefix_len * 4)); tptr+=prefix_len/2; tmp-=prefix_len/2; } break; case ISIS_TLV_IIH_SEQNR: if (tmp < ISIS_TLV_IIH_SEQNR_MINLEN) break; if (!ND_TTEST2(*tptr, ISIS_TLV_IIH_SEQNR_MINLEN)) /* check if four bytes are on the wire */ goto trunctlv; ND_PRINT((ndo, "\n\t Sequence number: %u", EXTRACT_32BITS(tptr))); break; case ISIS_TLV_VENDOR_PRIVATE: if (tmp < ISIS_TLV_VENDOR_PRIVATE_MINLEN) break; if (!ND_TTEST2(*tptr, ISIS_TLV_VENDOR_PRIVATE_MINLEN)) /* check if enough byte for a full oui */ goto trunctlv; vendor_id = EXTRACT_24BITS(tptr); ND_PRINT((ndo, "\n\t Vendor: %s (%u)", tok2str(oui_values, "Unknown", vendor_id), vendor_id)); tptr+=3; tmp-=3; if (tmp > 0) /* hexdump the rest */ if (!print_unknown_data(ndo, tptr, "\n\t\t", tmp)) 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; } /* 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((ndo, "\n\t %u straggler bytes", packet_len)); } return (1); trunc: ND_PRINT((ndo, "[|isis]")); return (1); trunctlv: ND_PRINT((ndo, "\n\t\t packet exceeded snapshot")); return(1); } static void osi_print_cksum(netdissect_options *ndo, const uint8_t *pptr, uint16_t checksum, u_int checksum_offset, u_int length) { uint16_t calculated_checksum; - /* do not attempt to verify the checksum if it is zero */ - if (!checksum) { + /* do not attempt to verify the checksum if it is zero, + * if the total length is nonsense, + * if the offset is nonsense, + * or the base pointer is not sane + */ + if (!checksum + || length > (u_int)ndo->ndo_snaplen + || checksum_offset > (uint)ndo->ndo_snaplen + || checksum_offset > length) { ND_PRINT((ndo, "(unverified)")); } else { + unsigned char *truncated = "trunc"; +#if 0 + printf("\nosi_print_cksum: %p %u %u %u\n", pptr, checksum_offset, length, ndo->ndo_snaplen); + ND_TCHECK2(pptr, checksum_offset+length); +#endif calculated_checksum = create_osi_cksum(pptr, checksum_offset, length); if (checksum == calculated_checksum) { ND_PRINT((ndo, " (correct)")); } else { - ND_PRINT((ndo, " (incorrect should be 0x%04x)", calculated_checksum)); + truncated = "incorrect"; +#if 0 + trunc: +#endif + ND_PRINT((ndo, " (%s should be 0x%04x)", truncated, calculated_checksum)); } } } /* * Local Variables: * c-style: whitesmith * c-basic-offset: 8 * End: */ Index: head/contrib/tcpdump/print-juniper.c =================================================================== --- head/contrib/tcpdump/print-juniper.c (revision 285274) +++ head/contrib/tcpdump/print-juniper.c (revision 285275) @@ -1,1472 +1,1464 @@ /* 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@juniper.net) */ #ifndef lint #else __RCSID("NetBSD: print-juniper.c,v 1.3 2007/07/25 06:31:32 dogcow Exp "); #endif #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "interface.h" #include "addrtoname.h" #include "extract.h" #include "ppp.h" #include "llc.h" #include "nlpid.h" #include "ethertype.h" #include "atm.h" #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 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} }; 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 2 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; uint8_t header_len; uint8_t cookie_len; uint8_t cookie_type; uint8_t cookie[8]; uint8_t 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 static const struct tok juniper_protocol_values[] = { { JUNIPER_PROTO_NULL, "Null" }, { JUNIPER_PROTO_IPV4, "IPv4" }, { JUNIPER_PROTO_IPV6, "IPv6" }, { 0, NULL} }; static int ip_heuristic_guess(netdissect_options *, register const u_char *, u_int); static int juniper_ppp_heuristic_guess(netdissect_options *, register const u_char *, u_int); static int juniper_parse_header(netdissect_options *, const u_char *, const struct pcap_pkthdr *, struct juniper_l2info_t *); #ifdef DLT_JUNIPER_GGSN u_int juniper_ggsn_print(netdissect_options *ndo, const struct pcap_pkthdr *h, register const u_char *p) { struct juniper_l2info_t l2info; struct juniper_ggsn_header { uint8_t svc_id; uint8_t flags_len; uint8_t proto; uint8_t flags; uint8_t vlan_id[2]; uint8_t res[2]; }; const struct juniper_ggsn_header *gh; l2info.pictype = DLT_JUNIPER_GGSN; if (juniper_parse_header(ndo, p, h, &l2info) == 0) return l2info.header_len; p+=l2info.header_len; gh = (struct juniper_ggsn_header *)&l2info.cookie; if (ndo->ndo_eflag) { ND_PRINT((ndo, "proto %s (%u), vlan %u: ", tok2str(juniper_protocol_values,"Unknown",gh->proto), gh->proto, EXTRACT_16BITS(&gh->vlan_id[0]))); } switch (gh->proto) { case JUNIPER_PROTO_IPV4: ip_print(ndo, p, l2info.length); break; -#ifdef INET6 case JUNIPER_PROTO_IPV6: ip6_print(ndo, p, l2info.length); break; -#endif /* INET6 */ default: if (!ndo->ndo_eflag) ND_PRINT((ndo, "unknown GGSN proto (%u)", gh->proto)); } return l2info.header_len; } #endif #ifdef DLT_JUNIPER_ES u_int juniper_es_print(netdissect_options *ndo, const struct pcap_pkthdr *h, register const u_char *p) { struct juniper_l2info_t l2info; struct juniper_ipsec_header { uint8_t sa_index[2]; uint8_t ttl; uint8_t type; uint8_t spi[4]; uint8_t src_ip[4]; uint8_t dst_ip[4]; }; u_int rewrite_len,es_type_bundle; const struct juniper_ipsec_header *ih; l2info.pictype = DLT_JUNIPER_ES; if (juniper_parse_header(ndo, p, h, &l2info) == 0) return l2info.header_len; p+=l2info.header_len; ih = (struct juniper_ipsec_header *)p; switch (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((ndo, "ES Invalid type %u, length %u", ih->type, l2info.length)); return l2info.header_len; } l2info.length-=rewrite_len; p+=rewrite_len; if (ndo->ndo_eflag) { if (!es_type_bundle) { ND_PRINT((ndo, "ES SA, index %u, ttl %u type %s (%u), spi %u, Tunnel %s > %s, length %u\n", EXTRACT_16BITS(&ih->sa_index), ih->ttl, tok2str(juniper_ipsec_type_values,"Unknown",ih->type), ih->type, EXTRACT_32BITS(&ih->spi), ipaddr_string(ndo, &ih->src_ip), ipaddr_string(ndo, &ih->dst_ip), l2info.length)); } else { ND_PRINT((ndo, "ES SA, index %u, ttl %u type %s (%u), length %u\n", EXTRACT_16BITS(&ih->sa_index), ih->ttl, tok2str(juniper_ipsec_type_values,"Unknown",ih->type), ih->type, l2info.length)); } } ip_print(ndo, p, l2info.length); return l2info.header_len; } #endif #ifdef DLT_JUNIPER_MONITOR u_int juniper_monitor_print(netdissect_options *ndo, const struct pcap_pkthdr *h, register const u_char *p) { struct juniper_l2info_t l2info; struct juniper_monitor_header { uint8_t pkt_type; uint8_t padding; uint8_t iif[2]; uint8_t service_id[4]; }; const struct juniper_monitor_header *mh; l2info.pictype = DLT_JUNIPER_MONITOR; if (juniper_parse_header(ndo, p, h, &l2info) == 0) return l2info.header_len; p+=l2info.header_len; mh = (struct juniper_monitor_header *)p; if (ndo->ndo_eflag) ND_PRINT((ndo, "service-id %u, iif %u, pkt-type %u: ", EXTRACT_32BITS(&mh->service_id), EXTRACT_16BITS(&mh->iif), mh->pkt_type)); /* no proto field - lets guess by first byte of IP header*/ ip_heuristic_guess (ndo, p, l2info.length); return l2info.header_len; } #endif #ifdef DLT_JUNIPER_SERVICES u_int juniper_services_print(netdissect_options *ndo, const struct pcap_pkthdr *h, register const u_char *p) { struct juniper_l2info_t l2info; struct juniper_services_header { uint8_t svc_id; uint8_t flags_len; uint8_t svc_set_id[2]; uint8_t dir_iif[4]; }; const struct juniper_services_header *sh; l2info.pictype = DLT_JUNIPER_SERVICES; if (juniper_parse_header(ndo, p, h, &l2info) == 0) return l2info.header_len; p+=l2info.header_len; sh = (struct juniper_services_header *)p; if (ndo->ndo_eflag) ND_PRINT((ndo, "service-id %u flags 0x%02x service-set-id 0x%04x iif %u: ", sh->svc_id, sh->flags_len, EXTRACT_16BITS(&sh->svc_set_id), EXTRACT_24BITS(&sh->dir_iif[1]))); /* no proto field - lets guess by first byte of IP header*/ ip_heuristic_guess (ndo, p, l2info.length); return l2info.header_len; } #endif #ifdef DLT_JUNIPER_PPPOE u_int juniper_pppoe_print(netdissect_options *ndo, const struct pcap_pkthdr *h, register const u_char *p) { struct juniper_l2info_t l2info; l2info.pictype = DLT_JUNIPER_PPPOE; if (juniper_parse_header(ndo, p, h, &l2info) == 0) return l2info.header_len; p+=l2info.header_len; /* this DLT contains nothing but raw ethernet frames */ ether_print(ndo, p, l2info.length, l2info.caplen, NULL, NULL); return l2info.header_len; } #endif #ifdef DLT_JUNIPER_ETHER u_int juniper_ether_print(netdissect_options *ndo, const struct pcap_pkthdr *h, register const u_char *p) { struct juniper_l2info_t l2info; l2info.pictype = DLT_JUNIPER_ETHER; if (juniper_parse_header(ndo, p, h, &l2info) == 0) return l2info.header_len; p+=l2info.header_len; /* this DLT contains nothing but raw Ethernet frames */ ether_print(ndo, p, l2info.length, l2info.caplen, NULL, NULL); return l2info.header_len; } #endif #ifdef DLT_JUNIPER_PPP u_int juniper_ppp_print(netdissect_options *ndo, const struct pcap_pkthdr *h, register const u_char *p) { struct juniper_l2info_t l2info; l2info.pictype = DLT_JUNIPER_PPP; if (juniper_parse_header(ndo, p, h, &l2info) == 0) return l2info.header_len; p+=l2info.header_len; /* this DLT contains nothing but raw ppp frames */ ppp_print(ndo, p, l2info.length); return l2info.header_len; } #endif #ifdef DLT_JUNIPER_FRELAY u_int juniper_frelay_print(netdissect_options *ndo, const struct pcap_pkthdr *h, register const u_char *p) { struct juniper_l2info_t l2info; l2info.pictype = DLT_JUNIPER_FRELAY; if (juniper_parse_header(ndo, p, h, &l2info) == 0) return l2info.header_len; p+=l2info.header_len; /* this DLT contains nothing but raw frame-relay frames */ fr_print(ndo, p, l2info.length); return l2info.header_len; } #endif #ifdef DLT_JUNIPER_CHDLC u_int juniper_chdlc_print(netdissect_options *ndo, const struct pcap_pkthdr *h, register const u_char *p) { struct juniper_l2info_t l2info; l2info.pictype = DLT_JUNIPER_CHDLC; if (juniper_parse_header(ndo, p, h, &l2info) == 0) return l2info.header_len; p+=l2info.header_len; /* this DLT contains nothing but raw c-hdlc frames */ chdlc_print(ndo, p, l2info.length); return l2info.header_len; } #endif #ifdef DLT_JUNIPER_PPPOE_ATM u_int juniper_pppoe_atm_print(netdissect_options *ndo, const struct pcap_pkthdr *h, register const u_char *p) { struct juniper_l2info_t l2info; uint16_t extracted_ethertype; l2info.pictype = DLT_JUNIPER_PPPOE_ATM; if (juniper_parse_header(ndo, p, h, &l2info) == 0) return l2info.header_len; p+=l2info.header_len; extracted_ethertype = EXTRACT_16BITS(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) == 0) /* ether_type not known, probably it wasn't one */ ND_PRINT((ndo, "unknown ethertype 0x%04x", extracted_ethertype)); return l2info.header_len; } #endif #ifdef DLT_JUNIPER_MLPPP u_int juniper_mlppp_print(netdissect_options *ndo, const struct pcap_pkthdr *h, register const u_char *p) { struct juniper_l2info_t l2info; l2info.pictype = DLT_JUNIPER_MLPPP; if (juniper_parse_header(ndo, p, h, &l2info) == 0) return l2info.header_len; /* suppress Bundle-ID if frame was captured on a child-link * best indicator if the cookie looks like a proto */ if (ndo->ndo_eflag && EXTRACT_16BITS(&l2info.cookie) != PPP_OSI && EXTRACT_16BITS(&l2info.cookie) != (PPP_ADDRESS << 8 | PPP_CONTROL)) ND_PRINT((ndo, "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); return l2info.header_len; -#ifdef INET6 case JUNIPER_LSQ_L3_PROTO_IPV6: ip6_print(ndo, p,l2info.length); return l2info.header_len; -#endif case JUNIPER_LSQ_L3_PROTO_MPLS: mpls_print(ndo, p, l2info.length); return l2info.header_len; case JUNIPER_LSQ_L3_PROTO_ISO: isoclns_print(ndo, p, l2info.length, l2info.caplen); return l2info.header_len; default: break; } /* zero length cookie ? */ switch (EXTRACT_16BITS(&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; } return l2info.header_len; } #endif #ifdef DLT_JUNIPER_MFR u_int juniper_mfr_print(netdissect_options *ndo, const struct pcap_pkthdr *h, register const u_char *p) { struct juniper_l2info_t l2info; l2info.pictype = DLT_JUNIPER_MFR; if (juniper_parse_header(ndo, p, h, &l2info) == 0) return l2info.header_len; p+=l2info.header_len; /* child-link ? */ if (l2info.cookie_len == 0) { mfr_print(ndo, p, l2info.length); return l2info.header_len; } /* 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); return l2info.header_len; -#ifdef INET6 case JUNIPER_LSQ_L3_PROTO_IPV6: ip6_print(ndo, p,l2info.length); return l2info.header_len; -#endif case JUNIPER_LSQ_L3_PROTO_MPLS: mpls_print(ndo, p, l2info.length); return l2info.header_len; case JUNIPER_LSQ_L3_PROTO_ISO: isoclns_print(ndo, p, l2info.length, l2info.caplen); return l2info.header_len; default: break; } return l2info.header_len; } /* suppress Bundle-ID if frame was captured on a child-link */ if (ndo->ndo_eflag && EXTRACT_32BITS(l2info.cookie) != 1) ND_PRINT((ndo, "Bundle-ID %u, ", l2info.bundle)); switch (l2info.proto) { case (LLCSAP_ISONS<<8 | LLCSAP_ISONS): isoclns_print(ndo, p + 1, l2info.length - 1, l2info.caplen - 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, l2info.caplen + 1); break; default: ND_PRINT((ndo, "unknown protocol 0x%04x, length %u", l2info.proto, l2info.length)); } return l2info.header_len; } #endif #ifdef DLT_JUNIPER_MLFR u_int juniper_mlfr_print(netdissect_options *ndo, const struct pcap_pkthdr *h, register const u_char *p) { struct juniper_l2info_t l2info; l2info.pictype = DLT_JUNIPER_MLFR; if (juniper_parse_header(ndo, p, h, &l2info) == 0) return l2info.header_len; p+=l2info.header_len; /* suppress Bundle-ID if frame was captured on a child-link */ if (ndo->ndo_eflag && EXTRACT_32BITS(l2info.cookie) != 1) ND_PRINT((ndo, "Bundle-ID %u, ", l2info.bundle)); switch (l2info.proto) { case (LLC_UI): case (LLC_UI<<8): isoclns_print(ndo, p, l2info.length, l2info.caplen); 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, l2info.caplen + 1); break; default: ND_PRINT((ndo, "unknown protocol 0x%04x, length %u", l2info.proto, l2info.length)); } return l2info.header_len; } #endif /* * ATM1 PIC cookie format * * +-----+-------------------------+-------------------------------+ * |fmtid| vc index | channel ID | * +-----+-------------------------+-------------------------------+ */ #ifdef DLT_JUNIPER_ATM1 u_int juniper_atm1_print(netdissect_options *ndo, const struct pcap_pkthdr *h, register const u_char *p) { uint16_t extracted_ethertype; struct juniper_l2info_t l2info; l2info.pictype = DLT_JUNIPER_ATM1; if (juniper_parse_header(ndo, p, h, &l2info) == 0) return l2info.header_len; p+=l2info.header_len; if (l2info.cookie[0] == 0x80) { /* OAM cell ? */ oam_print(ndo, p, l2info.length, ATM_OAM_NOHEC); return l2info.header_len; } if (EXTRACT_24BITS(p) == 0xfefe03 || /* NLPID encaps ? */ EXTRACT_24BITS(p) == 0xaaaa03) { /* SNAP encaps ? */ if (llc_print(ndo, p, l2info.length, l2info.caplen, NULL, NULL, &extracted_ethertype) != 0) return l2info.header_len; } if (p[0] == 0x03) { /* Cisco style NLPID encaps ? */ isoclns_print(ndo, p + 1, l2info.length - 1, l2info.caplen - 1); /* FIXME check if frame was recognized */ return l2info.header_len; } if (ip_heuristic_guess(ndo, p, l2info.length) != 0) /* last try - vcmux encaps ? */ return l2info.header_len; return l2info.header_len; } #endif /* * ATM2 PIC cookie format * * +-------------------------------+---------+---+-----+-----------+ * | channel ID | reserv |AAL| CCRQ| gap cnt | * +-------------------------------+---------+---+-----+-----------+ */ #ifdef DLT_JUNIPER_ATM2 u_int juniper_atm2_print(netdissect_options *ndo, const struct pcap_pkthdr *h, register const u_char *p) { uint16_t extracted_ethertype; struct juniper_l2info_t l2info; l2info.pictype = DLT_JUNIPER_ATM2; if (juniper_parse_header(ndo, p, h, &l2info) == 0) return l2info.header_len; p+=l2info.header_len; if (l2info.cookie[7] & ATM2_PKT_TYPE_MASK) { /* OAM cell ? */ oam_print(ndo, p, l2info.length, ATM_OAM_NOHEC); return l2info.header_len; } if (EXTRACT_24BITS(p) == 0xfefe03 || /* NLPID encaps ? */ EXTRACT_24BITS(p) == 0xaaaa03) { /* SNAP encaps ? */ if (llc_print(ndo, p, l2info.length, l2info.caplen, NULL, NULL, &extracted_ethertype) != 0) return l2info.header_len; } if (l2info.direction != JUNIPER_BPF_PKT_IN && /* ether-over-1483 encaps ? */ (EXTRACT_32BITS(l2info.cookie) & ATM2_GAP_COUNT_MASK)) { ether_print(ndo, p, l2info.length, l2info.caplen, NULL, NULL); return l2info.header_len; } if (p[0] == 0x03) { /* Cisco style NLPID encaps ? */ isoclns_print(ndo, p + 1, l2info.length - 1, l2info.caplen - 1); /* FIXME check if frame was recognized */ return l2info.header_len; } if(juniper_ppp_heuristic_guess(ndo, p, l2info.length) != 0) /* PPPoA vcmux encaps ? */ return l2info.header_len; if (ip_heuristic_guess(ndo, p, l2info.length) != 0) /* last try - vcmux encaps ? */ return l2info.header_len; return l2info.header_len; } #endif /* 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, - register const u_char *p, u_int length) { - + register const u_char *p, u_int length) +{ switch(EXTRACT_16BITS(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 : #ifdef INET6 case PPP_IPV6 : case PPP_IPV6CP : #endif ppp_print(ndo, p, length); break; default: return 0; /* did not find a ppp header */ break; } return 1; /* we printed a ppp packet */ } static int ip_heuristic_guess(netdissect_options *ndo, - register const u_char *p, u_int length) { - + register const u_char *p, u_int length) +{ switch(p[0]) { 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; -#ifdef INET6 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; -#endif default: return 0; /* did not find a ip header */ break; } return 1; /* we printed an v4/v6 packet */ } static int -juniper_read_tlv_value(const u_char *p, u_int tlv_type, u_int tlv_len) { - +juniper_read_tlv_value(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 = *p; break; case 2: tlv_value = EXTRACT_LE_16BITS(p); break; case 3: tlv_value = EXTRACT_LE_24BITS(p); break; case 4: tlv_value = EXTRACT_LE_32BITS(p); break; default: tlv_value = -1; break; } } else { /* TLVs >= 128 are big endian encoded */ switch (tlv_len) { case 1: tlv_value = *p; break; case 2: tlv_value = EXTRACT_16BITS(p); break; case 3: tlv_value = EXTRACT_24BITS(p); break; case 4: tlv_value = EXTRACT_32BITS(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 u_char *p, const struct pcap_pkthdr *h, struct juniper_l2info_t *l2info) +{ const struct juniper_cookie_table_t *lp = juniper_cookie_table; u_int idx, jnx_ext_len, jnx_header_len = 0; uint8_t tlv_type,tlv_len; uint32_t control_word; 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; ND_TCHECK2(p[0], 4); l2info->flags = p[3]; l2info->direction = p[3]&JUNIPER_BPF_PKT_IN; if (EXTRACT_24BITS(p) != JUNIPER_MGC_NUMBER) { /* magic number found ? */ ND_PRINT((ndo, "no magic-number found!")); return 0; } if (ndo->ndo_eflag) /* print direction */ ND_PRINT((ndo, "%3s ", tok2str(juniper_direction_values, "---", l2info->direction))); /* magic number + flags */ jnx_header_len = 4; if (ndo->ndo_vflag > 1) ND_PRINT((ndo, "\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 ? */ ND_TCHECK2(tptr[0], 2); jnx_ext_len = EXTRACT_16BITS(tptr); jnx_header_len += 2; tptr +=2; /* nail up the total length - * just in case something goes wrong * with TLV parsing */ jnx_header_len += jnx_ext_len; if (ndo->ndo_vflag > 1) ND_PRINT((ndo, ", PCAP Extension(s) total length %u", jnx_ext_len)); ND_TCHECK2(tptr[0], jnx_ext_len); while (jnx_ext_len > JUNIPER_EXT_TLV_OVERHEAD) { tlv_type = *(tptr++); tlv_len = *(tptr++); tlv_value = 0; /* sanity check */ if (tlv_type == 0 || tlv_len == 0) break; if (ndo->ndo_vflag > 1) ND_PRINT((ndo, "\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(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((ndo, "%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((ndo, "%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((ndo, "%u", tlv_value)); } break; } tptr+=tlv_len; jnx_ext_len -= tlv_len+JUNIPER_EXT_TLV_OVERHEAD; } if (ndo->ndo_vflag > 1) ND_PRINT((ndo, "\n\t-----original packet-----\n\t")); } if ((l2info->flags & JUNIPER_BPF_NO_L2 ) == JUNIPER_BPF_NO_L2 ) { if (ndo->ndo_eflag) ND_PRINT((ndo, "no-L2-hdr, ")); /* there is no link-layer present - * perform the v4/v6 heuristics * to figure out what it is */ ND_TCHECK2(p[jnx_header_len + 4], 1); if (ip_heuristic_guess(ndo, p + jnx_header_len + 4, l2info->length - (jnx_header_len + 4)) == 0) ND_PRINT((ndo, "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 and copy values matching for our PIC type */ while (lp->s != NULL) { if (lp->pictype == l2info->pictype) { l2info->cookie_len += lp->cookie_len; switch (p[0]) { 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 && (p[0] & 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((ndo, "%s-PIC, cookie-len %u", lp->s, l2info->cookie_len)); if (l2info->cookie_len > 0) { ND_TCHECK2(p[0], l2info->cookie_len); if (ndo->ndo_eflag) ND_PRINT((ndo, ", cookie 0x")); for (idx = 0; idx < l2info->cookie_len; idx++) { l2info->cookie[idx] = p[idx]; /* copy cookie data */ if (ndo->ndo_eflag) ND_PRINT((ndo, "%02x", p[idx])); } } if (ndo->ndo_eflag) ND_PRINT((ndo, ": ")); /* print demarc b/w L2/L3*/ l2info->proto = EXTRACT_16BITS(p+l2info->cookie_len); break; } ++lp; } 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: l2info->bundle = (EXTRACT_16BITS(&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 = EXTRACT_16BITS(p); l2info->header_len += 2; l2info->length -= 2; l2info->caplen -= 2; break; case AS_COOKIE_ID: l2info->bundle = (EXTRACT_16BITS(&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 = EXTRACT_16BITS(p); l2info->header_len += 2; l2info->length -= 2; l2info->caplen -= 2; break; case AS_COOKIE_ID: l2info->bundle = (EXTRACT_16BITS(&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_TCHECK2(p[0], 4); /* ATM cell relay control word present ? */ if (l2info->cookie[7] & ATM2_PKT_TYPE_MASK) { control_word = EXTRACT_32BITS(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((ndo, "control-word 0x%08x ", control_word)); } break; #endif #ifdef DLT_JUNIPER_GGSN case DLT_JUNIPER_GGSN: 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 default: ND_PRINT((ndo, "Unknown Juniper DLT_ type %u: ", l2info->pictype)); break; } if (ndo->ndo_eflag > 1) ND_PRINT((ndo, "hlen %u, proto 0x%04x, ", l2info->header_len, l2info->proto)); return 1; /* everything went ok so far. continue parsing */ trunc: ND_PRINT((ndo, "[|juniper_hdr], length %u", h->len)); return 0; } /* * Local Variables: * c-style: whitesmith * c-basic-offset: 4 * End: */ Index: head/contrib/tcpdump/print-ldp.c =================================================================== --- head/contrib/tcpdump/print-ldp.c (revision 285274) +++ head/contrib/tcpdump/print-ldp.c (revision 285275) @@ -1,674 +1,699 @@ /* * 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@juniper.net) * and Steinar Haug (sthaug@nethelp.no) */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "interface.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 { uint8_t version[2]; uint8_t pdu_length[2]; uint8_t lsr_id[4]; uint8_t label_space[2]; }; #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 { uint8_t type[2]; uint8_t length[2]; uint8_t id[4]; }; #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 int ldp_msg_print(netdissect_options *, register const u_char *); +static int ldp_pdu_print(netdissect_options *, register 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) \ ND_TCHECK2(*tptr, minlen); if (tlv_tlen < minlen) goto badtlv; static int ldp_tlv_print(netdissect_options *ndo, - register const u_char *tptr) { - + register const u_char *tptr, + u_short msg_tlen) +{ struct ldp_tlv_header { uint8_t type[2]; uint8_t length[2]; }; 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(*ldp_tlv_header); tlv_len=EXTRACT_16BITS(ldp_tlv_header->length); + if (tlv_len + 4 > msg_tlen) { + ND_PRINT((ndo, "\n\t\t TLV contents go past end of message")); + return 0; + } tlv_tlen=tlv_len; tlv_type=LDP_MASK_TLV_TYPE(EXTRACT_16BITS(ldp_tlv_header->type)); /* FIXME vendor private / experimental check */ ND_PRINT((ndo, "\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(EXTRACT_16BITS(&ldp_tlv_header->type)) ? "continue processing" : "ignore", LDP_MASK_F_BIT(EXTRACT_16BITS(&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((ndo, "\n\t Hold Time: %us, Flags: [%s Hello%s]", EXTRACT_16BITS(tptr), (EXTRACT_16BITS(tptr+2)&0x8000) ? "Targeted" : "Link", (EXTRACT_16BITS(tptr+2)&0x4000) ? ", Request for targeted Hellos" : "")); break; case LDP_TLV_IPV4_TRANSPORT_ADDR: TLV_TCHECK(4); ND_PRINT((ndo, "\n\t IPv4 Transport Address: %s", ipaddr_string(ndo, tptr))); break; #ifdef INET6 case LDP_TLV_IPV6_TRANSPORT_ADDR: TLV_TCHECK(16); ND_PRINT((ndo, "\n\t IPv6 Transport Address: %s", ip6addr_string(ndo, tptr))); break; #endif case LDP_TLV_CONFIG_SEQ_NUMBER: TLV_TCHECK(4); ND_PRINT((ndo, "\n\t Sequence Number: %u", EXTRACT_32BITS(tptr))); break; case LDP_TLV_ADDRESS_LIST: TLV_TCHECK(LDP_TLV_ADDRESS_LIST_AFNUM_LEN); af = EXTRACT_16BITS(tptr); tptr+=LDP_TLV_ADDRESS_LIST_AFNUM_LEN; tlv_tlen -= LDP_TLV_ADDRESS_LIST_AFNUM_LEN; ND_PRINT((ndo, "\n\t Address Family: %s, addresses", tok2str(af_values, "Unknown (%u)", af))); switch (af) { case AFNUM_INET: while(tlv_tlen >= sizeof(struct in_addr)) { ND_TCHECK2(*tptr, sizeof(struct in_addr)); ND_PRINT((ndo, " %s", ipaddr_string(ndo, tptr))); tlv_tlen-=sizeof(struct in_addr); tptr+=sizeof(struct in_addr); } break; #ifdef INET6 case AFNUM_INET6: while(tlv_tlen >= sizeof(struct in6_addr)) { ND_TCHECK2(*tptr, sizeof(struct in6_addr)); ND_PRINT((ndo, " %s", ip6addr_string(ndo, tptr))); tlv_tlen-=sizeof(struct in6_addr); tptr+=sizeof(struct in6_addr); } break; #endif default: /* unknown AF */ break; } break; case LDP_TLV_COMMON_SESSION: TLV_TCHECK(8); ND_PRINT((ndo, "\n\t Version: %u, Keepalive: %us, Flags: [Downstream %s, Loop Detection %s]", EXTRACT_16BITS(tptr), EXTRACT_16BITS(tptr+2), (EXTRACT_16BITS(tptr+6)&0x8000) ? "On Demand" : "Unsolicited", (EXTRACT_16BITS(tptr+6)&0x4000) ? "Enabled" : "Disabled" )); break; case LDP_TLV_FEC: TLV_TCHECK(1); fec_type = *tptr; ND_PRINT((ndo, "\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 = EXTRACT_16BITS(tptr); tptr+=LDP_TLV_ADDRESS_LIST_AFNUM_LEN; tlv_tlen-=LDP_TLV_ADDRESS_LIST_AFNUM_LEN; if (af == AFNUM_INET) { i=decode_prefix4(ndo, tptr, tlv_tlen, buf, sizeof(buf)); if (i == -2) goto trunc; if (i == -3) ND_PRINT((ndo, ": IPv4 prefix (goes past end of TLV)")); else if (i == -1) ND_PRINT((ndo, ": IPv4 prefix (invalid length)")); else ND_PRINT((ndo, ": IPv4 prefix %s", buf)); } #ifdef 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((ndo, ": IPv4 prefix (goes past end of TLV)")); else if (i == -1) ND_PRINT((ndo, ": IPv6 prefix (invalid length)")); else ND_PRINT((ndo, ": IPv6 prefix %s", buf)); } #endif else ND_PRINT((ndo, ": Address family %u prefix", af)); break; case LDP_FEC_HOSTADDRESS: break; case LDP_FEC_MARTINI_VC: /* * 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. */ TLV_TCHECK(7); vc_info_len = *(tptr+2); if (vc_info_len == 0) { ND_PRINT((ndo, ": %s, %scontrol word, group-ID %u, VC-info-length: %u", tok2str(l2vpn_encaps_values, "Unknown", EXTRACT_16BITS(tptr)&0x7fff), EXTRACT_16BITS(tptr)&0x8000 ? "" : "no ", EXTRACT_32BITS(tptr+3), vc_info_len)); break; } /* Make sure we have the VC ID as well */ TLV_TCHECK(11); ND_PRINT((ndo, ": %s, %scontrol word, group-ID %u, VC-ID %u, VC-info-length: %u", tok2str(l2vpn_encaps_values, "Unknown", EXTRACT_16BITS(tptr)&0x7fff), EXTRACT_16BITS(tptr)&0x8000 ? "" : "no ", EXTRACT_32BITS(tptr+3), EXTRACT_32BITS(tptr+7), vc_info_len)); - if (vc_info_len < 4) - goto trunc; /* minimum 4, for the VC ID */ + if (vc_info_len < 4) { + /* minimum 4, for the VC ID */ + ND_PRINT((ndo, " (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 = *tptr; vc_info_tlv_len = *(tptr+1); if (vc_info_tlv_len < 2) break; if (vc_info_len < vc_info_tlv_len) break; ND_PRINT((ndo, "\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((ndo, ": %u", EXTRACT_16BITS(tptr+2))); break; case LDP_FEC_MARTINI_IFPARM_DESC: ND_PRINT((ndo, ": ")); for (idx = 2; idx < vc_info_tlv_len; idx++) safeputchar(ndo, *(tptr + idx)); break; case LDP_FEC_MARTINI_IFPARM_VCCV: ND_PRINT((ndo, "\n\t\t Control Channels (0x%02x) = [%s]", *(tptr+2), bittok2str(ldp_fec_martini_ifparm_vccv_cc_values, "none", *(tptr+2)))); ND_PRINT((ndo, "\n\t\t CV Types (0x%02x) = [%s]", *(tptr+3), bittok2str(ldp_fec_martini_ifparm_vccv_cv_values, "none", *(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((ndo, "\n\t Label: %u", EXTRACT_32BITS(tptr) & 0xfffff)); break; case LDP_TLV_STATUS: TLV_TCHECK(8); ui = EXTRACT_32BITS(tptr); tptr+=4; ND_PRINT((ndo, "\n\t Status: 0x%02x, Flags: [%s and %s forward]", ui&0x3fffffff, ui&0x80000000 ? "Fatal error" : "Advisory Notification", ui&0x40000000 ? "do" : "don't")); ui = EXTRACT_32BITS(tptr); tptr+=4; if (ui) ND_PRINT((ndo, ", causing Message ID: 0x%08x", ui)); break; case LDP_TLV_FT_SESSION: TLV_TCHECK(8); ft_flags = EXTRACT_16BITS(tptr); ND_PRINT((ndo, "\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 ")); tptr+=4; ui = EXTRACT_32BITS(tptr); if (ui) ND_PRINT((ndo, ", Reconnect Timeout: %ums", ui)); tptr+=4; ui = EXTRACT_32BITS(tptr); if (ui) ND_PRINT((ndo, ", Recovery Time: %ums", ui)); break; case LDP_TLV_MTU: TLV_TCHECK(2); ND_PRINT((ndo, "\n\t MTU: %u", EXTRACT_16BITS(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_PRINT((ndo, "\n\t\t packet exceeded snapshot")); return 0; badtlv: ND_PRINT((ndo, "\n\t\t TLV contents go past end of TLV")); return(tlv_len+4); /* Type & Length fields not included */ } void ldp_print(netdissect_options *ndo, - register const u_char *pptr, register u_int len) { - + register const u_char *pptr, register u_int len) +{ int processed; while (len > (sizeof(struct ldp_common_header) + sizeof(struct ldp_msg_header))) { - processed = ldp_msg_print(ndo, pptr); + processed = ldp_pdu_print(ndo, pptr); if (processed == 0) return; len -= processed; pptr += processed; } } static int -ldp_msg_print(netdissect_options *ndo, - register const u_char *pptr) { - +ldp_pdu_print(netdissect_options *ndo, + register 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,msg_tlen; int hexdump,processed; - tptr=pptr; ldp_com_header = (const struct ldp_common_header *)pptr; ND_TCHECK(*ldp_com_header); /* * Sanity checking of the header. */ if (EXTRACT_16BITS(&ldp_com_header->version) != LDP_VERSION) { ND_PRINT((ndo, "%sLDP version %u packet not supported", (ndo->ndo_vflag < 1) ? "" : "\n\t", EXTRACT_16BITS(&ldp_com_header->version))); return 0; } - /* print the LSR-ID, label-space & length */ pdu_len = EXTRACT_16BITS(&ldp_com_header->pdu_length); + if (pdu_len < sizeof(const struct ldp_common_header)-4) { + /* length too short */ + ND_PRINT((ndo, "%sLDP, pdu-length: %u (too short, < %u)", + (ndo->ndo_vflag < 1) ? "" : "\n\t", + pdu_len, + (u_int)(sizeof(const struct ldp_common_header)-4))); + return 0; + } + + /* print the LSR-ID, label-space & length */ ND_PRINT((ndo, "%sLDP, Label-Space-ID: %s:%u, pdu-length: %u", (ndo->ndo_vflag < 1) ? "" : "\n\t", ipaddr_string(ndo, &ldp_com_header->lsr_id), EXTRACT_16BITS(&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 */ - tlen=pdu_len; + tptr = pptr + sizeof(const struct ldp_common_header); + tlen = pdu_len - (sizeof(const struct ldp_common_header)-4); /* Type & Length fields not included */ - tptr += sizeof(const struct ldp_common_header); - tlen -= sizeof(const struct ldp_common_header)-4; /* Type & Length fields not included */ - while(tlen>0) { /* did we capture enough for fully decoding the msg header ? */ ND_TCHECK2(*tptr, sizeof(struct ldp_msg_header)); ldp_msg_header = (const struct ldp_msg_header *)tptr; msg_len=EXTRACT_16BITS(ldp_msg_header->length); msg_type=LDP_MASK_MSG_TYPE(EXTRACT_16BITS(ldp_msg_header->type)); + if (msg_len < sizeof(struct ldp_msg_header)-4) { + /* length too short */ + /* FIXME vendor private / experimental check */ + ND_PRINT((ndo, "\n\t %s Message (0x%04x), length: %u (too short, < %u)", + tok2str(ldp_msg_values, + "Unknown", + msg_type), + msg_type, + msg_len, + (u_int)(sizeof(struct ldp_msg_header)-4))); + return 0; + } + /* FIXME vendor private / experimental check */ ND_PRINT((ndo, "\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, EXTRACT_32BITS(&ldp_msg_header->id), LDP_MASK_U_BIT(EXTRACT_16BITS(&ldp_msg_header->type)) ? "continue processing" : "ignore")); - if (msg_len == 0) /* infinite loop protection */ - return 0; - msg_tptr=tptr+sizeof(struct ldp_msg_header); - msg_tlen=msg_len-sizeof(struct ldp_msg_header)+4; /* Type & Length fields not included */ + 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_TCHECK2(*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); + 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_PRINT((ndo, "\n\t\t packet exceeded snapshot")); return 0; } /* * Local Variables: * c-style: whitesmith * c-basic-offset: 8 * End: */ Index: head/contrib/tcpdump/print-lldp.c =================================================================== --- head/contrib/tcpdump/print-lldp.c (revision 285274) +++ head/contrib/tcpdump/print-lldp.c (revision 285275) @@ -1,1613 +1,1613 @@ /* * 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. * * support for the IEEE Link Discovery Protocol as per 802.1AB * * Original code by Hannes Gredler (hannes@juniper.net) * IEEE and TIA extensions by Carles Kishimoto * DCBX extensions by Kaladhar Musunuru */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "interface.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_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_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_CAPABILTIY (1 << 0) #define LLDP_AGGREGATION_STATUS (1 << 1) static const struct tok lldp_aggregation_values[] = { { LLDP_AGGREGATION_CAPABILTIY, "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 Staion"}, { LLDP_EVB_MODE_RESERVED, "Reserved for future Standardization"}, }; #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 static void print_ets_priority_assignment_table(netdissect_options *ndo, const u_char *ptr) { ND_PRINT((ndo, "\n\t Priority Assignment Table")); ND_PRINT((ndo, "\n\t Priority : 0 1 2 3 4 5 6 7")); ND_PRINT((ndo, "\n\t Value : %-3d %-3d %-3d %-3d %-3d %-3d %-3d %-3d", ptr[0]>>4,ptr[0]&0x0f,ptr[1]>>4,ptr[1]&0x0f,ptr[2]>>4, ptr[2] & 0x0f, ptr[3] >> 4, ptr[3] & 0x0f)); } static void print_tc_bandwidth_table(netdissect_options *ndo, const u_char *ptr) { ND_PRINT((ndo, "\n\t TC Bandwidth Table")); ND_PRINT((ndo, "\n\t TC%% : 0 1 2 3 4 5 6 7")); ND_PRINT((ndo, "\n\t Value : %-3d %-3d %-3d %-3d %-3d %-3d %-3d %-3d", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7])); } static void print_tsa_assignment_table(netdissect_options *ndo, const u_char *ptr) { ND_PRINT((ndo, "\n\t TSA Assignment Table")); ND_PRINT((ndo, "\n\t Traffic Class: 0 1 2 3 4 5 6 7")); ND_PRINT((ndo, "\n\t Value : %-3d %-3d %-3d %-3d %-3d %-3d %-3d %-3d", ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], 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 subtype, hexdump = FALSE; u_int sublen; u_int tval; uint8_t i; if (tlv_len < 4) { return hexdump; } subtype = *(tptr+3); ND_PRINT((ndo, "\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((ndo, "\n\t port vlan id (PVID): %u", EXTRACT_16BITS(tptr + 4))); break; case LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_VLAN_ID: if (tlv_len < 7) { return hexdump; } ND_PRINT((ndo, "\n\t port and protocol vlan id (PPVID): %u, flags [%s] (0x%02x)", EXTRACT_16BITS(tptr+5), bittok2str(lldp_8021_port_protocol_id_values, "none", *(tptr+4)), *(tptr + 4))); break; case LLDP_PRIVATE_8021_SUBTYPE_VLAN_NAME: if (tlv_len < 6) { return hexdump; } ND_PRINT((ndo, "\n\t vlan id (VID): %u", EXTRACT_16BITS(tptr + 4))); if (tlv_len < 7) { return hexdump; } sublen = *(tptr+6); if (tlv_len < 7+sublen) { return hexdump; } ND_PRINT((ndo, "\n\t vlan name: ")); safeputs(ndo, tptr + 7, sublen); break; case LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_IDENTITY: if (tlv_len < 5) { return hexdump; } sublen = *(tptr+4); if (tlv_len < 5+sublen) { return hexdump; } ND_PRINT((ndo, "\n\t protocol identity: ")); safeputs(ndo, tptr + 5, sublen); break; case LLDP_PRIVATE_8021_SUBTYPE_CONGESTION_NOTIFICATION: if(tlv_len> i) & 0x01)); tval=*(tptr+5); ND_PRINT((ndo, "\n\t Pre-Priority Ready Indicator")); ND_PRINT((ndo, "\n\t Priority : 0 1 2 3 4 5 6 7")); ND_PRINT((ndo, "\n\t Value : ")); for(i=0;i> i) & 0x01)); break; case LLDP_PRIVATE_8021_SUBTYPE_ETS_CONFIGURATION: if(tlv_len> 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> 7, (tval >> 6) & 0x01, (tval >> 4) & 0x03, (tval & 0x0f))); ND_PRINT((ndo, "\n\t PFC Enable")); tval=*(tptr+5); ND_PRINT((ndo, "\n\t Priority : 0 1 2 3 4 5 6 7")); ND_PRINT((ndo, "\n\t Value : ")); for(i=0;i> i) & 0x01)); break; case LLDP_PRIVATE_8021_SUBTYPE_APPLICATION_PRIORITY: if(tlv_len> 5, (tval >> 3) & 0x03, (tval & 0x07))); ND_PRINT((ndo, "Protocol ID: %d", EXTRACT_16BITS(tptr + i + 5))); i=i+3; } break; case LLDP_PRIVATE_8021_SUBTYPE_EVB: if(tlv_len> 3, (tval >> 2) & 0x01, (tval >> 1) & 0x01, tval & 0x01)); ND_PRINT((ndo, "\n\t EVB Station Status")); tval=*(tptr+5); ND_PRINT((ndo, "\n\t RES: %d, SGID: %d, RRREQ: %d,RRSTAT: %d", tval >> 4, (tval >> 3) & 0x01, (tval >> 2) & 0x01, tval & 0x03)); tval=*(tptr+6); ND_PRINT((ndo, "\n\t R: %d, RTE: %d, ",tval >> 5, tval & 0x1f)); tval=*(tptr+7); ND_PRINT((ndo, "EVB Mode: %s [%d]", tok2str(lldp_evb_mode_values, "unknown", tval >> 6), tval >> 6)); ND_PRINT((ndo, "\n\t ROL: %d, RWD: %d, ", (tval >> 5) & 0x01, tval & 0x1f)); tval=*(tptr+8); ND_PRINT((ndo, "RES: %d, ROL: %d, RKA: %d", tval >> 6, (tval >> 5) & 0x01, tval & 0x1f)); break; case LLDP_PRIVATE_8021_SUBTYPE_CDCP: if(tlv_len> 7, (tval >> 4) & 0x07, (tval >> 3) & 0x01)); ND_PRINT((ndo, "ChnCap: %d", EXTRACT_16BITS(tptr + 6) & 0x0fff)); sublen=tlv_len-8; if(sublen%3!=0) { return hexdump; } i=0; while(i> 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 subtype, hexdump = FALSE; if (tlv_len < 4) { return hexdump; } subtype = *(tptr+3); ND_PRINT((ndo, "\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((ndo, "\n\t autonegotiation [%s] (0x%02x)", bittok2str(lldp_8023_autonegotiation_values, "none", *(tptr+4)), *(tptr + 4))); ND_PRINT((ndo, "\n\t PMD autoneg capability [%s] (0x%04x)", bittok2str(lldp_pmd_capability_values,"unknown", EXTRACT_16BITS(tptr+5)), EXTRACT_16BITS(tptr + 5))); ND_PRINT((ndo, "\n\t MAU type %s (0x%04x)", tok2str(lldp_mau_types_values, "unknown", EXTRACT_16BITS(tptr+7)), EXTRACT_16BITS(tptr + 7))); break; case LLDP_PRIVATE_8023_SUBTYPE_MDIPOWER: if (tlv_len < 7) { return hexdump; } ND_PRINT((ndo, "\n\t MDI power support [%s], power pair %s, power class %s", bittok2str(lldp_mdi_values, "none", *(tptr+4)), tok2str(lldp_mdi_power_pairs_values, "unknown", *(tptr+5)), tok2str(lldp_mdi_power_class_values, "unknown", *(tptr + 6)))); break; case LLDP_PRIVATE_8023_SUBTYPE_LINKAGGR: if (tlv_len < 9) { return hexdump; } ND_PRINT((ndo, "\n\t aggregation status [%s], aggregation port ID %u", bittok2str(lldp_aggregation_values, "none", *(tptr+4)), EXTRACT_32BITS(tptr + 5))); break; case LLDP_PRIVATE_8023_SUBTYPE_MTU: ND_PRINT((ndo, "\n\t MTU size %u", EXTRACT_16BITS(tptr + 4))); break; default: hexdump = TRUE; break; } return hexdump; } /* * Extract 34bits of latitude/longitude coordinates. */ static uint64_t lldp_extract_latlon(const u_char *tptr) { uint64_t latlon; latlon = *tptr & 0x3; latlon = (latlon << 32) | EXTRACT_32BITS(tptr+1); return latlon; } /* * Print private TIA extensions. */ static int lldp_private_tia_print(netdissect_options *ndo, const u_char *tptr, u_int tlv_len) { int subtype, hexdump = FALSE; 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 = *(tptr+3); ND_PRINT((ndo, "\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((ndo, "\n\t Media capabilities [%s] (0x%04x)", bittok2str(lldp_tia_capabilities_values, "none", EXTRACT_16BITS(tptr + 4)), EXTRACT_16BITS(tptr + 4))); ND_PRINT((ndo, "\n\t Device type [%s] (0x%02x)", tok2str(lldp_tia_device_type_values, "unknown", *(tptr+6)), *(tptr + 6))); break; case LLDP_PRIVATE_TIA_SUBTYPE_NETWORK_POLICY: if (tlv_len < 8) { return hexdump; } ND_PRINT((ndo, "\n\t Application type [%s] (0x%02x)", tok2str(lldp_tia_application_type_values, "none", *(tptr+4)), *(tptr + 4))); ND_PRINT((ndo, ", Flags [%s]", bittok2str( lldp_tia_network_policy_bits_values, "none", *(tptr + 5)))); ND_PRINT((ndo, "\n\t Vlan id %u", LLDP_EXTRACT_NETWORK_POLICY_VLAN(EXTRACT_16BITS(tptr + 5)))); ND_PRINT((ndo, ", L2 priority %u", LLDP_EXTRACT_NETWORK_POLICY_L2_PRIORITY(EXTRACT_16BITS(tptr + 6)))); ND_PRINT((ndo, ", DSCP value %u", LLDP_EXTRACT_NETWORK_POLICY_DSCP(EXTRACT_16BITS(tptr + 6)))); break; case LLDP_PRIVATE_TIA_SUBTYPE_LOCAL_ID: if (tlv_len < 5) { return hexdump; } location_format = *(tptr+4); ND_PRINT((ndo, "\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((ndo, "\n\t Latitude resolution %u, latitude value %" PRIu64, (*(tptr + 5) >> 2), lldp_extract_latlon(tptr + 5))); ND_PRINT((ndo, "\n\t Longitude resolution %u, longitude value %" PRIu64, (*(tptr + 10) >> 2), lldp_extract_latlon(tptr + 10))); ND_PRINT((ndo, "\n\t Altitude type %s (%u)", tok2str(lldp_tia_location_altitude_type_values, "unknown",(*(tptr+15)>>4)), (*(tptr + 15) >> 4))); ND_PRINT((ndo, "\n\t Altitude resolution %u, altitude value 0x%x", (EXTRACT_16BITS(tptr+15)>>6)&0x3f, ((EXTRACT_32BITS(tptr + 16) & 0x3fffffff)))); ND_PRINT((ndo, "\n\t Datum %s (0x%02x)", tok2str(lldp_tia_location_datum_type_values, "unknown", *(tptr+20)), *(tptr + 20))); break; case LLDP_TIA_LOCATION_DATA_FORMAT_CIVIC_ADDRESS: if (tlv_len < 6) { return hexdump; } lci_len = *(tptr+5); if (lci_len < 3) { return hexdump; } if (tlv_len < 7+lci_len) { return hexdump; } ND_PRINT((ndo, "\n\t LCI length %u, LCI what %s (0x%02x), Country-code ", lci_len, tok2str(lldp_tia_location_lci_what_values, "unknown", *(tptr+6)), *(tptr + 6))); /* Country code */ safeputs(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 = *(tptr); ca_len = *(tptr+1); tptr += 2; lci_len -= 2; ND_PRINT((ndo, "\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; } safeputs(ndo, tptr, ca_len); tptr += ca_len; lci_len -= ca_len; } break; case LLDP_TIA_LOCATION_DATA_FORMAT_ECS_ELIN: ND_PRINT((ndo, "\n\t ECS ELIN id ")); safeputs(ndo, tptr + 5, tlv_len - 5); break; default: ND_PRINT((ndo, "\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((ndo, "\n\t Power type [%s]", (*(tptr + 4) & 0xC0 >> 6) ? "PD device" : "PSE device")); ND_PRINT((ndo, ", Power source [%s]", tok2str(lldp_tia_power_source_values, "none", (*(tptr + 4) & 0x30) >> 4))); ND_PRINT((ndo, "\n\t Power priority [%s] (0x%02x)", tok2str(lldp_tia_power_priority_values, "none", *(tptr+4)&0x0f), *(tptr + 4) & 0x0f)); power_val = EXTRACT_16BITS(tptr+5); if (power_val < LLDP_TIA_POWER_VAL_MAX) { ND_PRINT((ndo, ", Power %.1f Watts", ((float)power_val) / 10)); } else { ND_PRINT((ndo, ", 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((ndo, "\n\t %s ", tok2str(lldp_tia_inventory_values, "unknown", subtype))); safeputs(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 subtype, hexdump = FALSE; uint8_t tval; uint16_t tlv; uint32_t i, pgval, uval; u_int tlen, tlv_type, tlv_len; const u_char *tptr, *mptr; if (len < 4) { return hexdump; } subtype = *(pptr+3); ND_PRINT((ndo, "\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_TCHECK2(*tptr, sizeof(tlv)); tlv = EXTRACT_16BITS(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_TCHECK2(*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((ndo, "\n\t Control - Protocol Control (type 0x%x, length %d)", LLDP_DCBX_CONTROL_TLV, tlv_len)); ND_PRINT((ndo, "\n\t Oper_Version: %d", *tptr)); ND_PRINT((ndo, "\n\t Max_Version: %d", *(tptr + 1))); ND_PRINT((ndo, "\n\t Sequence Number: %d", EXTRACT_32BITS(tptr + 2))); ND_PRINT((ndo, "\n\t Acknowledgement Number: %d", EXTRACT_32BITS(tptr + 6))); break; case LLDP_DCBX_PRIORITY_GROUPS_TLV: if (tlv_len < 17) { goto trunc; } ND_PRINT((ndo, "\n\t Feature - Priority Group (type 0x%x, length %d)", LLDP_DCBX_PRIORITY_GROUPS_TLV, tlv_len)); ND_PRINT((ndo, "\n\t Oper_Version: %d", *tptr)); ND_PRINT((ndo, "\n\t Max_Version: %d", *(tptr + 1))); ND_PRINT((ndo, "\n\t Info block(0x%02X): ", *(tptr + 2))); tval = *(tptr+2); ND_PRINT((ndo, "Enable bit: %d, Willing bit: %d, Error Bit: %d", (tval & 0x80) ? 1 : 0, (tval & 0x40) ? 1 : 0, (tval & 0x20) ? 1 : 0)); ND_PRINT((ndo, "\n\t SubType: %d", *(tptr + 3))); ND_PRINT((ndo, "\n\t Priority Allocation")); /* * Array of 8 4-bit priority group ID values; we fetch all * 32 bits and extract each nibble. */ pgval = EXTRACT_32BITS(tptr+4); for (i = 0; i <= 7; i++) { ND_PRINT((ndo, "\n\t PgId_%d: %d", i, (pgval >> (28 - 4 * i)) & 0xF)); } ND_PRINT((ndo, "\n\t Priority Group Allocation")); for (i = 0; i <= 7; i++) ND_PRINT((ndo, "\n\t Pg percentage[%d]: %d", i, *(tptr + 8 + i))); ND_PRINT((ndo, "\n\t NumTCsSupported: %d", *(tptr + 8 + 8))); break; case LLDP_DCBX_PRIORITY_FLOW_CONTROL_TLV: if (tlv_len < 6) { goto trunc; } ND_PRINT((ndo, "\n\t Feature - Priority Flow Control")); ND_PRINT((ndo, " (type 0x%x, length %d)", LLDP_DCBX_PRIORITY_FLOW_CONTROL_TLV, tlv_len)); ND_PRINT((ndo, "\n\t Oper_Version: %d", *tptr)); ND_PRINT((ndo, "\n\t Max_Version: %d", *(tptr + 1))); ND_PRINT((ndo, "\n\t Info block(0x%02X): ", *(tptr + 2))); tval = *(tptr+2); ND_PRINT((ndo, "Enable bit: %d, Willing bit: %d, Error Bit: %d", (tval & 0x80) ? 1 : 0, (tval & 0x40) ? 1 : 0, (tval & 0x20) ? 1 : 0)); ND_PRINT((ndo, "\n\t SubType: %d", *(tptr + 3))); tval = *(tptr+4); ND_PRINT((ndo, "\n\t PFC Config (0x%02X)", *(tptr + 4))); for (i = 0; i <= 7; i++) ND_PRINT((ndo, "\n\t Priority Bit %d: %s", i, (tval & (1 << i)) ? "Enabled" : "Disabled")); ND_PRINT((ndo, "\n\t NumTCPFCSupported: %d", *(tptr + 5))); break; case LLDP_DCBX_APPLICATION_TLV: if (tlv_len < 4) { goto trunc; } ND_PRINT((ndo, "\n\t Feature - Application (type 0x%x, length %d)", LLDP_DCBX_APPLICATION_TLV, tlv_len)); ND_PRINT((ndo, "\n\t Oper_Version: %d", *tptr)); ND_PRINT((ndo, "\n\t Max_Version: %d", *(tptr + 1))); ND_PRINT((ndo, "\n\t Info block(0x%02X): ", *(tptr + 2))); tval = *(tptr+2); ND_PRINT((ndo, "Enable bit: %d, Willing bit: %d, Error Bit: %d", (tval & 0x80) ? 1 : 0, (tval & 0x40) ? 1 : 0, (tval & 0x20) ? 1 : 0)); ND_PRINT((ndo, "\n\t SubType: %d", *(tptr + 3))); tval = tlv_len - 4; mptr = tptr + 4; while (tval >= 6) { ND_PRINT((ndo, "\n\t Application Value")); ND_PRINT((ndo, "\n\t Application Protocol ID: 0x%04x", EXTRACT_16BITS(mptr))); uval = EXTRACT_24BITS(mptr+2); ND_PRINT((ndo, "\n\t SF (0x%x) Application Protocol ID is %s", (uval >> 22), (uval >> 22) ? "Socket Number" : "L2 EtherType")); ND_PRINT((ndo, "\n\t OUI: 0x%06x", uval & 0x3fffff)); ND_PRINT((ndo, "\n\t User Priority Map: 0x%02x", *(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) { - +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 = *tptr; switch (af) { case AFNUM_INET: if (len < 4) return NULL; pfunc = getname; break; #ifdef INET6 case AFNUM_INET6: if (len < 16) return NULL; pfunc = getname6; break; #endif case AFNUM_802: if (len < 6) 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) { - + 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 = *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((ndo, "\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 = *tptr; ND_PRINT((ndo, "\n\t %s Interface Numbering (%u): %u", tok2str(lldp_intf_numb_subtype_values, "Unknown", intf_num_subtype), intf_num_subtype, EXTRACT_32BITS(tptr + 1))); tptr += LLDP_INTF_NUM_LEN; tlen -= LLDP_INTF_NUM_LEN; /* * The OID is optional. */ if (tlen) { oid_len = *tptr; if (tlen < oid_len) { return 0; } if (oid_len) { ND_PRINT((ndo, "\n\t OID length %u", oid_len)); safeputs(ndo, tptr + 1, oid_len); } } return 1; } void lldp_print(netdissect_options *ndo, - register const u_char *pptr, register u_int len) { - + register const u_char *pptr, register 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; tptr = pptr; tlen = len; ND_PRINT((ndo, "LLDP, length %u", len)); while (tlen >= sizeof(tlv)) { ND_TCHECK2(*tptr, sizeof(tlv)); tlv = EXTRACT_16BITS(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((ndo, "\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_TCHECK2(*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 = *tptr; ND_PRINT((ndo, "\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((ndo, "%s", etheraddr_string(ndo, 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: safeputs(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((ndo, "%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 = *tptr; ND_PRINT((ndo, "\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((ndo, "%s", etheraddr_string(ndo, 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: safeputs(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((ndo, "%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((ndo, ": TTL %us", EXTRACT_16BITS(tptr))); } break; case LLDP_PORT_DESCR_TLV: if (ndo->ndo_vflag) { ND_PRINT((ndo, ": ")); safeputs(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((ndo, ": ")); safeputs(ndo, tptr, tlv_len); break; case LLDP_SYSTEM_DESCR_TLV: if (ndo->ndo_vflag) { ND_PRINT((ndo, "\n\t ")); safeputs(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 = EXTRACT_16BITS(tptr); ena_cap = EXTRACT_16BITS(tptr+2); ND_PRINT((ndo, "\n\t System Capabilities [%s] (0x%04x)", bittok2str(lldp_cap_values, "none", cap), cap)); ND_PRINT((ndo, "\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 = EXTRACT_24BITS(tptr); ND_PRINT((ndo, ": 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_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((ndo, "\n\t[|LLDP]")); } /* * Local Variables: * c-style: whitesmith * c-basic-offset: 4 * End: */ Index: head/contrib/tcpdump/print-lmp.c =================================================================== --- head/contrib/tcpdump/print-lmp.c (revision 285274) +++ head/contrib/tcpdump/print-lmp.c (revision 285275) @@ -1,880 +1,880 @@ /* * 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 Link Management Protocol as per rfc 4204. * * Original code by Hannes Gredler (hannes@juniper.net) * Support for LMP service discovery extensions (defined by UNI 1.0) added * by Manu Pathak (mapathak@cisco.com), May 2005 */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "interface.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 { uint8_t version_res[2]; uint8_t flags; uint8_t msg_type; uint8_t length[2]; uint8_t reserved[2]; }; #define LMP_VERSION 1 #define LMP_EXTRACT_VERSION(x) (((x)&0xf0)>>4) 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 { uint8_t ctype; uint8_t class_num; uint8_t length[2]; }; #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} }; void lmp_print(netdissect_options *ndo, - register const u_char *pptr, register u_int len) { - + register const u_char *pptr, register u_int len) +{ const struct lmp_common_header *lmp_com_header; const struct lmp_object_header *lmp_obj_header; const u_char *tptr,*obj_tptr; int tlen,lmp_obj_len,lmp_obj_ctype,obj_tlen; int hexdump; int offset,subobj_type,subobj_len,total_subobj_len; int link_type; union { /* int to float conversion buffer */ float f; uint32_t i; } bw; tptr=pptr; lmp_com_header = (const struct lmp_common_header *)pptr; ND_TCHECK(*lmp_com_header); /* * Sanity checking of the header. */ if (LMP_EXTRACT_VERSION(lmp_com_header->version_res[0]) != LMP_VERSION) { ND_PRINT((ndo, "LMP version %u packet not supported", LMP_EXTRACT_VERSION(lmp_com_header->version_res[0]))); return; } /* in non-verbose mode just lets print the basic Message Type*/ if (ndo->ndo_vflag < 1) { ND_PRINT((ndo, "LMPv%u %s Message, length: %u", LMP_EXTRACT_VERSION(lmp_com_header->version_res[0]), tok2str(lmp_msg_type_values, "unknown (%u)",lmp_com_header->msg_type), len)); return; } /* ok they seem to want to know everything - lets fully decode it */ tlen=EXTRACT_16BITS(lmp_com_header->length); ND_PRINT((ndo, "\n\tLMPv%u, msg-type: %s, Flags: [%s], length: %u", LMP_EXTRACT_VERSION(lmp_com_header->version_res[0]), tok2str(lmp_msg_type_values, "unknown, type: %u",lmp_com_header->msg_type), bittok2str(lmp_header_flag_values,"none",lmp_com_header->flags), tlen)); tptr+=sizeof(const struct lmp_common_header); tlen-=sizeof(const struct lmp_common_header); while(tlen>0) { /* did we capture enough for fully decoding the object header ? */ ND_TCHECK2(*tptr, sizeof(struct lmp_object_header)); lmp_obj_header = (const struct lmp_object_header *)tptr; lmp_obj_len=EXTRACT_16BITS(lmp_obj_header->length); lmp_obj_ctype=(lmp_obj_header->ctype)&0x7f; if(lmp_obj_len % 4 || lmp_obj_len < 4) return; ND_PRINT((ndo, "\n\t %s Object (%u), Class-Type: %s (%u) Flags: [%snegotiable], length: %u", tok2str(lmp_obj_values, "Unknown", lmp_obj_header->class_num), lmp_obj_header->class_num, tok2str(lmp_ctype_values, "Unknown", ((lmp_obj_header->class_num)<<8)+lmp_obj_ctype), lmp_obj_ctype, (lmp_obj_header->ctype)&0x80 ? "" : "non-", lmp_obj_len)); 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_TCHECK2(*tptr, lmp_obj_len); hexdump=FALSE; switch(lmp_obj_header->class_num) { case LMP_OBJ_CC_ID: switch(lmp_obj_ctype) { case LMP_CTYPE_LOC: case LMP_CTYPE_RMT: ND_PRINT((ndo, "\n\t Control Channel ID: %u (0x%08x)", EXTRACT_32BITS(obj_tptr), EXTRACT_32BITS(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: ND_PRINT((ndo, "\n\t IPv4 Link ID: %s (0x%08x)", ipaddr_string(ndo, obj_tptr), EXTRACT_32BITS(obj_tptr))); break; #ifdef INET6 case LMP_CTYPE_IPV6_LOC: case LMP_CTYPE_IPV6_RMT: ND_PRINT((ndo, "\n\t IPv6 Link ID: %s (0x%08x)", ip6addr_string(ndo, obj_tptr), EXTRACT_32BITS(obj_tptr))); break; #endif case LMP_CTYPE_UNMD_LOC: case LMP_CTYPE_UNMD_RMT: ND_PRINT((ndo, "\n\t Link ID: %u (0x%08x)", EXTRACT_32BITS(obj_tptr), EXTRACT_32BITS(obj_tptr))); break; default: hexdump=TRUE; } break; case LMP_OBJ_MESSAGE_ID: switch(lmp_obj_ctype) { case LMP_CTYPE_1: ND_PRINT((ndo, "\n\t Message ID: %u (0x%08x)", EXTRACT_32BITS(obj_tptr), EXTRACT_32BITS(obj_tptr))); break; case LMP_CTYPE_2: ND_PRINT((ndo, "\n\t Message ID Ack: %u (0x%08x)", EXTRACT_32BITS(obj_tptr), EXTRACT_32BITS(obj_tptr))); break; default: hexdump=TRUE; } break; case LMP_OBJ_NODE_ID: switch(lmp_obj_ctype) { case LMP_CTYPE_LOC: case LMP_CTYPE_RMT: ND_PRINT((ndo, "\n\t Node ID: %s (0x%08x)", ipaddr_string(ndo, obj_tptr), EXTRACT_32BITS(obj_tptr))); break; default: hexdump=TRUE; } break; case LMP_OBJ_CONFIG: switch(lmp_obj_ctype) { case LMP_CTYPE_HELLO_CONFIG: ND_PRINT((ndo, "\n\t Hello Interval: %u\n\t Hello Dead Interval: %u", EXTRACT_16BITS(obj_tptr), EXTRACT_16BITS(obj_tptr+2))); break; default: hexdump=TRUE; } break; case LMP_OBJ_HELLO: switch(lmp_obj_ctype) { case LMP_CTYPE_HELLO: ND_PRINT((ndo, "\n\t Tx Seq: %u, Rx Seq: %u", EXTRACT_32BITS(obj_tptr), EXTRACT_32BITS(obj_tptr+4))); break; default: hexdump=TRUE; } break; case LMP_OBJ_TE_LINK: ND_PRINT((ndo, "\n\t Flags: [%s]", bittok2str(lmp_obj_te_link_flag_values, "none", EXTRACT_16BITS(obj_tptr)>>8))); switch(lmp_obj_ctype) { case LMP_CTYPE_IPV4: ND_PRINT((ndo, "\n\t Local Link-ID: %s (0x%08x)" "\n\t Remote Link-ID: %s (0x%08x)", ipaddr_string(ndo, obj_tptr+4), EXTRACT_32BITS(obj_tptr+4), ipaddr_string(ndo, obj_tptr+8), EXTRACT_32BITS(obj_tptr+8))); break; #ifdef INET6 case LMP_CTYPE_IPV6: #endif case LMP_CTYPE_UNMD: default: hexdump=TRUE; } break; case LMP_OBJ_DATA_LINK: ND_PRINT((ndo, "\n\t Flags: [%s]", bittok2str(lmp_obj_data_link_flag_values, "none", EXTRACT_16BITS(obj_tptr)>>8))); switch(lmp_obj_ctype) { case LMP_CTYPE_IPV4: case LMP_CTYPE_UNMD: ND_PRINT((ndo, "\n\t Local Interface ID: %s (0x%08x)" "\n\t Remote Interface ID: %s (0x%08x)", ipaddr_string(ndo, obj_tptr+4), EXTRACT_32BITS(obj_tptr+4), ipaddr_string(ndo, obj_tptr+8), EXTRACT_32BITS(obj_tptr+8))); total_subobj_len = lmp_obj_len - 16; offset = 12; while (total_subobj_len > 0 && hexdump == FALSE ) { subobj_type = EXTRACT_16BITS(obj_tptr+offset)>>8; subobj_len = EXTRACT_16BITS(obj_tptr+offset)&0x00FF; ND_PRINT((ndo, "\n\t Subobject, Type: %s (%u), Length: %u", tok2str(lmp_data_link_subobj, "Unknown", subobj_type), subobj_type, subobj_len)); switch(subobj_type) { case INT_SWITCHING_TYPE_SUBOBJ: ND_PRINT((ndo, "\n\t Switching Type: %s (%u)", tok2str(gmpls_switch_cap_values, "Unknown", EXTRACT_16BITS(obj_tptr+offset+2)>>8), EXTRACT_16BITS(obj_tptr+offset+2)>>8)); ND_PRINT((ndo, "\n\t Encoding Type: %s (%u)", tok2str(gmpls_encoding_values, "Unknown", EXTRACT_16BITS(obj_tptr+offset+2)&0x00FF), EXTRACT_16BITS(obj_tptr+offset+2)&0x00FF)); bw.i = EXTRACT_32BITS(obj_tptr+offset+4); ND_PRINT((ndo, "\n\t Min Reservable Bandwidth: %.3f Mbps", bw.f*8/1000000)); bw.i = EXTRACT_32BITS(obj_tptr+offset+8); ND_PRINT((ndo, "\n\t Max Reservable Bandwidth: %.3f Mbps", bw.f*8/1000000)); break; case WAVELENGTH_SUBOBJ: ND_PRINT((ndo, "\n\t Wavelength: %u", EXTRACT_32BITS(obj_tptr+offset+4))); break; default: /* Any Unknown Subobject ==> Exit loop */ hexdump=TRUE; break; } total_subobj_len-=subobj_len; offset+=subobj_len; } break; #ifdef INET6 case LMP_CTYPE_IPV6: #endif default: hexdump=TRUE; } break; case LMP_OBJ_VERIFY_BEGIN: switch(lmp_obj_ctype) { case LMP_CTYPE_1: ND_PRINT((ndo, "\n\t Flags: %s", bittok2str(lmp_obj_begin_verify_flag_values, "none", EXTRACT_16BITS(obj_tptr)))); ND_PRINT((ndo, "\n\t Verify Interval: %u", EXTRACT_16BITS(obj_tptr+2))); ND_PRINT((ndo, "\n\t Data links: %u", EXTRACT_32BITS(obj_tptr+4))); ND_PRINT((ndo, "\n\t Encoding type: %s", tok2str(gmpls_encoding_values, "Unknown", *(obj_tptr+8)))); ND_PRINT((ndo, "\n\t Verify Transport Mechanism: %u (0x%x)%s", EXTRACT_16BITS(obj_tptr+10), EXTRACT_16BITS(obj_tptr+10), EXTRACT_16BITS(obj_tptr+10)&8000 ? " (Payload test messages capable)" : "")); bw.i = EXTRACT_32BITS(obj_tptr+12); ND_PRINT((ndo, "\n\t Transmission Rate: %.3f Mbps",bw.f*8/1000000)); ND_PRINT((ndo, "\n\t Wavelength: %u", EXTRACT_32BITS(obj_tptr+16))); break; default: hexdump=TRUE; } break; case LMP_OBJ_VERIFY_BEGIN_ACK: switch(lmp_obj_ctype) { case LMP_CTYPE_1: ND_PRINT((ndo, "\n\t Verify Dead Interval: %u" "\n\t Verify Transport Response: %u", EXTRACT_16BITS(obj_tptr), EXTRACT_16BITS(obj_tptr+2))); break; default: hexdump=TRUE; } break; case LMP_OBJ_VERIFY_ID: switch(lmp_obj_ctype) { case LMP_CTYPE_1: ND_PRINT((ndo, "\n\t Verify ID: %u", EXTRACT_32BITS(obj_tptr))); break; default: hexdump=TRUE; } break; case LMP_OBJ_CHANNEL_STATUS: switch(lmp_obj_ctype) { case LMP_CTYPE_IPV4: case LMP_CTYPE_UNMD: offset = 0; /* Decode pairs: */ while (offset < (lmp_obj_len-(int)sizeof(struct lmp_object_header)) ) { ND_PRINT((ndo, "\n\t Interface ID: %s (0x%08x)", ipaddr_string(ndo, obj_tptr+offset), EXTRACT_32BITS(obj_tptr+offset))); ND_PRINT((ndo, "\n\t\t Active: %s (%u)", (EXTRACT_32BITS(obj_tptr+offset+4)>>31) ? "Allocated" : "Non-allocated", (EXTRACT_32BITS(obj_tptr+offset+4)>>31))); ND_PRINT((ndo, "\n\t\t Direction: %s (%u)", (EXTRACT_32BITS(obj_tptr+offset+4)>>30)&0x1 ? "Transmit" : "Receive", (EXTRACT_32BITS(obj_tptr+offset+4)>>30)&0x1)); ND_PRINT((ndo, "\n\t\t Channel Status: %s (%u)", tok2str(lmp_obj_channel_status_values, "Unknown", EXTRACT_32BITS(obj_tptr+offset+4)&0x3FFFFFF), EXTRACT_32BITS(obj_tptr+offset+4)&0x3FFFFFF)); offset+=8; } break; #ifdef INET6 case LMP_CTYPE_IPV6: #endif default: hexdump=TRUE; } break; case LMP_OBJ_CHANNEL_STATUS_REQ: switch(lmp_obj_ctype) { case LMP_CTYPE_IPV4: case LMP_CTYPE_UNMD: offset = 0; while (offset < (lmp_obj_len-(int)sizeof(struct lmp_object_header)) ) { ND_PRINT((ndo, "\n\t Interface ID: %s (0x%08x)", ipaddr_string(ndo, obj_tptr+offset), EXTRACT_32BITS(obj_tptr+offset))); offset+=4; } break; #ifdef INET6 case LMP_CTYPE_IPV6: #endif default: hexdump=TRUE; } break; case LMP_OBJ_ERROR_CODE: switch(lmp_obj_ctype) { case LMP_CTYPE_BEGIN_VERIFY_ERROR: ND_PRINT((ndo, "\n\t Error Code: %s", bittok2str(lmp_obj_begin_verify_error_values, "none", EXTRACT_32BITS(obj_tptr)))); break; case LMP_CTYPE_LINK_SUMMARY_ERROR: ND_PRINT((ndo, "\n\t Error Code: %s", bittok2str(lmp_obj_link_summary_error_values, "none", EXTRACT_32BITS(obj_tptr)))); break; default: hexdump=TRUE; } break; case LMP_OBJ_SERVICE_CONFIG: switch (lmp_obj_ctype) { case LMP_CTYPE_SERVICE_CONFIG_SP: ND_PRINT((ndo, "\n\t Flags: %s", bittok2str(lmp_obj_service_config_sp_flag_values, "none", EXTRACT_16BITS(obj_tptr)>>8))); ND_PRINT((ndo, "\n\t UNI Version: %u", EXTRACT_16BITS(obj_tptr) & 0x00FF)); break; case LMP_CTYPE_SERVICE_CONFIG_CPSA: link_type = EXTRACT_16BITS(obj_tptr)>>8; ND_PRINT((ndo, "\n\t Link Type: %s (%u)", tok2str(lmp_sd_service_config_cpsa_link_type_values, "Unknown", link_type), link_type)); if (link_type == LMP_SD_SERVICE_CONFIG_CPSA_LINK_TYPE_SDH) { ND_PRINT((ndo, "\n\t Signal Type: %s (%u)", tok2str(lmp_sd_service_config_cpsa_signal_type_sdh_values, "Unknown", EXTRACT_16BITS(obj_tptr) & 0x00FF), EXTRACT_16BITS(obj_tptr) & 0x00FF)); } if (link_type == LMP_SD_SERVICE_CONFIG_CPSA_LINK_TYPE_SONET) { ND_PRINT((ndo, "\n\t Signal Type: %s (%u)", tok2str(lmp_sd_service_config_cpsa_signal_type_sonet_values, "Unknown", EXTRACT_16BITS(obj_tptr) & 0x00FF), EXTRACT_16BITS(obj_tptr) & 0x00FF)); } ND_PRINT((ndo, "\n\t Transparency: %s", bittok2str(lmp_obj_service_config_cpsa_tp_flag_values, "none", EXTRACT_16BITS(obj_tptr+2)>>8))); ND_PRINT((ndo, "\n\t Contiguous Concatenation Types: %s", bittok2str(lmp_obj_service_config_cpsa_cct_flag_values, "none", EXTRACT_16BITS(obj_tptr+2)>>8 & 0x00FF))); ND_PRINT((ndo, "\n\t Minimum NCC: %u", EXTRACT_16BITS(obj_tptr+4))); ND_PRINT((ndo, "\n\t Maximum NCC: %u", EXTRACT_16BITS(obj_tptr+6))); ND_PRINT((ndo, "\n\t Minimum NVC:%u", EXTRACT_16BITS(obj_tptr+8))); ND_PRINT((ndo, "\n\t Maximum NVC:%u", EXTRACT_16BITS(obj_tptr+10))); ND_PRINT((ndo, "\n\t Local Interface ID: %s (0x%08x)", ipaddr_string(ndo, obj_tptr+12), EXTRACT_32BITS(obj_tptr+12))); break; case LMP_CTYPE_SERVICE_CONFIG_TRANSPARENCY_TCM: ND_PRINT((ndo, "\n\t Transparency Flags: %s", bittok2str( lmp_obj_service_config_nsa_transparency_flag_values, "none", EXTRACT_32BITS(obj_tptr)))); ND_PRINT((ndo, "\n\t TCM Monitoring Flags: %s", bittok2str( lmp_obj_service_config_nsa_tcm_flag_values, "none", EXTRACT_16BITS(obj_tptr+6) & 0x00FF))); break; case LMP_CTYPE_SERVICE_CONFIG_NETWORK_DIVERSITY: ND_PRINT((ndo, "\n\t Diversity: Flags: %s", bittok2str( lmp_obj_service_config_nsa_network_diversity_flag_values, "none", EXTRACT_16BITS(obj_tptr+2) & 0x00FF))); 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)); tptr+=lmp_obj_len; tlen-=lmp_obj_len; } return; trunc: ND_PRINT((ndo, "\n\t\t packet exceeded snapshot")); } /* * Local Variables: * c-style: whitesmith * c-basic-offset: 8 * End: */ Index: head/contrib/tcpdump/print-lspping.c =================================================================== --- head/contrib/tcpdump/print-lspping.c (revision 285274) +++ head/contrib/tcpdump/print-lspping.c (revision 285275) @@ -1,889 +1,889 @@ /* * 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@juniper.net) */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "interface.h" #include "extract.h" #include "addrtoname.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 { uint8_t version[2]; uint8_t reserved[2]; uint8_t msg_type; uint8_t reply_mode; uint8_t return_code; uint8_t return_subcode; uint8_t sender_handle[4]; uint8_t seq_number[4]; uint8_t ts_sent_sec[4]; uint8_t ts_sent_usec[4]; uint8_t ts_rcvd_sec[4]; uint8_t ts_rcvd_usec[4]; }; #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"}, }; /* * 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 { uint8_t type[2]; uint8_t length[2]; }; #define LSPPING_TLV_TARGET_FEC_STACK 1 #define LSPPING_TLV_DOWNSTREAM_MAPPING 2 #define LSPPING_TLV_PAD 3 #define LSPPING_TLV_VENDOR_ENTERPRISE 5 #define LSPPING_TLV_VENDOR_ENTERPRISE_LEN 4 #define LSPPING_TLV_INTERFACE_LABEL_STACK 7 #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 #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_L2VPN_VCID_OLD 9 #define LSPPING_TLV_TARGETFEC_SUBTLV_L2VPN_VCID 10 #define LSPPING_TLV_TARGETFEC_SUBTLV_BGP_IPV4 11 #define LSPPING_TLV_TARGETFEC_SUBTLV_BGP_IPV6 12 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_L2VPN_VCID_OLD, "L2 circuit ID (old)"}, { LSPPING_TLV_TARGETFEC_SUBTLV_L2VPN_VCID, "L2 circuit ID"}, { 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 { uint8_t prefix [4]; 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 { uint8_t prefix [16]; 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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Sender identifier | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | IPv4 prefix | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Prefix Length | Must Be Zero | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ struct lspping_tlv_targetfec_subtlv_bgp_ipv4_t { uint8_t sender_id [4]; uint8_t prefix [4]; 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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Sender identifier | * | (16 octets) | * | | * | | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | IPv6 prefix | * | (16 octets) | * | | * | | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Prefix Length | Must Be Zero | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ struct lspping_tlv_targetfec_subtlv_bgp_ipv6_t { uint8_t sender_id [16]; uint8_t prefix [16]; 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 { uint8_t tunnel_endpoint [4]; uint8_t res[2]; uint8_t tunnel_id[2]; uint8_t extended_tunnel_id[4]; uint8_t tunnel_sender [4]; uint8_t res2[2]; uint8_t lsp_id [2]; }; /* * 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 { uint8_t tunnel_endpoint [16]; uint8_t res[2]; uint8_t tunnel_id[2]; uint8_t extended_tunnel_id[16]; uint8_t tunnel_sender [16]; uint8_t res2[2]; uint8_t lsp_id [2]; }; /* * 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 { uint8_t rd [8]; uint8_t prefix [4]; 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 { uint8_t rd [8]; uint8_t prefix [16]; 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 CE ID | Receiver's CE ID | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Encapsulation Type | Must Be Zero | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * 0 1 2 3 */ struct lspping_tlv_targetfec_subtlv_l2vpn_endpt_t { uint8_t rd [8]; uint8_t sender_ce_id [2]; uint8_t receiver_ce_id [2]; uint8_t encapsulation[2]; }; /* * 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 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | VC ID | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Encapsulation Type | Must Be Zero | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ struct lspping_tlv_targetfec_subtlv_l2vpn_vcid_old_t { uint8_t remote_pe_address [4]; uint8_t vc_id [4]; uint8_t encapsulation[2]; }; /* * 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 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | VC ID | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Encapsulation Type | Must Be Zero | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ struct lspping_tlv_targetfec_subtlv_l2vpn_vcid_t { uint8_t sender_pe_address [4]; uint8_t remote_pe_address [4]; uint8_t vc_id [4]; uint8_t encapsulation[2]; }; /* * 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) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Hash Key Type | Depth Limit | Multipath Length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * . . * . (Multipath Information) . * . . * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Downstream Label | Protocol | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * . . * . . * . . * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Downstream Label | Protocol | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ struct lspping_tlv_downstream_map_ipv4_t { uint8_t mtu [2]; uint8_t address_type; uint8_t res; uint8_t downstream_ip[4]; uint8_t downstream_interface[4]; }; struct lspping_tlv_downstream_map_ipv6_t { uint8_t mtu [2]; uint8_t address_type; uint8_t res; uint8_t downstream_ip[16]; uint8_t downstream_interface[16]; }; struct lspping_tlv_downstream_map_info_t { uint8_t hash_key_type; uint8_t depth_limit; uint8_t multipath_length [2]; }; #define LSPPING_AFI_IPV4 1 #define LSPPING_AFI_UNMB 2 #define LSPPING_AFI_IPV6 3 static const struct tok lspping_tlv_downstream_addr_values[] = { { LSPPING_AFI_IPV4, "IPv4"}, { LSPPING_AFI_IPV6, "IPv6"}, { LSPPING_AFI_UNMB, "Unnumbered"}, { 0, NULL} }; void lspping_print(netdissect_options *ndo, - register const u_char *pptr, register u_int len) { - + register const u_char *pptr, register 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; int tlen,lspping_tlv_len,lspping_tlv_type,tlv_tlen; int tlv_hexdump,subtlv_hexdump; int lspping_subtlv_len,lspping_subtlv_type; struct timeval timestamp; union { const struct lspping_tlv_downstream_map_ipv4_t *lspping_tlv_downstream_map_ipv4; const struct lspping_tlv_downstream_map_ipv6_t *lspping_tlv_downstream_map_ipv6; 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_l2vpn_vcid_old_t *lspping_tlv_targetfec_subtlv_l2vpn_vcid_old; const struct lspping_tlv_targetfec_subtlv_l2vpn_vcid_t *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; tptr=pptr; lspping_com_header = (const struct lspping_common_header *)pptr; ND_TCHECK(*lspping_com_header); /* * Sanity checking of the header. */ if (EXTRACT_16BITS(&lspping_com_header->version[0]) != LSPPING_VERSION) { ND_PRINT((ndo, "LSP-PING version %u packet not supported", EXTRACT_16BITS(&lspping_com_header->version[0]))); return; } /* in non-verbose mode just lets print the basic Message Type*/ if (ndo->ndo_vflag < 1) { ND_PRINT((ndo, "LSP-PINGv%u, %s, seq %u, length: %u", EXTRACT_16BITS(&lspping_com_header->version[0]), tok2str(lspping_msg_type_values, "unknown (%u)",lspping_com_header->msg_type), EXTRACT_32BITS(lspping_com_header->seq_number), len)); return; } /* ok they seem to want to know everything - lets fully decode it */ tlen=len; ND_PRINT((ndo, "\n\tLSP-PINGv%u, msg-type: %s (%u), length: %u\n\t reply-mode: %s (%u)", EXTRACT_16BITS(&lspping_com_header->version[0]), tok2str(lspping_msg_type_values, "unknown",lspping_com_header->msg_type), lspping_com_header->msg_type, len, tok2str(lspping_reply_mode_values, "unknown",lspping_com_header->reply_mode), lspping_com_header->reply_mode)); /* * the following return codes require that the subcode is attached * at the end of the translated token output */ if (lspping_com_header->return_code == 3 || lspping_com_header->return_code == 4 || lspping_com_header->return_code == 8 || lspping_com_header->return_code == 10 || lspping_com_header->return_code == 11 || lspping_com_header->return_code == 12 ) ND_PRINT((ndo, "\n\t Return Code: %s %u (%u)\n\t Return Subcode: (%u)", tok2str(lspping_return_code_values, "unknown",lspping_com_header->return_code), lspping_com_header->return_subcode, lspping_com_header->return_code, lspping_com_header->return_subcode)); else ND_PRINT((ndo, "\n\t Return Code: %s (%u)\n\t Return Subcode: (%u)", tok2str(lspping_return_code_values, "unknown",lspping_com_header->return_code), lspping_com_header->return_code, lspping_com_header->return_subcode)); ND_PRINT((ndo, "\n\t Sender Handle: 0x%08x, Sequence: %u", EXTRACT_32BITS(lspping_com_header->sender_handle), EXTRACT_32BITS(lspping_com_header->seq_number))); timestamp.tv_sec=EXTRACT_32BITS(lspping_com_header->ts_sent_sec); timestamp.tv_usec=EXTRACT_32BITS(lspping_com_header->ts_sent_usec); ND_PRINT((ndo, "\n\t Sender Timestamp: ")); ts_print(ndo, ×tamp); timestamp.tv_sec=EXTRACT_32BITS(lspping_com_header->ts_rcvd_sec); timestamp.tv_usec=EXTRACT_32BITS(lspping_com_header->ts_rcvd_usec); ND_PRINT((ndo, "Receiver Timestamp: ")); if ((timestamp.tv_sec != 0) && (timestamp.tv_usec != 0)) ts_print(ndo, ×tamp); else ND_PRINT((ndo, "no timestamp")); tptr+=sizeof(const struct lspping_common_header); tlen-=sizeof(const struct lspping_common_header); while(tlen>(int)sizeof(struct lspping_tlv_header)) { /* did we capture enough for fully decoding the tlv header ? */ ND_TCHECK2(*tptr, sizeof(struct lspping_tlv_header)); lspping_tlv_header = (const struct lspping_tlv_header *)tptr; lspping_tlv_type=EXTRACT_16BITS(lspping_tlv_header->type); lspping_tlv_len=EXTRACT_16BITS(lspping_tlv_header->length); /* some little sanity checking */ if (lspping_tlv_type == 0 || lspping_tlv_len == 0) return; if(lspping_tlv_len < 4) { ND_PRINT((ndo, "\n\t ERROR: TLV %u bogus size %u",lspping_tlv_type,lspping_tlv_len)); return; } ND_PRINT((ndo, "\n\t %s TLV (%u), length: %u", tok2str(lspping_tlv_values, "Unknown", lspping_tlv_type), lspping_tlv_type, lspping_tlv_len)); tlv_tptr=tptr+sizeof(struct lspping_tlv_header); tlv_tlen=lspping_tlv_len; /* header not included -> no adjustment */ /* did we capture enough for fully decoding the tlv ? */ ND_TCHECK2(*tptr, lspping_tlv_len); tlv_hexdump=FALSE; switch(lspping_tlv_type) { case LSPPING_TLV_TARGET_FEC_STACK: while(tlv_tlen>(int)sizeof(struct lspping_tlv_header)) { /* did we capture enough for fully decoding the subtlv header ? */ ND_TCHECK2(*tptr, sizeof(struct lspping_tlv_header)); subtlv_hexdump=FALSE; lspping_subtlv_header = (const struct lspping_tlv_header *)tlv_tptr; lspping_subtlv_type=EXTRACT_16BITS(lspping_subtlv_header->type); lspping_subtlv_len=EXTRACT_16BITS(lspping_subtlv_header->length); subtlv_tptr=tlv_tptr+sizeof(struct lspping_tlv_header); if (lspping_subtlv_len == 0) break; ND_PRINT((ndo, "\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: subtlv_ptr.lspping_tlv_targetfec_subtlv_ldp_ipv4 = \ (const struct lspping_tlv_targetfec_subtlv_ldp_ipv4_t *)subtlv_tptr; ND_PRINT((ndo, "\n\t %s/%u", ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_ldp_ipv4->prefix), subtlv_ptr.lspping_tlv_targetfec_subtlv_ldp_ipv4->prefix_len)); break; #ifdef INET6 case LSPPING_TLV_TARGETFEC_SUBTLV_LDP_IPV6: subtlv_ptr.lspping_tlv_targetfec_subtlv_ldp_ipv6 = \ (const struct lspping_tlv_targetfec_subtlv_ldp_ipv6_t *)subtlv_tptr; ND_PRINT((ndo, "\n\t %s/%u", ip6addr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_ldp_ipv6->prefix), subtlv_ptr.lspping_tlv_targetfec_subtlv_ldp_ipv6->prefix_len)); break; #endif case LSPPING_TLV_TARGETFEC_SUBTLV_BGP_IPV4: subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv4 = \ (const struct lspping_tlv_targetfec_subtlv_bgp_ipv4_t *)subtlv_tptr; ND_PRINT((ndo, "\n\t %s/%u, sender-id %s", ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv4->prefix), subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv4->prefix_len, ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv4->sender_id))); break; #ifdef INET6 case LSPPING_TLV_TARGETFEC_SUBTLV_BGP_IPV6: subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv6 = \ (const struct lspping_tlv_targetfec_subtlv_bgp_ipv6_t *)subtlv_tptr; ND_PRINT((ndo, "\n\t %s/%u, sender-id %s", ip6addr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv6->prefix), subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv6->prefix_len, ip6addr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_bgp_ipv6->sender_id))); break; #endif case LSPPING_TLV_TARGETFEC_SUBTLV_RSVP_IPV4: subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv4 = \ (const struct lspping_tlv_targetfec_subtlv_rsvp_ipv4_t *)subtlv_tptr; ND_PRINT((ndo, "\n\t tunnel end-point %s, tunnel sender %s, lsp-id 0x%04x" \ "\n\t tunnel-id 0x%04x, extended tunnel-id %s", ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv4->tunnel_endpoint), ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv4->tunnel_sender), EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv4->lsp_id), EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv4->tunnel_id), ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv4->extended_tunnel_id))); break; #ifdef INET6 case LSPPING_TLV_TARGETFEC_SUBTLV_RSVP_IPV6: subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv6 = \ (const struct lspping_tlv_targetfec_subtlv_rsvp_ipv6_t *)subtlv_tptr; ND_PRINT((ndo, "\n\t tunnel end-point %s, tunnel sender %s, lsp-id 0x%04x" \ "\n\t tunnel-id 0x%04x, extended tunnel-id %s", ip6addr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv6->tunnel_endpoint), ip6addr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv6->tunnel_sender), EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv6->lsp_id), EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv6->tunnel_id), ip6addr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_rsvp_ipv6->extended_tunnel_id))); break; #endif case LSPPING_TLV_TARGETFEC_SUBTLV_L3VPN_IPV4: subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv4 = \ (const struct lspping_tlv_targetfec_subtlv_l3vpn_ipv4_t *)subtlv_tptr; ND_PRINT((ndo, "\n\t RD: %s, %s/%u", bgp_vpn_rd_print(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv4->rd), ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv4->prefix), subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv4->prefix_len)); break; #ifdef INET6 case LSPPING_TLV_TARGETFEC_SUBTLV_L3VPN_IPV6: subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv6 = \ (const struct lspping_tlv_targetfec_subtlv_l3vpn_ipv6_t *)subtlv_tptr; ND_PRINT((ndo, "\n\t RD: %s, %s/%u", bgp_vpn_rd_print(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv6->rd), ip6addr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv6->prefix), subtlv_ptr.lspping_tlv_targetfec_subtlv_l3vpn_ipv6->prefix_len)); break; #endif case LSPPING_TLV_TARGETFEC_SUBTLV_L2VPN_ENDPT: subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_endpt = \ (const struct lspping_tlv_targetfec_subtlv_l2vpn_endpt_t *)subtlv_tptr; ND_PRINT((ndo, "\n\t RD: %s, Sender CE-ID: %u, Receiver CE-ID: %u" \ "\n\t Encapsulation Type: %s (%u)", bgp_vpn_rd_print(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_endpt->rd), EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_endpt->sender_ce_id), EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_endpt->receiver_ce_id), tok2str(l2vpn_encaps_values, "unknown", EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_endpt->encapsulation)), EXTRACT_16BITS(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_L2VPN_VCID_OLD: subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid_old = \ (const struct lspping_tlv_targetfec_subtlv_l2vpn_vcid_old_t *)subtlv_tptr; ND_PRINT((ndo, "\n\t Remote PE: %s" \ "\n\t VC-ID: 0x%08x, Encapsulation Type: %s (%u)", ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid_old->remote_pe_address), EXTRACT_32BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid_old->vc_id), tok2str(l2vpn_encaps_values, "unknown", EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid_old->encapsulation)), EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid_old->encapsulation))); break; case LSPPING_TLV_TARGETFEC_SUBTLV_L2VPN_VCID: subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid = \ (const struct lspping_tlv_targetfec_subtlv_l2vpn_vcid_t *)subtlv_tptr; ND_PRINT((ndo, "\n\t Sender PE: %s, Remote PE: %s" \ "\n\t VC-ID: 0x%08x, Encapsulation Type: %s (%u)", ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid->sender_pe_address), ipaddr_string(ndo, subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid->remote_pe_address), EXTRACT_32BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid->vc_id), tok2str(l2vpn_encaps_values, "unknown", EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid->encapsulation)), EXTRACT_16BITS(subtlv_ptr.lspping_tlv_targetfec_subtlv_l2vpn_vcid->encapsulation))); 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); tlv_tptr+=lspping_subtlv_len; tlv_tlen-=lspping_subtlv_len+sizeof(struct lspping_tlv_header); } break; case LSPPING_TLV_DOWNSTREAM_MAPPING: /* that strange thing with the downstream map TLV is that until now - * we do not know if its IPv4 or IPv6 , after we found the adress-type + * we do not know if its IPv4 or IPv6 , after we found the address-type * lets recast the tlv_tptr and move on */ tlv_ptr.lspping_tlv_downstream_map_ipv4= \ (const struct lspping_tlv_downstream_map_ipv4_t *)tlv_tptr; tlv_ptr.lspping_tlv_downstream_map_ipv6= \ (const struct lspping_tlv_downstream_map_ipv6_t *)tlv_tptr; ND_PRINT((ndo, "\n\t MTU: %u, Address-Type: %s (%u)", EXTRACT_16BITS(tlv_ptr.lspping_tlv_downstream_map_ipv4->mtu), tok2str(lspping_tlv_downstream_addr_values, "unknown", tlv_ptr.lspping_tlv_downstream_map_ipv4->address_type), tlv_ptr.lspping_tlv_downstream_map_ipv4->address_type)); switch(tlv_ptr.lspping_tlv_downstream_map_ipv4->address_type) { case LSPPING_AFI_IPV4: ND_PRINT((ndo, "\n\t Downstream IP: %s" \ "\n\t Downstream Interface IP: %s", ipaddr_string(ndo, tlv_ptr.lspping_tlv_downstream_map_ipv4->downstream_ip), ipaddr_string(ndo, 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; #ifdef INET6 case LSPPING_AFI_IPV6: ND_PRINT((ndo, "\n\t Downstream IP: %s" \ "\n\t Downstream Interface IP: %s", ip6addr_string(ndo, tlv_ptr.lspping_tlv_downstream_map_ipv6->downstream_ip), ip6addr_string(ndo, 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; #endif case LSPPING_AFI_UNMB: ND_PRINT((ndo, "\n\t Downstream IP: %s" \ "\n\t Downstream Interface Index: 0x%08x", ipaddr_string(ndo, tlv_ptr.lspping_tlv_downstream_map_ipv4->downstream_ip), EXTRACT_32BITS(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; default: /* should not happen ! - no error message - tok2str() has barked already */ break; } 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 */ tlv_tptr+=sizeof(struct lspping_tlv_downstream_map_info_t); tlv_tlen-=sizeof(struct lspping_tlv_downstream_map_info_t); /* FIXME print downstream labels */ tlv_hexdump=TRUE; /* dump the TLV until code complete */ break; case LSPPING_TLV_BFD_DISCRIMINATOR: tptr += sizeof(struct lspping_tlv_header); ND_TCHECK2(*tptr, LSPPING_TLV_BFD_DISCRIMINATOR_LEN); ND_PRINT((ndo, "\n\t BFD Discriminator 0x%08x", EXTRACT_32BITS(tptr))); break; case LSPPING_TLV_VENDOR_ENTERPRISE: { uint32_t vendor_id; ND_TCHECK2(*tptr, LSPPING_TLV_VENDOR_ENTERPRISE_LEN); vendor_id = EXTRACT_32BITS(tlv_tptr); ND_PRINT((ndo, "\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 ? */ 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); } tptr+=lspping_tlv_len+sizeof(struct lspping_tlv_header); tlen-=lspping_tlv_len+sizeof(struct lspping_tlv_header); } return; trunc: ND_PRINT((ndo, "\n\t\t packet exceeded snapshot")); } /* * Local Variables: * c-style: whitesmith * c-basic-offset: 8 * End: */ Index: head/contrib/tcpdump/print-lwapp.c =================================================================== --- head/contrib/tcpdump/print-lwapp.c (revision 285274) +++ head/contrib/tcpdump/print-lwapp.c (revision 285275) @@ -1,348 +1,348 @@ /* * 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. * - * Support for the Light Weight Access Point Protocol as per draft-ohara-capwap-lwapp-04 + * Support for the Light Weight Access Point Protocol as per RFC 5412 * * Original code by Carles Kishimoto */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "interface.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 { uint8_t version; uint8_t frag_id; uint8_t length[2]; 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 { uint8_t msg_type; uint8_t seq_num; uint8_t len[2]; uint8_t session_id[4]; }; #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 { uint8_t type; uint8_t length[2]; }; void lwapp_control_print(netdissect_options *ndo, - const u_char *pptr, u_int len, int has_ap_ident) { - + 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; int tlen; int msg_tlen; tptr=pptr; if (has_ap_ident) { /* check if enough bytes for AP identity */ ND_TCHECK2(*tptr, 6); lwapp_trans_header = (const struct lwapp_transport_header *)(pptr+6); } else { lwapp_trans_header = (const struct lwapp_transport_header *)pptr; } ND_TCHECK(*lwapp_trans_header); /* * Sanity checking of the header. */ if (LWAPP_EXTRACT_VERSION(lwapp_trans_header->version) != LWAPP_VERSION) { ND_PRINT((ndo, "LWAPP version %u packet not supported", LWAPP_EXTRACT_VERSION(lwapp_trans_header->version))); return; } /* non-verbose */ if (ndo->ndo_vflag < 1) { ND_PRINT((ndo, "LWAPPv%u, %s frame, Flags [%s], length %u", LWAPP_EXTRACT_VERSION(lwapp_trans_header->version), LWAPP_EXTRACT_CONTROL_BIT(lwapp_trans_header->version) ? "Control" : "Data", bittok2str(lwapp_header_bits_values,"none",(lwapp_trans_header->version)&0x07), len)); return; } /* ok they seem to want to know everything - lets fully decode it */ tlen=EXTRACT_16BITS(lwapp_trans_header->length); ND_PRINT((ndo, "LWAPPv%u, %s frame, Radio-id %u, Flags [%s], Frag-id %u, length %u", LWAPP_EXTRACT_VERSION(lwapp_trans_header->version), LWAPP_EXTRACT_CONTROL_BIT(lwapp_trans_header->version) ? "Control" : "Data", LWAPP_EXTRACT_RID(lwapp_trans_header->version), bittok2str(lwapp_header_bits_values,"none",(lwapp_trans_header->version)&0x07), lwapp_trans_header->frag_id, tlen)); if (has_ap_ident) { ND_PRINT((ndo, "\n\tAP identity: %s", etheraddr_string(ndo, tptr))); tptr+=sizeof(const struct lwapp_transport_header)+6; } else { tptr+=sizeof(const struct lwapp_transport_header); } while(tlen>0) { /* did we capture enough for fully decoding the object header ? */ ND_TCHECK2(*tptr, sizeof(struct lwapp_control_header)); lwapp_control_header = (const struct lwapp_control_header *)tptr; msg_tlen = EXTRACT_16BITS(lwapp_control_header->len); /* print message header */ ND_PRINT((ndo, "\n\t Msg type: %s (%u), Seqnum: %u, Msg len: %d, Session: 0x%08x", tok2str(lwapp_msg_type_values,"Unknown",lwapp_control_header->msg_type), lwapp_control_header->msg_type, lwapp_control_header->seq_num, msg_tlen, EXTRACT_32BITS(lwapp_control_header->session_id))); /* did we capture enough for fully decoding the message */ ND_TCHECK2(*tptr, msg_tlen); /* XXX - Decode sub messages for each message */ switch(lwapp_control_header->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((ndo, "\n\t\t packet exceeded snapshot")); } void lwapp_data_print(netdissect_options *ndo, - const u_char *pptr, u_int len) { - + const u_char *pptr, u_int len) +{ const struct lwapp_transport_header *lwapp_trans_header; const u_char *tptr; int tlen; tptr=pptr; /* check if enough bytes for AP identity */ ND_TCHECK2(*tptr, 6); lwapp_trans_header = (const struct lwapp_transport_header *)pptr; ND_TCHECK(*lwapp_trans_header); /* * Sanity checking of the header. */ if (LWAPP_EXTRACT_VERSION(lwapp_trans_header->version) != LWAPP_VERSION) { ND_PRINT((ndo, "LWAPP version %u packet not supported", LWAPP_EXTRACT_VERSION(lwapp_trans_header->version))); return; } /* non-verbose */ if (ndo->ndo_vflag < 1) { ND_PRINT((ndo, "LWAPPv%u, %s frame, Flags [%s], length %u", LWAPP_EXTRACT_VERSION(lwapp_trans_header->version), LWAPP_EXTRACT_CONTROL_BIT(lwapp_trans_header->version) ? "Control" : "Data", bittok2str(lwapp_header_bits_values,"none",(lwapp_trans_header->version)&0x07), len)); return; } /* ok they seem to want to know everything - lets fully decode it */ tlen=EXTRACT_16BITS(lwapp_trans_header->length); ND_PRINT((ndo, "LWAPPv%u, %s frame, Radio-id %u, Flags [%s], Frag-id %u, length %u", LWAPP_EXTRACT_VERSION(lwapp_trans_header->version), LWAPP_EXTRACT_CONTROL_BIT(lwapp_trans_header->version) ? "Control" : "Data", LWAPP_EXTRACT_RID(lwapp_trans_header->version), bittok2str(lwapp_header_bits_values,"none",(lwapp_trans_header->version)&0x07), lwapp_trans_header->frag_id, tlen)); tptr+=sizeof(const struct lwapp_transport_header); tlen-=sizeof(const 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((ndo, "\n\t\t packet exceeded snapshot")); } /* * Local Variables: * c-style: whitesmith * c-basic-offset: 8 * End: */ Index: head/contrib/tcpdump/print-mobility.c =================================================================== --- head/contrib/tcpdump/print-mobility.c (revision 285274) +++ head/contrib/tcpdump/print-mobility.c (revision 285275) @@ -1,314 +1,334 @@ /* * 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. */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef INET6 #include #include "ip6.h" #include "interface.h" #include "addrtoname.h" #include "extract.h" /* must come after interface.h */ /* Mobility header */ struct ip6_mobility { uint8_t ip6m_pproto; /* following payload protocol (for PG) */ uint8_t ip6m_len; /* length in units of 8 octets */ uint8_t ip6m_type; /* message type */ uint8_t reserved; /* reserved */ uint16_t ip6m_cksum; /* sum of IPv6 pseudo-header and MH */ union { uint16_t ip6m_un_data16[1]; /* type-specific field */ 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 /* http://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 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 */ +}; + /* XXX: unused */ #define IP6MOPT_BU_MINLEN 10 #define IP6MOPT_BA_MINLEN 13 #define IP6MOPT_BR_MINLEN 2 /* 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 void mobility_opt_print(netdissect_options *ndo, const u_char *bp, const unsigned len) { unsigned i, optlen; for (i = 0; i < len; i += optlen) { + ND_TCHECK(bp[i]); if (bp[i] == IP6MOPT_PAD1) optlen = 1; else { - if (i + 1 < len) + if (i + 1 < len) { + ND_TCHECK(bp[i + 1]); optlen = bp[i + 1] + 2; + } else goto trunc; } if (i + optlen > len) goto trunc; + ND_TCHECK(bp[i + optlen]); switch (bp[i]) { case IP6MOPT_PAD1: ND_PRINT((ndo, "(pad1)")); break; case IP6MOPT_PADN: if (len - i < IP6MOPT_MINLEN) { ND_PRINT((ndo, "(padn: trunc)")); goto trunc; } ND_PRINT((ndo, "(padn)")); break; case IP6MOPT_REFRESH: if (len - i < IP6MOPT_REFRESH_MINLEN) { ND_PRINT((ndo, "(refresh: trunc)")); goto trunc; } /* units of 4 secs */ ND_PRINT((ndo, "(refresh: %u)", EXTRACT_16BITS(&bp[i+2]) << 2)); break; case IP6MOPT_ALTCOA: if (len - i < IP6MOPT_ALTCOA_MINLEN) { ND_PRINT((ndo, "(altcoa: trunc)")); goto trunc; } ND_PRINT((ndo, "(alt-CoA: %s)", ip6addr_string(ndo, &bp[i+2]))); break; case IP6MOPT_NONCEID: if (len - i < IP6MOPT_NONCEID_MINLEN) { ND_PRINT((ndo, "(ni: trunc)")); goto trunc; } ND_PRINT((ndo, "(ni: ho=0x%04x co=0x%04x)", EXTRACT_16BITS(&bp[i+2]), EXTRACT_16BITS(&bp[i+4]))); break; case IP6MOPT_AUTH: if (len - i < IP6MOPT_AUTH_MINLEN) { ND_PRINT((ndo, "(auth: trunc)")); goto trunc; } ND_PRINT((ndo, "(auth)")); break; default: if (len - i < IP6MOPT_MINLEN) { ND_PRINT((ndo, "(sopt_type %u: trunc)", bp[i])); goto trunc; } ND_PRINT((ndo, "(type-0x%02x: len=%u)", bp[i], bp[i + 1])); break; } } return; trunc: ND_PRINT((ndo, "[trunc] ")); } /* * 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; mh = (struct ip6_mobility *)bp; /* 'ep' points to the end of available data. */ ep = ndo->ndo_snapend; if (!ND_TTEST(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 = ep - bp; goto trunc; } mhlen = (mh->ip6m_len + 1) << 3; /* XXX ip6m_cksum */ ND_TCHECK(mh->ip6m_type); type = mh->ip6m_type; + if (type <= IP6M_MAX && mhlen < ip6m_hdrlen[type]) { + ND_PRINT((ndo, "(header length %u is too small for type %u)", mhlen, type)); + goto trunc; + } switch (type) { case IP6M_BINDING_REQUEST: ND_PRINT((ndo, "mobility: BRR")); hlen = IP6M_MINLEN; break; case IP6M_HOME_TEST_INIT: case IP6M_CAREOF_TEST_INIT: ND_PRINT((ndo, "mobility: %soTI", type == IP6M_HOME_TEST_INIT ? "H" : "C")); hlen = IP6M_MINLEN; if (ndo->ndo_vflag) { ND_TCHECK2(*mh, hlen + 8); ND_PRINT((ndo, " %s Init Cookie=%08x:%08x", type == IP6M_HOME_TEST_INIT ? "Home" : "Care-of", EXTRACT_32BITS(&bp[hlen]), EXTRACT_32BITS(&bp[hlen + 4]))); } hlen += 8; break; case IP6M_HOME_TEST: case IP6M_CAREOF_TEST: ND_PRINT((ndo, "mobility: %soT", type == IP6M_HOME_TEST ? "H" : "C")); ND_TCHECK(mh->ip6m_data16[0]); ND_PRINT((ndo, " nonce id=0x%x", EXTRACT_16BITS(&mh->ip6m_data16[0]))); hlen = IP6M_MINLEN; if (ndo->ndo_vflag) { ND_TCHECK2(*mh, hlen + 8); ND_PRINT((ndo, " %s Init Cookie=%08x:%08x", type == IP6M_HOME_TEST ? "Home" : "Care-of", EXTRACT_32BITS(&bp[hlen]), EXTRACT_32BITS(&bp[hlen + 4]))); } hlen += 8; if (ndo->ndo_vflag) { ND_TCHECK2(*mh, hlen + 8); ND_PRINT((ndo, " %s Keygen Token=%08x:%08x", type == IP6M_HOME_TEST ? "Home" : "Care-of", EXTRACT_32BITS(&bp[hlen]), EXTRACT_32BITS(&bp[hlen + 4]))); } hlen += 8; break; case IP6M_BINDING_UPDATE: ND_PRINT((ndo, "mobility: BU")); ND_TCHECK(mh->ip6m_data16[0]); ND_PRINT((ndo, " seq#=%u", EXTRACT_16BITS(&mh->ip6m_data16[0]))); hlen = IP6M_MINLEN; ND_TCHECK2(*mh, hlen + 1); if (bp[hlen] & 0xf0) ND_PRINT((ndo, " ")); if (bp[hlen] & 0x80) ND_PRINT((ndo, "A")); if (bp[hlen] & 0x40) ND_PRINT((ndo, "H")); if (bp[hlen] & 0x20) ND_PRINT((ndo, "L")); if (bp[hlen] & 0x10) ND_PRINT((ndo, "K")); /* Reserved (4bits) */ hlen += 1; /* Reserved (8bits) */ hlen += 1; ND_TCHECK2(*mh, hlen + 2); /* units of 4 secs */ ND_PRINT((ndo, " lifetime=%u", EXTRACT_16BITS(&bp[hlen]) << 2)); hlen += 2; break; case IP6M_BINDING_ACK: ND_PRINT((ndo, "mobility: BA")); ND_TCHECK(mh->ip6m_data8[0]); ND_PRINT((ndo, " status=%u", mh->ip6m_data8[0])); if (mh->ip6m_data8[1] & 0x80) ND_PRINT((ndo, " K")); /* Reserved (7bits) */ hlen = IP6M_MINLEN; ND_TCHECK2(*mh, hlen + 2); ND_PRINT((ndo, " seq#=%u", EXTRACT_16BITS(&bp[hlen]))); hlen += 2; ND_TCHECK2(*mh, hlen + 2); /* units of 4 secs */ ND_PRINT((ndo, " lifetime=%u", EXTRACT_16BITS(&bp[hlen]) << 2)); hlen += 2; break; case IP6M_BINDING_ERROR: ND_PRINT((ndo, "mobility: BE")); ND_TCHECK(mh->ip6m_data8[0]); ND_PRINT((ndo, " status=%u", mh->ip6m_data8[0])); /* Reserved */ hlen = IP6M_MINLEN; ND_TCHECK2(*mh, hlen + 16); ND_PRINT((ndo, " homeaddr %s", ip6addr_string(ndo, &bp[hlen]))); hlen += 16; break; default: ND_PRINT((ndo, "mobility: type-#%u len=%u", type, mh->ip6m_len)); return(mhlen); break; } if (ndo->ndo_vflag) mobility_opt_print(ndo, &bp[hlen], mhlen - hlen); return(mhlen); trunc: ND_PRINT((ndo, "[|MOBILITY]")); return(mhlen); } #endif /* INET6 */ Index: head/contrib/tcpdump/print-mpcp.c =================================================================== --- head/contrib/tcpdump/print-mpcp.c (revision 285274) +++ head/contrib/tcpdump/print-mpcp.c (revision 285275) @@ -1,260 +1,260 @@ /* * 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 MPCP protocol as per 802.3ah * * Original code by Hannes Gredler (hannes@juniper.net) */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "interface.h" #include "extract.h" #define MPCP_TIMESTAMP_LEN 4 #define MPCP_TIMESTAMP_DURATION_LEN 2 struct mpcp_common_header_t { uint8_t opcode[2]; uint8_t timestamp[MPCP_TIMESTAMP_LEN]; }; #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 { uint8_t starttime[MPCP_TIMESTAMP_LEN]; uint8_t duration[MPCP_TIMESTAMP_DURATION_LEN]; }; struct mpcp_reg_req_t { uint8_t flags; uint8_t pending_grants; }; static const struct tok mpcp_reg_req_flag_values[] = { { 1, "Register" }, { 3, "De-Register" }, { 0, NULL} }; struct mpcp_reg_t { uint8_t assigned_port[2]; uint8_t flags; uint8_t sync_time[MPCP_TIMESTAMP_DURATION_LEN]; 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 { uint8_t flags; uint8_t echoed_assigned_port[2]; uint8_t echoed_sync_time[MPCP_TIMESTAMP_DURATION_LEN]; }; static const struct tok mpcp_reg_ack_flag_values[] = { { 0, "NACK" }, { 1, "ACK" }, { 0, NULL} }; void -mpcp_print(netdissect_options *ndo, register const u_char *pptr, register u_int length) { - +mpcp_print(netdissect_options *ndo, register const u_char *pptr, register u_int length) +{ union { const struct mpcp_common_header_t *common_header; const struct mpcp_grant_t *grant; const struct mpcp_reg_req_t *reg_req; const struct mpcp_reg_t *reg; const struct mpcp_reg_ack_t *reg_ack; } mpcp; const u_char *tptr; uint16_t opcode; uint8_t grant_numbers, grant; uint8_t queue_sets, queue_set, report_bitmap, report; tptr=pptr; mpcp.common_header = (const struct mpcp_common_header_t *)pptr; ND_TCHECK2(*tptr, sizeof(const struct mpcp_common_header_t)); opcode = EXTRACT_16BITS(mpcp.common_header->opcode); ND_PRINT((ndo, "MPCP, Opcode %s", tok2str(mpcp_opcode_values, "Unknown (%u)", opcode))); if (opcode != MPCP_OPCODE_PAUSE) { ND_PRINT((ndo, ", Timestamp %u ticks", EXTRACT_32BITS(mpcp.common_header->timestamp))); } ND_PRINT((ndo, ", length %u", length)); if (!ndo->ndo_vflag) return; tptr += sizeof(const struct mpcp_common_header_t); switch (opcode) { case MPCP_OPCODE_PAUSE: break; case MPCP_OPCODE_GATE: ND_TCHECK2(*tptr, MPCP_GRANT_NUMBER_LEN); grant_numbers = *tptr & MPCP_GRANT_NUMBER_MASK; ND_PRINT((ndo, "\n\tGrant Numbers %u, Flags [ %s ]", grant_numbers, bittok2str(mpcp_grant_flag_values, "?", *tptr &~ MPCP_GRANT_NUMBER_MASK))); tptr++; for (grant = 1; grant <= grant_numbers; grant++) { ND_TCHECK2(*tptr, sizeof(const struct mpcp_grant_t)); mpcp.grant = (const struct mpcp_grant_t *)tptr; ND_PRINT((ndo, "\n\tGrant #%u, Start-Time %u ticks, duration %u ticks", grant, EXTRACT_32BITS(mpcp.grant->starttime), EXTRACT_16BITS(mpcp.grant->duration))); tptr += sizeof(const struct mpcp_grant_t); } ND_TCHECK2(*tptr, MPCP_TIMESTAMP_DURATION_LEN); ND_PRINT((ndo, "\n\tSync-Time %u ticks", EXTRACT_16BITS(tptr))); break; case MPCP_OPCODE_REPORT: ND_TCHECK2(*tptr, MPCP_REPORT_QUEUESETS_LEN); queue_sets = *tptr; tptr+=MPCP_REPORT_QUEUESETS_LEN; ND_PRINT((ndo, "\n\tTotal Queue-Sets %u", queue_sets)); for (queue_set = 1; queue_set < queue_sets; queue_set++) { ND_TCHECK2(*tptr, MPCP_REPORT_REPORTBITMAP_LEN); report_bitmap = *(tptr); ND_PRINT((ndo, "\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_TCHECK2(*tptr, MPCP_TIMESTAMP_DURATION_LEN); ND_PRINT((ndo, "\n\t Q%u Report, Duration %u ticks", report, EXTRACT_16BITS(tptr))); tptr+=MPCP_TIMESTAMP_DURATION_LEN; } report++; report_bitmap = report_bitmap >> 1; } } break; case MPCP_OPCODE_REG_REQ: ND_TCHECK2(*tptr, sizeof(const struct mpcp_reg_req_t)); mpcp.reg_req = (const struct mpcp_reg_req_t *)tptr; ND_PRINT((ndo, "\n\tFlags [ %s ], Pending-Grants %u", bittok2str(mpcp_reg_req_flag_values, "Reserved", mpcp.reg_req->flags), mpcp.reg_req->pending_grants)); break; case MPCP_OPCODE_REG: ND_TCHECK2(*tptr, sizeof(const struct mpcp_reg_t)); mpcp.reg = (const struct mpcp_reg_t *)tptr; ND_PRINT((ndo, "\n\tAssigned-Port %u, Flags [ %s ]" \ "\n\tSync-Time %u ticks, Echoed-Pending-Grants %u", EXTRACT_16BITS(mpcp.reg->assigned_port), bittok2str(mpcp_reg_flag_values, "Reserved", mpcp.reg->flags), EXTRACT_16BITS(mpcp.reg->sync_time), mpcp.reg->echoed_pending_grants)); break; case MPCP_OPCODE_REG_ACK: ND_TCHECK2(*tptr, sizeof(const struct mpcp_reg_ack_t)); mpcp.reg_ack = (const struct mpcp_reg_ack_t *)tptr; ND_PRINT((ndo, "\n\tEchoed-Assigned-Port %u, Flags [ %s ]" \ "\n\tEchoed-Sync-Time %u ticks", EXTRACT_16BITS(mpcp.reg_ack->echoed_assigned_port), bittok2str(mpcp_reg_ack_flag_values, "Reserved", mpcp.reg_ack->flags), EXTRACT_16BITS(mpcp.reg_ack->echoed_sync_time))); break; default: /* unknown opcode - hexdump for now */ print_unknown_data(ndo,pptr, "\n\t", length); break; } return; trunc: ND_PRINT((ndo, "\n\t[|MPCP]")); } /* * Local Variables: * c-style: whitesmith * c-basic-offset: 8 * End: */ Index: head/contrib/tcpdump/print-mpls.c =================================================================== --- head/contrib/tcpdump/print-mpls.c (revision 285274) +++ head/contrib/tcpdump/print-mpls.c (revision 285275) @@ -1,215 +1,211 @@ /* * 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. */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "interface.h" #include "extract.h" /* must come after interface.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; enum mpls_packet_type pt = PT_UNKNOWN; p = bp; ND_PRINT((ndo, "MPLS")); do { ND_TCHECK2(*p, sizeof(label_entry)); label_entry = EXTRACT_32BITS(p); ND_PRINT((ndo, "%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((ndo, " (%s)", mpls_labelname[MPLS_LABEL(label_entry)])); ND_PRINT((ndo, ", exp %u", MPLS_EXP(label_entry))); if (MPLS_STACK(label_entry)) ND_PRINT((ndo, ", [S]")); ND_PRINT((ndo, ", ttl %u)", MPLS_TTL(label_entry))); p += 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. */ switch(*p) { case 0x45: case 0x46: case 0x47: case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f: pt = PT_IPV4; 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: pt = PT_IPV6; break; case 0x81: case 0x82: case 0x83: pt = PT_OSI; break; default: /* ok bail out - we did not figure out what it is*/ break; } } /* * Print the payload. */ if (pt == PT_UNKNOWN) { if (!ndo->ndo_suppress_default_print) ND_DEFAULTPRINT(p, length - (p - bp)); return; } ND_PRINT((ndo, ndo->ndo_vflag ? "\n\t" : " ")); switch (pt) { case PT_IPV4: ip_print(ndo, p, length - (p - bp)); break; case PT_IPV6: -#ifdef INET6 ip6_print(ndo, p, length - (p - bp)); -#else - ND_PRINT((ndo, "IPv6, length: %u", length)); -#endif break; case PT_OSI: isoclns_print(ndo, p, length - (p - bp), length - (p - bp)); break; default: break; } return; trunc: ND_PRINT((ndo, "[|MPLS]")); } /* * Local Variables: * c-style: whitesmith * c-basic-offset: 8 * End: */ Index: head/contrib/tcpdump/print-nflog.c =================================================================== --- head/contrib/tcpdump/print-nflog.c (revision 285274) +++ head/contrib/tcpdump/print-nflog.c (revision 285275) @@ -1,167 +1,167 @@ /* * 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. */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "interface.h" #if defined(DLT_NFLOG) && defined(HAVE_PCAP_NFLOG_H) #include static const struct tok nflog_values[] = { { AF_INET, "IPv4" }, #ifdef INET6 { AF_INET6, "IPv6" }, #endif /*INET6*/ { 0, NULL } }; static inline void nflog_hdr_print(netdissect_options *ndo, const nflog_hdr_t *hdr, u_int length) { ND_PRINT((ndo, "version %d, resource ID %d", hdr->nflog_version, ntohs(hdr->nflog_rid))); if (!ndo->ndo_qflag) { ND_PRINT((ndo,", family %s (%d)", tok2str(nflog_values, "Unknown", hdr->nflog_family), hdr->nflog_family)); } else { ND_PRINT((ndo,", %s", tok2str(nflog_values, "Unknown NFLOG (0x%02x)", hdr->nflog_family))); } ND_PRINT((ndo, ", length %u: ", length)); } u_int 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; const nflog_tlv_t *tlv; uint16_t size; uint16_t h_size = sizeof(nflog_hdr_t); u_int caplen = h->caplen; u_int length = h->len; if (caplen < (int) sizeof(nflog_hdr_t) || length < (int) sizeof(nflog_hdr_t)) { ND_PRINT((ndo, "[|nflog]")); return h_size; } if (!(hdr->nflog_version) == 0) { ND_PRINT((ndo, "version %u (unknown)", hdr->nflog_version)); return h_size; } if (ndo->ndo_eflag) nflog_hdr_print(ndo, hdr, length); p += sizeof(nflog_hdr_t); length -= sizeof(nflog_hdr_t); caplen -= sizeof(nflog_hdr_t); while (length > 0) { /* We have some data. Do we have enough for the TLV header? */ if (caplen < sizeof(nflog_tlv_t) || length < sizeof(nflog_tlv_t)) { /* No. */ ND_PRINT((ndo, "[|nflog]")); return h_size; } tlv = (const nflog_tlv_t *) p; size = tlv->tlv_length; if (size % 4 != 0) size += 4 - size % 4; /* Is the TLV's length less than the minimum? */ if (size < sizeof(nflog_tlv_t)) { /* Yes. Give up now. */ ND_PRINT((ndo, "[|nflog]")); return h_size; } /* Do we have enough data for the full TLV? */ if (caplen < size || length < size) { /* No. */ ND_PRINT((ndo, "[|nflog]")); return h_size; } if (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 += sizeof(nflog_tlv_t); h_size += sizeof(nflog_tlv_t); length -= sizeof(nflog_tlv_t); caplen -= sizeof(nflog_tlv_t); break; } p += size; h_size += size; length -= size; caplen -= size; } switch (hdr->nflog_family) { case AF_INET: ip_print(ndo, p, length); break; -#ifdef INET6 +#ifdef AF_INET6 case AF_INET6: ip6_print(ndo, p, length); break; -#endif /*INET6*/ +#endif /* AF_INET6 */ default: if (!ndo->ndo_eflag) nflog_hdr_print(ndo, hdr, length + sizeof(nflog_hdr_t)); if (!ndo->ndo_suppress_default_print) ND_DEFAULTPRINT(p, caplen); break; } return h_size; } #endif /* defined(DLT_NFLOG) && defined(HAVE_PCAP_NFLOG_H) */ Index: head/contrib/tcpdump/print-null.c =================================================================== --- head/contrib/tcpdump/print-null.c (revision 285274) +++ head/contrib/tcpdump/print-null.c (revision 285275) @@ -1,150 +1,148 @@ /* * 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. * * $FreeBSD$ */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "interface.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 inline void null_hdr_print(netdissect_options *ndo, u_int family, u_int length) { if (!ndo->ndo_qflag) { ND_PRINT((ndo, "AF %s (%u)", tok2str(bsd_af_values,"Unknown",family),family)); } else { ND_PRINT((ndo, "%s", tok2str(bsd_af_values,"Unknown AF %u",family))); } ND_PRINT((ndo, ", 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. */ u_int 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; u_int family; if (caplen < NULL_HDRLEN) { ND_PRINT((ndo, "[|null]")); return (NULL_HDRLEN); } memcpy((char *)&family, (char *)p, sizeof(family)); /* * 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; -#ifdef INET6 case BSD_AFNUM_INET6_BSD: case BSD_AFNUM_INET6_FREEBSD: case BSD_AFNUM_INET6_DARWIN: ip6_print(ndo, p, length); break; -#endif case BSD_AFNUM_ISO: isoclns_print(ndo, p, length, caplen); 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); } return (NULL_HDRLEN); } /* * Local Variables: * c-style: whitesmith * c-basic-offset: 8 * End: */ Index: head/contrib/tcpdump/print-olsr.c =================================================================== --- head/contrib/tcpdump/print-olsr.c (revision 285274) +++ head/contrib/tcpdump/print-olsr.c (revision 285275) @@ -1,614 +1,644 @@ /* * 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. * * Optimized Link State Protocl (OLSR) as per rfc3626 * * Original code by Hannes Gredler * IPv6 additions by Florian Forster */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "interface.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 { uint8_t packet_len[2]; uint8_t packet_seq[2]; }; #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 { uint8_t msg_type; uint8_t vtime; uint8_t msg_len[2]; uint8_t originator[4]; uint8_t ttl; uint8_t hopcount; uint8_t msg_seq[2]; }; struct olsr_msg6 { uint8_t msg_type; uint8_t vtime; uint8_t msg_len[2]; uint8_t originator[16]; uint8_t ttl; uint8_t hopcount; uint8_t msg_seq[2]; }; struct olsr_hello { uint8_t res[2]; uint8_t htime; uint8_t will; }; struct olsr_hello_link { uint8_t link_code; uint8_t res; uint8_t len[2]; }; struct olsr_tc { uint8_t ans_seq[2]; uint8_t res[2]; }; struct olsr_hna4 { uint8_t network[4]; uint8_t mask[4]; }; struct olsr_hna6 { uint8_t network[16]; uint8_t mask[16]; }; #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 { uint8_t neighbor[4]; uint8_t link_quality; uint8_t neighbor_link_quality; uint8_t res[2]; }; struct olsr_lq_neighbor6 { uint8_t neighbor[16]; uint8_t link_quality; uint8_t neighbor_link_quality; uint8_t res[2]; }; /* * 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 void +static int olsr_print_lq_neighbor4(netdissect_options *ndo, const u_char *msg_data, u_int hello_len) { struct olsr_lq_neighbor4 *lq_neighbor; while (hello_len >= sizeof(struct olsr_lq_neighbor4)) { lq_neighbor = (struct olsr_lq_neighbor4 *)msg_data; + if (!ND_TTEST(*lq_neighbor)) + return (-1); ND_PRINT((ndo, "\n\t neighbor %s, link-quality %.2lf%%" ", neighbor-link-quality %.2lf%%", ipaddr_string(ndo, lq_neighbor->neighbor), ((double)lq_neighbor->link_quality/2.55), ((double)lq_neighbor->neighbor_link_quality/2.55))); msg_data += sizeof(struct olsr_lq_neighbor4); hello_len -= sizeof(struct olsr_lq_neighbor4); } + return (0); } #if INET6 -static void +static int olsr_print_lq_neighbor6(netdissect_options *ndo, const u_char *msg_data, u_int hello_len) { struct olsr_lq_neighbor6 *lq_neighbor; while (hello_len >= sizeof(struct olsr_lq_neighbor6)) { lq_neighbor = (struct olsr_lq_neighbor6 *)msg_data; + if (!ND_TTEST(*lq_neighbor)) + return (-1); ND_PRINT((ndo, "\n\t neighbor %s, link-quality %.2lf%%" ", neighbor-link-quality %.2lf%%", ip6addr_string(ndo, lq_neighbor->neighbor), ((double)lq_neighbor->link_quality/2.55), ((double)lq_neighbor->neighbor_link_quality/2.55))); msg_data += sizeof(struct olsr_lq_neighbor6); hello_len -= sizeof(struct olsr_lq_neighbor6); } + return (0); } #endif /* INET6 */ /* * print a neighbor list. */ -static void +static int olsr_print_neighbor(netdissect_options *ndo, const u_char *msg_data, u_int hello_len) { int neighbor; ND_PRINT((ndo, "\n\t neighbor\n\t\t")); neighbor = 1; while (hello_len >= sizeof(struct in_addr)) { + if (!ND_TTEST2(*msg_data, sizeof(struct in_addr))) + return (-1); /* print 4 neighbors per line */ ND_PRINT((ndo, "%s%s", ipaddr_string(ndo, msg_data), neighbor % 4 == 0 ? "\n\t\t" : " ")); msg_data += sizeof(struct in_addr); hello_len -= sizeof(struct in_addr); } + 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; tptr = pptr; if (length < sizeof(struct olsr_common)) { goto trunc; } ND_TCHECK2(*tptr, sizeof(struct olsr_common)); ptr.common = (struct olsr_common *)tptr; length = min(length, EXTRACT_16BITS(ptr.common->packet_len)); ND_PRINT((ndo, "OLSRv%i, seq 0x%04x, length %u", (is_ipv6 == 0) ? 4 : 6, EXTRACT_16BITS(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 { struct olsr_msg4 *v4; struct olsr_msg6 *v6; } msgptr; int msg_len_valid = 0; ND_TCHECK2(*tptr, sizeof(struct olsr_msg4)); #if INET6 if (is_ipv6) { msgptr.v6 = (struct olsr_msg6 *) tptr; msg_type = msgptr.v6->msg_type; msg_len = EXTRACT_16BITS(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((ndo, "\n\t%s Message (%#04x), originator %s, ttl %u, hop %u" "\n\t vtime %.3lfs, msg-seq 0x%04x, length %u%s", tok2str(olsr_msg_values, "Unknown", msg_type), msg_type, ip6addr_string(ndo, msgptr.v6->originator), msgptr.v6->ttl, msgptr.v6->hopcount, ME_TO_DOUBLE(msgptr.v6->vtime), EXTRACT_16BITS(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) */ #endif /* INET6 */ { msgptr.v4 = (struct olsr_msg4 *) tptr; msg_type = msgptr.v4->msg_type; msg_len = EXTRACT_16BITS(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((ndo, "\n\t%s Message (%#04x), originator %s, ttl %u, hop %u" "\n\t vtime %.3lfs, msg-seq 0x%04x, length %u%s", tok2str(olsr_msg_values, "Unknown", msg_type), msg_type, ipaddr_string(ndo, msgptr.v4->originator), msgptr.v4->ttl, msgptr.v4->hopcount, ME_TO_DOUBLE(msgptr.v4->vtime), EXTRACT_16BITS(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_TCHECK2(*msg_data, sizeof(struct olsr_hello)); ptr.hello = (struct olsr_hello *)msg_data; ND_PRINT((ndo, "\n\t hello-time %.3lfs, MPR willingness %u", ME_TO_DOUBLE(ptr.hello->htime), 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_TCHECK2(*msg_data, sizeof(struct olsr_hello_link)); ptr.hello_link = (struct olsr_hello_link *)msg_data; hello_len = EXTRACT_16BITS(ptr.hello_link->len); link_type = OLSR_EXTRACT_LINK_TYPE(ptr.hello_link->link_code); neighbor_type = OLSR_EXTRACT_NEIGHBOR_TYPE(ptr.hello_link->link_code); if ((hello_len <= msg_tlen) && (hello_len >= sizeof(struct olsr_hello_link))) hello_len_valid = 1; ND_PRINT((ndo, "\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_TCHECK2(*msg_data, hello_len); if (msg_type == OLSR_HELLO_MSG) { - olsr_print_neighbor(ndo, msg_data, hello_len); + if (olsr_print_neighbor(ndo, msg_data, hello_len) == -1) + goto trunc; } else { #if INET6 - if (is_ipv6) - olsr_print_lq_neighbor6(ndo, msg_data, hello_len); - else + if (is_ipv6) { + if (olsr_print_lq_neighbor6(ndo, msg_data, hello_len) == -1) + goto trunc; + } else #endif - olsr_print_lq_neighbor4(ndo, msg_data, hello_len); + { + 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_TCHECK2(*msg_data, sizeof(struct olsr_tc)); ptr.tc = (struct olsr_tc *)msg_data; ND_PRINT((ndo, "\n\t advertised neighbor seq 0x%04x", EXTRACT_16BITS(ptr.tc->ans_seq))); msg_data += sizeof(struct olsr_tc); msg_tlen -= sizeof(struct olsr_tc); if (msg_type == OLSR_TC_MSG) { - olsr_print_neighbor(ndo, msg_data, msg_tlen); + if (olsr_print_neighbor(ndo, msg_data, msg_tlen) == -1) + goto trunc; } else { #if INET6 - if (is_ipv6) - olsr_print_lq_neighbor6(ndo, msg_data, msg_tlen); - else + if (is_ipv6) { + if (olsr_print_lq_neighbor6(ndo, msg_data, msg_tlen) == -1) + goto trunc; + } else #endif - olsr_print_lq_neighbor4(ndo, msg_data, msg_tlen); + { + if (olsr_print_lq_neighbor4(ndo, msg_data, msg_tlen) == -1) + goto trunc; + } } break; case OLSR_MID_MSG: { size_t addr_size = sizeof(struct in_addr); #if INET6 if (is_ipv6) addr_size = sizeof(struct in6_addr); #endif while (msg_tlen >= addr_size) { ND_TCHECK2(*msg_data, addr_size); #if INET6 ND_PRINT((ndo, "\n\t interface address %s", is_ipv6 ? ip6addr_string(ndo, msg_data) : ipaddr_string(ndo, msg_data))); #else ND_PRINT((ndo, "\n\t interface address %s", ipaddr_string(ndo, msg_data))); #endif msg_data += addr_size; msg_tlen -= addr_size; } break; } case OLSR_HNA_MSG: ND_PRINT((ndo, "\n\t Advertised networks (total %u)", (unsigned int) (msg_tlen / sizeof(struct olsr_hna6)))); #if INET6 if (is_ipv6) { int i = 0; while (msg_tlen >= sizeof(struct olsr_hna6)) { struct olsr_hna6 *hna6; ND_TCHECK2(*msg_data, sizeof(struct olsr_hna6)); hna6 = (struct olsr_hna6 *)msg_data; ND_PRINT((ndo, "\n\t #%i: %s/%u", i, ip6addr_string(ndo, hna6->network), mask62plen (hna6->mask))); msg_data += sizeof(struct olsr_hna6); msg_tlen -= sizeof(struct olsr_hna6); } } else #endif { int col = 0; while (msg_tlen >= sizeof(struct olsr_hna4)) { ND_TCHECK2(*msg_data, sizeof(struct olsr_hna4)); ptr.hna = (struct olsr_hna4 *)msg_data; /* print 4 prefixes per line */ ND_PRINT((ndo, "%s%s/%u", col == 0 ? "\n\t " : ", ", ipaddr_string(ndo, ptr.hna->network), mask2plen(EXTRACT_32BITS(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 = EXTRACT_16BITS(msg_data+2); u_int addr_size = 4; int name_entries_valid = 0; u_int i; if (is_ipv6) addr_size = 16; if ((name_entries > 0) && ((name_entries * (4 + addr_size)) <= msg_tlen)) name_entries_valid = 1; if (msg_tlen < 4) goto trunc; ND_TCHECK2(*msg_data, 4); ND_PRINT((ndo, "\n\t Version %u, Entries %u%s", EXTRACT_16BITS(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; ND_TCHECK2(*msg_data, 4); name_entry_type = EXTRACT_16BITS(msg_data); name_entry_len = EXTRACT_16BITS(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((ndo, "\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_TCHECK2(*msg_data, addr_size + name_entry_len + name_entry_padding); #if INET6 if (is_ipv6) ND_PRINT((ndo, ", address %s, name \"", ip6addr_string(ndo, msg_data))); else #endif ND_PRINT((ndo, ", address %s, name \"", ipaddr_string(ndo, msg_data))); - fn_printn(ndo, msg_data + addr_size, name_entry_len, NULL); + (void)fn_printn(ndo, msg_data + addr_size, name_entry_len, NULL); ND_PRINT((ndo, "\"")); 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((ndo, "[|olsr]")); } /* * Local Variables: * c-style: whitesmith * c-basic-offset: 4 * End: */ Index: head/contrib/tcpdump/print-openflow-1.0.c =================================================================== --- head/contrib/tcpdump/print-openflow-1.0.c (revision 285274) +++ head/contrib/tcpdump/print-openflow-1.0.c (revision 285275) @@ -1,2078 +1,2560 @@ /* * 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] http://www.openflow.org/documents/openflow-spec-v1.0.0.pdf * + * Most functions in this file take 3 arguments into account: + * * cp -- the pointer to the first octet to decode + * * len -- the length of the current structure as declared on the wire + * * ep -- the pointer to the end of the captured frame + * They return either the pointer to the next not-yet-decoded part of the frame + * or the value of ep, which means the current frame processing is over as it + * has been fully decoded or is malformed or truncated. This way it is possible + * to chain and nest such functions uniformly to decode an OF1.0 message, which + * consists of several layers of nested structures. + * * 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. */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "interface.h" #include "extract.h" #include "addrtoname.h" #include "ether.h" #include "ethertype.h" #include "ipproto.h" +#include "oui.h" #include "openflow.h" static const char tstr[] = " [|openflow]"; static const char cstr[] = " (corrupt)"; #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 static const struct tok ofpt_str[] = { { OFPT_HELLO, "HELLO" }, { OFPT_ERROR, "ERROR" }, { OFPT_ECHO_REQUEST, "ECHO_REQUEST" }, { OFPT_ECHO_REPLY, "ECHO_REPLY" }, { OFPT_VENDOR, "VENDOR" }, { OFPT_FEATURES_REQUEST, "FEATURES_REQUEST" }, { OFPT_FEATURES_REPLY, "FEATURES_REPLY" }, { OFPT_GET_CONFIG_REQUEST, "GET_CONFIG_REQUEST" }, { OFPT_GET_CONFIG_REPLY, "GET_CONFIG_REPLY" }, { OFPT_SET_CONFIG, "SET_CONFIG" }, { OFPT_PACKET_IN, "PACKET_IN" }, { OFPT_FLOW_REMOVED, "FLOW_REMOVED" }, { OFPT_PORT_STATUS, "PORT_STATUS" }, { OFPT_PACKET_OUT, "PACKET_OUT" }, { OFPT_FLOW_MOD, "FLOW_MOD" }, { OFPT_PORT_MOD, "PORT_MOD" }, { OFPT_STATS_REQUEST, "STATS_REQUEST" }, { OFPT_STATS_REPLY, "STATS_REPLY" }, { OFPT_BARRIER_REQUEST, "BARRIER_REQUEST" }, { OFPT_BARRIER_REPLY, "BARRIER_REPLY" }, { OFPT_QUEUE_GET_CONFIG_REQUEST, "QUEUE_GET_CONFIG_REQUEST" }, { OFPT_QUEUE_GET_CONFIG_REPLY, "QUEUE_GET_CONFIG_REPLY" }, { 0, NULL } }; #define OFPPC_PORT_DOWN (1 << 0) #define OFPPC_NO_STP (1 << 1) #define OFPPC_NO_RECV (1 << 2) #define OFPPC_NO_RECV_STP (1 << 3) #define OFPPC_NO_FLOOD (1 << 4) #define OFPPC_NO_FWD (1 << 5) #define OFPPC_NO_PACKET_IN (1 << 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)) #define OFPPS_LINK_DOWN (1 << 0) #define OFPPS_STP_LISTEN (0 << 8) #define OFPPS_STP_LEARN (1 << 8) #define OFPPS_STP_FORWARD (2 << 8) #define OFPPS_STP_BLOCK (3 << 8) #define OFPPS_STP_MASK (3 << 8) static const struct tok ofpps_bm[] = { { OFPPS_LINK_DOWN, "LINK_DOWN" }, { 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 0xff00 #define OFPP_IN_PORT 0xfff8 #define OFPP_TABLE 0xfff9 #define OFPP_NORMAL 0xfffa #define OFPP_FLOOD 0xfffb #define OFPP_ALL 0xfffc #define OFPP_CONTROLLER 0xfffd #define OFPP_LOCAL 0xfffe #define OFPP_NONE 0xffff 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 (1 << 0) #define OFPPF_10MB_FD (1 << 1) #define OFPPF_100MB_HD (1 << 2) #define OFPPF_100MB_FD (1 << 3) #define OFPPF_1GB_HD (1 << 4) #define OFPPF_1GB_FD (1 << 5) #define OFPPF_10GB_FD (1 << 6) #define OFPPF_COPPER (1 << 7) #define OFPPF_FIBER (1 << 8) #define OFPPF_AUTONEG (1 << 9) #define OFPPF_PAUSE (1 << 10) #define OFPPF_PAUSE_ASYM (1 << 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 (1 << 0) #define OFPFW_DL_VLAN (1 << 1) #define OFPFW_DL_SRC (1 << 2) #define OFPFW_DL_DST (1 << 3) #define OFPFW_DL_TYPE (1 << 4) #define OFPFW_NW_PROTO (1 << 5) #define OFPFW_TP_SRC (1 << 6) #define OFPFW_TP_DST (1 << 7) #define OFPFW_NW_SRC_SHIFT 8 #define OFPFW_NW_SRC_BITS 6 #define OFPFW_NW_SRC_MASK (((1 << 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 (((1 << OFPFW_NW_DST_BITS) - 1) << OFPFW_NW_DST_SHIFT) #define OFPFW_DL_VLAN_PCP (1 << 20) #define OFPFW_NW_TOS (1 << 21) #define OFPFW_ALL ((1 << 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 0x0000 #define OFPAT_SET_VLAN_VID 0x0001 #define OFPAT_SET_VLAN_PCP 0x0002 #define OFPAT_STRIP_VLAN 0x0003 #define OFPAT_SET_DL_SRC 0x0004 #define OFPAT_SET_DL_DST 0x0005 #define OFPAT_SET_NW_SRC 0x0006 #define OFPAT_SET_NW_DST 0x0007 #define OFPAT_SET_NW_TOS 0x0008 #define OFPAT_SET_TP_SRC 0x0009 #define OFPAT_SET_TP_DST 0x000a #define OFPAT_ENQUEUE 0x000b #define OFPAT_VENDOR 0xffff 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[] = { { 1 << OFPAT_OUTPUT, "OUTPUT" }, { 1 << OFPAT_SET_VLAN_VID, "SET_VLAN_VID" }, { 1 << OFPAT_SET_VLAN_PCP, "SET_VLAN_PCP" }, { 1 << OFPAT_STRIP_VLAN, "STRIP_VLAN" }, { 1 << OFPAT_SET_DL_SRC, "SET_DL_SRC" }, { 1 << OFPAT_SET_DL_DST, "SET_DL_DST" }, { 1 << OFPAT_SET_NW_SRC, "SET_NW_SRC" }, { 1 << OFPAT_SET_NW_DST, "SET_NW_DST" }, { 1 << OFPAT_SET_NW_TOS, "SET_NW_TOS" }, { 1 << OFPAT_SET_TP_SRC, "SET_TP_SRC" }, { 1 << OFPAT_SET_TP_DST, "SET_TP_DST" }, { 1 << OFPAT_ENQUEUE, "ENQUEUE" }, { 0, NULL } }; #define OFPAT_U (~(1 << OFPAT_OUTPUT | 1 << OFPAT_SET_VLAN_VID | \ 1 << OFPAT_SET_VLAN_PCP | 1 << OFPAT_STRIP_VLAN | \ 1 << OFPAT_SET_DL_SRC | 1 << OFPAT_SET_DL_DST | \ 1 << OFPAT_SET_NW_SRC | 1 << OFPAT_SET_NW_DST | \ 1 << OFPAT_SET_NW_TOS | 1 << OFPAT_SET_TP_SRC | \ 1 << OFPAT_SET_TP_DST | 1 << OFPAT_ENQUEUE)) #define OFPC_FLOW_STATS (1 << 0) #define OFPC_TABLE_STATS (1 << 1) #define OFPC_PORT_STATS (1 << 2) #define OFPC_STP (1 << 3) #define OFPC_RESERVED (1 << 4) #define OFPC_IP_REASM (1 << 5) #define OFPC_QUEUE_STATS (1 << 6) #define OFPC_ARP_MATCH_IP (1 << 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 0x0000 #define OFPC_FRAG_DROP 0x0001 #define OFPC_FRAG_REASM 0x0002 #define OFPC_FRAG_MASK 0x0003 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 0x0000 #define OFPFC_MODIFY 0x0001 #define OFPFC_MODIFY_STRICT 0x0002 #define OFPFC_DELETE 0x0003 #define OFPFC_DELETE_STRICT 0x0004 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 (1 << 0) #define OFPFF_CHECK_OVERLAP (1 << 1) #define OFPFF_EMERG (1 << 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 0x0000 #define OFPST_FLOW 0x0001 #define OFPST_AGGREGATE 0x0002 #define OFPST_TABLE 0x0003 #define OFPST_PORT 0x0004 #define OFPST_QUEUE 0x0005 #define OFPST_VENDOR 0xffff 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[] = { { 0xfe, "EMERG" }, { 0xff, "ALL" }, { 0, NULL } }; #define OFPQ_ALL 0xffffffff static const struct tok ofpq_str[] = { { OFPQ_ALL, "ALL" }, { 0, NULL } }; #define OFPSF_REPLY_MORE 0x0001 static const struct tok ofpsf_reply_bm[] = { { OFPSF_REPLY_MORE, "MORE" }, { 0, NULL } }; #define OFPSF_REPLY_U (~(OFPSF_REPLY_MORE)) #define OFPR_NO_MATCH 0x00 #define OFPR_ACTION 0x01 static const struct tok ofpr_str[] = { { OFPR_NO_MATCH, "NO_MATCH" }, { OFPR_ACTION, "ACTION" }, { 0, NULL } }; #define OFPRR_IDLE_TIMEOUT 0x00 #define OFPRR_HARD_TIMEOUT 0x01 #define OFPRR_DELETE 0x02 static const struct tok ofprr_str[] = { { OFPRR_IDLE_TIMEOUT, "IDLE_TIMEOUT" }, { OFPRR_HARD_TIMEOUT, "HARD_TIMEOUT" }, { OFPRR_DELETE, "DELETE" }, { 0, NULL } }; #define OFPPR_ADD 0x00 #define OFPPR_DELETE 0x01 #define OFPPR_MODIFY 0x02 static const struct tok ofppr_str[] = { { OFPPR_ADD, "ADD" }, { OFPPR_DELETE, "DELETE" }, { OFPPR_MODIFY, "MODIFY" }, { 0, NULL } }; #define OFPET_HELLO_FAILED 0x0000 #define OFPET_BAD_REQUEST 0x0001 #define OFPET_BAD_ACTION 0x0002 #define OFPET_FLOW_MOD_FAILED 0x0003 #define OFPET_PORT_MOD_FAILED 0x0004 #define OFPET_QUEUE_OP_FAILED 0x0005 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 0x0000 #define OFPHFC_EPERM 0x0001 static const struct tok ofphfc_str[] = { { OFPHFC_INCOMPATIBLE, "INCOMPATIBLE" }, { OFPHFC_EPERM, "EPERM" }, { 0, NULL } }; #define OFPBRC_BAD_VERSION 0x0000 #define OFPBRC_BAD_TYPE 0x0001 #define OFPBRC_BAD_STAT 0x0002 #define OFPBRC_BAD_VENDOR 0x0003 #define OFPBRC_BAD_SUBTYPE 0x0004 #define OFPBRC_EPERM 0x0005 #define OFPBRC_BAD_LEN 0x0006 #define OFPBRC_BUFFER_EMPTY 0x0007 #define OFPBRC_BUFFER_UNKNOWN 0x0008 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 0x0000 #define OFPBAC_BAD_LEN 0x0001 #define OFPBAC_BAD_VENDOR 0x0002 #define OFPBAC_BAD_VENDOR_TYPE 0x0003 #define OFPBAC_BAD_OUT_PORT 0x0004 #define OFPBAC_BAD_ARGUMENT 0x0005 #define OFPBAC_EPERM 0x0006 #define OFPBAC_TOO_MANY 0x0007 #define OFPBAC_BAD_QUEUE 0x0008 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 0x0000 #define OFPFMFC_OVERLAP 0x0001 #define OFPFMFC_EPERM 0x0002 #define OFPFMFC_BAD_EMERG_TIMEOUT 0x0003 #define OFPFMFC_BAD_COMMAND 0x0004 #define OFPFMFC_UNSUPPORTED 0x0005 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 0x0000 #define OFPPMFC_BAD_HW_ADDR 0x0001 static const struct tok ofppmfc_str[] = { { OFPPMFC_BAD_PORT, "BAD_PORT" }, { OFPPMFC_BAD_HW_ADDR, "BAD_HW_ADDR" }, { 0, NULL } }; #define OFPQOFC_BAD_PORT 0x0000 #define OFPQOFC_BAD_QUEUE 0x0001 #define OFPQOFC_EPERM 0x0002 static const struct tok ofpqofc_str[] = { { OFPQOFC_BAD_PORT, "BAD_PORT" }, { OFPQOFC_BAD_QUEUE, "BAD_QUEUE" }, { OFPQOFC_EPERM, "EPERM" }, { 0, NULL } }; static const struct tok empty_str[] = { { 0, NULL } }; /* lengths (fixed or minimal) of particular protocol structures */ #define OF_SWITCH_CONFIG_LEN 12 #define OF_PHY_PORT_LEN 48 #define OF_SWITCH_FEATURES_LEN 32 #define OF_PORT_STATUS_LEN 64 #define OF_PORT_MOD_LEN 32 #define OF_PACKET_IN_LEN 20 #define OF_ACTION_OUTPUT_LEN 8 #define OF_ACTION_VLAN_VID_LEN 8 #define OF_ACTION_VLAN_PCP_LEN 8 #define OF_ACTION_DL_ADDR_LEN 16 #define OF_ACTION_NW_ADDR_LEN 8 #define OF_ACTION_TP_PORT_LEN 8 #define OF_ACTION_NW_TOS_LEN 8 #define OF_ACTION_VENDOR_HEADER_LEN 8 #define OF_ACTION_HEADER_LEN 8 #define OF_PACKET_OUT_LEN 16 #define OF_MATCH_LEN 40 #define OF_FLOW_MOD_LEN 72 #define OF_FLOW_REMOVED_LEN 88 #define OF_ERROR_MSG_LEN 12 #define OF_STATS_REQUEST_LEN 12 #define OF_STATS_REPLY_LEN 12 #define OF_DESC_STATS_LEN 1056 #define OF_FLOW_STATS_REQUEST_LEN 44 #define OF_FLOW_STATS_LEN 88 #define OF_AGGREGATE_STATS_REQUEST_LEN 44 #define OF_AGGREGATE_STATS_REPLY_LEN 24 #define OF_TABLE_STATS_LEN 64 #define OF_PORT_STATS_REQUEST_LEN 8 #define OF_PORT_STATS_LEN 104 #define OF_VENDOR_HEADER_LEN 12 #define OF_QUEUE_PROP_HEADER_LEN 8 #define OF_QUEUE_PROP_MIN_RATE_LEN 16 #define OF_PACKET_QUEUE_LEN 8 #define OF_QUEUE_GET_CONFIG_REQUEST_LEN 12 #define OF_QUEUE_GET_CONFIG_REPLY_LEN 16 #define OF_ACTION_ENQUEUE_LEN 16 #define OF_QUEUE_STATS_REQUEST_LEN 8 #define OF_QUEUE_STATS_LEN 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 0xffff +/* 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) { +vlan_str(const uint16_t vid) +{ static char buf[sizeof("65535 (bogus)")]; const char *fmt; if (vid == OFP_VLAN_NONE) return "NONE"; fmt = (vid > 0 && vid < 0x0fff) ? "%u" : "%u (bogus)"; snprintf(buf, sizeof(buf), fmt, vid); return buf; } static const char * -pcp_str(const uint8_t pcp) { +pcp_str(const uint8_t pcp) +{ static char buf[sizeof("255 (bogus)")]; snprintf(buf, sizeof(buf), pcp <= 7 ? "%u" : "%u (bogus)", pcp); return buf; } static void of10_bitmap_print(netdissect_options *ndo, - const struct tok *t, const uint32_t v, const uint32_t u) { + const struct tok *t, const uint32_t v, const uint32_t u) +{ const char *sep = " ("; if (v == 0) return; /* assigned bits */ for (; t->s != NULL; t++) if (v & t->v) { ND_PRINT((ndo, "%s%s", sep, t->s)); sep = ", "; } /* unassigned bits? */ ND_PRINT((ndo, v & u ? ") (bogus)" : ")")); } static const u_char * of10_data_print(netdissect_options *ndo, - const u_char *cp, const u_char *ep, const u_int len) { + const u_char *cp, const u_char *ep, const u_int len) +{ if (len == 0) return cp; /* data */ ND_PRINT((ndo, "\n\t data (%u octets)", len)); ND_TCHECK2(*cp, len); if (ndo->ndo_vflag >= 2) hex_and_ascii_print(ndo, "\n\t ", cp, len); return cp + len; trunc: ND_PRINT((ndo, "%s", tstr)); return ep; } +static const u_char * +of10_bsn_message_print(netdissect_options *ndo, + const u_char *cp, const u_char *ep, const u_int len) +{ + const u_char *cp0 = cp; + uint32_t subtype; + + if (len < 4) + goto corrupt; + /* subtype */ + ND_TCHECK2(*cp, 4); + subtype = EXTRACT_32BITS(cp); + cp += 4; + ND_PRINT((ndo, "\n\t 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 != 12) + goto corrupt; + /* index */ + ND_TCHECK2(*cp, 1); + ND_PRINT((ndo, ", index %u", *cp)); + cp += 1; + /* pad */ + ND_TCHECK2(*cp, 7); + cp += 7; + 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 != 12) + goto corrupt; + /* index */ + ND_TCHECK2(*cp, 1); + ND_PRINT((ndo, ", index %u", *cp)); + cp += 1; + /* pad */ + ND_TCHECK2(*cp, 3); + cp += 3; + /* mask */ + ND_TCHECK2(*cp, 4); + ND_PRINT((ndo, ", mask %s", ipaddr_string(ndo, cp))); + cp += 4; + 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 != 8) + goto corrupt; + /* report_mirror_ports */ + ND_TCHECK2(*cp, 1); + ND_PRINT((ndo, ", report_mirror_ports %s", tok2str(bsn_onoff_str, "bogus (%u)", *cp))); + cp += 1; + /* pad */ + ND_TCHECK2(*cp, 3); + cp += 3; + 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 != 4) + goto corrupt; + 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 != 8) + goto corrupt; + /* vport_no */ + ND_TCHECK2(*cp, 4); + ND_PRINT((ndo, ", vport_no %u", EXTRACT_32BITS(cp))); + cp += 4; + 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 < 8) + goto corrupt; + /* service */ + ND_TCHECK2(*cp, 4); + ND_PRINT((ndo, ", service %u", EXTRACT_32BITS(cp))); + cp += 4; + /* data */ + ND_PRINT((ndo, ", data '")); + if (fn_printn(ndo, cp, len - 8, ep)) { + ND_PRINT((ndo, "'")); + goto trunc; + } + ND_PRINT((ndo, "'")); + cp += len - 8; + 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((ndo, ", data '")); + if (fn_printn(ndo, cp, len - 4, ep)) { + ND_PRINT((ndo, "'")); + goto trunc; + } + ND_PRINT((ndo, "'")); + cp += len - 4; + 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 != 8) + goto corrupt; + /* status */ + ND_TCHECK2(*cp, 4); + ND_PRINT((ndo, ", status 0x%08x", EXTRACT_32BITS(cp))); + cp += 4; + break; + default: + ND_TCHECK2(*cp, len - 4); + cp += len - 4; + } + return cp; + +corrupt: /* skip the undersized data */ + ND_PRINT((ndo, "%s", cstr)); + ND_TCHECK2(*cp0, len); + return cp0 + len; +trunc: + ND_PRINT((ndo, "%s", tstr)); + return ep; +} + +static const u_char * +of10_bsn_actions_print(netdissect_options *ndo, + const u_char *cp, const u_char *ep, const u_int len) +{ + const u_char *cp0 = cp; + uint32_t subtype, vlan_tag; + + if (len < 4) + goto corrupt; + /* subtype */ + ND_TCHECK2(*cp, 4); + subtype = EXTRACT_32BITS(cp); + cp += 4; + ND_PRINT((ndo, "\n\t 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 != 16) + goto corrupt; + /* dest_port */ + ND_TCHECK2(*cp, 4); + ND_PRINT((ndo, ", dest_port %u", EXTRACT_32BITS(cp))); + cp += 4; + /* vlan_tag */ + ND_TCHECK2(*cp, 4); + vlan_tag = EXTRACT_32BITS(cp); + cp += 4; + switch (vlan_tag >> 16) { + case 0: + ND_PRINT((ndo, ", vlan_tag none")); + break; + case ETHERTYPE_8021Q: + ND_PRINT((ndo, ", vlan_tag 802.1Q (%s)", ieee8021q_tci_string(vlan_tag & 0xffff))); + break; + default: + ND_PRINT((ndo, ", vlan_tag unknown (0x%04x)", vlan_tag >> 16)); + } + /* copy_stage */ + ND_TCHECK2(*cp, 1); + ND_PRINT((ndo, ", copy_stage %s", tok2str(bsn_mirror_copy_stage_str, "unknown (%u)", *cp))); + cp += 1; + /* pad */ + ND_TCHECK2(*cp, 3); + cp += 3; + break; + default: + ND_TCHECK2(*cp, len - 4); + cp += len - 4; + } + + return cp; + +corrupt: + ND_PRINT((ndo, "%s", cstr)); + ND_TCHECK2(*cp0, len); + return cp0 + len; +trunc: + ND_PRINT((ndo, "%s", tstr)); + return ep; +} + +static const u_char * +of10_vendor_action_print(netdissect_options *ndo, + const u_char *cp, const u_char *ep, const u_int len) +{ + uint32_t vendor; + const u_char *(*decoder)(netdissect_options *, const u_char *, const u_char *, const u_int); + + if (len < 4) + goto corrupt; + /* vendor */ + ND_TCHECK2(*cp, 4); + vendor = EXTRACT_32BITS(cp); + cp += 4; + ND_PRINT((ndo, ", vendor 0x%08x (%s)", vendor, of_vendor_name(vendor))); + /* data */ + decoder = + vendor == OUI_BSN ? of10_bsn_actions_print : + of10_data_print; + return decoder(ndo, cp, ep, len - 4); + +corrupt: /* skip the undersized data */ + ND_PRINT((ndo, "%s", cstr)); + ND_TCHECK2(*cp, len); + return cp + len; +trunc: + ND_PRINT((ndo, "%s", tstr)); + return ep; +} + +static const u_char * +of10_vendor_message_print(netdissect_options *ndo, + const u_char *cp, const u_char *ep, const u_int len) +{ + uint32_t vendor; + const u_char *(*decoder)(netdissect_options *, const u_char *, const u_char *, u_int); + + if (len < 4) + goto corrupt; + /* vendor */ + ND_TCHECK2(*cp, 4); + vendor = EXTRACT_32BITS(cp); + cp += 4; + ND_PRINT((ndo, ", vendor 0x%08x (%s)", vendor, of_vendor_name(vendor))); + /* data */ + decoder = + vendor == OUI_BSN ? of10_bsn_message_print : + of10_data_print; + return decoder(ndo, cp, ep, len - 4); + +corrupt: /* skip the undersized data */ + ND_PRINT((ndo, "%s", cstr)); + ND_TCHECK2(*cp, len); + return cp + len; +trunc: + ND_PRINT((ndo, "%s", tstr)); + return ep; +} + /* Vendor ID is mandatory, data is optional. */ static const u_char * of10_vendor_data_print(netdissect_options *ndo, - const u_char *cp, const u_char *ep, const u_int len) { + const u_char *cp, const u_char *ep, const u_int len) +{ + uint32_t vendor; + if (len < 4) goto corrupt; /* vendor */ ND_TCHECK2(*cp, 4); - ND_PRINT((ndo, ", vendor 0x%08x", EXTRACT_32BITS(cp))); + vendor = EXTRACT_32BITS(cp); cp += 4; + ND_PRINT((ndo, ", vendor 0x%08x (%s)", vendor, of_vendor_name(vendor))); /* data */ return of10_data_print(ndo, cp, ep, len - 4); corrupt: /* skip the undersized data */ ND_PRINT((ndo, "%s", cstr)); ND_TCHECK2(*cp, len); return cp + len; trunc: ND_PRINT((ndo, "%s", tstr)); return ep; } static const u_char * of10_packet_data_print(netdissect_options *ndo, - const u_char *cp, const u_char *ep, const u_int len) { + const u_char *cp, const u_char *ep, const u_int len) +{ if (len == 0) return cp; /* data */ ND_PRINT((ndo, "\n\t data (%u octets)", len)); if (ndo->ndo_vflag < 3) return cp + len; ND_TCHECK2(*cp, len); ndo->ndo_vflag -= 3; ND_PRINT((ndo, ", frame decoding below\n")); ether_print(ndo, cp, len, ndo->ndo_snapend - cp, NULL, NULL); ndo->ndo_vflag += 3; return cp + len; trunc: ND_PRINT((ndo, "%s", tstr)); return ep; } /* [OF10] Section 5.2.1 */ static const u_char * of10_phy_ports_print(netdissect_options *ndo, - const u_char *cp, const u_char *ep, u_int len) { + const u_char *cp, const u_char *ep, u_int len) +{ const u_char *cp0 = cp; const u_int len0 = len; while (len) { if (len < OF_PHY_PORT_LEN) goto corrupt; /* port_no */ ND_TCHECK2(*cp, 2); ND_PRINT((ndo, "\n\t port_no %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp)))); cp += 2; /* hw_addr */ ND_TCHECK2(*cp, ETHER_ADDR_LEN); ND_PRINT((ndo, ", hw_addr %s", etheraddr_string(ndo, cp))); cp += ETHER_ADDR_LEN; /* name */ ND_TCHECK2(*cp, OFP_MAX_PORT_NAME_LEN); ND_PRINT((ndo, ", name '")); fn_print(ndo, cp, cp + OFP_MAX_PORT_NAME_LEN); ND_PRINT((ndo, "'")); cp += OFP_MAX_PORT_NAME_LEN; if (ndo->ndo_vflag < 2) { ND_TCHECK2(*cp, 24); cp += 24; goto next_port; } /* config */ ND_TCHECK2(*cp, 4); ND_PRINT((ndo, "\n\t config 0x%08x", EXTRACT_32BITS(cp))); of10_bitmap_print(ndo, ofppc_bm, EXTRACT_32BITS(cp), OFPPC_U); cp += 4; /* state */ ND_TCHECK2(*cp, 4); ND_PRINT((ndo, "\n\t state 0x%08x", EXTRACT_32BITS(cp))); of10_bitmap_print(ndo, ofpps_bm, EXTRACT_32BITS(cp), OFPPS_U); cp += 4; /* curr */ ND_TCHECK2(*cp, 4); ND_PRINT((ndo, "\n\t curr 0x%08x", EXTRACT_32BITS(cp))); of10_bitmap_print(ndo, ofppf_bm, EXTRACT_32BITS(cp), OFPPF_U); cp += 4; /* advertised */ ND_TCHECK2(*cp, 4); ND_PRINT((ndo, "\n\t advertised 0x%08x", EXTRACT_32BITS(cp))); of10_bitmap_print(ndo, ofppf_bm, EXTRACT_32BITS(cp), OFPPF_U); cp += 4; /* supported */ ND_TCHECK2(*cp, 4); ND_PRINT((ndo, "\n\t supported 0x%08x", EXTRACT_32BITS(cp))); of10_bitmap_print(ndo, ofppf_bm, EXTRACT_32BITS(cp), OFPPF_U); cp += 4; /* peer */ ND_TCHECK2(*cp, 4); ND_PRINT((ndo, "\n\t peer 0x%08x", EXTRACT_32BITS(cp))); of10_bitmap_print(ndo, ofppf_bm, EXTRACT_32BITS(cp), OFPPF_U); cp += 4; next_port: len -= OF_PHY_PORT_LEN; } /* while */ return cp; corrupt: /* skip the undersized trailing data */ ND_PRINT((ndo, "%s", cstr)); ND_TCHECK2(*cp0, len0); return cp0 + len0; trunc: ND_PRINT((ndo, "%s", tstr)); return ep; } /* [OF10] Section 5.2.2 */ static const u_char * of10_queue_props_print(netdissect_options *ndo, - const u_char *cp, const u_char *ep, u_int len) { + const u_char *cp, const u_char *ep, u_int len) +{ const u_char *cp0 = cp; const u_int len0 = len; uint16_t property, plen, rate; while (len) { u_char plen_bogus = 0, skip = 0; if (len < OF_QUEUE_PROP_HEADER_LEN) goto corrupt; /* property */ ND_TCHECK2(*cp, 2); property = EXTRACT_16BITS(cp); cp += 2; ND_PRINT((ndo, "\n\t property %s", tok2str(ofpqt_str, "invalid (0x%04x)", property))); /* len */ ND_TCHECK2(*cp, 2); plen = EXTRACT_16BITS(cp); cp += 2; ND_PRINT((ndo, ", len %u", plen)); if (plen < OF_QUEUE_PROP_HEADER_LEN || plen > len) goto corrupt; /* pad */ ND_TCHECK2(*cp, 4); cp += 4; /* property-specific constraints and decoding */ switch (property) { case OFPQT_NONE: plen_bogus = plen != OF_QUEUE_PROP_HEADER_LEN; break; case OFPQT_MIN_RATE: plen_bogus = plen != OF_QUEUE_PROP_MIN_RATE_LEN; break; default: skip = 1; } if (plen_bogus) { ND_PRINT((ndo, " (bogus)")); skip = 1; } if (skip) { ND_TCHECK2(*cp, plen - 4); cp += plen - 4; goto next_property; } if (property == OFPQT_MIN_RATE) { /* the only case of property decoding */ /* rate */ ND_TCHECK2(*cp, 2); rate = EXTRACT_16BITS(cp); cp += 2; if (rate > 1000) ND_PRINT((ndo, ", rate disabled")); else ND_PRINT((ndo, ", rate %u.%u%%", rate / 10, rate % 10)); /* pad */ ND_TCHECK2(*cp, 6); cp += 6; } next_property: len -= plen; } /* while */ return cp; corrupt: /* skip the rest of queue properties */ ND_PRINT((ndo, "%s", cstr)); ND_TCHECK2(*cp0, len0); return cp0 + len0; trunc: ND_PRINT((ndo, "%s", tstr)); return ep; } /* ibid */ static const u_char * of10_queues_print(netdissect_options *ndo, - const u_char *cp, const u_char *ep, u_int len) { + const u_char *cp, const u_char *ep, u_int len) +{ const u_char *cp0 = cp; const u_int len0 = len; uint16_t desclen; while (len) { if (len < OF_PACKET_QUEUE_LEN) goto corrupt; /* queue_id */ ND_TCHECK2(*cp, 4); ND_PRINT((ndo, "\n\t queue_id %u", EXTRACT_32BITS(cp))); cp += 4; /* len */ ND_TCHECK2(*cp, 2); desclen = EXTRACT_16BITS(cp); cp += 2; ND_PRINT((ndo, ", len %u", desclen)); if (desclen < OF_PACKET_QUEUE_LEN || desclen > len) goto corrupt; /* pad */ ND_TCHECK2(*cp, 2); cp += 2; /* properties */ if (ndo->ndo_vflag < 2) { ND_TCHECK2(*cp, desclen - OF_PACKET_QUEUE_LEN); cp += desclen - OF_PACKET_QUEUE_LEN; goto next_queue; } if (ep == (cp = of10_queue_props_print(ndo, cp, ep, desclen - OF_PACKET_QUEUE_LEN))) return ep; /* end of snapshot */ next_queue: len -= desclen; } /* while */ return cp; corrupt: /* skip the rest of queues */ ND_PRINT((ndo, "%s", cstr)); ND_TCHECK2(*cp0, len0); return cp0 + len0; trunc: ND_PRINT((ndo, "%s", tstr)); return ep; } /* [OF10] Section 5.2.3 */ static const u_char * of10_match_print(netdissect_options *ndo, - const char *pfx, const u_char *cp, const u_char *ep) { + const char *pfx, const u_char *cp, const u_char *ep) +{ uint32_t wildcards; uint16_t dl_type; uint8_t nw_proto; u_char nw_bits; const char *field_name; /* wildcards */ ND_TCHECK2(*cp, 4); wildcards = EXTRACT_32BITS(cp); if (wildcards & OFPFW_U) ND_PRINT((ndo, "%swildcards 0x%08x (bogus)", pfx, wildcards)); cp += 4; /* in_port */ ND_TCHECK2(*cp, 2); if (! (wildcards & OFPFW_IN_PORT)) ND_PRINT((ndo, "%smatch in_port %s", pfx, tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp)))); cp += 2; /* dl_src */ ND_TCHECK2(*cp, ETHER_ADDR_LEN); if (! (wildcards & OFPFW_DL_SRC)) ND_PRINT((ndo, "%smatch dl_src %s", pfx, etheraddr_string(ndo, cp))); cp += ETHER_ADDR_LEN; /* dl_dst */ ND_TCHECK2(*cp, ETHER_ADDR_LEN); if (! (wildcards & OFPFW_DL_DST)) ND_PRINT((ndo, "%smatch dl_dst %s", pfx, etheraddr_string(ndo, cp))); cp += ETHER_ADDR_LEN; /* dl_vlan */ ND_TCHECK2(*cp, 2); if (! (wildcards & OFPFW_DL_VLAN)) ND_PRINT((ndo, "%smatch dl_vlan %s", pfx, vlan_str(EXTRACT_16BITS(cp)))); cp += 2; /* dl_vlan_pcp */ ND_TCHECK2(*cp, 1); if (! (wildcards & OFPFW_DL_VLAN_PCP)) ND_PRINT((ndo, "%smatch dl_vlan_pcp %s", pfx, pcp_str(*cp))); cp += 1; /* pad1 */ ND_TCHECK2(*cp, 1); cp += 1; /* dl_type */ ND_TCHECK2(*cp, 2); dl_type = EXTRACT_16BITS(cp); cp += 2; if (! (wildcards & OFPFW_DL_TYPE)) ND_PRINT((ndo, "%smatch dl_type 0x%04x", pfx, dl_type)); /* nw_tos */ ND_TCHECK2(*cp, 1); if (! (wildcards & OFPFW_NW_TOS)) ND_PRINT((ndo, "%smatch nw_tos 0x%02x", pfx, *cp)); cp += 1; /* nw_proto */ ND_TCHECK2(*cp, 1); nw_proto = *cp; cp += 1; if (! (wildcards & OFPFW_NW_PROTO)) { field_name = ! (wildcards & OFPFW_DL_TYPE) && dl_type == ETHERTYPE_ARP ? "arp_opcode" : "nw_proto"; ND_PRINT((ndo, "%smatch %s %u", pfx, field_name, nw_proto)); } /* pad2 */ ND_TCHECK2(*cp, 2); cp += 2; /* nw_src */ ND_TCHECK2(*cp, 4); nw_bits = (wildcards & OFPFW_NW_SRC_MASK) >> OFPFW_NW_SRC_SHIFT; if (nw_bits < 32) ND_PRINT((ndo, "%smatch nw_src %s/%u", pfx, ipaddr_string(ndo, cp), 32 - nw_bits)); cp += 4; /* nw_dst */ ND_TCHECK2(*cp, 4); nw_bits = (wildcards & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT; if (nw_bits < 32) ND_PRINT((ndo, "%smatch nw_dst %s/%u", pfx, ipaddr_string(ndo, cp), 32 - nw_bits)); cp += 4; /* tp_src */ ND_TCHECK2(*cp, 2); 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((ndo, "%smatch %s %u", pfx, field_name, EXTRACT_16BITS(cp))); } cp += 2; /* tp_dst */ ND_TCHECK2(*cp, 2); 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((ndo, "%smatch %s %u", pfx, field_name, EXTRACT_16BITS(cp))); } return cp + 2; trunc: ND_PRINT((ndo, "%s", tstr)); return ep; } /* [OF10] Section 5.2.4 */ static const u_char * of10_actions_print(netdissect_options *ndo, const char *pfx, const u_char *cp, const u_char *ep, - u_int len) { + u_int len) +{ const u_char *cp0 = cp; const u_int len0 = len; uint16_t type, alen, output_port; while (len) { u_char alen_bogus = 0, skip = 0; if (len < OF_ACTION_HEADER_LEN) goto corrupt; /* type */ ND_TCHECK2(*cp, 2); type = EXTRACT_16BITS(cp); cp += 2; ND_PRINT((ndo, "%saction type %s", pfx, tok2str(ofpat_str, "invalid (0x%04x)", type))); /* length */ ND_TCHECK2(*cp, 2); alen = EXTRACT_16BITS(cp); cp += 2; ND_PRINT((ndo, ", len %u", alen)); /* On action size underrun/overrun skip the rest of the action list. */ if (alen < OF_ACTION_HEADER_LEN || alen > len) goto corrupt; /* On action size inappropriate for the given type or invalid type just skip * the current action, as the basic length constraint has been met. */ 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((ndo, " (bogus)")); skip = 1; } if (skip) { ND_TCHECK2(*cp, alen - 4); cp += alen - 4; goto next_action; } /* OK to decode the rest of the action structure */ switch (type) { case OFPAT_OUTPUT: /* port */ ND_TCHECK2(*cp, 2); output_port = EXTRACT_16BITS(cp); cp += 2; ND_PRINT((ndo, ", port %s", tok2str(ofpp_str, "%u", output_port))); /* max_len */ ND_TCHECK2(*cp, 2); if (output_port == OFPP_CONTROLLER) ND_PRINT((ndo, ", max_len %u", EXTRACT_16BITS(cp))); cp += 2; break; case OFPAT_SET_VLAN_VID: /* vlan_vid */ ND_TCHECK2(*cp, 2); ND_PRINT((ndo, ", vlan_vid %s", vlan_str(EXTRACT_16BITS(cp)))); cp += 2; /* pad */ ND_TCHECK2(*cp, 2); cp += 2; break; case OFPAT_SET_VLAN_PCP: /* vlan_pcp */ ND_TCHECK2(*cp, 1); ND_PRINT((ndo, ", vlan_pcp %s", pcp_str(*cp))); cp += 1; /* pad */ ND_TCHECK2(*cp, 3); cp += 3; break; case OFPAT_SET_DL_SRC: case OFPAT_SET_DL_DST: /* dl_addr */ ND_TCHECK2(*cp, ETHER_ADDR_LEN); ND_PRINT((ndo, ", dl_addr %s", etheraddr_string(ndo, cp))); cp += ETHER_ADDR_LEN; /* pad */ ND_TCHECK2(*cp, 6); cp += 6; break; case OFPAT_SET_NW_SRC: case OFPAT_SET_NW_DST: /* nw_addr */ ND_TCHECK2(*cp, 4); ND_PRINT((ndo, ", nw_addr %s", ipaddr_string(ndo, cp))); cp += 4; break; case OFPAT_SET_NW_TOS: /* nw_tos */ ND_TCHECK2(*cp, 1); ND_PRINT((ndo, ", nw_tos 0x%02x", *cp)); cp += 1; /* pad */ ND_TCHECK2(*cp, 3); cp += 3; break; case OFPAT_SET_TP_SRC: case OFPAT_SET_TP_DST: /* nw_tos */ ND_TCHECK2(*cp, 2); ND_PRINT((ndo, ", tp_port %u", EXTRACT_16BITS(cp))); cp += 2; /* pad */ ND_TCHECK2(*cp, 2); cp += 2; break; case OFPAT_ENQUEUE: /* port */ ND_TCHECK2(*cp, 2); ND_PRINT((ndo, ", port %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp)))); cp += 2; /* pad */ ND_TCHECK2(*cp, 6); cp += 6; /* queue_id */ ND_TCHECK2(*cp, 4); ND_PRINT((ndo, ", queue_id %s", tok2str(ofpq_str, "%u", EXTRACT_32BITS(cp)))); cp += 4; break; case OFPAT_VENDOR: - if (ep == (cp = of10_vendor_data_print(ndo, cp, ep, alen - 4))) + if (ep == (cp = of10_vendor_action_print(ndo, cp, ep, alen - 4))) return ep; /* end of snapshot */ break; case OFPAT_STRIP_VLAN: /* pad */ ND_TCHECK2(*cp, 4); cp += 4; break; } /* switch */ next_action: len -= alen; } /* while */ return cp; corrupt: /* skip the rest of actions */ ND_PRINT((ndo, "%s", cstr)); ND_TCHECK2(*cp0, len0); return cp0 + len0; trunc: ND_PRINT((ndo, "%s", tstr)); return ep; } /* [OF10] Section 5.3.1 */ static const u_char * of10_features_reply_print(netdissect_options *ndo, - const u_char *cp, const u_char *ep, const u_int len) { + const u_char *cp, const u_char *ep, const u_int len) +{ /* datapath_id */ ND_TCHECK2(*cp, 8); ND_PRINT((ndo, "\n\t dpid 0x%016" PRIx64, EXTRACT_64BITS(cp))); cp += 8; /* n_buffers */ ND_TCHECK2(*cp, 4); ND_PRINT((ndo, ", n_buffers %u", EXTRACT_32BITS(cp))); cp += 4; /* n_tables */ ND_TCHECK2(*cp, 1); ND_PRINT((ndo, ", n_tables %u", *cp)); cp += 1; /* pad */ ND_TCHECK2(*cp, 3); cp += 3; /* capabilities */ ND_TCHECK2(*cp, 4); ND_PRINT((ndo, "\n\t capabilities 0x%08x", EXTRACT_32BITS(cp))); of10_bitmap_print(ndo, ofp_capabilities_bm, EXTRACT_32BITS(cp), OFPCAP_U); cp += 4; /* actions */ ND_TCHECK2(*cp, 4); ND_PRINT((ndo, "\n\t actions 0x%08x", EXTRACT_32BITS(cp))); of10_bitmap_print(ndo, ofpat_bm, EXTRACT_32BITS(cp), OFPAT_U); cp += 4; /* ports */ return of10_phy_ports_print(ndo, cp, ep, len - OF_SWITCH_FEATURES_LEN); trunc: ND_PRINT((ndo, "%s", tstr)); return ep; } /* [OF10] Section 5.3.3 */ static const u_char * of10_flow_mod_print(netdissect_options *ndo, - const u_char *cp, const u_char *ep, const u_int len) { + const u_char *cp, const u_char *ep, const u_int len) +{ uint16_t command; /* match */ if (ep == (cp = of10_match_print(ndo, "\n\t ", cp, ep))) return ep; /* end of snapshot */ /* cookie */ ND_TCHECK2(*cp, 8); ND_PRINT((ndo, "\n\t cookie 0x%016" PRIx64, EXTRACT_64BITS(cp))); cp += 8; /* command */ ND_TCHECK2(*cp, 2); command = EXTRACT_16BITS(cp); ND_PRINT((ndo, ", command %s", tok2str(ofpfc_str, "invalid (0x%04x)", command))); cp += 2; /* idle_timeout */ ND_TCHECK2(*cp, 2); if (EXTRACT_16BITS(cp)) ND_PRINT((ndo, ", idle_timeout %u", EXTRACT_16BITS(cp))); cp += 2; /* hard_timeout */ ND_TCHECK2(*cp, 2); if (EXTRACT_16BITS(cp)) ND_PRINT((ndo, ", hard_timeout %u", EXTRACT_16BITS(cp))); cp += 2; /* priority */ ND_TCHECK2(*cp, 2); if (EXTRACT_16BITS(cp)) ND_PRINT((ndo, ", priority %u", EXTRACT_16BITS(cp))); cp += 2; /* buffer_id */ ND_TCHECK2(*cp, 4); if (command == OFPFC_ADD || command == OFPFC_MODIFY || command == OFPFC_MODIFY_STRICT) ND_PRINT((ndo, ", buffer_id %s", tok2str(bufferid_str, "0x%08x", EXTRACT_32BITS(cp)))); cp += 4; /* out_port */ ND_TCHECK2(*cp, 2); if (command == OFPFC_DELETE || command == OFPFC_DELETE_STRICT) ND_PRINT((ndo, ", out_port %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp)))); cp += 2; /* flags */ ND_TCHECK2(*cp, 2); ND_PRINT((ndo, ", flags 0x%04x", EXTRACT_16BITS(cp))); of10_bitmap_print(ndo, ofpff_bm, EXTRACT_16BITS(cp), OFPFF_U); cp += 2; /* actions */ return of10_actions_print(ndo, "\n\t ", cp, ep, len - OF_FLOW_MOD_LEN); trunc: ND_PRINT((ndo, "%s", tstr)); return ep; } /* ibid */ static const u_char * of10_port_mod_print(netdissect_options *ndo, - const u_char *cp, const u_char *ep) { + const u_char *cp, const u_char *ep) +{ /* port_no */ ND_TCHECK2(*cp, 2); ND_PRINT((ndo, "\n\t port_no %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp)))); cp += 2; /* hw_addr */ ND_TCHECK2(*cp, ETHER_ADDR_LEN); ND_PRINT((ndo, ", hw_addr %s", etheraddr_string(ndo, cp))); cp += ETHER_ADDR_LEN; /* config */ ND_TCHECK2(*cp, 4); ND_PRINT((ndo, "\n\t config 0x%08x", EXTRACT_32BITS(cp))); of10_bitmap_print(ndo, ofppc_bm, EXTRACT_32BITS(cp), OFPPC_U); cp += 4; /* mask */ ND_TCHECK2(*cp, 4); ND_PRINT((ndo, "\n\t mask 0x%08x", EXTRACT_32BITS(cp))); of10_bitmap_print(ndo, ofppc_bm, EXTRACT_32BITS(cp), OFPPC_U); cp += 4; /* advertise */ ND_TCHECK2(*cp, 4); ND_PRINT((ndo, "\n\t advertise 0x%08x", EXTRACT_32BITS(cp))); of10_bitmap_print(ndo, ofppf_bm, EXTRACT_32BITS(cp), OFPPF_U); cp += 4; /* pad */ ND_TCHECK2(*cp, 4); return cp + 4; trunc: ND_PRINT((ndo, "%s", tstr)); return ep; } /* [OF10] Section 5.3.5 */ static const u_char * of10_stats_request_print(netdissect_options *ndo, - const u_char *cp, const u_char *ep, u_int len) { + const u_char *cp, const u_char *ep, u_int len) +{ const u_char *cp0 = cp; const u_int len0 = len; uint16_t type; /* type */ ND_TCHECK2(*cp, 2); type = EXTRACT_16BITS(cp); cp += 2; ND_PRINT((ndo, "\n\t type %s", tok2str(ofpst_str, "invalid (0x%04x)", type))); /* flags */ ND_TCHECK2(*cp, 2); ND_PRINT((ndo, ", flags 0x%04x", EXTRACT_16BITS(cp))); if (EXTRACT_16BITS(cp)) ND_PRINT((ndo, " (bogus)")); cp += 2; /* type-specific body of one of fixed lengths */ len -= OF_STATS_REQUEST_LEN; switch(type) { case OFPST_DESC: case OFPST_TABLE: if (len) goto corrupt; return cp; case OFPST_FLOW: case OFPST_AGGREGATE: if (len != OF_FLOW_STATS_REQUEST_LEN) goto corrupt; /* match */ if (ep == (cp = of10_match_print(ndo, "\n\t ", cp, ep))) return ep; /* end of snapshot */ /* table_id */ ND_TCHECK2(*cp, 1); ND_PRINT((ndo, "\n\t table_id %s", tok2str(tableid_str, "%u", *cp))); cp += 1; /* pad */ ND_TCHECK2(*cp, 1); cp += 1; /* out_port */ ND_TCHECK2(*cp, 2); ND_PRINT((ndo, ", out_port %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp)))); return cp + 2; case OFPST_PORT: if (len != OF_PORT_STATS_REQUEST_LEN) goto corrupt; /* port_no */ ND_TCHECK2(*cp, 2); ND_PRINT((ndo, "\n\t port_no %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp)))); cp += 2; /* pad */ ND_TCHECK2(*cp, 6); return cp + 6; case OFPST_QUEUE: if (len != OF_QUEUE_STATS_REQUEST_LEN) goto corrupt; /* port_no */ ND_TCHECK2(*cp, 2); ND_PRINT((ndo, "\n\t port_no %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp)))); cp += 2; /* pad */ ND_TCHECK2(*cp, 2); cp += 2; /* queue_id */ ND_TCHECK2(*cp, 4); ND_PRINT((ndo, ", queue_id %s", tok2str(ofpq_str, "%u", EXTRACT_32BITS(cp)))); return cp + 4; case OFPST_VENDOR: return of10_vendor_data_print(ndo, cp, ep, len); } return cp; corrupt: /* skip the message body */ ND_PRINT((ndo, "%s", cstr)); ND_TCHECK2(*cp0, len0); return cp0 + len0; trunc: ND_PRINT((ndo, "%s", tstr)); return ep; } /* ibid */ static const u_char * of10_desc_stats_reply_print(netdissect_options *ndo, - const u_char *cp, const u_char *ep, const u_int len) { + const u_char *cp, const u_char *ep, const u_int len) +{ if (len != OF_DESC_STATS_LEN) goto corrupt; /* mfr_desc */ ND_TCHECK2(*cp, DESC_STR_LEN); ND_PRINT((ndo, "\n\t mfr_desc '")); fn_print(ndo, cp, cp + DESC_STR_LEN); ND_PRINT((ndo, "'")); cp += DESC_STR_LEN; /* hw_desc */ ND_TCHECK2(*cp, DESC_STR_LEN); ND_PRINT((ndo, "\n\t hw_desc '")); fn_print(ndo, cp, cp + DESC_STR_LEN); ND_PRINT((ndo, "'")); cp += DESC_STR_LEN; /* sw_desc */ ND_TCHECK2(*cp, DESC_STR_LEN); ND_PRINT((ndo, "\n\t sw_desc '")); fn_print(ndo, cp, cp + DESC_STR_LEN); ND_PRINT((ndo, "'")); cp += DESC_STR_LEN; /* serial_num */ ND_TCHECK2(*cp, SERIAL_NUM_LEN); ND_PRINT((ndo, "\n\t serial_num '")); fn_print(ndo, cp, cp + SERIAL_NUM_LEN); ND_PRINT((ndo, "'")); cp += SERIAL_NUM_LEN; /* dp_desc */ ND_TCHECK2(*cp, DESC_STR_LEN); ND_PRINT((ndo, "\n\t dp_desc '")); fn_print(ndo, cp, cp + DESC_STR_LEN); ND_PRINT((ndo, "'")); return cp + DESC_STR_LEN; corrupt: /* skip the message body */ ND_PRINT((ndo, "%s", cstr)); ND_TCHECK2(*cp, len); return cp + len; trunc: ND_PRINT((ndo, "%s", tstr)); return ep; } /* ibid */ static const u_char * of10_flow_stats_reply_print(netdissect_options *ndo, - const u_char *cp, const u_char *ep, u_int len) { + const u_char *cp, const u_char *ep, u_int len) +{ const u_char *cp0 = cp; const u_int len0 = len; uint16_t entry_len; while (len) { if (len < OF_FLOW_STATS_LEN) goto corrupt; /* length */ ND_TCHECK2(*cp, 2); entry_len = EXTRACT_16BITS(cp); ND_PRINT((ndo, "\n\t length %u", entry_len)); if (entry_len < OF_FLOW_STATS_LEN || entry_len > len) goto corrupt; cp += 2; /* table_id */ ND_TCHECK2(*cp, 1); ND_PRINT((ndo, ", table_id %s", tok2str(tableid_str, "%u", *cp))); cp += 1; /* pad */ ND_TCHECK2(*cp, 1); cp += 1; /* match */ if (ep == (cp = of10_match_print(ndo, "\n\t ", cp, ep))) return ep; /* end of snapshot */ /* duration_sec */ ND_TCHECK2(*cp, 4); ND_PRINT((ndo, "\n\t duration_sec %u", EXTRACT_32BITS(cp))); cp += 4; /* duration_nsec */ ND_TCHECK2(*cp, 4); ND_PRINT((ndo, ", duration_nsec %u", EXTRACT_32BITS(cp))); cp += 4; /* priority */ ND_TCHECK2(*cp, 2); ND_PRINT((ndo, ", priority %u", EXTRACT_16BITS(cp))); cp += 2; /* idle_timeout */ ND_TCHECK2(*cp, 2); ND_PRINT((ndo, ", idle_timeout %u", EXTRACT_16BITS(cp))); cp += 2; /* hard_timeout */ ND_TCHECK2(*cp, 2); ND_PRINT((ndo, ", hard_timeout %u", EXTRACT_16BITS(cp))); cp += 2; /* pad2 */ ND_TCHECK2(*cp, 6); cp += 6; /* cookie */ ND_TCHECK2(*cp, 8); ND_PRINT((ndo, ", cookie 0x%016" PRIx64, EXTRACT_64BITS(cp))); cp += 8; /* packet_count */ ND_TCHECK2(*cp, 8); ND_PRINT((ndo, ", packet_count %" PRIu64, EXTRACT_64BITS(cp))); cp += 8; /* byte_count */ ND_TCHECK2(*cp, 8); ND_PRINT((ndo, ", byte_count %" PRIu64, EXTRACT_64BITS(cp))); cp += 8; /* actions */ if (ep == (cp = of10_actions_print(ndo, "\n\t ", cp, ep, entry_len - OF_FLOW_STATS_LEN))) return ep; /* end of snapshot */ len -= entry_len; } /* while */ return cp; corrupt: /* skip the rest of flow statistics entries */ ND_PRINT((ndo, "%s", cstr)); ND_TCHECK2(*cp0, len0); return cp0 + len0; trunc: ND_PRINT((ndo, "%s", tstr)); return ep; } /* ibid */ static const u_char * of10_aggregate_stats_reply_print(netdissect_options *ndo, const u_char *cp, const u_char *ep, - const u_int len) { + const u_int len) +{ if (len != OF_AGGREGATE_STATS_REPLY_LEN) goto corrupt; /* packet_count */ ND_TCHECK2(*cp, 8); ND_PRINT((ndo, "\n\t packet_count %" PRIu64, EXTRACT_64BITS(cp))); cp += 8; /* byte_count */ ND_TCHECK2(*cp, 8); ND_PRINT((ndo, ", byte_count %" PRIu64, EXTRACT_64BITS(cp))); cp += 8; /* flow_count */ ND_TCHECK2(*cp, 4); ND_PRINT((ndo, ", flow_count %u", EXTRACT_32BITS(cp))); cp += 4; /* pad */ ND_TCHECK2(*cp, 4); return cp + 4; corrupt: /* skip the message body */ ND_PRINT((ndo, "%s", cstr)); ND_TCHECK2(*cp, len); return cp + len; trunc: ND_PRINT((ndo, "%s", tstr)); return ep; } /* ibid */ static const u_char * of10_table_stats_reply_print(netdissect_options *ndo, - const u_char *cp, const u_char *ep, u_int len) { + const u_char *cp, const u_char *ep, u_int len) +{ const u_char *cp0 = cp; const u_int len0 = len; while (len) { if (len < OF_TABLE_STATS_LEN) goto corrupt; /* table_id */ ND_TCHECK2(*cp, 1); ND_PRINT((ndo, "\n\t table_id %s", tok2str(tableid_str, "%u", *cp))); cp += 1; /* pad */ ND_TCHECK2(*cp, 3); cp += 3; /* name */ ND_TCHECK2(*cp, OFP_MAX_TABLE_NAME_LEN); ND_PRINT((ndo, ", name '")); fn_print(ndo, cp, cp + OFP_MAX_TABLE_NAME_LEN); ND_PRINT((ndo, "'")); cp += OFP_MAX_TABLE_NAME_LEN; /* wildcards */ ND_TCHECK2(*cp, 4); ND_PRINT((ndo, "\n\t wildcards 0x%08x", EXTRACT_32BITS(cp))); of10_bitmap_print(ndo, ofpfw_bm, EXTRACT_32BITS(cp), OFPFW_U); cp += 4; /* max_entries */ ND_TCHECK2(*cp, 4); ND_PRINT((ndo, "\n\t max_entries %u", EXTRACT_32BITS(cp))); cp += 4; /* active_count */ ND_TCHECK2(*cp, 4); ND_PRINT((ndo, ", active_count %u", EXTRACT_32BITS(cp))); cp += 4; /* lookup_count */ ND_TCHECK2(*cp, 8); ND_PRINT((ndo, ", lookup_count %" PRIu64, EXTRACT_64BITS(cp))); cp += 8; /* matched_count */ ND_TCHECK2(*cp, 8); ND_PRINT((ndo, ", matched_count %" PRIu64, EXTRACT_64BITS(cp))); cp += 8; len -= OF_TABLE_STATS_LEN; } /* while */ return cp; corrupt: /* skip the undersized trailing data */ ND_PRINT((ndo, "%s", cstr)); ND_TCHECK2(*cp0, len0); return cp0 + len0; trunc: ND_PRINT((ndo, "%s", tstr)); return ep; } /* ibid */ static const u_char * of10_port_stats_reply_print(netdissect_options *ndo, - const u_char *cp, const u_char *ep, u_int len) { + const u_char *cp, const u_char *ep, u_int len) +{ const u_char *cp0 = cp; const u_int len0 = len; while (len) { if (len < OF_PORT_STATS_LEN) goto corrupt; /* port_no */ ND_TCHECK2(*cp, 2); ND_PRINT((ndo, "\n\t port_no %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp)))); cp += 2; if (ndo->ndo_vflag < 2) { ND_TCHECK2(*cp, OF_PORT_STATS_LEN - 2); cp += OF_PORT_STATS_LEN - 2; goto next_port; } /* pad */ ND_TCHECK2(*cp, 6); cp += 6; /* rx_packets */ ND_TCHECK2(*cp, 8); ND_PRINT((ndo, ", rx_packets %" PRIu64, EXTRACT_64BITS(cp))); cp += 8; /* tx_packets */ ND_TCHECK2(*cp, 8); ND_PRINT((ndo, ", tx_packets %" PRIu64, EXTRACT_64BITS(cp))); cp += 8; /* rx_bytes */ ND_TCHECK2(*cp, 8); ND_PRINT((ndo, ", rx_bytes %" PRIu64, EXTRACT_64BITS(cp))); cp += 8; /* tx_bytes */ ND_TCHECK2(*cp, 8); ND_PRINT((ndo, ", tx_bytes %" PRIu64, EXTRACT_64BITS(cp))); cp += 8; /* rx_dropped */ ND_TCHECK2(*cp, 8); ND_PRINT((ndo, ", rx_dropped %" PRIu64, EXTRACT_64BITS(cp))); cp += 8; /* tx_dropped */ ND_TCHECK2(*cp, 8); ND_PRINT((ndo, ", tx_dropped %" PRIu64, EXTRACT_64BITS(cp))); cp += 8; /* rx_errors */ ND_TCHECK2(*cp, 8); ND_PRINT((ndo, ", rx_errors %" PRIu64, EXTRACT_64BITS(cp))); cp += 8; /* tx_errors */ ND_TCHECK2(*cp, 8); ND_PRINT((ndo, ", tx_errors %" PRIu64, EXTRACT_64BITS(cp))); cp += 8; /* rx_frame_err */ ND_TCHECK2(*cp, 8); ND_PRINT((ndo, ", rx_frame_err %" PRIu64, EXTRACT_64BITS(cp))); cp += 8; /* rx_over_err */ ND_TCHECK2(*cp, 8); ND_PRINT((ndo, ", rx_over_err %" PRIu64, EXTRACT_64BITS(cp))); cp += 8; /* rx_crc_err */ ND_TCHECK2(*cp, 8); ND_PRINT((ndo, ", rx_crc_err %" PRIu64, EXTRACT_64BITS(cp))); cp += 8; /* collisions */ ND_TCHECK2(*cp, 8); ND_PRINT((ndo, ", collisions %" PRIu64, EXTRACT_64BITS(cp))); cp += 8; next_port: len -= OF_PORT_STATS_LEN; } /* while */ return cp; corrupt: /* skip the undersized trailing data */ ND_PRINT((ndo, "%s", cstr)); ND_TCHECK2(*cp0, len0); return cp0 + len0; trunc: ND_PRINT((ndo, "%s", tstr)); return ep; } /* ibid */ static const u_char * of10_queue_stats_reply_print(netdissect_options *ndo, - const u_char *cp, const u_char *ep, u_int len) { + const u_char *cp, const u_char *ep, u_int len) +{ const u_char *cp0 = cp; const u_int len0 = len; while (len) { if (len < OF_QUEUE_STATS_LEN) goto corrupt; /* port_no */ ND_TCHECK2(*cp, 2); ND_PRINT((ndo, "\n\t port_no %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp)))); cp += 2; /* pad */ ND_TCHECK2(*cp, 2); cp += 2; /* queue_id */ ND_TCHECK2(*cp, 4); ND_PRINT((ndo, ", queue_id %u", EXTRACT_32BITS(cp))); cp += 4; /* tx_bytes */ ND_TCHECK2(*cp, 8); ND_PRINT((ndo, ", tx_bytes %" PRIu64, EXTRACT_64BITS(cp))); cp += 8; /* tx_packets */ ND_TCHECK2(*cp, 8); ND_PRINT((ndo, ", tx_packets %" PRIu64, EXTRACT_64BITS(cp))); cp += 8; /* tx_errors */ ND_TCHECK2(*cp, 8); ND_PRINT((ndo, ", tx_errors %" PRIu64, EXTRACT_64BITS(cp))); cp += 8; len -= OF_QUEUE_STATS_LEN; } /* while */ return cp; corrupt: /* skip the undersized trailing data */ ND_PRINT((ndo, "%s", cstr)); ND_TCHECK2(*cp0, len0); return cp0 + len0; trunc: ND_PRINT((ndo, "%s", tstr)); return ep; } /* ibid */ static const u_char * of10_stats_reply_print(netdissect_options *ndo, - const u_char *cp, const u_char *ep, const u_int len) { + const u_char *cp, const u_char *ep, const u_int len) +{ const u_char *cp0 = cp; uint16_t type; /* type */ ND_TCHECK2(*cp, 2); type = EXTRACT_16BITS(cp); ND_PRINT((ndo, "\n\t type %s", tok2str(ofpst_str, "invalid (0x%04x)", type))); cp += 2; /* flags */ ND_TCHECK2(*cp, 2); ND_PRINT((ndo, ", flags 0x%04x", EXTRACT_16BITS(cp))); of10_bitmap_print(ndo, ofpsf_reply_bm, EXTRACT_16BITS(cp), OFPSF_REPLY_U); cp += 2; if (ndo->ndo_vflag > 0) { const u_char *(*decoder)(netdissect_options *, const u_char *, 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) return decoder(ndo, cp, ep, len - OF_STATS_REPLY_LEN); } ND_TCHECK2(*cp0, len); return cp0 + len; trunc: ND_PRINT((ndo, "%s", tstr)); return ep; } /* [OF10] Section 5.3.6 */ static const u_char * of10_packet_out_print(netdissect_options *ndo, - const u_char *cp, const u_char *ep, const u_int len) { + const u_char *cp, const u_char *ep, const u_int len) +{ const u_char *cp0 = cp; const u_int len0 = len; uint16_t actions_len; /* buffer_id */ ND_TCHECK2(*cp, 4); ND_PRINT((ndo, "\n\t buffer_id 0x%08x", EXTRACT_32BITS(cp))); cp += 4; /* in_port */ ND_TCHECK2(*cp, 2); ND_PRINT((ndo, ", in_port %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp)))); cp += 2; /* actions_len */ ND_TCHECK2(*cp, 2); actions_len = EXTRACT_16BITS(cp); cp += 2; if (actions_len > len - OF_PACKET_OUT_LEN) goto corrupt; /* actions */ if (ep == (cp = of10_actions_print(ndo, "\n\t ", cp, ep, actions_len))) return ep; /* end of snapshot */ /* data */ return of10_packet_data_print(ndo, cp, ep, len - OF_PACKET_OUT_LEN - actions_len); corrupt: /* skip the rest of the message body */ ND_PRINT((ndo, "%s", cstr)); ND_TCHECK2(*cp0, len0); return cp0 + len0; trunc: ND_PRINT((ndo, "%s", tstr)); return ep; } /* [OF10] Section 5.4.1 */ static const u_char * of10_packet_in_print(netdissect_options *ndo, - const u_char *cp, const u_char *ep, const u_int len) { + const u_char *cp, const u_char *ep, const u_int len) +{ /* buffer_id */ ND_TCHECK2(*cp, 4); ND_PRINT((ndo, "\n\t buffer_id %s", tok2str(bufferid_str, "0x%08x", EXTRACT_32BITS(cp)))); cp += 4; /* total_len */ ND_TCHECK2(*cp, 2); ND_PRINT((ndo, ", total_len %u", EXTRACT_16BITS(cp))); cp += 2; /* in_port */ ND_TCHECK2(*cp, 2); ND_PRINT((ndo, ", in_port %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp)))); cp += 2; /* reason */ ND_TCHECK2(*cp, 1); ND_PRINT((ndo, ", reason %s", tok2str(ofpr_str, "invalid (0x%02x)", *cp))); cp += 1; /* pad */ ND_TCHECK2(*cp, 1); cp += 1; /* data */ /* 2 mock octets count in OF_PACKET_IN_LEN but not in len */ return of10_packet_data_print(ndo, cp, ep, len - (OF_PACKET_IN_LEN - 2)); trunc: ND_PRINT((ndo, "%s", tstr)); return ep; } /* [OF10] Section 5.4.2 */ static const u_char * of10_flow_removed_print(netdissect_options *ndo, - const u_char *cp, const u_char *ep) { + const u_char *cp, const u_char *ep) +{ /* match */ if (ep == (cp = of10_match_print(ndo, "\n\t ", cp, ep))) return ep; /* end of snapshot */ /* cookie */ ND_TCHECK2(*cp, 8); ND_PRINT((ndo, "\n\t cookie 0x%016" PRIx64, EXTRACT_64BITS(cp))); cp += 8; /* priority */ ND_TCHECK2(*cp, 2); if (EXTRACT_16BITS(cp)) ND_PRINT((ndo, ", priority %u", EXTRACT_16BITS(cp))); cp += 2; /* reason */ ND_TCHECK2(*cp, 1); ND_PRINT((ndo, ", reason %s", tok2str(ofprr_str, "unknown (0x%02x)", *cp))); cp += 1; /* pad */ ND_TCHECK2(*cp, 1); cp += 1; /* duration_sec */ ND_TCHECK2(*cp, 4); ND_PRINT((ndo, ", duration_sec %u", EXTRACT_32BITS(cp))); cp += 4; /* duration_nsec */ ND_TCHECK2(*cp, 4); ND_PRINT((ndo, ", duration_nsec %u", EXTRACT_32BITS(cp))); cp += 4; /* idle_timeout */ ND_TCHECK2(*cp, 2); if (EXTRACT_16BITS(cp)) ND_PRINT((ndo, ", idle_timeout %u", EXTRACT_16BITS(cp))); cp += 2; /* pad2 */ ND_TCHECK2(*cp, 2); cp += 2; /* packet_count */ ND_TCHECK2(*cp, 8); ND_PRINT((ndo, ", packet_count %" PRIu64, EXTRACT_64BITS(cp))); cp += 8; /* byte_count */ ND_TCHECK2(*cp, 8); ND_PRINT((ndo, ", byte_count %" PRIu64, EXTRACT_64BITS(cp))); return cp + 8; trunc: ND_PRINT((ndo, "%s", tstr)); return ep; } /* [OF10] Section 5.4.4 */ static const u_char * of10_error_print(netdissect_options *ndo, - const u_char *cp, const u_char *ep, const u_int len) { + const u_char *cp, const u_char *ep, const u_int len) +{ uint16_t type; const struct tok *code_str; /* type */ ND_TCHECK2(*cp, 2); type = EXTRACT_16BITS(cp); cp += 2; ND_PRINT((ndo, "\n\t type %s", tok2str(ofpet_str, "invalid (0x%04x)", type))); /* code */ ND_TCHECK2(*cp, 2); code_str = type == OFPET_HELLO_FAILED ? ofphfc_str : type == OFPET_BAD_REQUEST ? ofpbrc_str : type == OFPET_BAD_ACTION ? ofpbac_str : type == OFPET_FLOW_MOD_FAILED ? ofpfmfc_str : type == OFPET_PORT_MOD_FAILED ? ofppmfc_str : type == OFPET_QUEUE_OP_FAILED ? ofpqofc_str : empty_str; ND_PRINT((ndo, ", code %s", tok2str(code_str, "invalid (0x%04x)", EXTRACT_16BITS(cp)))); cp += 2; /* data */ return of10_data_print(ndo, cp, ep, len - OF_ERROR_MSG_LEN); trunc: ND_PRINT((ndo, "%s", tstr)); return ep; } const u_char * of10_header_body_print(netdissect_options *ndo, const u_char *cp, const u_char *ep, const uint8_t type, - const uint16_t len, const uint32_t xid) { + const uint16_t len, const uint32_t xid) +{ const u_char *cp0 = cp; const u_int len0 = len; /* Thus far message length is not less than the basic header size, but most * message types have additional assorted constraints on the length. Wherever * possible, check that message length meets the constraint, in remaining * cases check that the length is OK to begin decoding and leave any final * verification up to a lower-layer function. When the current message is * corrupt, proceed to the next message. */ /* [OF10] Section 5.1 */ ND_PRINT((ndo, "\n\tversion 1.0, type %s, length %u, xid 0x%08x", tok2str(ofpt_str, "invalid (0x%02x)", type), len, xid)); switch (type) { /* OpenFlow header only. */ case OFPT_FEATURES_REQUEST: /* [OF10] Section 5.3.1 */ case OFPT_GET_CONFIG_REQUEST: /* [OF10] Section 5.3.2 */ case OFPT_BARRIER_REQUEST: /* [OF10] Section 5.3.7 */ case OFPT_BARRIER_REPLY: /* ibid */ if (len != OF_HEADER_LEN) goto corrupt; break; /* OpenFlow header and fixed-size message body. */ case OFPT_SET_CONFIG: /* [OF10] Section 5.3.2 */ case OFPT_GET_CONFIG_REPLY: /* ibid */ if (len != OF_SWITCH_CONFIG_LEN) goto corrupt; if (ndo->ndo_vflag < 1) goto next_message; /* flags */ ND_TCHECK2(*cp, 2); ND_PRINT((ndo, "\n\t flags %s", tok2str(ofp_config_str, "invalid (0x%04x)", EXTRACT_16BITS(cp)))); cp += 2; /* miss_send_len */ ND_TCHECK2(*cp, 2); ND_PRINT((ndo, ", miss_send_len %u", EXTRACT_16BITS(cp))); return cp + 2; case OFPT_PORT_MOD: if (len != OF_PORT_MOD_LEN) goto corrupt; if (ndo->ndo_vflag < 1) goto next_message; return of10_port_mod_print(ndo, cp, ep); case OFPT_QUEUE_GET_CONFIG_REQUEST: /* [OF10] Section 5.3.4 */ if (len != OF_QUEUE_GET_CONFIG_REQUEST_LEN) goto corrupt; if (ndo->ndo_vflag < 1) goto next_message; /* port */ ND_TCHECK2(*cp, 2); ND_PRINT((ndo, "\n\t port_no %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp)))); cp += 2; /* pad */ ND_TCHECK2(*cp, 2); return cp + 2; case OFPT_FLOW_REMOVED: if (len != OF_FLOW_REMOVED_LEN) goto corrupt; if (ndo->ndo_vflag < 1) goto next_message; return of10_flow_removed_print(ndo, cp, ep); case OFPT_PORT_STATUS: /* [OF10] Section 5.4.3 */ if (len != OF_PORT_STATUS_LEN) goto corrupt; if (ndo->ndo_vflag < 1) goto next_message; /* reason */ ND_TCHECK2(*cp, 1); ND_PRINT((ndo, "\n\t reason %s", tok2str(ofppr_str, "invalid (0x%02x)", *cp))); cp += 1; /* pad */ ND_TCHECK2(*cp, 7); cp += 7; /* desc */ return of10_phy_ports_print(ndo, cp, ep, OF_PHY_PORT_LEN); /* OpenFlow header, fixed-size message body and n * fixed-size data units. */ case OFPT_FEATURES_REPLY: if (len < OF_SWITCH_FEATURES_LEN) goto corrupt; if (ndo->ndo_vflag < 1) goto next_message; return of10_features_reply_print(ndo, cp, ep, len); /* OpenFlow header and variable-size data. */ case OFPT_HELLO: /* [OF10] Section 5.5.1 */ case OFPT_ECHO_REQUEST: /* [OF10] Section 5.5.2 */ case OFPT_ECHO_REPLY: /* [OF10] Section 5.5.3 */ if (ndo->ndo_vflag < 1) goto next_message; return of10_data_print(ndo, cp, ep, len - OF_HEADER_LEN); /* OpenFlow header, fixed-size message body and variable-size data. */ case OFPT_ERROR: if (len < OF_ERROR_MSG_LEN) goto corrupt; if (ndo->ndo_vflag < 1) goto next_message; return of10_error_print(ndo, cp, ep, len); case OFPT_VENDOR: /* [OF10] Section 5.5.4 */ if (len < OF_VENDOR_HEADER_LEN) goto corrupt; if (ndo->ndo_vflag < 1) goto next_message; - return of10_vendor_data_print(ndo, cp, ep, len - OF_HEADER_LEN); + return of10_vendor_message_print(ndo, cp, ep, len - OF_HEADER_LEN); case OFPT_PACKET_IN: /* 2 mock octets count in OF_PACKET_IN_LEN but not in len */ if (len < OF_PACKET_IN_LEN - 2) goto corrupt; if (ndo->ndo_vflag < 1) goto next_message; return of10_packet_in_print(ndo, cp, ep, len); /* a. OpenFlow header. */ /* b. OpenFlow header and one of the fixed-size message bodies. */ /* c. OpenFlow header, fixed-size message body and variable-size data. */ case OFPT_STATS_REQUEST: if (len < OF_STATS_REQUEST_LEN) goto corrupt; if (ndo->ndo_vflag < 1) goto next_message; return of10_stats_request_print(ndo, cp, ep, len); /* a. OpenFlow header and fixed-size message body. */ /* b. OpenFlow header and n * fixed-size data units. */ /* c. OpenFlow header and n * variable-size data units. */ /* d. OpenFlow header, fixed-size message body and variable-size data. */ case OFPT_STATS_REPLY: if (len < OF_STATS_REPLY_LEN) goto corrupt; if (ndo->ndo_vflag < 1) goto next_message; return of10_stats_reply_print(ndo, cp, ep, len); /* OpenFlow header and n * variable-size data units and variable-size data. */ case OFPT_PACKET_OUT: if (len < OF_PACKET_OUT_LEN) goto corrupt; if (ndo->ndo_vflag < 1) goto next_message; return of10_packet_out_print(ndo, cp, ep, len); /* OpenFlow header, fixed-size message body and n * variable-size data units. */ case OFPT_FLOW_MOD: if (len < OF_FLOW_MOD_LEN) goto corrupt; if (ndo->ndo_vflag < 1) goto next_message; return of10_flow_mod_print(ndo, cp, ep, len); /* OpenFlow header, fixed-size message body and n * variable-size data units. */ case OFPT_QUEUE_GET_CONFIG_REPLY: /* [OF10] Section 5.3.4 */ if (len < OF_QUEUE_GET_CONFIG_REPLY_LEN) goto corrupt; if (ndo->ndo_vflag < 1) goto next_message; /* port */ ND_TCHECK2(*cp, 2); ND_PRINT((ndo, "\n\t port_no %s", tok2str(ofpp_str, "%u", EXTRACT_16BITS(cp)))); cp += 2; /* pad */ ND_TCHECK2(*cp, 6); cp += 6; /* queues */ return of10_queues_print(ndo, cp, ep, len - OF_QUEUE_GET_CONFIG_REPLY_LEN); } /* switch (type) */ goto next_message; corrupt: /* skip the message body */ ND_PRINT((ndo, "%s", cstr)); next_message: ND_TCHECK2(*cp0, len0 - OF_HEADER_LEN); return cp0 + len0 - OF_HEADER_LEN; trunc: ND_PRINT((ndo, "%s", tstr)); return ep; } Index: head/contrib/tcpdump/print-openflow.c =================================================================== --- head/contrib/tcpdump/print-openflow.c (revision 285274) +++ head/contrib/tcpdump/print-openflow.c (revision 285275) @@ -1,119 +1,142 @@ /* * 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. */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "interface.h" #include "extract.h" #include "openflow.h" +#include "oui.h" static const char tstr[] = " [|openflow]"; static const char cstr[] = " (corrupt)"; #define OF_VER_1_0 0x01 +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" }, + { 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); +} + static void of_header_print(netdissect_options *ndo, const uint8_t version, const uint8_t type, - const uint16_t length, const uint32_t xid) { + const uint16_t length, const uint32_t xid) +{ ND_PRINT((ndo, "\n\tversion unknown (0x%02x), type 0x%02x, length %u, xid 0x%08x", version, type, length, xid)); } /* Print a single OpenFlow message. */ static const u_char * -of_header_body_print(netdissect_options *ndo, const u_char *cp, const u_char *ep) { +of_header_body_print(netdissect_options *ndo, const u_char *cp, const u_char *ep) +{ uint8_t version, type; uint16_t length; uint32_t xid; if (ep < cp + OF_HEADER_LEN) goto corrupt; /* version */ ND_TCHECK2(*cp, 1); version = *cp; cp += 1; /* type */ ND_TCHECK2(*cp, 1); type = *cp; cp += 1; /* length */ ND_TCHECK2(*cp, 2); length = EXTRACT_16BITS(cp); cp += 2; /* xid */ ND_TCHECK2(*cp, 4); xid = EXTRACT_32BITS(cp); cp += 4; /* 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. */ if (length < OF_HEADER_LEN) { of_header_print(ndo, version, type, length, xid); goto corrupt; } /* Decode known protocol versions further without printing the header (the * type decoding is version-specific. */ switch (version) { case OF_VER_1_0: return of10_header_body_print(ndo, cp, ep, type, length, xid); default: of_header_print(ndo, version, type, length, xid); ND_TCHECK2(*cp, length - OF_HEADER_LEN); return cp + length - OF_HEADER_LEN; /* done with current message */ } corrupt: /* fail current packet */ ND_PRINT((ndo, "%s", cstr)); ND_TCHECK2(*cp, ep - cp); return ep; trunc: ND_PRINT((ndo, "%s", tstr)); return ep; } /* 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, const u_int len) { +openflow_print(netdissect_options *ndo, const u_char *cp, const u_int len) +{ const u_char *ep = cp + len; ND_PRINT((ndo, ": OpenFlow")); while (cp < ep) cp = of_header_body_print(ndo, cp, ep); } Index: head/contrib/tcpdump/print-ospf.c =================================================================== --- head/contrib/tcpdump/print-ospf.c (revision 285274) +++ head/contrib/tcpdump/print-ospf.c (revision 285275) @@ -1,1141 +1,1141 @@ /* * 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) */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "interface.h" #include "addrtoname.h" #include "extract.h" #include "gmpls.h" #include "ospf.h" static const char tstr[] = " [|ospf2]"; static const struct tok ospf_option_values[] = { { OSPF_OPTION_T, "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_W1, "Virtual" }, { RLA_FLAG_W2, "W2" }, { 0, NULL } }; static const struct tok type2str[] = { { OSPF_TYPE_UMD, "UMD" }, { 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_print_grace_lsa(netdissect_options *ndo, - const uint8_t *tptr, u_int ls_length) { - + const uint8_t *tptr, u_int ls_length) +{ u_int tlv_type, tlv_length; while (ls_length > 0) { ND_TCHECK2(*tptr, 4); if (ls_length < 4) { ND_PRINT((ndo, "\n\t Remaining LS length %u < 4", ls_length)); return -1; } tlv_type = EXTRACT_16BITS(tptr); tlv_length = EXTRACT_16BITS(tptr+2); tptr+=4; ls_length-=4; ND_PRINT((ndo, "\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((ndo, "\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_TCHECK2(*tptr, tlv_length); switch(tlv_type) { case LS_OPAQUE_GRACE_TLV_PERIOD: if (tlv_length != 4) { ND_PRINT((ndo, "\n\t Bogus length %u != 4", tlv_length)); return -1; } ND_PRINT((ndo, "%us", EXTRACT_32BITS(tptr))); break; case LS_OPAQUE_GRACE_TLV_REASON: if (tlv_length != 1) { ND_PRINT((ndo, "\n\t Bogus length %u != 1", tlv_length)); return -1; } ND_PRINT((ndo, "%s (%u)", tok2str(lsa_opaque_grace_tlv_reason_values, "Unknown", *tptr), *tptr)); break; case LS_OPAQUE_GRACE_TLV_INT_ADDRESS: if (tlv_length != 4) { ND_PRINT((ndo, "\n\t Bogus length %u != 4", tlv_length)); return -1; } ND_PRINT((ndo, "%s", ipaddr_string(ndo, 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_print_te_lsa(netdissect_options *ndo, - const uint8_t *tptr, u_int ls_length) { - + const uint8_t *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_TCHECK2(*tptr, 4); if (ls_length < 4) { ND_PRINT((ndo, "\n\t Remaining LS length %u < 4", ls_length)); return -1; } tlv_type = EXTRACT_16BITS(tptr); tlv_length = EXTRACT_16BITS(tptr+2); tptr+=4; ls_length-=4; ND_PRINT((ndo, "\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((ndo, "\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 >= sizeof(subtlv_type) + sizeof(subtlv_length)) { if (tlv_length < 4) { ND_PRINT((ndo, "\n\t Remaining TLV length %u < 4", tlv_length)); return -1; } ND_TCHECK2(*tptr, 4); subtlv_type = EXTRACT_16BITS(tptr); subtlv_length = EXTRACT_16BITS(tptr+2); tptr+=4; tlv_length-=4; ND_PRINT((ndo, "\n\t %s subTLV (%u), length: %u", tok2str(lsa_opaque_te_link_tlv_subtlv_values,"unknown",subtlv_type), subtlv_type, subtlv_length)); ND_TCHECK2(*tptr, subtlv_length); switch(subtlv_type) { case LS_OPAQUE_TE_LINK_SUBTLV_ADMIN_GROUP: ND_PRINT((ndo, ", 0x%08x", EXTRACT_32BITS(tptr))); break; case LS_OPAQUE_TE_LINK_SUBTLV_LINK_ID: case LS_OPAQUE_TE_LINK_SUBTLV_LINK_LOCAL_REMOTE_ID: ND_PRINT((ndo, ", %s (0x%08x)", ipaddr_string(ndo, tptr), EXTRACT_32BITS(tptr))); if (subtlv_length == 8) /* rfc4203 */ ND_PRINT((ndo, ", %s (0x%08x)", ipaddr_string(ndo, tptr+4), EXTRACT_32BITS(tptr + 4))); break; case LS_OPAQUE_TE_LINK_SUBTLV_LOCAL_IP: case LS_OPAQUE_TE_LINK_SUBTLV_REMOTE_IP: ND_PRINT((ndo, ", %s", ipaddr_string(ndo, tptr))); break; case LS_OPAQUE_TE_LINK_SUBTLV_MAX_BW: case LS_OPAQUE_TE_LINK_SUBTLV_MAX_RES_BW: bw.i = EXTRACT_32BITS(tptr); ND_PRINT((ndo, ", %.3f Mbps", bw.f * 8 / 1000000)); break; case LS_OPAQUE_TE_LINK_SUBTLV_UNRES_BW: for (te_class = 0; te_class < 8; te_class++) { bw.i = EXTRACT_32BITS(tptr+te_class*4); ND_PRINT((ndo, "\n\t\tTE-Class %u: %.3f Mbps", te_class, bw.f * 8 / 1000000)); } break; case LS_OPAQUE_TE_LINK_SUBTLV_BW_CONSTRAINTS: ND_PRINT((ndo, "\n\t\tBandwidth Constraints Model ID: %s (%u)", tok2str(diffserv_te_bc_values, "unknown", *tptr), *tptr)); /* decode BCs until the subTLV ends */ for (te_class = 0; te_class < (subtlv_length-4)/4; te_class++) { bw.i = EXTRACT_32BITS(tptr+4+te_class*4); ND_PRINT((ndo, "\n\t\t Bandwidth constraint CT%u: %.3f Mbps", te_class, bw.f * 8 / 1000000)); } break; case LS_OPAQUE_TE_LINK_SUBTLV_TE_METRIC: ND_PRINT((ndo, ", Metric %u", EXTRACT_32BITS(tptr))); break; case LS_OPAQUE_TE_LINK_SUBTLV_LINK_PROTECTION_TYPE: ND_PRINT((ndo, ", %s, Priority %u", bittok2str(gmpls_link_prot_values, "none", *tptr), *(tptr + 1))); break; case LS_OPAQUE_TE_LINK_SUBTLV_INTF_SW_CAP_DESCR: ND_PRINT((ndo, "\n\t\tInterface Switching Capability: %s", tok2str(gmpls_switch_cap_values, "Unknown", *(tptr)))); ND_PRINT((ndo, "\n\t\tLSP Encoding: %s\n\t\tMax LSP Bandwidth:", tok2str(gmpls_encoding_values, "Unknown", *(tptr + 1)))); for (priority_level = 0; priority_level < 8; priority_level++) { bw.i = EXTRACT_32BITS(tptr+4+(priority_level*4)); ND_PRINT((ndo, "\n\t\t priority level %d: %.3f Mbps", priority_level, bw.f * 8 / 1000000)); } break; case LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE: ND_PRINT((ndo, ", %s (%u)", tok2str(lsa_opaque_te_tlv_link_type_sub_tlv_values,"unknown",*tptr), *tptr)); break; case LS_OPAQUE_TE_LINK_SUBTLV_SHARED_RISK_GROUP: count_srlg = subtlv_length / 4; if (count_srlg != 0) ND_PRINT((ndo, "\n\t\t Shared risk group: ")); while (count_srlg > 0) { bw.i = EXTRACT_32BITS(tptr); ND_PRINT((ndo, "%d", bw.i)); tptr+=4; count_srlg--; if (count_srlg > 0) ND_PRINT((ndo, ", ")); } 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); tlv_length-=subtlv_length; tptr+=subtlv_length; } break; case LS_OPAQUE_TE_TLV_ROUTER: if (tlv_length < 4) { ND_PRINT((ndo, "\n\t TLV length %u < 4", tlv_length)); return -1; } ND_TCHECK2(*tptr, 4); ND_PRINT((ndo, ", %s", ipaddr_string(ndo, 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; } static int ospf_print_lshdr(netdissect_options *ndo, register const struct lsa_hdr *lshp) { u_int ls_length; ND_TCHECK(lshp->ls_length); ls_length = EXTRACT_16BITS(&lshp->ls_length); if (ls_length < sizeof(struct lsa_hdr)) { ND_PRINT((ndo, "\n\t Bogus length %u < header (%lu)", ls_length, (unsigned long)sizeof(struct lsa_hdr))); return(-1); } ND_TCHECK(lshp->ls_seq); /* XXX - ls_length check checked this */ ND_PRINT((ndo, "\n\t Advertising Router %s, seq 0x%08x, age %us, length %u", ipaddr_string(ndo, &lshp->ls_router), EXTRACT_32BITS(&lshp->ls_seq), EXTRACT_16BITS(&lshp->ls_age), ls_length - (u_int)sizeof(struct lsa_hdr))); ND_TCHECK(lshp->ls_type); /* XXX - ls_length check checked this */ switch (lshp->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((ndo, "\n\t %s LSA (%d), Opaque-Type %s LSA (%u), Opaque-ID %u", tok2str(lsa_values,"unknown",lshp->ls_type), lshp->ls_type, tok2str(lsa_opaque_values, "unknown", *(&lshp->un_lsa_id.opaque_field.opaque_type)), *(&lshp->un_lsa_id.opaque_field.opaque_type), EXTRACT_24BITS(&lshp->un_lsa_id.opaque_field.opaque_id) )); break; /* all other LSA types use regular style LSA headers */ default: ND_PRINT((ndo, "\n\t %s LSA (%d), LSA-ID: %s", tok2str(lsa_values,"unknown",lshp->ls_type), lshp->ls_type, ipaddr_string(ndo, &lshp->un_lsa_id.lsa_id))); break; } ND_TCHECK(lshp->ls_options); /* XXX - ls_length check checked this */ ND_PRINT((ndo, "\n\t Options: [%s]", bittok2str(ospf_option_values, "none", lshp->ls_options))); return (ls_length); trunc: return (-1); } /* 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) { int metric_count; int toscount; toscount = tos->link.link_tos_count+1; metric_count = 0; /* * All but the first metric contain a valid topology id. */ while (toscount) { ND_PRINT((ndo, "\n\t\ttopology %s(%u), metric %u", tok2str(ospf_topology_values, "", metric_count ? tos->metrics.tos_type : 0), metric_count ? tos->metrics.tos_type : 0, EXTRACT_16BITS(&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, register const struct lsa *lsap) { register const uint8_t *ls_end; register const struct rlalink *rlp; register const struct in_addr *ap; register const struct aslametric *almp; register const struct mcla *mcp; register const uint32_t *lp; register int j, tlv_type, tlv_length, topology; register int ls_length; const uint8_t *tptr; tptr = (uint8_t *)lsap->lsa_un.un_unknown; /* squelch compiler warnings */ ls_length = ospf_print_lshdr(ndo, &lsap->ls_hdr); if (ls_length == -1) return(NULL); ls_end = (uint8_t *)lsap + ls_length; ls_length -= sizeof(struct lsa_hdr); switch (lsap->ls_hdr.ls_type) { case LS_TYPE_ROUTER: ND_TCHECK(lsap->lsa_un.un_rla.rla_flags); ND_PRINT((ndo, "\n\t Router LSA Options: [%s]", bittok2str(ospf_rla_flag_values, "none", lsap->lsa_un.un_rla.rla_flags))); ND_TCHECK(lsap->lsa_un.un_rla.rla_count); j = EXTRACT_16BITS(&lsap->lsa_un.un_rla.rla_count); ND_TCHECK(lsap->lsa_un.un_rla.rla_link); rlp = lsap->lsa_un.un_rla.rla_link; while (j--) { ND_TCHECK(*rlp); switch (rlp->un_tos.link.link_type) { case RLA_TYPE_VIRTUAL: ND_PRINT((ndo, "\n\t Virtual Link: Neighbor Router-ID: %s, Interface Address: %s", ipaddr_string(ndo, &rlp->link_id), ipaddr_string(ndo, &rlp->link_data))); break; case RLA_TYPE_ROUTER: ND_PRINT((ndo, "\n\t Neighbor Router-ID: %s, Interface Address: %s", ipaddr_string(ndo, &rlp->link_id), ipaddr_string(ndo, &rlp->link_data))); break; case RLA_TYPE_TRANSIT: ND_PRINT((ndo, "\n\t Neighbor Network-ID: %s, Interface Address: %s", ipaddr_string(ndo, &rlp->link_id), ipaddr_string(ndo, &rlp->link_data))); break; case RLA_TYPE_STUB: ND_PRINT((ndo, "\n\t Stub Network: %s, Mask: %s", ipaddr_string(ndo, &rlp->link_id), ipaddr_string(ndo, &rlp->link_data))); break; default: ND_PRINT((ndo, "\n\t Unknown Router Link Type (%u)", rlp->un_tos.link.link_type)); return (ls_end); } ospf_print_tos_metrics(ndo, &rlp->un_tos); rlp = (struct rlalink *)((u_char *)(rlp + 1) + ((rlp->un_tos.link.link_tos_count) * sizeof(union un_tos))); } break; case LS_TYPE_NETWORK: ND_TCHECK(lsap->lsa_un.un_nla.nla_mask); ND_PRINT((ndo, "\n\t Mask %s\n\t Connected Routers:", ipaddr_string(ndo, &lsap->lsa_un.un_nla.nla_mask))); ap = lsap->lsa_un.un_nla.nla_router; while ((u_char *)ap < ls_end) { ND_TCHECK(*ap); ND_PRINT((ndo, "\n\t %s", ipaddr_string(ndo, ap))); ++ap; } break; case LS_TYPE_SUM_IP: ND_TCHECK(lsap->lsa_un.un_nla.nla_mask); ND_PRINT((ndo, "\n\t Mask %s", ipaddr_string(ndo, &lsap->lsa_un.un_sla.sla_mask))); ND_TCHECK(lsap->lsa_un.un_sla.sla_tosmetric); lp = lsap->lsa_un.un_sla.sla_tosmetric; while ((u_char *)lp < ls_end) { register uint32_t ul; ND_TCHECK(*lp); ul = EXTRACT_32BITS(lp); topology = (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS; ND_PRINT((ndo, "\n\t\ttopology %s(%u) metric %d", tok2str(ospf_topology_values, "", topology), topology, ul & SLA_MASK_METRIC)); ++lp; } break; case LS_TYPE_SUM_ABR: ND_TCHECK(lsap->lsa_un.un_sla.sla_tosmetric); lp = lsap->lsa_un.un_sla.sla_tosmetric; while ((u_char *)lp < ls_end) { register uint32_t ul; ND_TCHECK(*lp); ul = EXTRACT_32BITS(lp); topology = (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS; ND_PRINT((ndo, "\n\t\ttopology %s(%u) metric %d", tok2str(ospf_topology_values, "", topology), topology, ul & SLA_MASK_METRIC)); ++lp; } break; case LS_TYPE_ASE: case LS_TYPE_NSSA: /* fall through - those LSAs share the same format */ ND_TCHECK(lsap->lsa_un.un_nla.nla_mask); ND_PRINT((ndo, "\n\t Mask %s", ipaddr_string(ndo, &lsap->lsa_un.un_asla.asla_mask))); ND_TCHECK(lsap->lsa_un.un_sla.sla_tosmetric); almp = lsap->lsa_un.un_asla.asla_metric; while ((u_char *)almp < ls_end) { register uint32_t ul; ND_TCHECK(almp->asla_tosmetric); ul = EXTRACT_32BITS(&almp->asla_tosmetric); topology = ((ul & ASLA_MASK_TOS) >> ASLA_SHIFT_TOS); ND_PRINT((ndo, "\n\t\ttopology %s(%u), type %d, metric", tok2str(ospf_topology_values, "", topology), topology, (ul & ASLA_FLAG_EXTERNAL) ? 2 : 1)); if ((ul & ASLA_MASK_METRIC) == 0xffffff) ND_PRINT((ndo, " infinite")); else ND_PRINT((ndo, " %d", (ul & ASLA_MASK_METRIC))); ND_TCHECK(almp->asla_forward); if (almp->asla_forward.s_addr) { ND_PRINT((ndo, ", forward %s", ipaddr_string(ndo, &almp->asla_forward))); } ND_TCHECK(almp->asla_tag); if (almp->asla_tag.s_addr) { ND_PRINT((ndo, ", tag %s", ipaddr_string(ndo, &almp->asla_tag))); } ++almp; } break; case LS_TYPE_GROUP: /* Multicast extensions as of 23 July 1991 */ mcp = lsap->lsa_un.un_mcla; while ((u_char *)mcp < ls_end) { ND_TCHECK(mcp->mcla_vid); switch (EXTRACT_32BITS(&mcp->mcla_vtype)) { case MCLA_VERTEX_ROUTER: ND_PRINT((ndo, "\n\t Router Router-ID %s", ipaddr_string(ndo, &mcp->mcla_vid))); break; case MCLA_VERTEX_NETWORK: ND_PRINT((ndo, "\n\t Network Designated Router %s", ipaddr_string(ndo, &mcp->mcla_vid))); break; default: ND_PRINT((ndo, "\n\t unknown VertexType (%u)", EXTRACT_32BITS(&mcp->mcla_vtype))); break; } ++mcp; } break; case LS_TYPE_OPAQUE_LL: /* fall through */ case LS_TYPE_OPAQUE_AL: case LS_TYPE_OPAQUE_DW: switch (*(&lsap->ls_hdr.un_lsa_id.opaque_field.opaque_type)) { case LS_OPAQUE_TYPE_RI: tptr = (uint8_t *)(&lsap->lsa_un.un_ri_tlv.type); while (ls_length != 0) { ND_TCHECK2(*tptr, 4); if (ls_length < 4) { ND_PRINT((ndo, "\n\t Remaining LS length %u < 4", ls_length)); return(ls_end); } tlv_type = EXTRACT_16BITS(tptr); tlv_length = EXTRACT_16BITS(tptr+2); tptr+=4; ls_length-=4; ND_PRINT((ndo, "\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) { ND_PRINT((ndo, "\n\t Bogus length %u > %u", tlv_length, ls_length)); return(ls_end); } ND_TCHECK2(*tptr, tlv_length); switch(tlv_type) { case LS_OPAQUE_RI_TLV_CAP: if (tlv_length != 4) { ND_PRINT((ndo, "\n\t Bogus length %u != 4", tlv_length)); return(ls_end); } ND_PRINT((ndo, "Capabilities: %s", bittok2str(lsa_opaque_ri_tlv_cap_values, "Unknown", EXTRACT_32BITS(tptr)))); break; default: if (ndo->ndo_vflag <= 1) { if (!print_unknown_data(ndo, tptr, "\n\t ", tlv_length)) return(ls_end); } break; } tptr+=tlv_length; ls_length-=tlv_length; } break; case LS_OPAQUE_TYPE_GRACE: if (ospf_print_grace_lsa(ndo, (uint8_t *)(&lsap->lsa_un.un_grace_tlv.type), ls_length) == -1) { return(ls_end); } break; case LS_OPAQUE_TYPE_TE: if (ospf_print_te_lsa(ndo, (uint8_t *)(&lsap->lsa_un.un_te_lsa_tlv.type), ls_length) == -1) { return(ls_end); } break; default: if (ndo->ndo_vflag <= 1) { if (!print_unknown_data(ndo, (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, (uint8_t *)lsap->lsa_un.un_unknown, "\n\t ", ls_length)) { return(ls_end); } return (ls_end); trunc: return (NULL); } static int ospf_decode_lls(netdissect_options *ndo, register const struct ospfhdr *op, register u_int length) { register const u_char *dptr; register const u_char *dataend; register u_int length2; register uint16_t lls_type, lls_len; register uint32_t lls_flags; switch (op->ospf_type) { case OSPF_TYPE_HELLO: if (!(op->ospf_hello.hello_options & OSPF_OPTION_L)) return (0); break; case OSPF_TYPE_DD: if (!(op->ospf_db.db_options & OSPF_OPTION_L)) return (0); break; default: return (0); } /* dig deeper if LLS data is available; see RFC4813 */ length2 = EXTRACT_16BITS(&op->ospf_len); dptr = (u_char *)op + length2; dataend = (u_char *)op + length; if (EXTRACT_16BITS(&op->ospf_authtype) == OSPF_AUTH_MD5) { dptr = dptr + op->ospf_authdata[3]; length2 += op->ospf_authdata[3]; } if (length2 >= length) { ND_PRINT((ndo, "\n\t[LLS truncated]")); return (1); } ND_TCHECK2(*dptr, 2); ND_PRINT((ndo, "\n\t LLS: checksum: 0x%04x", (u_int)EXTRACT_16BITS(dptr))); dptr += 2; ND_TCHECK2(*dptr, 2); length2 = EXTRACT_16BITS(dptr); ND_PRINT((ndo, ", length: %u", length2)); dptr += 2; ND_TCHECK(*dptr); while (dptr < dataend) { ND_TCHECK2(*dptr, 2); lls_type = EXTRACT_16BITS(dptr); ND_PRINT((ndo, "\n\t %s (%u)", tok2str(ospf_lls_tlv_values,"Unknown TLV",lls_type), lls_type)); dptr += 2; ND_TCHECK2(*dptr, 2); lls_len = EXTRACT_16BITS(dptr); ND_PRINT((ndo, ", length: %u", lls_len)); dptr += 2; switch (lls_type) { case OSPF_LLS_EO: if (lls_len != 4) { ND_PRINT((ndo, " [should be 4]")); lls_len = 4; } ND_TCHECK2(*dptr, 4); lls_flags = EXTRACT_32BITS(dptr); ND_PRINT((ndo, "\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((ndo, " [should be 20]")); lls_len = 20; } ND_TCHECK2(*dptr, 4); ND_PRINT((ndo, "\n\t Sequence number: 0x%08x", EXTRACT_32BITS(dptr))); break; } dptr += lls_len; } return (0); trunc: return (1); } static int ospf_decode_v2(netdissect_options *ndo, register const struct ospfhdr *op, register const u_char *dataend) { register const struct in_addr *ap; register const struct lsr *lsrp; register const struct lsa_hdr *lshp; register const struct lsa *lsap; register uint32_t lsa_count,lsa_count_max; switch (op->ospf_type) { case OSPF_TYPE_UMD: /* * Rob Coltun's special monitoring packets; * do nothing */ break; case OSPF_TYPE_HELLO: ND_PRINT((ndo, "\n\tOptions [%s]", bittok2str(ospf_option_values,"none",op->ospf_hello.hello_options))); ND_TCHECK(op->ospf_hello.hello_deadint); ND_PRINT((ndo, "\n\t Hello Timer %us, Dead Timer %us, Mask %s, Priority %u", EXTRACT_16BITS(&op->ospf_hello.hello_helloint), EXTRACT_32BITS(&op->ospf_hello.hello_deadint), ipaddr_string(ndo, &op->ospf_hello.hello_mask), op->ospf_hello.hello_priority)); ND_TCHECK(op->ospf_hello.hello_dr); if (op->ospf_hello.hello_dr.s_addr != 0) ND_PRINT((ndo, "\n\t Designated Router %s", ipaddr_string(ndo, &op->ospf_hello.hello_dr))); ND_TCHECK(op->ospf_hello.hello_bdr); if (op->ospf_hello.hello_bdr.s_addr != 0) ND_PRINT((ndo, ", Backup Designated Router %s", ipaddr_string(ndo, &op->ospf_hello.hello_bdr))); ap = op->ospf_hello.hello_neighbor; if ((u_char *)ap < dataend) ND_PRINT((ndo, "\n\t Neighbor List:")); while ((u_char *)ap < dataend) { ND_TCHECK(*ap); ND_PRINT((ndo, "\n\t %s", ipaddr_string(ndo, ap))); ++ap; } break; /* HELLO */ case OSPF_TYPE_DD: ND_TCHECK(op->ospf_db.db_options); ND_PRINT((ndo, "\n\tOptions [%s]", bittok2str(ospf_option_values, "none", op->ospf_db.db_options))); ND_TCHECK(op->ospf_db.db_flags); ND_PRINT((ndo, ", DD Flags [%s]", bittok2str(ospf_dd_flag_values, "none", op->ospf_db.db_flags))); ND_TCHECK(op->ospf_db.db_ifmtu); if (op->ospf_db.db_ifmtu) { ND_PRINT((ndo, ", MTU: %u", EXTRACT_16BITS(&op->ospf_db.db_ifmtu))); } ND_TCHECK(op->ospf_db.db_seq); ND_PRINT((ndo, ", Sequence: 0x%08x", EXTRACT_32BITS(&op->ospf_db.db_seq))); /* Print all the LS adv's */ lshp = op->ospf_db.db_lshdr; while (((u_char *)lshp < dataend) && ospf_print_lshdr(ndo, lshp) != -1) { ++lshp; } break; case OSPF_TYPE_LS_REQ: lsrp = op->ospf_lsr; while ((u_char *)lsrp < dataend) { ND_TCHECK(*lsrp); ND_PRINT((ndo, "\n\t Advertising Router: %s, %s LSA (%u)", ipaddr_string(ndo, &lsrp->ls_router), tok2str(lsa_values,"unknown",EXTRACT_32BITS(lsrp->ls_type)), EXTRACT_32BITS(&lsrp->ls_type))); switch (EXTRACT_32BITS(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((ndo, ", Opaque-Type: %s LSA (%u), Opaque-ID: %u", tok2str(lsa_opaque_values, "unknown",lsrp->un_ls_stateid.opaque_field.opaque_type), lsrp->un_ls_stateid.opaque_field.opaque_type, EXTRACT_24BITS(&lsrp->un_ls_stateid.opaque_field.opaque_id))); break; default: ND_PRINT((ndo, ", LSA-ID: %s", ipaddr_string(ndo, &lsrp->un_ls_stateid.ls_stateid))); break; } ++lsrp; } break; case OSPF_TYPE_LS_UPDATE: lsap = op->ospf_lsu.lsu_lsa; ND_TCHECK(op->ospf_lsu.lsu_count); lsa_count_max = EXTRACT_32BITS(&op->ospf_lsu.lsu_count); ND_PRINT((ndo, ", %d LSA%s", lsa_count_max, PLURAL_SUFFIX(lsa_count_max))); for (lsa_count=1;lsa_count <= lsa_count_max;lsa_count++) { ND_PRINT((ndo, "\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) { ++lshp; } break; default: break; } return (0); trunc: return (1); } void ospf_print(netdissect_options *ndo, register const u_char *bp, register u_int length, const u_char *bp2 _U_) { register const struct ospfhdr *op; register const u_char *dataend; register const char *cp; op = (struct ospfhdr *)bp; /* XXX Before we do anything else, strip off the MD5 trailer */ ND_TCHECK(op->ospf_authtype); if (EXTRACT_16BITS(&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 */ ND_TCHECK(op->ospf_type); cp = tok2str(type2str, "unknown LS-type", op->ospf_type); ND_PRINT((ndo, "OSPFv%u, %s, length %u", op->ospf_version, cp, length)); if (*cp == 'u') return; if (!ndo->ndo_vflag) { /* non verbose - so lets bail out here */ return; } ND_TCHECK(op->ospf_len); if (length != EXTRACT_16BITS(&op->ospf_len)) { ND_PRINT((ndo, " [len %d]", EXTRACT_16BITS(&op->ospf_len))); } if (length > EXTRACT_16BITS(&op->ospf_len)) { dataend = bp + EXTRACT_16BITS(&op->ospf_len); } else { dataend = bp + length; } ND_TCHECK(op->ospf_routerid); ND_PRINT((ndo, "\n\tRouter-ID %s", ipaddr_string(ndo, &op->ospf_routerid))); ND_TCHECK(op->ospf_areaid); if (op->ospf_areaid.s_addr != 0) ND_PRINT((ndo, ", Area %s", ipaddr_string(ndo, &op->ospf_areaid))); else ND_PRINT((ndo, ", Backbone Area")); if (ndo->ndo_vflag) { /* Print authentication data (should we really do this?) */ ND_TCHECK2(op->ospf_authdata[0], sizeof(op->ospf_authdata)); ND_PRINT((ndo, ", Authentication Type: %s (%u)", tok2str(ospf_authtype_values, "unknown", EXTRACT_16BITS(&op->ospf_authtype)), EXTRACT_16BITS(&op->ospf_authtype))); switch (EXTRACT_16BITS(&op->ospf_authtype)) { case OSPF_AUTH_NONE: break; case OSPF_AUTH_SIMPLE: ND_PRINT((ndo, "\n\tSimple text password: ")); safeputs(ndo, op->ospf_authdata, OSPF_AUTH_SIMPLE_LEN); break; case OSPF_AUTH_MD5: ND_PRINT((ndo, "\n\tKey-ID: %u, Auth-Length: %u, Crypto Sequence Number: 0x%08x", *((op->ospf_authdata) + 2), *((op->ospf_authdata) + 3), EXTRACT_32BITS((op->ospf_authdata) + 4))); break; default: return; } } /* Do rest according to version. */ switch (op->ospf_version) { case 2: /* ospf version 2 */ if (ospf_decode_v2(ndo, op, dataend)) goto trunc; if (length > EXTRACT_16BITS(&op->ospf_len)) { if (ospf_decode_lls(ndo, op, length)) goto trunc; } break; default: ND_PRINT((ndo, " ospf [version %d]", op->ospf_version)); break; } /* end switch on version */ return; trunc: ND_PRINT((ndo, "%s", tstr)); } Index: head/contrib/tcpdump/print-pflog.c =================================================================== --- head/contrib/tcpdump/print-pflog.c (revision 285274) +++ head/contrib/tcpdump/print-pflog.c (revision 285275) @@ -1,183 +1,185 @@ /* * 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. */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifndef HAVE_NET_PFVAR_H #error "No pf headers available" #endif #include #include #include #include #include #include #include "interface.h" #include "extract.h" static const char tstr[] = "[|pflog]"; static const struct tok pf_reasons[] = { { 0, "0(match)" }, { 1, "1(bad-offset)" }, { 2, "2(fragment)" }, { 3, "3(short)" }, { 4, "4(normalize)" }, { 5, "5(memory)" }, { 6, "6(bad-timestamp)" }, { 7, "7(congestion)" }, { 8, "8(ip-option)" }, { 9, "9(proto-cksum)" }, { 10, "10(state-mismatch)" }, { 11, "11(state-insert)" }, { 12, "12(state-limit)" }, { 13, "13(src-limit)" }, { 14, "14(synproxy)" }, { 0, NULL } }; static const struct tok pf_actions[] = { { PF_PASS, "pass" }, { PF_DROP, "block" }, { PF_SCRUB, "scrub" }, { PF_NAT, "nat" }, { PF_NONAT, "nat" }, { PF_BINAT, "binat" }, { PF_NOBINAT, "binat" }, { PF_RDR, "rdr" }, { PF_NORDR, "rdr" }, { PF_SYNPROXY_DROP, "synproxy-drop" }, { 0, NULL } }; static const struct tok pf_directions[] = { { PF_INOUT, "in/out" }, { PF_IN, "in" }, { PF_OUT, "out" }, { 0, NULL } }; /* For reading capture files on other systems */ #define OPENBSD_AF_INET 2 #define OPENBSD_AF_INET6 24 static void pflog_print(netdissect_options *ndo, const struct pfloghdr *hdr) { uint32_t rulenr, subrulenr; rulenr = EXTRACT_32BITS(&hdr->rulenr); subrulenr = EXTRACT_32BITS(&hdr->subrulenr); if (subrulenr == (uint32_t)-1) ND_PRINT((ndo, "rule %u/", rulenr)); else ND_PRINT((ndo, "rule %u.%s.%u/", rulenr, hdr->ruleset, subrulenr)); ND_PRINT((ndo, "%s: %s %s on %s: ", tok2str(pf_reasons, "unkn(%u)", hdr->reason), tok2str(pf_actions, "unkn(%u)", hdr->action), tok2str(pf_directions, "unkn(%u)", hdr->dir), hdr->ifname)); } u_int pflog_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, register const u_char *p) { u_int length = h->len; u_int hdrlen; u_int caplen = h->caplen; const struct pfloghdr *hdr; uint8_t af; /* check length */ if (caplen < sizeof(uint8_t)) { ND_PRINT((ndo, "%s", tstr)); return (caplen); } #define MIN_PFLOG_HDRLEN 45 hdr = (struct pfloghdr *)p; if (hdr->length < MIN_PFLOG_HDRLEN) { ND_PRINT((ndo, "[pflog: invalid header length!]")); return (hdr->length); /* XXX: not really */ } hdrlen = BPF_WORDALIGN(hdr->length); if (caplen < hdrlen) { ND_PRINT((ndo, "%s", tstr)); return (hdrlen); /* XXX: true? */ } /* print what we know */ hdr = (struct pfloghdr *)p; ND_TCHECK(*hdr); if (ndo->ndo_eflag) pflog_print(ndo, hdr); /* skip to the real packet */ af = hdr->af; length -= hdrlen; caplen -= hdrlen; p += hdrlen; switch (af) { case AF_INET: #if OPENBSD_AF_INET != AF_INET case OPENBSD_AF_INET: /* XXX: read pcap files */ #endif ip_print(ndo, p, length); break; -#ifdef INET6 +#if defined(AF_INET6) || defined(OPENBSD_AF_INET6) +#ifdef AF_INET6 case AF_INET6: -#if OPENBSD_AF_INET6 != AF_INET6 +#endif /* AF_INET6 */ +#if !defined(AF_INET6) || OPENBSD_AF_INET6 != AF_INET6 case OPENBSD_AF_INET6: /* XXX: read pcap files */ -#endif +#endif /* !defined(AF_INET6) || OPENBSD_AF_INET6 != AF_INET6 */ ip6_print(ndo, p, length); break; -#endif +#endif /* defined(AF_INET6) || defined(OPENBSD_AF_INET6) */ 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); } return (hdrlen); trunc: ND_PRINT((ndo, "%s", tstr)); return (hdrlen); } /* * Local Variables: * c-style: whitesmith * c-basic-offset: 8 * End: */ Index: head/contrib/tcpdump/print-pim.c =================================================================== --- head/contrib/tcpdump/print-pim.c (revision 285274) +++ head/contrib/tcpdump/print-pim.c (revision 285275) @@ -1,1095 +1,1095 @@ /* * 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. * * $FreeBSD$ */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "interface.h" #include "addrtoname.h" #include "extract.h" #include "ip.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} }; /* * XXX: We consider a case where IPv6 is not ready yet for portability, * but PIM dependent defintions should be independent of IPv6... */ struct pim { 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) u_char pim_rsv; /* Reserved */ u_short pim_cksum; /* IP style check sum */ }; static void pimv2_print(netdissect_options *, register const u_char *bp, register u_int len, u_int cksum); static void pimv1_join_prune_print(netdissect_options *ndo, register const u_char *bp, register u_int len) { int ngroups, njoin, nprune; int njp; /* If it's a single group and a single source, use 1-line output. */ if (ND_TTEST2(bp[0], 30) && bp[11] == 1 && ((njoin = EXTRACT_16BITS(&bp[20])) + EXTRACT_16BITS(&bp[22])) == 1) { int hold; ND_PRINT((ndo, " RPF %s ", ipaddr_string(ndo, bp))); hold = EXTRACT_16BITS(&bp[6]); if (hold != 180) { ND_PRINT((ndo, "Hold ")); relts_print(ndo, hold); } ND_PRINT((ndo, "%s (%s/%d, %s", njoin ? "Join" : "Prune", ipaddr_string(ndo, &bp[26]), bp[25] & 0x3f, ipaddr_string(ndo, &bp[12]))); if (EXTRACT_32BITS(&bp[16]) != 0xffffffff) ND_PRINT((ndo, "/%s", ipaddr_string(ndo, &bp[16]))); ND_PRINT((ndo, ") %s%s %s", (bp[24] & 0x01) ? "Sparse" : "Dense", (bp[25] & 0x80) ? " WC" : "", (bp[25] & 0x40) ? "RP" : "SPT")); return; } ND_TCHECK2(bp[0], sizeof(struct in_addr)); if (ndo->ndo_vflag > 1) ND_PRINT((ndo, "\n")); ND_PRINT((ndo, " Upstream Nbr: %s", ipaddr_string(ndo, bp))); ND_TCHECK2(bp[6], 2); if (ndo->ndo_vflag > 1) ND_PRINT((ndo, "\n")); ND_PRINT((ndo, " Hold time: ")); relts_print(ndo, EXTRACT_16BITS(&bp[6])); if (ndo->ndo_vflag < 2) return; bp += 8; len -= 8; ND_TCHECK2(bp[0], 4); ngroups = bp[3]; bp += 4; len -= 4; while (ngroups--) { /* * XXX - does the address have length "addrlen" and the * mask length "maddrlen"? */ ND_TCHECK2(bp[0], sizeof(struct in_addr)); ND_PRINT((ndo, "\n\tGroup: %s", ipaddr_string(ndo, bp))); ND_TCHECK2(bp[4], sizeof(struct in_addr)); if (EXTRACT_32BITS(&bp[4]) != 0xffffffff) ND_PRINT((ndo, "/%s", ipaddr_string(ndo, &bp[4]))); ND_TCHECK2(bp[8], 4); njoin = EXTRACT_16BITS(&bp[8]); nprune = EXTRACT_16BITS(&bp[10]); ND_PRINT((ndo, " joined: %d pruned: %d", njoin, nprune)); bp += 12; len -= 12; for (njp = 0; njp < (njoin + nprune); njp++) { const char *type; if (njp < njoin) type = "Join "; else type = "Prune"; ND_TCHECK2(bp[0], 6); ND_PRINT((ndo, "\n\t%s %s%s%s%s/%d", type, (bp[0] & 0x01) ? "Sparse " : "Dense ", (bp[1] & 0x80) ? "WC " : "", (bp[1] & 0x40) ? "RP " : "SPT ", ipaddr_string(ndo, &bp[2]), bp[1] & 0x3f)); bp += 6; len -= 6; } } return; trunc: ND_PRINT((ndo, "[|pim]")); return; } void pimv1_print(netdissect_options *ndo, register const u_char *bp, register u_int len) { register const u_char *ep; register u_char type; ep = (const u_char *)ndo->ndo_snapend; if (bp >= ep) return; ND_TCHECK(bp[1]); type = bp[1]; ND_PRINT((ndo, " %s", tok2str(pimv1_type_str, "[type %u]", type))); switch (type) { case PIMV1_TYPE_QUERY: if (ND_TTEST(bp[8])) { switch (bp[8] >> 4) { case 0: ND_PRINT((ndo, " Dense-mode")); break; case 1: ND_PRINT((ndo, " Sparse-mode")); break; case 2: ND_PRINT((ndo, " Sparse-Dense-mode")); break; default: ND_PRINT((ndo, " mode-%d", bp[8] >> 4)); break; } } if (ndo->ndo_vflag) { ND_TCHECK2(bp[10],2); ND_PRINT((ndo, " (Hold-time ")); relts_print(ndo, EXTRACT_16BITS(&bp[10])); ND_PRINT((ndo, ")")); } break; case PIMV1_TYPE_REGISTER: ND_TCHECK2(bp[8], 20); /* ip header */ ND_PRINT((ndo, " for %s > %s", ipaddr_string(ndo, &bp[20]), ipaddr_string(ndo, &bp[24]))); break; case PIMV1_TYPE_REGISTER_STOP: ND_TCHECK2(bp[12], sizeof(struct in_addr)); ND_PRINT((ndo, " for %s > %s", ipaddr_string(ndo, &bp[8]), ipaddr_string(ndo, &bp[12]))); break; case PIMV1_TYPE_RP_REACHABILITY: if (ndo->ndo_vflag) { ND_TCHECK2(bp[22], 2); ND_PRINT((ndo, " group %s", ipaddr_string(ndo, &bp[8]))); if (EXTRACT_32BITS(&bp[12]) != 0xffffffff) ND_PRINT((ndo, "/%s", ipaddr_string(ndo, &bp[12]))); ND_PRINT((ndo, " RP %s hold ", ipaddr_string(ndo, &bp[16]))); relts_print(ndo, EXTRACT_16BITS(&bp[22])); } break; case PIMV1_TYPE_ASSERT: ND_TCHECK2(bp[16], sizeof(struct in_addr)); ND_PRINT((ndo, " for %s > %s", ipaddr_string(ndo, &bp[16]), ipaddr_string(ndo, &bp[8]))); if (EXTRACT_32BITS(&bp[12]) != 0xffffffff) ND_PRINT((ndo, "/%s", ipaddr_string(ndo, &bp[12]))); ND_TCHECK2(bp[24], 4); ND_PRINT((ndo, " %s pref %d metric %d", (bp[20] & 0x80) ? "RP-tree" : "SPT", EXTRACT_32BITS(&bp[20]) & 0x7fffffff, EXTRACT_32BITS(&bp[24]))); break; case PIMV1_TYPE_JOIN_PRUNE: case PIMV1_TYPE_GRAFT: case PIMV1_TYPE_GRAFT_ACK: if (ndo->ndo_vflag) pimv1_join_prune_print(ndo, &bp[8], len - 8); break; } if ((bp[4] >> 4) != 1) ND_PRINT((ndo, " [v%d]", bp[4] >> 4)); return; trunc: ND_PRINT((ndo, "[|pim]")); return; } /* * 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, register const u_char *bp, register u_int len) { int type; int numrps; int hold; ND_TCHECK(bp[0]); ND_PRINT((ndo, " auto-rp ")); type = bp[0]; switch (type) { case 0x11: ND_PRINT((ndo, "candidate-advert")); break; case 0x12: ND_PRINT((ndo, "mapping")); break; default: ND_PRINT((ndo, "type-0x%02x", type)); break; } ND_TCHECK(bp[1]); numrps = bp[1]; ND_TCHECK2(bp[2], 2); ND_PRINT((ndo, " Hold ")); hold = EXTRACT_16BITS(&bp[2]); if (hold) relts_print(ndo, EXTRACT_16BITS(&bp[2])); else ND_PRINT((ndo, "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--) { int nentries; char s; ND_TCHECK2(bp[0], 4); ND_PRINT((ndo, " RP %s", ipaddr_string(ndo, bp))); ND_TCHECK(bp[4]); switch (bp[4] & 0x3) { case 0: ND_PRINT((ndo, " PIMv?")); break; case 1: ND_PRINT((ndo, " PIMv1")); break; case 2: ND_PRINT((ndo, " PIMv2")); break; case 3: ND_PRINT((ndo, " PIMv1+2")); break; } if (bp[4] & 0xfc) ND_PRINT((ndo, " [rsvd=0x%02x]", bp[4] & 0xfc)); ND_TCHECK(bp[5]); nentries = bp[5]; bp += 6; len -= 6; s = ' '; for (; nentries; nentries--) { ND_TCHECK2(bp[0], 6); ND_PRINT((ndo, "%c%s%s/%d", s, bp[0] & 1 ? "!" : "", ipaddr_string(ndo, &bp[2]), bp[1])); if (bp[0] & 0x02) { ND_PRINT((ndo, " bidir")); } if (bp[0] & 0xfc) { ND_PRINT((ndo, "[rsvd=0x%02x]", bp[0] & 0xfc)); } s = ','; bp += 6; len -= 6; } } return; trunc: ND_PRINT((ndo, "[|autorp]")); return; } void pim_print(netdissect_options *ndo, register const u_char *bp, register u_int len, u_int cksum) { register const u_char *ep; register struct pim *pim = (struct pim *)bp; ep = (const u_char *)ndo->ndo_snapend; if (bp >= ep) return; #ifdef notyet /* currently we see only version and type */ ND_TCHECK(pim->pim_rsv); #endif switch (PIM_VER(pim->pim_typever)) { case 2: if (!ndo->ndo_vflag) { ND_PRINT((ndo, "PIMv%u, %s, length %u", PIM_VER(pim->pim_typever), tok2str(pimv2_type_values,"Unknown Type",PIM_TYPE(pim->pim_typever)), len)); return; } else { ND_PRINT((ndo, "PIMv%u, length %u\n\t%s", PIM_VER(pim->pim_typever), len, tok2str(pimv2_type_values,"Unknown Type",PIM_TYPE(pim->pim_typever)))); pimv2_print(ndo, bp, len, cksum); } break; default: ND_PRINT((ndo, "PIMv%u, length %u", PIM_VER(pim->pim_typever), len)); break; } return; } /* * 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. * */ static int pimv2_addr_len; 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, enum pimv2_addrtype at, int silent) { int af; int len, hdrlen; ND_TCHECK(bp[0]); if (pimv2_addr_len == 0) { ND_TCHECK(bp[1]); switch (bp[0]) { case 1: af = AF_INET; len = sizeof(struct in_addr); break; #ifdef INET6 case 2: af = AF_INET6; len = sizeof(struct in6_addr); break; #endif default: return -1; } if (bp[1] != 0) return -1; hdrlen = 2; } else { switch (pimv2_addr_len) { case sizeof(struct in_addr): af = AF_INET; break; #ifdef INET6 case sizeof(struct in6_addr): af = AF_INET6; break; #endif default: return -1; break; } len = pimv2_addr_len; hdrlen = 0; } bp += hdrlen; switch (at) { case pimv2_unicast: ND_TCHECK2(bp[0], len); if (af == AF_INET) { if (!silent) ND_PRINT((ndo, "%s", ipaddr_string(ndo, bp))); } #ifdef INET6 else if (af == AF_INET6) { if (!silent) ND_PRINT((ndo, "%s", ip6addr_string(ndo, bp))); } #endif return hdrlen + len; case pimv2_group: case pimv2_source: ND_TCHECK2(bp[0], len + 2); if (af == AF_INET) { if (!silent) { ND_PRINT((ndo, "%s", ipaddr_string(ndo, bp + 2))); if (bp[1] != 32) ND_PRINT((ndo, "/%u", bp[1])); } } #ifdef INET6 else if (af == AF_INET6) { if (!silent) { ND_PRINT((ndo, "%s", ip6addr_string(ndo, bp + 2))); if (bp[1] != 128) ND_PRINT((ndo, "/%u", bp[1])); } } #endif if (bp[0] && !silent) { if (at == pimv2_group) { ND_PRINT((ndo, "(0x%02x)", bp[0])); } else { ND_PRINT((ndo, "(%s%s%s", bp[0] & 0x04 ? "S" : "", bp[0] & 0x02 ? "W" : "", bp[0] & 0x01 ? "R" : "")); if (bp[0] & 0xf8) { ND_PRINT((ndo, "+0x%02x", bp[0] & 0xf8)); } ND_PRINT((ndo, ")")); } } return hdrlen + 2 + len; default: return -1; } trunc: return -1; } static void pimv2_print(netdissect_options *ndo, register const u_char *bp, register u_int len, u_int cksum) { register const u_char *ep; register struct pim *pim = (struct pim *)bp; int advance; ep = (const u_char *)ndo->ndo_snapend; if (bp >= ep) return; if (ep > bp + len) ep = bp + len; ND_TCHECK(pim->pim_rsv); pimv2_addr_len = pim->pim_rsv; if (pimv2_addr_len != 0) ND_PRINT((ndo, ", RFC2117-encoding")); ND_PRINT((ndo, ", cksum 0x%04x ", EXTRACT_16BITS(&pim->pim_cksum))); if (EXTRACT_16BITS(&pim->pim_cksum) == 0) { ND_PRINT((ndo, "(unverified)")); } else { ND_PRINT((ndo, "(%scorrect)", ND_TTEST2(bp[0], len) && cksum ? "in" : "" )); } switch (PIM_TYPE(pim->pim_typever)) { case PIMV2_TYPE_HELLO: { uint16_t otype, olen; bp += 4; while (bp < ep) { ND_TCHECK2(bp[0], 4); otype = EXTRACT_16BITS(&bp[0]); olen = EXTRACT_16BITS(&bp[2]); ND_TCHECK2(bp[0], 4 + olen); ND_PRINT((ndo, "\n\t %s Option (%u), length %u, Value: ", tok2str(pimv2_hello_option_values, "Unknown", otype), otype, olen)); bp += 4; switch (otype) { case PIMV2_HELLO_OPTION_HOLDTIME: relts_print(ndo, EXTRACT_16BITS(bp)); break; case PIMV2_HELLO_OPTION_LANPRUNEDELAY: if (olen != 4) { ND_PRINT((ndo, "ERROR: Option Length != 4 Bytes (%u)", olen)); } else { char t_bit; uint16_t lan_delay, override_interval; lan_delay = EXTRACT_16BITS(bp); override_interval = EXTRACT_16BITS(bp+2); t_bit = (lan_delay & 0x8000)? 1 : 0; lan_delay &= ~0x8000; ND_PRINT((ndo, "\n\t T-bit=%d, LAN delay %dms, Override interval %dms", 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((ndo, "Bi-Directional Capability (Old)")); break; case 4: ND_PRINT((ndo, "%u", EXTRACT_32BITS(bp))); break; default: ND_PRINT((ndo, "ERROR: Option Length != 4 Bytes (%u)", olen)); break; } break; case PIMV2_HELLO_OPTION_GENID: ND_PRINT((ndo, "0x%08x", EXTRACT_32BITS(bp))); break; case PIMV2_HELLO_OPTION_REFRESH_CAP: ND_PRINT((ndo, "v%d", *bp)); if (*(bp+1) != 0) { ND_PRINT((ndo, ", interval ")); relts_print(ndo, *(bp+1)); } if (EXTRACT_16BITS(bp+2) != 0) { ND_PRINT((ndo, " ?0x%04x?", EXTRACT_16BITS(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; while (ptr < (bp+olen)) { int advance; ND_PRINT((ndo, "\n\t ")); advance = pimv2_addr_print(ndo, ptr, pimv2_unicast, 0); if (advance < 0) { ND_PRINT((ndo, "...")); break; } ptr += 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; } break; } case PIMV2_TYPE_REGISTER: { struct ip *ip; ND_TCHECK2(*(bp + 4), PIMV2_REGISTER_FLAG_LEN); ND_PRINT((ndo, ", Flags [ %s ]\n\t", tok2str(pimv2_register_flag_values, "none", EXTRACT_32BITS(bp+4)))); bp += 8; len -= 8; /* encapsulated multicast packet */ ip = (struct ip *)bp; switch (IP_V(ip)) { case 0: /* Null header */ ND_PRINT((ndo, "IP-Null-header %s > %s", ipaddr_string(ndo, &ip->ip_src), ipaddr_string(ndo, &ip->ip_dst))); break; case 4: /* IPv4 */ ip_print(ndo, bp, len); break; -#ifdef INET6 + case 6: /* IPv6 */ ip6_print(ndo, bp, len); break; -#endif + default: ND_PRINT((ndo, "IP ver %d", IP_V(ip))); break; } break; } case PIMV2_TYPE_REGISTER_STOP: bp += 4; len -= 4; if (bp >= ep) break; ND_PRINT((ndo, " group=")); if ((advance = pimv2_addr_print(ndo, bp, pimv2_group, 0)) < 0) { ND_PRINT((ndo, "...")); break; } bp += advance; len -= advance; if (bp >= ep) break; ND_PRINT((ndo, " source=")); if ((advance = pimv2_addr_print(ndo, bp, pimv2_unicast, 0)) < 0) { ND_PRINT((ndo, "...")); break; } 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; int i, j; bp += 4; len -= 4; if (PIM_TYPE(pim->pim_typever) != 7) { /*not for Graft-ACK*/ if (bp >= ep) break; ND_PRINT((ndo, ", upstream-neighbor: ")); if ((advance = pimv2_addr_print(ndo, bp, pimv2_unicast, 0)) < 0) { ND_PRINT((ndo, "...")); break; } bp += advance; len -= advance; } if (bp + 4 > ep) break; ngroup = bp[1]; holdtime = EXTRACT_16BITS(&bp[2]); ND_PRINT((ndo, "\n\t %u group(s)", ngroup)); if (PIM_TYPE(pim->pim_typever) != 7) { /*not for Graft-ACK*/ ND_PRINT((ndo, ", holdtime: ")); if (holdtime == 0xffff) ND_PRINT((ndo, "infinite")); else relts_print(ndo, holdtime); } bp += 4; len -= 4; for (i = 0; i < ngroup; i++) { if (bp >= ep) goto jp_done; ND_PRINT((ndo, "\n\t group #%u: ", i+1)); if ((advance = pimv2_addr_print(ndo, bp, pimv2_group, 0)) < 0) { ND_PRINT((ndo, "...)")); goto jp_done; } bp += advance; len -= advance; if (bp + 4 > ep) { ND_PRINT((ndo, "...)")); goto jp_done; } njoin = EXTRACT_16BITS(&bp[0]); nprune = EXTRACT_16BITS(&bp[2]); ND_PRINT((ndo, ", joined sources: %u, pruned sources: %u", njoin, nprune)); bp += 4; len -= 4; for (j = 0; j < njoin; j++) { ND_PRINT((ndo, "\n\t joined source #%u: ", j+1)); if ((advance = pimv2_addr_print(ndo, bp, pimv2_source, 0)) < 0) { ND_PRINT((ndo, "...)")); goto jp_done; } bp += advance; len -= advance; } for (j = 0; j < nprune; j++) { ND_PRINT((ndo, "\n\t pruned source #%u: ", j+1)); if ((advance = pimv2_addr_print(ndo, bp, pimv2_source, 0)) < 0) { ND_PRINT((ndo, "...)")); goto jp_done; } bp += advance; len -= advance; } } jp_done: break; } case PIMV2_TYPE_BOOTSTRAP: { int i, j, frpcnt; bp += 4; /* Fragment Tag, Hash Mask len, and BSR-priority */ if (bp + sizeof(uint16_t) >= ep) break; ND_PRINT((ndo, " tag=%x", EXTRACT_16BITS(bp))); bp += sizeof(uint16_t); if (bp >= ep) break; ND_PRINT((ndo, " hashmlen=%d", bp[0])); if (bp + 1 >= ep) break; ND_PRINT((ndo, " BSRprio=%d", bp[1])); bp += 2; /* Encoded-Unicast-BSR-Address */ if (bp >= ep) break; ND_PRINT((ndo, " BSR=")); if ((advance = pimv2_addr_print(ndo, bp, pimv2_unicast, 0)) < 0) { ND_PRINT((ndo, "...")); break; } bp += advance; for (i = 0; bp < ep; i++) { /* Encoded-Group Address */ ND_PRINT((ndo, " (group%d: ", i)); if ((advance = pimv2_addr_print(ndo, bp, pimv2_group, 0)) < 0) { ND_PRINT((ndo, "...)")); goto bs_done; } bp += advance; /* RP-Count, Frag RP-Cnt, and rsvd */ if (bp >= ep) { ND_PRINT((ndo, "...)")); goto bs_done; } ND_PRINT((ndo, " RPcnt=%d", bp[0])); if (bp + 1 >= ep) { ND_PRINT((ndo, "...)")); goto bs_done; } ND_PRINT((ndo, " FRPcnt=%d", frpcnt = bp[1])); bp += 4; for (j = 0; j < frpcnt && bp < ep; j++) { /* each RP info */ ND_PRINT((ndo, " RP%d=", j)); if ((advance = pimv2_addr_print(ndo, bp, pimv2_unicast, 0)) < 0) { ND_PRINT((ndo, "...)")); goto bs_done; } bp += advance; if (bp + 1 >= ep) { ND_PRINT((ndo, "...)")); goto bs_done; } ND_PRINT((ndo, ",holdtime=")); relts_print(ndo, EXTRACT_16BITS(bp)); if (bp + 2 >= ep) { ND_PRINT((ndo, "...)")); goto bs_done; } ND_PRINT((ndo, ",prio=%d", bp[2])); bp += 4; } ND_PRINT((ndo, ")")); } bs_done: break; } case PIMV2_TYPE_ASSERT: bp += 4; len -= 4; if (bp >= ep) break; ND_PRINT((ndo, " group=")); if ((advance = pimv2_addr_print(ndo, bp, pimv2_group, 0)) < 0) { ND_PRINT((ndo, "...")); break; } bp += advance; len -= advance; if (bp >= ep) break; ND_PRINT((ndo, " src=")); if ((advance = pimv2_addr_print(ndo, bp, pimv2_unicast, 0)) < 0) { ND_PRINT((ndo, "...")); break; } bp += advance; len -= advance; if (bp + 8 > ep) break; if (bp[0] & 0x80) ND_PRINT((ndo, " RPT")); ND_PRINT((ndo, " pref=%u", EXTRACT_32BITS(&bp[0]) & 0x7fffffff)); ND_PRINT((ndo, " metric=%u", EXTRACT_32BITS(&bp[4]))); break; case PIMV2_TYPE_CANDIDATE_RP: { int i, pfxcnt; bp += 4; /* Prefix-Cnt, Priority, and Holdtime */ if (bp >= ep) break; ND_PRINT((ndo, " prefix-cnt=%d", bp[0])); pfxcnt = bp[0]; if (bp + 1 >= ep) break; ND_PRINT((ndo, " prio=%d", bp[1])); if (bp + 3 >= ep) break; ND_PRINT((ndo, " holdtime=")); relts_print(ndo, EXTRACT_16BITS(&bp[2])); bp += 4; /* Encoded-Unicast-RP-Address */ if (bp >= ep) break; ND_PRINT((ndo, " RP=")); if ((advance = pimv2_addr_print(ndo, bp, pimv2_unicast, 0)) < 0) { ND_PRINT((ndo, "...")); break; } bp += advance; /* Encoded-Group Addresses */ for (i = 0; i < pfxcnt && bp < ep; i++) { ND_PRINT((ndo, " Group%d=", i)); if ((advance = pimv2_addr_print(ndo, bp, pimv2_group, 0)) < 0) { ND_PRINT((ndo, "...")); break; } bp += advance; } break; } case PIMV2_TYPE_PRUNE_REFRESH: ND_PRINT((ndo, " src=")); if ((advance = pimv2_addr_print(ndo, bp, pimv2_unicast, 0)) < 0) { ND_PRINT((ndo, "...")); break; } bp += advance; ND_PRINT((ndo, " grp=")); if ((advance = pimv2_addr_print(ndo, bp, pimv2_group, 0)) < 0) { ND_PRINT((ndo, "...")); break; } bp += advance; ND_PRINT((ndo, " forwarder=")); if ((advance = pimv2_addr_print(ndo, bp, pimv2_unicast, 0)) < 0) { ND_PRINT((ndo, "...")); break; } bp += advance; ND_TCHECK2(bp[0], 2); ND_PRINT((ndo, " TUNR ")); relts_print(ndo, EXTRACT_16BITS(bp)); break; default: ND_PRINT((ndo, " [type %d]", PIM_TYPE(pim->pim_typever))); break; } return; trunc: ND_PRINT((ndo, "[|pim]")); } /* * Local Variables: * c-style: whitesmith * c-basic-offset: 8 * End: */ Index: head/contrib/tcpdump/print-ppi.c =================================================================== --- head/contrib/tcpdump/print-ppi.c (revision 285274) +++ head/contrib/tcpdump/print-ppi.c (revision 285275) @@ -1,109 +1,119 @@ /* * Oracle */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "interface.h" #include "extract.h" typedef struct ppi_header { uint8_t ppi_ver; uint8_t ppi_flags; uint16_t ppi_len; uint32_t ppi_dlt; } ppi_header_t; #define PPI_HDRLEN 8 #ifdef DLT_PPI static inline void ppi_header_print(netdissect_options *ndo, const u_char *bp, u_int length) { const ppi_header_t *hdr; - uint32_t dlt; uint16_t len; + uint32_t dlt; hdr = (const ppi_header_t *)bp; len = EXTRACT_LE_16BITS(&hdr->ppi_len); dlt = EXTRACT_LE_32BITS(&hdr->ppi_dlt); if (!ndo->ndo_qflag) { - ND_PRINT((ndo,", V.%d DLT %s (%d) len %d", hdr->ppi_ver, + ND_PRINT((ndo, "V.%d DLT %s (%d) len %d", hdr->ppi_ver, pcap_datalink_val_to_name(dlt), dlt, len)); } else { - ND_PRINT((ndo,", %s", pcap_datalink_val_to_name(dlt))); + ND_PRINT((ndo, "%s", pcap_datalink_val_to_name(dlt))); } ND_PRINT((ndo, ", length %u: ", length)); } static void ppi_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { if_ndo_printer ndo_printer; if_printer printer; ppi_header_t *hdr; u_int caplen = h->caplen; u_int length = h->len; + uint16_t len; uint32_t dlt; if (caplen < sizeof(ppi_header_t)) { ND_PRINT((ndo, "[|ppi]")); return; } + hdr = (ppi_header_t *)p; + len = EXTRACT_LE_16BITS(&hdr->ppi_len); + if (len < sizeof(ppi_header_t)) { + ND_PRINT((ndo, "[|ppi]")); + return; + } + if (caplen < len) { + ND_PRINT((ndo, "[|ppi]")); + return; + } dlt = EXTRACT_LE_32BITS(&hdr->ppi_dlt); if (ndo->ndo_eflag) ppi_header_print(ndo, p, length); - length -= sizeof(ppi_header_t); - caplen -= sizeof(ppi_header_t); - p += sizeof(ppi_header_t); + length -= len; + caplen -= len; + p += len; if ((printer = lookup_printer(dlt)) != NULL) { printer(h, p); } else if ((ndo_printer = lookup_ndo_printer(dlt)) != NULL) { ndo_printer(ndo, h, p); } else { if (!ndo->ndo_eflag) - ppi_header_print(ndo, (u_char *)hdr, - length + sizeof(ppi_header_t)); + ppi_header_print(ndo, (u_char *)hdr, length + len); 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. */ u_int ppi_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { ppi_print(ndo, h, p); return (sizeof(ppi_header_t)); } /* * Local Variables: * c-style: whitesmith * c-basic-offset: 8 * End: */ #endif /* DLT_PPI */ Index: head/contrib/tcpdump/print-ppp.c =================================================================== --- head/contrib/tcpdump/print-ppp.c (revision 285274) +++ head/contrib/tcpdump/print-ppp.c (revision 285275) @@ -1,1863 +1,1853 @@ /* * 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. * * $FreeBSD$ */ /* * TODO: * o resolve XXX as much as possible * o MP support * o BAP support */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #ifdef __bsdi__ #include #include #endif #include #include "interface.h" #include "extract.h" #include "addrtoname.h" #include "ppp.h" #include "chdlc.h" #include "ethertype.h" #include "oui.h" /* * The following constatns are defined by IANA. Please refer to * http://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 #define LCPOPT_MIN LCPOPT_VEXT #define LCPOPT_MAX LCPOPT_PPPMUX 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(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) */ }; /* 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 int print_lcp_config_options(netdissect_options *, const u_char *p, int); static int print_ipcp_config_options(netdissect_options *, const u_char *p, int); static int print_ip6cp_config_options(netdissect_options *, const u_char *p, int); static int print_ccp_config_options(netdissect_options *, const u_char *p, int); static int print_bacp_config_options(netdissect_options *, const u_char *p, int); static void handle_ppp(netdissect_options *, u_int proto, const u_char *p, 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, int length) { const char *typestr; u_int code, len; int (*pfunc)(netdissect_options *, const u_char *, int); int x, j; const u_char *tptr; tptr=pptr; typestr = tok2str(ppptype2str, "unknown ctrl-proto (0x%04x)", proto); ND_PRINT((ndo, "%s, ", typestr)); if (length < 4) /* FIXME weak boundary checking */ goto trunc; ND_TCHECK2(*tptr, 2); code = *tptr++; ND_PRINT((ndo, "%s (0x%02x), id %u, length %u", tok2str(cpcodes, "Unknown Opcode",code), code, *tptr++, /* ID */ length + 2)); if (!ndo->ndo_vflag) return; if (length <= 4) return; /* there may be a NULL confreq etc. */ ND_TCHECK2(*tptr, 2); len = EXTRACT_16BITS(tptr); tptr += 2; ND_PRINT((ndo, "\n\tencoded length %u (=Option(s) length %u)", len, len - 4)); if (ndo->ndo_vflag > 1) print_unknown_data(ndo, pptr - 2, "\n\t", 6); switch (code) { case CPCODES_VEXT: if (length < 11) break; ND_TCHECK2(*tptr, 4); ND_PRINT((ndo, "\n\t Magic-Num 0x%08x", EXTRACT_32BITS(tptr))); tptr += 4; ND_TCHECK2(*tptr, 3); ND_PRINT((ndo, " Vendor: %s (%u)", tok2str(oui_values,"Unknown",EXTRACT_24BITS(tptr)), EXTRACT_24BITS(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: x = 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 ((j = (*pfunc)(ndo, tptr, len)) == 0) break; x -= j; tptr += j; } while (x > 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_TCHECK2(*tptr, 2); ND_PRINT((ndo, "\n\t Rejected %s Protocol (0x%04x)", tok2str(ppptype2str,"unknown", EXTRACT_16BITS(tptr)), EXTRACT_16BITS(tptr))); /* XXX: need to decode Rejected-Information? - hexdump for now */ if (len > 6) { ND_PRINT((ndo, "\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_TCHECK2(*tptr, 4); ND_PRINT((ndo, "\n\t Magic-Num 0x%08x", EXTRACT_32BITS(tptr))); /* XXX: need to decode Data? - hexdump for now */ if (len > 8) { ND_PRINT((ndo, "\n\t -----trailing data-----")); ND_TCHECK2(tptr[4], len - 8); print_unknown_data(ndo, tptr + 4, "\n\t ", len - 8); } break; case CPCODES_ID: if (length < 8) break; ND_TCHECK2(*tptr, 4); ND_PRINT((ndo, "\n\t Magic-Num 0x%08x", EXTRACT_32BITS(tptr))); /* RFC 1661 says this is intended to be human readable */ if (len > 8) { ND_PRINT((ndo, "\n\t Message\n\t ")); if (fn_printn(ndo, tptr + 4, len - 4, ndo->ndo_snapend)) goto trunc; } break; case CPCODES_TIME_REM: if (length < 12) break; ND_TCHECK2(*tptr, 4); ND_PRINT((ndo, "\n\t Magic-Num 0x%08x", EXTRACT_32BITS(tptr))); ND_TCHECK2(*(tptr + 4), 4); ND_PRINT((ndo, ", Seconds-Remaining %us", EXTRACT_32BITS(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((ndo, "[|%s]", typestr)); } /* LCP config options */ static int print_lcp_config_options(netdissect_options *ndo, const u_char *p, int length) { int len, opt; if (length < 2) return 0; ND_TCHECK2(*p, 2); len = p[1]; opt = p[0]; if (length < len) return 0; if (len < 2) { if ((opt >= LCPOPT_MIN) && (opt <= LCPOPT_MAX)) ND_PRINT((ndo, "\n\t %s Option (0x%02x), length %u (length bogus, should be >= 2)", lcpconfopts[opt], opt, len)); else ND_PRINT((ndo, "\n\tunknown LCP option 0x%02x", opt)); return 0; } if ((opt >= LCPOPT_MIN) && (opt <= LCPOPT_MAX)) ND_PRINT((ndo, "\n\t %s Option (0x%02x), length %u", lcpconfopts[opt], opt, len)); else { ND_PRINT((ndo, "\n\tunknown LCP option 0x%02x", opt)); return len; } switch (opt) { case LCPOPT_VEXT: if (len < 6) { ND_PRINT((ndo, " (length bogus, should be >= 6)")); return len; } ND_TCHECK2(*(p + 2), 3); ND_PRINT((ndo, ": Vendor: %s (%u)", tok2str(oui_values,"Unknown",EXTRACT_24BITS(p+2)), EXTRACT_24BITS(p + 2))); #if 0 ND_TCHECK(p[5]); ND_PRINT((ndo, ", kind: 0x%02x", p[5])); ND_PRINT((ndo, ", Value: 0x")); for (i = 0; i < len - 6; i++) { ND_TCHECK(p[6 + i]); ND_PRINT((ndo, "%02x", p[6 + i])); } #endif break; case LCPOPT_MRU: if (len != 4) { ND_PRINT((ndo, " (length bogus, should be = 4)")); return len; } ND_TCHECK2(*(p + 2), 2); ND_PRINT((ndo, ": %u", EXTRACT_16BITS(p + 2))); break; case LCPOPT_ACCM: if (len != 6) { ND_PRINT((ndo, " (length bogus, should be = 6)")); return len; } ND_TCHECK2(*(p + 2), 4); ND_PRINT((ndo, ": 0x%08x", EXTRACT_32BITS(p + 2))); break; case LCPOPT_AP: if (len < 4) { ND_PRINT((ndo, " (length bogus, should be >= 4)")); return len; } ND_TCHECK2(*(p + 2), 2); ND_PRINT((ndo, ": %s", tok2str(ppptype2str, "Unknown Auth Proto (0x04x)", EXTRACT_16BITS(p + 2)))); switch (EXTRACT_16BITS(p+2)) { case PPP_CHAP: ND_TCHECK(p[4]); ND_PRINT((ndo, ", %s", tok2str(authalg_values, "Unknown Auth Alg %u", 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((ndo, " (length bogus, should be >= 4)")); return 0; } ND_TCHECK2(*(p + 2), 2); if (EXTRACT_16BITS(p+2) == PPP_LQM) ND_PRINT((ndo, ": LQR")); else ND_PRINT((ndo, ": unknown")); break; case LCPOPT_MN: if (len != 6) { ND_PRINT((ndo, " (length bogus, should be = 6)")); return 0; } ND_TCHECK2(*(p + 2), 4); ND_PRINT((ndo, ": 0x%08x", EXTRACT_32BITS(p + 2))); break; case LCPOPT_PFC: break; case LCPOPT_ACFC: break; case LCPOPT_LD: if (len != 4) { ND_PRINT((ndo, " (length bogus, should be = 4)")); return 0; } ND_TCHECK2(*(p + 2), 2); ND_PRINT((ndo, ": 0x%04x", EXTRACT_16BITS(p + 2))); break; case LCPOPT_CBACK: if (len < 3) { ND_PRINT((ndo, " (length bogus, should be >= 3)")); return 0; } ND_PRINT((ndo, ": ")); ND_TCHECK(p[2]); ND_PRINT((ndo, ": Callback Operation %s (%u)", tok2str(ppp_callback_values, "Unknown", p[2]), p[2])); break; case LCPOPT_MLMRRU: if (len != 4) { ND_PRINT((ndo, " (length bogus, should be = 4)")); return 0; } ND_TCHECK2(*(p + 2), 2); ND_PRINT((ndo, ": %u", EXTRACT_16BITS(p + 2))); break; case LCPOPT_MLED: if (len < 3) { ND_PRINT((ndo, " (length bogus, should be >= 3)")); return 0; } ND_TCHECK(p[2]); switch (p[2]) { /* class */ case MEDCLASS_NULL: ND_PRINT((ndo, ": Null")); break; case MEDCLASS_LOCAL: ND_PRINT((ndo, ": Local")); /* XXX */ break; case MEDCLASS_IPV4: if (len != 7) { ND_PRINT((ndo, " (length bogus, should be = 7)")); return 0; } ND_TCHECK2(*(p + 3), 4); ND_PRINT((ndo, ": IPv4 %s", ipaddr_string(ndo, p + 3))); break; case MEDCLASS_MAC: if (len != 9) { ND_PRINT((ndo, " (length bogus, should be = 9)")); return 0; } ND_TCHECK2(*(p + 3), 6); ND_PRINT((ndo, ": MAC %s", etheraddr_string(ndo, p + 3))); break; case MEDCLASS_MNB: ND_PRINT((ndo, ": Magic-Num-Block")); /* XXX */ break; case MEDCLASS_PSNDN: ND_PRINT((ndo, ": PSNDN")); /* XXX */ break; default: ND_PRINT((ndo, ": Unknown class %u", 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((ndo, "[|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, int length) { - + const u_char *p, int length) +{ if (!ndo->ndo_eflag) ND_PRINT((ndo, "MLPPP, ")); ND_PRINT((ndo, "seq 0x%03x, Flags [%s], length %u", (EXTRACT_16BITS(p))&0x0fff, /* only support 12-Bit sequence space for now */ bittok2str(ppp_ml_flag_values, "none", *p & 0xc0), length)); } /* CHAP */ static void handle_chap(netdissect_options *ndo, const u_char *p, int length) { u_int code, len; int val_size, name_size, msg_size; const u_char *p0; int i; p0 = p; if (length < 1) { ND_PRINT((ndo, "[|chap]")); return; } else if (length < 4) { ND_TCHECK(*p); ND_PRINT((ndo, "[|chap 0x%02x]", *p)); return; } ND_TCHECK(*p); code = *p; ND_PRINT((ndo, "CHAP, %s (0x%02x)", tok2str(chapcode_values,"unknown",code), code)); p++; ND_TCHECK(*p); ND_PRINT((ndo, ", id %u", *p)); /* ID */ p++; ND_TCHECK2(*p, 2); len = EXTRACT_16BITS(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. */ switch (code) { case CHAP_CHAL: case CHAP_RESP: if (length - (p - p0) < 1) return; ND_TCHECK(*p); val_size = *p; /* value size */ p++; if (length - (p - p0) < val_size) return; ND_PRINT((ndo, ", Value ")); for (i = 0; i < val_size; i++) { ND_TCHECK(*p); ND_PRINT((ndo, "%02x", *p++)); } name_size = len - (p - p0); ND_PRINT((ndo, ", Name ")); for (i = 0; i < name_size; i++) { ND_TCHECK(*p); safeputchar(ndo, *p++); } break; case CHAP_SUCC: case CHAP_FAIL: msg_size = len - (p - p0); ND_PRINT((ndo, ", Msg ")); for (i = 0; i< msg_size; i++) { ND_TCHECK(*p); safeputchar(ndo, *p++); } break; } return; trunc: ND_PRINT((ndo, "[|chap]")); } /* PAP (see RFC 1334) */ static void handle_pap(netdissect_options *ndo, const u_char *p, int length) { u_int code, len; int peerid_len, passwd_len, msg_len; const u_char *p0; int i; p0 = p; if (length < 1) { ND_PRINT((ndo, "[|pap]")); return; } else if (length < 4) { ND_TCHECK(*p); ND_PRINT((ndo, "[|pap 0x%02x]", *p)); return; } ND_TCHECK(*p); code = *p; ND_PRINT((ndo, "PAP, %s (0x%02x)", tok2str(papcode_values, "unknown", code), code)); p++; ND_TCHECK(*p); ND_PRINT((ndo, ", id %u", *p)); /* ID */ p++; ND_TCHECK2(*p, 2); len = EXTRACT_16BITS(p); p += 2; if ((int)len > length) { ND_PRINT((ndo, ", length %u > packet size", len)); return; } length = len; if (length < (p - p0)) { ND_PRINT((ndo, ", length %u < PAP header length", length)); return; } switch (code) { case PAP_AREQ: if (length - (p - p0) < 1) return; ND_TCHECK(*p); peerid_len = *p; /* Peer-ID Length */ p++; if (length - (p - p0) < peerid_len) return; ND_PRINT((ndo, ", Peer ")); for (i = 0; i < peerid_len; i++) { ND_TCHECK(*p); safeputchar(ndo, *p++); } if (length - (p - p0) < 1) return; ND_TCHECK(*p); passwd_len = *p; /* Password Length */ p++; if (length - (p - p0) < passwd_len) return; ND_PRINT((ndo, ", Name ")); for (i = 0; i < passwd_len; i++) { ND_TCHECK(*p); safeputchar(ndo, *p++); } break; case PAP_AACK: case PAP_ANAK: if (length - (p - p0) < 1) return; ND_TCHECK(*p); msg_len = *p; /* Msg-Length */ p++; if (length - (p - p0) < msg_len) return; ND_PRINT((ndo, ", Msg ")); for (i = 0; i< msg_len; i++) { ND_TCHECK(*p); safeputchar(ndo, *p++); } break; } return; trunc: ND_PRINT((ndo, "[|pap]")); } /* BAP */ static void handle_bap(netdissect_options *ndo _U_, const u_char *p _U_, int length _U_) { /* XXX: to be supported!! */ } /* IPCP config options */ static int print_ipcp_config_options(netdissect_options *ndo, const u_char *p, int length) { int len, opt; u_int compproto, ipcomp_subopttotallen, ipcomp_subopt, ipcomp_suboptlen; if (length < 2) return 0; ND_TCHECK2(*p, 2); len = p[1]; opt = p[0]; if (length < len) return 0; if (len < 2) { ND_PRINT((ndo, "\n\t %s Option (0x%02x), length %u (length bogus, should be >= 2)", tok2str(ipcpopt_values,"unknown",opt), opt, len)); return 0; } ND_PRINT((ndo, "\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((ndo, " (length bogus, should be = 10)")); return len; } ND_TCHECK2(*(p + 6), 4); ND_PRINT((ndo, ": src %s, dst %s", ipaddr_string(ndo, p + 2), ipaddr_string(ndo, p + 6))); break; case IPCPOPT_IPCOMP: if (len < 4) { ND_PRINT((ndo, " (length bogus, should be >= 4)")); return 0; } ND_TCHECK2(*(p + 2), 2); compproto = EXTRACT_16BITS(p+2); ND_PRINT((ndo, ": %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((ndo, " (length bogus, should be >= %u)", IPCPOPT_IPCOMP_MINLEN)); return 0; } ND_TCHECK2(*(p + 2), IPCPOPT_IPCOMP_MINLEN); ND_PRINT((ndo, "\n\t TCP Space %u, non-TCP Space %u" \ ", maxPeriod %u, maxTime %u, maxHdr %u", EXTRACT_16BITS(p+4), EXTRACT_16BITS(p+6), EXTRACT_16BITS(p+8), EXTRACT_16BITS(p+10), EXTRACT_16BITS(p+12))); /* suboptions present ? */ if (len > IPCPOPT_IPCOMP_MINLEN) { ipcomp_subopttotallen = len - IPCPOPT_IPCOMP_MINLEN; p += IPCPOPT_IPCOMP_MINLEN; ND_PRINT((ndo, "\n\t Suboptions, length %u", ipcomp_subopttotallen)); while (ipcomp_subopttotallen >= 2) { ND_TCHECK2(*p, 2); ipcomp_subopt = *p; ipcomp_suboptlen = *(p+1); /* sanity check */ if (ipcomp_subopt == 0 || ipcomp_suboptlen == 0 ) break; /* XXX: just display the suboptions for now */ ND_PRINT((ndo, "\n\t\t%s Suboption #%u, length %u", tok2str(ipcpopt_compproto_subopt_values, "Unknown", ipcomp_subopt), ipcomp_subopt, ipcomp_suboptlen)); 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((ndo, " (length bogus, should be = 6)")); return 0; } ND_TCHECK2(*(p + 2), 4); ND_PRINT((ndo, ": %s", ipaddr_string(ndo, 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((ndo, "[|ipcp]")); return 0; } /* IP6CP config options */ static int print_ip6cp_config_options(netdissect_options *ndo, const u_char *p, int length) { int len, opt; if (length < 2) return 0; ND_TCHECK2(*p, 2); len = p[1]; opt = p[0]; if (length < len) return 0; if (len < 2) { ND_PRINT((ndo, "\n\t %s Option (0x%02x), length %u (length bogus, should be >= 2)", tok2str(ip6cpopt_values,"unknown",opt), opt, len)); return 0; } ND_PRINT((ndo, "\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((ndo, " (length bogus, should be = 10)")); return len; } ND_TCHECK2(*(p + 2), 8); ND_PRINT((ndo, ": %04x:%04x:%04x:%04x", EXTRACT_16BITS(p + 2), EXTRACT_16BITS(p + 4), EXTRACT_16BITS(p + 6), EXTRACT_16BITS(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((ndo, "[|ip6cp]")); return 0; } /* CCP config options */ static int print_ccp_config_options(netdissect_options *ndo, const u_char *p, int length) { int len, opt; if (length < 2) return 0; ND_TCHECK2(*p, 2); len = p[1]; opt = p[0]; if (length < len) return 0; if (len < 2) { ND_PRINT((ndo, "\n\t %s Option (0x%02x), length %u (length bogus, should be >= 2)", tok2str(ccpconfopts_values, "Unknown", opt), opt, len)); return 0; } ND_PRINT((ndo, "\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((ndo, " (length bogus, should be >= 3)")); return len; } ND_TCHECK2(*(p + 2), 1); ND_PRINT((ndo, ": Version: %u, Dictionary Bits: %u", p[2] >> 5, p[2] & 0x1f)); break; case CCPOPT_MVRCA: if (len < 4) { ND_PRINT((ndo, " (length bogus, should be >= 4)")); return len; } ND_TCHECK2(*(p + 2), 1); ND_PRINT((ndo, ": Features: %u, PxP: %s, History: %u, #CTX-ID: %u", (p[2] & 0xc0) >> 6, (p[2] & 0x20) ? "Enabled" : "Disabled", p[2] & 0x1f, p[3])); break; case CCPOPT_DEFLATE: if (len < 4) { ND_PRINT((ndo, " (length bogus, should be >= 4)")); return len; } ND_TCHECK2(*(p + 2), 1); ND_PRINT((ndo, ": Window: %uK, Method: %s (0x%x), MBZ: %u, CHK: %u", (p[2] & 0xf0) >> 4, ((p[2] & 0x0f) == 8) ? "zlib" : "unkown", p[2] & 0x0f, (p[3] & 0xfc) >> 2, 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((ndo, "[|ccp]")); return 0; } /* BACP config options */ static int print_bacp_config_options(netdissect_options *ndo, const u_char *p, int length) { int len, opt; if (length < 2) return 0; ND_TCHECK2(*p, 2); len = p[1]; opt = p[0]; if (length < len) return 0; if (len < 2) { ND_PRINT((ndo, "\n\t %s Option (0x%02x), length %u (length bogus, should be >= 2)", tok2str(bacconfopts_values, "Unknown", opt), opt, len)); return 0; } ND_PRINT((ndo, "\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((ndo, " (length bogus, should be = 6)")); return len; } ND_TCHECK2(*(p + 2), 4); ND_PRINT((ndo, ": Magic-Num 0x%08x", EXTRACT_32BITS(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((ndo, "[|bacp]")); return 0; } static void ppp_hdlc(netdissect_options *ndo, const u_char *p, int length) { - u_char *b, *s, *t, c; + u_char *b, *t, c; + const u_char *s; int i, proto; const void *se; if (length <= 0) return; - b = (uint8_t *)malloc(length); + b = (u_char *)malloc(length); if (b == NULL) return; /* * Unescape all the data into a temporary, private, buffer. * Do this so that we dont overwrite the original packet * contents. */ - for (s = (u_char *)p, t = b, i = length; i > 0; i--) { + for (s = p, t = b, i = length; i > 0 && ND_TTEST(*s); i--) { c = *s++; if (c == 0x7d) { - if (i > 1) { - i--; - c = *s++ ^ 0x20; - } else - continue; + if (i <= 1 || !ND_TTEST(*s)) + break; + i--; + c = *s++ ^ 0x20; } *t++ = c; } se = ndo->ndo_snapend; ndo->ndo_snapend = t; length = t - b; /* now lets guess about the payload codepoint format */ if (length < 1) goto trunc; proto = *b; /* start with a one-octet codepoint guess */ switch (proto) { case PPP_IP: ip_print(ndo, b + 1, length - 1); goto cleanup; -#ifdef INET6 case PPP_IPV6: ip6_print(ndo, b + 1, length - 1); goto cleanup; -#endif default: /* no luck - try next guess */ break; } if (length < 2) goto trunc; proto = EXTRACT_16BITS(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 = EXTRACT_16BITS(b+2); /* load the PPP proto-id */ handle_ppp(ndo, proto, b + 4, length - 4); break; default: /* last guess - proto must be a PPP proto-id */ handle_ppp(ndo, proto, b + 2, length - 2); break; } cleanup: ndo->ndo_snapend = se; free(b); return; trunc: ndo->ndo_snapend = se; free(b); ND_PRINT((ndo, "[|ppp]")); } /* PPP */ static void handle_ppp(netdissect_options *ndo, u_int proto, const u_char *p, 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; -#ifdef INET6 case ETHERTYPE_IPV6: /*XXX*/ case PPP_IPV6: ip6_print(ndo, p, length); break; -#endif case ETHERTYPE_IPX: /*XXX*/ case PPP_IPX: ipx_print(ndo, p, length); break; case PPP_OSI: isoclns_print(ndo, p, length, length); break; case PPP_MPLS_UCAST: case PPP_MPLS_MCAST: mpls_print(ndo, p, length); break; case PPP_COMP: ND_PRINT((ndo, "compressed PPP data")); break; default: ND_PRINT((ndo, "%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, register const u_char *p, u_int length) { u_int proto,ppp_header; u_int olen = length; /* _o_riginal length */ u_int hdr_len = 0; /* * Here, we assume that p points to the Address and Control * field (if they present). */ if (length < 2) goto trunc; ND_TCHECK2(*p, 2); ppp_header = EXTRACT_16BITS(p); switch(ppp_header) { case (PPP_WITHDIRECTION_IN << 8 | PPP_CONTROL): if (ndo->ndo_eflag) ND_PRINT((ndo, "In ")); p += 2; length -= 2; hdr_len += 2; break; case (PPP_WITHDIRECTION_OUT << 8 | PPP_CONTROL): if (ndo->ndo_eflag) ND_PRINT((ndo, "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; ND_TCHECK(*p); if (*p % 2) { proto = *p; /* PFC is used */ p++; length--; hdr_len++; } else { ND_TCHECK2(*p, 2); proto = EXTRACT_16BITS(p); p += 2; length -= 2; hdr_len += 2; } if (ndo->ndo_eflag) ND_PRINT((ndo, "%s (0x%04x), length %u: ", tok2str(ppptype2str, "unknown", proto), proto, olen)); handle_ppp(ndo, proto, p, length); return (hdr_len); trunc: ND_PRINT((ndo, "[|ppp]")); return (0); } /* PPP I/F printer */ u_int ppp_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, register const u_char *p) { register u_int length = h->len; register u_int caplen = h->caplen; if (caplen < PPP_HDRLEN) { ND_PRINT((ndo, "[|ppp]")); return (caplen); } #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((ndo, "%c %4d %02x ", p[0] ? 'O' : 'I', length, p[1])); #endif ppp_print(ndo, p, length); return (0); } /* * 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. */ u_int ppp_hdlc_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, register const u_char *p) { register u_int length = h->len; register u_int caplen = h->caplen; u_int proto; u_int hdrlen = 0; if (caplen < 2) { ND_PRINT((ndo, "[|ppp]")); return (caplen); } switch (p[0]) { case PPP_ADDRESS: if (caplen < 4) { ND_PRINT((ndo, "[|ppp]")); return (caplen); } if (ndo->ndo_eflag) ND_PRINT((ndo, "%02x %02x %d ", p[0], p[1], length)); p += 2; length -= 2; hdrlen += 2; proto = EXTRACT_16BITS(p); p += 2; length -= 2; hdrlen += 2; ND_PRINT((ndo, "%s: ", tok2str(ppptype2str, "unknown PPP protocol (0x%04x)", proto))); handle_ppp(ndo, proto, p, length); break; case CHDLC_UNICAST: case CHDLC_BCAST: return (chdlc_if_print(ndo, h, p)); default: if (ndo->ndo_eflag) ND_PRINT((ndo, "%02x %02x %d ", p[0], 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((ndo, "unknown addr %02x; ctrl %02x", p[0], p[1])); break; } return (hdrlen); } #define PPP_BSDI_HDRLEN 24 /* BSD/OS specific PPP printer */ u_int ppp_bsdos_if_print(netdissect_options *ndo _U_, const struct pcap_pkthdr *h _U_, register const u_char *p _U_) { register int hdrlength; #ifdef __bsdi__ register u_int length = h->len; register u_int caplen = h->caplen; uint16_t ptype; const u_char *q; int i; if (caplen < PPP_BSDI_HDRLEN) { ND_PRINT((ndo, "[|ppp]")); return (caplen) } hdrlength = 0; #if 0 if (p[0] == PPP_ADDRESS && p[1] == PPP_CONTROL) { if (ndo->ndo_eflag) ND_PRINT((ndo, "%02x %02x ", p[0], p[1])); p += 2; hdrlength = 2; } if (ndo->ndo_eflag) ND_PRINT((ndo, "%d ", length)); /* Retrieve the protocol type */ if (*p & 01) { /* Compressed protocol field */ ptype = *p; if (ndo->ndo_eflag) ND_PRINT((ndo, "%02x ", ptype)); p++; hdrlength += 1; } else { /* Un-compressed protocol field */ ptype = EXTRACT_16BITS(p); if (ndo->ndo_eflag) ND_PRINT((ndo, "%04x ", ptype)); p += 2; hdrlength += 2; } #else ptype = 0; /*XXX*/ if (ndo->ndo_eflag) ND_PRINT((ndo, "%c ", p[SLC_DIR] ? 'O' : 'I')); if (p[SLC_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((ndo, "%02x %02x ", q[0], q[1])); ptype = EXTRACT_16BITS(&ph->phdr_type); if (ndo->ndo_eflag && (ptype == PPP_VJC || ptype == PPP_VJNC)) { ND_PRINT((ndo, "%s ", tok2str(ppptype2str, "proto-#%d", ptype))); } } else { if (ndo->ndo_eflag) { ND_PRINT((ndo, "LLH=[")); for (i = 0; i < p[SLC_LLHL]; i++) ND_PRINT((ndo, "%02x", q[i])); ND_PRINT((ndo, "] ")); } } } if (ndo->ndo_eflag) ND_PRINT((ndo, "%d ", length)); if (p[SLC_CHL]) { q = p + SLC_BPFHDRLEN + p[SLC_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; -#ifdef INET6 case PPP_IPV6: ip6_print(ndo, p, length); break; -#endif 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; -#ifdef INET6 case PPP_IPV6: ip6_print(ndo, p, length); break; -#endif case PPP_MPLS_UCAST: case PPP_MPLS_MCAST: mpls_print(ndo, p, length); break; } goto printx; default: if (ndo->ndo_eflag) { ND_PRINT((ndo, "CH=[")); for (i = 0; i < p[SLC_LLHL]; i++) ND_PRINT((ndo, "%02x", q[i])); ND_PRINT((ndo, "] ")); } break; } } hdrlength = PPP_BSDI_HDRLEN; #endif length -= hdrlength; p += hdrlength; switch (ptype) { case PPP_IP: ip_print(p, length); break; -#ifdef INET6 case PPP_IPV6: ip6_print(ndo, p, length); break; -#endif case PPP_MPLS_UCAST: case PPP_MPLS_MCAST: mpls_print(ndo, p, length); break; default: ND_PRINT((ndo, "%s ", tok2str(ppptype2str, "unknown PPP protocol (0x%04x)", ptype))); } printx: #else /* __bsdi */ hdrlength = 0; #endif /* __bsdi__ */ return (hdrlength); } /* * Local Variables: * c-style: whitesmith * c-basic-offset: 8 * End: */ Index: head/contrib/tcpdump/print-radius.c =================================================================== --- head/contrib/tcpdump/print-radius.c (revision 285274) +++ head/contrib/tcpdump/print-radius.c (revision 285275) @@ -1,934 +1,989 @@ /* * 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. */ /* * 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 4675: + * "RADIUS Attributes for Virtual LAN and Priority Support" + * + * RFC 5176: + * "Dynamic Authorization Extensions to RADIUS" + * * Alfredo Andres Omella (aandres@s21sec.com) v0.1 2000/09/15 * * TODO: Among other things to print ok MacIntosh and Vendor values */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "interface.h" #include "addrtoname.h" #include "extract.h" #include "oui.h" static const char tstr[] = " [|radius]"; #define TAM_SIZE(x) (sizeof(x)/sizeof(x[0]) ) #define PRINT_HEX(bytes_len, ptr_data) \ while(bytes_len) \ { \ ND_PRINT((ndo, "%02X", *ptr_data )); \ ptr_data++; \ bytes_len--; \ } /* Radius packet codes */ #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 */ 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_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" }, { 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 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 /********************************/ /* 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 *, register u_char *, u_int, u_short ); static void print_attr_num(netdissect_options *, register u_char *, u_int, u_short ); static void print_vendor_attr(netdissect_options *, register u_char *, u_int, u_short ); static void print_attr_address(netdissect_options *, register u_char *, u_int, u_short); static void print_attr_time(netdissect_options *, register u_char *, u_int, u_short); static void print_attr_strange(netdissect_options *, register u_char *, u_int, u_short); struct radius_hdr { uint8_t code; /* Radius packet code */ uint8_t id; /* Radius packet id */ uint16_t len; /* Radius total length */ uint8_t auth[16]; /* Authenticator */ }; #define MIN_RADIUS_LEN 20 struct radius_attr { uint8_t type; /* Attribute type */ uint8_t len; /* Attribute length */ }; /* Service-Type Attribute standard values */ static const char *serv_type[]={ NULL, "Login", "Framed", "Callback Login", "Callback Framed", "Outbound", "Administrative", "NAS Prompt", "Authenticate Only", "Callback NAS Prompt", "Call Check", "Callback Administrative", }; /* Framed-Protocol Attribute standard values */ static const char *frm_proto[]={ NULL, "PPP", "SLIP", "ARAP", "Gandalf proprietary", "Xylogics IPX/SLIP", "X.75 Synchronous", }; /* Framed-Routing Attribute standard values */ static const char *frm_routing[]={ "None", "Send", "Listen", "Send&Listen", }; /* Framed-Compression Attribute standard values */ static const char *frm_comp[]={ "None", "VJ TCP/IP", "IPX", "Stac-LZS", }; /* Login-Service Attribute standard values */ 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 */ 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 */ 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", "G.3 Fax", "SDSL", "ADSL-CAP", "ADSL-DMT", "ISDN-DSL", "Ethernet", "xDSL", "Cable", "Wireless - Other", "Wireless - IEEE 802.11", }; /* Acct-Status-Type Accounting Attribute standard values */ static const char *acct_status[]={ NULL, "Start", "Stop", "Interim-Update", "Unassigned", "Unassigned", "Unassigned", "Accounting-On", "Accounting-Off", "Tunnel-Start", "Tunnel-Stop", "Tunnel-Reject", "Tunnel-Link-Start", "Tunnel-Link-Stop", "Tunnel-Link-Reject", "Failed", }; /* Acct-Authentic Accounting Attribute standard values */ static const char *acct_auth[]={ NULL, "RADIUS", "Local", "Remote", }; /* Acct-Terminate-Cause Accounting Attribute standard values */ static const char *acct_term[]={ NULL, "User Request", "Lost Carrier", "Lost Service", "Idle Timeout", "Session Timeout", "Admin Reset", "Admin Reboot", "Port Error", "NAS Error", "NAS Request", "NAS Reboot", "Port Unneeded", "Port Preempted", "Port Suspended", "Service Unavailable", "Callback", "User Error", "Host Request", }; /* Tunnel-Type Attribute standard values */ static const char *tunnel_type[]={ NULL, "PPTP", "L2F", "L2TP", "ATMP", "VTP", "AH", "IP-IP", "MIN-IP-IP", "ESP", "GRE", "DVS", "IP-in-IP Tunneling", }; /* Tunnel-Medium-Type Attribute standard values */ static const char *tunnel_medium[]={ NULL, "IPv4", "IPv6", "NSAP", "HDLC", "BBN 1822", "802", "E.163", "E.164", "F.69", "X.121", "IPX", "Appletalk", "Decnet IV", "Banyan Vines", "E.164 with NSAP subaddress", }; /* ARAP-Zone-Access Attribute standard values */ static const char *arap_zone[]={ NULL, "Only access to dfl zone", "Use zone filter inc.", "Not used", "Use zone filter exc.", }; static const char *prompt[]={ "No Echo", "Echo", }; 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 *, register u_char *, u_int, u_short); } attr_type[]= { { NULL, NULL, 0, 0, NULL }, - { "Username", NULL, 0, 0, print_attr_string }, - { "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 Network", NULL, 0, 0, print_attr_address }, - { "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 }, + { "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 }, + { "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", NULL, 0, 0, print_attr_string }, - { "Callback-number", NULL, 0, 0, print_attr_string }, - { "Callback-ID", NULL, 0, 0, print_attr_string }, + { "Reply-Message", NULL, 0, 0, print_attr_string }, + { "Callback-Number", NULL, 0, 0, print_attr_string }, + { "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 }, + { "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 }, - { "Called Station", NULL, 0, 0, print_attr_string }, - { "Calling Station", NULL, 0, 0, print_attr_string }, - { "NAS ID", 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 Appltalk Net", NULL, 0, 0, print_attr_num }, - { "Framed Appletalk Zone", NULL, 0, 0, print_attr_string }, - { "Accounting Status", acct_status, TAM_SIZE(acct_status)-1, 1, print_attr_num }, - { "Accounting Delay", NULL, 0, 0, print_attr_num }, - { "Accounting Input Octets", NULL, 0, 0, print_attr_num }, - { "Accounting Output Octets", NULL, 0, 0, print_attr_num }, - { "Accounting Session ID", NULL, 0, 0, print_attr_string }, - { "Accounting Authentication", acct_auth, TAM_SIZE(acct_auth)-1, 1, print_attr_num }, - { "Accounting Session Time", NULL, 0, 0, print_attr_num }, - { "Accounting Input Packets", NULL, 0, 0, print_attr_num }, - { "Accounting Output Packets", NULL, 0, 0, print_attr_num }, - { "Accounting Termination Cause", acct_term, TAM_SIZE(acct_term)-1, 1, print_attr_num }, - { "Accounting Multilink Session ID", NULL, 0, 0, print_attr_string }, - { "Accounting Link Count", NULL, 0, 0, print_attr_num }, - { "Accounting Input Giga", NULL, 0, 0, print_attr_num }, - { "Accounting Output Giga", NULL, 0, 0, print_attr_num }, + { "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 }, + { "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 }, + { "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 }, + { "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 }, - { "Unassigned", NULL, 0, 0, NULL }, /*56*/ - { "Unassigned", NULL, 0, 0, NULL }, /*57*/ - { "Unassigned", NULL, 0, 0, NULL }, /*58*/ - { "Unassigned", NULL, 0, 0, NULL }, /*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", tunnel_medium, TAM_SIZE(tunnel_medium)-1, 1, print_attr_num }, - { "Tunnel Client End", NULL, 0, 0, print_attr_string }, - { "Tunnel Server End", NULL, 0, 0, print_attr_string }, - { "Accounting Tunnel connect", NULL, 0, 0, print_attr_string }, - { "Tunnel Password", NULL, 0, 0, print_attr_string }, - { "ARAP Password", NULL, 0, 0, print_attr_strange }, - { "ARAP Feature", NULL, 0, 0, print_attr_strange }, - { "ARAP Zone Acces", 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 }, + { "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 }, + { "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 }, + { "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 }, - { "Config Token", NULL, 0, 0, print_attr_string }, - { "EAP Message", NULL, 0, 0, print_attr_string }, - { "Message Authentication", NULL, 0, 0, print_attr_string }, /*80*/ - { "Tunnel Private Group", NULL, 0, 0, print_attr_string }, - { "Tunnel Assigned ID", NULL, 0, 0, print_attr_string }, - { "Tunnel Preference", NULL, 0, 0, print_attr_num }, - { "ARAP Challenge Response", NULL, 0, 0, print_attr_strange }, - { "Accounting Interim Interval", NULL, 0, 0, print_attr_num }, - { "Accounting 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 }, - { "Chargeable User Identity", NULL, 0, 0, print_attr_string }, - { "Tunnel Client Authentication ID", NULL, 0, 0, print_attr_string }, - { "Tunnel Server Authentication ID", NULL, 0, 0, print_attr_string }, + { "Connect-Info", NULL, 0, 0, print_attr_string }, + { "Configuration-Token", NULL, 0, 0, print_attr_string }, + { "EAP-Message", NULL, 0, 0, print_attr_string }, + { "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 }, + { "Tunnel-Client-Auth-ID", NULL, 0, 0, print_attr_string }, + { "Tunnel-Server-Auth-ID", NULL, 0, 0, print_attr_string }, { "Unassigned", NULL, 0, 0, NULL }, /*92*/ { "Unassigned", NULL, 0, 0, NULL } /*93*/ }; /*****************************/ /* Print an attribute string */ /* value pointed by 'data' */ /* and 'length' size. */ /*****************************/ /* Returns nothing. */ /*****************************/ static void print_attr_string(netdissect_options *ndo, register u_char *data, u_int length, u_short attr_code) { register u_int i; ND_TCHECK2(data[0],length); switch(attr_code) { case TUNNEL_PASS: if (length < 3) { ND_PRINT((ndo, "%s", tstr)); return; } if (*data && (*data <=0x1F) ) - ND_PRINT((ndo, "Tag %u, ",*data)); + ND_PRINT((ndo, "Tag[%u] ", *data)); + else + ND_PRINT((ndo, "Tag[Unused] ")); data++; length--; ND_PRINT((ndo, "Salt %u ", EXTRACT_16BITS(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 (*data <= 0x1F) { if (length < 1) { ND_PRINT((ndo, "%s", tstr)); return; } - ND_PRINT((ndo, "Tag %u", *data)); + if (*data) + ND_PRINT((ndo, "Tag[%u] ", *data)); + else + ND_PRINT((ndo, "Tag[Unused] ")); data++; length--; } break; + case EGRESS_VLAN_NAME: + ND_PRINT((ndo, "%s (0x%02x) ", + tok2str(rfc4675_tagged,"Unknown tag",*data), + *data)); + data++; + length--; + break; } for (i=0; *data && i < length ; i++, data++) ND_PRINT((ndo, "%c", (*data < 32 || *data > 128) ? '.' : *data)); return; trunc: ND_PRINT((ndo, "%s", tstr)); } /* * print vendor specific attributes */ static void print_vendor_attr(netdissect_options *ndo, register 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; ND_TCHECK2(*data, 4); vendor_id = EXTRACT_32BITS(data); data+=4; length-=4; ND_PRINT((ndo, "Vendor: %s (%u)", tok2str(smi_values,"Unknown",vendor_id), vendor_id)); while (length >= 2) { ND_TCHECK2(*data, 2); vendor_type = *(data); vendor_length = *(data+1); if (vendor_length < 2) { ND_PRINT((ndo, "\n\t Vendor Attribute: %u, Length: %u (bogus, must be >= 2)", vendor_type, vendor_length)); return; } if (vendor_length > length) { ND_PRINT((ndo, "\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_TCHECK2(*data, vendor_length); ND_PRINT((ndo, "\n\t Vendor Attribute: %u, Length: %u, Value: ", vendor_type, vendor_length)); for (idx = 0; idx < vendor_length ; idx++, data++) ND_PRINT((ndo, "%c", (*data < 32 || *data > 128) ? '.' : *data)); length-=vendor_length; } return; trunc: ND_PRINT((ndo, "%s", tstr)); } /******************************/ /* Print an attribute numeric */ /* value pointed by 'data' */ /* and 'length' size. */ /******************************/ /* Returns nothing. */ /******************************/ static void print_attr_num(netdissect_options *ndo, register u_char *data, u_int length, u_short attr_code) { - uint8_t tag; uint32_t timeout; if (length != 4) { ND_PRINT((ndo, "ERROR: length %u != 4", length)); return; } ND_TCHECK2(data[0],4); /* This attribute has standard values */ 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 (!*data) - ND_PRINT((ndo, "Tag[Unused]")); + ND_PRINT((ndo, "Tag[Unused] ")); else - ND_PRINT((ndo, "Tag[%d]", *data)); + ND_PRINT((ndo, "Tag[%d] ", *data)); data++; data_value = EXTRACT_24BITS(data); } else { data_value = EXTRACT_32BITS(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((ndo, "%s", table[data_value])); else ND_PRINT((ndo, "#%u", data_value)); } else { switch(attr_code) /* Be aware of special cases... */ { case FRM_IPX: if (EXTRACT_32BITS( data) == 0xFFFFFFFE ) ND_PRINT((ndo, "NAS Select")); else ND_PRINT((ndo, "%d", EXTRACT_32BITS(data))); break; case SESSION_TIMEOUT: case IDLE_TIMEOUT: case ACCT_DELAY: case ACCT_SESSION_TIME: case ACCT_INT_INTERVAL: timeout = EXTRACT_32BITS( data); if ( timeout < 60 ) ND_PRINT((ndo, "%02d secs", timeout)); else { if ( timeout < 3600 ) ND_PRINT((ndo, "%02d:%02d min", timeout / 60, timeout % 60)); else ND_PRINT((ndo, "%02d:%02d:%02d hours", timeout / 3600, (timeout % 3600) / 60, timeout % 60)); } break; case FRM_ATALK_LINK: if (EXTRACT_32BITS(data) ) ND_PRINT((ndo, "%d", EXTRACT_32BITS(data))); else ND_PRINT((ndo, "Unnumbered")); break; case FRM_ATALK_NETWORK: if (EXTRACT_32BITS(data) ) ND_PRINT((ndo, "%d", EXTRACT_32BITS(data))); else ND_PRINT((ndo, "NAS assigned")); break; case TUNNEL_PREFERENCE: - tag = *data; - data++; - if (tag == 0) - ND_PRINT((ndo, "Tag (Unused) %d", EXTRACT_24BITS(data))); + if (*data) + ND_PRINT((ndo, "Tag[%d] ", *data)); else - ND_PRINT((ndo, "Tag (%d) %d", tag, EXTRACT_24BITS(data))); + ND_PRINT((ndo, "Tag[Unused] ")); + data++; + ND_PRINT((ndo, "%d", EXTRACT_24BITS(data))); + break; + + case EGRESS_VLAN_ID: + ND_PRINT((ndo, "%s (0x%02x) ", + tok2str(rfc4675_tagged,"Unknown tag",*data), + *data)); + data++; + ND_PRINT((ndo, "%d", EXTRACT_24BITS(data))); break; default: ND_PRINT((ndo, "%d", EXTRACT_32BITS(data))); break; } /* switch */ } /* if-else */ return; trunc: ND_PRINT((ndo, "%s", tstr)); } /*****************************/ /* Print an attribute IPv4 */ /* address value pointed by */ /* 'data' and 'length' size. */ /*****************************/ /* Returns nothing. */ /*****************************/ static void print_attr_address(netdissect_options *ndo, register u_char *data, u_int length, u_short attr_code) { if (length != 4) { ND_PRINT((ndo, "ERROR: length %u != 4", length)); return; } ND_TCHECK2(data[0],4); switch(attr_code) { case FRM_IPADDR: case LOG_IPHOST: if (EXTRACT_32BITS(data) == 0xFFFFFFFF ) ND_PRINT((ndo, "User Selected")); else if (EXTRACT_32BITS(data) == 0xFFFFFFFE ) ND_PRINT((ndo, "NAS Select")); else ND_PRINT((ndo, "%s",ipaddr_string(ndo, data))); break; default: ND_PRINT((ndo, "%s", ipaddr_string(ndo, data))); break; } return; trunc: ND_PRINT((ndo, "%s", tstr)); } /*************************************/ /* 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, register u_char *data, u_int length, u_short attr_code _U_) { time_t attr_time; char string[26]; if (length != 4) { ND_PRINT((ndo, "ERROR: length %u != 4", length)); return; } ND_TCHECK2(data[0],4); attr_time = EXTRACT_32BITS(data); strlcpy(string, ctime(&attr_time), sizeof(string)); /* Get rid of the newline */ string[24] = '\0'; ND_PRINT((ndo, "%.24s", string)); return; trunc: ND_PRINT((ndo, "%s", tstr)); } /***********************************/ /* Print an attribute of 'strange' */ /* data format pointed by 'data' */ /* and 'length' size. */ /***********************************/ /* Returns nothing. */ /***********************************/ static void print_attr_strange(netdissect_options *ndo, register u_char *data, u_int length, u_short attr_code) { u_short len_data; switch(attr_code) { case ARAP_PASS: if (length != 16) { ND_PRINT((ndo, "ERROR: length %u != 16", length)); return; } ND_PRINT((ndo, "User_challenge (")); ND_TCHECK2(data[0],8); len_data = 8; PRINT_HEX(len_data, data); ND_PRINT((ndo, ") User_resp(")); ND_TCHECK2(data[0],8); len_data = 8; PRINT_HEX(len_data, data); ND_PRINT((ndo, ")")); break; case ARAP_FEATURES: if (length != 14) { ND_PRINT((ndo, "ERROR: length %u != 14", length)); return; } ND_TCHECK2(data[0],1); if (*data) ND_PRINT((ndo, "User can change password")); else ND_PRINT((ndo, "User cannot change password")); data++; ND_TCHECK2(data[0],1); ND_PRINT((ndo, ", Min password length: %d", *data)); data++; ND_PRINT((ndo, ", created at: ")); ND_TCHECK2(data[0],4); len_data = 4; PRINT_HEX(len_data, data); ND_PRINT((ndo, ", expires in: ")); ND_TCHECK2(data[0],4); len_data = 4; PRINT_HEX(len_data, data); ND_PRINT((ndo, ", Current Time: ")); ND_TCHECK2(data[0],4); len_data = 4; PRINT_HEX(len_data, data); break; case ARAP_CHALLENGE_RESP: if (length < 8) { ND_PRINT((ndo, "ERROR: length %u != 8", length)); return; } ND_TCHECK2(data[0],8); len_data = 8; PRINT_HEX(len_data, data); break; } return; trunc: ND_PRINT((ndo, "%s", tstr)); } static void radius_attrs_print(netdissect_options *ndo, register const u_char *attr, u_int length) { register const struct radius_attr *rad_attr = (struct radius_attr *)attr; const char *attr_string; while (length > 0) { if (length < 2) goto trunc; ND_TCHECK(*rad_attr); if (rad_attr->type > 0 && rad_attr->type < TAM_SIZE(attr_type)) attr_string = attr_type[rad_attr->type].name; else attr_string = "Unknown"; if (rad_attr->len < 2) { ND_PRINT((ndo, "\n\t %s Attribute (%u), length: %u (bogus, must be >= 2)", attr_string, rad_attr->type, rad_attr->len)); return; } if (rad_attr->len > length) { ND_PRINT((ndo, "\n\t %s Attribute (%u), length: %u (bogus, goes past end of packet)", attr_string, rad_attr->type, rad_attr->len)); return; } ND_PRINT((ndo, "\n\t %s Attribute (%u), length: %u, Value: ", attr_string, rad_attr->type, rad_attr->len)); if (rad_attr->type < TAM_SIZE(attr_type)) { if (rad_attr->len > 2) { if ( attr_type[rad_attr->type].print_func ) (*attr_type[rad_attr->type].print_func)( ndo, ((u_char *)(rad_attr+1)), rad_attr->len - 2, rad_attr->type); } } /* do we also want to see a hex dump ? */ if (ndo->ndo_vflag> 1) print_unknown_data(ndo, (u_char *)rad_attr+2, "\n\t ", (rad_attr->len)-2); length-=(rad_attr->len); rad_attr = (struct radius_attr *)( ((char *)(rad_attr))+rad_attr->len); } return; trunc: ND_PRINT((ndo, "%s", tstr)); } void radius_print(netdissect_options *ndo, const u_char *dat, u_int length) { register const struct radius_hdr *rad; u_int len, auth_idx; ND_TCHECK2(*dat, MIN_RADIUS_LEN); rad = (struct radius_hdr *)dat; len = EXTRACT_16BITS(&rad->len); if (len < MIN_RADIUS_LEN) { ND_PRINT((ndo, "%s", tstr)); return; } if (len > length) len = length; if (ndo->ndo_vflag < 1) { ND_PRINT((ndo, "RADIUS, %s (%u), id: 0x%02x length: %u", tok2str(radius_command_values,"Unknown Command",rad->code), rad->code, rad->id, len)); return; } else { ND_PRINT((ndo, "RADIUS, length: %u\n\t%s (%u), id: 0x%02x, Authenticator: ", len, tok2str(radius_command_values,"Unknown Command",rad->code), rad->code, rad->id)); for(auth_idx=0; auth_idx < 16; auth_idx++) ND_PRINT((ndo, "%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((ndo, "%s", tstr)); } Index: head/contrib/tcpdump/print-rpki-rtr.c =================================================================== --- head/contrib/tcpdump/print-rpki-rtr.c (revision 285274) +++ head/contrib/tcpdump/print-rpki-rtr.c (revision 285275) @@ -1,362 +1,368 @@ /* * 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. * * support for the The RPKI/Router Protocol as RFC6810 * * Original code by Hannes Gredler (hannes@juniper.net) */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "interface.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_ { u_char version; /* Version number */ u_char pdu_type; /* PDU type */ union { u_char session_id[2]; /* Session id */ u_char error_code[2]; /* Error code */ } u; u_char length[4]; } rpki_rtr_pdu; #define RPKI_RTR_PDU_OVERHEAD (offsetof(rpki_rtr_pdu, rpki_rtr_pdu_msg)) /* * IPv4 Prefix PDU. */ typedef struct rpki_rtr_pdu_ipv4_prefix_ { rpki_rtr_pdu pdu_header; u_char flags; u_char prefix_length; u_char max_length; u_char zero; u_char prefix[4]; u_char as[4]; } rpki_rtr_pdu_ipv4_prefix; /* * IPv6 Prefix PDU. */ typedef struct rpki_rtr_pdu_ipv6_prefix_ { rpki_rtr_pdu pdu_header; u_char flags; u_char prefix_length; u_char max_length; u_char zero; u_char prefix[16]; u_char as[4]; } rpki_rtr_pdu_ipv6_prefix; /* * Error report PDU. */ typedef struct rpki_rtr_pdu_error_report_ { rpki_rtr_pdu pdu_header; u_char encapsulated_pdu_length[4]; /* Encapsulated PDU length */ } 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 identation string for a given identation level. + * 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 void rpki_rtr_pdu_print (netdissect_options *ndo, const u_char *tptr, u_int indent) { const rpki_rtr_pdu *pdu_header; u_int pdu_type, pdu_len, hexdump; const u_char *msg; pdu_header = (rpki_rtr_pdu *)tptr; pdu_type = pdu_header->pdu_type; pdu_len = EXTRACT_32BITS(pdu_header->length); + ND_TCHECK2(*tptr, pdu_len); hexdump = FALSE; ND_PRINT((ndo, "%sRPKI-RTRv%u, %s PDU (%u), length: %u", indent_string(8), pdu_header->version, tok2str(rpki_rtr_pdu_values, "Unknown", pdu_type), pdu_type, pdu_len)); 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: msg = (const u_char *)(pdu_header + 1); ND_PRINT((ndo, "%sSession ID: 0x%04x, Serial: %u", indent_string(indent+2), EXTRACT_16BITS(pdu_header->u.session_id), EXTRACT_32BITS(msg))); break; /* * The following PDUs share the message format. */ case RPKI_RTR_RESET_QUERY_PDU: case RPKI_RTR_CACHE_RESET_PDU: /* * Zero payload PDUs. */ break; case RPKI_RTR_CACHE_RESPONSE_PDU: ND_PRINT((ndo, "%sSession ID: 0x%04x", indent_string(indent+2), EXTRACT_16BITS(pdu_header->u.session_id))); break; case RPKI_RTR_IPV4_PREFIX_PDU: { rpki_rtr_pdu_ipv4_prefix *pdu; pdu = (rpki_rtr_pdu_ipv4_prefix *)tptr; ND_PRINT((ndo, "%sIPv4 Prefix %s/%u-%u, origin-as %u, flags 0x%02x", indent_string(indent+2), ipaddr_string(ndo, pdu->prefix), pdu->prefix_length, pdu->max_length, EXTRACT_32BITS(pdu->as), pdu->flags)); } break; #ifdef INET6 case RPKI_RTR_IPV6_PREFIX_PDU: { rpki_rtr_pdu_ipv6_prefix *pdu; pdu = (rpki_rtr_pdu_ipv6_prefix *)tptr; ND_PRINT((ndo, "%sIPv6 Prefix %s/%u-%u, origin-as %u, flags 0x%02x", indent_string(indent+2), ip6addr_string(ndo, pdu->prefix), pdu->prefix_length, pdu->max_length, EXTRACT_32BITS(pdu->as), pdu->flags)); } break; #endif case RPKI_RTR_ERROR_REPORT_PDU: { rpki_rtr_pdu_error_report *pdu; u_int encapsulated_pdu_length, text_length, tlen, error_code; - u_char buf[80]; pdu = (rpki_rtr_pdu_error_report *)tptr; encapsulated_pdu_length = EXTRACT_32BITS(pdu->encapsulated_pdu_length); + ND_TCHECK2(*tptr, encapsulated_pdu_length); tlen = pdu_len; error_code = EXTRACT_16BITS(pdu->pdu_header.u.error_code); ND_PRINT((ndo, "%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)); tptr += sizeof(*pdu); tlen -= sizeof(*pdu); /* * Recurse if there is an encapsulated PDU. */ if (encapsulated_pdu_length && (encapsulated_pdu_length <= tlen)) { ND_PRINT((ndo, "%s-----encapsulated PDU-----", indent_string(indent+4))); rpki_rtr_pdu_print(ndo, tptr, indent+2); } tptr += encapsulated_pdu_length; tlen -= encapsulated_pdu_length; /* * Extract, trail-zero and print the Error message. */ text_length = 0; if (tlen > 4) { text_length = EXTRACT_32BITS(tptr); tptr += 4; tlen -= 4; } + ND_TCHECK2(*tptr, text_length); if (text_length && (text_length <= tlen )) { - memcpy(buf, tptr, min(sizeof(buf)-1, text_length)); - buf[text_length] = '\0'; - ND_PRINT((ndo, "%sError text: %s", indent_string(indent+2), buf)); + ND_PRINT((ndo, "%sError text: ", indent_string(indent+2))); + fn_printn(ndo, tptr, text_length, ndo->ndo_snapend); } } break; default: /* * 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; + + trunc: + ND_PRINT((ndo, "|trunc")); + return; } void -rpki_rtr_print(netdissect_options *ndo, register const u_char *pptr, register u_int len) { - +rpki_rtr_print(netdissect_options *ndo, register const u_char *pptr, register u_int len) +{ u_int tlen, pdu_type, pdu_len; const u_char *tptr; const rpki_rtr_pdu *pdu_header; tptr = pptr; tlen = len; if (!ndo->ndo_vflag) { ND_PRINT((ndo, ", RPKI-RTR")); return; } while (tlen >= sizeof(rpki_rtr_pdu)) { ND_TCHECK2(*tptr, sizeof(rpki_rtr_pdu)); pdu_header = (rpki_rtr_pdu *)tptr; pdu_type = pdu_header->pdu_type; pdu_len = EXTRACT_32BITS(pdu_header->length); + ND_TCHECK2(*tptr, pdu_len); /* infinite loop check */ if (!pdu_type || !pdu_len) { break; } - ND_TCHECK2(*tptr, pdu_len); if (tlen < pdu_len) { goto trunc; } /* * Print the PDU. */ rpki_rtr_pdu_print(ndo, tptr, 8); tlen -= pdu_len; tptr += pdu_len; } return; trunc: ND_PRINT((ndo, "\n\t[|RPKI-RTR]")); } /* * Local Variables: * c-style: whitesmith * c-basic-offset: 4 * End: */ Index: head/contrib/tcpdump/print-rsvp.c =================================================================== --- head/contrib/tcpdump/print-rsvp.c (revision 285274) +++ head/contrib/tcpdump/print-rsvp.c (revision 285275) @@ -1,1935 +1,1935 @@ /* * 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@juniper.net) */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "interface.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 { uint8_t version_flags; uint8_t msg_type; uint8_t checksum[2]; uint8_t ttl; uint8_t reserved; uint8_t length[2]; }; /* * RFC2205 object header * * * 0 1 2 3 * +-------------+-------------+-------------+-------------+ * | Length (bytes) | Class-Num | C-Type | * +-------------+-------------+-------------+-------------+ * | | * // (Object contents) // * | | * +-------------+-------------+-------------+-------------+ */ struct rsvp_object_header { uint8_t length[2]; uint8_t class_num; 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_AGGREGATE 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_AGGREGATE, "Aggregate" }, { 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} }; #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 /* draft-ietf-mpls-rsvp-lsp-fastreroute-07 */ #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_NOTIFY_REQ 195 /* rfc3473 */ #define RSVP_OBJ_ADMIN_STATUS 196 /* rfc3473 */ #define RSVP_OBJ_PROPERTIES 204 /* juniper proprietary */ #define RSVP_OBJ_FASTREROUTE 205 /* draft-ietf-mpls-rsvp-lsp-fastreroute-07 */ #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_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_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} }; 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_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} }; /* draft-ietf-mpls-rsvp-lsp-fastreroute-07.txt */ 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 int rsvp_intserv_print(netdissect_options *ndo, - const u_char *tptr, u_short obj_tlen) { - + const u_char *tptr, u_short obj_tlen) +{ int parameter_id,parameter_length; union { float f; uint32_t i; } bw; if (obj_tlen < 4) return 0; parameter_id = *(tptr); parameter_length = EXTRACT_16BITS(tptr+2)<<2; /* convert wordcount to bytecount */ ND_PRINT((ndo, "\n\t Parameter ID: %s (%u), length: %u, Flags: [0x%02x]", tok2str(rsvp_intserv_parameter_id_values,"unknown",parameter_id), parameter_id, parameter_length, *(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((ndo, "\n\t\tIS hop count: %u", EXTRACT_32BITS(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 = EXTRACT_32BITS(tptr+4); ND_PRINT((ndo, "\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((ndo, "\n\t\tMinimum path latency: ")); if (EXTRACT_32BITS(tptr+4) == 0xffffffff) ND_PRINT((ndo, "don't care")); else ND_PRINT((ndo, "%u", EXTRACT_32BITS(tptr + 4))); } break; case 10: /* * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | 10 (n) | (o) | 1 (p) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Composed MTU (32-bit unsigned integer) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ if (parameter_length == 4) ND_PRINT((ndo, "\n\t\tComposed MTU: %u bytes", EXTRACT_32BITS(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) { bw.i = EXTRACT_32BITS(tptr+4); ND_PRINT((ndo, "\n\t\tToken Bucket Rate: %.10g Mbps", bw.f / 125000)); bw.i = EXTRACT_32BITS(tptr+8); ND_PRINT((ndo, "\n\t\tToken Bucket Size: %.10g bytes", bw.f)); bw.i = EXTRACT_32BITS(tptr+12); ND_PRINT((ndo, "\n\t\tPeak Data Rate: %.10g Mbps", bw.f / 125000)); ND_PRINT((ndo, "\n\t\tMinimum Policed Unit: %u bytes", EXTRACT_32BITS(tptr + 16))); ND_PRINT((ndo, "\n\t\tMaximum Packet Size: %u bytes", EXTRACT_32BITS(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) { bw.i = EXTRACT_32BITS(tptr+4); ND_PRINT((ndo, "\n\t\tRate: %.10g Mbps", bw.f / 125000)); ND_PRINT((ndo, "\n\t\tSlack Term: %u", EXTRACT_32BITS(tptr + 8))); } break; case 133: case 134: case 135: case 136: if (parameter_length == 4) ND_PRINT((ndo, "\n\t\tValue: %u", EXTRACT_32BITS(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 */ } static int rsvp_obj_print(netdissect_options *ndo, const u_char *pptr #ifndef HAVE_LIBCRYPTO _U_ #endif , u_int plen #ifndef HAVE_LIBCRYPTO _U_ #endif , const u_char *tptr, - const char *ident, u_int tlen) { - + const char *ident, u_int tlen) +{ 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,obj_tlen,intserv_serv_tlen; int hexdump,processed,padbytes,error_code,error_value,i,sigcheck; union { float f; uint32_t i; } bw; uint8_t namelen; u_int action, subchannel; while(tlen>=sizeof(struct rsvp_object_header)) { /* did we capture enough for fully decoding the object header ? */ ND_TCHECK2(*tptr, sizeof(struct rsvp_object_header)); rsvp_obj_header = (const struct rsvp_object_header *)tptr; rsvp_obj_len=EXTRACT_16BITS(rsvp_obj_header->length); rsvp_obj_ctype=rsvp_obj_header->ctype; if(rsvp_obj_len % 4) { ND_PRINT((ndo, "%sERROR: object header size %u not a multiple of 4", ident, rsvp_obj_len)); return -1; } if(rsvp_obj_len < sizeof(struct rsvp_object_header)) { ND_PRINT((ndo, "%sERROR: object header too short %u < %lu", ident, rsvp_obj_len, (unsigned long)sizeof(const struct rsvp_object_header))); return -1; } ND_PRINT((ndo, "%s%s Object (%u) Flags: [%s", ident, tok2str(rsvp_obj_values, "Unknown", rsvp_obj_header->class_num), rsvp_obj_header->class_num, ((rsvp_obj_header->class_num) & 0x80) ? "ignore" : "reject")); if (rsvp_obj_header->class_num > 128) ND_PRINT((ndo, " %s", ((rsvp_obj_header->class_num) & 0x40) ? "and forward" : "silently")); ND_PRINT((ndo, " if unknown], Class-Type: %s (%u), length: %u", tok2str(rsvp_ctype_values, "Unknown", ((rsvp_obj_header->class_num)<<8)+rsvp_obj_ctype), rsvp_obj_ctype, rsvp_obj_len)); if(tlen < rsvp_obj_len) { ND_PRINT((ndo, "%sERROR: object goes past end of objects TLV", ident)); 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 ? */ if (!ND_TTEST2(*tptr, rsvp_obj_len)) return -1; hexdump=FALSE; switch(rsvp_obj_header->class_num) { case RSVP_OBJ_SESSION: switch(rsvp_obj_ctype) { case RSVP_CTYPE_IPV4: if (obj_tlen < 8) return -1; ND_PRINT((ndo, "%s IPv4 DestAddress: %s, Protocol ID: 0x%02x", ident, ipaddr_string(ndo, obj_tptr), *(obj_tptr + sizeof(struct in_addr)))); ND_PRINT((ndo, "%s Flags: [0x%02x], DestPort %u", ident, *(obj_tptr+5), EXTRACT_16BITS(obj_tptr + 6))); obj_tlen-=8; obj_tptr+=8; break; #ifdef INET6 case RSVP_CTYPE_IPV6: if (obj_tlen < 20) return -1; ND_PRINT((ndo, "%s IPv6 DestAddress: %s, Protocol ID: 0x%02x", ident, ip6addr_string(ndo, obj_tptr), *(obj_tptr + sizeof(struct in6_addr)))); ND_PRINT((ndo, "%s Flags: [0x%02x], DestPort %u", ident, *(obj_tptr+sizeof(struct in6_addr)+1), EXTRACT_16BITS(obj_tptr + sizeof(struct in6_addr) + 2))); obj_tlen-=20; obj_tptr+=20; break; case RSVP_CTYPE_TUNNEL_IPV6: if (obj_tlen < 36) return -1; ND_PRINT((ndo, "%s IPv6 Tunnel EndPoint: %s, Tunnel ID: 0x%04x, Extended Tunnel ID: %s", ident, ip6addr_string(ndo, obj_tptr), EXTRACT_16BITS(obj_tptr+18), ip6addr_string(ndo, obj_tptr + 20))); obj_tlen-=36; obj_tptr+=36; break; case RSVP_CTYPE_14: /* IPv6 p2mp LSP Tunnel */ if (obj_tlen < 26) return -1; ND_PRINT((ndo, "%s IPv6 P2MP LSP ID: 0x%08x, Tunnel ID: 0x%04x, Extended Tunnel ID: %s", ident, EXTRACT_32BITS(obj_tptr), EXTRACT_16BITS(obj_tptr+6), ip6addr_string(ndo, obj_tptr + 8))); obj_tlen-=26; obj_tptr+=26; break; #endif case RSVP_CTYPE_13: /* IPv4 p2mp LSP Tunnel */ if (obj_tlen < 12) return -1; ND_PRINT((ndo, "%s IPv4 P2MP LSP ID: %s, Tunnel ID: 0x%04x, Extended Tunnel ID: %s", ident, ipaddr_string(ndo, obj_tptr), EXTRACT_16BITS(obj_tptr+6), ipaddr_string(ndo, obj_tptr + 8))); obj_tlen-=12; obj_tptr+=12; break; case RSVP_CTYPE_TUNNEL_IPV4: case RSVP_CTYPE_UNI_IPV4: if (obj_tlen < 12) return -1; ND_PRINT((ndo, "%s IPv4 Tunnel EndPoint: %s, Tunnel ID: 0x%04x, Extended Tunnel ID: %s", ident, ipaddr_string(ndo, obj_tptr), EXTRACT_16BITS(obj_tptr+6), ipaddr_string(ndo, 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(struct in_addr)) return -1; ND_PRINT((ndo, "%s IPv4 Receiver Address: %s", ident, ipaddr_string(ndo, obj_tptr))); obj_tlen-=sizeof(struct in_addr); obj_tptr+=sizeof(struct in_addr); break; #ifdef INET6 case RSVP_CTYPE_IPV6: if (obj_tlen < sizeof(struct in6_addr)) return -1; ND_PRINT((ndo, "%s IPv6 Receiver Address: %s", ident, ip6addr_string(ndo, obj_tptr))); obj_tlen-=sizeof(struct in6_addr); obj_tptr+=sizeof(struct in6_addr); break; #endif default: hexdump=TRUE; } break; case RSVP_OBJ_NOTIFY_REQ: switch(rsvp_obj_ctype) { case RSVP_CTYPE_IPV4: if (obj_tlen < sizeof(struct in_addr)) return -1; ND_PRINT((ndo, "%s IPv4 Notify Node Address: %s", ident, ipaddr_string(ndo, obj_tptr))); obj_tlen-=sizeof(struct in_addr); obj_tptr+=sizeof(struct in_addr); break; #ifdef INET6 case RSVP_CTYPE_IPV6: if (obj_tlen < sizeof(struct in6_addr)) return-1; ND_PRINT((ndo, "%s IPv6 Notify Node Address: %s", ident, ip6addr_string(ndo, obj_tptr))); obj_tlen-=sizeof(struct in6_addr); obj_tptr+=sizeof(struct in6_addr); break; #endif 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((ndo, "%s Label: %u", ident, EXTRACT_32BITS(obj_tptr))); obj_tlen-=4; obj_tptr+=4; } break; case RSVP_CTYPE_2: if (obj_tlen < 4) return-1; ND_PRINT((ndo, "%s Generalized Label: %u", ident, EXTRACT_32BITS(obj_tptr))); obj_tlen-=4; obj_tptr+=4; break; case RSVP_CTYPE_3: if (obj_tlen < 12) return-1; ND_PRINT((ndo, "%s Waveband ID: %u%s Start Label: %u, Stop Label: %u", ident, EXTRACT_32BITS(obj_tptr), ident, EXTRACT_32BITS(obj_tptr+4), EXTRACT_32BITS(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) return-1; ND_PRINT((ndo, "%s Reservation Style: %s, Flags: [0x%02x]", ident, tok2str(rsvp_resstyle_values, "Unknown", EXTRACT_24BITS(obj_tptr+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) return-1; ND_PRINT((ndo, "%s Source Address: %s, Source Port: %u", ident, ipaddr_string(ndo, obj_tptr), EXTRACT_16BITS(obj_tptr + 6))); obj_tlen-=8; obj_tptr+=8; break; #ifdef INET6 case RSVP_CTYPE_IPV6: if (obj_tlen < 20) return-1; ND_PRINT((ndo, "%s Source Address: %s, Source Port: %u", ident, ip6addr_string(ndo, obj_tptr), EXTRACT_16BITS(obj_tptr + 18))); obj_tlen-=20; obj_tptr+=20; break; case RSVP_CTYPE_13: /* IPv6 p2mp LSP tunnel */ if (obj_tlen < 40) return-1; ND_PRINT((ndo, "%s IPv6 Tunnel Sender Address: %s, LSP ID: 0x%04x" "%s Sub-Group Originator ID: %s, Sub-Group ID: 0x%04x", ident, ip6addr_string(ndo, obj_tptr), EXTRACT_16BITS(obj_tptr+18), ident, ip6addr_string(ndo, obj_tptr+20), EXTRACT_16BITS(obj_tptr + 38))); obj_tlen-=40; obj_tptr+=40; break; #endif case RSVP_CTYPE_TUNNEL_IPV4: if (obj_tlen < 8) return-1; ND_PRINT((ndo, "%s IPv4 Tunnel Sender Address: %s, LSP-ID: 0x%04x", ident, ipaddr_string(ndo, obj_tptr), EXTRACT_16BITS(obj_tptr + 6))); obj_tlen-=8; obj_tptr+=8; break; case RSVP_CTYPE_12: /* IPv4 p2mp LSP tunnel */ if (obj_tlen < 16) return-1; ND_PRINT((ndo, "%s IPv4 Tunnel Sender Address: %s, LSP ID: 0x%04x" "%s Sub-Group Originator ID: %s, Sub-Group ID: 0x%04x", ident, ipaddr_string(ndo, obj_tptr), EXTRACT_16BITS(obj_tptr+6), ident, ipaddr_string(ndo, obj_tptr+8), EXTRACT_16BITS(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((ndo, "%s L3 Protocol ID: %s", ident, tok2str(ethertype_values, "Unknown Protocol (0x%04x)", EXTRACT_16BITS(obj_tptr + 2)))); obj_tlen-=4; obj_tptr+=4; } break; case RSVP_CTYPE_2: if (obj_tlen < 12) return-1; ND_PRINT((ndo, "%s L3 Protocol ID: %s", ident, tok2str(ethertype_values, "Unknown Protocol (0x%04x)", EXTRACT_16BITS(obj_tptr + 2)))); ND_PRINT((ndo, ",%s merge capability",((*(obj_tptr + 4)) & 0x80) ? "no" : "" )); ND_PRINT((ndo, "%s Minimum VPI/VCI: %u/%u", ident, (EXTRACT_16BITS(obj_tptr+4))&0xfff, (EXTRACT_16BITS(obj_tptr + 6)) & 0xfff)); ND_PRINT((ndo, "%s Maximum VPI/VCI: %u/%u", ident, (EXTRACT_16BITS(obj_tptr+8))&0xfff, (EXTRACT_16BITS(obj_tptr + 10)) & 0xfff)); obj_tlen-=12; obj_tptr+=12; break; case RSVP_CTYPE_3: if (obj_tlen < 12) return-1; ND_PRINT((ndo, "%s L3 Protocol ID: %s", ident, tok2str(ethertype_values, "Unknown Protocol (0x%04x)", EXTRACT_16BITS(obj_tptr + 2)))); ND_PRINT((ndo, "%s Minimum/Maximum DLCI: %u/%u, %s%s bit DLCI", ident, (EXTRACT_32BITS(obj_tptr+4))&0x7fffff, (EXTRACT_32BITS(obj_tptr+8))&0x7fffff, (((EXTRACT_16BITS(obj_tptr+4)>>7)&3) == 0 ) ? "10" : "", (((EXTRACT_16BITS(obj_tptr + 4) >> 7) & 3) == 2 ) ? "23" : "")); obj_tlen-=12; obj_tptr+=12; break; case RSVP_CTYPE_4: if (obj_tlen < 4) return-1; ND_PRINT((ndo, "%s LSP Encoding Type: %s (%u)", ident, tok2str(gmpls_encoding_values, "Unknown", *obj_tptr), *obj_tptr)); ND_PRINT((ndo, "%s Switching Type: %s (%u), Payload ID: %s (0x%04x)", ident, tok2str(gmpls_switch_cap_values, "Unknown", *(obj_tptr+1)), *(obj_tptr+1), tok2str(gmpls_payload_values, "Unknown", EXTRACT_16BITS(obj_tptr+2)), EXTRACT_16BITS(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 ) { ND_PRINT((ndo, "%s Subobject Type: %s, length %u", ident, tok2str(rsvp_obj_xro_values, "Unknown %u", RSVP_OBJ_XRO_MASK_SUBOBJ(*obj_tptr)), *(obj_tptr + 1))); if (*(obj_tptr+1) == 0) { /* prevent infinite loops */ ND_PRINT((ndo, "%s ERROR: zero length ERO subtype", ident)); break; } switch(RSVP_OBJ_XRO_MASK_SUBOBJ(*obj_tptr)) { case RSVP_OBJ_XRO_IPV4: ND_PRINT((ndo, ", %s, %s/%u, Flags: [%s]", RSVP_OBJ_XRO_MASK_LOOSE(*obj_tptr) ? "Loose" : "Strict", ipaddr_string(ndo, obj_tptr+2), *(obj_tptr+6), bittok2str(rsvp_obj_rro_flag_values, "none", *(obj_tptr + 7)))); /* rfc3209 says that this field is rsvd. */ break; case RSVP_OBJ_XRO_LABEL: ND_PRINT((ndo, ", Flags: [%s] (%#x), Class-Type: %s (%u), %u", bittok2str(rsvp_obj_rro_label_flag_values, "none", *(obj_tptr+2)), *(obj_tptr+2), tok2str(rsvp_ctype_values, "Unknown", *(obj_tptr+3) + 256*RSVP_OBJ_RRO), *(obj_tptr+3), EXTRACT_32BITS(obj_tptr + 4))); } obj_tlen-=*(obj_tptr+1); obj_tptr+=*(obj_tptr+1); } 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) return-1; ND_PRINT((ndo, "%s Source Instance: 0x%08x, Destination Instance: 0x%08x", ident, EXTRACT_32BITS(obj_tptr), EXTRACT_32BITS(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) return-1; ND_PRINT((ndo, "%s Restart Time: %ums, Recovery Time: %ums", ident, EXTRACT_32BITS(obj_tptr), EXTRACT_32BITS(obj_tptr + 4))); obj_tlen-=8; obj_tptr+=8; break; default: hexdump=TRUE; } break; case RSVP_OBJ_SESSION_ATTRIBUTE: switch(rsvp_obj_ctype) { case RSVP_CTYPE_TUNNEL_IPV4: if (obj_tlen < 4) return-1; namelen = *(obj_tptr+3); if (obj_tlen < 4+namelen) return-1; ND_PRINT((ndo, "%s Session Name: ", ident)); for (i = 0; i < namelen; i++) safeputchar(ndo, *(obj_tptr + 4 + i)); ND_PRINT((ndo, "%s Setup Priority: %u, Holding Priority: %u, Flags: [%s] (%#x)", ident, (int)*obj_tptr, (int)*(obj_tptr+1), bittok2str(rsvp_session_attribute_flag_values, "none", *(obj_tptr+2)), *(obj_tptr + 2))); obj_tlen-=4+*(obj_tptr+3); obj_tptr+=4+*(obj_tptr+3); break; default: hexdump=TRUE; } break; case RSVP_OBJ_GENERALIZED_UNI: switch(rsvp_obj_ctype) { int subobj_type,af,subobj_len,total_subobj_len; case RSVP_CTYPE_1: if (obj_tlen < 4) return-1; /* read variable length subobjects */ total_subobj_len = obj_tlen; while(total_subobj_len > 0) { subobj_len = EXTRACT_16BITS(obj_tptr); subobj_type = (EXTRACT_16BITS(obj_tptr+2))>>8; af = (EXTRACT_16BITS(obj_tptr+2))&0x00FF; ND_PRINT((ndo, "%s Subobject Type: %s (%u), AF: %s (%u), length: %u", ident, tok2str(rsvp_obj_generalized_uni_values, "Unknown", subobj_type), subobj_type, tok2str(af_values, "Unknown", af), af, subobj_len)); 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) return -1; ND_PRINT((ndo, "%s UNI IPv4 TNA address: %s", ident, ipaddr_string(ndo, obj_tptr + 4))); break; #ifdef INET6 case AFNUM_INET6: if (subobj_len < 20) return -1; ND_PRINT((ndo, "%s UNI IPv6 TNA address: %s", ident, ip6addr_string(ndo, obj_tptr + 4))); break; #endif 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) { /* unless we have a TLV parser lets just hexdump */ hexdump=TRUE; } break; case RSVP_GEN_UNI_SUBOBJ_EGRESS_LABEL: if (subobj_len < 16) { return -1; } ND_PRINT((ndo, "%s U-bit: %x, Label type: %u, Logical port id: %u, Label: %u", ident, ((EXTRACT_32BITS(obj_tptr+4))>>31), ((EXTRACT_32BITS(obj_tptr+4))&0xFF), EXTRACT_32BITS(obj_tptr+8), EXTRACT_32BITS(obj_tptr + 12))); break; case RSVP_GEN_UNI_SUBOBJ_SERVICE_LEVEL: if (subobj_len < 8) { return -1; } ND_PRINT((ndo, "%s Service level: %u", ident, (EXTRACT_32BITS(obj_tptr + 4)) >> 24)); break; default: hexdump=TRUE; break; } total_subobj_len-=subobj_len; obj_tptr+=subobj_len; obj_tlen+=subobj_len; } if (total_subobj_len) { /* unless we have a TLV parser lets just hexdump */ hexdump=TRUE; } 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) return-1; ND_PRINT((ndo, "%s Previous/Next Interface: %s, Logical Interface Handle: 0x%08x", ident, ipaddr_string(ndo, obj_tptr), EXTRACT_32BITS(obj_tptr + 4))); obj_tlen-=8; obj_tptr+=8; if (obj_tlen) hexdump=TRUE; /* unless we have a TLV parser lets just hexdump */ break; #ifdef INET6 case RSVP_CTYPE_4: /* fall through - FIXME add TLV parser */ case RSVP_CTYPE_IPV6: if (obj_tlen < 20) return-1; ND_PRINT((ndo, "%s Previous/Next Interface: %s, Logical Interface Handle: 0x%08x", ident, ip6addr_string(ndo, obj_tptr), EXTRACT_32BITS(obj_tptr + 16))); obj_tlen-=20; obj_tptr+=20; hexdump=TRUE; /* unless we have a TLV parser lets just hexdump */ break; #endif default: hexdump=TRUE; } break; case RSVP_OBJ_TIME_VALUES: switch(rsvp_obj_ctype) { case RSVP_CTYPE_1: if (obj_tlen < 4) return-1; ND_PRINT((ndo, "%s Refresh Period: %ums", ident, EXTRACT_32BITS(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) return-1; ND_PRINT((ndo, "%s Msg-Version: %u, length: %u", ident, (*obj_tptr & 0xf0) >> 4, EXTRACT_16BITS(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=EXTRACT_16BITS(obj_tptr+2)<<2; ND_PRINT((ndo, "%s Service Type: %s (%u), break bit %s set, Service length: %u", ident, tok2str(rsvp_intserv_service_type_values,"unknown",*(obj_tptr)), *(obj_tptr), (*(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) return-1; ND_PRINT((ndo, "%s Source Address: %s, Source Port: %u", ident, ipaddr_string(ndo, obj_tptr), EXTRACT_16BITS(obj_tptr + 6))); obj_tlen-=8; obj_tptr+=8; break; #ifdef INET6 case RSVP_CTYPE_IPV6: if (obj_tlen < 20) return-1; ND_PRINT((ndo, "%s Source Address: %s, Source Port: %u", ident, ip6addr_string(ndo, obj_tptr), EXTRACT_16BITS(obj_tptr + 18))); obj_tlen-=20; obj_tptr+=20; break; case RSVP_CTYPE_3: if (obj_tlen < 20) return-1; ND_PRINT((ndo, "%s Source Address: %s, Flow Label: %u", ident, ip6addr_string(ndo, obj_tptr), EXTRACT_24BITS(obj_tptr + 17))); obj_tlen-=20; obj_tptr+=20; break; case RSVP_CTYPE_TUNNEL_IPV6: if (obj_tlen < 20) return-1; ND_PRINT((ndo, "%s Source Address: %s, LSP-ID: 0x%04x", ident, ipaddr_string(ndo, obj_tptr), EXTRACT_16BITS(obj_tptr + 18))); obj_tlen-=20; obj_tptr+=20; break; case RSVP_CTYPE_13: /* IPv6 p2mp LSP tunnel */ if (obj_tlen < 40) return-1; ND_PRINT((ndo, "%s IPv6 Tunnel Sender Address: %s, LSP ID: 0x%04x" "%s Sub-Group Originator ID: %s, Sub-Group ID: 0x%04x", ident, ip6addr_string(ndo, obj_tptr), EXTRACT_16BITS(obj_tptr+18), ident, ip6addr_string(ndo, obj_tptr+20), EXTRACT_16BITS(obj_tptr + 38))); obj_tlen-=40; obj_tptr+=40; break; #endif case RSVP_CTYPE_TUNNEL_IPV4: if (obj_tlen < 8) return-1; ND_PRINT((ndo, "%s Source Address: %s, LSP-ID: 0x%04x", ident, ipaddr_string(ndo, obj_tptr), EXTRACT_16BITS(obj_tptr + 6))); obj_tlen-=8; obj_tptr+=8; break; case RSVP_CTYPE_12: /* IPv4 p2mp LSP tunnel */ if (obj_tlen < 16) return-1; ND_PRINT((ndo, "%s IPv4 Tunnel Sender Address: %s, LSP ID: 0x%04x" "%s Sub-Group Originator ID: %s, Sub-Group ID: 0x%04x", ident, ipaddr_string(ndo, obj_tptr), EXTRACT_16BITS(obj_tptr+6), ident, ipaddr_string(ndo, obj_tptr+8), EXTRACT_16BITS(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; bw.i = EXTRACT_32BITS(obj_ptr.rsvp_obj_frr->bandwidth); switch(rsvp_obj_ctype) { case RSVP_CTYPE_1: /* new style */ if (obj_tlen < sizeof(struct rsvp_obj_frr_t)) return-1; ND_PRINT((ndo, "%s Setup Priority: %u, Holding Priority: %u, Hop-limit: %u, Bandwidth: %.10g Mbps", ident, (int)obj_ptr.rsvp_obj_frr->setup_prio, (int)obj_ptr.rsvp_obj_frr->hold_prio, (int)obj_ptr.rsvp_obj_frr->hop_limit, bw.f * 8 / 1000000)); ND_PRINT((ndo, "%s Include-any: 0x%08x, Exclude-any: 0x%08x, Include-all: 0x%08x", ident, EXTRACT_32BITS(obj_ptr.rsvp_obj_frr->include_any), EXTRACT_32BITS(obj_ptr.rsvp_obj_frr->exclude_any), EXTRACT_32BITS(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) return-1; ND_PRINT((ndo, "%s Setup Priority: %u, Holding Priority: %u, Hop-limit: %u, Bandwidth: %.10g Mbps", ident, (int)obj_ptr.rsvp_obj_frr->setup_prio, (int)obj_ptr.rsvp_obj_frr->hold_prio, (int)obj_ptr.rsvp_obj_frr->hop_limit, bw.f * 8 / 1000000)); ND_PRINT((ndo, "%s Include Colors: 0x%08x, Exclude Colors: 0x%08x", ident, EXTRACT_32BITS(obj_ptr.rsvp_obj_frr->include_any), EXTRACT_32BITS(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((ndo, "%s PLR-ID: %s, Avoid-Node-ID: %s", ident, ipaddr_string(ndo, obj_tptr), ipaddr_string(ndo, 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: ND_PRINT((ndo, "%s CT: %u", ident, EXTRACT_32BITS(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) return-1; error_code=*(obj_tptr+5); error_value=EXTRACT_16BITS(obj_tptr+6); ND_PRINT((ndo, "%s Error Node Address: %s, Flags: [0x%02x]%s Error Code: %s (%u)", ident, ipaddr_string(ndo, obj_tptr), *(obj_tptr+4), ident, tok2str(rsvp_obj_error_code_values,"unknown",error_code), error_code)); switch (error_code) { case RSVP_OBJ_ERROR_SPEC_CODE_ROUTING: ND_PRINT((ndo, ", 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((ndo, ", Error Value: %s (%u)", tok2str(rsvp_obj_error_code_diffserv_te_values,"unknown",error_value), error_value)); break; default: ND_PRINT((ndo, ", Unknown Error Value (%u)", error_value)); break; } obj_tlen-=8; obj_tptr+=8; break; #ifdef INET6 case RSVP_CTYPE_4: /* fall through - FIXME add TLV parser */ case RSVP_CTYPE_IPV6: if (obj_tlen < 20) return-1; error_code=*(obj_tptr+17); error_value=EXTRACT_16BITS(obj_tptr+18); ND_PRINT((ndo, "%s Error Node Address: %s, Flags: [0x%02x]%s Error Code: %s (%u)", ident, ip6addr_string(ndo, obj_tptr), *(obj_tptr+16), ident, tok2str(rsvp_obj_error_code_values,"unknown",error_code), error_code)); switch (error_code) { case RSVP_OBJ_ERROR_SPEC_CODE_ROUTING: ND_PRINT((ndo, ", 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; #endif default: hexdump=TRUE; } break; case RSVP_OBJ_PROPERTIES: switch(rsvp_obj_ctype) { case RSVP_CTYPE_1: if (obj_tlen < 4) return-1; padbytes = EXTRACT_16BITS(obj_tptr+2); ND_PRINT((ndo, "%s TLV count: %u, padding bytes: %u", ident, EXTRACT_16BITS(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((ndo, "%s %s TLV (0x%02x), length: %u", /* length includes header */ ident, tok2str(rsvp_obj_prop_tlv_values,"unknown",*obj_tptr), *obj_tptr, *(obj_tptr + 1))); if (obj_tlen < *(obj_tptr+1)) return-1; if (*(obj_tptr+1) < 2) return -1; print_unknown_data(ndo, obj_tptr + 2, "\n\t\t", *(obj_tptr + 1) - 2); obj_tlen-=*(obj_tptr+1); obj_tptr+=*(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 < 8) return-1; ND_PRINT((ndo, "%s Flags [0x%02x], epoch: %u", ident, *obj_tptr, EXTRACT_24BITS(obj_tptr + 1))); obj_tlen-=4; obj_tptr+=4; /* loop through as long there are no messages left */ while(obj_tlen >= 4) { ND_PRINT((ndo, "%s Message-ID 0x%08x (%u)", ident, EXTRACT_32BITS(obj_tptr), EXTRACT_32BITS(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)) return-1; obj_ptr.rsvp_obj_integrity = (const struct rsvp_obj_integrity_t *)obj_tptr; ND_PRINT((ndo, "%s Key-ID 0x%04x%08x, Sequence 0x%08x%08x, Flags [%s]", ident, EXTRACT_16BITS(obj_ptr.rsvp_obj_integrity->key_id), EXTRACT_32BITS(obj_ptr.rsvp_obj_integrity->key_id+2), EXTRACT_32BITS(obj_ptr.rsvp_obj_integrity->sequence), EXTRACT_32BITS(obj_ptr.rsvp_obj_integrity->sequence+4), bittok2str(rsvp_obj_integrity_flag_values, "none", obj_ptr.rsvp_obj_integrity->flags))); ND_PRINT((ndo, "%s MD5-sum 0x%08x%08x%08x%08x ", ident, EXTRACT_32BITS(obj_ptr.rsvp_obj_integrity->digest), EXTRACT_32BITS(obj_ptr.rsvp_obj_integrity->digest+4), EXTRACT_32BITS(obj_ptr.rsvp_obj_integrity->digest+8), EXTRACT_32BITS(obj_ptr.rsvp_obj_integrity->digest + 12))); #ifdef HAVE_LIBCRYPTO sigcheck = signature_verify(ndo, pptr, plen, (unsigned char *)obj_ptr.\ rsvp_obj_integrity->digest); #else sigcheck = CANT_CHECK_SIGNATURE; #endif ND_PRINT((ndo, " (%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) return-1; ND_PRINT((ndo, "%s Flags [%s]", ident, bittok2str(rsvp_obj_admin_status_flag_values, "none", EXTRACT_32BITS(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) return-1; action = (EXTRACT_16BITS(obj_tptr)>>8); ND_PRINT((ndo, "%s Action: %s (%u), Label type: %u", ident, tok2str(rsvp_obj_label_set_action_values, "Unknown", action), action, ((EXTRACT_32BITS(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) return -1; ND_PRINT((ndo, "%s Start range: %u, End range: %u", ident, EXTRACT_32BITS(obj_tptr+4), EXTRACT_32BITS(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((ndo, "%s Subchannel #%u: %u", ident, subchannel, EXTRACT_32BITS(obj_tptr))); obj_tptr+=4; obj_tlen-=4; subchannel++; } break; } break; default: hexdump=TRUE; } case RSVP_OBJ_S2L: switch (rsvp_obj_ctype) { case RSVP_CTYPE_IPV4: if (obj_tlen < 4) return-1; ND_PRINT((ndo, "%s Sub-LSP destination address: %s", ident, ipaddr_string(ndo, obj_tptr))); obj_tlen-=4; obj_tptr+=4; break; #ifdef INET6 case RSVP_CTYPE_IPV6: if (obj_tlen < 16) return-1; ND_PRINT((ndo, "%s Sub-LSP destination address: %s", ident, ip6addr_string(ndo, obj_tptr))); obj_tlen-=16; obj_tptr+=16; break; #endif default: hexdump=TRUE; } /* * 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; trunc: ND_PRINT((ndo, "\n\t\t packet exceeded snapshot")); return -1; } void rsvp_print(netdissect_options *ndo, - register const u_char *pptr, register u_int len) { - + register const u_char *pptr, register u_int len) +{ struct rsvp_common_header *rsvp_com_header; const u_char *tptr,*subtptr; u_short plen, tlen, subtlen; tptr=pptr; rsvp_com_header = (struct rsvp_common_header *)pptr; ND_TCHECK(*rsvp_com_header); /* * Sanity checking of the header. */ if (RSVP_EXTRACT_VERSION(rsvp_com_header->version_flags) != RSVP_VERSION) { ND_PRINT((ndo, "ERROR: RSVP version %u packet not supported", RSVP_EXTRACT_VERSION(rsvp_com_header->version_flags))); return; } /* in non-verbose mode just lets print the basic Message Type*/ if (ndo->ndo_vflag < 1) { ND_PRINT((ndo, "RSVPv%u %s Message, length: %u", RSVP_EXTRACT_VERSION(rsvp_com_header->version_flags), tok2str(rsvp_msg_type_values, "unknown (%u)",rsvp_com_header->msg_type), len)); return; } /* ok they seem to want to know everything - lets fully decode it */ plen = tlen = EXTRACT_16BITS(rsvp_com_header->length); ND_PRINT((ndo, "\n\tRSVPv%u %s Message (%u), Flags: [%s], length: %u, ttl: %u, checksum: 0x%04x", RSVP_EXTRACT_VERSION(rsvp_com_header->version_flags), tok2str(rsvp_msg_type_values, "unknown, type: %u",rsvp_com_header->msg_type), rsvp_com_header->msg_type, bittok2str(rsvp_header_flag_values,"none",RSVP_EXTRACT_FLAGS(rsvp_com_header->version_flags)), tlen, rsvp_com_header->ttl, EXTRACT_16BITS(rsvp_com_header->checksum))); /* * Clear checksum prior to signature verification. */ rsvp_com_header->checksum[0] = 0; rsvp_com_header->checksum[1] = 0; if (tlen < sizeof(const struct rsvp_common_header)) { ND_PRINT((ndo, "ERROR: common header too short %u < %lu", tlen, (unsigned long)sizeof(const struct rsvp_common_header))); return; } tptr+=sizeof(const struct rsvp_common_header); tlen-=sizeof(const struct rsvp_common_header); switch(rsvp_com_header->msg_type) { case RSVP_MSGTYPE_AGGREGATE: while(tlen > 0) { subtptr=tptr; rsvp_com_header = (struct rsvp_common_header *)subtptr; ND_TCHECK(*rsvp_com_header); /* * Sanity checking of the header. */ if (RSVP_EXTRACT_VERSION(rsvp_com_header->version_flags) != RSVP_VERSION) { ND_PRINT((ndo, "ERROR: RSVP version %u packet not supported", RSVP_EXTRACT_VERSION(rsvp_com_header->version_flags))); return; } subtlen=EXTRACT_16BITS(rsvp_com_header->length); ND_PRINT((ndo, "\n\t RSVPv%u %s Message (%u), Flags: [%s], length: %u, ttl: %u, checksum: 0x%04x", RSVP_EXTRACT_VERSION(rsvp_com_header->version_flags), tok2str(rsvp_msg_type_values, "unknown, type: %u",rsvp_com_header->msg_type), rsvp_com_header->msg_type, bittok2str(rsvp_header_flag_values,"none",RSVP_EXTRACT_FLAGS(rsvp_com_header->version_flags)), subtlen, rsvp_com_header->ttl, EXTRACT_16BITS(rsvp_com_header->checksum))); /* * Clear checksum prior to signature verification. */ rsvp_com_header->checksum[0] = 0; rsvp_com_header->checksum[1] = 0; if (subtlen < sizeof(const struct rsvp_common_header)) { ND_PRINT((ndo, "ERROR: common header too short %u < %lu", subtlen, (unsigned long)sizeof(const struct rsvp_common_header))); return; } if (tlen < subtlen) { ND_PRINT((ndo, "ERROR: common header too large %u > %u", subtlen, tlen)); return; } subtptr+=sizeof(const struct rsvp_common_header); subtlen-=sizeof(const struct rsvp_common_header); if (rsvp_obj_print(ndo, pptr, plen, subtptr, "\n\t ", subtlen) == -1) return; tptr+=subtlen+sizeof(const struct rsvp_common_header); tlen-=subtlen+sizeof(const 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: if (rsvp_obj_print(ndo, pptr, plen, tptr, "\n\t ", tlen) == -1) return; break; default: print_unknown_data(ndo, tptr, "\n\t ", tlen); break; } return; trunc: ND_PRINT((ndo, "\n\t\t packet exceeded snapshot")); } Index: head/contrib/tcpdump/print-rtsp.c =================================================================== --- head/contrib/tcpdump/print-rtsp.c (nonexistent) +++ head/contrib/tcpdump/print-rtsp.c (revision 285275) @@ -0,0 +1,50 @@ +/* + * 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 lint +static const char rcsid[] _U_ = + "@(#) $Header$"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include +#include + +#include "interface.h" +#include "extract.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) +{ + txtproto_print(ndo, pptr, len, "rtsp", rtspcmds, RESP_CODE_SECOND_TOKEN); +} Property changes on: head/contrib/tcpdump/print-rtsp.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/contrib/tcpdump/print-sflow.c =================================================================== --- head/contrib/tcpdump/print-sflow.c (revision 285274) +++ head/contrib/tcpdump/print-sflow.c (revision 285275) @@ -1,942 +1,941 @@ /* * 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. * * The SFLOW protocol as per http://www.sflow.org/developers/specifications.php * * Original code by Carles Kishimoto * * Expansion and refactoring by Rick Jones */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "interface.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 { uint8_t version[4]; uint8_t ip_version[4]; uint8_t agent[4]; uint8_t agent_id[4]; uint8_t seqnum[4]; uint8_t uptime[4]; uint8_t samples[4]; }; struct sflow_sample_header { uint8_t format[4]; uint8_t len[4]; }; #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 { uint8_t seqnum[4]; uint8_t typesource[4]; uint8_t rate[4]; uint8_t pool[4]; uint8_t drops[4]; uint8_t in_interface[4]; uint8_t out_interface[4]; uint8_t records[4]; }; struct sflow_expanded_flow_sample_t { uint8_t seqnum[4]; uint8_t type[4]; uint8_t index[4]; uint8_t rate[4]; uint8_t pool[4]; uint8_t drops[4]; uint8_t in_interface_format[4]; uint8_t in_interface_value[4]; uint8_t out_interface_format[4]; uint8_t out_interface_value[4]; uint8_t records[4]; }; #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 { uint8_t protocol[4]; uint8_t length[4]; uint8_t stripped_bytes[4]; uint8_t header_size[4]; }; struct sflow_ethernet_frame_t { uint8_t length[4]; uint8_t src_mac[8]; uint8_t dst_mac[8]; uint8_t type[4]; }; struct sflow_extended_switch_data_t { uint8_t src_vlan[4]; uint8_t src_pri[4]; uint8_t dst_vlan[4]; uint8_t dst_pri[4]; }; struct sflow_counter_record_t { uint8_t format[4]; uint8_t length[4]; }; struct sflow_flow_record_t { uint8_t format[4]; uint8_t length[4]; }; struct sflow_counter_sample_t { uint8_t seqnum[4]; uint8_t typesource[4]; uint8_t records[4]; }; struct sflow_expanded_counter_sample_t { uint8_t seqnum[4]; uint8_t type[4]; uint8_t index[4]; uint8_t records[4]; }; #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 { uint8_t ifindex[4]; uint8_t iftype[4]; uint8_t ifspeed[8]; uint8_t ifdirection[4]; uint8_t ifstatus[4]; uint8_t ifinoctets[8]; uint8_t ifinunicastpkts[4]; uint8_t ifinmulticastpkts[4]; uint8_t ifinbroadcastpkts[4]; uint8_t ifindiscards[4]; uint8_t ifinerrors[4]; uint8_t ifinunkownprotos[4]; uint8_t ifoutoctets[8]; uint8_t ifoutunicastpkts[4]; uint8_t ifoutmulticastpkts[4]; uint8_t ifoutbroadcastpkts[4]; uint8_t ifoutdiscards[4]; uint8_t ifouterrors[4]; uint8_t ifpromiscmode[4]; }; struct sflow_ethernet_counter_t { uint8_t alignerrors[4]; uint8_t fcserrors[4]; uint8_t single_collision_frames[4]; uint8_t multiple_collision_frames[4]; uint8_t test_errors[4]; uint8_t deferred_transmissions[4]; uint8_t late_collisions[4]; uint8_t excessive_collisions[4]; uint8_t mac_transmit_errors[4]; uint8_t carrier_sense_errors[4]; uint8_t frame_too_longs[4]; uint8_t mac_receive_errors[4]; uint8_t symbol_errors[4]; }; struct sflow_100basevg_counter_t { uint8_t in_highpriority_frames[4]; uint8_t in_highpriority_octets[8]; uint8_t in_normpriority_frames[4]; uint8_t in_normpriority_octets[8]; uint8_t in_ipmerrors[4]; uint8_t in_oversized[4]; uint8_t in_data_errors[4]; uint8_t in_null_addressed_frames[4]; uint8_t out_highpriority_frames[4]; uint8_t out_highpriority_octets[8]; uint8_t transitioninto_frames[4]; uint8_t hc_in_highpriority_octets[8]; uint8_t hc_in_normpriority_octets[8]; uint8_t hc_out_highpriority_octets[8]; }; struct sflow_vlan_counter_t { uint8_t vlan_id[4]; uint8_t octets[8]; uint8_t unicast_pkt[4]; uint8_t multicast_pkt[4]; uint8_t broadcast_pkt[4]; uint8_t discards[4]; }; static int print_sflow_counter_generic(netdissect_options *ndo, - const u_char *pointer, u_int len) { - + 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((ndo, "\n\t ifindex %u, iftype %u, ifspeed %" PRIu64 ", ifdirection %u (%s)", EXTRACT_32BITS(sflow_gen_counter->ifindex), EXTRACT_32BITS(sflow_gen_counter->iftype), EXTRACT_64BITS(sflow_gen_counter->ifspeed), EXTRACT_32BITS(sflow_gen_counter->ifdirection), tok2str(sflow_iface_direction_values, "Unknown", EXTRACT_32BITS(sflow_gen_counter->ifdirection)))); ND_PRINT((ndo, "\n\t ifstatus %u, adminstatus: %s, operstatus: %s", EXTRACT_32BITS(sflow_gen_counter->ifstatus), EXTRACT_32BITS(sflow_gen_counter->ifstatus)&1 ? "up" : "down", (EXTRACT_32BITS(sflow_gen_counter->ifstatus)>>1)&1 ? "up" : "down")); ND_PRINT((ndo, "\n\t In octets %" PRIu64 ", unicast pkts %u, multicast pkts %u, broadcast pkts %u, discards %u", EXTRACT_64BITS(sflow_gen_counter->ifinoctets), EXTRACT_32BITS(sflow_gen_counter->ifinunicastpkts), EXTRACT_32BITS(sflow_gen_counter->ifinmulticastpkts), EXTRACT_32BITS(sflow_gen_counter->ifinbroadcastpkts), EXTRACT_32BITS(sflow_gen_counter->ifindiscards))); ND_PRINT((ndo, "\n\t In errors %u, unknown protos %u", EXTRACT_32BITS(sflow_gen_counter->ifinerrors), EXTRACT_32BITS(sflow_gen_counter->ifinunkownprotos))); ND_PRINT((ndo, "\n\t Out octets %" PRIu64 ", unicast pkts %u, multicast pkts %u, broadcast pkts %u, discards %u", EXTRACT_64BITS(sflow_gen_counter->ifoutoctets), EXTRACT_32BITS(sflow_gen_counter->ifoutunicastpkts), EXTRACT_32BITS(sflow_gen_counter->ifoutmulticastpkts), EXTRACT_32BITS(sflow_gen_counter->ifoutbroadcastpkts), EXTRACT_32BITS(sflow_gen_counter->ifoutdiscards))); ND_PRINT((ndo, "\n\t Out errors %u, promisc mode %u", EXTRACT_32BITS(sflow_gen_counter->ifouterrors), EXTRACT_32BITS(sflow_gen_counter->ifpromiscmode))); return 0; } static int print_sflow_counter_ethernet(netdissect_options *ndo, - const u_char *pointer, u_int len){ - + 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((ndo, "\n\t align errors %u, fcs errors %u, single collision %u, multiple collision %u, test error %u", EXTRACT_32BITS(sflow_eth_counter->alignerrors), EXTRACT_32BITS(sflow_eth_counter->fcserrors), EXTRACT_32BITS(sflow_eth_counter->single_collision_frames), EXTRACT_32BITS(sflow_eth_counter->multiple_collision_frames), EXTRACT_32BITS(sflow_eth_counter->test_errors))); ND_PRINT((ndo, "\n\t deferred %u, late collision %u, excessive collision %u, mac trans error %u", EXTRACT_32BITS(sflow_eth_counter->deferred_transmissions), EXTRACT_32BITS(sflow_eth_counter->late_collisions), EXTRACT_32BITS(sflow_eth_counter->excessive_collisions), EXTRACT_32BITS(sflow_eth_counter->mac_transmit_errors))); ND_PRINT((ndo, "\n\t carrier error %u, frames too long %u, mac receive errors %u, symbol errors %u", EXTRACT_32BITS(sflow_eth_counter->carrier_sense_errors), EXTRACT_32BITS(sflow_eth_counter->frame_too_longs), EXTRACT_32BITS(sflow_eth_counter->mac_receive_errors), EXTRACT_32BITS(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_) { - + 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 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((ndo, "\n\t in high prio frames %u, in high prio octets %" PRIu64, EXTRACT_32BITS(sflow_100basevg_counter->in_highpriority_frames), EXTRACT_64BITS(sflow_100basevg_counter->in_highpriority_octets))); ND_PRINT((ndo, "\n\t in norm prio frames %u, in norm prio octets %" PRIu64, EXTRACT_32BITS(sflow_100basevg_counter->in_normpriority_frames), EXTRACT_64BITS(sflow_100basevg_counter->in_normpriority_octets))); ND_PRINT((ndo, "\n\t in ipm errors %u, oversized %u, in data errors %u, null addressed frames %u", EXTRACT_32BITS(sflow_100basevg_counter->in_ipmerrors), EXTRACT_32BITS(sflow_100basevg_counter->in_oversized), EXTRACT_32BITS(sflow_100basevg_counter->in_data_errors), EXTRACT_32BITS(sflow_100basevg_counter->in_null_addressed_frames))); ND_PRINT((ndo, "\n\t out high prio frames %u, out high prio octets %" PRIu64 ", trans into frames %u", EXTRACT_32BITS(sflow_100basevg_counter->out_highpriority_frames), EXTRACT_64BITS(sflow_100basevg_counter->out_highpriority_octets), EXTRACT_32BITS(sflow_100basevg_counter->transitioninto_frames))); ND_PRINT((ndo, "\n\t in hc high prio octets %" PRIu64 ", in hc norm prio octets %" PRIu64 ", out hc high prio octets %" PRIu64, EXTRACT_64BITS(sflow_100basevg_counter->hc_in_highpriority_octets), EXTRACT_64BITS(sflow_100basevg_counter->hc_in_normpriority_octets), EXTRACT_64BITS(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 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((ndo, "\n\t vlan_id %u, octets %" PRIu64 ", unicast_pkt %u, multicast_pkt %u, broadcast_pkt %u, discards %u", EXTRACT_32BITS(sflow_vlan_counter->vlan_id), EXTRACT_64BITS(sflow_vlan_counter->octets), EXTRACT_32BITS(sflow_vlan_counter->unicast_pkt), EXTRACT_32BITS(sflow_vlan_counter->multicast_pkt), EXTRACT_32BITS(sflow_vlan_counter->broadcast_pkt), EXTRACT_32BITS(sflow_vlan_counter->discards))); return 0; } struct sflow_processor_counter_t { uint8_t five_sec_util[4]; uint8_t one_min_util[4]; uint8_t five_min_util[4]; uint8_t total_memory[8]; uint8_t free_memory[8]; }; static int print_sflow_counter_processor(netdissect_options *ndo, - const u_char *pointer, u_int len) { - + 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((ndo, "\n\t 5sec %u, 1min %u, 5min %u, total_mem %" PRIu64 ", total_mem %" PRIu64, EXTRACT_32BITS(sflow_processor_counter->five_sec_util), EXTRACT_32BITS(sflow_processor_counter->one_min_util), EXTRACT_32BITS(sflow_processor_counter->five_min_util), EXTRACT_64BITS(sflow_processor_counter->total_memory), EXTRACT_64BITS(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) { - + 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 = EXTRACT_32BITS(sflow_counter_record->format); counter_type = enterprise & 0x0FFF; enterprise = enterprise >> 20; counter_len = EXTRACT_32BITS(sflow_counter_record->length); ND_PRINT((ndo, "\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 u_char *pointer, u_int len) +{ const struct sflow_counter_sample_t *sflow_counter_sample; u_int nrecords; u_int typesource; u_int type; u_int index; if (len < sizeof(struct sflow_counter_sample_t)) return 1; sflow_counter_sample = (const struct sflow_counter_sample_t *)pointer; typesource = EXTRACT_32BITS(sflow_counter_sample->typesource); nrecords = EXTRACT_32BITS(sflow_counter_sample->records); type = typesource >> 24; index = typesource & 0x0FFF; ND_PRINT((ndo, " seqnum %u, type %u, idx %u, records %u", EXTRACT_32BITS(sflow_counter_sample->seqnum), type, 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 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 = EXTRACT_32BITS(sflow_expanded_counter_sample->records); ND_PRINT((ndo, " seqnum %u, type %u, idx %u, records %u", EXTRACT_32BITS(sflow_expanded_counter_sample->seqnum), EXTRACT_32BITS(sflow_expanded_counter_sample->type), EXTRACT_32BITS(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 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((ndo, "\n\t protocol %s (%u), length %u, stripped bytes %u, header_size %u", tok2str(sflow_flow_raw_protocol_values,"Unknown",EXTRACT_32BITS(sflow_flow_raw->protocol)), EXTRACT_32BITS(sflow_flow_raw->protocol), EXTRACT_32BITS(sflow_flow_raw->length), EXTRACT_32BITS(sflow_flow_raw->stripped_bytes), EXTRACT_32BITS(sflow_flow_raw->header_size))); /* QUESTION - should we attempt to print the raw header itself? assuming of course there is wnough data present to do so... */ return 0; } static int print_sflow_ethernet_frame(netdissect_options *ndo, - const u_char *pointer, u_int len) { - + 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((ndo, "\n\t frame len %u, type %u", EXTRACT_32BITS(sflow_ethernet_frame->length), EXTRACT_32BITS(sflow_ethernet_frame->type))); return 0; } static int print_sflow_extended_switch_data(netdissect_options *ndo, - const u_char *pointer, u_int len) { - + 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((ndo, "\n\t src vlan %u, src pri %u, dst vlan %u, dst pri %u", EXTRACT_32BITS(sflow_extended_sw_data->src_vlan), EXTRACT_32BITS(sflow_extended_sw_data->src_pri), EXTRACT_32BITS(sflow_extended_sw_data->dst_vlan), EXTRACT_32BITS(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) { - + 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 bits, we must also check the enterprise. */ enterprise = EXTRACT_32BITS(sflow_flow_record->format); flow_type = enterprise & 0x0FFF; enterprise = enterprise >> 12; flow_len = EXTRACT_32BITS(sflow_flow_record->length); ND_PRINT((ndo, "\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 u_char *pointer, u_int len) +{ const struct sflow_flow_sample_t *sflow_flow_sample; u_int nrecords; u_int typesource; u_int type; u_int index; if (len < sizeof(struct sflow_flow_sample_t)) return 1; sflow_flow_sample = (struct sflow_flow_sample_t *)pointer; typesource = EXTRACT_32BITS(sflow_flow_sample->typesource); nrecords = EXTRACT_32BITS(sflow_flow_sample->records); type = typesource >> 24; index = typesource & 0x0FFF; ND_PRINT((ndo, " seqnum %u, type %u, idx %u, rate %u, pool %u, drops %u, input %u output %u records %u", EXTRACT_32BITS(sflow_flow_sample->seqnum), type, index, EXTRACT_32BITS(sflow_flow_sample->rate), EXTRACT_32BITS(sflow_flow_sample->pool), EXTRACT_32BITS(sflow_flow_sample->drops), EXTRACT_32BITS(sflow_flow_sample->in_interface), EXTRACT_32BITS(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 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 = EXTRACT_32BITS(sflow_expanded_flow_sample->records); ND_PRINT((ndo, " seqnum %u, type %u, idx %u, rate %u, pool %u, drops %u, records %u", EXTRACT_32BITS(sflow_expanded_flow_sample->seqnum), EXTRACT_32BITS(sflow_expanded_flow_sample->type), EXTRACT_32BITS(sflow_expanded_flow_sample->index), EXTRACT_32BITS(sflow_expanded_flow_sample->rate), EXTRACT_32BITS(sflow_expanded_flow_sample->pool), EXTRACT_32BITS(sflow_expanded_flow_sample->drops), EXTRACT_32BITS(sflow_expanded_flow_sample->records))); 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 u_char *pptr, u_int len) +{ const struct sflow_datagram_t *sflow_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; tptr = pptr; tlen = len; sflow_datagram = (const struct sflow_datagram_t *)pptr; ND_TCHECK(*sflow_datagram); /* * Sanity checking of the header. */ if (EXTRACT_32BITS(sflow_datagram->version) != 5) { ND_PRINT((ndo, "sFlow version %u packet not supported", EXTRACT_32BITS(sflow_datagram->version))); return; } if (ndo->ndo_vflag < 1) { ND_PRINT((ndo, "sFlowv%u, %s agent %s, agent-id %u, length %u", EXTRACT_32BITS(sflow_datagram->version), EXTRACT_32BITS(sflow_datagram->ip_version) == 1 ? "IPv4" : "IPv6", ipaddr_string(ndo, sflow_datagram->agent), EXTRACT_32BITS(sflow_datagram->agent_id), len)); return; } /* ok they seem to want to know everything - lets fully decode it */ nsamples=EXTRACT_32BITS(sflow_datagram->samples); ND_PRINT((ndo, "sFlowv%u, %s agent %s, agent-id %u, seqnum %u, uptime %u, samples %u, length %u", EXTRACT_32BITS(sflow_datagram->version), EXTRACT_32BITS(sflow_datagram->ip_version) == 1 ? "IPv4" : "IPv6", ipaddr_string(ndo, sflow_datagram->agent), EXTRACT_32BITS(sflow_datagram->agent_id), EXTRACT_32BITS(sflow_datagram->seqnum), EXTRACT_32BITS(sflow_datagram->uptime), nsamples, len)); /* skip Common header */ tptr += sizeof(const struct sflow_datagram_t); tlen -= sizeof(const struct sflow_datagram_t); while (nsamples > 0 && tlen > 0) { sflow_sample = (const struct sflow_sample_header *)tptr; ND_TCHECK(*sflow_sample); sflow_sample_type = (EXTRACT_32BITS(sflow_sample->format)&0x0FFF); sflow_sample_len = EXTRACT_32BITS(sflow_sample->len); if (tlen < sizeof(struct sflow_sample_header)) goto trunc; tptr += sizeof(struct sflow_sample_header); tlen -= sizeof(struct sflow_sample_header); ND_PRINT((ndo, "\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 trunc; /* did we capture enough for fully decoding the sample ? */ ND_TCHECK2(*tptr, sflow_sample_len); switch(sflow_sample_type) { case SFLOW_FLOW_SAMPLE: if (sflow_print_flow_sample(ndo, tptr, tlen)) goto trunc; break; case SFLOW_COUNTER_SAMPLE: if (sflow_print_counter_sample(ndo, tptr,tlen)) goto trunc; break; case SFLOW_EXPANDED_FLOW_SAMPLE: if (sflow_print_expanded_flow_sample(ndo, tptr, tlen)) goto trunc; break; case SFLOW_EXPANDED_COUNTER_SAMPLE: if (sflow_print_expanded_counter_sample(ndo, tptr,tlen)) goto trunc; 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; trunc: ND_PRINT((ndo, "[|SFLOW]")); } /* * Local Variables: * c-style: whitesmith * c-basic-offset: 4 * End: */ Index: head/contrib/tcpdump/print-sip.c =================================================================== --- head/contrib/tcpdump/print-sip.c (revision 285274) +++ head/contrib/tcpdump/print-sip.c (revision 285275) @@ -1,56 +1,53 @@ /* * 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@juniper.net) + * Turned into common "text protocol" code, which this uses, by + * Guy Harris. */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "interface.h" #include "extract.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, - register const u_char *pptr, register u_int len) +sip_print(netdissect_options *ndo, const u_char *pptr, u_int len) { - u_int idx; - - ND_PRINT((ndo, "SIP, length: %u%s", len, ndo->ndo_vflag ? "\n\t" : "")); - - /* in non-verbose mode just lets print the protocol and length */ - if (ndo->ndo_vflag < 1) - return; - - for (idx = 0; idx < len; idx++) { - ND_TCHECK2(*(pptr+idx), 2); - if (EXTRACT_16BITS(pptr+idx) != 0x0d0a) { /* linefeed ? */ - safeputchar(ndo, *(pptr + idx)); - } else { - ND_PRINT((ndo, "\n\t")); - idx+=1; - } - } - - /* do we want to see an additionally hexdump ? */ - if (ndo->ndo_vflag > 1) - print_unknown_data(ndo, pptr, "\n\t", len); - - return; - -trunc: - ND_PRINT((ndo, "[|sip]")); + txtproto_print(ndo, pptr, len, "sip", sipcmds, RESP_CODE_SECOND_TOKEN); } Index: head/contrib/tcpdump/print-sl.c =================================================================== --- head/contrib/tcpdump/print-sl.c (revision 285274) +++ head/contrib/tcpdump/print-sl.c (revision 285275) @@ -1,252 +1,250 @@ /* * 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. * * $FreeBSD$ */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "interface.h" #include "extract.h" /* must come after interface.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 CHDR_LEN 15 #define SLIPDIR_IN 0 #define SLIPDIR_OUT 1 static const char tstr[] = "[|slip]"; 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); u_int sl_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { register u_int caplen = h->caplen; register u_int length = h->len; register const struct ip *ip; if (caplen < SLIP_HDRLEN || length < SLIP_HDRLEN) { ND_PRINT((ndo, "%s", tstr)); return (caplen); } length -= SLIP_HDRLEN; ip = (struct ip *)(p + SLIP_HDRLEN); if (ndo->ndo_eflag) sliplink_print(ndo, p, ip, length); switch (IP_V(ip)) { case 4: ip_print(ndo, (u_char *)ip, length); break; -#ifdef INET6 case 6: ip6_print(ndo, (u_char *)ip, length); break; -#endif default: ND_PRINT((ndo, "ip v%d", IP_V(ip))); } return (SLIP_HDRLEN); } u_int sl_bsdos_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { register u_int caplen = h->caplen; register u_int length = h->len; register const struct ip *ip; if (caplen < SLIP_HDRLEN) { ND_PRINT((ndo, "%s", tstr)); return (caplen); } length -= SLIP_HDRLEN; ip = (struct ip *)(p + SLIP_HDRLEN); #ifdef notdef if (ndo->ndo_eflag) sliplink_print(ndo, p, ip, length); #endif ip_print(ndo, (u_char *)ip, length); return (SLIP_HDRLEN); } static void sliplink_print(netdissect_options *ndo, register const u_char *p, register const struct ip *ip, register u_int length) { int dir; u_int hlen; dir = p[SLX_DIR]; ND_PRINT((ndo, dir == SLIPDIR_IN ? "I " : "O ")); if (ndo->ndo_nflag) { /* XXX just dump the header */ register int i; for (i = SLX_CHDR; i < SLX_CHDR + CHDR_LEN - 1; ++i) ND_PRINT((ndo, "%02x.", p[i])); ND_PRINT((ndo, "%02x: ", p[SLX_CHDR + CHDR_LEN - 1])); return; } switch (p[SLX_CHDR] & 0xf0) { case TYPE_IP: ND_PRINT((ndo, "ip %d: ", 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 = ((struct ip *)&p[SLX_CHDR])->ip_p; hlen = IP_HL(ip); hlen += TH_OFF((struct tcphdr *)&((int *)ip)[hlen]); lastlen[dir][lastconn] = length - (hlen << 2); ND_PRINT((ndo, "utcp %d: ", lastconn)); break; default: if (p[SLX_CHDR] & TYPE_COMPRESSED_TCP) { compressed_sl_print(ndo, &p[SLX_CHDR], ip, length, dir); ND_PRINT((ndo, ": ")); } else ND_PRINT((ndo, "slip-%d!: ", p[SLX_CHDR])); } } static const u_char * print_sl_change(netdissect_options *ndo, const char *str, register const u_char *cp) { register u_int i; if ((i = *cp++) == 0) { i = EXTRACT_16BITS(cp); cp += 2; } ND_PRINT((ndo, " %s%d", str, i)); return (cp); } static const u_char * print_sl_winchange(netdissect_options *ndo, register const u_char *cp) { register short i; if ((i = *cp++) == 0) { i = EXTRACT_16BITS(cp); cp += 2; } if (i >= 0) ND_PRINT((ndo, " W+%d", i)); else ND_PRINT((ndo, " 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) { register const u_char *cp = chdr; register u_int flags, hlen; flags = *cp++; if (flags & NEW_C) { lastconn = *cp++; ND_PRINT((ndo, "ctcp %d", lastconn)); } else ND_PRINT((ndo, "ctcp *")); /* skip tcp checksum */ cp += 2; switch (flags & SPECIALS_MASK) { case SPECIAL_I: ND_PRINT((ndo, " *SA+%d", lastlen[dir][lastconn])); break; case SPECIAL_D: ND_PRINT((ndo, " *S+%d", 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. */ hlen = IP_HL(ip); hlen += TH_OFF((struct tcphdr *)&((int32_t *)ip)[hlen]); lastlen[dir][lastconn] = length - (hlen << 2); ND_PRINT((ndo, " %d (%ld)", lastlen[dir][lastconn], (long)(cp - chdr))); } Index: head/contrib/tcpdump/print-sll.c =================================================================== --- head/contrib/tcpdump/print-sll.c (revision 285274) +++ head/contrib/tcpdump/print-sll.c (revision 285275) @@ -1,311 +1,308 @@ /* * 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. */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "interface.h" #include "addrtoname.h" #include "ethertype.h" #include "extract.h" #include "ether.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 { uint16_t sll_pkttype; /* packet type */ uint16_t sll_hatype; /* link-layer address type */ uint16_t sll_halen; /* link-layer address length */ uint8_t sll_addr[SLL_ADDRLEN]; /* link-layer address */ uint16_t sll_protocol; /* protocol */ }; /* * 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 inline void sll_print(netdissect_options *ndo, register const struct sll_header *sllp, u_int length) { u_short ether_type; ND_PRINT((ndo, "%3s ",tok2str(sll_pkttype_values,"?",EXTRACT_16BITS(&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 (EXTRACT_16BITS(&sllp->sll_halen) == 6) ND_PRINT((ndo, "%s ", etheraddr_string(ndo, sllp->sll_addr))); if (!ndo->ndo_qflag) { ether_type = EXTRACT_16BITS(&sllp->sll_protocol); if (ether_type <= ETHERMTU) { /* * Not an Ethernet type; what type is it? */ switch (ether_type) { case LINUX_SLL_P_802_3: /* * Ethernet_802.3 IPX frame. */ ND_PRINT((ndo, "802.3")); break; case LINUX_SLL_P_802_2: /* * 802.2. */ ND_PRINT((ndo, "802.2")); break; default: /* * What is it? */ ND_PRINT((ndo, "ethertype Unknown (0x%04x)", ether_type)); break; } } else { ND_PRINT((ndo, "ethertype %s (0x%04x)", tok2str(ethertype_values, "Unknown", ether_type), ether_type)); } ND_PRINT((ndo, ", 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. */ u_int 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; register const struct sll_header *sllp; u_short ether_type; u_short extracted_ethertype; if (caplen < SLL_HDR_LEN) { /* * XXX - this "can't happen" because "pcap-linux.c" always * adds this many bytes of header to every packet in a * cooked socket capture. */ ND_PRINT((ndo, "[|sll]")); return (caplen); } 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; ether_type = EXTRACT_16BITS(&sllp->sll_protocol); recurse: /* * Is it (gag) an 802.3 encapsulation, or some non-Ethernet * packet type? */ if (ether_type <= ETHERMTU) { /* * 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. */ if (llc_print(ndo, p, length, caplen, NULL, NULL, &extracted_ethertype) == 0) goto unknown; /* unknown LLC type */ break; default: extracted_ethertype = 0; /*FALLTHROUGH*/ unknown: /* ether_type not known, print raw packet */ if (!ndo->ndo_eflag) sll_print(ndo, sllp, length + SLL_HDR_LEN); if (extracted_ethertype) { ND_PRINT((ndo, "(LLC %s) ", etherproto_string(htons(extracted_ethertype)))); } 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 || length < 4) { ND_PRINT((ndo, "[|vlan]")); return (SLL_HDR_LEN); } if (ndo->ndo_eflag) { uint16_t tag = EXTRACT_16BITS(p); - ND_PRINT((ndo, "vlan %u, p %u%s, ", - tag & 0xfff, - tag >> 13, - (tag & 0x1000) ? ", CFI" : "")); + ND_PRINT((ndo, "%s, ", ieee8021q_tci_string(tag))); } ether_type = EXTRACT_16BITS(p + 2); if (ether_type <= ETHERMTU) ether_type = LINUX_SLL_P_802_2; if (!ndo->ndo_qflag) { ND_PRINT((ndo, "ethertype %s, ", tok2str(ethertype_values, "Unknown", ether_type))); } p += 4; length -= 4; caplen -= 4; goto recurse; } else { if (ethertype_print(ndo, ether_type, p, length, caplen) == 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); } } return (SLL_HDR_LEN); } Index: head/contrib/tcpdump/print-slow.c =================================================================== --- head/contrib/tcpdump/print-slow.c (revision 285274) +++ head/contrib/tcpdump/print-slow.c (revision 285275) @@ -1,658 +1,658 @@ /* * 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@juniper.net) */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "interface.h" #include "extract.h" #include "addrtoname.h" #include "ether.h" #include "oui.h" struct slow_common_header_t { uint8_t proto_subtype; uint8_t version; }; #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 { uint8_t info_type; uint8_t info_length; uint8_t oam_version; uint8_t revision[2]; uint8_t state; uint8_t oam_config; uint8_t oam_pdu_config[2]; uint8_t oui[3]; uint8_t vendor_private[4]; }; #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 { uint8_t event_type; uint8_t event_length; uint8_t time_stamp[2]; uint8_t window[8]; uint8_t threshold[8]; uint8_t errors[8]; uint8_t errors_running_total[8]; uint8_t event_running_total[4]; }; struct slow_oam_variablerequest_t { uint8_t branch; uint8_t leaf[2]; }; struct slow_oam_variableresponse_t { uint8_t branch; uint8_t leaf[2]; uint8_t length; }; struct slow_oam_loopbackctrl_t { 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 { uint8_t type; uint8_t length; }; #define LACP_TLV_TERMINATOR 0x00 #define LACP_TLV_ACTOR_INFO 0x01 #define LACP_TLV_PARTNER_INFO 0x02 #define LACP_TLV_COLLECTOR_INFO 0x03 #define MARKER_TLV_TERMINATOR 0x00 #define MARKER_TLV_MARKER_INFO 0x01 static const struct tok slow_tlv_values[] = { { (SLOW_PROTO_LACP << 8) + LACP_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) + MARKER_TLV_TERMINATOR, "Terminator"}, { (SLOW_PROTO_MARKER << 8) + MARKER_TLV_MARKER_INFO, "Marker Information"}, { 0, NULL} }; struct lacp_tlv_actor_partner_info_t { uint8_t sys_pri[2]; uint8_t sys[ETHER_ADDR_LEN]; uint8_t key[2]; uint8_t port_pri[2]; uint8_t port[2]; uint8_t state; uint8_t 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 { uint8_t max_delay[2]; uint8_t pad[12]; }; struct marker_tlv_marker_info_t { uint8_t req_port[2]; uint8_t req_sys[ETHER_ADDR_LEN]; uint8_t req_trans_id[4]; uint8_t pad[2]; }; struct lacp_marker_tlv_terminator_t { uint8_t pad[50]; }; static void slow_marker_lacp_print(netdissect_options *, register const u_char *, register u_int); static void slow_oam_print(netdissect_options *, register const u_char *, register u_int); const struct slow_common_header_t *slow_com_header; void slow_print(netdissect_options *ndo, - register const u_char *pptr, register u_int len) { - + register const u_char *pptr, register u_int len) +{ int print_version; slow_com_header = (const struct slow_common_header_t *)pptr; ND_TCHECK(*slow_com_header); /* * Sanity checking of the header. */ switch (slow_com_header->proto_subtype) { case SLOW_PROTO_LACP: if (slow_com_header->version != LACP_VERSION) { ND_PRINT((ndo, "LACP version %u packet not supported",slow_com_header->version)); return; } print_version = 1; break; case SLOW_PROTO_MARKER: if (slow_com_header->version != MARKER_VERSION) { ND_PRINT((ndo, "MARKER version %u packet not supported",slow_com_header->version)); 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) { ND_PRINT((ndo, "%sv%u, length %u", tok2str(slow_proto_values, "unknown (%u)",slow_com_header->proto_subtype), slow_com_header->version, len)); } else { /* some slow protos don't have a version number in the header */ ND_PRINT((ndo, "%s, length %u", tok2str(slow_proto_values, "unknown (%u)",slow_com_header->proto_subtype), len)); } /* unrecognized subtype */ if (print_version == -1) { print_unknown_data(ndo, pptr, "\n\t", len); return; } if (!ndo->ndo_vflag) return; switch (slow_com_header->proto_subtype) { default: /* should not happen */ break; case SLOW_PROTO_OAM: /* skip proto_subtype */ slow_oam_print(ndo, pptr+1, len-1); break; case SLOW_PROTO_LACP: /* LACP and MARKER share the same semantics */ case SLOW_PROTO_MARKER: /* skip slow_common_header */ len -= sizeof(const struct slow_common_header_t); pptr += sizeof(const struct slow_common_header_t); slow_marker_lacp_print(ndo, pptr, len); break; } return; trunc: ND_PRINT((ndo, "\n\t\t packet exceeded snapshot")); } static void slow_marker_lacp_print(netdissect_options *ndo, - register const u_char *tptr, register u_int tlen) { - + register const u_char *tptr, register u_int tlen) +{ const struct tlv_header_t *tlv_header; const u_char *tlv_tptr; u_int 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) { /* did we capture enough for fully decoding the tlv header ? */ ND_TCHECK2(*tptr, sizeof(struct tlv_header_t)); tlv_header = (const struct tlv_header_t *)tptr; tlv_len = tlv_header->length; ND_PRINT((ndo, "\n\t%s TLV (0x%02x), length %u", tok2str(slow_tlv_values, "Unknown", (slow_com_header->proto_subtype << 8) + tlv_header->type), tlv_header->type, tlv_len)); if ((tlv_len < sizeof(struct tlv_header_t) || tlv_len > tlen) && tlv_header->type != LACP_TLV_TERMINATOR && tlv_header->type != MARKER_TLV_TERMINATOR) { ND_PRINT((ndo, "\n\t-----trailing data-----")); print_unknown_data(ndo, tptr+sizeof(struct tlv_header_t), "\n\t ", tlen); return; } tlv_tptr=tptr+sizeof(struct tlv_header_t); tlv_tlen=tlv_len-sizeof(struct tlv_header_t); /* did we capture enough for fully decoding the tlv ? */ ND_TCHECK2(*tptr, tlv_len); switch((slow_com_header->proto_subtype << 8) + tlv_header->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): tlv_ptr.lacp_tlv_actor_partner_info = (const struct lacp_tlv_actor_partner_info_t *)tlv_tptr; ND_PRINT((ndo, "\n\t System %s, System Priority %u, Key %u" \ ", Port %u, Port Priority %u\n\t State Flags [%s]", etheraddr_string(ndo, tlv_ptr.lacp_tlv_actor_partner_info->sys), EXTRACT_16BITS(tlv_ptr.lacp_tlv_actor_partner_info->sys_pri), EXTRACT_16BITS(tlv_ptr.lacp_tlv_actor_partner_info->key), EXTRACT_16BITS(tlv_ptr.lacp_tlv_actor_partner_info->port), EXTRACT_16BITS(tlv_ptr.lacp_tlv_actor_partner_info->port_pri), bittok2str(lacp_tlv_actor_partner_info_state_values, "none", tlv_ptr.lacp_tlv_actor_partner_info->state))); break; case ((SLOW_PROTO_LACP << 8) + LACP_TLV_COLLECTOR_INFO): tlv_ptr.lacp_tlv_collector_info = (const struct lacp_tlv_collector_info_t *)tlv_tptr; ND_PRINT((ndo, "\n\t Max Delay %u", EXTRACT_16BITS(tlv_ptr.lacp_tlv_collector_info->max_delay))); break; case ((SLOW_PROTO_MARKER << 8) + MARKER_TLV_MARKER_INFO): tlv_ptr.marker_tlv_marker_info = (const struct marker_tlv_marker_info_t *)tlv_tptr; ND_PRINT((ndo, "\n\t Request System %s, Request Port %u, Request Transaction ID 0x%08x", etheraddr_string(ndo, tlv_ptr.marker_tlv_marker_info->req_sys), EXTRACT_16BITS(tlv_ptr.marker_tlv_marker_info->req_port), EXTRACT_32BITS(tlv_ptr.marker_tlv_marker_info->req_trans_id))); break; /* those two TLVs have the same structure -> fall through */ case ((SLOW_PROTO_LACP << 8) + LACP_TLV_TERMINATOR): case ((SLOW_PROTO_MARKER << 8) + LACP_TLV_TERMINATOR): tlv_ptr.lacp_marker_tlv_terminator = (const struct lacp_marker_tlv_terminator_t *)tlv_tptr; if (tlv_len == 0) { tlv_len = sizeof(tlv_ptr.lacp_marker_tlv_terminator->pad) + sizeof(struct tlv_header_t); /* tell the user that we modified the length field */ if (ndo->ndo_vflag>1) ND_PRINT((ndo, " (=%u)", tlv_len)); /* we have messed around with the length field - now we need to check * again if there are enough bytes on the wire for the hexdump */ ND_TCHECK2(tlv_ptr.lacp_marker_tlv_terminator->pad[0], sizeof(tlv_ptr.lacp_marker_tlv_terminator->pad)); } break; default: if (ndo->ndo_vflag <= 1) print_unknown_data(ndo, tlv_tptr, "\n\t ", tlv_tlen); break; } /* 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; trunc: ND_PRINT((ndo, "\n\t\t packet exceeded snapshot")); } static void slow_oam_print(netdissect_options *ndo, - register const u_char *tptr, register u_int tlen) { - + register const u_char *tptr, register u_int tlen) +{ u_int hexdump; struct slow_oam_common_header_t { uint8_t flags[2]; uint8_t code; }; struct slow_oam_tlv_header_t { uint8_t type; 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 = (struct slow_oam_common_header_t *)tptr; tptr += sizeof(struct slow_oam_common_header_t); tlen -= sizeof(struct slow_oam_common_header_t); ND_PRINT((ndo, "\n\tCode %s OAM PDU, Flags [%s]", tok2str(slow_oam_code_values, "Unknown (%u)", ptr.slow_oam_common_header->code), bittok2str(slow_oam_flag_values, "none", EXTRACT_16BITS(&ptr.slow_oam_common_header->flags)))); switch (ptr.slow_oam_common_header->code) { case SLOW_OAM_CODE_INFO: while (tlen > 0) { ptr.slow_oam_tlv_header = (const struct slow_oam_tlv_header_t *)tptr; ND_PRINT((ndo, "\n\t %s Information Type (%u), length %u", tok2str(slow_oam_info_type_values, "Reserved", ptr.slow_oam_tlv_header->type), ptr.slow_oam_tlv_header->type, ptr.slow_oam_tlv_header->length)); hexdump = FALSE; switch (ptr.slow_oam_tlv_header->type) { case SLOW_OAM_INFO_TYPE_END_OF_TLV: if (ptr.slow_oam_tlv_header->length != 0) { ND_PRINT((ndo, "\n\t ERROR: illegal length - should be 0")); } return; 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 (tlv.slow_oam_info->info_length != sizeof(struct slow_oam_info_t)) { ND_PRINT((ndo, "\n\t ERROR: illegal length - should be %lu", (unsigned long) sizeof(struct slow_oam_info_t))); return; } ND_PRINT((ndo, "\n\t OAM-Version %u, Revision %u", tlv.slow_oam_info->oam_version, EXTRACT_16BITS(&tlv.slow_oam_info->revision))); ND_PRINT((ndo, "\n\t State-Parser-Action %s, State-MUX-Action %s", tok2str(slow_oam_info_type_state_parser_values, "Reserved", tlv.slow_oam_info->state & OAM_INFO_TYPE_PARSER_MASK), tok2str(slow_oam_info_type_state_mux_values, "Reserved", tlv.slow_oam_info->state & OAM_INFO_TYPE_MUX_MASK))); ND_PRINT((ndo, "\n\t OAM-Config Flags [%s], OAM-PDU-Config max-PDU size %u", bittok2str(slow_oam_info_type_oam_config_values, "none", tlv.slow_oam_info->oam_config), EXTRACT_16BITS(&tlv.slow_oam_info->oam_pdu_config) & OAM_INFO_TYPE_PDU_SIZE_MASK)); ND_PRINT((ndo, "\n\t OUI %s (0x%06x), Vendor-Private 0x%08x", tok2str(oui_values, "Unknown", EXTRACT_24BITS(&tlv.slow_oam_info->oui)), EXTRACT_24BITS(&tlv.slow_oam_info->oui), EXTRACT_32BITS(&tlv.slow_oam_info->vendor_private))); break; case SLOW_OAM_INFO_TYPE_ORG_SPECIFIC: hexdump = TRUE; break; default: hexdump = TRUE; break; } /* infinite loop check */ if (!ptr.slow_oam_tlv_header->length) { return; } /* do we also want to see a hex dump ? */ if (ndo->ndo_vflag > 1 || hexdump==TRUE) { print_unknown_data(ndo, tptr, "\n\t ", ptr.slow_oam_tlv_header->length); } tlen -= ptr.slow_oam_tlv_header->length; tptr += ptr.slow_oam_tlv_header->length; } break; case SLOW_OAM_CODE_EVENT_NOTIF: while (tlen > 0) { ptr.slow_oam_tlv_header = (const struct slow_oam_tlv_header_t *)tptr; ND_PRINT((ndo, "\n\t %s Link Event Type (%u), length %u", tok2str(slow_oam_link_event_values, "Reserved", ptr.slow_oam_tlv_header->type), ptr.slow_oam_tlv_header->type, ptr.slow_oam_tlv_header->length)); hexdump = FALSE; switch (ptr.slow_oam_tlv_header->type) { case SLOW_OAM_LINK_EVENT_END_OF_TLV: if (ptr.slow_oam_tlv_header->length != 0) { ND_PRINT((ndo, "\n\t ERROR: illegal length - should be 0")); } return; 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 (tlv.slow_oam_link_event->event_length != sizeof(struct slow_oam_link_event_t)) { ND_PRINT((ndo, "\n\t ERROR: illegal length - should be %lu", (unsigned long) sizeof(struct slow_oam_link_event_t))); return; } ND_PRINT((ndo, "\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", EXTRACT_16BITS(&tlv.slow_oam_link_event->time_stamp)*100, EXTRACT_64BITS(&tlv.slow_oam_link_event->window), EXTRACT_64BITS(&tlv.slow_oam_link_event->threshold), EXTRACT_64BITS(&tlv.slow_oam_link_event->errors), EXTRACT_64BITS(&tlv.slow_oam_link_event->errors_running_total), EXTRACT_32BITS(&tlv.slow_oam_link_event->event_running_total))); break; case SLOW_OAM_LINK_EVENT_ORG_SPECIFIC: hexdump = TRUE; break; default: hexdump = TRUE; break; } /* infinite loop check */ if (!ptr.slow_oam_tlv_header->length) { return; } /* do we also want to see a hex dump ? */ if (ndo->ndo_vflag > 1 || hexdump==TRUE) { print_unknown_data(ndo, tptr, "\n\t ", ptr.slow_oam_tlv_header->length); } tlen -= ptr.slow_oam_tlv_header->length; tptr += ptr.slow_oam_tlv_header->length; } break; case SLOW_OAM_CODE_LOOPBACK_CTRL: tlv.slow_oam_loopbackctrl = (const struct slow_oam_loopbackctrl_t *)tptr; ND_PRINT((ndo, "\n\t Command %s (%u)", tok2str(slow_oam_loopbackctrl_cmd_values, "Unknown", tlv.slow_oam_loopbackctrl->command), tlv.slow_oam_loopbackctrl->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; } Index: head/contrib/tcpdump/print-smb.c =================================================================== --- head/contrib/tcpdump/print-smb.c (revision 285274) +++ head/contrib/tcpdump/print-smb.c (revision 285275) @@ -1,1492 +1,1493 @@ /* * 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 */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "interface.h" #include "extract.h" #include "smb.h" static const char tstr[] = "[|SMB]"; static int request = 0; static int unicodestr = 0; 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 *, int, 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, int pcnt, int dcnt) { const char *fmt; if (request) fmt = "Attribute=[A]\nSearchCount=[d]\nFlags=[w]\nLevel=[dP4]\nFile=[S]\n"; else fmt = "Handle=[w]\nCount=[d]\nEOS=[w]\nEoffset=[d]\nLastNameOfs=[w]\n"; smb_fdata(ndo, param, fmt, param + pcnt, unicodestr); if (dcnt) { ND_PRINT((ndo, "data:\n")); print_data(ndo, data, dcnt); } } static void trans2_qfsinfo(netdissect_options *ndo, const u_char *param, const u_char *data, int pcnt, int dcnt) { static int level = 0; const char *fmt=""; if (request) { ND_TCHECK2(*param, 2); level = EXTRACT_LE_16BITS(param); fmt = "InfoLevel=[d]\n"; smb_fdata(ndo, param, fmt, param + pcnt, unicodestr); } else { switch (level) { case 1: fmt = "idFileSystem=[W]\nSectorUnit=[D]\nUnit=[D]\nAvail=[D]\nSectorSize=[d]\n"; break; case 2: fmt = "CreationTime=[T2]VolNameLength=[lb]\nVolumeLabel=[c]\n"; break; case 0x105: fmt = "Capabilities=[W]\nMaxFileLen=[D]\nVolNameLen=[lD]\nVolume=[C]\n"; break; default: fmt = "UnknownLevel\n"; break; } smb_fdata(ndo, data, fmt, data + dcnt, unicodestr); } if (dcnt) { ND_PRINT((ndo, "data:\n")); print_data(ndo, data, dcnt); } return; trunc: ND_PRINT((ndo, "%s", tstr)); } static const struct smbfnsint trans2_fns[] = { { 0, "TRANSACT2_OPEN", 0, { "Flags2=[w]\nMode=[w]\nSearchAttrib=[A]\nAttrib=[A]\nTime=[T2]\nOFun=[w]\nSize=[D]\nRes=([w, w, w, w, w])\nPath=[S]", NULL, "Handle=[d]\nAttrib=[A]\nTime=[T2]\nSize=[D]\nAccess=[w]\nType=[w]\nState=[w]\nAction=[w]\nInode=[W]\nOffErr=[d]\n|EALength=[d]\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; int pcnt, dcnt; ND_TCHECK(words[0]); if (request) { ND_TCHECK2(w[14 * 2], 2); pcnt = EXTRACT_LE_16BITS(w + 9 * 2); param = buf + EXTRACT_LE_16BITS(w + 10 * 2); dcnt = EXTRACT_LE_16BITS(w + 11 * 2); data = buf + EXTRACT_LE_16BITS(w + 12 * 2); fn = smbfindint(EXTRACT_LE_16BITS(w + 14 * 2), trans2_fns); } else { if (words[0] == 0) { ND_PRINT((ndo, "%s\n", fn->name)); ND_PRINT((ndo, "Trans2Interim\n")); return; } ND_TCHECK2(w[7 * 2], 2); pcnt = EXTRACT_LE_16BITS(w + 3 * 2); param = buf + EXTRACT_LE_16BITS(w + 4 * 2); dcnt = EXTRACT_LE_16BITS(w + 6 * 2); data = buf + EXTRACT_LE_16BITS(w + 7 * 2); } ND_PRINT((ndo, "%s param_length=%d data_length=%d\n", fn->name, pcnt, dcnt)); if (request) { if (words[0] == 8) { smb_fdata(ndo, words + 1, "Trans2Secondary\nTotParam=[d]\nTotData=[d]\nParamCnt=[d]\nParamOff=[d]\nParamDisp=[d]\nDataCnt=[d]\nDataOff=[d]\nDataDisp=[d]\nHandle=[d]\n", maxbuf, unicodestr); return; } else { smb_fdata(ndo, words + 1, "TotParam=[d]\nTotData=[d]\nMaxParam=[d]\nMaxData=[d]\nMaxSetup=[b][P1]\nFlags=[w]\nTimeOut=[D]\nRes1=[w]\nParamCnt=[d]\nParamOff=[d]\nDataCnt=[d]\nDataOff=[d]\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=[d]\nTotData=[d]\nRes1=[w]\nParamCnt=[d]\nParamOff=[d]\nParamDisp[d]\nDataCnt=[d]\nDataOff=[d]\nDataDisp=[d]\nSetupCnt=[b][P1]\n", words + 1 + 10 * 2, unicodestr); f1 = fn->descript.rep_f1; f2 = fn->descript.rep_f2; } ND_TCHECK2(*dat, 2); bcc = EXTRACT_LE_16BITS(dat); ND_PRINT((ndo, "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((ndo, "%s", tstr)); } static void print_browse(netdissect_options *ndo, const u_char *param, int paramlen, const u_char *data, int datalen) { const u_char *maxbuf = data + datalen; int command; ND_TCHECK(data[0]); command = data[0]; 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=[d]\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=[d]\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=[d]\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; } return; trunc: ND_PRINT((ndo, "%s", tstr)); } static void print_ipc(netdissect_options *ndo, const u_char *param, int paramlen, const u_char *data, 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; int datalen, paramlen; if (request) { ND_TCHECK2(w[12 * 2], 2); paramlen = EXTRACT_LE_16BITS(w + 9 * 2); param = buf + EXTRACT_LE_16BITS(w + 10 * 2); datalen = EXTRACT_LE_16BITS(w + 11 * 2); data = buf + EXTRACT_LE_16BITS(w + 12 * 2); f1 = "TotParamCnt=[d] \nTotDataCnt=[d] \nMaxParmCnt=[d] \nMaxDataCnt=[d]\nMaxSCnt=[d] \nTransFlags=[w] \nRes1=[w] \nRes2=[w] \nRes3=[w]\nParamCnt=[d] \nParamOff=[d] \nDataCnt=[d] \nDataOff=[d] \nSUCnt=[d]\n"; f2 = "|Name=[S]\n"; f3 = "|Param "; f4 = "|Data "; } else { ND_TCHECK2(w[7 * 2], 2); paramlen = EXTRACT_LE_16BITS(w + 3 * 2); param = buf + EXTRACT_LE_16BITS(w + 4 * 2); datalen = EXTRACT_LE_16BITS(w + 6 * 2); data = buf + EXTRACT_LE_16BITS(w + 7 * 2); f1 = "TotParamCnt=[d] \nTotDataCnt=[d] \nRes1=[d]\nParamCnt=[d] \nParamOff=[d] \nRes2=[d] \nDataCnt=[d] \nDataOff=[d] \nRes3=[d]\nLsetup=[d]\n"; f2 = "|Unknown "; f3 = "|Param "; f4 = "|Data "; } smb_fdata(ndo, words + 1, f1, min(words + 1 + 2 * words[0], maxbuf), unicodestr); ND_TCHECK2(*data1, 2); bcc = EXTRACT_LE_16BITS(data1); ND_PRINT((ndo, "smb_bcc=%u\n", bcc)); if (bcc > 0) { smb_fdata(ndo, data1 + 2, f2, maxbuf - (paramlen + datalen), unicodestr); if (strcmp((const char *)(data1 + 2), "\\MAILSLOT\\BROWSE") == 0) { print_browse(ndo, param, paramlen, data, datalen); return; } if (strcmp((const char *)(data1 + 2), "\\PIPE\\LANMAN") == 0) { print_ipc(ndo, param, paramlen, data, datalen); return; } if (paramlen) smb_fdata(ndo, param, f3, min(param + paramlen, maxbuf), unicodestr); if (datalen) smb_fdata(ndo, data, f4, min(data + datalen, maxbuf), unicodestr); } return; trunc: ND_PRINT((ndo, "%s", tstr)); } 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; ND_TCHECK(words[0]); wct = words[0]; if (request) f2 = "*|Dialect=[Y]\n"; else { if (wct == 1) f1 = "Core Protocol\nDialectIndex=[d]"; else if (wct == 17) f1 = "NT1 Protocol\nDialectIndex=[d]\nSecMode=[B]\nMaxMux=[d]\nNumVcs=[d]\nMaxBuffer=[D]\nRawSize=[D]\nSessionKey=[W]\nCapabilities=[W]\nServerTime=[T3]TimeZone=[d]\nCryptKey="; else if (wct == 13) f1 = "Coreplus/Lanman1/Lanman2 Protocol\nDialectIndex=[d]\nSecMode=[w]\nMaxXMit=[d]\nMaxMux=[d]\nMaxVcs=[d]\nBlkMode=[w]\nSessionKey=[W]\nServerTime=[T1]TimeZone=[d]\nRes=[W]\nCryptKey="; } if (f1) smb_fdata(ndo, words + 1, f1, min(words + 1 + wct * 2, maxbuf), unicodestr); else print_data(ndo, words + 1, min(wct * 2, PTR_DIFF(maxbuf, words + 1))); ND_TCHECK2(*data, 2); bcc = EXTRACT_LE_16BITS(data); ND_PRINT((ndo, "smb_bcc=%u\n", bcc)); if (bcc > 0) { if (f2) smb_fdata(ndo, data + 2, f2, min(data + 2 + EXTRACT_LE_16BITS(data), maxbuf), unicodestr); else print_data(ndo, data + 2, min(EXTRACT_LE_16BITS(data), PTR_DIFF(maxbuf, data + 2))); } return; trunc: ND_PRINT((ndo, "%s", tstr)); } 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; ND_TCHECK(words[0]); wct = words[0]; if (request) { if (wct == 10) f1 = "Com2=[w]\nOff2=[d]\nBufSize=[d]\nMpxMax=[d]\nVcNum=[d]\nSessionKey=[W]\nPassLen=[d]\nCryptLen=[d]\nCryptOff=[d]\nPass&Name=\n"; else f1 = "Com2=[B]\nRes1=[B]\nOff2=[d]\nMaxBuffer=[d]\nMaxMpx=[d]\nVcNumber=[d]\nSessionKey=[W]\nCaseInsensitivePasswordLength=[d]\nCaseSensitivePasswordLength=[d]\nRes=[W]\nCapabilities=[W]\nPass1&Pass2&Account&Domain&OS&LanMan=\n"; } else { if (wct == 3) { f1 = "Com2=[w]\nOff2=[d]\nAction=[w]\n"; } else if (wct == 13) { f1 = "Com2=[B]\nRes=[B]\nOff2=[d]\nAction=[w]\n"; f2 = "NativeOS=[S]\nNativeLanMan=[S]\nPrimaryDomain=[S]\n"; } } if (f1) smb_fdata(ndo, words + 1, f1, min(words + 1 + wct * 2, maxbuf), unicodestr); else print_data(ndo, words + 1, min(wct * 2, PTR_DIFF(maxbuf, words + 1))); ND_TCHECK2(*data, 2); bcc = EXTRACT_LE_16BITS(data); ND_PRINT((ndo, "smb_bcc=%u\n", bcc)); if (bcc > 0) { if (f2) smb_fdata(ndo, data + 2, f2, min(data + 2 + EXTRACT_LE_16BITS(data), maxbuf), unicodestr); else print_data(ndo, data + 2, min(EXTRACT_LE_16BITS(data), PTR_DIFF(maxbuf, data + 2))); } return; trunc: ND_PRINT((ndo, "%s", tstr)); } 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; ND_TCHECK(words[0]); wct = words[0]; if (request) { f1 = "Com2=[w]\nOff2=[d]\nHandle=[d]\nLockType=[w]\nTimeOut=[D]\nUnlockCount=[d]\nLockCount=[d]\n"; ND_TCHECK(words[7]); if (words[7] & 0x10) f2 = "*Process=[d]\n[P2]Offset=[M]\nLength=[M]\n"; else f2 = "*Process=[d]\nOffset=[D]\nLength=[D]\n"; } else { f1 = "Com2=[w]\nOff2=[d]\n"; } maxwords = min(words + 1 + wct * 2, maxbuf); if (wct) smb_fdata(ndo, words + 1, f1, maxwords, unicodestr); ND_TCHECK2(*data, 2); bcc = EXTRACT_LE_16BITS(data); ND_PRINT((ndo, "smb_bcc=%u\n", bcc)); if (bcc > 0) { if (f2) smb_fdata(ndo, data + 2, f2, min(data + 2 + EXTRACT_LE_16BITS(data), maxbuf), unicodestr); else print_data(ndo, data + 2, min(EXTRACT_LE_16BITS(data), PTR_DIFF(maxbuf, data + 2))); } return; trunc: ND_PRINT((ndo, "%s", tstr)); } static const struct smbfns smb_fns[] = { { -1, "SMBunknown", 0, DEFDESCRIPT }, { SMBtcon, "SMBtcon", 0, { NULL, "Path=[Z]\nPassword=[Z]\nDevice=[Z]\n", "MaxXmit=[d]\nTreeId=[d]\n", NULL, NULL } }, { SMBtdis, "SMBtdis", 0, DEFDESCRIPT }, { SMBexit, "SMBexit", 0, DEFDESCRIPT }, { SMBioctl, "SMBioctl", 0, DEFDESCRIPT }, { SMBecho, "SMBecho", 0, { "ReverbCount=[d]\n", NULL, "SequenceNum=[d]\n", NULL, NULL } }, { SMBulogoffX, "SMBulogoffX", FLG_CHAIN, DEFDESCRIPT }, { SMBgetatr, "SMBgetatr", 0, { NULL, "Path=[Z]\n", "Attribute=[A]\nTime=[T2]Size=[D]\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=[d]\nAttrib=[A]\n", "Path=[Z]\nBlkType=[B]\nBlkLen=[d]\n|Res1=[B]\nMask=[s11]\nSrv1=[B]\nDirIndex=[d]\nSrv2=[w]\nRes2=[W]\n", "Count=[d]\n", "BlkType=[B]\nBlkLen=[d]\n*\nRes1=[B]\nMask=[s11]\nSrv1=[B]\nDirIndex=[d]\nSrv2=[w]\nRes2=[W]\nAttrib=[a]\nTime=[T1]Size=[D]\nName=[s13]\n", NULL } }, { SMBopen, "SMBopen", 0, { "Mode=[w]\nAttribute=[A]\n", "Path=[Z]\n", "Handle=[d]\nOAttrib=[A]\nTime=[T2]Size=[D]\nAccess=[w]\n", NULL, NULL } }, { SMBcreate, "SMBcreate", 0, { "Attrib=[A]\nTime=[T2]", "Path=[Z]\n", "Handle=[d]\n", NULL, NULL } }, { SMBmknew, "SMBmknew", 0, { "Attrib=[A]\nTime=[T2]", "Path=[Z]\n", "Handle=[d]\n", NULL, NULL } }, { SMBunlink, "SMBunlink", 0, { "Attrib=[A]\n", "Path=[Z]\n", NULL, NULL, NULL } }, { SMBread, "SMBread", 0, { "Handle=[d]\nByteCount=[d]\nOffset=[D]\nCountLeft=[d]\n", NULL, "Count=[d]\nRes=([w,w,w,w])\n", NULL, NULL } }, { SMBwrite, "SMBwrite", 0, { "Handle=[d]\nByteCount=[d]\nOffset=[D]\nCountLeft=[d]\n", NULL, "Count=[d]\n", NULL, NULL } }, { SMBclose, "SMBclose", 0, { "Handle=[d]\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=[d]\nBlocksPerUnit=[d]\nBlockSize=[d]\nFreeUnits=[d]\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=[d]\nMode=[w]\nOffset=[D]\n", "Offset=[D]\n", NULL, NULL, NULL } }, { SMBflush, "SMBflush", 0, { "Handle=[d]\n", NULL, NULL, NULL, NULL } }, { SMBsplopen, "SMBsplopen", 0, { "SetupLen=[d]\nMode=[w]\n", "Ident=[Z]\n", "Handle=[d]\n", NULL, NULL } }, { SMBsplclose, "SMBsplclose", 0, { "Handle=[d]\n", NULL, NULL, NULL, NULL } }, { SMBsplretq, "SMBsplretq", 0, { "MaxCount=[d]\nStartIndex=[d]\n", NULL, "Count=[d]\nIndex=[d]\n", "*Time=[T2]Status=[B]\nJobID=[d]\nSize=[D]\nRes=[B]Name=[s16]\n", NULL } }, { SMBsplwr, "SMBsplwr", 0, { "Handle=[d]\n", NULL, NULL, NULL, NULL } }, { SMBlock, "SMBlock", 0, { "Handle=[d]\nCount=[D]\nOffset=[D]\n", NULL, NULL, NULL, NULL } }, { SMBunlock, "SMBunlock", 0, { "Handle=[d]\nCount=[D]\nOffset=[D]\n", NULL, NULL, NULL, NULL } }, /* CORE+ PROTOCOL FOLLOWS */ { SMBreadbraw, "SMBreadbraw", 0, { "Handle=[d]\nOffset=[D]\nMaxCount=[d]\nMinCount=[d]\nTimeOut=[D]\nRes=[d]\n", NULL, NULL, NULL, NULL } }, { SMBwritebraw, "SMBwritebraw", 0, { "Handle=[d]\nTotalCount=[d]\nRes=[w]\nOffset=[D]\nTimeOut=[D]\nWMode=[w]\nRes2=[W]\n|DataSize=[d]\nDataOff=[d]\n", NULL, "WriteRawAck", NULL, NULL } }, { SMBwritec, "SMBwritec", 0, { NULL, NULL, "Count=[d]\n", NULL, NULL } }, { SMBwriteclose, "SMBwriteclose", 0, { "Handle=[d]\nCount=[d]\nOffset=[D]\nTime=[T2]Res=([w,w,w,w,w,w])", NULL, "Count=[d]\n", NULL, NULL } }, { SMBlockread, "SMBlockread", 0, { "Handle=[d]\nByteCount=[d]\nOffset=[D]\nCountLeft=[d]\n", NULL, "Count=[d]\nRes=([w,w,w,w])\n", NULL, NULL } }, { SMBwriteunlock, "SMBwriteunlock", 0, { "Handle=[d]\nByteCount=[d]\nOffset=[D]\nCountLeft=[d]\n", NULL, "Count=[d]\n", NULL, NULL } }, { SMBreadBmpx, "SMBreadBmpx", 0, { "Handle=[d]\nOffset=[D]\nMaxCount=[d]\nMinCount=[d]\nTimeOut=[D]\nRes=[w]\n", NULL, "Offset=[D]\nTotCount=[d]\nRemaining=[d]\nRes=([w,w])\nDataSize=[d]\nDataOff=[d]\n", NULL, NULL } }, { SMBwriteBmpx, "SMBwriteBmpx", 0, { "Handle=[d]\nTotCount=[d]\nRes=[w]\nOffset=[D]\nTimeOut=[D]\nWMode=[w]\nRes2=[W]\nDataSize=[d]\nDataOff=[d]\n", NULL, "Remaining=[d]\n", NULL, NULL } }, { SMBwriteBs, "SMBwriteBs", 0, { "Handle=[d]\nTotCount=[d]\nOffset=[D]\nRes=[W]\nDataSize=[d]\nDataOff=[d]\n", NULL, "Count=[d]\n", NULL, NULL } }, { SMBsetattrE, "SMBsetattrE", 0, { "Handle=[d]\nCreationTime=[T2]AccessTime=[T2]ModifyTime=[T2]", NULL, NULL, NULL, NULL } }, { SMBgetattrE, "SMBgetattrE", 0, { "Handle=[d]\n", NULL, "CreationTime=[T2]AccessTime=[T2]ModifyTime=[T2]Size=[D]\nAllocSize=[D]\nAttribute=[A]\n", NULL, NULL } }, { SMBtranss, "SMBtranss", 0, DEFDESCRIPT }, { SMBioctls, "SMBioctls", 0, DEFDESCRIPT }, { SMBcopy, "SMBcopy", 0, { "TreeID2=[d]\nOFun=[w]\nFlags=[w]\n", "Path=[S]\nNewPath=[S]\n", "CopyCount=[d]\n", "|ErrStr=[S]\n", NULL } }, { SMBmove, "SMBmove", 0, { "TreeID2=[d]\nOFun=[w]\nFlags=[w]\n", "Path=[S]\nNewPath=[S]\n", "MoveCount=[d]\n", "|ErrStr=[S]\n", NULL } }, { SMBopenX, "SMBopenX", FLG_CHAIN, { "Com2=[w]\nOff2=[d]\nFlags=[w]\nMode=[w]\nSearchAttrib=[A]\nAttrib=[A]\nTime=[T2]OFun=[w]\nSize=[D]\nTimeOut=[D]\nRes=[W]\n", "Path=[S]\n", "Com2=[w]\nOff2=[d]\nHandle=[d]\nAttrib=[A]\nTime=[T2]Size=[D]\nAccess=[w]\nType=[w]\nState=[w]\nAction=[w]\nFileID=[W]\nRes=[w]\n", NULL, NULL } }, { SMBreadX, "SMBreadX", FLG_CHAIN, { "Com2=[w]\nOff2=[d]\nHandle=[d]\nOffset=[D]\nMaxCount=[d]\nMinCount=[d]\nTimeOut=[D]\nCountLeft=[d]\n", NULL, "Com2=[w]\nOff2=[d]\nRemaining=[d]\nRes=[W]\nDataSize=[d]\nDataOff=[d]\nRes=([w,w,w,w])\n", NULL, NULL } }, { SMBwriteX, "SMBwriteX", FLG_CHAIN, { "Com2=[w]\nOff2=[d]\nHandle=[d]\nOffset=[D]\nTimeOut=[D]\nWMode=[w]\nCountLeft=[d]\nRes=[w]\nDataSize=[d]\nDataOff=[d]\n", NULL, "Com2=[w]\nOff2=[d]\nCount=[d]\nRemaining=[d]\nRes=[W]\n", NULL, NULL } }, { SMBffirst, "SMBffirst", 0, { "Count=[d]\nAttrib=[A]\n", "Path=[Z]\nBlkType=[B]\nBlkLen=[d]\n|Res1=[B]\nMask=[s11]\nSrv1=[B]\nDirIndex=[d]\nSrv2=[w]\n", "Count=[d]\n", "BlkType=[B]\nBlkLen=[d]\n*\nRes1=[B]\nMask=[s11]\nSrv1=[B]\nDirIndex=[d]\nSrv2=[w]\nRes2=[W]\nAttrib=[a]\nTime=[T1]Size=[D]\nName=[s13]\n", NULL } }, { SMBfunique, "SMBfunique", 0, { "Count=[d]\nAttrib=[A]\n", "Path=[Z]\nBlkType=[B]\nBlkLen=[d]\n|Res1=[B]\nMask=[s11]\nSrv1=[B]\nDirIndex=[d]\nSrv2=[w]\n", "Count=[d]\n", "BlkType=[B]\nBlkLen=[d]\n*\nRes1=[B]\nMask=[s11]\nSrv1=[B]\nDirIndex=[d]\nSrv2=[w]\nRes2=[W]\nAttrib=[a]\nTime=[T1]Size=[D]\nName=[s13]\n", NULL } }, { SMBfclose, "SMBfclose", 0, { "Count=[d]\nAttrib=[A]\n", "Path=[Z]\nBlkType=[B]\nBlkLen=[d]\n|Res1=[B]\nMask=[s11]\nSrv1=[B]\nDirIndex=[d]\nSrv2=[w]\n", "Count=[d]\n", "BlkType=[B]\nBlkLen=[d]\n*\nRes1=[B]\nMask=[s11]\nSrv1=[B]\nDirIndex=[d]\nSrv2=[w]\nRes2=[W]\nAttrib=[a]\nTime=[T1]Size=[D]\nName=[s13]\n", NULL } }, { SMBfindnclose, "SMBfindnclose", 0, { "Handle=[d]\n", NULL, NULL, NULL, NULL } }, { SMBfindclose, "SMBfindclose", 0, { "Handle=[d]\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=[d]\n", NULL, NULL } }, { SMBsendend, "SMBsendend", 0, { "GroupID=[d]\n", NULL, NULL, NULL, NULL } }, { SMBsendtxt, "SMBsendtxt", 0, { "GroupID=[d]\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=[d]\nFlags=[w]\nPassLen=[d]\nPasswd&Path&Device=\n", NULL, "Com2=[w]\nOff2=[d]\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=[d]\nRes=[b]\nNameLen=[ld]\nFlags=[W]\nRootDirectoryFid=[D]\nAccessMask=[W]\nAllocationSize=[L]\nExtFileAttributes=[W]\nShareAccess=[W]\nCreateDisposition=[W]\nCreateOptions=[W]\nImpersonationLevel=[W]\nSecurityFlags=[b]\n", "Path=[C]\n", "Com2=[w]\nOff2=[d]\nOplockLevel=[b]\nFid=[d]\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; int nterrcodes; 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 = [d]\nFlags1 = [B]\nFlags2 = [B][P13]\nTree ID = [d]\nProc ID = [d]\nUID = [d]\nMID = [d]\nWord Count = [b]\n"; int smboffset; ND_TCHECK(buf[9]); request = (buf[9] & 0x80) ? 0 : 1; flags2 = EXTRACT_LE_16BITS(&buf[10]); unicodestr = flags2 & 0x8000; nterrcodes = flags2 & 0x4000; startbuf = buf; command = buf[4]; fn = smbfind(command, smb_fns); if (ndo->ndo_vflag > 1) ND_PRINT((ndo, "\n")); ND_PRINT((ndo, "SMB PACKET: %s (%s)\n", fn->name, request ? "REQUEST" : "REPLY")); if (ndo->ndo_vflag < 2) return; /* print out the header */ smb_fdata(ndo, buf, fmt_smbheader, buf + 33, unicodestr); if (nterrcodes) { nterror = EXTRACT_LE_32BITS(&buf[5]); if (nterror) ND_PRINT((ndo, "NTError = %s\n", nt_errstr(nterror))); } else { if (buf[5]) ND_PRINT((ndo, "SMBError = %s\n", smb_errstr(buf[5], EXTRACT_LE_16BITS(&buf[7])))); } smboffset = 32; for (;;) { const char *f1, *f2; int wct; u_int bcc; int newsmboffset; words = buf + smboffset; ND_TCHECK(words[0]); wct = words[0]; data = words + 1 + wct * 2; maxwords = 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; } 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 { int i; int v; for (i = 0; &words[1 + 2 * i] < maxwords; i++) { ND_TCHECK2(words[1 + 2 * i], 2); v = EXTRACT_LE_16BITS(words + 1 + 2 * i); ND_PRINT((ndo, "smb_vwv[%d]=%d (0x%X)\n", i, v, v)); } } } ND_TCHECK2(*data, 2); bcc = EXTRACT_LE_16BITS(data); ND_PRINT((ndo, "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((ndo, "smb_buf[]=\n")); print_data(ndo, data + 2, min(bcc, PTR_DIFF(maxbuf, data + 2))); } } } if ((fn->flags & FLG_CHAIN) == 0) break; if (wct == 0) break; ND_TCHECK(words[1]); command = words[1]; if (command == 0xFF) break; ND_TCHECK2(words[3], 2); newsmboffset = EXTRACT_LE_16BITS(words + 3); fn = smbfind(command, smb_fns); ND_PRINT((ndo, "\nSMB PACKET: %s (%s) (CHAINED)\n", fn->name, request ? "REQUEST" : "REPLY")); if (newsmboffset <= smboffset) { ND_PRINT((ndo, "Bad andX offset: %u <= %u\n", newsmboffset, smboffset)); break; } smboffset = newsmboffset; } ND_PRINT((ndo, "\n")); return; trunc: ND_PRINT((ndo, "%s", tstr)); } /* * print a NBT packet received across tcp on port 139 */ void nbt_tcp_print(netdissect_options *ndo, const u_char *data, int length) { int caplen; int type; u_int nbt_len; const u_char *maxbuf; if (length < 4) goto trunc; if (ndo->ndo_snapend < data) goto trunc; caplen = ndo->ndo_snapend - data; if (caplen < 4) goto trunc; maxbuf = data + caplen; type = data[0]; nbt_len = EXTRACT_16BITS(data + 2); length -= 4; caplen -= 4; startbuf = data; if (ndo->ndo_vflag < 2) { ND_PRINT((ndo, " NBT Session Packet: ")); switch (type) { case 0x00: ND_PRINT((ndo, "Session Message")); break; case 0x81: ND_PRINT((ndo, "Session Request")); break; case 0x82: ND_PRINT((ndo, "Session Granted")); break; case 0x83: { int ecode; if (nbt_len < 4) goto trunc; if (length < 4) goto trunc; if (caplen < 4) goto trunc; ecode = data[4]; ND_PRINT((ndo, "Session Reject, ")); switch (ecode) { case 0x80: ND_PRINT((ndo, "Not listening on called name")); break; case 0x81: ND_PRINT((ndo, "Not listening for calling name")); break; case 0x82: ND_PRINT((ndo, "Called name not present")); break; case 0x83: ND_PRINT((ndo, "Called name present, but insufficient resources")); break; default: ND_PRINT((ndo, "Unspecified error 0x%X", ecode)); break; } } break; case 0x85: ND_PRINT((ndo, "Session Keepalive")); break; default: data = smb_fdata(ndo, data, "Unknown packet type [rB]", maxbuf, 0); break; } } else { ND_PRINT((ndo, "\n>>> NBT Session Packet\n")); switch (type) { case 0x00: data = smb_fdata(ndo, data, "[P1]NBT Session Message\nFlags=[B]\nLength=[rd]\n", data + 4, 0); if (data == NULL) break; if (nbt_len >= 4 && caplen >= 4 && memcmp(data,"\377SMB",4) == 0) { if ((int)nbt_len > caplen) { if ((int)nbt_len > length) ND_PRINT((ndo, "WARNING: Packet is continued in later TCP segments\n")); else ND_PRINT((ndo, "WARNING: Short packet. Try increasing the snap length by %d\n", nbt_len - caplen)); } print_smb(ndo, data, maxbuf > data + nbt_len ? data + nbt_len : maxbuf); } else ND_PRINT((ndo, "Session packet:(raw data or continuation?)\n")); break; case 0x81: data = smb_fdata(ndo, data, "[P1]NBT Session Request\nFlags=[B]\nLength=[rd]\nDestination=[n1]\nSource=[n1]\n", maxbuf, 0); break; case 0x82: data = smb_fdata(ndo, data, "[P1]NBT Session Granted\nFlags=[B]\nLength=[rd]\n", maxbuf, 0); break; case 0x83: { const u_char *origdata; int ecode; origdata = data; data = smb_fdata(ndo, data, "[P1]NBT SessionReject\nFlags=[B]\nLength=[rd]\nReason=[B]\n", maxbuf, 0); if (data == NULL) break; if (nbt_len >= 1 && caplen >= 1) { ecode = origdata[4]; switch (ecode) { case 0x80: ND_PRINT((ndo, "Not listening on called name\n")); break; case 0x81: ND_PRINT((ndo, "Not listening for calling name\n")); break; case 0x82: ND_PRINT((ndo, "Called name not present\n")); break; case 0x83: ND_PRINT((ndo, "Called name present, but insufficient resources\n")); break; default: ND_PRINT((ndo, "Unspecified error 0x%X\n", ecode)); break; } } } break; case 0x85: data = smb_fdata(ndo, data, "[P1]NBT Session Keepalive\nFlags=[B]\nLength=[rd]\n", maxbuf, 0); break; default: data = smb_fdata(ndo, data, "NBT - Unknown packet type\nType=[B]\n", maxbuf, 0); break; } ND_PRINT((ndo, "\n")); } return; trunc: ND_PRINT((ndo, "%s", tstr)); } 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, int length) { const u_char *maxbuf = data + length; int name_trn_id, response, opcode, nm_flags, rcode; int qdcount, ancount, nscount, arcount; const u_char *p; int total, i; ND_TCHECK2(data[10], 2); name_trn_id = EXTRACT_16BITS(data); response = (data[2] >> 7); opcode = (data[2] >> 3) & 0xF; nm_flags = ((data[2] & 0x7) << 4) + (data[3] >> 4); rcode = data[3] & 0xF; qdcount = EXTRACT_16BITS(data + 4); ancount = EXTRACT_16BITS(data + 6); nscount = EXTRACT_16BITS(data + 8); arcount = EXTRACT_16BITS(data + 10); startbuf = data; if (maxbuf <= data) return; if (ndo->ndo_vflag > 1) ND_PRINT((ndo, "\n>>> ")); ND_PRINT((ndo, "NBT UDP PACKET(137): %s", tok2str(opcode_str, "OPUNKNOWN", opcode))); if (response) { ND_PRINT((ndo, "; %s", rcode ? "NEGATIVE" : "POSITIVE")); } ND_PRINT((ndo, "; %s; %s", response ? "RESPONSE" : "REQUEST", (nm_flags & 1) ? "BROADCAST" : "UNICAST")); if (ndo->ndo_vflag < 2) return; ND_PRINT((ndo, "\nTrnID=0x%X\nOpCode=%d\nNmFlags=0x%X\nRcode=%d\nQueryCount=%d\nAnswerCount=%d\nAuthorityCount=%d\nAddressRecCount=%d\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((ndo, "Corrupt packet??\n")); return; } if (qdcount) { ND_PRINT((ndo, "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((ndo, "\nResourceRecords:\n")); for (i = 0; i < total; i++) { int rdlen; int restype; p = smb_fdata(ndo, p, "Name=[n1]\n#", maxbuf, 0); if (p == NULL) goto out; restype = EXTRACT_16BITS(p); p = smb_fdata(ndo, p, "ResType=[rw]\nResClass=[rw]\nTTL=[rD]\n", p + 8, 0); if (p == NULL) goto out; rdlen = EXTRACT_16BITS(p); ND_PRINT((ndo, "ResourceLength=%d\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) { int numnames; ND_TCHECK(*p); numnames = p[0]; 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(*p); if (p[0] & 0x80) ND_PRINT((ndo, " ")); switch (p[0] & 0x60) { case 0x00: ND_PRINT((ndo, "B ")); break; case 0x20: ND_PRINT((ndo, "P ")); break; case 0x40: ND_PRINT((ndo, "M ")); break; case 0x60: ND_PRINT((ndo, "_ ")); break; } if (p[0] & 0x10) ND_PRINT((ndo, " ")); if (p[0] & 0x08) ND_PRINT((ndo, " ")); if (p[0] & 0x04) ND_PRINT((ndo, " ")); if (p[0] & 0x02) ND_PRINT((ndo, " ")); ND_PRINT((ndo, "\n")); p += 2; } } else { print_data(ndo, p, min(rdlen, length - (p - data))); p += rdlen; } } } } if (p < maxbuf) smb_fdata(ndo, p, "AdditionalData:\n", maxbuf, 0); out: ND_PRINT((ndo, "\n")); return; trunc: ND_PRINT((ndo, "%s", tstr)); } /* * Print an SMB-over-TCP packet received across tcp on port 445 */ void smb_tcp_print(netdissect_options *ndo, const u_char * data, int length) { int caplen; u_int smb_len; const u_char *maxbuf; if (length < 4) goto trunc; if (ndo->ndo_snapend < data) goto trunc; caplen = ndo->ndo_snapend - data; if (caplen < 4) goto trunc; maxbuf = data + caplen; smb_len = EXTRACT_24BITS(data + 1); length -= 4; caplen -= 4; startbuf = data; data += 4; if (smb_len >= 4 && caplen >= 4 && memcmp(data,"\377SMB",4) == 0) { if ((int)smb_len > caplen) { if ((int)smb_len > length) - ND_PRINT((ndo, "WARNING: Packet is continued in later TCP segments\n")); + ND_PRINT((ndo, " WARNING: Packet is continued in later TCP segments\n")); else - ND_PRINT((ndo, "WARNING: Short packet. Try increasing the snap length by %d\n", + ND_PRINT((ndo, " WARNING: Short packet. Try increasing the snap length by %d\n", smb_len - caplen)); - } + } else + ND_PRINT((ndo, " ")); print_smb(ndo, data, maxbuf > data + smb_len ? data + smb_len : maxbuf); } else - ND_PRINT((ndo, "SMB-over-TCP packet:(raw data or continuation?)\n")); + ND_PRINT((ndo, " SMB-over-TCP packet:(raw data or continuation?)\n")); return; trunc: ND_PRINT((ndo, "%s", tstr)); } /* * print a NBT packet received across udp on port 138 */ void nbt_udp138_print(netdissect_options *ndo, const u_char *data, int length) { const u_char *maxbuf = data + length; if (maxbuf > ndo->ndo_snapend) maxbuf = ndo->ndo_snapend; if (maxbuf <= data) return; startbuf = data; if (ndo->ndo_vflag < 2) { ND_PRINT((ndo, "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=[rd] Length=[rd] 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: ND_PRINT((ndo, "\n")); } /* print netbeui frames */ 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, int length) { const u_char *maxbuf = data + length; int len; int command; const u_char *data2; int is_truncated = 0; if (maxbuf > ndo->ndo_snapend) maxbuf = ndo->ndo_snapend; ND_TCHECK(data[4]); len = EXTRACT_LE_16BITS(data); command = data[4]; data2 = data + len; if (data2 >= maxbuf) { data2 = maxbuf; is_truncated = 1; } startbuf = data; if (ndo->ndo_vflag < 2) { ND_PRINT((ndo, "NBF Packet: ")); data = smb_fdata(ndo, data, "[P5]#", maxbuf, 0); } else { ND_PRINT((ndo, "\n>>> NBF Packet\nType=0x%X ", control)); data = smb_fdata(ndo, data, "Length=[d] 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((ndo, "%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((ndo, "%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((ndo, "\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 { int i; for (i = 0; i < 128; i++) { if (&data2[i + 3] >= maxbuf) break; if (memcmp(&data2[i], "\377SMB", 4) == 0) { ND_PRINT((ndo, "found SMB packet at %d\n", i)); print_smb(ndo, &data2[i], maxbuf); break; } } } out: ND_PRINT((ndo, "\n")); return; trunc: ND_PRINT((ndo, "%s", tstr)); } /* * 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 */ int i; const u_char *maxbuf; 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); ND_PRINT((ndo, "\n")); break; } } if (i == 128) smb_fdata(ndo, data, "\n>>> Unknown IPX ", maxbuf, 0); } Index: head/contrib/tcpdump/print-smtp.c =================================================================== --- head/contrib/tcpdump/print-smtp.c (nonexistent) +++ head/contrib/tcpdump/print-smtp.c (revision 285275) @@ -0,0 +1,30 @@ +/* + * 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 + +#include +#include + +#include "netdissect.h" +#include "extract.h" + +void +smtp_print(netdissect_options *ndo, const u_char *pptr, u_int len) +{ + txtproto_print(ndo, pptr, len, "smtp", NULL, 0); +} Property changes on: head/contrib/tcpdump/print-smtp.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/contrib/tcpdump/print-tcp.c =================================================================== --- head/contrib/tcpdump/print-tcp.c (revision 285274) +++ head/contrib/tcpdump/print-tcp.c (revision 285275) @@ -1,884 +1,897 @@ /* $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. */ #ifndef lint #else __RCSID("$NetBSD: print-tcp.c,v 1.8 2007/07/24 11:53:48 drochner Exp $"); #endif #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "interface.h" #include "addrtoname.h" #include "extract.h" #include "tcp.h" #include "ip.h" #ifdef INET6 #include "ip6.h" #endif #include "ipproto.h" #include "rpc_auth.h" #include "rpc_msg.h" #include "nameser.h" #ifdef HAVE_LIBCRYPTO #include #include static int tcp_verify_signature(netdissect_options *ndo, const struct ip *ip, const struct tcphdr *tp, const u_char *data, int length, const u_char *rcvsig); #endif static void print_tcp_rst_data(netdissect_options *, register const u_char *sp, u_int length); #define MAX_RST_DATA_LEN 30 struct tha { struct in_addr src; struct in_addr dst; u_int port; }; struct tcp_seq_hash { struct tcp_seq_hash *nxt; struct tha addr; tcp_seq seq; tcp_seq ack; }; #ifdef INET6 struct tha6 { struct in6_addr src; struct in6_addr dst; u_int port; }; struct tcp_seq_hash6 { struct tcp_seq_hash6 *nxt; struct tha6 addr; tcp_seq seq; tcp_seq ack; }; #endif #define TSEQ_HASHSIZE 919 /* These tcp optinos 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]; #ifdef INET6 static struct tcp_seq_hash6 tcp_seq_hash6[TSEQ_HASHSIZE]; #endif 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_SIGNATURE, "md5" }, { TCPOPT_AUTH, "enhanced auth" }, { TCPOPT_UTO, "uto" }, { TCPOPT_MPTCP, "mptcp" }, { TCPOPT_EXPERIMENT2, "exp" }, { 0, NULL } }; static int tcp_cksum(netdissect_options *ndo, register const struct ip *ip, register const struct tcphdr *tp, register u_int len) { return nextproto4_cksum(ndo, ip, (const uint8_t *)tp, len, len, IPPROTO_TCP); } void tcp_print(netdissect_options *ndo, register const u_char *bp, register u_int length, register const u_char *bp2, int fragmented) { register const struct tcphdr *tp; register const struct ip *ip; register u_char flags; register u_int hlen; register char ch; uint16_t sport, dport, win, urp; uint32_t seq, ack, thseq, thack; u_int utoval; uint16_t magic; register int rev; #ifdef INET6 register const struct ip6_hdr *ip6; #endif tp = (struct tcphdr *)bp; ip = (struct ip *)bp2; #ifdef INET6 if (IP_V(ip) == 6) ip6 = (struct ip6_hdr *)bp2; else ip6 = NULL; #endif /*INET6*/ ch = '\0'; if (!ND_TTEST(tp->th_dport)) { ND_PRINT((ndo, "%s > %s: [|tcp]", ipaddr_string(ndo, &ip->ip_src), ipaddr_string(ndo, &ip->ip_dst))); return; } sport = EXTRACT_16BITS(&tp->th_sport); dport = EXTRACT_16BITS(&tp->th_dport); hlen = TH_OFF(tp) * 4; #ifdef INET6 if (ip6) { if (ip6->ip6_nxt == IPPROTO_TCP) { ND_PRINT((ndo, "%s.%s > %s.%s: ", ip6addr_string(ndo, &ip6->ip6_src), tcpport_string(sport), ip6addr_string(ndo, &ip6->ip6_dst), tcpport_string(dport))); } else { ND_PRINT((ndo, "%s > %s: ", tcpport_string(sport), tcpport_string(dport))); } } else #endif /*INET6*/ { if (ip->ip_p == IPPROTO_TCP) { ND_PRINT((ndo, "%s.%s > %s.%s: ", ipaddr_string(ndo, &ip->ip_src), tcpport_string(sport), ipaddr_string(ndo, &ip->ip_dst), tcpport_string(dport))); } else { ND_PRINT((ndo, "%s > %s: ", tcpport_string(sport), tcpport_string(dport))); } } if (hlen < sizeof(*tp)) { ND_PRINT((ndo, " tcp %d [bad hdr length %u - too short, < %lu]", length - hlen, hlen, (unsigned long)sizeof(*tp))); return; } ND_TCHECK(*tp); seq = EXTRACT_32BITS(&tp->th_seq); ack = EXTRACT_32BITS(&tp->th_ack); win = EXTRACT_16BITS(&tp->th_win); urp = EXTRACT_16BITS(&tp->th_urp); if (ndo->ndo_qflag) { ND_PRINT((ndo, "tcp %d", length - hlen)); if (hlen > length) { ND_PRINT((ndo, " [bad hdr length %u - too long, > %u]", hlen, length)); } return; } flags = tp->th_flags; ND_PRINT((ndo, "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; #ifdef INET6 if (ip6) { register struct tcp_seq_hash6 *th; struct tcp_seq_hash6 *tcp_seq_hash; const struct in6_addr *src, *dst; struct tha6 tha; tcp_seq_hash = tcp_seq_hash6; src = &ip6->ip6_src; dst = &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 = dport << 16 | sport; } else { UNALIGNED_MEMCPY(&tha.dst, dst, sizeof ip6->ip6_dst); UNALIGNED_MEMCPY(&tha.src, src, sizeof ip6->ip6_src); tha.port = 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 */ if (th->nxt == NULL) { th->nxt = (struct tcp_seq_hash6 *) calloc(1, sizeof(*th)); if (th->nxt == NULL) error("tcp_print: calloc"); } 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 { #else /*INET6*/ { #endif /*INET6*/ register struct tcp_seq_hash *th; struct tcp_seq_hash *tcp_seq_hash; const struct in_addr *src, *dst; struct tha tha; tcp_seq_hash = tcp_seq_hash4; src = &ip->ip_src; dst = &ip->ip_dst; if (sport > dport) rev = 1; else if (sport == dport) { if (UNALIGNED_MEMCMP(src, dst, sizeof ip->ip_dst) > 0) rev = 1; } if (rev) { UNALIGNED_MEMCPY(&tha.src, dst, sizeof ip->ip_dst); UNALIGNED_MEMCPY(&tha.dst, src, sizeof ip->ip_src); tha.port = dport << 16 | sport; } else { UNALIGNED_MEMCPY(&tha.dst, dst, sizeof ip->ip_dst); UNALIGNED_MEMCPY(&tha.src, src, sizeof ip->ip_src); tha.port = 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 */ if (th->nxt == NULL) { th->nxt = (struct tcp_seq_hash *) calloc(1, sizeof(*th)); if (th->nxt == NULL) error("tcp_print: calloc"); } 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((ndo, " [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_TTEST2(tp->th_sport, length)) { sum = tcp_cksum(ndo, ip, tp, length); tcp_sum = EXTRACT_16BITS(&tp->th_sum); ND_PRINT((ndo, ", cksum 0x%04x", tcp_sum)); if (sum != 0) ND_PRINT((ndo, " (incorrect -> 0x%04x)", in_cksum_shouldbe(tcp_sum, sum))); else ND_PRINT((ndo, " (correct)")); } } #ifdef INET6 else if (IP_V(ip) == 6 && ip6->ip6_plen) { if (ND_TTEST2(tp->th_sport, length)) { sum = nextproto6_cksum(ip6, (const uint8_t *)tp, length, length, IPPROTO_TCP); tcp_sum = EXTRACT_16BITS(&tp->th_sum); ND_PRINT((ndo, ", cksum 0x%04x", tcp_sum)); if (sum != 0) ND_PRINT((ndo, " (incorrect -> 0x%04x)", in_cksum_shouldbe(tcp_sum, sum))); else ND_PRINT((ndo, " (correct)")); } } #endif } length -= hlen; if (ndo->ndo_vflag > 1 || length > 0 || flags & (TH_SYN | TH_FIN | TH_RST)) { ND_PRINT((ndo, ", seq %u", seq)); if (length > 0) { ND_PRINT((ndo, ":%u", seq + length)); } } if (flags & TH_ACK) { ND_PRINT((ndo, ", ack %u", ack)); } ND_PRINT((ndo, ", win %d", win)); if (flags & TH_URG) ND_PRINT((ndo, ", urg %d", urp)); /* * Handle any options. */ if (hlen > sizeof(*tp)) { register const u_char *cp; register u_int i, opt, datalen; register u_int len; hlen -= sizeof(*tp); cp = (const u_char *)tp + sizeof(*tp); ND_PRINT((ndo, ", options [")); while (hlen > 0) { if (ch != '\0') ND_PRINT((ndo, "%c", ch)); ND_TCHECK(*cp); opt = *cp++; if (ZEROLENOPT(opt)) len = 1; else { ND_TCHECK(*cp); len = *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_TCHECK2(*cp, l); } ND_PRINT((ndo, "%s", tok2str(tcp_option_values, "unknown-%u", opt))); switch (opt) { case TCPOPT_MAXSEG: datalen = 2; LENCHECK(datalen); ND_PRINT((ndo, " %u", EXTRACT_16BITS(cp))); break; case TCPOPT_WSCALE: datalen = 1; LENCHECK(datalen); ND_PRINT((ndo, " %u", *cp)); break; case TCPOPT_SACK: datalen = len - 2; if (datalen % 8 != 0) { ND_PRINT((ndo, "malformed sack")); } else { uint32_t s, e; ND_PRINT((ndo, " %d ", datalen / 8)); for (i = 0; i < datalen; i += 8) { LENCHECK(i + 4); s = EXTRACT_32BITS(cp + i); LENCHECK(i + 8); e = EXTRACT_32BITS(cp + i + 4); if (rev) { s -= thseq; e -= thseq; } else { s -= thack; e -= thack; } ND_PRINT((ndo, "{%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((ndo, " %u", EXTRACT_32BITS(cp))); break; case TCPOPT_TIMESTAMP: datalen = 8; LENCHECK(datalen); ND_PRINT((ndo, " val %u ecr %u", EXTRACT_32BITS(cp), EXTRACT_32BITS(cp + 4))); break; case TCPOPT_SIGNATURE: datalen = TCP_SIGLEN; LENCHECK(datalen); #ifdef HAVE_LIBCRYPTO switch (tcp_verify_signature(ndo, ip, tp, bp + TH_OFF(tp) * 4, length, cp)) { case SIGNATURE_VALID: ND_PRINT((ndo, "valid")); break; case SIGNATURE_INVALID: ND_PRINT((ndo, "invalid")); break; case CANT_CHECK_SIGNATURE: ND_PRINT((ndo, "can't check - ")); for (i = 0; i < TCP_SIGLEN; ++i) ND_PRINT((ndo, "%02x", cp[i])); break; } #else for (i = 0; i < TCP_SIGLEN; ++i) ND_PRINT((ndo, "%02x", cp[i])); #endif break; case TCPOPT_AUTH: ND_PRINT((ndo, "keyid %d", *cp++)); datalen = len - 3; for (i = 0; i < datalen; ++i) { LENCHECK(i); ND_PRINT((ndo, "%02x", 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 = EXTRACT_16BITS(cp); ND_PRINT((ndo, "0x%x", utoval)); if (utoval & 0x0001) utoval = (utoval >> 1) * 60; else utoval >>= 1; ND_PRINT((ndo, " %u", utoval)); break; case TCPOPT_MPTCP: datalen = len - 2; LENCHECK(datalen); if (!mptcp_print(ndo, cp-2, len, flags)) goto bad; break; case TCPOPT_EXPERIMENT2: datalen = len - 2; LENCHECK(datalen); if (datalen < 2) goto bad; /* RFC6994 */ magic = EXTRACT_16BITS(cp); ND_PRINT((ndo, "-")); switch(magic) { case 0xf989: - /* TCP Fast Open: draft-ietf-tcpm-fastopen-04 */ + /* TCP Fast Open: RFC 7413 */ if (datalen == 2) { /* Fast Open Cookie Request */ ND_PRINT((ndo, "tfo cookiereq")); } else { /* Fast Open Cookie */ if (datalen % 2 != 0 || datalen < 6 || datalen > 18) { ND_PRINT((ndo, "tfo malformed")); } else { ND_PRINT((ndo, "tfo cookie ")); for (i = 2; i < datalen; ++i) ND_PRINT((ndo, "%02x", cp[i])); } } break; default: /* Unknown magic number */ ND_PRINT((ndo, "%04x", magic)); break; } break; default: datalen = len - 2; if (datalen) ND_PRINT((ndo, " 0x")); for (i = 0; i < datalen; ++i) { LENCHECK(i); ND_PRINT((ndo, "%02x", 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((ndo, "[len %d]", len)); ch = ','; if (opt == TCPOPT_EOL) break; } ND_PRINT((ndo, "]")); } /* * Print length field before crawling down the stack. */ ND_PRINT((ndo, ", length %u", length)); if (length <= 0) return; /* * Decode payload if necessary. */ bp += TH_OFF(tp) * 4; 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; } return; } if (sport == TELNET_PORT || dport == TELNET_PORT) { - if (!ndo->ndo_qflag && ndo->ndo_vflag) - telnet_print(ndo, bp, length); + telnet_print(ndo, bp, length); + } else if (sport == SMTP_PORT || dport == SMTP_PORT) { + ND_PRINT((ndo, ": ")); + smtp_print(ndo, bp, length); } else if (sport == BGP_PORT || dport == BGP_PORT) bgp_print(ndo, bp, length); else if (sport == PPTP_PORT || dport == PPTP_PORT) pptp_print(ndo, bp); #ifdef TCPDUMP_DO_SMB else if (sport == NETBIOS_SSN_PORT || dport == NETBIOS_SSN_PORT) nbt_tcp_print(ndo, bp, length); else if (sport == SMB_PORT || dport == SMB_PORT) smb_tcp_print(ndo, bp, length); #endif else if (sport == BEEP_PORT || dport == BEEP_PORT) beep_print(ndo, bp, length); else if (sport == OPENFLOW_PORT_OLD || dport == OPENFLOW_PORT_OLD || sport == OPENFLOW_PORT_IANA || dport == OPENFLOW_PORT_IANA) openflow_print(ndo, bp, length); - else if (length > 2 && + else if (sport == FTP_PORT || dport == FTP_PORT) { + ND_PRINT((ndo, ": ")); + ftp_print(ndo, bp, length); + } else if (sport == HTTP_PORT || dport == HTTP_PORT || + sport == HTTP_PORT_ALT || dport == HTTP_PORT_ALT) { + ND_PRINT((ndo, ": ")); + http_print(ndo, bp, length); + } else if (sport == RTSP_PORT || dport == RTSP_PORT || + sport == RTSP_PORT_ALT || dport == RTSP_PORT_ALT) { + ND_PRINT((ndo, ": ")); + rtsp_print(ndo, bp, length); + } else if (length > 2 && (sport == NAMESERVER_PORT || dport == NAMESERVER_PORT || sport == MULTICASTDNS_PORT || dport == MULTICASTDNS_PORT)) { /* * TCP DNS query has 2byte length at the head. * XXX packet could be unaligned, it can go strange */ ns_print(ndo, bp + 2, length - 2, 0); } else if (sport == MSDP_PORT || dport == MSDP_PORT) { msdp_print(ndo, bp, length); } else if (sport == RPKI_RTR_PORT || dport == RPKI_RTR_PORT) { rpki_rtr_print(ndo, bp, length); } else if (length > 0 && (sport == LDP_PORT || dport == LDP_PORT)) { ldp_print(ndo, bp, length); } else if ((sport == NFS_PORT || dport == NFS_PORT) && length >= 4 && ND_TTEST2(*bp, 4)) { /* * 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; register struct sunrpc_msg *rp; enum sunrpc_msg_type direction; fraglen = EXTRACT_32BITS(bp) & 0x7FFFFFFF; if (fraglen > (length) - 4) fraglen = (length) - 4; rp = (struct sunrpc_msg *)(bp + 4); if (ND_TTEST(rp->rm_direction)) { direction = (enum sunrpc_msg_type)EXTRACT_32BITS(&rp->rm_direction); if (dport == NFS_PORT && direction == SUNRPC_CALL) { ND_PRINT((ndo, ": NFS request xid %u ", EXTRACT_32BITS(&rp->rm_xid))); nfsreq_print_noaddr(ndo, (u_char *)rp, fraglen, (u_char *)ip); return; } if (sport == NFS_PORT && direction == SUNRPC_REPLY) { ND_PRINT((ndo, ": NFS reply xid %u ", EXTRACT_32BITS(&rp->rm_xid))); nfsreply_print_noaddr(ndo, (u_char *)rp, fraglen, (u_char *)ip); return; } } } return; bad: ND_PRINT((ndo, "[bad opt]")); if (ch != '\0') ND_PRINT((ndo, ">")); return; trunc: ND_PRINT((ndo, "[|tcp]")); if (ch != '\0') ND_PRINT((ndo, ">")); } /* * 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, register const u_char *sp, u_int length) { int c; ND_PRINT((ndo, ND_TTEST2(*sp, length) ? " [RST" : " [!RST")); if (length > MAX_RST_DATA_LEN) { length = MAX_RST_DATA_LEN; /* can use -X for longer */ ND_PRINT((ndo, "+")); /* indicate we truncate */ } ND_PRINT((ndo, " ")); while (length-- && sp <= ndo->ndo_snapend) { c = *sp++; safeputchar(ndo, c); } ND_PRINT((ndo, "]")); } #ifdef HAVE_LIBCRYPTO USES_APPLE_DEPRECATED_API static int tcp_verify_signature(netdissect_options *ndo, const struct ip *ip, const struct tcphdr *tp, const u_char *data, 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; #ifdef INET6 struct ip6_hdr *ip6; uint32_t len32; uint8_t nxt; #endif if (data + length > ndo->ndo_snapend) { ND_PRINT((ndo, "snaplen too short, ")); return (CANT_CHECK_SIGNATURE); } tp1 = *tp; if (ndo->ndo_sigsecret == NULL) { ND_PRINT((ndo, "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, (char *)&ip->ip_src, sizeof(ip->ip_src)); MD5_Update(&ctx, (char *)&ip->ip_dst, sizeof(ip->ip_dst)); MD5_Update(&ctx, (char *)&zero_proto, sizeof(zero_proto)); MD5_Update(&ctx, (char *)&ip->ip_p, sizeof(ip->ip_p)); tlen = EXTRACT_16BITS(&ip->ip_len) - IP_HL(ip) * 4; tlen = htons(tlen); MD5_Update(&ctx, (char *)&tlen, sizeof(tlen)); #ifdef INET6 } else if (IP_V(ip) == 6) { ip6 = (struct ip6_hdr *)ip; MD5_Update(&ctx, (char *)&ip6->ip6_src, sizeof(ip6->ip6_src)); MD5_Update(&ctx, (char *)&ip6->ip6_dst, sizeof(ip6->ip6_dst)); len32 = htonl(EXTRACT_16BITS(&ip6->ip6_plen)); MD5_Update(&ctx, (char *)&len32, sizeof(len32)); nxt = 0; MD5_Update(&ctx, (char *)&nxt, sizeof(nxt)); MD5_Update(&ctx, (char *)&nxt, sizeof(nxt)); MD5_Update(&ctx, (char *)&nxt, sizeof(nxt)); nxt = IPPROTO_TCP; MD5_Update(&ctx, (char *)&nxt, sizeof(nxt)); #endif } else { #ifdef INET6 ND_PRINT((ndo, "IP version not 4 or 6, ")); #else ND_PRINT((ndo, "IP version not 4, ")); #endif return (CANT_CHECK_SIGNATURE); } /* * Step 2: Update MD5 hash with TCP header, excluding options. * The TCP checksum must be set to zero. */ savecsum = tp1.th_sum; tp1.th_sum = 0; MD5_Update(&ctx, (char *)&tp1, sizeof(struct tcphdr)); tp1.th_sum = savecsum; /* * 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); } USES_APPLE_RST #endif /* HAVE_LIBCRYPTO */ /* * Local Variables: * c-style: whitesmith * c-basic-offset: 8 * End: */ Index: head/contrib/tcpdump/print-telnet.c =================================================================== --- head/contrib/tcpdump/print-telnet.c (revision 285274) +++ head/contrib/tcpdump/print-telnet.c (revision 285275) @@ -1,543 +1,547 @@ /* $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. */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "interface.h" #define TELCMDS #define TELOPTS /* 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 */ #ifdef TELCMDS const char *telcmds[] = { "EOF", "SUSP", "ABORT", "EOR", "SE", "NOP", "DMARK", "BRK", "IP", "AO", "AYT", "EC", "EL", "GA", "SB", "WILL", "WONT", "DO", "DONT", "IAC", 0, }; #else extern char *telcmds[]; #endif #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_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) #ifdef TELOPTS 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] #endif /* 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; \ ND_TCHECK(*sp); \ c = *sp++; \ length--; \ } while (0) osp = sp; FETCH(c, sp, length); if (c != IAC) goto pktend; FETCH(c, sp, length); if (c == IAC) { /* ! */ if (print) ND_PRINT((ndo, "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((ndo, "%s %s", telcmds[i], telopts[x])); } else { if (print) ND_PRINT((ndo, "%s %#x", telcmds[i], x)); } if (c != SB) break; /* IAC SB .... IAC SE */ p = sp; while (length > (u_int)(p + 1 - sp)) { if (p[0] == IAC && p[1] == SE) break; p++; } if (*p != IAC) goto pktend; switch (x) { case TELOPT_AUTHENTICATION: if (p <= sp) break; FETCH(c, sp, length); if (print) ND_PRINT((ndo, " %s", STR_OR_ID(c, authcmd))); if (p <= sp) break; FETCH(c, sp, length); if (print) ND_PRINT((ndo, " %s", STR_OR_ID(c, authtype))); break; case TELOPT_ENCRYPT: if (p <= sp) break; FETCH(c, sp, length); if (print) ND_PRINT((ndo, " %s", STR_OR_ID(c, enccmd))); if (p <= sp) break; FETCH(c, sp, length); if (print) ND_PRINT((ndo, " %s", STR_OR_ID(c, enctype))); break; default: if (p <= sp) break; FETCH(c, sp, length); if (print) ND_PRINT((ndo, " %s", STR_OR_ID(c, cmds))); break; } while (p > sp) { FETCH(x, sp, length); if (print) ND_PRINT((ndo, " %#x", x)); } /* terminating IAC SE */ if (print) ND_PRINT((ndo, " SE")); sp += 2; break; default: if (print) ND_PRINT((ndo, "%s", telcmds[i])); goto done; } done: return sp - osp; trunc: ND_PRINT((ndo, "[|telnet]")); 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; osp = sp; while (length > 0 && *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((ndo, "\nTelnet:")); hex_print_with_offset(ndo, "\n", sp, l, sp - osp); if (l > 8) ND_PRINT((ndo, "\n\t\t\t\t")); else ND_PRINT((ndo, "%*s\t", (8 - l) * 3, "")); } else ND_PRINT((ndo, "%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((ndo, "\n")); else ND_PRINT((ndo, "]")); } } Index: head/contrib/tcpdump/print-udp.c =================================================================== --- head/contrib/tcpdump/print-udp.c (revision 285274) +++ head/contrib/tcpdump/print-udp.c (revision 285275) @@ -1,696 +1,710 @@ /* * 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. * * $FreeBSD$ */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "interface.h" #include "addrtoname.h" #include "extract.h" #include "appletalk.h" #include "udp.h" #include "ip.h" #ifdef INET6 #include "ip6.h" #endif #include "ipproto.h" #include "rpc_auth.h" #include "rpc_msg.h" #include "nameser.h" #include "nfs.h" -#include "bootp.h" struct rtcphdr { uint16_t rh_flags; /* T:2 P:1 CNT:5 PT:8 */ uint16_t rh_len; /* length of message (in words) */ uint32_t rh_ssrc; /* synchronization src id */ }; typedef struct { uint32_t upper; /* more significant 32 bits */ uint32_t lower; /* less significant 32 bits */ } ntp64; /* * Sender report. */ struct rtcp_sr { ntp64 sr_ntp; /* 64-bit ntp timestamp */ uint32_t sr_ts; /* reference media timestamp */ uint32_t sr_np; /* no. packets sent */ uint32_t sr_nb; /* no. bytes sent */ }; /* * Receiver report. * Time stamps are middle 32-bits of ntp timestamp. */ struct rtcp_rr { uint32_t rr_srcid; /* sender being reported */ uint32_t rr_nl; /* no. packets lost */ uint32_t rr_ls; /* extended last seq number received */ uint32_t rr_dv; /* jitter (delay variance) */ uint32_t rr_lsr; /* orig. ts from last rr from this src */ 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 void *hdr, register const struct udphdr *up) { /* vat/vt audio */ u_int ts = *(uint16_t *)hdr; if ((ts & 0xf060) != 0) { /* probably vt */ ND_PRINT((ndo, "udp/vt %u %d / %d", (uint32_t)(EXTRACT_16BITS(&up->uh_ulen) - sizeof(*up)), ts & 0x3ff, ts >> 10)); } else { /* probably vat */ uint32_t i0 = EXTRACT_32BITS(&((u_int *)hdr)[0]); uint32_t i1 = EXTRACT_32BITS(&((u_int *)hdr)[1]); ND_PRINT((ndo, "udp/vat %u c%d %u%s", (uint32_t)(EXTRACT_16BITS(&up->uh_ulen) - sizeof(*up) - 8), i0 & 0xffff, i1, i0 & 0x800000? "*" : "")); /* audio format */ if (i0 & 0x1f0000) ND_PRINT((ndo, " f%d", (i0 >> 16) & 0x1f)); if (i0 & 0x3f000000) ND_PRINT((ndo, " s%d", (i0 >> 24) & 0x3f)); } } static void rtp_print(netdissect_options *ndo, const void *hdr, u_int len, register const struct udphdr *up) { /* rtp v1 or v2 */ u_int *ip = (u_int *)hdr; u_int hasopt, hasext, contype, hasmarker; uint32_t i0 = EXTRACT_32BITS(&((u_int *)hdr)[0]); uint32_t i1 = EXTRACT_32BITS(&((u_int *)hdr)[1]); u_int dlen = EXTRACT_16BITS(&up->uh_ulen) - sizeof(*up) - 8; const char * ptype; ip += 2; len >>= 2; len -= 2; hasopt = 0; hasext = 0; if ((i0 >> 30) == 1) { /* rtp v1 */ hasopt = i0 & 0x800000; contype = (i0 >> 16) & 0x3f; hasmarker = i0 & 0x400000; ptype = "rtpv1"; } else { /* rtp v2 */ hasext = i0 & 0x10000000; contype = (i0 >> 16) & 0x7f; hasmarker = i0 & 0x800000; dlen -= 4; ptype = "rtp"; ip += 1; len -= 1; } ND_PRINT((ndo, "udp/%s %d c%d %s%s %d %u", ptype, dlen, contype, (hasopt || hasext)? "+" : "", hasmarker? "*" : "", i0 & 0xffff, i1)); if (ndo->ndo_vflag) { ND_PRINT((ndo, " %u", EXTRACT_32BITS(&((u_int *)hdr)[2]))); if (hasopt) { u_int i2, optlen; do { i2 = ip[0]; optlen = (i2 >> 16) & 0xff; if (optlen == 0 || optlen > len) { ND_PRINT((ndo, " !opt")); return; } ip += optlen; len -= optlen; } while ((int)i2 >= 0); } if (hasext) { u_int i2, extlen; i2 = ip[0]; extlen = (i2 & 0xffff) + 1; if (extlen > len) { ND_PRINT((ndo, " !ext")); return; } ip += extlen; } if (contype == 0x1f) /*XXX H.261 */ ND_PRINT((ndo, " 0x%04x", ip[0] >> 16)); } } static const u_char * rtcp_print(netdissect_options *ndo, const u_char *hdr, const u_char *ep) { /* rtp v2 control (rtcp) */ struct rtcp_rr *rr = 0; struct rtcp_sr *sr; struct rtcphdr *rh = (struct rtcphdr *)hdr; u_int len; uint16_t flags; int cnt; double ts, dts; if ((u_char *)(rh + 1) > ep) { ND_PRINT((ndo, " [|rtcp]")); return (ep); } len = (EXTRACT_16BITS(&rh->rh_len) + 1) * 4; flags = EXTRACT_16BITS(&rh->rh_flags); cnt = (flags >> 8) & 0x1f; switch (flags & 0xff) { case RTCP_PT_SR: sr = (struct rtcp_sr *)(rh + 1); ND_PRINT((ndo, " sr")); if (len != cnt * sizeof(*rr) + sizeof(*sr) + sizeof(*rh)) ND_PRINT((ndo, " [%d]", len)); if (ndo->ndo_vflag) ND_PRINT((ndo, " %u", EXTRACT_32BITS(&rh->rh_ssrc))); if ((u_char *)(sr + 1) > ep) { ND_PRINT((ndo, " [|rtcp]")); return (ep); } ts = (double)(EXTRACT_32BITS(&sr->sr_ntp.upper)) + ((double)(EXTRACT_32BITS(&sr->sr_ntp.lower)) / 4294967296.0); ND_PRINT((ndo, " @%.2f %u %up %ub", ts, EXTRACT_32BITS(&sr->sr_ts), EXTRACT_32BITS(&sr->sr_np), EXTRACT_32BITS(&sr->sr_nb))); rr = (struct rtcp_rr *)(sr + 1); break; case RTCP_PT_RR: ND_PRINT((ndo, " rr")); if (len != cnt * sizeof(*rr) + sizeof(*rh)) ND_PRINT((ndo, " [%d]", len)); rr = (struct rtcp_rr *)(rh + 1); if (ndo->ndo_vflag) ND_PRINT((ndo, " %u", EXTRACT_32BITS(&rh->rh_ssrc))); break; case RTCP_PT_SDES: ND_PRINT((ndo, " sdes %d", len)); if (ndo->ndo_vflag) ND_PRINT((ndo, " %u", EXTRACT_32BITS(&rh->rh_ssrc))); cnt = 0; break; case RTCP_PT_BYE: ND_PRINT((ndo, " bye %d", len)); if (ndo->ndo_vflag) ND_PRINT((ndo, " %u", EXTRACT_32BITS(&rh->rh_ssrc))); cnt = 0; break; default: ND_PRINT((ndo, " type-0x%x %d", flags & 0xff, len)); cnt = 0; break; } if (cnt > 1) ND_PRINT((ndo, " c%d", cnt)); while (--cnt >= 0) { if ((u_char *)(rr + 1) > ep) { ND_PRINT((ndo, " [|rtcp]")); return (ep); } if (ndo->ndo_vflag) ND_PRINT((ndo, " %u", EXTRACT_32BITS(&rr->rr_srcid))); ts = (double)(EXTRACT_32BITS(&rr->rr_lsr)) / 65536.; dts = (double)(EXTRACT_32BITS(&rr->rr_dlsr)) / 65536.; ND_PRINT((ndo, " %ul %us %uj @%.2f+%.2f", EXTRACT_32BITS(&rr->rr_nl) & 0x00ffffff, EXTRACT_32BITS(&rr->rr_ls), EXTRACT_32BITS(&rr->rr_dv), ts, dts)); } return (hdr + len); } static int udp_cksum(netdissect_options *ndo, register const struct ip *ip, register const struct udphdr *up, register u_int len) { return nextproto4_cksum(ndo, ip, (const uint8_t *)(void *)up, len, len, IPPROTO_UDP); } #ifdef INET6 static int udp6_cksum(const struct ip6_hdr *ip6, const struct udphdr *up, u_int len) { return nextproto6_cksum(ip6, (const uint8_t *)(void *)up, len, len, IPPROTO_UDP); } #endif static void udpipaddr_print(netdissect_options *ndo, const struct ip *ip, int sport, int dport) { #ifdef INET6 const struct ip6_hdr *ip6; if (IP_V(ip) == 6) ip6 = (const struct ip6_hdr *)ip; else ip6 = NULL; if (ip6) { if (ip6->ip6_nxt == IPPROTO_UDP) { if (sport == -1) { ND_PRINT((ndo, "%s > %s: ", ip6addr_string(ndo, &ip6->ip6_src), ip6addr_string(ndo, &ip6->ip6_dst))); } else { ND_PRINT((ndo, "%s.%s > %s.%s: ", ip6addr_string(ndo, &ip6->ip6_src), udpport_string(sport), ip6addr_string(ndo, &ip6->ip6_dst), udpport_string(dport))); } } else { if (sport != -1) { ND_PRINT((ndo, "%s > %s: ", udpport_string(sport), udpport_string(dport))); } } } else #endif /*INET6*/ { if (ip->ip_p == IPPROTO_UDP) { if (sport == -1) { ND_PRINT((ndo, "%s > %s: ", ipaddr_string(ndo, &ip->ip_src), ipaddr_string(ndo, &ip->ip_dst))); } else { ND_PRINT((ndo, "%s.%s > %s.%s: ", ipaddr_string(ndo, &ip->ip_src), udpport_string(sport), ipaddr_string(ndo, &ip->ip_dst), udpport_string(dport))); } } else { if (sport != -1) { ND_PRINT((ndo, "%s > %s: ", udpport_string(sport), udpport_string(dport))); } } } } void udp_print(netdissect_options *ndo, register const u_char *bp, u_int length, register const u_char *bp2, int fragmented) { register const struct udphdr *up; register const struct ip *ip; register const u_char *cp; register const u_char *ep = bp + length; uint16_t sport, dport, ulen; #ifdef INET6 register const struct ip6_hdr *ip6; #endif if (ep > ndo->ndo_snapend) ep = ndo->ndo_snapend; up = (struct udphdr *)bp; ip = (struct ip *)bp2; #ifdef INET6 if (IP_V(ip) == 6) ip6 = (struct ip6_hdr *)bp2; else ip6 = NULL; #endif /*INET6*/ - cp = (u_char *)(up + 1); if (!ND_TTEST(up->uh_dport)) { udpipaddr_print(ndo, ip, -1, -1); ND_PRINT((ndo, "[|udp]")); return; } sport = EXTRACT_16BITS(&up->uh_sport); dport = EXTRACT_16BITS(&up->uh_dport); if (length < sizeof(struct udphdr)) { udpipaddr_print(ndo, ip, sport, dport); ND_PRINT((ndo, "truncated-udp %d", length)); return; } + ulen = EXTRACT_16BITS(&up->uh_ulen); + if (ulen < sizeof(struct udphdr)) { + udpipaddr_print(ndo, ip, sport, dport); + ND_PRINT((ndo, "truncated-udplength %d", ulen)); + return; + } + ulen -= sizeof(struct udphdr); length -= sizeof(struct udphdr); + if (ulen < length) + length = ulen; + cp = (u_char *)(up + 1); if (cp > ndo->ndo_snapend) { udpipaddr_print(ndo, ip, sport, dport); ND_PRINT((ndo, "[|udp]")); return; } - ulen = EXTRACT_16BITS(&up->uh_ulen); - if (ulen < 8) { - udpipaddr_print(ndo, ip, sport, dport); - ND_PRINT((ndo, "truncated-udplength %d", ulen)); - return; - } if (ndo->ndo_packettype) { register 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, (void *)(up + 1), up); break; case PT_WB: udpipaddr_print(ndo, ip, sport, dport); wb_print(ndo, (void *)(up + 1), length); break; case PT_RPC: rp = (struct sunrpc_msg *)(up + 1); direction = (enum sunrpc_msg_type)EXTRACT_32BITS(&rp->rm_direction); if (direction == SUNRPC_CALL) sunrpcrequest_print(ndo, (u_char *)rp, length, (u_char *)ip); else nfsreply_print(ndo, (u_char *)rp, length, (u_char *)ip); /*XXX*/ break; case PT_RTP: udpipaddr_print(ndo, ip, sport, dport); rtp_print(ndo, (void *)(up + 1), length, up); 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, (const u_char *)(up + 1), length); break; case PT_CNFP: udpipaddr_print(ndo, ip, sport, dport); - cnfp_print(ndo, cp, (const u_char *)ip); + 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, (const u_char *)(up + 1), length, #ifdef INET6 ip6 != NULL); #else 0); #endif 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, (const u_char *)(up + 1), 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; } return; } udpipaddr_print(ndo, ip, sport, dport); if (!ndo->ndo_qflag) { register struct sunrpc_msg *rp; enum sunrpc_msg_type direction; rp = (struct sunrpc_msg *)(up + 1); if (ND_TTEST(rp->rm_direction)) { direction = (enum sunrpc_msg_type)EXTRACT_32BITS(&rp->rm_direction); if (dport == NFS_PORT && direction == SUNRPC_CALL) { ND_PRINT((ndo, "NFS request xid %u ", EXTRACT_32BITS(&rp->rm_xid))); nfsreq_print_noaddr(ndo, (u_char *)rp, length, (u_char *)ip); return; } if (sport == NFS_PORT && direction == SUNRPC_REPLY) { ND_PRINT((ndo, "NFS reply xid %u ", EXTRACT_32BITS(&rp->rm_xid))); nfsreply_print_noaddr(ndo, (u_char *)rp, length, (u_char *)ip); return; } #ifdef notdef if (dport == SUNRPC_PORT && direction == SUNRPC_CALL) { sunrpcrequest_print((u_char *)rp, length, (u_char *)ip); return; } #endif } if (ND_TTEST(((struct LAP *)cp)->type) && ((struct LAP *)cp)->type == lapDDP && (atalk_port(sport) || atalk_port(dport))) { if (ndo->ndo_vflag) ND_PRINT((ndo, "kip ")); llap_print(ndo, cp, length); return; } } 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 = EXTRACT_16BITS(&up->uh_sum); if (udp_sum == 0) { ND_PRINT((ndo, "[no cksum] ")); } else if (ND_TTEST2(cp[0], length)) { sum = udp_cksum(ndo, ip, up, length + sizeof(struct udphdr)); if (sum != 0) { ND_PRINT((ndo, "[bad udp cksum 0x%04x -> 0x%04x!] ", udp_sum, in_cksum_shouldbe(udp_sum, sum))); } else ND_PRINT((ndo, "[udp sum ok] ")); } } #ifdef INET6 else if (IP_V(ip) == 6 && ip6->ip6_plen) { /* for IPv6, UDP checksum is mandatory */ if (ND_TTEST2(cp[0], length)) { sum = udp6_cksum(ip6, up, length + sizeof(struct udphdr)); udp_sum = EXTRACT_16BITS(&up->uh_sum); if (sum != 0) { ND_PRINT((ndo, "[bad udp cksum 0x%04x -> 0x%04x!] ", udp_sum, in_cksum_shouldbe(udp_sum, sum))); } else ND_PRINT((ndo, "[udp sum ok] ")); } } #endif } if (!ndo->ndo_qflag) { #define ISPORT(p) (dport == (p) || sport == (p)) if (ISPORT(NAMESERVER_PORT)) ns_print(ndo, (const u_char *)(up + 1), length, 0); else if (ISPORT(MULTICASTDNS_PORT)) ns_print(ndo, (const u_char *)(up + 1), length, 1); else if (ISPORT(TIMED_PORT)) timed_print(ndo, (const u_char *)(up + 1)); else if (ISPORT(TFTP_PORT)) tftp_print(ndo, (const u_char *)(up + 1), length); - else if (ISPORT(IPPORT_BOOTPC) || ISPORT(IPPORT_BOOTPS)) + else if (ISPORT(BOOTPC_PORT) || ISPORT(BOOTPS_PORT)) bootp_print(ndo, (const u_char *)(up + 1), length); else if (ISPORT(RIP_PORT)) rip_print(ndo, (const u_char *)(up + 1), length); else if (ISPORT(AODV_PORT)) aodv_print(ndo, (const u_char *)(up + 1), length, #ifdef INET6 ip6 != NULL); #else 0); #endif else if (ISPORT(ISAKMP_PORT)) isakmp_print(ndo, (const u_char *)(up + 1), length, bp2); else if (ISPORT(ISAKMP_PORT_NATT)) isakmp_rfc3948_print(ndo, (const u_char *)(up + 1), length, bp2); #if 1 /*???*/ else if (ISPORT(ISAKMP_PORT_USER1) || ISPORT(ISAKMP_PORT_USER2)) isakmp_print(ndo, (const u_char *)(up + 1), length, bp2); #endif else if (ISPORT(SNMP_PORT) || ISPORT(SNMPTRAP_PORT)) snmp_print(ndo, (const u_char *)(up + 1), length); else if (ISPORT(NTP_PORT)) ntp_print(ndo, (const u_char *)(up + 1), length); else if (ISPORT(KERBEROS_PORT) || ISPORT(KERBEROS_SEC_PORT)) krb_print(ndo, (const void *)(up + 1)); else if (ISPORT(L2TP_PORT)) l2tp_print(ndo, (const u_char *)(up + 1), length); #ifdef TCPDUMP_DO_SMB else if (ISPORT(NETBIOS_NS_PORT)) nbt_udp137_print(ndo, (const u_char *)(up + 1), length); else if (ISPORT(NETBIOS_DGRAM_PORT)) nbt_udp138_print(ndo, (const u_char *)(up + 1), length); #endif else if (dport == VAT_PORT) vat_print(ndo, (const void *)(up + 1), up); else if (ISPORT(ZEPHYR_SRV_PORT) || ISPORT(ZEPHYR_CLT_PORT)) zephyr_print(ndo, (const void *)(up + 1), 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, (const void *)(up + 1), length, sport, dport, (u_char *) ip); #ifdef INET6 else if (ISPORT(RIPNG_PORT)) ripng_print(ndo, (const u_char *)(up + 1), length); else if (ISPORT(DHCP6_SERV_PORT) || ISPORT(DHCP6_CLI_PORT)) dhcp6_print(ndo, (const u_char *)(up + 1), length); else if (ISPORT(AHCP_PORT)) ahcp_print(ndo, (const u_char *)(up + 1), length); else if (ISPORT(BABEL_PORT) || ISPORT(BABEL_PORT_OLD)) babel_print(ndo, (const u_char *)(up + 1), length); #endif /*INET6*/ /* * Kludge in test for whiteboard packets. */ else if (dport == WB_PORT) wb_print(ndo, (const void *)(up + 1), length); else if (ISPORT(CISCO_AUTORP_PORT)) cisco_autorp_print(ndo, (const void *)(up + 1), length); else if (ISPORT(RADIUS_PORT) || ISPORT(RADIUS_NEW_PORT) || ISPORT(RADIUS_ACCOUNTING_PORT) || - ISPORT(RADIUS_NEW_ACCOUNTING_PORT) ) + ISPORT(RADIUS_NEW_ACCOUNTING_PORT) || + ISPORT(RADIUS_COA_PORT) ) radius_print(ndo, (const u_char *)(up+1), length); else if (dport == HSRP_PORT) hsrp_print(ndo, (const u_char *)(up + 1), length); else if (ISPORT(LWRES_PORT)) lwres_print(ndo, (const u_char *)(up + 1), length); else if (ISPORT(LDP_PORT)) ldp_print(ndo, (const u_char *)(up + 1), length); else if (ISPORT(OLSR_PORT)) olsr_print(ndo, (const u_char *)(up + 1), length, #if INET6 (IP_V(ip) == 6) ? 1 : 0); #else 0); #endif else if (ISPORT(MPLS_LSP_PING_PORT)) lspping_print(ndo, (const u_char *)(up + 1), length); else if (dport == BFD_CONTROL_PORT || dport == BFD_ECHO_PORT ) bfd_print(ndo, (const u_char *)(up+1), length, dport); else if (ISPORT(LMP_PORT)) lmp_print(ndo, (const u_char *)(up + 1), length); else if (ISPORT(VQP_PORT)) vqp_print(ndo, (const u_char *)(up + 1), length); else if (ISPORT(SFLOW_PORT)) sflow_print(ndo, (const u_char *)(up + 1), length); else if (dport == LWAPP_CONTROL_PORT) lwapp_control_print(ndo, (const u_char *)(up + 1), length, 1); else if (sport == LWAPP_CONTROL_PORT) lwapp_control_print(ndo, (const u_char *)(up + 1), length, 0); else if (ISPORT(LWAPP_DATA_PORT)) lwapp_data_print(ndo, (const u_char *)(up + 1), length); else if (ISPORT(SIP_PORT)) sip_print(ndo, (const u_char *)(up + 1), length); else if (ISPORT(SYSLOG_PORT)) syslog_print(ndo, (const u_char *)(up + 1), length); else if (ISPORT(OTV_PORT)) otv_print(ndo, (const u_char *)(up + 1), length); else if (ISPORT(VXLAN_PORT)) vxlan_print(ndo, (const u_char *)(up + 1), length); - else - ND_PRINT((ndo, "UDP, length %u", - (uint32_t)(ulen - sizeof(*up)))); + else if (ISPORT(GENEVE_PORT)) + geneve_print(ndo, (const u_char *)(up + 1), length); + else { + if (ulen > length) + ND_PRINT((ndo, "UDP, bad length %u > %u", + ulen, length)); + else + ND_PRINT((ndo, "UDP, length %u", ulen)); + } #undef ISPORT - } else - ND_PRINT((ndo, "UDP, length %u", (uint32_t)(ulen - sizeof(*up)))); + } else { + if (ulen > length) + ND_PRINT((ndo, "UDP, bad length %u > %u", + ulen, length)); + else + ND_PRINT((ndo, "UDP, length %u", ulen)); + } } /* * Local Variables: * c-style: whitesmith * c-basic-offset: 8 * End: */ Index: head/contrib/tcpdump/print-vxlan.c =================================================================== --- head/contrib/tcpdump/print-vxlan.c (revision 285274) +++ head/contrib/tcpdump/print-vxlan.c (revision 285275) @@ -1,60 +1,62 @@ /* * 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) */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "interface.h" #include "extract.h" /* - * VXLAN header, draft-mahalingam-dutt-dcops-vxlan-03 + * 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; if (len < 8) { ND_PRINT((ndo, "[|VXLAN]")); return; } flags = *bp; bp += 4; vni = EXTRACT_24BITS(bp); bp += 4; ND_PRINT((ndo, "VXLAN, ")); ND_PRINT((ndo, "flags [%s] (0x%02x), ", flags & 0x08 ? "I" : ".", flags)); ND_PRINT((ndo, "vni %u\n", vni)); ether_print(ndo, bp, len - 8, len - 8, NULL, NULL); } Index: head/contrib/tcpdump/print-wb.c =================================================================== --- head/contrib/tcpdump/print-wb.c (revision 285274) +++ head/contrib/tcpdump/print-wb.c (revision 285275) @@ -1,448 +1,452 @@ /* * 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. */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "interface.h" #include "addrtoname.h" #include "extract.h" static const char tstr[] = "[|wb]"; /* XXX need to add byte-swapping macros! */ /* XXX - you mean like the ones in "extract.h"? */ /* * Largest packet size. Everything should fit within this space. * For instance, multiline objects are sent piecewise. */ #define MAXFRAMESIZE 1024 /* * 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) ((((int)(x)) + (DOP_ALIGN - 1)) & ~(DOP_ALIGN - 1)) #define DOP_NEXT(d)\ ((struct dophdr *)((u_char *)(d) + \ DOP_ROUNDUP(EXTRACT_16BITS(&(d)->dh_len) + sizeof(*(d))))) /* * Format of the whiteboard packet header. * The transport level header. */ struct pkt_hdr { uint32_t ph_src; /* site id of source */ uint32_t ph_ts; /* time stamp (for skew computation) */ uint16_t ph_version; /* version number */ u_char ph_type; /* message type */ u_char 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 */ #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 */ struct PageID { uint32_t p_sid; /* session id of initiator */ uint32_t p_uid; /* page number */ }; struct dophdr { uint32_t dh_ts; /* sender's timestamp */ uint16_t dh_len; /* body length */ u_char dh_flags; u_char 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 #define DT_MAXTYPE 15 /* * A drawing operation. */ struct pkt_dop { struct PageID pd_page; /* page that operations apply to */ uint32_t pd_sseq; /* start sequence number */ uint32_t pd_eseq; /* end sequence number */ /* drawing ops follow */ }; /* * A repair request. */ struct pkt_rreq { uint32_t pr_id; /* source id of drawops to be repaired */ struct PageID pr_page; /* page of drawops */ uint32_t pr_sseq; /* start seqno */ uint32_t pr_eseq; /* end seqno */ }; /* * A repair reply. */ struct pkt_rrep { uint32_t pr_id; /* original site id of ops */ struct pkt_dop pr_dop; /* drawing ops follow */ }; struct id_off { uint32_t id; uint32_t off; }; struct pgstate { uint32_t slot; struct PageID page; uint16_t nid; uint16_t rsvd; /* seqptr's */ }; /* * An announcement packet. */ struct pkt_id { 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; uint32_t pp_low; uint32_t pp_high; }; struct pkt_prep { 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) { int i; const char *cp; const struct id_off *io; char c; int nid; ND_PRINT((ndo, " wb-id:")); - if (len < sizeof(*id) || (u_char *)(id + 1) > ndo->ndo_snapend) + if (len < sizeof(*id) || !ND_TTEST(*id)) return (-1); len -= sizeof(*id); ND_PRINT((ndo, " %u/%s:%u (max %u/%s:%u) ", EXTRACT_32BITS(&id->pi_ps.slot), ipaddr_string(ndo, &id->pi_ps.page.p_sid), EXTRACT_32BITS(&id->pi_ps.page.p_uid), EXTRACT_32BITS(&id->pi_mslot), ipaddr_string(ndo, &id->pi_mpage.p_sid), EXTRACT_32BITS(&id->pi_mpage.p_uid))); nid = EXTRACT_16BITS(&id->pi_ps.nid); len -= sizeof(*io) * nid; io = (struct id_off *)(id + 1); cp = (char *)(io + nid); - if ((u_char *)cp + len <= ndo->ndo_snapend) { + if (ND_TTEST2(cp, len)) { ND_PRINT((ndo, "\"")); fn_print(ndo, (u_char *)cp, (u_char *)cp + len); ND_PRINT((ndo, "\"")); } c = '<'; - for (i = 0; i < nid && (u_char *)(io + 1) <= ndo->ndo_snapend; ++io, ++i) { + for (i = 0; i < nid && ND_TTEST(*io); ++io, ++i) { ND_PRINT((ndo, "%c%s:%u", c, ipaddr_string(ndo, &io->id), EXTRACT_32BITS(&io->off))); c = ','; } if (i >= nid) { ND_PRINT((ndo, ">")); return (0); } return (-1); } static int wb_rreq(netdissect_options *ndo, const struct pkt_rreq *rreq, u_int len) { ND_PRINT((ndo, " wb-rreq:")); - if (len < sizeof(*rreq) || (u_char *)(rreq + 1) > ndo->ndo_snapend) + if (len < sizeof(*rreq) || !ND_TTEST(*rreq)) return (-1); ND_PRINT((ndo, " please repair %s %s:%u<%u:%u>", ipaddr_string(ndo, &rreq->pr_id), ipaddr_string(ndo, &rreq->pr_page.p_sid), EXTRACT_32BITS(&rreq->pr_page.p_uid), EXTRACT_32BITS(&rreq->pr_sseq), EXTRACT_32BITS(&rreq->pr_eseq))); return (0); } static int wb_preq(netdissect_options *ndo, const struct pkt_preq *preq, u_int len) { ND_PRINT((ndo, " wb-preq:")); - if (len < sizeof(*preq) || (u_char *)(preq + 1) > ndo->ndo_snapend) + if (len < sizeof(*preq) || !ND_TTEST(*preq)) return (-1); ND_PRINT((ndo, " need %u/%s:%u", EXTRACT_32BITS(&preq->pp_low), ipaddr_string(ndo, &preq->pp_page.p_sid), EXTRACT_32BITS(&preq->pp_page.p_uid))); return (0); } static int wb_prep(netdissect_options *ndo, const struct pkt_prep *prep, u_int len) { int n; const struct pgstate *ps; const u_char *ep = ndo->ndo_snapend; ND_PRINT((ndo, " wb-prep:")); if (len < sizeof(*prep)) { return (-1); } n = EXTRACT_32BITS(&prep->pp_n); ps = (const struct pgstate *)(prep + 1); - while (--n >= 0 && (u_char *)(ps + 1) <= ep) { + while (--n >= 0 && ND_TTEST(*ps)) { const struct id_off *io, *ie; char c = '<'; ND_PRINT((ndo, " %u/%s:%u", EXTRACT_32BITS(&ps->slot), ipaddr_string(ndo, &ps->page.p_sid), EXTRACT_32BITS(&ps->page.p_uid))); io = (struct id_off *)(ps + 1); - for (ie = io + ps->nid; io < ie && (u_char *)(io + 1) <= ep; ++io) { + for (ie = io + ps->nid; io < ie && ND_TTEST(*io); ++io) { ND_PRINT((ndo, "%c%s:%u", c, ipaddr_string(ndo, &io->id), EXTRACT_32BITS(&io->off))); c = ','; } ND_PRINT((ndo, ">")); ps = (struct pgstate *)io; } return ((u_char *)ps <= ep? 0 : -1); } static const char *dopstr[] = { "dop-0!", "dop-1!", "RECT", "LINE", "ML", "DEL", "XFORM", "ELL", "CHAR", "STR", "NOP", "PSCODE", "PSCOMP", "REF", "SKIP", "HOLE", }; static int -wb_dops(netdissect_options *ndo, - const struct dophdr *dh, uint32_t ss, uint32_t es) +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((ndo, " <")); for ( ; ss <= es; ++ss) { - register int t = dh->dh_type; + int t; + if (!ND_TTEST(*dh)) { + ND_PRINT((ndo, "%s", tstr)); + break; + } + t = dh->dh_type; + if (t > DT_MAXTYPE) ND_PRINT((ndo, " dop-%d!", t)); else { ND_PRINT((ndo, " %s", dopstr[t])); if (t == DT_SKIP || t == DT_HOLE) { uint32_t ts = EXTRACT_32BITS(&dh->dh_ts); ND_PRINT((ndo, "%d", ts - ss + 1)); if (ss > ts || ts > es) { ND_PRINT((ndo, "[|]")); if (ts < ss) return (0); } ss = ts; } } dh = DOP_NEXT(dh); - if ((u_char *)dh > ndo->ndo_snapend) { - ND_PRINT((ndo, "%s", tstr)); - break; - } } ND_PRINT((ndo, " >")); return (0); } 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((ndo, " wb-rrep:")); - if (len < sizeof(*rrep) || (u_char *)(rrep + 1) > ndo->ndo_snapend) + if (len < sizeof(*rrep) || !ND_TTEST(*rrep)) return (-1); len -= sizeof(*rrep); ND_PRINT((ndo, " for %s %s:%u<%u:%u>", ipaddr_string(ndo, &rrep->pr_id), ipaddr_string(ndo, &dop->pd_page.p_sid), EXTRACT_32BITS(&dop->pd_page.p_uid), EXTRACT_32BITS(&dop->pd_sseq), EXTRACT_32BITS(&dop->pd_eseq))); if (ndo->ndo_vflag) - return (wb_dops(ndo, (const struct dophdr *)(dop + 1), + return (wb_dops(ndo, dop, EXTRACT_32BITS(&dop->pd_sseq), EXTRACT_32BITS(&dop->pd_eseq))); return (0); } static int wb_drawop(netdissect_options *ndo, const struct pkt_dop *dop, u_int len) { ND_PRINT((ndo, " wb-dop:")); - if (len < sizeof(*dop) || (u_char *)(dop + 1) > ndo->ndo_snapend) + if (len < sizeof(*dop) || !ND_TTEST(*dop)) return (-1); len -= sizeof(*dop); ND_PRINT((ndo, " %s:%u<%u:%u>", ipaddr_string(ndo, &dop->pd_page.p_sid), EXTRACT_32BITS(&dop->pd_page.p_uid), EXTRACT_32BITS(&dop->pd_sseq), EXTRACT_32BITS(&dop->pd_eseq))); if (ndo->ndo_vflag) - return (wb_dops(ndo, (const struct dophdr *)(dop + 1), + return (wb_dops(ndo, dop, EXTRACT_32BITS(&dop->pd_sseq), EXTRACT_32BITS(&dop->pd_eseq))); return (0); } /* * Print whiteboard multicast packets. */ void wb_print(netdissect_options *ndo, register const void *hdr, register u_int len) { register const struct pkt_hdr *ph; ph = (const struct pkt_hdr *)hdr; - if (len < sizeof(*ph) || (u_char *)(ph + 1) > ndo->ndo_snapend) { + if (len < sizeof(*ph) || !ND_TTEST(*ph)) { ND_PRINT((ndo, "%s", tstr)); return; } len -= sizeof(*ph); if (ph->ph_flags) ND_PRINT((ndo, "*")); switch (ph->ph_type) { case PT_KILL: ND_PRINT((ndo, " wb-kill")); return; case PT_ID: if (wb_id(ndo, (struct pkt_id *)(ph + 1), len) >= 0) return; break; case PT_RREQ: if (wb_rreq(ndo, (struct pkt_rreq *)(ph + 1), len) >= 0) return; break; case PT_RREP: if (wb_rrep(ndo, (struct pkt_rrep *)(ph + 1), len) >= 0) return; break; case PT_DRAWOP: if (wb_drawop(ndo, (struct pkt_dop *)(ph + 1), len) >= 0) return; break; case PT_PREQ: if (wb_preq(ndo, (struct pkt_preq *)(ph + 1), len) >= 0) return; break; case PT_PREP: if (wb_prep(ndo, (struct pkt_prep *)(ph + 1), len) >= 0) return; break; default: ND_PRINT((ndo, " wb-%d!", ph->ph_type)); return; } } Index: head/contrib/tcpdump/print-zeromq.c =================================================================== --- head/contrib/tcpdump/print-zeromq.c (revision 285274) +++ head/contrib/tcpdump/print-zeromq.c (revision 285275) @@ -1,215 +1,219 @@ /* * This file implements decoding of ZeroMQ network protocol(s). * * * 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. */ #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "interface.h" #include "extract.h" static const char tstr[] = " [|zmtp1]"; /* 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 /* * 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) { +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((ndo, "\n\t")); ND_TCHECK2(*cp, 1); /* length/0xFF */ if (cp[0] != 0xFF) { header_len = 1; /* length */ body_len_declared = cp[0]; if (body_len_declared == 0) return cp + header_len; /* skip to next frame */ ND_PRINT((ndo, " frame flags+body (8-bit) length %u", cp[0])); ND_TCHECK2(*cp, header_len + 1); /* length, flags */ flags = cp[1]; } else { header_len = 1 + 8; /* 0xFF, length */ ND_PRINT((ndo, " frame flags+body (64-bit) length")); ND_TCHECK2(*cp, header_len); /* 0xFF, length */ body_len_declared = EXTRACT_64BITS(cp + 1); if (body_len_declared == 0) return cp + header_len; /* skip to next frame */ ND_PRINT((ndo, " %" PRIu64, body_len_declared)); ND_TCHECK2(*cp, header_len + 1); /* 0xFF, length, flags */ flags = cp[9]; } body_len_captured = ep - cp - header_len; if (body_len_declared > body_len_captured) ND_PRINT((ndo, " (%" PRIu64 " captured)", body_len_captured)); ND_PRINT((ndo, ", flags 0x%02x", flags)); if (ndo->ndo_vflag) { uint64_t body_len_printed = min(body_len_captured, body_len_declared); ND_PRINT((ndo, " (%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" : "-")); if (ndo->ndo_vflag == 1) body_len_printed = min(VBYTES + 1, body_len_printed); if (body_len_printed > 1) { ND_PRINT((ndo, ", 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); ND_PRINT((ndo, "\n")); } } ND_TCHECK2(*cp, header_len + body_len_declared); /* Next frame within the buffer ? */ return cp + header_len + body_len_declared; trunc: ND_PRINT((ndo, "%s", tstr)); return ep; } void -zmtp1_print(netdissect_options *ndo, const u_char *cp, u_int len) { +zmtp1_print(netdissect_options *ndo, const u_char *cp, u_int len) +{ const u_char *ep = min(ndo->ndo_snapend, cp + len); ND_PRINT((ndo, ": 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) { +zmtp1_print_intermediate_part(netdissect_options *ndo, const u_char *cp, const u_int len) +{ u_int frame_offset; uint64_t remaining_len; ND_TCHECK2(*cp, 2); frame_offset = EXTRACT_16BITS(cp); ND_PRINT((ndo, "\n\t frame offset 0x%04x", frame_offset)); cp += 2; remaining_len = ndo->ndo_snapend - 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((ndo, " (exceeds datagram declared length)")); goto trunc; } /* offset within declared length of the datagram */ if (frame_offset) { ND_PRINT((ndo, "\n\t frame intermediate part, %u bytes", frame_offset)); if (frame_offset > remaining_len) ND_PRINT((ndo, " (%"PRIu64" captured)", remaining_len)); if (ndo->ndo_vflag) { uint64_t len_printed = min(frame_offset, remaining_len); if (ndo->ndo_vflag == 1) len_printed = min(VBYTES, len_printed); if (len_printed > 1) { ND_PRINT((ndo, ", first %"PRIu64" byte(s):", len_printed)); hex_and_ascii_print(ndo, "\n\t ", cp, len_printed); ND_PRINT((ndo, "\n")); } } } return cp + frame_offset; trunc: ND_PRINT((ndo, "%s", tstr)); return cp + len; } void -zmtp1_print_datagram(netdissect_options *ndo, const u_char *cp, const u_int len) { +zmtp1_print_datagram(netdissect_options *ndo, const u_char *cp, const u_int len) +{ const u_char *ep = min(ndo->ndo_snapend, cp + len); cp = zmtp1_print_intermediate_part(ndo, cp, len); while (cp < ep) cp = zmtp1_print_frame(ndo, cp, ep); } Index: head/contrib/tcpdump/tcp.h =================================================================== --- head/contrib/tcpdump/tcp.h (revision 285274) +++ head/contrib/tcpdump/tcp.h (revision 285275) @@ -1,118 +1,136 @@ /* * 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 */ typedef uint32_t tcp_seq; /* * TCP header. * Per RFC 793, September, 1981. */ struct tcphdr { uint16_t th_sport; /* source port */ uint16_t th_dport; /* destination port */ tcp_seq th_seq; /* sequence number */ tcp_seq th_ack; /* acknowledgement number */ uint8_t th_offx2; /* data offset, rsvd */ uint8_t th_flags; uint16_t th_win; /* window */ uint16_t th_sum; /* checksum */ uint16_t th_urp; /* urgent pointer */ } UNALIGNED; #define TH_OFF(th) (((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_AUTH 20 /* Enhanced AUTH option */ #define TCPOPT_UTO 28 /* tcp user timeout (rfc5482) */ #define TCPOLEN_UTO 4 #define TCPOPT_MPTCP 30 /* MPTCP options */ #define TCPOPT_EXPERIMENT2 254 /* experimental headers (rfc4727) */ #define TCPOPT_TSTAMP_HDR \ (TCPOPT_NOP<<24|TCPOPT_NOP<<16|TCPOPT_TIMESTAMP<<8|TCPOLEN_TIMESTAMP) #ifndef TELNET_PORT #define TELNET_PORT 23 #endif +#ifndef SMTP_PORT +#define SMTP_PORT 25 +#endif #ifndef BGP_PORT #define BGP_PORT 179 #endif #define NETBIOS_SSN_PORT 139 #ifndef OPENFLOW_PORT_OLD #define OPENFLOW_PORT_OLD 6633 #endif #ifndef OPENFLOW_PORT_IANA #define OPENFLOW_PORT_IANA 6653 #endif #ifndef PPTP_PORT #define PPTP_PORT 1723 #endif #define BEEP_PORT 10288 #ifndef NFS_PORT #define NFS_PORT 2049 #endif #define MSDP_PORT 639 #define RPKI_RTR_PORT 323 #define LDP_PORT 646 #ifndef SMB_PORT #define SMB_PORT 445 +#endif +#ifndef HTTP_PORT +#define HTTP_PORT 80 +#endif +#ifndef HTTP_PORT_ALT +#define HTTP_PORT_ALT 8080 +#endif +#ifndef RTSP_PORT +#define RTSP_PORT 554 +#endif +#ifndef RTSP_PORT_ALT +#define RTSP_PORT_ALT 8554 +#endif +#ifndef FTP_PORT +#define FTP_PORT 21 #endif Index: head/contrib/tcpdump/tcpdump.1.in =================================================================== --- head/contrib/tcpdump/tcpdump.1.in (revision 285274) +++ head/contrib/tcpdump/tcpdump.1.in (revision 285275) @@ -1,1959 +1,1976 @@ .\" $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 "11 July 2014" .SH NAME tcpdump \- dump traffic on a network .SH SYNOPSIS .na .B tcpdump [ .B \-AbdDefhHIJKlLnNOpqRStuUvxX# ] [ .B \-B .I buffer_size ] .br .ti +8 [ .B \-c .I count ] .br .ti +8 [ .B \-C .I file_size ] [ .B \-G .I rotate_seconds ] [ .B \-F .I file ] .br .ti +8 [ .B \-i .I interface ] [ .B \-j .I tstamp_type ] [ .B \-m .I module ] [ .B \-M .I secret ] .br .ti +8 [ .B \-\-number ] [ .B \-Q .I in|out|inout ] .ti +8 [ .B \-r .I file ] [ .B \-V .I file ] [ .B \-s .I snaplen ] [ .B \-T .I type ] [ .B \-w .I file ] .br .ti +8 [ .B \-W .I filecount ] .br .ti +8 [ .B \-E .I spi@ipaddr algo:secret,... ] .br .ti +8 [ .B \-y .I datalinktype ] [ .B \-z .I postrotate-command ] [ .B \-Z .I user ] .ti +8 [ .BI \-\-time\-stamp\-precision= tstamp_precision ] +.ti +8 [ +.B \-\-immediate\-mode +] +[ .B \-\-version ] .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. It can also +network interface that match the boolean \fIexpression\fP; 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 Mac OS X) 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 Mac OS X, 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. +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 Reading packets from a network interface may require that you have special privileges; see the .B 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 \-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. .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, is 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 .B pcap_findalldevs() 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 RFC2406 ESP, not RFC1827 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 which capture is being done. If that address or netmask are not available, available, either because the interface on which capture is being done has no address or netmask or because the capture is being done on the Linux "any" interface, 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. .IP If used in conjunction with the .B \-C option, filenames will take the form of `\fIfile\fP'. .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 on \fIinterface\fP. If unspecified, \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, an .I interface argument of ``any'' can be used to capture packets from all interfaces. Note that captures on the ``any'' device 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. .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. .LP 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. .LP 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 \-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. .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 \-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 .B \-R Assume ESP/AH packets to be based on old specification (RFC1825 to RFC1829). If specified, \fItcpdump\fP will not print replay prevention field. Since there is no protocol version field in ESP/AH specification, \fItcpdump\fP cannot deduce the version of ESP/AH protocol. .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 pcap-ng 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 65535 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. 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. 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 65535, 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), \fBlmp\fR (Link Management Protocol), \fBpgm\fR (Pragmatic General Multicast), \fBpgm_zmtp1\fR (ZMTP/1.0 inside PGM/EPGM), \fBradius\fR (RADIUS), \fBrpc\fR (Remote Procedure Call), \fBrtp\fR (Real-Time Applications protocol), \fBrtcp\fR (Real-Time Applications control protocol), \fBsnmp\fR (Simple Network Management Protocol), \fBtftp\fR (Trivial File Transfer Protocol), \fBvat\fR (Visual Audio Tool), \fBwb\fR (distributed White Board), \fBzmtp1\fR (ZeroMQ Message Transport Protocol 1.0) and \fBvxlan\fR (Virtual eXtensible Local Area Network). .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 an unformatted timestamp on each dump line. +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 (micro-second resolution) between current and previous line on each dump line. .TP .B \-tttt -Print a timestamp in default format proceeded by date on each dump line. +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 (micro-second resolution) between current and first line on each dump line. .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, 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 .B pcap_dump_flush() 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, report, every 10 seconds, the number of packets captured. .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 .B \-W 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. If used with .B \-C as well, the behavior will result in cyclical files per timeslice. .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. .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. .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 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 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 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 .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 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, neither this description nor \fItcpdump\fP will be of much use to you.)\fP .LP The general format of a tcp protocol line is: .RS .nf .sp .5 \fIsrc > dst: flags data-seqno ack window urgent options\fP .sp .5 .fi .RE \fISrc\fP and \fIdst\fP are the source and destination IP addresses and ports. \fIFlags\fP are some combination of S (SYN), F (FIN), P (PUSH), R (RST), U (URG), W (ECN CWR), E (ECN-Echo) 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). \fIAck\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. \fIOptions\fP are tcp options enclosed in angle brackets (e.g., ). .LP \fISrc, dst\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 \s-2\f(CWrtsg.1023 > csam.login: S 768512:768512(0) win 4096 csam.login > rtsg.1023: S 947648:947648(0) ack 768513 win 4096 rtsg.1023 > csam.login: . ack 1 win 4096 rtsg.1023 > csam.login: P 1:2(1) ack 1 win 4096 csam.login > rtsg.1023: . ack 2 win 4096 rtsg.1023 > csam.login: P 2:21(19) ack 1 win 4096 csam.login > rtsg.1023: P 1:2(1) ack 21 win 4077 csam.login > rtsg.1023: P 2:3(1) ack 21 win 4077 urg 1 csam.login > rtsg.1023: P 3:4(1) ack 21 win 4077 urg 1\fR\s+2 .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(nbytes)' which means `sequence numbers \fIfirst\fP up to but not including \fIlast\fP which is \fInbytes\fP bytes of user data'.) 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. 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 PUSH 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.) .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 .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-act, tcp-urg. .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 .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 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, not including the 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 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 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, 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 .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 www.cifs.org or the pub/samba/specs/ directory on your favorite samba.org mirror site. The SMB patches were written by Andrew Tridgell (tridge@samba.org). .HD 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 Note that NFS requests are very large and much of the detail won't be printed unless \fIsnaplen\fP is increased. Try using `\fB\-s 192\fP' to watch NFS traffic. .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 .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 Note that AFS requests are very large and many of the arguments won't be printed unless \fIsnaplen\fP is increased. Try using `\fB-s 256\fP' to watch AFS traffic. .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) .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: .RS .nf .sp .5 \s-2\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\s+2 .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: .RS .nf .sp .5 \s-2\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\s+2 .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. .HD IP Fragmentation .LP Fragmented Internet datagrams are printed as .RS .nf .sp .5 \fB(frag \fIid\fB:\fIsize\fB@\fIoffset\fB+)\fR \fB(frag \fIid\fB:\fIsize\fB@\fIoffset\fB)\fR .sp .5 .fi .RE (The first form indicates there are more fragments. The second indicates this is the last fragment.) .LP \fIId\fP is the fragment id. \fISize\fP is the fragment size (in bytes) excluding the IP header. \fIOffset\fP is this fragment's offset (in bytes) in the original datagram. .LP The fragment information is output for each fragment. The first fragment contains the higher level protocol header and the frag info is printed after the protocol info. Fragments after the first contain no higher level protocol header and the frag info is printed after the source and destination addresses. For example, here is part of an ftp from arizona.edu to lbl-rtsg.arpa over a CSNET connection that doesn't appear to handle 576 byte datagrams: .RS .nf .sp .5 \s-2\f(CWarizona.ftp-data > rtsg.1170: . 1024:1332(308) ack 1 win 4096 (frag 595a:328@0+) arizona > rtsg: (frag 595a:204@328) rtsg.1170 > arizona.ftp-data: . ack 1536 win 2560\fP\s+2 .sp .5 .fi .RE There are a couple of things to note here: First, addresses in the 2nd line don't include port numbers. This is because the TCP protocol information is all in the first fragment and we have no idea what the port or sequence numbers are when we print the later fragments. Second, the tcp sequence information in the first line is printed as if there were 308 bytes of user data when, in fact, there are 512 bytes (308 in the first frag and 204 in the second). If you are looking for holes in the sequence space or trying to match up acks with packets, this can fool you. .LP A packet with the IP \fIdon't fragment\fP flag is marked with a trailing \fB(DF)\fP. .HD 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 first saw the packet. No attempt is made to account for the time lag between when the Ethernet interface removed the packet from the wire and when the kernel serviced the `new packet' interrupt. .SH "SEE ALSO" stty(1), pcap(3PCAP), bpf(4), nit(4P), pcap-savefile(@MAN_FILE_FORMATS@), pcap-filter(@MAN_MISC_INFO@), pcap-tstamp(@MAN_MISC_INFO@) .LP .RS .I http://www.iana.org/assignments/media-types/application/vnd.tcpdump.pcap .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 being maintained by tcpdump.org. .LP The current version is available via http: .LP .RS .I http://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 Eric Young's SSLeay library, under specific configurations. .SH BUGS Please send problems, bugs, questions, desirable enhancements, patches etc. to: .LP .RS tcpdump-workers@lists.tcpdump.org .RE .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 userland, 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. Index: head/contrib/tcpdump/tcpdump.c =================================================================== --- head/contrib/tcpdump/tcpdump.c (revision 285274) +++ head/contrib/tcpdump/tcpdump.c (revision 285275) @@ -1,2641 +1,2809 @@ /* * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * Support for splitting captures into multiple files with a maximum * file size: * * Copyright (c) 2001 * Seth Webster */ #ifndef lint static const char copyright[] _U_ = "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* $FreeBSD$ */ /* * tcpdump - monitor tcp/ip traffic on an ethernet. * * First written in 1987 by Van Jacobson, Lawrence Berkeley Laboratory. * Mercilessly hacked and occasionally improved since then via the * combined efforts of Van, Steve McCanne and Craig Leres of LBL. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif +/* + * Mac OS X may ship pcap.h from libpcap 0.6 with a libpcap based on + * 0.8. That means it has pcap_findalldevs() but the header doesn't + * define pcap_if_t, meaning that we can't actually *use* pcap_findalldevs(). + */ +#ifdef HAVE_PCAP_FINDALLDEVS +#ifndef HAVE_PCAP_IF_T +#undef HAVE_PCAP_FINDALLDEVS +#endif +#endif + #include #ifdef WIN32 #include "w32_fzs.h" extern int strcasecmp (const char *__s1, const char *__s2); extern int SIZE_BUF; #define off_t long #define uint UINT #endif /* WIN32 */ #ifdef USE_LIBSMI #include #endif #ifdef HAVE_LIBCRYPTO #include #endif #ifdef HAVE_GETOPT_LONG #include #else #include "getopt_long.h" #endif -#include -#include -#include -#include -#include -#include +/* Capsicum-specific code requires macros from , which will fail + * to compile if has already been included; including the headers + * in the opposite order works fine. + */ #ifdef __FreeBSD__ #include #include #endif /* __FreeBSD__ */ #ifdef HAVE_CAPSICUM #include #include #include #include #include #include #include #include #include #endif /* HAVE_CAPSICUM */ +#include +#include +#include +#include +#include +#include #ifndef WIN32 #include #include #include #include #endif /* WIN32 */ -/* capabilities convinience library */ +/* capabilities convenience library */ +/* If a code depends on HAVE_LIBCAP_NG, it depends also on HAVE_CAP_NG_H. + * If HAVE_CAP_NG_H is not defined, undefine HAVE_LIBCAP_NG. + * Thus, the later tests are done only on HAVE_LIBCAP_NG. + */ +#ifdef HAVE_LIBCAP_NG #ifdef HAVE_CAP_NG_H #include +#else +#undef HAVE_LIBCAP_NG #endif /* HAVE_CAP_NG_H */ +#endif /* HAVE_LIBCAP_NG */ #include "netdissect.h" #include "interface.h" #include "addrtoname.h" #include "machdep.h" #include "setsignal.h" #include "gmt2local.h" #include "pcap-missing.h" #ifndef PATH_MAX #define PATH_MAX 1024 #endif #ifdef SIGINFO #define SIGNAL_REQ_INFO SIGINFO #elif SIGUSR1 #define SIGNAL_REQ_INFO SIGUSR1 #endif netdissect_options Gndo; netdissect_options *gndo = &Gndo; static int Dflag; /* list available devices and exit */ static int dflag; /* print filter code */ static int Lflag; /* list available data link types and exit */ #ifdef HAVE_PCAP_SET_TSTAMP_TYPE static int Jflag; /* list available time stamp types */ #endif #ifdef HAVE_PCAP_SETDIRECTION int Qflag = -1; /* restrict captured packet by send/receive direction */ #endif static char *zflag = NULL; /* compress each savefile using a specified command (like gzip or bzip2) */ static int infodelay; static int infoprint; char *program_name; #ifdef HAVE_CAPSICUM cap_channel_t *capdns; #endif int32_t thiszone; /* seconds offset from gmt to local time */ /* Forwards */ static RETSIGTYPE cleanup(int); static RETSIGTYPE child_cleanup(int); static void print_version(void); static void print_usage(void); static void show_dlts_and_exit(const char *device, pcap_t *pd) __attribute__((noreturn)); static void print_packet(u_char *, const struct pcap_pkthdr *, const u_char *); static void ndo_default_print(netdissect_options *, const u_char *, u_int); static void dump_packet_and_trunc(u_char *, const struct pcap_pkthdr *, const u_char *); static void dump_packet(u_char *, const struct pcap_pkthdr *, const u_char *); static void droproot(const char *, const char *); static void ndo_error(netdissect_options *ndo, const char *fmt, ...) __attribute__((noreturn)) #ifdef __ATTRIBUTE___FORMAT_OK __attribute__((format (printf, 2, 3))) #endif /* __ATTRIBUTE___FORMAT_OK */ ; static void ndo_warning(netdissect_options *ndo, const char *fmt, ...) #ifdef __ATTRIBUTE___FORMAT_OK __attribute__((format (printf, 2, 3))) #endif /* __ATTRIBUTE___FORMAT_OK */ ; #ifdef SIGNAL_REQ_INFO RETSIGTYPE requestinfo(int); #endif #if defined(USE_WIN32_MM_TIMER) #include static UINT timer_id; static void CALLBACK verbose_stats_dump(UINT, UINT, DWORD_PTR, DWORD_PTR, DWORD_PTR); #elif defined(HAVE_ALARM) static void verbose_stats_dump(int sig); #endif static void info(int); static u_int packets_captured; struct printer { if_printer f; int type; }; struct ndo_printer { if_ndo_printer f; int type; }; static const struct printer printers[] = { { NULL, 0 }, }; static const struct ndo_printer ndo_printers[] = { { ether_if_print, DLT_EN10MB }, #ifdef DLT_IPNET { ipnet_if_print, DLT_IPNET }, #endif #ifdef DLT_IEEE802_15_4 { ieee802_15_4_if_print, DLT_IEEE802_15_4 }, #endif #ifdef DLT_IEEE802_15_4_NOFCS { ieee802_15_4_if_print, DLT_IEEE802_15_4_NOFCS }, #endif #ifdef DLT_PPI { ppi_if_print, DLT_PPI }, #endif #ifdef DLT_NETANALYZER { netanalyzer_if_print, DLT_NETANALYZER }, #endif #ifdef DLT_NETANALYZER_TRANSPARENT { netanalyzer_transparent_if_print, DLT_NETANALYZER_TRANSPARENT }, #endif #if defined(DLT_NFLOG) && defined(HAVE_PCAP_NFLOG_H) { nflog_if_print, DLT_NFLOG}, #endif #ifdef DLT_CIP { cip_if_print, DLT_CIP }, #endif #ifdef DLT_ATM_CLIP { cip_if_print, DLT_ATM_CLIP }, #endif #ifdef DLT_IP_OVER_FC { ipfc_if_print, DLT_IP_OVER_FC }, #endif { null_if_print, DLT_NULL }, #ifdef DLT_LOOP { null_if_print, DLT_LOOP }, #endif #ifdef DLT_APPLE_IP_OVER_IEEE1394 { ap1394_if_print, DLT_APPLE_IP_OVER_IEEE1394 }, #endif #if defined(DLT_BLUETOOTH_HCI_H4_WITH_PHDR) && defined(HAVE_PCAP_BLUETOOTH_H) { bt_if_print, DLT_BLUETOOTH_HCI_H4_WITH_PHDR}, #endif #ifdef DLT_LANE8023 { lane_if_print, DLT_LANE8023 }, #endif { arcnet_if_print, DLT_ARCNET }, #ifdef DLT_ARCNET_LINUX { arcnet_linux_if_print, DLT_ARCNET_LINUX }, #endif { raw_if_print, DLT_RAW }, #ifdef DLT_IPV4 { raw_if_print, DLT_IPV4 }, #endif #ifdef DLT_IPV6 { raw_if_print, DLT_IPV6 }, #endif #ifdef HAVE_PCAP_USB_H #ifdef DLT_USB_LINUX { usb_linux_48_byte_print, DLT_USB_LINUX}, #endif /* DLT_USB_LINUX */ #ifdef DLT_USB_LINUX_MMAPPED { usb_linux_64_byte_print, DLT_USB_LINUX_MMAPPED}, #endif /* DLT_USB_LINUX_MMAPPED */ #endif /* HAVE_PCAP_USB_H */ #ifdef DLT_SYMANTEC_FIREWALL { symantec_if_print, DLT_SYMANTEC_FIREWALL }, #endif #ifdef DLT_C_HDLC { chdlc_if_print, DLT_C_HDLC }, #endif #ifdef DLT_HDLC { chdlc_if_print, DLT_HDLC }, #endif #ifdef DLT_PPP_ETHER { pppoe_if_print, DLT_PPP_ETHER }, #endif #if defined(DLT_PFLOG) && defined(HAVE_NET_PFVAR_H) { pflog_if_print, DLT_PFLOG }, #endif { token_if_print, DLT_IEEE802 }, { fddi_if_print, DLT_FDDI }, #ifdef DLT_LINUX_SLL { sll_if_print, DLT_LINUX_SLL }, #endif #ifdef DLT_FR { fr_if_print, DLT_FR }, #endif #ifdef DLT_FRELAY { fr_if_print, DLT_FRELAY }, #endif #ifdef DLT_MFR { mfr_if_print, DLT_MFR }, #endif { atm_if_print, DLT_ATM_RFC1483 }, #ifdef DLT_SUNATM { sunatm_if_print, DLT_SUNATM }, #endif #ifdef DLT_ENC { enc_if_print, DLT_ENC }, #endif { sl_if_print, DLT_SLIP }, #ifdef DLT_SLIP_BSDOS { sl_bsdos_if_print, DLT_SLIP_BSDOS }, #endif #ifdef DLT_LTALK { ltalk_if_print, DLT_LTALK }, #endif #ifdef DLT_JUNIPER_ATM1 { juniper_atm1_print, DLT_JUNIPER_ATM1 }, #endif #ifdef DLT_JUNIPER_ATM2 { juniper_atm2_print, DLT_JUNIPER_ATM2 }, #endif #ifdef DLT_JUNIPER_MFR { juniper_mfr_print, DLT_JUNIPER_MFR }, #endif #ifdef DLT_JUNIPER_MLFR { juniper_mlfr_print, DLT_JUNIPER_MLFR }, #endif #ifdef DLT_JUNIPER_MLPPP { juniper_mlppp_print, DLT_JUNIPER_MLPPP }, #endif #ifdef DLT_JUNIPER_PPPOE { juniper_pppoe_print, DLT_JUNIPER_PPPOE }, #endif #ifdef DLT_JUNIPER_PPPOE_ATM { juniper_pppoe_atm_print, DLT_JUNIPER_PPPOE_ATM }, #endif #ifdef DLT_JUNIPER_GGSN { juniper_ggsn_print, DLT_JUNIPER_GGSN }, #endif #ifdef DLT_JUNIPER_ES { juniper_es_print, DLT_JUNIPER_ES }, #endif #ifdef DLT_JUNIPER_MONITOR { juniper_monitor_print, DLT_JUNIPER_MONITOR }, #endif #ifdef DLT_JUNIPER_SERVICES { juniper_services_print, DLT_JUNIPER_SERVICES }, #endif #ifdef DLT_JUNIPER_ETHER { juniper_ether_print, DLT_JUNIPER_ETHER }, #endif #ifdef DLT_JUNIPER_PPP { juniper_ppp_print, DLT_JUNIPER_PPP }, #endif #ifdef DLT_JUNIPER_FRELAY { juniper_frelay_print, DLT_JUNIPER_FRELAY }, #endif #ifdef DLT_JUNIPER_CHDLC { juniper_chdlc_print, DLT_JUNIPER_CHDLC }, #endif #ifdef DLT_PKTAP { pktap_if_print, DLT_PKTAP }, #endif #ifdef DLT_IEEE802_11_RADIO { ieee802_11_radio_if_print, DLT_IEEE802_11_RADIO }, #endif #ifdef DLT_IEEE802_11 { ieee802_11_if_print, DLT_IEEE802_11}, #endif #ifdef DLT_IEEE802_11_RADIO_AVS { ieee802_11_radio_avs_if_print, DLT_IEEE802_11_RADIO_AVS }, #endif #ifdef DLT_PRISM_HEADER { prism_if_print, DLT_PRISM_HEADER }, #endif { ppp_if_print, DLT_PPP }, #ifdef DLT_PPP_WITHDIRECTION { ppp_if_print, DLT_PPP_WITHDIRECTION }, #endif #ifdef DLT_PPP_BSDOS { ppp_bsdos_if_print, DLT_PPP_BSDOS }, #endif #ifdef DLT_PPP_SERIAL { ppp_hdlc_if_print, DLT_PPP_SERIAL }, #endif { NULL, 0 }, }; static const struct tok status_flags[] = { #ifdef PCAP_IF_UP { PCAP_IF_UP, "Up" }, #endif #ifdef PCAP_IF_RUNNING { PCAP_IF_RUNNING, "Running" }, #endif { PCAP_IF_LOOPBACK, "Loopback" }, { 0, NULL } }; if_printer lookup_printer(int type) { const struct printer *p; for (p = printers; p->f; ++p) if (type == p->type) return p->f; return NULL; /* NOTREACHED */ } if_ndo_printer lookup_ndo_printer(int type) { const struct ndo_printer *p; for (p = ndo_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 = ndo_printers; p->f; ++p) if (DLT_PKTAP == p->type) return p->f; } #endif return NULL; /* NOTREACHED */ } static pcap_t *pd; static int supports_monitor_mode; extern int optind; extern int opterr; extern char *optarg; struct print_info { netdissect_options *ndo; union { if_printer printer; if_ndo_printer ndo_printer; } p; int ndo_type; }; struct dump_info { char *WFileName; char *CurrentFileName; pcap_t *pd; pcap_dumper_t *p; #ifdef HAVE_CAPSICUM int dirfd; #endif }; #ifdef HAVE_PCAP_SET_TSTAMP_TYPE static void show_tstamp_types_and_exit(const char *device, pcap_t *pd) { int n_tstamp_types; int *tstamp_types = 0; const char *tstamp_type_name; int i; n_tstamp_types = pcap_list_tstamp_types(pd, &tstamp_types); if (n_tstamp_types < 0) error("%s", pcap_geterr(pd)); if (n_tstamp_types == 0) { fprintf(stderr, "Time stamp type cannot be set for %s\n", device); exit(0); } fprintf(stderr, "Time stamp types for %s (use option -j to set):\n", device); for (i = 0; i < n_tstamp_types; i++) { tstamp_type_name = pcap_tstamp_type_val_to_name(tstamp_types[i]); if (tstamp_type_name != NULL) { (void) fprintf(stderr, " %s (%s)\n", tstamp_type_name, pcap_tstamp_type_val_to_description(tstamp_types[i])); } else { (void) fprintf(stderr, " %d\n", tstamp_types[i]); } } pcap_free_tstamp_types(tstamp_types); exit(0); } #endif static void show_dlts_and_exit(const char *device, pcap_t *pd) { int n_dlts; int *dlts = 0; const char *dlt_name; n_dlts = pcap_list_datalinks(pd, &dlts); if (n_dlts < 0) error("%s", pcap_geterr(pd)); else if (n_dlts == 0 || !dlts) error("No data link types."); /* * If the interface is known to support monitor mode, indicate * whether these are the data link types available when not in * monitor mode, if -I wasn't specified, or when in monitor mode, * when -I was specified (the link-layer types available in * monitor mode might be different from the ones available when * not in monitor mode). */ if (supports_monitor_mode) (void) fprintf(stderr, "Data link types for %s %s (use option -y to set):\n", device, Iflag ? "when in monitor mode" : "when not in monitor mode"); else (void) fprintf(stderr, "Data link types for %s (use option -y to set):\n", device); while (--n_dlts >= 0) { dlt_name = pcap_datalink_val_to_name(dlts[n_dlts]); if (dlt_name != NULL) { (void) fprintf(stderr, " %s (%s)", dlt_name, pcap_datalink_val_to_description(dlts[n_dlts])); /* * OK, does tcpdump handle that type? */ if (lookup_printer(dlts[n_dlts]) == NULL && lookup_ndo_printer(dlts[n_dlts]) == NULL) (void) fprintf(stderr, " (printing not supported)"); fprintf(stderr, "\n"); } else { (void) fprintf(stderr, " DLT %d (printing not supported)\n", dlts[n_dlts]); } } #ifdef HAVE_PCAP_FREE_DATALINKS pcap_free_datalinks(dlts); #endif exit(0); } #ifdef HAVE_PCAP_FINDALLDEVS static void show_devices_and_exit (void) { pcap_if_t *devpointer; char ebuf[PCAP_ERRBUF_SIZE]; int i; if (pcap_findalldevs(&devpointer, ebuf) < 0) error("%s", ebuf); else { for (i = 0; devpointer != NULL; i++) { printf("%d.%s", i+1, devpointer->name); if (devpointer->description != NULL) printf(" (%s)", devpointer->description); if (devpointer->flags != 0) printf(" [%s]", bittok2str(status_flags, "none", devpointer->flags)); printf("\n"); devpointer = devpointer->next; } } exit(0); } #endif /* HAVE_PCAP_FINDALLDEVS */ /* * Short options. * * Note that there we use all letters for short options except for g, k, * o, and P, and those are used by other versions of tcpdump, and we should * only use them for the same purposes that the other versions of tcpdump * use them: * * OS X tcpdump uses -g to force non--v output for IP to be on one * line, making it more "g"repable; * * OS X tcpdump uses -k tospecify that packet comments in pcap-ng files * should be printed; * * OpenBSD tcpdump uses -o to indicate that OS fingerprinting should be done * for hosts sending TCP SYN packets; * * OS X tcpdump uses -P to indicate that -w should write pcap-ng rather * than pcap files. + * + * OS X tcpdump also uses -Q to specify expressions that match packet + * metadata, including but not limited to the packet direction. + * The expression syntax is different from a simple "in|out|inout", + * and those expressions aren't accepted by OS X tcpdump, but the + * equivalents would be "in" = "dir=in", "out" = "dir=out", and + * "inout" = "dir=in or dir=out", and the parser could conceivably + * special-case "in", "out", and "inout" as expressions for backwards + * compatibility, so all is not (yet) lost. */ /* * Set up flags that might or might not be supported depending on the * version of libpcap we're using. */ #if defined(HAVE_PCAP_CREATE) || defined(WIN32) #define B_FLAG "B:" #define B_FLAG_USAGE " [ -B size ]" #else /* defined(HAVE_PCAP_CREATE) || defined(WIN32) */ #define B_FLAG #define B_FLAG_USAGE #endif /* defined(HAVE_PCAP_CREATE) || defined(WIN32) */ #ifdef HAVE_PCAP_CREATE #define I_FLAG "I" #else /* HAVE_PCAP_CREATE */ #define I_FLAG #endif /* HAVE_PCAP_CREATE */ #ifdef HAVE_PCAP_SET_TSTAMP_TYPE #define j_FLAG "j:" #define j_FLAG_USAGE " [ -j tstamptype ]" #define J_FLAG "J" #else /* PCAP_ERROR_TSTAMP_TYPE_NOTSUP */ #define j_FLAG #define j_FLAG_USAGE #define J_FLAG #endif /* PCAP_ERROR_TSTAMP_TYPE_NOTSUP */ #ifdef HAVE_PCAP_FINDALLDEVS -#ifndef HAVE_PCAP_IF_T -#undef HAVE_PCAP_FINDALLDEVS -#endif -#endif - -#ifdef HAVE_PCAP_FINDALLDEVS #define D_FLAG "D" #else #define D_FLAG #endif #ifdef HAVE_PCAP_DUMP_FLUSH #define U_FLAG "U" #else #define U_FLAG #endif #ifdef HAVE_PCAP_SETDIRECTION #define Q_FLAG "Q:" #else #define Q_FLAG #endif +#define SHORTOPTS "aAb" B_FLAG "c:C:d" D_FLAG "eE:fF:G:hHi:" I_FLAG j_FLAG J_FLAG "KlLm:M:nNOpq" Q_FLAG "r:Rs:StT:u" U_FLAG "vV:w:W:xXy:Yz:Z:#" + /* * Long options. * * We do not currently have long options corresponding to all short * options; we should probably pick appropriate option names for them. * * However, the short options where the number of times the option is * specified matters, such as -v and -d and -t, should probably not * just map to a long option, as saying * * tcpdump --verbose --verbose * * doesn't make sense; it should be --verbosity={N} or something such * as that. * * For long options with no corresponding short options, we define values * outside the range of ASCII graphic characters, make that the last * component of the entry for the long option, and have a case for that * option in the switch statement. */ #define OPTION_VERSION 128 #define OPTION_TSTAMP_PRECISION 129 +#define OPTION_IMMEDIATE_MODE 130 static const struct option longopts[] = { #if defined(HAVE_PCAP_CREATE) || defined(WIN32) { "buffer-size", required_argument, NULL, 'B' }, #endif { "list-interfaces", no_argument, NULL, 'D' }, { "help", no_argument, NULL, 'h' }, { "interface", required_argument, NULL, 'i' }, #ifdef HAVE_PCAP_CREATE { "monitor-mode", no_argument, NULL, 'I' }, #endif #ifdef HAVE_PCAP_SET_TSTAMP_TYPE { "time-stamp-type", required_argument, NULL, 'j' }, { "list-time-stamp-types", no_argument, NULL, 'J' }, #endif #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION { "time-stamp-precision", required_argument, NULL, OPTION_TSTAMP_PRECISION}, #endif { "dont-verify-checksums", no_argument, NULL, 'K' }, { "list-data-link-types", no_argument, NULL, 'L' }, { "no-optimize", no_argument, NULL, 'O' }, { "no-promiscuous-mode", no_argument, NULL, 'p' }, #ifdef HAVE_PCAP_SETDIRECTION { "direction", required_argument, NULL, 'Q' }, #endif { "snapshot-length", required_argument, NULL, 's' }, { "absolute-tcp-sequence-numbers", no_argument, NULL, 'S' }, #ifdef HAVE_PCAP_DUMP_FLUSH { "packet-buffered", no_argument, NULL, 'U' }, #endif { "linktype", required_argument, NULL, 'y' }, +#ifdef HAVE_PCAP_SET_IMMEDIATE_MODE + { "immediate-mode", no_argument, NULL, OPTION_IMMEDIATE_MODE }, +#endif #if defined(HAVE_PCAP_DEBUG) || defined(HAVE_YYDEBUG) { "debug-filter-parser", no_argument, NULL, 'Y' }, #endif { "relinquish-privileges", required_argument, NULL, 'Z' }, { "number", no_argument, NULL, '#' }, { "version", no_argument, NULL, OPTION_VERSION }, { NULL, 0, NULL, 0 } }; #ifndef WIN32 /* Drop root privileges and chroot if necessary */ static void droproot(const char *username, const char *chroot_dir) { struct passwd *pw = NULL; if (chroot_dir && !username) { fprintf(stderr, "tcpdump: Chroot without dropping root is insecure\n"); exit(1); } pw = getpwnam(username); if (pw) { if (chroot_dir) { if (chroot(chroot_dir) != 0 || chdir ("/") != 0) { fprintf(stderr, "tcpdump: Couldn't chroot/chdir to '%.64s': %s\n", chroot_dir, pcap_strerror(errno)); exit(1); } } -#ifdef HAVE_CAP_NG_H +#ifdef HAVE_LIBCAP_NG int ret = capng_change_id(pw->pw_uid, pw->pw_gid, CAPNG_NO_FLAG); if (ret < 0) { fprintf(stderr, "error : ret %d\n", ret); } else { - printf("dropped privs to %s\n", username); + fprintf(stderr, "dropped privs to %s\n", username); } - /* We don't need CAP_SETUID and CAP_SETGID */ - capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_SETUID); - capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_SETUID); - capng_update(CAPNG_DROP, CAPNG_PERMITTED, CAP_SETUID); - capng_update(CAPNG_DROP, CAPNG_PERMITTED, CAP_SETUID); - capng_apply(CAPNG_SELECT_BOTH); - #else if (initgroups(pw->pw_name, pw->pw_gid) != 0 || setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) { fprintf(stderr, "tcpdump: Couldn't change to '%.32s' uid=%lu gid=%lu: %s\n", username, (unsigned long)pw->pw_uid, (unsigned long)pw->pw_gid, pcap_strerror(errno)); exit(1); } else { - printf("dropped privs to %s\n", username); + fprintf(stderr, "dropped privs to %s\n", username); } -#endif /* HAVE_CAP_NG_H */ +#endif /* HAVE_LIBCAP_NG */ } else { fprintf(stderr, "tcpdump: Couldn't find user '%.32s'\n", username); exit(1); } +#ifdef HAVE_LIBCAP_NG + /* We don't need CAP_SETUID and CAP_SETGID any more. */ + capng_updatev( + CAPNG_DROP, + CAPNG_EFFECTIVE | CAPNG_PERMITTED, + CAP_SETUID, + CAP_SETGID, + -1); + capng_apply(CAPNG_SELECT_BOTH); +#endif /* HAVE_LIBCAP_NG */ + } #endif /* WIN32 */ static int getWflagChars(int x) { int c = 0; x -= 1; while (x > 0) { c += 1; x /= 10; } return c; } static void MakeFilename(char *buffer, char *orig_name, int cnt, int max_chars) { char *filename = malloc(PATH_MAX + 1); if (filename == NULL) error("Makefilename: malloc"); /* Process with strftime if Gflag is set. */ if (Gflag != 0) { struct tm *local_tm; /* Convert Gflag_time to a usable format */ if ((local_tm = localtime(&Gflag_time)) == NULL) { error("MakeTimedFilename: localtime"); } /* There's no good way to detect an error in strftime since a return * value of 0 isn't necessarily failure. */ strftime(filename, PATH_MAX, orig_name, local_tm); } else { strncpy(filename, orig_name, PATH_MAX); } if (cnt == 0 && max_chars == 0) strncpy(buffer, filename, PATH_MAX + 1); else if (snprintf(buffer, PATH_MAX + 1, "%s%0*d", filename, max_chars, cnt) > PATH_MAX) /* Report an error if the filename is too large */ error("too many output files or filename is too long (> %d)", PATH_MAX); free(filename); } static int tcpdump_printf(netdissect_options *ndo _U_, const char *fmt, ...) { va_list args; int ret; va_start(args, fmt); ret=vfprintf(stdout, fmt, args); va_end(args); return ret; } static struct print_info get_print_info(int type) { struct print_info printinfo; printinfo.ndo_type = 1; printinfo.ndo = gndo; printinfo.p.ndo_printer = lookup_ndo_printer(type); if (printinfo.p.ndo_printer == NULL) { printinfo.p.printer = lookup_printer(type); printinfo.ndo_type = 0; if (printinfo.p.printer == NULL) { gndo->ndo_dltname = pcap_datalink_val_to_name(type); if (gndo->ndo_dltname != NULL) error("packet printing is not supported for link type %s: use -w", gndo->ndo_dltname); else error("packet printing is not supported for link type %d: use -w", type); } } return (printinfo); } static char * get_next_file(FILE *VFile, char *ptr) { char *ret; ret = fgets(ptr, PATH_MAX, VFile); if (!ret) return NULL; if (ptr[strlen(ptr) - 1] == '\n') ptr[strlen(ptr) - 1] = '\0'; return ret; } #ifdef HAVE_CAPSICUM 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) { warning("unable to contact casperd"); return (NULL); } capdnsloc = cap_service_open(capcas, "system.dns"); /* Casper capability no longer needed. */ cap_close(capcas); if (capdnsloc == NULL) error("unable to open system.dns service"); /* Limit system.dns to reverse DNS lookups. */ types[0] = "ADDR"; if (cap_dns_type_limit(capdnsloc, types, 1) < 0) error("unable to limit access to system.dns service"); families[0] = AF_INET; families[1] = AF_INET6; if (cap_dns_family_limit(capdnsloc, families, 2) < 0) error("unable to limit access to system.dns service"); return (capdnsloc); } #endif /* HAVE_CAPSICUM */ #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION static int tstamp_precision_from_string(const char *precision) { if (strncmp(precision, "nano", strlen("nano")) == 0) return PCAP_TSTAMP_PRECISION_NANO; if (strncmp(precision, "micro", strlen("micro")) == 0) return PCAP_TSTAMP_PRECISION_MICRO; return -EINVAL; } static const char * tstamp_precision_to_string(int precision) { switch (precision) { case PCAP_TSTAMP_PRECISION_MICRO: return "micro"; case PCAP_TSTAMP_PRECISION_NANO: return "nano"; default: return "unknown"; } } #endif +#ifdef HAVE_CAPSICUM +/* + * Ensure that, on a dump file's descriptor, we have all the rights + * necessary to make the standard I/O library work with an fdopen()ed + * FILE * from that descriptor. + * + * A long time ago, in a galaxy far far away, AT&T decided that, instead + * of providing separate APIs for getting and setting the FD_ flags on a + * descriptor, getting and setting the O_ flags on a descriptor, and + * locking files, they'd throw them all into a kitchen-sink fcntl() call + * along the lines of ioctl(), the fact that ioctl() operations are + * largely specific to particular character devices but fcntl() operations + * are either generic to all descriptors or generic to all descriptors for + * regular files nonwithstanding. + * + * The Capsicum people decided that fine-grained control of descriptor + * operations was required, so that you need to grant permission for + * reading, writing, seeking, and fcntl-ing. The latter, courtesy of + * AT&T's decision, means that "fcntl-ing" isn't a thing, but a motley + * collection of things, so there are *individual* fcntls for which + * permission needs to be granted. + * + * The FreeBSD standard I/O people implemented some optimizations that + * requires that the standard I/O routines be able to determine whether + * the descriptor for the FILE * is open append-only or not; as that + * descriptor could have come from an open() rather than an fopen(), + * that requires that it be able to do an F_GETFL fcntl() to read + * the O_ flags. + * + * Tcpdump uses ftell() to determine how much data has been written + * to a file in order to, when used with -C, determine when it's time + * to rotate capture files. ftell() therefore needs to do an lseek() + * to find out the file offset and must, thanks to the aforementioned + * optimization, also know whether the descriptor is open append-only + * or not. + * + * The net result of all the above is that we need to grant CAP_SEEK, + * CAP_WRITE, and CAP_FCNTL with the CAP_FCNTL_GETFL subcapability. + * + * Perhaps this is the universe's way of saying that either + * + * 1) there needs to be an fopenat() call and a pcap_dump_openat() call + * using it, so that Capsicum-capable tcpdump wouldn't need to do + * an fdopen() + * + * or + * + * 2) there needs to be a cap_fdopen() call in the FreeBSD standard + * I/O library that knows what rights are needed by the standard + * I/O library, based on the open mode, and assigns them, perhaps + * with an additional argument indicating, for example, whether + * seeking should be allowed, so that tcpdump doesn't need to know + * what the standard I/O library happens to require this week. + */ +static void +set_dumper_capsicum_rights(pcap_dumper_t *p) +{ + int fd = fileno(pcap_dump_file(p)); + cap_rights_t rights; + + cap_rights_init(&rights, CAP_SEEK, CAP_WRITE, CAP_FCNTL); + if (cap_rights_limit(fd, &rights) < 0 && errno != ENOSYS) { + error("unable to limit dump descriptor"); + } + if (cap_fcntls_limit(fd, CAP_FCNTL_GETFL) < 0 && errno != ENOSYS) { + error("unable to limit dump descriptor fcntls"); + } +} +#endif + int main(int argc, char **argv) { register int cnt, op, i; bpf_u_int32 localnet =0 , netmask = 0; register char *cp, *infile, *cmdbuf, *device, *RFileName, *VFileName, *WFileName; pcap_handler callback; int type; int dlt; int new_dlt; const char *dlt_name; struct bpf_program fcode; #ifndef WIN32 RETSIGTYPE (*oldhandler)(int); #endif struct print_info printinfo; struct dump_info dumpinfo; u_char *pcap_userdata; char ebuf[PCAP_ERRBUF_SIZE]; char VFileLine[PATH_MAX + 1]; char *username = NULL; char *chroot_dir = NULL; char *ret = NULL; char *end; #ifdef HAVE_PCAP_FINDALLDEVS pcap_if_t *devpointer; int devnum; #endif int status; FILE *VFile; #ifdef HAVE_CAPSICUM cap_rights_t rights; #endif /* HAVE_CAPSICUM */ int cansandbox; #ifdef WIN32 if(wsockinit() != 0) return 1; #endif /* WIN32 */ jflag=-1; /* not set */ gndo->ndo_Oflag=1; gndo->ndo_Rflag=1; gndo->ndo_dlt=-1; gndo->ndo_default_print=ndo_default_print; gndo->ndo_printf=tcpdump_printf; gndo->ndo_error=ndo_error; gndo->ndo_warning=ndo_warning; gndo->ndo_snaplen = DEFAULT_SNAPLEN; + gndo->ndo_immediate = 0; cnt = -1; device = NULL; infile = NULL; RFileName = NULL; VFileName = NULL; VFile = NULL; WFileName = NULL; dlt = -1; if ((cp = strrchr(argv[0], '/')) != NULL) program_name = cp + 1; else program_name = argv[0]; + /* + * 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); #ifdef USE_LIBSMI smiInit("tcpdump"); #endif while ( - (op = getopt_long(argc, argv, "aAb" B_FLAG "c:C:d" D_FLAG "eE:fF:G:hHi:" I_FLAG j_FLAG J_FLAG "KlLm:M:nNOpq" Q_FLAG "r:Rs:StT:u" U_FLAG "vV:w:W:xXy:Yz:Z:#", longopts, NULL)) != -1) + (op = getopt_long(argc, argv, SHORTOPTS, longopts, NULL)) != -1) switch (op) { case 'a': /* compatibility for old -a */ break; case 'A': ++Aflag; break; case 'b': ++bflag; break; #if defined(HAVE_PCAP_CREATE) || defined(WIN32) case 'B': Bflag = atoi(optarg)*1024; if (Bflag <= 0) error("invalid packet buffer size %s", optarg); break; #endif /* defined(HAVE_PCAP_CREATE) || defined(WIN32) */ case 'c': cnt = atoi(optarg); if (cnt <= 0) error("invalid packet count %s", optarg); break; case 'C': Cflag = atoi(optarg) * 1000000; if (Cflag < 0) error("invalid file size %s", optarg); break; case 'd': ++dflag; break; case 'D': Dflag++; break; case 'L': Lflag++; break; case 'e': ++eflag; break; case 'E': #ifndef HAVE_LIBCRYPTO warning("crypto code not compiled in"); #endif gndo->ndo_espsecret = optarg; break; case 'f': ++fflag; break; case 'F': infile = optarg; break; case 'G': Gflag = atoi(optarg); if (Gflag < 0) error("invalid number of seconds %s", optarg); /* We will create one file initially. */ Gflag_count = 0; /* Grab the current time for rotation use. */ if ((Gflag_time = time(NULL)) == (time_t)-1) { error("main: can't get current time: %s", pcap_strerror(errno)); } break; case 'h': print_usage(); exit(0); break; case 'H': ++Hflag; break; case 'i': if (optarg[0] == '0' && optarg[1] == 0) error("Invalid adapter index"); #ifdef HAVE_PCAP_FINDALLDEVS /* * If the argument is a number, treat it as * an index into the list of adapters, as * printed by "tcpdump -D". * * This should be OK on UNIX systems, as interfaces * shouldn't have names that begin with digits. * It can be useful on Windows, where more than * one interface can have the same name. */ devnum = strtol(optarg, &end, 10); if (optarg != end && *end == '\0') { if (devnum < 0) error("Invalid adapter index"); if (pcap_findalldevs(&devpointer, ebuf) < 0) error("%s", ebuf); else { /* * Look for the devnum-th entry * in the list of devices * (1-based). */ for (i = 0; i < devnum-1 && devpointer != NULL; i++, devpointer = devpointer->next) ; if (devpointer == NULL) error("Invalid adapter index"); } device = devpointer->name; break; } #endif /* HAVE_PCAP_FINDALLDEVS */ device = optarg; break; #ifdef HAVE_PCAP_CREATE case 'I': ++Iflag; break; #endif /* HAVE_PCAP_CREATE */ #ifdef HAVE_PCAP_SET_TSTAMP_TYPE case 'j': jflag = pcap_tstamp_type_name_to_val(optarg); if (jflag < 0) error("invalid time stamp type %s", optarg); break; case 'J': Jflag++; break; #endif case 'l': #ifdef WIN32 /* * _IOLBF is the same as _IOFBF in Microsoft's C * libraries; the only alternative they offer * is _IONBF. * * XXX - this should really be checking for MSVC++, * not WIN32, if, for example, MinGW has its own * C library that is more UNIX-compatible. */ setvbuf(stdout, NULL, _IONBF, 0); #else /* WIN32 */ #ifdef HAVE_SETLINEBUF setlinebuf(stdout); #else setvbuf(stdout, NULL, _IOLBF, 0); #endif #endif /* WIN32 */ break; case 'K': ++Kflag; break; case 'm': #ifdef USE_LIBSMI if (smiLoadModule(optarg) == 0) { error("could not load MIB module %s", optarg); } sflag = 1; #else (void)fprintf(stderr, "%s: ignoring option `-m %s' ", program_name, optarg); (void)fprintf(stderr, "(no libsmi support)\n"); #endif break; case 'M': /* TCP-MD5 shared secret */ #ifndef HAVE_LIBCRYPTO warning("crypto code not compiled in"); #endif sigsecret = optarg; break; case 'n': ++nflag; break; case 'N': ++Nflag; break; case 'O': Oflag = 0; break; case 'p': ++pflag; break; case 'q': ++qflag; ++suppress_default_print; break; #ifdef HAVE_PCAP_SETDIRECTION case 'Q': if (strcasecmp(optarg, "in") == 0) Qflag = PCAP_D_IN; else if (strcasecmp(optarg, "out") == 0) Qflag = PCAP_D_OUT; else if (strcasecmp(optarg, "inout") == 0) Qflag = PCAP_D_INOUT; else error("unknown capture direction `%s'", optarg); break; #endif /* HAVE_PCAP_SETDIRECTION */ case 'r': RFileName = optarg; break; case 'R': Rflag = 0; break; case 's': snaplen = strtol(optarg, &end, 0); if (optarg == end || *end != '\0' || snaplen < 0 || snaplen > MAXIMUM_SNAPLEN) error("invalid snaplen %s", optarg); else if (snaplen == 0) snaplen = MAXIMUM_SNAPLEN; break; case 'S': ++Sflag; break; case 't': ++tflag; break; case 'T': if (strcasecmp(optarg, "vat") == 0) packettype = PT_VAT; else if (strcasecmp(optarg, "wb") == 0) packettype = PT_WB; else if (strcasecmp(optarg, "rpc") == 0) packettype = PT_RPC; else if (strcasecmp(optarg, "rtp") == 0) packettype = PT_RTP; else if (strcasecmp(optarg, "rtcp") == 0) packettype = PT_RTCP; else if (strcasecmp(optarg, "snmp") == 0) packettype = PT_SNMP; else if (strcasecmp(optarg, "cnfp") == 0) packettype = PT_CNFP; else if (strcasecmp(optarg, "tftp") == 0) packettype = PT_TFTP; else if (strcasecmp(optarg, "aodv") == 0) packettype = PT_AODV; else if (strcasecmp(optarg, "carp") == 0) packettype = PT_CARP; else if (strcasecmp(optarg, "radius") == 0) packettype = PT_RADIUS; else if (strcasecmp(optarg, "zmtp1") == 0) packettype = PT_ZMTP1; else if (strcasecmp(optarg, "vxlan") == 0) packettype = PT_VXLAN; else if (strcasecmp(optarg, "pgm") == 0) packettype = PT_PGM; else if (strcasecmp(optarg, "pgm_zmtp1") == 0) packettype = PT_PGM_ZMTP1; else if (strcasecmp(optarg, "lmp") == 0) packettype = PT_LMP; else error("unknown packet type `%s'", optarg); break; case 'u': ++uflag; break; #ifdef HAVE_PCAP_DUMP_FLUSH case 'U': ++Uflag; break; #endif case 'v': ++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': ++xflag; ++suppress_default_print; break; case 'X': ++Xflag; ++suppress_default_print; break; case 'y': gndo->ndo_dltname = optarg; gndo->ndo_dlt = pcap_datalink_name_to_val(gndo->ndo_dltname); if (gndo->ndo_dlt < 0) error("invalid data link type %s", gndo->ndo_dltname); break; #if defined(HAVE_PCAP_DEBUG) || defined(HAVE_YYDEBUG) case 'Y': { /* Undocumented flag */ #ifdef HAVE_PCAP_DEBUG extern int pcap_debug; pcap_debug = 1; #else extern int yydebug; yydebug = 1; #endif } break; #endif case 'z': zflag = strdup(optarg); break; case 'Z': username = strdup(optarg); break; case '#': gndo->ndo_packet_number = 1; break; case OPTION_VERSION: print_version(); exit(0); break; #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION case OPTION_TSTAMP_PRECISION: gndo->ndo_tstamp_precision = tstamp_precision_from_string(optarg); if (gndo->ndo_tstamp_precision < 0) error("unsupported time stamp precision"); break; #endif +#ifdef HAVE_PCAP_SET_IMMEDIATE_MODE + case OPTION_IMMEDIATE_MODE: + gndo->ndo_immediate = 1; + break; +#endif + default: print_usage(); exit(1); /* NOTREACHED */ } #ifdef HAVE_PCAP_FINDALLDEVS if (Dflag) show_devices_and_exit(); #endif switch (tflag) { case 0: /* Default */ case 4: /* Default + Date*/ thiszone = gmt2local(0); break; case 1: /* No time stamp */ case 2: /* Unix timeval style */ case 3: /* Microseconds since previous packet */ case 5: /* Microseconds since first packet */ break; default: /* Not supported */ error("only -t, -tt, -ttt, -tttt and -ttttt are supported"); break; } if (fflag != 0 && (VFileName != NULL || RFileName != NULL)) error("-f can not be used with -V or -r"); if (VFileName != NULL && RFileName != NULL) error("-V and -r are mutually exclusive."); +#ifdef HAVE_PCAP_SET_IMMEDIATE_MODE + /* + * If we're printing dissected packets to the standard output + * rather than saving raw packets to a file, and the standard + * output is a terminal, use immediate mode, as the user's + * probably expecting to see packets pop up immediately. + */ + if (WFileName == NULL && isatty(1)) + gndo->ndo_immediate = 1; +#endif + #ifdef WITH_CHROOT /* if run as root, prepare for chrooting */ if (getuid() == 0 || geteuid() == 0) { /* future extensibility for cmd-line arguments */ if (!chroot_dir) chroot_dir = WITH_CHROOT; } #endif #ifdef WITH_USER /* if run as root, prepare for dropping root privileges */ if (getuid() == 0 || geteuid() == 0) { /* Run with '-Z root' to restore old behaviour */ if (!username) username = WITH_USER; } #endif if (RFileName != NULL || VFileName != NULL) { /* * If RFileName is non-null, it's the pathname of a * savefile to read. If VFileName is non-null, it's * the pathname of a file containing a list of pathnames * (one per line) of savefiles to read. * * In either case, we're reading a savefile, not doing * a live capture. */ #ifndef WIN32 /* * We don't need network access, so relinquish any set-UID * or set-GID privileges we have (if any). * * We do *not* want set-UID privileges when opening a * trace file, as that might let the user read other * people's trace files (especially if we're set-UID * root). */ if (setgid(getgid()) != 0 || setuid(getuid()) != 0 ) fprintf(stderr, "Warning: setgid/setuid failed !\n"); #endif /* WIN32 */ if (VFileName != NULL) { if (VFileName[0] == '-' && VFileName[1] == '\0') VFile = stdin; else VFile = fopen(VFileName, "r"); if (VFile == NULL) error("Unable to open file: %s\n", 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, gndo->ndo_tstamp_precision, ebuf); #else pd = pcap_open_offline(RFileName, ebuf); #endif if (pd == NULL) error("%s", ebuf); #ifdef HAVE_CAPSICUM cap_rights_init(&rights, CAP_READ); if (cap_rights_limit(fileno(pcap_file(pd)), &rights) < 0 && errno != ENOSYS) { error("unable to limit pcap descriptor"); } #endif dlt = pcap_datalink(pd); dlt_name = pcap_datalink_val_to_name(dlt); if (dlt_name == NULL) { fprintf(stderr, "reading from file %s, link-type %u\n", RFileName, dlt); } else { fprintf(stderr, "reading from file %s, link-type %s (%s)\n", RFileName, dlt_name, pcap_datalink_val_to_description(dlt)); } } else { /* * We're doing a live capture. */ if (device == NULL) { device = pcap_lookupdev(ebuf); if (device == NULL) error("%s", ebuf); } #ifdef WIN32 /* * Print a message to the standard error on Windows. * XXX - why do it here, with a different message? */ if(strlen(device) == 1) /* we assume that an ASCII string is always longer than 1 char */ { /* a Unicode string has a \0 as second byte (so strlen() is 1) */ fprintf(stderr, "%s: listening on %ws\n", program_name, device); } else { fprintf(stderr, "%s: listening on %s\n", program_name, device); } fflush(stderr); #endif /* WIN32 */ #ifdef HAVE_PCAP_CREATE pd = pcap_create(device, ebuf); if (pd == NULL) error("%s", ebuf); #ifdef HAVE_PCAP_SET_TSTAMP_TYPE if (Jflag) show_tstamp_types_and_exit(device, pd); #endif #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION status = pcap_set_tstamp_precision(pd, gndo->ndo_tstamp_precision); if (status != 0) error("%s: Can't set %ssecond time stamp precision: %s", device, tstamp_precision_to_string(gndo->ndo_tstamp_precision), pcap_statustostr(status)); #endif +#ifdef HAVE_PCAP_SET_IMMEDIATE_MODE + if (gndo->ndo_immediate) { + status = pcap_set_immediate_mode(pd, 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(pd) == 1) supports_monitor_mode = 1; else supports_monitor_mode = 0; status = pcap_set_snaplen(pd, snaplen); if (status != 0) error("%s: Can't set snapshot length: %s", device, pcap_statustostr(status)); status = pcap_set_promisc(pd, !pflag); if (status != 0) error("%s: Can't set promiscuous mode: %s", device, pcap_statustostr(status)); if (Iflag) { status = pcap_set_rfmon(pd, 1); if (status != 0) error("%s: Can't set monitor mode: %s", device, pcap_statustostr(status)); } status = pcap_set_timeout(pd, 1000); if (status != 0) error("%s: pcap_set_timeout failed: %s", device, pcap_statustostr(status)); if (Bflag != 0) { status = pcap_set_buffer_size(pd, 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(pd, jflag); if (status < 0) error("%s: Can't set time stamp type: %s", - device, pcap_statustostr(status)); + device, pcap_statustostr(status)); } #endif status = pcap_activate(pd); if (status < 0) { /* * pcap_activate() failed. */ cp = pcap_geterr(pd); if (status == PCAP_ERROR) error("%s", cp); else if ((status == PCAP_ERROR_NO_SUCH_DEVICE || status == PCAP_ERROR_PERM_DENIED) && *cp != '\0') error("%s: %s\n(%s)", device, pcap_statustostr(status), cp); #ifdef __FreeBSD__ else if (status == PCAP_ERROR_RFMON_NOTSUP && strncmp(device, "wlan", 4) == 0) { char parent[8], newdev[8]; char sysctl[32]; size_t s = sizeof(parent); snprintf(sysctl, sizeof(sysctl), "net.wlan.%d.%%parent", atoi(device + 4)); sysctlbyname(sysctl, parent, &s, NULL, 0); strlcpy(newdev, device, sizeof(newdev)); /* Suggest a new wlan device. */ newdev[strlen(newdev)-1]++; error("%s is not a monitor mode VAP\n" "To create a new monitor mode VAP use:\n" " ifconfig %s create wlandev %s wlanmode " "monitor\nand use %s as the tcpdump " "interface", device, newdev, parent, newdev); } #endif else error("%s: %s", device, pcap_statustostr(status)); } else if (status > 0) { /* * pcap_activate() succeeded, but it's warning us * of a problem it had. */ cp = pcap_geterr(pd); 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(pd, Qflag); if (status != 0) error("%s: pcap_setdirection() failed: %s", device, pcap_geterr(pd)); } #endif /* HAVE_PCAP_SETDIRECTION */ #else *ebuf = '\0'; pd = pcap_open_live(device, snaplen, !pflag, 1000, ebuf); if (pd == NULL) error("%s", ebuf); else if (*ebuf) warning("%s", ebuf); #endif /* HAVE_PCAP_CREATE */ /* * Let user own process after socket has been opened. */ #ifndef WIN32 if (setgid(getgid()) != 0 || setuid(getuid()) != 0) fprintf(stderr, "Warning: setgid/setuid failed !\n"); #endif /* WIN32 */ #if !defined(HAVE_PCAP_CREATE) && defined(WIN32) if(Bflag != 0) if(pcap_setbuff(pd, Bflag)==-1){ error("%s", pcap_geterr(pd)); } #endif /* !defined(HAVE_PCAP_CREATE) && defined(WIN32) */ if (Lflag) show_dlts_and_exit(device, pd); if (gndo->ndo_dlt >= 0) { #ifdef HAVE_PCAP_SET_DATALINK if (pcap_set_datalink(pd, gndo->ndo_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 (gndo->ndo_dlt != pcap_datalink(pd)) { error("%s is not one of the DLTs supported by this device\n", gndo->ndo_dltname); } #endif (void)fprintf(stderr, "%s: data link type %s\n", program_name, gndo->ndo_dltname); (void)fflush(stderr); } i = pcap_snapshot(pd); if (snaplen < i) { warning("snaplen raised from %d to %d", snaplen, i); snaplen = i; } if(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]); 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); exit(0); } #ifdef HAVE_CAPSICUM if (!nflag) capdns = capdns_setup(); #endif /* HAVE_CAPSICUM */ init_addrtoname(gndo, localnet, netmask); init_checksum(); #ifndef WIN32 (void)setsignal(SIGPIPE, cleanup); (void)setsignal(SIGTERM, cleanup); (void)setsignal(SIGINT, cleanup); #endif /* WIN32 */ #if defined(HAVE_FORK) || defined(HAVE_VFORK) (void)setsignal(SIGCHLD, child_cleanup); #endif /* Cooperate with nohup(1) */ #ifndef WIN32 if ((oldhandler = setsignal(SIGHUP, cleanup)) != SIG_DFL) (void)setsignal(SIGHUP, oldhandler); #endif /* WIN32 */ #ifndef WIN32 /* * If a user name was specified with "-Z", attempt to switch to * that user's UID. This would probably be used with sudo, * to allow tcpdump to be run in a special restricted * account (if you just want to allow users to open capture * devices, and can't just give users that permission, * you'd make tcpdump set-UID or set-GID). * * Tcpdump doesn't necessarily write only to one savefile; * the general only way to allow a -Z instance to write to * savefiles as the user under whose UID it's run, rather * than as the user specified with -Z, would thus be to switch * to the original user ID before opening a capture file and * then switch back to the -Z user ID after opening the savefile. * Switching to the -Z user ID only after opening the first * savefile doesn't handle the general case. */ -#ifdef HAVE_CAP_NG_H - /* We are running as root and we will be writing to savefile */ - if ((getuid() == 0 || geteuid() == 0) && WFileName) { + if (getuid() == 0 || geteuid() == 0) { +#ifdef HAVE_LIBCAP_NG + /* Initialize capng */ + capng_clear(CAPNG_SELECT_BOTH); if (username) { - /* Drop all capabilities from effective set */ - capng_clear(CAPNG_EFFECTIVE); - /* Add capabilities we will need*/ - capng_update(CAPNG_ADD, CAPNG_PERMITTED, CAP_SETUID); - capng_update(CAPNG_ADD, CAPNG_PERMITTED, CAP_SETGID); - capng_update(CAPNG_ADD, CAPNG_PERMITTED, CAP_DAC_OVERRIDE); - - capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_SETUID); - capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_SETGID); - capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); - - capng_apply(CAPNG_SELECT_BOTH); + capng_updatev( + CAPNG_ADD, + CAPNG_PERMITTED | CAPNG_EFFECTIVE, + CAP_SETUID, + CAP_SETGID, + -1); } - } -#endif /* HAVE_CAP_NG_H */ - if (getuid() == 0 || geteuid() == 0) { + if (WFileName) { + capng_update( + CAPNG_ADD, + CAPNG_PERMITTED | CAPNG_EFFECTIVE, + CAP_DAC_OVERRIDE + ); + } + capng_apply(CAPNG_SELECT_BOTH); +#endif /* HAVE_LIBCAP_NG */ if (username || chroot_dir) droproot(username, chroot_dir); } #endif /* WIN32 */ if (pcap_setfilter(pd, &fcode) < 0) error("%s", pcap_geterr(pd)); #ifdef HAVE_CAPSICUM if (RFileName == NULL && VFileName == NULL) { static const unsigned long cmds[] = { BIOCGSTATS }; - cap_rights_init(&rights, CAP_IOCTL, CAP_READ); + /* + * The various libpcap devices use a combination of + * read (bpf), ioctl (bpf, netmap), poll (netmap). + * Grant the relevant access rights, sorted by name. + */ + cap_rights_init(&rights, CAP_EVENT, CAP_IOCTL, CAP_READ); if (cap_rights_limit(pcap_fileno(pd), &rights) < 0 && errno != ENOSYS) { error("unable to limit pcap descriptor"); } if (cap_ioctls_limit(pcap_fileno(pd), cmds, sizeof(cmds) / sizeof(cmds[0])) < 0 && errno != ENOSYS) { error("unable to limit ioctls on pcap descriptor"); } } #endif if (WFileName) { pcap_dumper_t *p; /* Do not exceed the default PATH_MAX for files. */ dumpinfo.CurrentFileName = (char *)malloc(PATH_MAX + 1); if (dumpinfo.CurrentFileName == NULL) error("malloc of dumpinfo.CurrentFileName"); /* We do not need numbering for dumpfiles if Cflag isn't set. */ if (Cflag != 0) MakeFilename(dumpinfo.CurrentFileName, WFileName, 0, WflagChars); else MakeFilename(dumpinfo.CurrentFileName, WFileName, 0, 0); p = pcap_dump_open(pd, dumpinfo.CurrentFileName); -#ifdef HAVE_CAP_NG_H - /* Give up capabilities, clear Effective set */ - capng_clear(CAPNG_EFFECTIVE); -#endif +#ifdef HAVE_LIBCAP_NG + /* Give up CAP_DAC_OVERRIDE capability. + * Only allow it to be restored if the -C or -G flag have been + * set since we may need to create more files later on. + */ + capng_update( + CAPNG_DROP, + (Cflag || Gflag ? 0 : CAPNG_PERMITTED) + | CAPNG_EFFECTIVE, + CAP_DAC_OVERRIDE + ); + capng_apply(CAPNG_SELECT_BOTH); +#endif /* HAVE_LIBCAP_NG */ if (p == NULL) error("%s", pcap_geterr(pd)); #ifdef HAVE_CAPSICUM - cap_rights_init(&rights, CAP_SEEK, CAP_WRITE); - if (cap_rights_limit(fileno(pcap_dump_file(p)), &rights) < 0 && - errno != ENOSYS) { - error("unable to limit dump descriptor"); - } + set_dumper_capsicum_rights(p); #endif if (Cflag != 0 || Gflag != 0) { #ifdef HAVE_CAPSICUM dumpinfo.WFileName = strdup(basename(WFileName)); dumpinfo.dirfd = open(dirname(WFileName), O_DIRECTORY | O_RDONLY); if (dumpinfo.dirfd < 0) { error("unable to open directory %s", dirname(WFileName)); } cap_rights_init(&rights, CAP_CREATE, CAP_FCNTL, CAP_FTRUNCATE, CAP_LOOKUP, CAP_SEEK, CAP_WRITE); if (cap_rights_limit(dumpinfo.dirfd, &rights) < 0 && errno != ENOSYS) { error("unable to limit directory rights"); } + if (cap_fcntls_limit(dumpinfo.dirfd, CAP_FCNTL_GETFL) < 0 && + errno != ENOSYS) { + error("unable to limit dump descriptor fcntls"); + } #else /* !HAVE_CAPSICUM */ dumpinfo.WFileName = WFileName; #endif callback = dump_packet_and_trunc; dumpinfo.pd = pd; dumpinfo.p = p; pcap_userdata = (u_char *)&dumpinfo; } else { callback = dump_packet; pcap_userdata = (u_char *)p; } #ifdef HAVE_PCAP_DUMP_FLUSH if (Uflag) pcap_dump_flush(p); #endif } else { type = pcap_datalink(pd); printinfo = get_print_info(type); callback = print_packet; pcap_userdata = (u_char *)&printinfo; } #ifdef SIGNAL_REQ_INFO /* * We can't get statistics when reading from a file rather * than capturing from a device. */ if (RFileName == NULL) (void)setsignal(SIGNAL_REQ_INFO, requestinfo); #endif if (vflag > 0 && WFileName) { /* * When capturing to a file, "-v" means tcpdump should, * every 10 secodns, "v"erbosely report the number of * packets captured. */ #ifdef USE_WIN32_MM_TIMER /* call verbose_stats_dump() each 1000 +/-100msec */ timer_id = timeSetEvent(1000, 100, verbose_stats_dump, 0, TIME_PERIODIC); setvbuf(stderr, NULL, _IONBF, 0); #elif defined(HAVE_ALARM) (void)setsignal(SIGALRM, verbose_stats_dump); alarm(1); #endif } #ifndef 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 (!vflag && !WFileName) { (void)fprintf(stderr, "%s: verbose output suppressed, use -v or -vv for full protocol decode\n", program_name); } else (void)fprintf(stderr, "%s: ", program_name); dlt = pcap_datalink(pd); dlt_name = pcap_datalink_val_to_name(dlt); if (dlt_name == NULL) { (void)fprintf(stderr, "listening on %s, link-type %u, capture size %u bytes\n", device, dlt, snaplen); } else { (void)fprintf(stderr, "listening on %s, link-type %s (%s), capture size %u bytes\n", device, dlt_name, pcap_datalink_val_to_description(dlt), snaplen); } (void)fflush(stderr); } #endif /* WIN32 */ #ifdef __FreeBSD__ cansandbox = (VFileName == NULL && zflag == NULL); #ifdef HAVE_CAPSICUM cansandbox = (cansandbox && (nflag || capdns != NULL)); #else cansandbox = (cansandbox && nflag); #endif if (cansandbox && cap_enter() < 0 && errno != ENOSYS) error("unable to enter the capability mode"); #endif /* __FreeBSD__ */ 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) { 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 (WFileName && new_dlt != dlt) error("%s: new dlt does not match original", RFileName); printinfo = get_print_info(new_dlt); dlt_name = pcap_datalink_val_to_name(new_dlt); if (dlt_name == NULL) { fprintf(stderr, "reading from file %s, link-type %u\n", RFileName, new_dlt); } else { fprintf(stderr, "reading from file %s, link-type %s (%s)\n", RFileName, dlt_name, pcap_datalink_val_to_description(new_dlt)); } if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0) error("%s", pcap_geterr(pd)); if (pcap_setfilter(pd, &fcode) < 0) error("%s", pcap_geterr(pd)); } } } while (ret != NULL); free(cmdbuf); exit(status == -1 ? 1 : 0); } /* make a clean exit on interrupts */ static RETSIGTYPE cleanup(int signo _U_) { #ifdef USE_WIN32_MM_TIMER if (timer_id) timeKillEvent(timer_id); timer_id = 0; #elif defined(HAVE_ALARM) alarm(0); #endif #ifdef HAVE_PCAP_BREAKLOOP /* * We have "pcap_breakloop()"; use it, so that we do as little * as possible in the signal handler (it's probably not safe * to do anything with standard I/O streams in a signal handler - * the ANSI C standard doesn't say it is). */ pcap_breakloop(pd); #else /* * We don't have "pcap_breakloop()"; this isn't safe, but * it's the best we can do. Print the summary if we're * not reading from a savefile - i.e., if we're doing a * live capture - and exit. */ if (pd != NULL && pcap_file(pd) == NULL) { /* * We got interrupted, so perhaps we didn't * manage to finish a line we were printing. * Print an extra newline, just in case. */ putchar('\n'); (void)fflush(stdout); info(1); } exit(0); #endif } /* On windows, we do not use a fork, so we do not care less about waiting a child processes to die */ #if defined(HAVE_FORK) || defined(HAVE_VFORK) static RETSIGTYPE child_cleanup(int signo _U_) { wait(NULL); } #endif /* HAVE_FORK && HAVE_VFORK */ static void info(register int verbose) { struct pcap_stat stat; /* * Older versions of libpcap didn't set ps_ifdrop on some * platforms; initialize it to 0 to handle that. */ stat.ps_ifdrop = 0; if (pcap_stats(pd, &stat) < 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", stat.ps_recv, PLURAL_SUFFIX(stat.ps_recv)); if (!verbose) fputs(", ", stderr); else putc('\n', stderr); (void)fprintf(stderr, "%u packet%s dropped by kernel", stat.ps_drop, PLURAL_SUFFIX(stat.ps_drop)); if (stat.ps_ifdrop != 0) { if (!verbose) fputs(", ", stderr); else putc('\n', stderr); (void)fprintf(stderr, "%u packet%s dropped by interface\n", stat.ps_ifdrop, PLURAL_SUFFIX(stat.ps_ifdrop)); } else putc('\n', stderr); infoprint = 0; } #if defined(HAVE_FORK) || defined(HAVE_VFORK) static void compress_savefile(const char *filename) { # ifdef HAVE_FORK if (fork()) # else if (vfork()) # endif return; /* * 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): %s\n", zflag, filename, strerror(errno)); # ifdef HAVE_FORK exit(1); # else _exit(1); # endif } #else /* HAVE_FORK && HAVE_VFORK */ static void compress_savefile(const char *filename) { fprintf(stderr, "compress_savefile failed. Functionality not implemented under your system\n"); } #endif /* HAVE_FORK && HAVE_VFORK */ static void dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) { struct dump_info *dump_info; -#ifdef HAVE_CAPSICUM - cap_rights_t rights; -#endif ++packets_captured; ++infodelay; dump_info = (struct dump_info *)user; /* * XXX - this won't force the file to rotate on the specified time * boundary, but it will rotate on the first packet received after the * specified Gflag number of seconds. Note: if a Gflag time boundary * and a Cflag size boundary coincide, the time rotation will occur * first thereby cancelling the Cflag boundary (since the file should * be 0). */ if (Gflag != 0) { /* Check if it is time to rotate */ time_t t; /* Get the current time */ if ((t = time(NULL)) == (time_t)-1) { error("dump_and_trunc_packet: can't get current_time: %s", pcap_strerror(errno)); } /* If the time is greater than the specified window, rotate */ if (t - Gflag_time >= Gflag) { #ifdef HAVE_CAPSICUM FILE *fp; int fd; #endif /* Update the Gflag_time */ Gflag_time = t; /* Update Gflag_count */ Gflag_count++; /* * Close the current file and open a new one. */ pcap_dump_close(dump_info->p); /* * Compress the file we just closed, if the user asked for it */ if (zflag != NULL) compress_savefile(dump_info->CurrentFileName); /* * Check to see if we've exceeded the Wflag (when * not using Cflag). */ if (Cflag == 0 && Wflag > 0 && Gflag_count >= Wflag) { (void)fprintf(stderr, "Maximum file limit reached: %d\n", Wflag); exit(0); /* NOTREACHED */ } if (dump_info->CurrentFileName != NULL) free(dump_info->CurrentFileName); /* Allocate space for max filename + \0. */ dump_info->CurrentFileName = (char *)malloc(PATH_MAX + 1); if (dump_info->CurrentFileName == NULL) error("dump_packet_and_trunc: malloc"); /* * Gflag was set otherwise we wouldn't be here. Reset the count * so multiple files would end with 1,2,3 in the filename. * The counting is handled with the -C flow after this. */ Cflag_count = 0; /* * This is always the first file in the Cflag * rotation: e.g. 0 * We also don't need numbering if Cflag is not set. */ if (Cflag != 0) MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, 0, WflagChars); else MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, 0, 0); -#ifdef HAVE_CAP_NG_H +#ifdef HAVE_LIBCAP_NG capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); - capng_apply(CAPNG_EFFECTIVE); -#endif /* HAVE_CAP_NG_H */ + capng_apply(CAPNG_SELECT_BOTH); +#endif /* HAVE_LIBCAP_NG */ #ifdef HAVE_CAPSICUM fd = openat(dump_info->dirfd, dump_info->CurrentFileName, O_CREAT | O_WRONLY | O_TRUNC, 0644); if (fd < 0) { error("unable to open file %s", dump_info->CurrentFileName); } fp = fdopen(fd, "w"); if (fp == NULL) { error("unable to fdopen file %s", dump_info->CurrentFileName); } dump_info->p = pcap_dump_fopen(dump_info->pd, fp); #else /* !HAVE_CAPSICUM */ dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName); #endif -#ifdef HAVE_CAP_NG_H +#ifdef HAVE_LIBCAP_NG capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); - capng_apply(CAPNG_EFFECTIVE); -#endif /* HAVE_CAP_NG_H */ + capng_apply(CAPNG_SELECT_BOTH); +#endif /* HAVE_LIBCAP_NG */ if (dump_info->p == NULL) error("%s", pcap_geterr(pd)); #ifdef HAVE_CAPSICUM - cap_rights_init(&rights, CAP_SEEK, CAP_WRITE); - if (cap_rights_limit(fileno(pcap_dump_file(dump_info->p)), - &rights) < 0 && errno != ENOSYS) { - error("unable to limit dump descriptor"); - } + set_dumper_capsicum_rights(dump_info->p); #endif } } /* * XXX - this won't prevent capture files from getting * larger than Cflag - the last packet written to the * file could put it over Cflag. */ - if (Cflag != 0 && pcap_dump_ftell(dump_info->p) > Cflag) { + if (Cflag != 0) { + long size = pcap_dump_ftell(dump_info->p); + + if (size == -1) + error("ftell fails on output file"); + if (size > Cflag) { #ifdef HAVE_CAPSICUM - FILE *fp; - int fd; + FILE *fp; + int fd; #endif - /* - * Close the current file and open a new one. - */ - pcap_dump_close(dump_info->p); + /* + * Close the current file and open a new one. + */ + pcap_dump_close(dump_info->p); - /* - * Compress the file we just closed, if the user asked for it - */ - if (zflag != NULL) - compress_savefile(dump_info->CurrentFileName); + /* + * Compress the file we just closed, if the user + * asked for it. + */ + if (zflag != NULL) + compress_savefile(dump_info->CurrentFileName); - Cflag_count++; - if (Wflag > 0) { - if (Cflag_count >= Wflag) - Cflag_count = 0; - } - if (dump_info->CurrentFileName != NULL) - free(dump_info->CurrentFileName); - dump_info->CurrentFileName = (char *)malloc(PATH_MAX + 1); - if (dump_info->CurrentFileName == NULL) - error("dump_packet_and_trunc: malloc"); - MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, Cflag_count, WflagChars); + Cflag_count++; + if (Wflag > 0) { + if (Cflag_count >= Wflag) + Cflag_count = 0; + } + if (dump_info->CurrentFileName != NULL) + free(dump_info->CurrentFileName); + dump_info->CurrentFileName = (char *)malloc(PATH_MAX + 1); + if (dump_info->CurrentFileName == NULL) + error("dump_packet_and_trunc: malloc"); + MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, Cflag_count, WflagChars); +#ifdef HAVE_LIBCAP_NG + capng_update(CAPNG_ADD, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); + capng_apply(CAPNG_SELECT_BOTH); +#endif /* HAVE_LIBCAP_NG */ #ifdef HAVE_CAPSICUM - fd = openat(dump_info->dirfd, dump_info->CurrentFileName, - O_CREAT | O_WRONLY | O_TRUNC, 0644); - if (fd < 0) { - error("unable to open file %s", - dump_info->CurrentFileName); - } - fp = fdopen(fd, "w"); - if (fp == NULL) { - error("unable to fdopen file %s", - dump_info->CurrentFileName); - } - dump_info->p = pcap_dump_fopen(dump_info->pd, fp); + fd = openat(dump_info->dirfd, dump_info->CurrentFileName, + O_CREAT | O_WRONLY | O_TRUNC, 0644); + if (fd < 0) { + error("unable to open file %s", + dump_info->CurrentFileName); + } + fp = fdopen(fd, "w"); + if (fp == NULL) { + error("unable to fdopen file %s", + dump_info->CurrentFileName); + } + dump_info->p = pcap_dump_fopen(dump_info->pd, fp); #else /* !HAVE_CAPSICUM */ - dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName); + dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName); #endif - if (dump_info->p == NULL) - error("%s", pcap_geterr(pd)); +#ifdef HAVE_LIBCAP_NG + capng_update(CAPNG_DROP, CAPNG_EFFECTIVE, CAP_DAC_OVERRIDE); + capng_apply(CAPNG_SELECT_BOTH); +#endif /* HAVE_LIBCAP_NG */ + if (dump_info->p == NULL) + error("%s", pcap_geterr(pd)); #ifdef HAVE_CAPSICUM - cap_rights_init(&rights, CAP_SEEK, CAP_WRITE); - if (cap_rights_limit(fileno(pcap_dump_file(dump_info->p)), - &rights) < 0 && errno != ENOSYS) { - error("unable to limit dump descriptor"); - } + set_dumper_capsicum_rights(dump_info->p); #endif + } } pcap_dump((u_char *)dump_info->p, h, sp); #ifdef HAVE_PCAP_DUMP_FLUSH if (Uflag) pcap_dump_flush(dump_info->p); #endif --infodelay; if (infoprint) info(0); } static void dump_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) { ++packets_captured; ++infodelay; pcap_dump(user, h, sp); #ifdef HAVE_PCAP_DUMP_FLUSH if (Uflag) pcap_dump_flush((pcap_dumper_t *)user); #endif --infodelay; if (infoprint) info(0); } static void print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) { struct print_info *print_info; u_int hdrlen; netdissect_options *ndo; ++packets_captured; ++infodelay; print_info = (struct print_info *)user; ndo = print_info->ndo; if(ndo->ndo_packet_number) ND_PRINT((ndo, "%5u ", packets_captured)); ts_print(ndo, &h->ts); /* * Some printers want to check that they're not walking off the * end of the packet. - * Rather than pass it all the way down, we set this global. + * Rather than pass it all the way down, we set this member + * of the netdissect_options structure. */ ndo->ndo_snapend = sp + h->caplen; if(print_info->ndo_type) { hdrlen = (*print_info->p.ndo_printer)(print_info->ndo, h, sp); } else { hdrlen = (*print_info->p.printer)(h, sp); } + /* + * Restore the original snapend, as a printer might have + * changed it. + */ + ndo->ndo_snapend = sp + h->caplen; if (ndo->ndo_Xflag) { /* * Print the raw packet data in hex and ASCII. */ if (ndo->ndo_Xflag > 1) { /* * Include the link-layer header. */ hex_and_ascii_print(ndo, "\n\t", sp, h->caplen); } else { /* * Don't include the link-layer header - and if * we have nothing past the link-layer header, * print nothing. */ if (h->caplen > hdrlen) hex_and_ascii_print(ndo, "\n\t", sp + hdrlen, h->caplen - hdrlen); } } else if (ndo->ndo_xflag) { /* * Print the raw packet data in hex. */ if (ndo->ndo_xflag > 1) { /* * Include the link-layer header. */ hex_print(ndo, "\n\t", sp, h->caplen); } else { /* * Don't include the link-layer header - and if * we have nothing past the link-layer header, * print nothing. */ if (h->caplen > hdrlen) hex_print(ndo, "\n\t", sp + hdrlen, h->caplen - hdrlen); } } else if (ndo->ndo_Aflag) { /* * Print the raw packet data in ASCII. */ if (ndo->ndo_Aflag > 1) { /* * Include the link-layer header. */ ascii_print(ndo, sp, h->caplen); } else { /* * Don't include the link-layer header - and if * we have nothing past the link-layer header, * print nothing. */ if (h->caplen > hdrlen) ascii_print(ndo, sp + hdrlen, h->caplen - hdrlen); } } putchar('\n'); --infodelay; if (infoprint) info(0); } #ifdef WIN32 /* * XXX - there should really be libpcap calls to get the version * number as a string (the string would be generated from #defines * at run time, so that it's not generated from string constants * in the library, as, on many UNIX systems, those constants would * be statically linked into the application executable image, and * would thus reflect the version of libpcap on the system on * which the application was *linked*, not the system on which it's * *running*. * * That routine should be documented, unlike the "version[]" * string, so that UNIX vendors providing their own libpcaps * don't omit it (as a couple of vendors have...). * * Packet.dll should perhaps also export a routine to return the * version number of the Packet.dll code, to supply the * "Wpcap_version" information on Windows. */ char WDversion[]="current-git.tcpdump.org"; #if !defined(HAVE_GENERATED_VERSION) char version[]="current-git.tcpdump.org"; #endif char pcap_version[]="current-git.tcpdump.org"; char Wpcap_version[]="3.1"; #endif /* * 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 identation string */ + hex_and_ascii_print(ndo, "\n\t", bp, length); /* pass on lf and indentation string */ } void default_print(const u_char *bp, u_int length) { ndo_default_print(gndo, bp, length); } #ifdef SIGNAL_REQ_INFO RETSIGTYPE requestinfo(int signo _U_) { if (infodelay) ++infoprint; else info(0); } #endif /* * Called once each second in verbose mode while dumping to file */ #ifdef USE_WIN32_MM_TIMER void CALLBACK verbose_stats_dump (UINT timer_id _U_, UINT msg _U_, DWORD_PTR arg _U_, DWORD_PTR dw1 _U_, DWORD_PTR dw2 _U_) { struct pcap_stat stat; if (infodelay == 0 && pcap_stats(pd, &stat) >= 0) fprintf(stderr, "Got %u\r", packets_captured); } #elif defined(HAVE_ALARM) static void verbose_stats_dump(int sig _U_) { struct pcap_stat stat; if (infodelay == 0 && pcap_stats(pd, &stat) >= 0) fprintf(stderr, "Got %u\r", packets_captured); alarm(1); } #endif USES_APPLE_DEPRECATED_API static void print_version(void) { extern char version[]; #ifndef HAVE_PCAP_LIB_VERSION #if defined(WIN32) || defined(HAVE_PCAP_VERSION) extern char pcap_version[]; #else /* defined(WIN32) || defined(HAVE_PCAP_VERSION) */ static char pcap_version[] = "unknown"; #endif /* defined(WIN32) || defined(HAVE_PCAP_VERSION) */ #endif /* HAVE_PCAP_LIB_VERSION */ #ifdef HAVE_PCAP_LIB_VERSION #ifdef WIN32 (void)fprintf(stderr, "%s version %s, based on tcpdump version %s\n", program_name, WDversion, version); #else /* WIN32 */ (void)fprintf(stderr, "%s version %s\n", program_name, version); #endif /* WIN32 */ (void)fprintf(stderr, "%s\n",pcap_lib_version()); #else /* HAVE_PCAP_LIB_VERSION */ #ifdef WIN32 (void)fprintf(stderr, "%s version %s, based on tcpdump version %s\n", program_name, WDversion, version); (void)fprintf(stderr, "WinPcap version %s, based on libpcap version %s\n",Wpcap_version, pcap_version); #else /* WIN32 */ (void)fprintf(stderr, "%s version %s\n", program_name, version); (void)fprintf(stderr, "libpcap version %s\n", pcap_version); #endif /* WIN32 */ #endif /* HAVE_PCAP_LIB_VERSION */ #if defined(HAVE_LIBCRYPTO) && defined(SSLEAY_VERSION) (void)fprintf (stderr, "%s\n", SSLeay_version(SSLEAY_VERSION)); #endif #ifdef USE_LIBSMI (void)fprintf (stderr, "SMI-library: %s\n", smi_version_string); #endif } USES_APPLE_RST static void print_usage(void) { print_version(); (void)fprintf(stderr, "Usage: %s [-aAbd" D_FLAG "efhH" I_FLAG J_FLAG "KlLnNOpqRStu" U_FLAG "vxX#]" B_FLAG_USAGE " [ -c count ]\n", program_name); (void)fprintf(stderr, "\t\t[ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ]\n"); (void)fprintf(stderr, "\t\t[ -i interface ]" j_FLAG_USAGE " [ -M secret ] [ --number ]\n"); #ifdef HAVE_PCAP_SETDIRECTION (void)fprintf(stderr, "\t\t[ -Q in|out|inout ]\n"); #endif (void)fprintf(stderr, "\t\t[ -r file ] [ -s snaplen ] "); #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION (void)fprintf(stderr, "[ --time-stamp-precision precision ]\n"); (void)fprintf(stderr, "\t\t"); +#endif +#ifdef HAVE_PCAP_SET_IMMEDIATE_MODE + (void)fprintf(stderr, "[ --immediate-mode ] "); #endif (void)fprintf(stderr, "[ -T type ] [ --version ] [ -V file ]\n"); (void)fprintf(stderr, "\t\t[ -w file ] [ -W filecount ] [ -y datalinktype ] [ -z command ]\n"); (void)fprintf(stderr, "\t\t[ -Z user ] [ expression ]\n"); } /* VARARGS */ static void ndo_error(netdissect_options *ndo _U_, const char *fmt, ...) { va_list ap; (void)fprintf(stderr, "%s: ", program_name); va_start(ap, fmt); (void)vfprintf(stderr, fmt, ap); va_end(ap); if (*fmt) { fmt += strlen(fmt); if (fmt[-1] != '\n') (void)fputc('\n', stderr); } exit(1); /* NOTREACHED */ } /* VARARGS */ static void ndo_warning(netdissect_options *ndo _U_, const char *fmt, ...) { va_list ap; (void)fprintf(stderr, "%s: WARNING: ", program_name); va_start(ap, fmt); (void)vfprintf(stderr, fmt, ap); va_end(ap); if (*fmt) { fmt += strlen(fmt); if (fmt[-1] != '\n') (void)fputc('\n', stderr); } } /* * Local Variables: * c-style: whitesmith * c-basic-offset: 8 * End: */ Index: head/contrib/tcpdump/udp.h =================================================================== --- head/contrib/tcpdump/udp.h (revision 285274) +++ head/contrib/tcpdump/udp.h (revision 285275) @@ -1,99 +1,103 @@ /* * 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 { uint16_t uh_sport; /* source port */ uint16_t uh_dport; /* destination port */ uint16_t uh_ulen; /* udp length */ uint16_t uh_sum; /* udp checksum */ }; +#define BOOTPS_PORT 67 /* RFC951 */ +#define BOOTPC_PORT 68 /* RFC951 */ #define TFTP_PORT 69 /*XXX*/ #define KERBEROS_PORT 88 /*XXX*/ #define SUNRPC_PORT 111 /*XXX*/ #define SNMP_PORT 161 /*XXX*/ #define NTP_PORT 123 /*XXX*/ #define SNMPTRAP_PORT 162 /*XXX*/ #define ISAKMP_PORT 500 /*XXX*/ #define SYSLOG_PORT 514 /* rfc3164 */ #define TIMED_PORT 525 /*XXX*/ #define RIP_PORT 520 /*XXX*/ #define LDP_PORT 646 #define AODV_PORT 654 /*XXX*/ #define OLSR_PORT 698 /* rfc3626 */ #define KERBEROS_SEC_PORT 750 /*XXX*/ #define L2TP_PORT 1701 /*XXX*/ #define SIP_PORT 5060 #define ISAKMP_PORT_NATT 4500 /* rfc3948 */ #define ISAKMP_PORT_USER1 7500 /*XXX - nonstandard*/ #define ISAKMP_PORT_USER2 8500 /*XXX - nonstandard*/ #define RX_PORT_LOW 7000 /*XXX*/ #define RX_PORT_HIGH 7009 /*XXX*/ #define NETBIOS_NS_PORT 137 #define NETBIOS_DGRAM_PORT 138 #define CISCO_AUTORP_PORT 496 /*XXX*/ #define RADIUS_PORT 1645 #define RADIUS_NEW_PORT 1812 #define RADIUS_ACCOUNTING_PORT 1646 #define RADIUS_NEW_ACCOUNTING_PORT 1813 +#define RADIUS_COA_PORT 3799 #define HSRP_PORT 1985 /*XXX*/ #define LMP_PORT 701 /* rfc4204 */ #define LWRES_PORT 921 #define VQP_PORT 1589 #define ZEPHYR_SRV_PORT 2103 #define ZEPHYR_CLT_PORT 2104 #define VAT_PORT 3456 #define MPLS_LSP_PING_PORT 3503 /* draft-ietf-mpls-lsp-ping-02.txt */ #define BFD_CONTROL_PORT 3784 /* draft-katz-ward-bfd-v4v6-1hop-00.txt */ #define BFD_ECHO_PORT 3785 /* draft-katz-ward-bfd-v4v6-1hop-00.txt */ #define WB_PORT 4567 #define SFLOW_PORT 6343 /* http://www.sflow.org/developers/specifications.php */ -#define LWAPP_DATA_PORT 12222 /* draft-ohara-capwap-lwapp-04.txt */ -#define LWAPP_CONTROL_PORT 12223 /* draft-ohara-capwap-lwapp-04.txt */ +#define LWAPP_DATA_PORT 12222 /* RFC 5412 */ +#define LWAPP_CONTROL_PORT 12223 /* RFC 5412 */ #define OTV_PORT 8472 /* draft-hasmit-otv-04 */ -#define VXLAN_PORT 4789 /* draft-mahalingam-dutt-dcops-vxlan-04 */ +#define VXLAN_PORT 4789 /* RFC 7348 */ +#define GENEVE_PORT 6081 /* draft-gross-geneve-02 */ #ifdef INET6 -#define RIPNG_PORT 521 /*XXX*/ +#define RIPNG_PORT 521 /* RFC 2080 */ #define DHCP6_SERV_PORT 546 /*XXX*/ #define DHCP6_CLI_PORT 547 /*XXX*/ #define AHCP_PORT 5359 /* draft-chroboczek-ahcp-00 */ -#define BABEL_PORT 6696 -#define BABEL_PORT_OLD 6697 +#define BABEL_PORT 6696 /* RFC 6126 errata */ +#define BABEL_PORT_OLD 6697 /* RFC 6126 */ #endif Index: head/contrib/tcpdump/util.c =================================================================== --- head/contrib/tcpdump/util.c (revision 285274) +++ head/contrib/tcpdump/util.c (revision 285275) @@ -1,627 +1,890 @@ /* * 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@juniper.net): + * + * 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. + */ + #define NETDISSECT_REWORKED #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #ifdef HAVE_FCNTL_H #include #endif #include #include #include #include #include "interface.h" /* * Print out a null-terminated filename (or other ascii string). * If ep is NULL, assume no truncation check is needed. * Return true if truncated. */ int fn_print(netdissect_options *ndo, register const u_char *s, register const u_char *ep) { register int ret; register u_char c; ret = 1; /* assume truncated */ while (ep == NULL || s < ep) { c = *s++; if (c == '\0') { ret = 0; break; } if (!ND_ISASCII(c)) { c = ND_TOASCII(c); ND_PRINT((ndo, "M-")); } if (!ND_ISPRINT(c)) { c ^= 0x40; /* DEL to ?, others to alpha */ ND_PRINT((ndo, "^")); } ND_PRINT((ndo, "%c", c)); } return(ret); } /* * Print out a counted filename (or other ascii string). * If ep is NULL, assume no truncation check is needed. * Return true if truncated. */ int fn_printn(netdissect_options *ndo, register const u_char *s, register u_int n, register const u_char *ep) { register u_char c; while (n > 0 && (ep == NULL || s < ep)) { n--; c = *s++; if (!ND_ISASCII(c)) { c = ND_TOASCII(c); ND_PRINT((ndo, "M-")); } if (!ND_ISPRINT(c)) { c ^= 0x40; /* DEL to ?, others to alpha */ ND_PRINT((ndo, "^")); } ND_PRINT((ndo, "%c", c)); } return (n == 0) ? 0 : 1; } /* * Print out a null-padded filename (or other ascii string). * If ep is NULL, assume no truncation check is needed. * Return true if truncated. */ int fn_printzp(netdissect_options *ndo, register const u_char *s, register u_int n, register const u_char *ep) { register int ret; register u_char c; ret = 1; /* assume truncated */ while (n > 0 && (ep == NULL || s < ep)) { n--; c = *s++; if (c == '\0') { ret = 0; break; } if (!ND_ISASCII(c)) { c = ND_TOASCII(c); ND_PRINT((ndo, "M-")); } if (!ND_ISPRINT(c)) { c ^= 0x40; /* DEL to ?, others to alpha */ ND_PRINT((ndo, "^")); } ND_PRINT((ndo, "%c", c)); } return (n == 0) ? 0 : ret; } /* * Format the timestamp */ static char * -ts_format(netdissect_options *ndo, int sec, int usec) +ts_format(netdissect_options *ndo +#ifndef HAVE_PCAP_SET_TSTAMP_PRECISION +_U_ +#endif +, int sec, int usec) { static char buf[sizeof("00:00:00.000000000")]; const char *format; #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION switch (ndo->ndo_tstamp_precision) { case PCAP_TSTAMP_PRECISION_MICRO: format = "%02d:%02d:%02d.%06u"; break; case PCAP_TSTAMP_PRECISION_NANO: format = "%02d:%02d:%02d.%09u"; break; default: format = "%02d:%02d:%02d.{unknown precision}"; break; } #else format = "%02d:%02d:%02d.%06u"; #endif snprintf(buf, sizeof(buf), format, sec / 3600, (sec % 3600) / 60, sec % 60, usec); return buf; } /* * Print the timestamp */ void ts_print(netdissect_options *ndo, register const struct timeval *tvp) { register int s; struct tm *tm; time_t Time; static unsigned b_sec; static unsigned b_usec; int d_usec; int d_sec; switch (ndo->ndo_tflag) { case 0: /* Default */ s = (tvp->tv_sec + thiszone) % 86400; ND_PRINT((ndo, "%s ", ts_format(ndo, s, tvp->tv_usec))); break; case 1: /* No time stamp */ break; case 2: /* Unix timeval style */ ND_PRINT((ndo, "%u.%06u ", (unsigned)tvp->tv_sec, (unsigned)tvp->tv_usec)); break; case 3: /* Microseconds since previous packet */ case 5: /* Microseconds since first packet */ if (b_sec == 0) { /* init timestamp for first packet */ b_usec = tvp->tv_usec; b_sec = tvp->tv_sec; } d_usec = tvp->tv_usec - b_usec; d_sec = tvp->tv_sec - b_sec; while (d_usec < 0) { d_usec += 1000000; d_sec--; } ND_PRINT((ndo, "%s ", ts_format(ndo, d_sec, d_usec))); if (ndo->ndo_tflag == 3) { /* set timestamp for last packet */ b_sec = tvp->tv_sec; b_usec = tvp->tv_usec; } break; case 4: /* Default + Date*/ s = (tvp->tv_sec + thiszone) % 86400; Time = (tvp->tv_sec + thiszone) - s; tm = gmtime (&Time); if (!tm) ND_PRINT((ndo, "Date fail ")); else ND_PRINT((ndo, "%04d-%02d-%02d %s ", tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, ts_format(ndo, s, tvp->tv_usec))); break; } } /* * Print a relative number of seconds (e.g. hold time, prune timer) * in the form 5m1s. This does no truncation, so 32230861 seconds * is represented as 1y1w1d1h1m1s. */ void relts_print(netdissect_options *ndo, int secs) { static const char *lengths[] = {"y", "w", "d", "h", "m", "s"}; static const int seconds[] = {31536000, 604800, 86400, 3600, 60, 1}; const char **l = lengths; const int *s = seconds; if (secs == 0) { ND_PRINT((ndo, "0s")); return; } if (secs < 0) { ND_PRINT((ndo, "-")); secs = -secs; } while (secs > 0) { if (secs >= *s) { ND_PRINT((ndo, "%d%s", secs / *s, *l)); secs -= (secs / *s) * *s; } s++; l++; } } /* * this is a generic routine for printing unknown data; * we pass on the linefeed plus indentation string to * get a proper output - returns 0 on error */ int print_unknown_data(netdissect_options *ndo, const u_char *cp,const char *ident,int len) { if (len < 0) { ND_PRINT((ndo,"%sDissector error: print_unknown_data called with negative length", ident)); return(0); } if (ndo->ndo_snapend - cp < len) len = ndo->ndo_snapend - cp; if (len < 0) { ND_PRINT((ndo,"%sDissector error: print_unknown_data called with pointer past end of packet", ident)); return(0); } hex_print(ndo, ident,cp,len); return(1); /* everything is ok */ } /* * Convert a token value to a string; use "fmt" if not found. */ const char * tok2strbuf(register const struct tok *lp, register const char *fmt, register u_int v, char *buf, size_t bufsize) { if (lp != NULL) { while (lp->s != NULL) { if (lp->v == v) return (lp->s); ++lp; } } if (fmt == NULL) fmt = "#%d"; (void)snprintf(buf, bufsize, fmt, v); return (const char *)buf; } /* * Convert a token value to a string; use "fmt" if not found. */ const char * tok2str(register const struct tok *lp, register const char *fmt, - register int v) + register u_int v) { static char buf[4][128]; static int idx = 0; char *ret; ret = buf[idx]; idx = (idx+1) & 3; return tok2strbuf(lp, fmt, v, ret, sizeof(buf[0])); } /* * Convert a bit token value to a string; use "fmt" if not found. * this is useful for parsing bitfields, the output strings are seperated * if the s field is positive. */ static char * bittok2str_internal(register const struct tok *lp, register const char *fmt, - register int v, register int sep) + register u_int v, const char *sep) { static char buf[256]; /* our stringbuffer */ int buflen=0; - register int rotbit; /* this is the bit we rotate through all bitpositions */ - register int tokval; + register u_int rotbit; /* this is the bit we rotate through all bitpositions */ + register u_int tokval; const char * sepstr = ""; while (lp != NULL && lp->s != NULL) { tokval=lp->v; /* load our first value */ rotbit=1; while (rotbit != 0) { /* * lets AND the rotating bit with our token value * and see if we have got a match */ if (tokval == (v&rotbit)) { /* ok we have found something */ buflen+=snprintf(buf+buflen, sizeof(buf)-buflen, "%s%s", sepstr, lp->s); - sepstr = sep ? ", " : ""; + sepstr = sep; break; } rotbit=rotbit<<1; /* no match - lets shift and try again */ } lp++; } if (buflen == 0) /* bummer - lets print the "unknown" message as advised in the fmt string if we got one */ - (void)snprintf(buf, sizeof(buf), fmt == NULL ? "#%d" : fmt, v); + (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 seperated. */ char * bittok2str_nosep(register const struct tok *lp, register const char *fmt, - register int v) + register u_int v) { - return (bittok2str_internal(lp, fmt, v, 0)); + 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 seperated. */ char * bittok2str(register const struct tok *lp, register const char *fmt, - register int v) + register u_int v) { - return (bittok2str_internal(lp, fmt, v, 1)); + return (bittok2str_internal(lp, fmt, v, ", ")); } /* * Convert a value to a string using an array; the macro * tok2strary() in is the public interface to * this function and ensures that the second argument is * correct for bounds-checking. */ const char * tok2strary_internal(register const char **lp, int n, register const char *fmt, register int v) { static char buf[128]; if (v >= 0 && v < n && lp[v] != NULL) return lp[v]; if (fmt == NULL) fmt = "#%d"; (void)snprintf(buf, sizeof(buf), fmt, v); return (buf); } /* * Convert a 32-bit netmask to prefixlen if possible * the function returns the prefix-len; if plen == -1 * then conversion was not possible; */ int mask2plen(uint32_t mask) { uint32_t bitmasks[33] = { 0x00000000, 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000, 0xff000000, 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff }; int prefix_len = 32; /* let's see if we can transform the mask into a prefixlen */ while (prefix_len >= 0) { if (bitmasks[prefix_len] == mask) break; prefix_len--; } return (prefix_len); } #ifdef INET6 int mask62plen(const u_char *mask) { u_char bitmasks[9] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff }; int byte; int cidr_len = 0; for (byte = 0; byte < 16; byte++) { u_int bits; for (bits = 0; bits < (sizeof (bitmasks) / sizeof (bitmasks[0])); bits++) { if (mask[byte] == bitmasks[bits]) { cidr_len += bits; break; } } if (mask[byte] != 0xff) break; } return (cidr_len); } #endif /* INET6 */ + +/* + * Routine to print out information for text-based protocols such as FTP, + * HTTP, SMTP, RTSP, SIP, .... + */ +#define MAX_TOKEN 128 + +/* + * Fetch a token from a packet, starting at the specified index, + * and return the length of the token. + * + * Returns 0 on error; yes, this is indistinguishable from an empty + * token, but an "empty token" isn't a valid token - it just means + * either a space character at the beginning of the line (this + * includes a blank line) or no more tokens remaining on the line. + */ +static int +fetch_token(netdissect_options *ndo, const u_char *pptr, u_int idx, u_int len, + u_char *tbuf, size_t tbuflen) +{ + size_t toklen = 0; + + for (; idx < len; idx++) { + if (!ND_TTEST(*(pptr + idx))) { + /* ran past end of captured data */ + return (0); + } + if (!isascii(*(pptr + idx))) { + /* not an ASCII character */ + return (0); + } + if (isspace(*(pptr + idx))) { + /* end of token */ + break; + } + if (!isprint(*(pptr + idx))) { + /* not part of a command token or response code */ + return (0); + } + if (toklen + 2 > tbuflen) { + /* no room for this character and terminating '\0' */ + return (0); + } + tbuf[toklen] = *(pptr + idx); + toklen++; + } + if (toklen == 0) { + /* no token */ + return (0); + } + tbuf[toklen] = '\0'; + + /* + * Skip past any white space after the token, until we see + * an end-of-line (CR or LF). + */ + for (; idx < len; idx++) { + if (!ND_TTEST(*(pptr + idx))) { + /* ran past end of captured data */ + break; + } + if (*(pptr + idx) == '\r' || *(pptr + idx) == '\n') { + /* end of line */ + break; + } + if (!isascii(*(pptr + idx)) || !isprint(*(pptr + idx))) { + /* not a printable ASCII character */ + break; + } + if (!isspace(*(pptr + idx))) { + /* beginning of next token */ + break; + } + } + return (idx); +} + +/* + * Scan a buffer looking for a line ending - LF or CR-LF. + * Return the index of the character after the line ending or 0 if + * we encounter a non-ASCII or non-printable character or don't find + * the line ending. + */ +static u_int +print_txt_line(netdissect_options *ndo, const char *protoname, + const char *prefix, const u_char *pptr, u_int idx, u_int len) +{ + u_int startidx; + u_int linelen; + + startidx = idx; + while (idx < len) { + ND_TCHECK(*(pptr+idx)); + if (*(pptr+idx) == '\n') { + /* + * LF without CR; end of line. + * Skip the LF and print the line, with the + * exception of the LF. + */ + linelen = idx - startidx; + idx++; + goto print; + } else if (*(pptr+idx) == '\r') { + /* CR - any LF? */ + if ((idx+1) >= len) { + /* not in this packet */ + return (0); + } + ND_TCHECK(*(pptr+idx+1)); + if (*(pptr+idx+1) == '\n') { + /* + * CR-LF; end of line. + * Skip the CR-LF and print the line, with + * the exception of the CR-LF. + */ + linelen = idx - startidx; + idx += 2; + goto print; + } + + /* + * CR followed by something else; treat this + * as if it were binary data, and don't print + * it. + */ + return (0); + } else if (!isascii(*(pptr+idx)) || + (!isprint(*(pptr+idx)) && *(pptr+idx) != '\t')) { + /* + * Not a printable ASCII character and not a tab; + * treat this as if it were binary data, and + * don't print it. + */ + return (0); + } + idx++; + } + + /* + * All printable ASCII, but no line ending after that point + * in the buffer; treat this as if it were truncated. + */ +trunc: + linelen = idx - startidx; + ND_PRINT((ndo, "%s%.*s[!%s]", prefix, (int)linelen, pptr + startidx, + protoname)); + return (0); + +print: + ND_PRINT((ndo, "%s%.*s", prefix, (int)linelen, pptr + startidx)); + return (idx); +} + +void +txtproto_print(netdissect_options *ndo, const u_char *pptr, u_int len, + const char *protoname, const char **cmds, u_int flags) +{ + u_int idx, eol; + u_char token[MAX_TOKEN+1]; + const char *cmd; + int is_reqresp = 0; + const char *pnp; + + if (cmds != NULL) { + /* + * This protocol has more than just request and + * response lines; see whether this looks like a + * request or response. + */ + idx = fetch_token(ndo, pptr, 0, len, token, sizeof(token)); + if (idx != 0) { + /* Is this a valid request name? */ + while ((cmd = *cmds++) != NULL) { + if (strcasecmp((const char *)token, cmd) == 0) { + /* Yes. */ + is_reqresp = 1; + break; + } + } + + /* + * No - is this a valid response code (3 digits)? + * + * Is this token the response code, or is the next + * token the response code? + */ + if (flags & RESP_CODE_SECOND_TOKEN) { + /* + * Next token - get it. + */ + idx = fetch_token(ndo, pptr, idx, len, token, + sizeof(token)); + } + if (idx != 0) { + if (isdigit(token[0]) && isdigit(token[1]) && + isdigit(token[2]) && token[3] == '\0') { + /* Yes. */ + is_reqresp = 1; + } + } + } + } else { + /* + * This protocol has only request and response lines + * (e.g., FTP, where all the data goes over a + * different connection); assume the payload is + * a request or response. + */ + is_reqresp = 1; + } + + /* Capitalize the protocol name */ + for (pnp = protoname; *pnp != '\0'; pnp++) + ND_PRINT((ndo, "%c", toupper(*pnp))); + + if (is_reqresp) { + /* + * In non-verbose mode, just print the protocol, followed + * by the first line as the request or response info. + * + * In verbose mode, print lines as text until we run out + * of characters or see something that's not a + * printable-ASCII line. + */ + if (ndo->ndo_vflag) { + /* + * We're going to print all the text lines in the + * request or response; just print the length + * on the first line of the output. + */ + ND_PRINT((ndo, ", length: %u", len)); + for (idx = 0; + idx < len && (eol = print_txt_line(ndo, protoname, "\n\t", pptr, idx, len)) != 0; + idx = eol) + ; + } else { + /* + * Just print the first text line. + */ + print_txt_line(ndo, protoname, ": ", pptr, 0, len); + } + } +} /* VARARGS */ void error(const char *fmt, ...) { va_list ap; (void)fprintf(stderr, "%s: ", program_name); va_start(ap, fmt); (void)vfprintf(stderr, fmt, ap); va_end(ap); if (*fmt) { fmt += strlen(fmt); if (fmt[-1] != '\n') (void)fputc('\n', stderr); } exit(1); /* NOTREACHED */ } /* VARARGS */ 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); } } /* * Copy arg vector into a new buffer, concatenating arguments with spaces. */ char * copy_argv(register char **argv) { register char **p; register u_int len = 0; char *buf; char *src, *dst; p = argv; if (*p == 0) return 0; while (*p) len += strlen(*p++) + 1; buf = (char *)malloc(len); if (buf == NULL) error("copy_argv: malloc"); p = argv; dst = buf; while ((src = *p++) != NULL) { while ((*dst++ = *src++) != '\0') ; dst[-1] = ' '; } dst[-1] = '\0'; return buf; } /* * On Windows, we need to open the file in binary mode, so that * we get all the bytes specified by the size we get from "fstat()". * On UNIX, that's not necessary. O_BINARY is defined on Windows; * we define it as 0 if it's not defined, so it does nothing. */ #ifndef O_BINARY #define O_BINARY 0 #endif char * read_infile(char *fname) { register int i, fd, cc; register char *cp; struct stat buf; fd = open(fname, O_RDONLY|O_BINARY); if (fd < 0) error("can't open %s: %s", fname, pcap_strerror(errno)); if (fstat(fd, &buf) < 0) error("can't stat %s: %s", fname, pcap_strerror(errno)); cp = malloc((u_int)buf.st_size + 1); if (cp == NULL) error("malloc(%d) for %s: %s", (u_int)buf.st_size + 1, fname, pcap_strerror(errno)); cc = read(fd, cp, (u_int)buf.st_size); if (cc < 0) error("read %s: %s", fname, pcap_strerror(errno)); if (cc != buf.st_size) error("short read %s (%d != %d)", fname, cc, (int)buf.st_size); close(fd); /* replace "# comment" with spaces */ for (i = 0; i < cc; i++) { if (cp[i] == '#') while (i < cc && cp[i] != '\n') cp[i++] = ' '; } cp[cc] = '\0'; return (cp); } void safeputs(netdissect_options *ndo, const u_char *s, const u_int maxlen) { u_int idx = 0; while (*s && idx < maxlen) { safeputchar(ndo, *s); idx++; s++; } } void safeputchar(netdissect_options *ndo, const u_char c) { ND_PRINT((ndo, (c < 0x80 && ND_ISPRINT(c)) ? "%c" : "\\0x%02x", c)); } #ifdef LBL_ALIGN /* * Some compilers try to optimize memcpy(), using the alignment constraint * on the argument pointer type. by using this function, we try to avoid the * optimization. */ void unaligned_memcpy(void *p, const void *q, size_t l) { memcpy(p, q, l); } /* As with memcpy(), so with memcmp(). */ int unaligned_memcmp(const void *p, const void *q, size_t l) { return (memcmp(p, q, l)); } #endif Index: head/contrib/tcpdump =================================================================== --- head/contrib/tcpdump (revision 285274) +++ head/contrib/tcpdump (revision 285275) Property changes on: head/contrib/tcpdump ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /vendor/tcpdump/dist:r285191 Index: head/usr.sbin/tcpdump/tcpdump/Makefile =================================================================== --- head/usr.sbin/tcpdump/tcpdump/Makefile (revision 285274) +++ head/usr.sbin/tcpdump/tcpdump/Makefile (revision 285275) @@ -1,195 +1,200 @@ # $FreeBSD$ .include TCPDUMP_DISTDIR?= ${.CURDIR}/../../../contrib/tcpdump .PATH: ${TCPDUMP_DISTDIR} PROG= tcpdump SRCS= addrtoname.c \ af.c \ checksum.c \ cpack.c \ gmpls.c \ gmt2local.c \ in_cksum.c \ ipproto.c \ l2vpn.c \ machdep.c \ nlpid.c \ oui.c \ parsenfsfh.c \ print-802_11.c \ print-802_15_4.c \ print-ah.c \ print-ahcp.c \ print-aodv.c \ print-aoe.c \ print-ap1394.c \ print-arcnet.c \ print-arp.c \ print-ascii.c \ print-atalk.c \ print-atm.c \ print-beep.c \ print-bfd.c \ print-bgp.c \ print-bootp.c \ print-bt.c \ print-calm-fast.c \ print-carp.c \ print-cdp.c \ print-cfm.c \ print-chdlc.c \ print-cip.c \ print-cnfp.c \ print-dccp.c \ print-decnet.c \ print-domain.c \ print-dtp.c \ print-dvmrp.c \ print-eap.c \ print-egp.c \ print-eigrp.c \ print-enc.c \ print-esp.c \ print-ether.c \ print-fddi.c \ print-forces.c \ print-fr.c \ + print-ftp.c \ + print-geneve.c \ print-geonet.c \ print-gre.c \ print-hsrp.c \ + print-http.c \ print-icmp.c \ print-igmp.c \ print-igrp.c \ print-ip.c \ + print-ip6.c \ print-ipcomp.c \ print-ipfc.c \ print-ipnet.c \ print-ipx.c \ print-isakmp.c \ print-isoclns.c \ print-juniper.c \ print-krb.c \ print-l2tp.c \ print-lane.c \ print-ldp.c \ print-llc.c \ print-lldp.c \ print-lmp.c \ print-loopback.c \ print-lspping.c \ print-lwapp.c \ print-lwres.c \ print-m3ua.c \ print-mobile.c \ print-mpcp.c \ print-mpls.c \ print-mptcp.c \ print-msdp.c \ print-msnlb.c \ print-nfs.c \ print-ntp.c \ print-null.c \ print-olsr.c \ print-openflow.c \ print-openflow-1.0.c \ print-ospf.c \ print-otv.c \ print-pgm.c \ print-pim.c \ print-pktap.c \ print-ppi.c \ print-ppp.c \ print-pppoe.c \ print-pptp.c \ print-radius.c \ print-raw.c \ print-rip.c \ print-rpki-rtr.c \ print-rrcp.c \ print-rsvp.c \ + print-rtsp.c \ print-rx.c \ print-sctp.c \ print-sflow.c \ print-sip.c \ print-sl.c \ print-sll.c \ print-slow.c \ print-smb.c \ + print-smtp.c \ print-snmp.c \ print-stp.c \ print-sunatm.c \ print-sunrpc.c \ print-symantec.c \ print-syslog.c \ print-tcp.c \ print-telnet.c \ print-tftp.c \ print-timed.c \ print-tipc.c \ print-token.c \ print-udld.c \ print-udp.c \ print-vjc.c \ print-vqp.c \ print-vrrp.c \ print-vtp.c \ print-vxlan.c \ print-wb.c \ print-zephyr.c \ print-zeromq.c \ setsignal.c \ signature.c \ smbutil.c \ tcpdump.c \ util.c \ version.c CLEANFILES+= version.c CFLAGS+= -I${.CURDIR} -I${TCPDUMP_DISTDIR} CFLAGS+= -DHAVE_CONFIG_H CFLAGS+= -D_U_="__attribute__((unused))" .if ${MK_INET6_SUPPORT} != "no" SRCS+= print-babel.c \ print-dhcp6.c \ print-frag6.c \ print-icmp6.c \ - print-ip6.c \ print-ip6opts.c \ print-mobility.c \ print-ospf6.c \ print-ripng.c \ print-rt6.c CFLAGS+= -DINET6 .endif .if ${MACHINE_CPUARCH} != "i386" CFLAGS+= -DLBL_ALIGN .endif LIBADD= l pcap .if ${MK_CASPER} != "no" LIBADD+= capsicum CFLAGS+=-DHAVE_CAPSICUM .endif .if ${MK_OPENSSL} != "no" LIBADD+= crypto CFLAGS+= -I${DESTDIR}/usr/include/openssl CFLAGS+= -DHAVE_LIBCRYPTO -DHAVE_OPENSSL_EVP_H .endif .if ${MK_PF} != "no" SRCS+= print-pflog.c \ print-pfsync.c CFLAGS+= -DHAVE_NET_PFVAR_H .endif version.c: ${TCPDUMP_DISTDIR}/VERSION rm -f version.c ; \ sed 's/.*/char version[] = "&";/' ${TCPDUMP_DISTDIR}/VERSION \ > version.c .include Index: head/usr.sbin/tcpdump/tcpdump/config.h =================================================================== --- head/usr.sbin/tcpdump/tcpdump/config.h (revision 285274) +++ head/usr.sbin/tcpdump/tcpdump/config.h (revision 285275) @@ -1,393 +1,406 @@ /* $FreeBSD$ */ /* This is an edited copy of the config.h generated by configure. */ /* config.h. Generated from config.h.in by configure. */ /* config.h.in. Generated from configure.in by autoheader. */ /* define if you have the addrinfo function */ #define HAVE_ADDRINFO 1 /* Define to 1 if you have the `alarm' function. */ #define HAVE_ALARM 1 /* Define to 1 if you have the `bpf_dump' function. */ #define HAVE_BPF_DUMP 1 /* capsicum support available */ /* See Makefile */ /* #undef HAVE_CAPSICUM */ /* 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_rights_init' function. */ -/* #undef HAVE_CAP_RIGHTS_INIT */ +/* Define to 1 if you have the header file. */ +/* #undef HAVE_CAP_NG_H */ /* Define to 1 if you have the `cap_rights_limit' function. */ #define HAVE_CAP_RIGHTS_LIMIT 1 /* Define to 1 if you have the declaration of `ether_ntohost', and to 0 if you don't. */ #define HAVE_DECL_ETHER_NTOHOST 1 /* define if you have the dnet_htoa function */ /* #undef HAVE_DNET_HTOA */ /* Define to 1 if you have the `ether_ntohost' function. */ #define HAVE_ETHER_NTOHOST 1 /* Define to 1 if you have the 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 `getnameinfo' function. */ #define HAVE_GETNAMEINFO 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 if you have the h_errno variable */ #define HAVE_H_ERRNO 1 /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 +/* Define to 1 if you have the `cap-ng' library (-lcap-ng). */ +/* #undef HAVE_LIBCAP_NG */ + /* Define to 1 if you have the `crypto' library (-lcrypto). */ /* See Makefile */ /* #undef HAVE_LIBCRYPTO */ /* Define to 1 if you have the `rpc' library (-lrpc). */ /* #undef HAVE_LIBRPC */ /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_NETDNET_DNETDB_H */ /* define if you have a dnet_htoa declaration in */ /* #undef HAVE_NETDNET_DNETDB_H_DNET_HTOA */ /* Define to 1 if you have the header file. */ /* #undef HAVE_NETINET_ETHER_H */ /* Define to 1 if you have the header file. */ #define HAVE_NETINET_IF_ETHER_H 1 /* Define to 1 if you have the header file. */ /* See Makefile */ /* #undef HAVE_NET_PFVAR_H */ /* Define to 1 if you have the `openat' function. */ #define HAVE_OPENAT 1 /* Define to 1 if you have the header file. */ /* See Makefile */ /* #undef HAVE_OPENSSL_EVP_H 1 */ /* if there's an os_proto.h for this platform, to use additional prototypes */ /* #undef HAVE_OS_PROTO_H */ /* Define to 1 if you have the header file. */ /* #undef HAVE_PCAP_BLUETOOTH_H */ /* Define to 1 if you have the `pcap_breakloop' function. */ #define HAVE_PCAP_BREAKLOOP 1 /* Define to 1 if you have the `pcap_create' function. */ #define HAVE_PCAP_CREATE 1 /* define if libpcap has pcap_datalink_name_to_val() */ #define HAVE_PCAP_DATALINK_NAME_TO_VAL 1 /* define if libpcap has pcap_datalink_val_to_description() */ #define HAVE_PCAP_DATALINK_VAL_TO_DESCRIPTION 1 /* define if libpcap has pcap_debug */ /* #undef HAVE_PCAP_DEBUG */ /* Define to 1 if you have the `pcap_dump_flush' function. */ #define HAVE_PCAP_DUMP_FLUSH 1 /* define if libpcap has pcap_dump_ftell() */ #define HAVE_PCAP_DUMP_FTELL 1 /* Define to 1 if you have the `pcap_findalldevs' function. */ #define HAVE_PCAP_FINDALLDEVS 1 /* Define to 1 if you have the `pcap_free_datalinks' function. */ #define HAVE_PCAP_FREE_DATALINKS 1 /* Define to 1 if the system has the type `pcap_if_t'. */ #define HAVE_PCAP_IF_T 1 /* Define to 1 if you have the `pcap_lib_version' function. */ #define HAVE_PCAP_LIB_VERSION 1 /* define if libpcap has pcap_list_datalinks() */ #define HAVE_PCAP_LIST_DATALINKS 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_PCAP_NFLOG_H */ /* Define to 1 if you have the `pcap_setdirection' function. */ #define HAVE_PCAP_SETDIRECTION 1 /* Define to 1 if you have the `pcap_set_datalink' function. */ #define HAVE_PCAP_SET_DATALINK 1 +/* Define to 1 if you have the `pcap_set_immediate_mode' function. */ +#define HAVE_PCAP_SET_IMMEDIATE_MODE 1 + /* Define to 1 if you have the `pcap_set_tstamp_precision' function. */ #define HAVE_PCAP_SET_TSTAMP_PRECISION 1 /* Define to 1 if you have the `pcap_set_tstamp_type' function. */ #define HAVE_PCAP_SET_TSTAMP_TYPE 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_PCAP_USB_H */ /* define if libpcap has pcap_version */ /* #undef HAVE_PCAP_VERSION */ /* Define to 1 if you have the `pfopen' function. */ /* #undef HAVE_PFOPEN */ /* Define to 1 if you have the header file. */ #define HAVE_RPC_RPCENT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_RPC_RPC_H 1 /* Define to 1 if you have the `setlinebuf' function. */ #define HAVE_SETLINEBUF 1 /* Define to 1 if you have the `sigaction' function. */ #define HAVE_SIGACTION 1 /* Define to 1 if you have the `sigset' function. */ /* #undef HAVE_SIGSET */ /* Define to 1 if you have the `snprintf' function. */ #define HAVE_SNPRINTF 1 /* if struct sockaddr has the sa_len member */ #define HAVE_SOCKADDR_SA_LEN 1 /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the `strcasecmp' function. */ #define HAVE_STRCASECMP 1 /* Define to 1 if you have the `strdup' function. */ #define HAVE_STRDUP 1 /* Define to 1 if you have the `strftime' function. */ #define HAVE_STRFTIME 1 /* Define to 1 if you have the header file. */ #define HAVE_STRINGS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the `strlcat' function. */ #define HAVE_STRLCAT 1 /* Define to 1 if you have the `strlcpy' function. */ #define HAVE_STRLCPY 1 /* Define to 1 if you have the `strsep' function. */ #define HAVE_STRSEP 1 /* Define to 1 if the system has the type `struct ether_addr'. */ /* #undef HAVE_STRUCT_ETHER_ADDR */ /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H 1 +/* Define to 1 if the system has the type `uintptr_t'. */ +#define HAVE_UINTPTR_T 1 + /* Define to 1 if you have the header file. */ #define HAVE_UNISTD_H 1 /* Define to 1 if you have the `vfork' function. */ #define HAVE_VFORK 1 /* Define to 1 if you have the `vfprintf' function. */ #define HAVE_VFPRINTF 1 /* Define to 1 if you have the `vsnprintf' function. */ #define HAVE_VSNPRINTF 1 /* define if libpcap has yydebug */ /* #undef HAVE_YYDEBUG */ /* define if your compiler has __attribute__ */ #define HAVE___ATTRIBUTE__ 1 /* Define if you enable IPv6 support */ /* See Makefile */ /* #undef INET6 */ /* if unaligned access fails */ /* #undef LBL_ALIGN */ /* define if you need to include missing/addrinfo.h */ /* #undef NEED_ADDRINFO_H */ /* Define to 1 if netinet/ether.h declares `ether_ntohost' */ /* #undef NETINET_ETHER_H_DECLARES_ETHER_NTOHOST */ /* Define to 1 if netinet/if_ether.h declares `ether_ntohost' */ #define NETINET_IF_ETHER_H_DECLARES_ETHER_NTOHOST /**/ /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "" /* Define to the full name of this package. */ #define PACKAGE_NAME "" /* Define to the full name and version of this package. */ #define PACKAGE_STRING "" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "" /* Define to the home page for this package. */ #define PACKAGE_URL "" /* Define to the version of this package. */ #define PACKAGE_VERSION "" /* define if the platform doesn't define PRId64 */ /* #undef PRId64 */ /* define if the platform doesn't define PRIo64 */ /* #undef PRIo64 */ /* define if the platform doesn't define PRIx64 */ /* #undef PRIu64 */ /* define if the platform doesn't define PRIu64 */ /* #undef PRIx64 */ /* Define as the return type of signal handlers (`int' or `void'). */ #define RETSIGTYPE void /* return value of signal handlers */ #define RETSIGVAL /**/ /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* define if you want to build the possibly-buggy SMB printer */ #define TCPDUMP_DO_SMB 1 /* Define to 1 if you can safely include both and . */ #define TIME_WITH_SYS_TIME 1 /* define if you have ether_ntohost() and it works */ #define USE_ETHER_NTOHOST 1 /* Define if you enable support for libsmi */ /* #undef USE_LIBSMI */ /* define if should chroot when dropping privileges */ /* #undef WITH_CHROOT */ /* define if should drop privileges by default */ /* #undef WITH_USER */ /* get BSD semantics on Irix */ /* #undef _BSD_SIGNALS */ /* define on AIX to get certain functions */ /* #undef _SUN */ /* Define for Solaris 2.5.1 so the uint32_t typedef from , , or is not used. If the typedef were allowed, the #define below would cause a syntax error. */ /* #undef _UINT32_T */ /* Define for Solaris 2.5.1 so the uint64_t typedef from , , or is not used. If the typedef were allowed, the #define below would cause a syntax error. */ /* #undef _UINT64_T */ /* Define for Solaris 2.5.1 so the uint8_t typedef from , , or is not used. If the typedef were allowed, the #define below would cause a syntax error. */ /* #undef _UINT8_T */ /* define if your compiler allows __attribute__((format)) without a warning */ #define __ATTRIBUTE___FORMAT_OK 1 /* define if your compiler allows __attribute__((format)) to be applied to function pointers */ #define __ATTRIBUTE___FORMAT_OK_FOR_FUNCTION_POINTERS 1 /* define if your compiler allows __attribute__((noreturn)) to be applied to function pointers */ #define __ATTRIBUTE___NORETURN_OK_FOR_FUNCTION_POINTERS 1 /* to handle Ultrix compilers that don't support const in prototypes */ /* #undef const */ /* Define as token for inline if inlining supported */ #define inline inline /* Define to the type of a signed integer type of width exactly 16 bits if such a type exists and the standard includes do not define it. */ /* #undef int16_t */ /* Define to the type of a signed integer type of width exactly 32 bits if such a type exists and the standard includes do not define it. */ /* #undef int32_t */ /* Define to the type of a signed integer type of width exactly 64 bits if such a type exists and the standard includes do not define it. */ /* #undef int64_t */ /* Define to the type of a signed integer type of width exactly 8 bits if such a type exists and the standard includes do not define it. */ /* #undef int8_t */ /* Define to `uint16_t' if u_int16_t not defined. */ /* #undef u_int16_t */ /* Define to `uint32_t' if u_int32_t not defined. */ /* #undef u_int32_t */ /* Define to `uint64_t' if u_int64_t not defined. */ /* #undef u_int64_t */ /* Define to `uint8_t' if u_int8_t not defined. */ /* #undef u_int8_t */ /* Define to the type of an unsigned integer type of width exactly 16 bits if such a type exists and the standard includes do not define it. */ /* #undef uint16_t */ /* Define to the type of an unsigned integer type of width exactly 32 bits if such a type exists and the standard includes do not define it. */ /* #undef uint32_t */ /* Define to the type of an unsigned integer type of width exactly 64 bits if such a type exists and the standard includes do not define it. */ /* #undef uint64_t */ /* Define to the type of an unsigned integer type of width exactly 8 bits if such a type exists and the standard includes do not define it. */ /* #undef uint8_t */ + +/* Define to the type of an unsigned integer type wide enough to hold a + pointer, if such a type exists, and if the system does not define it. */ +/* #undef uintptr_t */ Index: head/usr.sbin/tcpdump/tcpdump/tcpdump.1 =================================================================== --- head/usr.sbin/tcpdump/tcpdump/tcpdump.1 (revision 285274) +++ head/usr.sbin/tcpdump/tcpdump/tcpdump.1 (revision 285275) @@ -1,1960 +1,1977 @@ .\" $FreeBSD$ .\" $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 "11 July 2014" .SH NAME tcpdump \- dump traffic on a network .SH SYNOPSIS .na .B tcpdump [ .B \-AbdDefhHIJKlLnNOpqRStuUvxX# ] [ .B \-B .I buffer_size ] .br .ti +8 [ .B \-c .I count ] .br .ti +8 [ .B \-C .I file_size ] [ .B \-G .I rotate_seconds ] [ .B \-F .I file ] .br .ti +8 [ .B \-i .I interface ] [ .B \-j .I tstamp_type ] [ .B \-m .I module ] [ .B \-M .I secret ] .br .ti +8 [ .B \-\-number ] [ .B \-Q .I in|out|inout ] .ti +8 [ .B \-r .I file ] [ .B \-V .I file ] [ .B \-s .I snaplen ] [ .B \-T .I type ] [ .B \-w .I file ] .br .ti +8 [ .B \-W .I filecount ] .br .ti +8 [ .B \-E .I spi@ipaddr algo:secret,... ] .br .ti +8 [ .B \-y .I datalinktype ] [ .B \-z .I postrotate-command ] [ .B \-Z .I user ] .ti +8 [ .BI \-\-time\-stamp\-precision= tstamp_precision ] +.ti +8 [ +.B \-\-immediate\-mode +] +[ .B \-\-version ] .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. It can also +network interface that match the boolean \fIexpression\fP; 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 Mac OS X) 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 Mac OS X, 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. +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 Reading packets from a network interface may require that you have special privileges; see the .B 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 \-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. .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, is 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 .B pcap_findalldevs() 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 RFC2406 ESP, not RFC1827 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 which capture is being done. If that address or netmask are not available, available, either because the interface on which capture is being done has no address or netmask or because the capture is being done on the Linux "any" interface, 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. .IP If used in conjunction with the .B \-C option, filenames will take the form of `\fIfile\fP'. .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 on \fIinterface\fP. If unspecified, \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, an .I interface argument of ``any'' can be used to capture packets from all interfaces. Note that captures on the ``any'' device 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. .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 (7); 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. .LP 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. .LP 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 \-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. .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 \-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 .B \-R Assume ESP/AH packets to be based on old specification (RFC1825 to RFC1829). If specified, \fItcpdump\fP will not print replay prevention field. Since there is no protocol version field in ESP/AH specification, \fItcpdump\fP cannot deduce the version of ESP/AH protocol. .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 pcap-ng 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 65535 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. 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. 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 65535, 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), \fBlmp\fR (Link Management Protocol), \fBpgm\fR (Pragmatic General Multicast), \fBpgm_zmtp1\fR (ZMTP/1.0 inside PGM/EPGM), \fBradius\fR (RADIUS), \fBrpc\fR (Remote Procedure Call), \fBrtp\fR (Real-Time Applications protocol), \fBrtcp\fR (Real-Time Applications control protocol), \fBsnmp\fR (Simple Network Management Protocol), \fBtftp\fR (Trivial File Transfer Protocol), \fBvat\fR (Visual Audio Tool), \fBwb\fR (distributed White Board), \fBzmtp1\fR (ZeroMQ Message Transport Protocol 1.0) and \fBvxlan\fR (Virtual eXtensible Local Area Network). .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 an unformatted timestamp on each dump line. +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 (micro-second resolution) between current and previous line on each dump line. .TP .B \-tttt -Print a timestamp in default format proceeded by date on each dump line. +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 (micro-second resolution) between current and first line on each dump line. .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, 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 .B pcap_dump_flush() 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, report, every 10 seconds, the number of packets captured. .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 (5) for a description of the file format. .TP .B \-W 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. If used with .B \-C as well, the behavior will result in cyclical files per timeslice. .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. .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. .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 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 (7). .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 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 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 .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 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, neither this description nor \fItcpdump\fP will be of much use to you.)\fP .LP The general format of a tcp protocol line is: .RS .nf .sp .5 \fIsrc > dst: flags data-seqno ack window urgent options\fP .sp .5 .fi .RE \fISrc\fP and \fIdst\fP are the source and destination IP addresses and ports. \fIFlags\fP are some combination of S (SYN), F (FIN), P (PUSH), R (RST), U (URG), W (ECN CWR), E (ECN-Echo) 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). \fIAck\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. \fIOptions\fP are tcp options enclosed in angle brackets (e.g., ). .LP \fISrc, dst\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 \s-2\f(CWrtsg.1023 > csam.login: S 768512:768512(0) win 4096 csam.login > rtsg.1023: S 947648:947648(0) ack 768513 win 4096 rtsg.1023 > csam.login: . ack 1 win 4096 rtsg.1023 > csam.login: P 1:2(1) ack 1 win 4096 csam.login > rtsg.1023: . ack 2 win 4096 rtsg.1023 > csam.login: P 2:21(19) ack 1 win 4096 csam.login > rtsg.1023: P 1:2(1) ack 21 win 4077 csam.login > rtsg.1023: P 2:3(1) ack 21 win 4077 urg 1 csam.login > rtsg.1023: P 3:4(1) ack 21 win 4077 urg 1\fR\s+2 .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(nbytes)' which means `sequence numbers \fIfirst\fP up to but not including \fIlast\fP which is \fInbytes\fP bytes of user data'.) 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. 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 PUSH 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.) .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 .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-act, tcp-urg. .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 .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 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, not including the 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 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 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, 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 .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 www.cifs.org or the pub/samba/specs/ directory on your favorite samba.org mirror site. The SMB patches were written by Andrew Tridgell (tridge@samba.org). .HD 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 Note that NFS requests are very large and much of the detail won't be printed unless \fIsnaplen\fP is increased. Try using `\fB\-s 192\fP' to watch NFS traffic. .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 .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 Note that AFS requests are very large and many of the arguments won't be printed unless \fIsnaplen\fP is increased. Try using `\fB-s 256\fP' to watch AFS traffic. .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) .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: .RS .nf .sp .5 \s-2\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\s+2 .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: .RS .nf .sp .5 \s-2\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\s+2 .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. .HD IP Fragmentation .LP Fragmented Internet datagrams are printed as .RS .nf .sp .5 \fB(frag \fIid\fB:\fIsize\fB@\fIoffset\fB+)\fR \fB(frag \fIid\fB:\fIsize\fB@\fIoffset\fB)\fR .sp .5 .fi .RE (The first form indicates there are more fragments. The second indicates this is the last fragment.) .LP \fIId\fP is the fragment id. \fISize\fP is the fragment size (in bytes) excluding the IP header. \fIOffset\fP is this fragment's offset (in bytes) in the original datagram. .LP The fragment information is output for each fragment. The first fragment contains the higher level protocol header and the frag info is printed after the protocol info. Fragments after the first contain no higher level protocol header and the frag info is printed after the source and destination addresses. For example, here is part of an ftp from arizona.edu to lbl-rtsg.arpa over a CSNET connection that doesn't appear to handle 576 byte datagrams: .RS .nf .sp .5 \s-2\f(CWarizona.ftp-data > rtsg.1170: . 1024:1332(308) ack 1 win 4096 (frag 595a:328@0+) arizona > rtsg: (frag 595a:204@328) rtsg.1170 > arizona.ftp-data: . ack 1536 win 2560\fP\s+2 .sp .5 .fi .RE There are a couple of things to note here: First, addresses in the 2nd line don't include port numbers. This is because the TCP protocol information is all in the first fragment and we have no idea what the port or sequence numbers are when we print the later fragments. Second, the tcp sequence information in the first line is printed as if there were 308 bytes of user data when, in fact, there are 512 bytes (308 in the first frag and 204 in the second). If you are looking for holes in the sequence space or trying to match up acks with packets, this can fool you. .LP A packet with the IP \fIdon't fragment\fP flag is marked with a trailing \fB(DF)\fP. .HD 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 first saw the packet. No attempt is made to account for the time lag between when the Ethernet interface removed the packet from the wire and when the kernel serviced the `new packet' interrupt. .SH "SEE ALSO" stty(1), pcap(3PCAP), bpf(4), nit(4P), pcap-savefile(5), pcap-filter(7), pcap-tstamp(7) .LP .RS .I http://www.iana.org/assignments/media-types/application/vnd.tcpdump.pcap .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 being maintained by tcpdump.org. .LP The current version is available via http: .LP .RS .I http://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 Eric Young's SSLeay library, under specific configurations. .SH BUGS Please send problems, bugs, questions, desirable enhancements, patches etc. to: .LP .RS tcpdump-workers@lists.tcpdump.org .RE .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 userland, 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.