xref: /netbsd-src/external/bsd/tcpdump/dist/print-chdlc.c (revision 26ba0b503b498a5194a71ac319838b7f5497f3fe)
10f74e101Schristos /*
20f74e101Schristos  * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
30f74e101Schristos  *	The Regents of the University of California.  All rights reserved.
40f74e101Schristos  *
50f74e101Schristos  * Redistribution and use in source and binary forms, with or without
60f74e101Schristos  * modification, are permitted provided that: (1) source code distributions
70f74e101Schristos  * retain the above copyright notice and this paragraph in its entirety, (2)
80f74e101Schristos  * distributions including binary code include the above copyright notice and
90f74e101Schristos  * this paragraph in its entirety in the documentation or other materials
100f74e101Schristos  * provided with the distribution, and (3) all advertising materials mentioning
110f74e101Schristos  * features or use of this software display the following acknowledgement:
120f74e101Schristos  * ``This product includes software developed by the University of California,
130f74e101Schristos  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
140f74e101Schristos  * the University nor the names of its contributors may be used to endorse
150f74e101Schristos  * or promote products derived from this software without specific prior
160f74e101Schristos  * written permission.
170f74e101Schristos  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
180f74e101Schristos  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
190f74e101Schristos  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
200f74e101Schristos  */
210f74e101Schristos 
2211b3aaa1Schristos #include <sys/cdefs.h>
230f74e101Schristos #ifndef lint
24*26ba0b50Schristos __RCSID("$NetBSD: print-chdlc.c,v 1.11 2024/09/02 16:15:30 christos Exp $");
250f74e101Schristos #endif
260f74e101Schristos 
27dc860a36Sspz /* \summary: Cisco HDLC printer */
28dc860a36Sspz 
29c74ad251Schristos #include <config.h>
300f74e101Schristos 
31c74ad251Schristos #include "netdissect-stdinc.h"
320f74e101Schristos 
33fdccd7e4Schristos #include "netdissect.h"
340f74e101Schristos #include "addrtoname.h"
350f74e101Schristos #include "ethertype.h"
360f74e101Schristos #include "extract.h"
370f74e101Schristos #include "chdlc.h"
38c74ad251Schristos #include "nlpid.h"
390f74e101Schristos 
40b3a00663Schristos static void chdlc_slarp_print(netdissect_options *, const u_char *, u_int);
410f74e101Schristos 
42870189d2Schristos static const struct tok chdlc_cast_values[] = {
430f74e101Schristos     { CHDLC_UNICAST, "unicast" },
440f74e101Schristos     { CHDLC_BCAST, "bcast" },
450f74e101Schristos     { 0, NULL}
460f74e101Schristos };
470f74e101Schristos 
480f74e101Schristos 
490f74e101Schristos /* Standard CHDLC printer */
50c74ad251Schristos void
51c74ad251Schristos chdlc_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
520f74e101Schristos {
53c74ad251Schristos 	ndo->ndo_protocol = "chdlc";
54c74ad251Schristos 	ndo->ndo_ll_hdr_len += chdlc_print(ndo, p, h->len);
550f74e101Schristos }
560f74e101Schristos 
570f74e101Schristos u_int
58c74ad251Schristos chdlc_print(netdissect_options *ndo, const u_char *p, u_int length)
59ba2ff121Schristos {
600f74e101Schristos 	u_int proto;
6172c96ff3Schristos 	const u_char *bp = p;
620f74e101Schristos 
63c74ad251Schristos 	ndo->ndo_protocol = "chdlc";
6472c96ff3Schristos 	if (length < CHDLC_HDRLEN)
6572c96ff3Schristos 		goto trunc;
66c74ad251Schristos 	proto = GET_BE_U_2(p + 2);
67b3a00663Schristos 	if (ndo->ndo_eflag) {
68c74ad251Schristos                 ND_PRINT("%s, ethertype %s (0x%04x), length %u: ",
69c74ad251Schristos                        tok2str(chdlc_cast_values, "0x%02x", GET_U_1(p)),
700f74e101Schristos                        tok2str(ethertype_values, "Unknown", proto),
710f74e101Schristos                        proto,
72c74ad251Schristos                        length);
730f74e101Schristos 	}
740f74e101Schristos 
750f74e101Schristos 	length -= CHDLC_HDRLEN;
760f74e101Schristos 	p += CHDLC_HDRLEN;
770f74e101Schristos 
780f74e101Schristos 	switch (proto) {
790f74e101Schristos 	case ETHERTYPE_IP:
80b3a00663Schristos 		ip_print(ndo, p, length);
810f74e101Schristos 		break;
820f74e101Schristos 	case ETHERTYPE_IPV6:
83b3a00663Schristos 		ip6_print(ndo, p, length);
840f74e101Schristos 		break;
850f74e101Schristos 	case CHDLC_TYPE_SLARP:
86b3a00663Schristos 		chdlc_slarp_print(ndo, p, length);
870f74e101Schristos 		break;
880f74e101Schristos         case ETHERTYPE_MPLS:
890f74e101Schristos         case ETHERTYPE_MPLS_MULTI:
90b3a00663Schristos                 mpls_print(ndo, p, length);
910f74e101Schristos 		break;
920f74e101Schristos         case ETHERTYPE_ISO:
930f74e101Schristos                 /* is the fudge byte set ? lets verify by spotting ISO headers */
9472c96ff3Schristos                 if (length < 2)
9572c96ff3Schristos                     goto trunc;
96c74ad251Schristos                 if (GET_U_1(p + 1) == NLPID_CLNP ||
97c74ad251Schristos                     GET_U_1(p + 1) == NLPID_ESIS ||
98c74ad251Schristos                     GET_U_1(p + 1) == NLPID_ISIS)
9972c96ff3Schristos                     isoclns_print(ndo, p + 1, length - 1);
1000f74e101Schristos                 else
10172c96ff3Schristos                     isoclns_print(ndo, p, length);
1020f74e101Schristos                 break;
1030f74e101Schristos 	default:
104b3a00663Schristos                 if (!ndo->ndo_eflag)
105c74ad251Schristos                         ND_PRINT("unknown CHDLC protocol (0x%04x)", proto);
1060f74e101Schristos                 break;
1070f74e101Schristos 	}
1080f74e101Schristos 
1090f74e101Schristos 	return (CHDLC_HDRLEN);
11072c96ff3Schristos 
11172c96ff3Schristos trunc:
112c74ad251Schristos 	nd_print_trunc(ndo);
113c74ad251Schristos 	return (ND_BYTES_AVAILABLE_AFTER(bp));
1140f74e101Schristos }
1150f74e101Schristos 
1160f74e101Schristos /*
1170f74e101Schristos  * The fixed-length portion of a SLARP packet.
1180f74e101Schristos  */
1190f74e101Schristos struct cisco_slarp {
120c74ad251Schristos 	nd_uint32_t code;
1210f74e101Schristos #define SLARP_REQUEST	0
1220f74e101Schristos #define SLARP_REPLY	1
1230f74e101Schristos #define SLARP_KEEPALIVE	2
1240f74e101Schristos 	union {
1250f74e101Schristos 		struct {
126b3a00663Schristos 			uint8_t addr[4];
127b3a00663Schristos 			uint8_t mask[4];
1280f74e101Schristos 		} addr;
1290f74e101Schristos 		struct {
130c74ad251Schristos 			nd_uint32_t myseq;
131c74ad251Schristos 			nd_uint32_t yourseq;
132c74ad251Schristos 			nd_uint16_t rel;
1330f74e101Schristos 		} keep;
1340f74e101Schristos 	} un;
1350f74e101Schristos };
1360f74e101Schristos 
1370f74e101Schristos #define SLARP_MIN_LEN	14
1380f74e101Schristos #define SLARP_MAX_LEN	18
1390f74e101Schristos 
1400f74e101Schristos static void
141b3a00663Schristos chdlc_slarp_print(netdissect_options *ndo, const u_char *cp, u_int length)
1420f74e101Schristos {
1430f74e101Schristos 	const struct cisco_slarp *slarp;
1440f74e101Schristos         u_int sec,min,hrs,days;
1450f74e101Schristos 
146c74ad251Schristos 	ndo->ndo_protocol = "chdlc_slarp";
147c74ad251Schristos 	ND_PRINT("SLARP (length: %u), ",length);
1480f74e101Schristos 	if (length < SLARP_MIN_LEN)
1490f74e101Schristos 		goto trunc;
1500f74e101Schristos 
1510f74e101Schristos 	slarp = (const struct cisco_slarp *)cp;
152c74ad251Schristos 	ND_TCHECK_LEN(slarp, SLARP_MIN_LEN);
153c74ad251Schristos 	switch (GET_BE_U_4(slarp->code)) {
1540f74e101Schristos 	case SLARP_REQUEST:
155c74ad251Schristos 		ND_PRINT("request");
1560f74e101Schristos 		/*
1570f74e101Schristos 		 * At least according to William "Chops" Westfield's
1580f74e101Schristos 		 * message in
1590f74e101Schristos 		 *
160c74ad251Schristos 		 *	https://web.archive.org/web/20190725151313/www.nethelp.no/net/cisco-hdlc.txt
1610f74e101Schristos 		 *
1620f74e101Schristos 		 * the address and mask aren't used in requests -
1630f74e101Schristos 		 * they're just zero.
1640f74e101Schristos 		 */
1650f74e101Schristos 		break;
1660f74e101Schristos 	case SLARP_REPLY:
167c74ad251Schristos 		ND_PRINT("reply %s/%s",
168c74ad251Schristos 			GET_IPADDR_STRING(slarp->un.addr.addr),
169c74ad251Schristos 			GET_IPADDR_STRING(slarp->un.addr.mask));
1700f74e101Schristos 		break;
1710f74e101Schristos 	case SLARP_KEEPALIVE:
172c74ad251Schristos 		ND_PRINT("keepalive: mineseen=0x%08x, yourseen=0x%08x, reliability=0x%04x",
173c74ad251Schristos                        GET_BE_U_4(slarp->un.keep.myseq),
174c74ad251Schristos                        GET_BE_U_4(slarp->un.keep.yourseq),
175c74ad251Schristos                        GET_BE_U_2(slarp->un.keep.rel));
1760f74e101Schristos 
1770f74e101Schristos                 if (length >= SLARP_MAX_LEN) { /* uptime-stamp is optional */
1780f74e101Schristos                         cp += SLARP_MIN_LEN;
179c74ad251Schristos                         sec = GET_BE_U_4(cp) / 1000;
1800f74e101Schristos                         min = sec / 60; sec -= min * 60;
1810f74e101Schristos                         hrs = min / 60; min -= hrs * 60;
1820f74e101Schristos                         days = hrs / 24; hrs -= days * 24;
183c74ad251Schristos                         ND_PRINT(", link uptime=%ud%uh%um%us",days,hrs,min,sec);
1840f74e101Schristos                 }
1850f74e101Schristos 		break;
1860f74e101Schristos 	default:
187c74ad251Schristos 		ND_PRINT("0x%02x unknown", GET_BE_U_4(slarp->code));
188b3a00663Schristos                 if (ndo->ndo_vflag <= 1)
189b3a00663Schristos                     print_unknown_data(ndo,cp+4,"\n\t",length-4);
1900f74e101Schristos 		break;
1910f74e101Schristos 	}
1920f74e101Schristos 
193b3a00663Schristos 	if (SLARP_MAX_LEN < length && ndo->ndo_vflag)
194c74ad251Schristos 		ND_PRINT(", (trailing junk: %u bytes)", length - SLARP_MAX_LEN);
195b3a00663Schristos         if (ndo->ndo_vflag > 1)
196b3a00663Schristos             print_unknown_data(ndo,cp+4,"\n\t",length-4);
1970f74e101Schristos 	return;
1980f74e101Schristos 
1990f74e101Schristos trunc:
200c74ad251Schristos 	nd_print_trunc(ndo);
2010f74e101Schristos }
202