Index: Makefile =================================================================== RCS file: /cvs/src/usr.sbin/tcpdump/Makefile,v retrieving revision 1.63 diff -u -p -r1.63 Makefile --- Makefile 3 Feb 2018 13:39:48 -0000 1.63 +++ Makefile 18 Jan 2019 03:17:29 -0000 @@ -48,7 +48,7 @@ SRCS= tcpdump.c addrtoname.c privsep.c p print-bgp.c print-ospf6.c print-ripng.c print-rt6.c print-stp.c \ print-etherip.c print-lwres.c print-lldp.c print-cdp.c print-pflog.c \ print-pfsync.c pf_print_state.c print-ofp.c ofp_map.c \ - print-udpencap.c print-carp.c \ + print-udpencap.c print-carp.c print-ldp.c \ print-802_11.c print-iapp.c print-mpls.c print-slow.c print-usbpcap.c \ gmt2local.c savestr.c setsignal.c in_cksum.c Index: interface.h =================================================================== RCS file: /cvs/src/usr.sbin/tcpdump/interface.h,v retrieving revision 1.79 diff -u -p -r1.79 interface.h --- interface.h 22 Oct 2018 16:12:45 -0000 1.79 +++ interface.h 18 Jan 2019 03:17:29 -0000 @@ -216,6 +216,7 @@ extern void ppp_ether_if_print(u_char *, extern void gre_print(const u_char *, u_int); extern void vxlan_print(const u_char *, u_int); extern void icmp_print(const u_char *, u_int, const u_char *); +extern void ldp_print(uint8_t, const u_char *, u_int); extern void ieee802_11_if_print(u_char *, const struct pcap_pkthdr *, const u_char *); extern void ieee802_11_radio_if_print(u_char *, const struct pcap_pkthdr *, Index: print-ldp.c =================================================================== RCS file: print-ldp.c diff -N print-ldp.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ print-ldp.c 18 Jan 2019 03:17:29 -0000 @@ -0,0 +1,287 @@ +/* $OpenBSD$ */ + +#include + +#include + +#include +#include +#include + +#include "interface.h" +#include "addrtoname.h" +#include "extract.h" + +#ifndef nitems +#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) +#endif + +struct ldp_identifier { + uint8_t router[4]; + uint16_t space; +} __packed; + +struct ldp_pdu_header { + uint16_t ver; + uint16_t len; + /* followed by struct ldp_identifier */ +} __packed; + +struct ldp_tlv_header { + uint16_t type; +#define LDP_TLV_T_U (1U << 15) +#define LDP_TLV_T_F (1U << 14) +#define LDP_TLV_T_MASK (0x3fffU) + uint16_t len; +}; + +struct ldp_tlv_handler { + uint16_t type; + void (*fn)(const u_char *, u_int); +}; + +static int ldp_print_tlvs(const u_char *, u_int, const char *, + const struct ldp_tlv_handler *, unsigned int); +static int ldp_print_tlv(const u_char *, u_int, const char *, + const struct ldp_tlv_handler *, unsigned int); + +static void ldp_print_hello(const u_char *, u_int); + +static const struct ldp_tlv_handler ldp_pdu_tlvs[] = { + { 0x0100, ldp_print_hello }, +}; + +static void ldp_print_hello_common_params(const u_char *, u_int); +static void ldp_print_hello_ipv4_transport(const u_char *, u_int); +static void ldp_print_hello_config_sequence(const u_char *, u_int); +static void ldp_print_hello_ipv6_transport(const u_char *, u_int); + +static const struct ldp_tlv_handler ldp_hello_tlvs[] = { + { 0x0400, ldp_print_hello_common_params }, + { 0x0401, ldp_print_hello_ipv4_transport }, + { 0x0402, ldp_print_hello_config_sequence }, + { 0x0403, ldp_print_hello_ipv6_transport }, +}; + +void +ldp_print(uint8_t proto, const u_char *cp, u_int len) +{ + struct ldp_pdu_header h; + struct ldp_identifier id; + int l; + + l = snapend - cp; + if (l < sizeof(h)) + goto trunc; + + h.ver = EXTRACT_16BITS(cp + offsetof(struct ldp_pdu_header, ver)); + h.len = EXTRACT_16BITS(cp + offsetof(struct ldp_pdu_header, len)); + cp += sizeof(h); + len -= sizeof(h); + l -= sizeof(h); + + printf("LDP "); + if (vflag) + printf("v%u ", h.ver); + + if (h.ver != 1) { + printf("ldp-unknown-version-%04x", h.ver); + return; + } + + if (l < sizeof(id)) + goto trunc; + + memcpy(id.router, cp, sizeof(id.router)); + id.space = EXTRACT_16BITS(cp + + offsetof(struct ldp_identifier, space)); + cp += sizeof(id); + len -= sizeof(id); + l -= sizeof(id); + + printf("Ident %u.%u.%u.%u:%u:", + id.router[0], id.router[1], id.router[2], id.router[3], + id.space); + + if (ldp_print_tlvs(cp, len, " ", + ldp_pdu_tlvs, nitems(ldp_pdu_tlvs)) == -1) + goto trunc; + + return; + +trunc: + printf("[|ldp]"); +} + +static int +ldp_print_tlvs(const u_char *cp, u_int len, const char *next, + const struct ldp_tlv_handler *handlers, unsigned int nhandlers) +{ + const char *sep = " "; + do { + int tlen = ldp_print_tlv(cp, len, sep, handlers, nhandlers); + if (tlen == -1) + return (-1); + + cp += tlen; + len -= tlen; + sep = next; + } while (len > 0); + + return (0); +} + +static int +ldp_print_tlv(const u_char *cp, u_int len, const char *sep, + const struct ldp_tlv_handler *handlers, unsigned int nhandlers) +{ + const struct ldp_tlv_handler *handler; + unsigned int i; + struct ldp_tlv_header h; + uint16_t type; + int l; + + l = snapend - cp; + if (l < sizeof(h)) + return (-1); + + h.type = EXTRACT_16BITS(cp + offsetof(struct ldp_tlv_header, type)); + h.len = EXTRACT_16BITS(cp + offsetof(struct ldp_tlv_header, len)); + cp += sizeof(h); + len -= sizeof(h); + l -= sizeof(h); + + if (l < h.len) + return (-1); + + printf("%s", sep); + + type = h.type & LDP_TLV_T_MASK; + for (i = 0; i < nhandlers; i++) { + handler = &handlers[i]; + if (handler->type == type) { + (*handler->fn)(cp, h.len); + goto done; + } + } + + printf("ldp-unknown-tlv-%04x (%u)", type, h.len); + +done: + return (sizeof(h) + h.len); +} + +static void +ldp_print_hello(const u_char *cp, u_int len) +{ + uint32_t msgid; + + msgid = EXTRACT_32BITS(cp); + cp += sizeof(msgid); + len -= sizeof(msgid); + + printf("Hello %u", msgid); + if (Xflag) + printf(" (%08x)", msgid); + printf(":"); + + ldp_print_tlvs(cp, len, ", ", ldp_hello_tlvs, nitems(ldp_hello_tlvs)); +} + +static void +ldp_print_hello_ipv4_transport(const u_char *cp, u_int len) +{ + printf("IPv4: "); + + if (len != sizeof(struct in_addr)) { + printf("unexpected len %u", len); + return; + } + + printf("%s", ipaddr_string(cp)); +} + +struct ldp_hello_params { + uint16_t hold_time; + uint16_t flags; +#define LDP_HELLO_T (1U << 15) +#define LDP_HELLO_R (1U << 14) +}; + +static void +ldp_print_hello_common_params(const u_char *cp, u_int len) +{ + struct ldp_hello_params params; + + printf("Config Params: "); + + if (len != sizeof(params)) { + printf("unexpected len %u", len); + return; + } + + params.hold_time = EXTRACT_16BITS(cp + + offsetof(struct ldp_hello_params, hold_time)); + params.flags = EXTRACT_16BITS(cp + + offsetof(struct ldp_hello_params, flags)); + + printf("Hold time "); + switch (params.hold_time) { + case 0xffff: + printf("infinite"); + break; + case 0: + printf("15"); + break; + default: + printf("%u", params.hold_time); + break; + } + printf(" "); + + if (vflag) { + if (params.flags & LDP_HELLO_R) + printf("requesting targetd hellos "); + if (params.flags & LDP_HELLO_T) + printf("Largeted hello"); + else + printf("Link hello"); + + } else { + if (params.flags & LDP_HELLO_R) + printf("R"); + if (params.flags & LDP_HELLO_T) + printf("T"); + else + printf("!T"); + } +} + +static void +ldp_print_hello_ipv6_transport(const u_char *cp, u_int len) +{ + printf("IPv6: "); + + if (len != sizeof(struct in6_addr)) { + printf("unexpected len %u", len); + return; + } + + printf("%s", ip6addr_string(cp)); +} + +static void +ldp_print_hello_config_sequence(const u_char *cp, u_int len) +{ + uint32_t seq; + + printf("Config Seq: "); + + if (len != sizeof(seq)) { + printf("unexpected len %u", len); + return; + } + + seq = EXTRACT_32BITS(cp); + printf("%u", seq); +} Index: print-udp.c =================================================================== RCS file: /cvs/src/usr.sbin/tcpdump/print-udp.c,v retrieving revision 1.51 diff -u -p -r1.51 print-udp.c --- print-udp.c 22 Oct 2018 16:12:45 -0000 1.51 +++ print-udp.c 18 Jan 2019 03:17:29 -0000 @@ -297,6 +297,7 @@ rtcp_print(const u_char *hdr, const u_ch #define ISAKMP_PORT 500 /*XXX*/ #define RIP_PORT 520 /*XXX*/ #define TIMED_PORT 525 /*XXX*/ +#define LDP_PORT 646 #define KERBEROS_SEC_PORT 750 /*XXX*/ #define LWRES_PORT 921 #define VQP_PORT 1589 @@ -563,6 +564,8 @@ udp_print(const u_char *bp, u_int length vxlan_print(cp, length); else if (ISPORT(MPLS_PORT)) mpls_print(cp, length); + else if (ISPORT(LDP_PORT)) + ldp_print(IPPROTO_UDP, cp, length); else if (ISPORT(RIPNG_PORT)) ripng_print(cp, length); else if (ISPORT(DHCP6_PORT1) || ISPORT(DHCP6_PORT2)) {