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)) {

Reply via email to