so far this only handles printing the UDP hellos, it doesnt try to reach
into a TCP stream and print what it finds in there.
output looks like this:
dlg@cpe0 tcpdump$ sudo ./obj/tcpdump -ni vmx1 port ldp
tcpdump: listening on vmx1, link-type EN10MB
12:26:51.700366 192.168.1.24.646 > 224.0.0.2.646: LDP Ident 192.168.0.0:0:
Hello 0: Config Params: Hold time 15 !T, IPv4: 192.168.0.0 [tos 0xc0] [ttl 1]
12:26:52.635598 192.168.1.25.646 > 224.0.0.2.646: LDP Ident 192.168.0.25:0:
Hello 2437: Config Params: Hold time 15 !T, IPv4: 192.168.0.25, Config Seq: 1
[tos 0xc0] [ttl 1]
or:
dlg@cpe0 tcpdump$ sudo ./obj/tcpdump -nvi vmx1 port ldp
tcpdump: listening on vmx1, link-type EN10MB
12:26:21.947034 192.168.1.24.646 > 224.0.0.2.646: [udp sum ok] LDP v1 Ident
192.168.0.0:0: Hello 0: Config Params: Hold time 15 Link hello, IPv4:
192.168.0.0 [tos 0xc0] [ttl 1] (id 0, len 62)
0000: 45c0 003e 0000 0000 0111 172d c0a8 0118 E..>.......-....
0010: e000 0002 0286 0286 002a ce2e 0001 001e .........*......
0020: c0a8 0000 0000 0100 0014 0000 0000 0400 ................
0030: 0004 000f 0000 0401 0004 c0a8 0000 ..............
12:26:32.599582 192.168.1.25.646 > 224.0.0.2.646: LDP Ident 192.168.0.25:0:
Hello 2432 (00000980): Config Params: Hold time 15 !T, IPv4: 192.168.0.25,
Config Seq: 1 [tos 0xc0] [ttl 1]
0000: 45c0 0046 2d37 0000 0111 e9ec c0a8 0119 E..F-7..........
0010: e000 0002 0286 0286 0032 a207 0001 0026 .........2.....&
0020: c0a8 0019 0000 0100 001c 0000 0980 0400 ................
0030: 0004 000f 2000 0401 0004 c0a8 0019 0402 .... ...........
0040: 0004 0000 0001 ......
also part of this is that I wanted a better understanding of the
protocol.
ok?
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 <sys/time.h>
+
+#include <netinet/in.h>
+
+#include <stdio.h>
+#include <stddef.h>
+#include <string.h>
+
+#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)) {