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