> On 14 Apr 2020, at 8:15 pm, Remi Locherer <remi.loche...@relo.ch> wrote:
> 
> On Tue, Apr 14, 2020 at 01:49:32PM +1000, David Gwynne wrote:
>> 
>> 
>>> On 13 Apr 2020, at 19:03, Remi Locherer <remi.loche...@relo.ch> wrote:
>>> 
>>> Hi,
>>> 
>>> I recently looked into NHRP (RFC 2332) and noticed that our tcpdump does
>>> not have a printer for it. So I added support for NHRP to tcpdump.
>>> 
>>> Initially I was surprised: I expected a simpler protocol! But it is from
>>> the 90's with all the protocols from then in mind (frame relay, ATM, ...).
>>> 
>>> I tested with public available pcap files and compared the output with
>>> wirshark.
>>> https://packetlife.net/captures/protocol/nhrp/
>>> https://www.networkingwithfish.com/fun-in-the-lab-sniffer-tracing-a-dmvpn-tunnel-startup/
>>> 
>>> The output looks like this:
>>> 
>>> 08:34:45.647483 172.16.25.2 > 172.16.15.2: gre NHRP: reg request, id 7 [tos 
>>> 0xc0]
>>> 08:34:45.671422 172.16.15.2 > 172.16.25.2: gre NHRP: reg reply, id 7 [tos 
>>> 0xc0]
>>> 
>>> 08:47:16.138679 172.16.15.2 > 172.16.25.2: gre NHRP: res request, id 6 [tos 
>>> 0xc0]
>>> 08:47:16.148863 172.16.25.2 > 172.16.15.2: gre NHRP: res reply, id 6 [tos 
>>> 0xc0]
>>> 
>>> With -v set:
>>> 
>>> 08:34:45.647483 172.16.25.2 > 172.16.15.2: gre [] 2001 NHRP: reg request, 
>>> id 7, hopcnt 255, src nbma 172.16.25.2, 192.168.0.2 -> 192.168.0.1 (code 0, 
>>> pl 255, mtu 1514, htime 7200, pref 0) [tos 0xc0] (ttl 254, id 22, len 116)
>>> 08:34:45.671422 172.16.15.2 > 172.16.25.2: gre [] 2001 NHRP: reg reply, id 
>>> 7, hopcnt 255, src nbma 172.16.25.2, 192.168.0.2 -> 192.168.0.1 (code 0, pl 
>>> 255, mtu 1514, htime 7200, pref 0) [tos 0xc0] (ttl 255, id 7, len 136)
>>> 
>>> 08:47:16.138679 172.16.15.2 > 172.16.25.2: gre [] 2001 NHRP: res request, 
>>> id 6, hopcnt 254, src nbma 172.16.45.2, 192.168.0.4 -> 192.168.0.2 (code 0, 
>>> pl 0, mtu 1514, htime 7200, pref 0) [tos 0xc0] (ttl 254, id 20, len 116)
>>> 08:47:16.148863 172.16.25.2 > 172.16.15.2: gre [] 2001 NHRP: res reply, id 
>>> 6, hopcnt 255, src nbma 172.16.45.2, 192.168.0.4 -> 192.168.0.2 (code 0, pl 
>>> 32, mtu 1514, htime 7199, pref 0, nbma 172.16.25.2, proto 192.168.0.2) [tos 
>>> 0xc0] (ttl 255, id 31, len 144)
>>> 
>>> Extensions are not parsed and printed.
>>> 
>>> It would be nice to get pcaps with expamles that use address or protocol
>>> combinations other than GRE and IPv4.
>>> 
>>> Comments, OKs?
>> 
>> Can you print the addresses when -v is not set too?
>> 
>> Otherwise I'm keen.
>> 
> 
> Like this?

yes. ok by me.

> tcpdump -n:
> 08:47:16.068855 172.16.25.2 > 172.16.15.2: gre NHRP: res request, id 8, src 
> nbma 172.16.25.2, 192.168.0.2 -> 192.168.0.4 (code 0) [tos 0xc0]
> 08:47:16.150679 172.16.15.2 > 172.16.25.2: gre NHRP: res reply, id 8, src 
> nbma 172.16.25.2, 192.168.0.2 -> 192.168.0.4 (code 0, nbma 172.16.45.2, proto 
> 192.168.0.4) [tos 0xc0]
> 
> tcpdump -nv:
> 08:47:16.068855 172.16.25.2 > 172.16.15.2: gre [] 2001 NHRP: res request, id 
> 8, hopcnt 255, src nbma 172.16.25.2, 192.168.0.2 -> 192.168.0.4 (code 0, pl 
> 0, mtu 1514, htime 7200, pref 0) [tos 0xc0] (ttl 255, id 29, len 96)
> 08:47:16.150679 172.16.15.2 > 172.16.25.2: gre [] 2001 NHRP: res reply, id 8, 
> hopcnt 254, src nbma 172.16.25.2, 192.168.0.2 -> 192.168.0.4 (code 0, pl 32, 
> mtu 1514, htime 7199, pref 0, nbma 172.16.45.2, proto 192.168.0.4) [tos 0xc0] 
> (ttl 254, id 21, len 164)
> 
> 
> 
> Index: Makefile
> ===================================================================
> RCS file: /cvs/src/usr.sbin/tcpdump/Makefile,v
> retrieving revision 1.64
> diff -u -p -r1.64 Makefile
> --- Makefile  3 Dec 2019 01:43:33 -0000       1.64
> +++ Makefile  28 Mar 2020 17:07:22 -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-nhrp.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.83
> diff -u -p -r1.83 interface.h
> --- interface.h       3 Dec 2019 01:43:33 -0000       1.83
> +++ interface.h       28 Mar 2020 17:07:22 -0000
> @@ -217,6 +217,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 nsh_print(const u_char *, u_int);
> +extern void nhrp_print(const u_char *, u_int);
> extern void icmp_print(const u_char *, u_int, const u_char *);
> extern void ieee802_11_if_print(u_char *, const struct pcap_pkthdr *,
>     const u_char *);
> Index: print-ether.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/tcpdump/print-ether.c,v
> retrieving revision 1.37
> diff -u -p -r1.37 print-ether.c
> --- print-ether.c     24 Jan 2020 22:46:36 -0000      1.37
> +++ print-ether.c     28 Mar 2020 17:07:22 -0000
> @@ -303,6 +303,13 @@ recurse:
>               ether_pbb_print(p, length, caplen);
>               return (1);
> 
> +#ifndef ETHERTYPE_NHRP
> +#define ETHERTYPE_NHRP 0x2001
> +#endif
> +     case ETHERTYPE_NHRP:
> +             nhrp_print(p, length);
> +             return (1);
> +
> #ifdef PPP
>       case ETHERTYPE_PPPOEDISC:
>       case ETHERTYPE_PPPOE:
> Index: print-gre.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/tcpdump/print-gre.c,v
> retrieving revision 1.30
> diff -u -p -r1.30 print-gre.c
> --- print-gre.c       24 Jan 2020 22:46:36 -0000      1.30
> +++ print-gre.c       28 Mar 2020 17:07:22 -0000
> @@ -289,6 +289,12 @@ gre_print_0(const u_char *p, u_int lengt
>       case 0x2000:
>               cdp_print(p, length, l, 0);
>               break;
> +#ifndef ETHERTYPE_NHRP
> +#define ETHERTYPE_NHRP 0x2001
> +#endif
> +     case ETHERTYPE_NHRP:
> +             nhrp_print(p, length);
> +             break;
>       default:
>               printf("unknown-proto-%04x", proto);
>       }
> Index: print-nhrp.c
> ===================================================================
> RCS file: print-nhrp.c
> diff -N print-nhrp.c
> --- /dev/null 1 Jan 1970 00:00:00 -0000
> +++ print-nhrp.c      14 Apr 2020 10:02:02 -0000
> @@ -0,0 +1,287 @@
> +/*   $OpenBSD:$ */
> +
> +/*
> + * Copyright (c) 2020 Remi Locherer <r...@openbsd.org>
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +/*
> + * RFC 2332 NBMA Next Hop Resolution Protocol (NHRP)
> + */
> +
> +#include <sys/time.h>
> +#include <sys/uio.h>
> +#include <sys/socket.h>
> +
> +#include <netinet/in.h>
> +#include <netinet/ip.h>
> +#include <arpa/inet.h>
> +
> +#include <net/ethertypes.h>
> +
> +#include <stdio.h>
> +#include <string.h>
> +#include <ctype.h>
> +
> +#include "addrtoname.h"
> +#include "afnum.h"
> +#include "interface.h"
> +#include "extract.h"
> +
> +#define NHRP_VER_RFC2332             1
> +
> +#define NHRP_PKG_RESOLUTION_REQUEST  1
> +#define NHRP_PKG_RESOLUTION_REPLY    2
> +#define NHRP_PKG_REGISTRATION_REQUEST        3
> +#define NHRP_PKG_REGISTRATION_REPLY  4
> +#define NHRP_PKG_PURGE_REQUEST               5
> +#define NHRP_PKG_PURGE_REPLY         6
> +#define NHRP_PKG_ERROR_INDICATION    7
> +
> +
> +struct nhrp_header {
> +     /* fixed header part */
> +     u_int16_t       afn;            /* link layer address */
> +     u_int16_t       pro_type;       /* protocol type (short form) */
> +     u_int8_t        pro_snap[5];    /* protocol type (long form) */
> +     u_int8_t        hopcnt;         /* hop count */
> +     u_int16_t       pktsz;          /* length of the NHRP packet (octets) */
> +     u_int16_t       chksum;         /* IP checksum over the entier packet */
> +     u_int16_t       extoff;         /* extension offset */
> +     u_int8_t        op_version;     /* version of address mapping and
> +                                        management protocol */
> +     u_int8_t        op_type;        /* NHRP packet type */
> +     u_int8_t        shtl;           /* type and length of src NBMA addr */
> +     u_int8_t        sstl;           /* type and length of src NBMA
> +                                        subaddress */
> +     /* mandatory header part */
> +     u_int8_t        spl;            /* src proto len */
> +     u_int8_t        dpl;            /* dst proto len */
> +     u_int16_t       flags;          /* flags */
> +        union {
> +             u_int32_t       id;     /* request id */
> +             struct {                /* error code */
> +                     u_int16_t       code;
> +                     u_int16_t       offset;
> +             } err;
> +     } u;
> +};
> +
> +struct nhrp_cie {
> +     /* client information entrie */
> +     u_int8_t        code;
> +     u_int8_t        plen;
> +     u_int16_t       unused;
> +     u_int16_t       mtu;
> +     u_int16_t       htime;
> +     u_int8_t        cli_addr_tl;
> +     u_int8_t        cli_saddr_tl;
> +     u_int8_t        cli_proto_tl;
> +     u_int8_t        pref;
> +};
> +
> +static const u_char *        nhrp_print_cie(const u_char *, u_int16_t, 
> u_int16_t);
> +
> +
> +void
> +nhrp_print(const u_char *p, u_int length)
> +{
> +     struct nhrp_header      *hdr;
> +     const u_char            *nhrpext, *nhrpend;
> +
> +     printf("NHRP: ");
> +
> +     if ((snapend - p) < sizeof(*hdr))
> +             goto trunc;
> +
> +     hdr = (struct nhrp_header *)p;
> +
> +     if (hdr->op_version != NHRP_VER_RFC2332) {
> +             printf("unknown-version-%02x", hdr->op_version);
> +             return;
> +
> +     }
> +
> +     nhrpext = p + EXTRACT_16BITS(&hdr->extoff);
> +     nhrpend = p + EXTRACT_16BITS(&hdr->pktsz);
> +
> +     switch (hdr->op_type) {
> +     case NHRP_PKG_RESOLUTION_REQUEST:
> +             printf("res request, ");
> +             break;
> +     case NHRP_PKG_RESOLUTION_REPLY:
> +             printf("res reply, ");
> +             break;
> +     case NHRP_PKG_REGISTRATION_REQUEST:
> +             printf("reg request, ");
> +             break;
> +     case NHRP_PKG_REGISTRATION_REPLY:
> +             printf("reg reply, ");
> +             break;
> +     case NHRP_PKG_PURGE_REQUEST:
> +             printf("purge request, ");
> +             break;
> +     case NHRP_PKG_PURGE_REPLY:
> +             printf("purge reply, ");
> +             break;
> +     case NHRP_PKG_ERROR_INDICATION:
> +             printf("error %u", hdr->u.err.code);
> +             return;
> +     default:
> +             printf("unknown-op-type-%04x, ", hdr->op_type);
> +             break;
> +     }
> +
> +     printf("id %u", EXTRACT_32BITS(&hdr->u.id));
> +
> +     if (vflag) {
> +             printf(", hopcnt %u", hdr->hopcnt);
> +
> +             /* most significat bit must be 0 */
> +             if (hdr->shtl & 0x80)
> +                     printf(" (shtl bit 7 set)");
> +
> +             /* check 2nd most significant bit */
> +             if (hdr->shtl & 0x40)
> +                     printf(" (nbma E.154)");
> +     }
> +
> +     p += sizeof(*hdr);
> +     if ((snapend - p) < hdr->shtl)
> +             goto trunc;
> +
> +     if (hdr->shtl) {
> +             switch (EXTRACT_16BITS(&hdr->afn)) {
> +             case AFNUM_INET:
> +                     printf(", src nbma %s", ipaddr_string(p));
> +                     break;
> +             case AFNUM_INET6:
> +                     printf(", src nbma %s", ip6addr_string(p));
> +                     break;
> +             case AFNUM_802:
> +                     printf(", src nbma %s", etheraddr_string(p));
> +                     break;
> +             default:
> +                     printf(", unknown-nbma-addr-family-%04x",
> +                         EXTRACT_16BITS(&hdr->afn));
> +                     break;
> +             }
> +     }
> +
> +     p += hdr->shtl;
> +     if ((snapend - p) < (hdr->spl + hdr->dpl))
> +             goto trunc;
> +
> +     switch (EXTRACT_16BITS(&hdr->pro_type)) {
> +     case ETHERTYPE_IP:
> +             printf(", %s -> %s",
> +                 ipaddr_string(p),
> +                 ipaddr_string(p + hdr->spl));
> +             break;
> +     case ETHERTYPE_IPV6:
> +             printf(", %s -> %s",
> +                 ip6addr_string(p),
> +                 ip6addr_string(p + hdr->spl));
> +             break;
> +     default:
> +             printf(", proto type %04x",
> +                 EXTRACT_16BITS(&hdr->pro_type));
> +             break;
> +     }
> +
> +     p += hdr->spl + hdr->dpl;
> +
> +     do {
> +             p = nhrp_print_cie(p, hdr->afn, hdr->pro_type);
> +             if (p == 0)
> +                     goto trunc;
> +     } while ((hdr->extoff && (p < nhrpext)) ||
> +                 ((!hdr->extoff && (p < nhrpend))));
> +
> +     return;
> +
> +trunc:
> +     printf(" [|nhrp]");
> +
> +}
> +
> +static const u_char *
> +nhrp_print_cie(const u_char *data, u_int16_t afn, u_int16_t pro_type)
> +{
> +     struct nhrp_cie         *cie;
> +     int                      family, type;
> +
> +     if ((snapend - data) < sizeof(*cie))
> +             return (0);
> +
> +     cie = (struct nhrp_cie *)data;
> +
> +     family = EXTRACT_16BITS(&afn);
> +     type = EXTRACT_16BITS(&pro_type);
> +
> +     printf(" (code %d", cie->code);
> +     if (vflag)
> +             printf(", pl %d, mtu %d, htime %d, pref %d", cie->plen,
> +                 EXTRACT_16BITS(&cie->mtu), EXTRACT_16BITS(&cie->htime),
> +                 cie->pref);
> +
> +     /* check 2nd most significant bit */
> +     if (cie->cli_addr_tl & 0x40)
> +             printf(", nbma E.154");
> +
> +     data += sizeof(*cie);
> +     if ((snapend - data) < cie->cli_addr_tl)
> +             return (0);
> +
> +     if (cie->cli_addr_tl) {
> +             switch (family) {
> +             case AFNUM_INET:
> +                     printf(", nbma %s", ipaddr_string(data));
> +                     break;
> +             case AFNUM_INET6:
> +                     printf(", nbma %s", ip6addr_string(data));
> +                     break;
> +             case AFNUM_802:
> +                     printf(", nbma %s", etheraddr_string(data));
> +                     break;
> +             default:
> +                     printf(", unknown-nbma-addr-family-%04x", family);
> +                     break;
> +             }
> +     }
> +     if (cie->cli_saddr_tl)
> +             printf(", unknown-nbma-saddr-family");
> +
> +     data += cie->cli_addr_tl + cie->cli_saddr_tl;
> +     if ((snapend - data) < cie->cli_proto_tl)
> +             return (0);
> +
> +     if (cie->cli_proto_tl) {
> +             switch (type) {
> +             case ETHERTYPE_IP:
> +                     printf(", proto %s", ipaddr_string(data));
> +                     break;
> +             case ETHERTYPE_IPV6:
> +                     printf(", proto %s", ip6addr_string(data));
> +                     break;
> +             default:
> +                     printf(", unknown-proto-family-%04x", type);
> +                     break;
> +             }
> +     }
> +
> +     printf(")");
> +
> +     return (data + cie->cli_proto_tl);
> +}

Reply via email to