1 /* 2 * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that: (1) source code distributions 7 * retain the above copyright notice and this paragraph in its entirety, (2) 8 * distributions including binary code include the above copyright notice and 9 * this paragraph in its entirety in the documentation or other materials 10 * provided with the distribution, and (3) all advertising materials mentioning 11 * features or use of this software display the following acknowledgement: 12 * ``This product includes software developed by the University of California, 13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14 * the University nor the names of its contributors may be used to endorse 15 * or promote products derived from this software without specific prior 16 * written permission. 17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20 */ 21 22 #include <sys/cdefs.h> 23 #ifndef lint 24 __RCSID("$NetBSD: print-chdlc.c,v 1.11 2024/09/02 16:15:30 christos Exp $"); 25 #endif 26 27 /* \summary: Cisco HDLC printer */ 28 29 #include <config.h> 30 31 #include "netdissect-stdinc.h" 32 33 #include "netdissect.h" 34 #include "addrtoname.h" 35 #include "ethertype.h" 36 #include "extract.h" 37 #include "chdlc.h" 38 #include "nlpid.h" 39 40 static void chdlc_slarp_print(netdissect_options *, const u_char *, u_int); 41 42 static const struct tok chdlc_cast_values[] = { 43 { CHDLC_UNICAST, "unicast" }, 44 { CHDLC_BCAST, "bcast" }, 45 { 0, NULL} 46 }; 47 48 49 /* Standard CHDLC printer */ 50 void 51 chdlc_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) 52 { 53 ndo->ndo_protocol = "chdlc"; 54 ndo->ndo_ll_hdr_len += chdlc_print(ndo, p, h->len); 55 } 56 57 u_int 58 chdlc_print(netdissect_options *ndo, const u_char *p, u_int length) 59 { 60 u_int proto; 61 const u_char *bp = p; 62 63 ndo->ndo_protocol = "chdlc"; 64 if (length < CHDLC_HDRLEN) 65 goto trunc; 66 proto = GET_BE_U_2(p + 2); 67 if (ndo->ndo_eflag) { 68 ND_PRINT("%s, ethertype %s (0x%04x), length %u: ", 69 tok2str(chdlc_cast_values, "0x%02x", GET_U_1(p)), 70 tok2str(ethertype_values, "Unknown", proto), 71 proto, 72 length); 73 } 74 75 length -= CHDLC_HDRLEN; 76 p += CHDLC_HDRLEN; 77 78 switch (proto) { 79 case ETHERTYPE_IP: 80 ip_print(ndo, p, length); 81 break; 82 case ETHERTYPE_IPV6: 83 ip6_print(ndo, p, length); 84 break; 85 case CHDLC_TYPE_SLARP: 86 chdlc_slarp_print(ndo, p, length); 87 break; 88 case ETHERTYPE_MPLS: 89 case ETHERTYPE_MPLS_MULTI: 90 mpls_print(ndo, p, length); 91 break; 92 case ETHERTYPE_ISO: 93 /* is the fudge byte set ? lets verify by spotting ISO headers */ 94 if (length < 2) 95 goto trunc; 96 if (GET_U_1(p + 1) == NLPID_CLNP || 97 GET_U_1(p + 1) == NLPID_ESIS || 98 GET_U_1(p + 1) == NLPID_ISIS) 99 isoclns_print(ndo, p + 1, length - 1); 100 else 101 isoclns_print(ndo, p, length); 102 break; 103 default: 104 if (!ndo->ndo_eflag) 105 ND_PRINT("unknown CHDLC protocol (0x%04x)", proto); 106 break; 107 } 108 109 return (CHDLC_HDRLEN); 110 111 trunc: 112 nd_print_trunc(ndo); 113 return (ND_BYTES_AVAILABLE_AFTER(bp)); 114 } 115 116 /* 117 * The fixed-length portion of a SLARP packet. 118 */ 119 struct cisco_slarp { 120 nd_uint32_t code; 121 #define SLARP_REQUEST 0 122 #define SLARP_REPLY 1 123 #define SLARP_KEEPALIVE 2 124 union { 125 struct { 126 uint8_t addr[4]; 127 uint8_t mask[4]; 128 } addr; 129 struct { 130 nd_uint32_t myseq; 131 nd_uint32_t yourseq; 132 nd_uint16_t rel; 133 } keep; 134 } un; 135 }; 136 137 #define SLARP_MIN_LEN 14 138 #define SLARP_MAX_LEN 18 139 140 static void 141 chdlc_slarp_print(netdissect_options *ndo, const u_char *cp, u_int length) 142 { 143 const struct cisco_slarp *slarp; 144 u_int sec,min,hrs,days; 145 146 ndo->ndo_protocol = "chdlc_slarp"; 147 ND_PRINT("SLARP (length: %u), ",length); 148 if (length < SLARP_MIN_LEN) 149 goto trunc; 150 151 slarp = (const struct cisco_slarp *)cp; 152 ND_TCHECK_LEN(slarp, SLARP_MIN_LEN); 153 switch (GET_BE_U_4(slarp->code)) { 154 case SLARP_REQUEST: 155 ND_PRINT("request"); 156 /* 157 * At least according to William "Chops" Westfield's 158 * message in 159 * 160 * https://web.archive.org/web/20190725151313/www.nethelp.no/net/cisco-hdlc.txt 161 * 162 * the address and mask aren't used in requests - 163 * they're just zero. 164 */ 165 break; 166 case SLARP_REPLY: 167 ND_PRINT("reply %s/%s", 168 GET_IPADDR_STRING(slarp->un.addr.addr), 169 GET_IPADDR_STRING(slarp->un.addr.mask)); 170 break; 171 case SLARP_KEEPALIVE: 172 ND_PRINT("keepalive: mineseen=0x%08x, yourseen=0x%08x, reliability=0x%04x", 173 GET_BE_U_4(slarp->un.keep.myseq), 174 GET_BE_U_4(slarp->un.keep.yourseq), 175 GET_BE_U_2(slarp->un.keep.rel)); 176 177 if (length >= SLARP_MAX_LEN) { /* uptime-stamp is optional */ 178 cp += SLARP_MIN_LEN; 179 sec = GET_BE_U_4(cp) / 1000; 180 min = sec / 60; sec -= min * 60; 181 hrs = min / 60; min -= hrs * 60; 182 days = hrs / 24; hrs -= days * 24; 183 ND_PRINT(", link uptime=%ud%uh%um%us",days,hrs,min,sec); 184 } 185 break; 186 default: 187 ND_PRINT("0x%02x unknown", GET_BE_U_4(slarp->code)); 188 if (ndo->ndo_vflag <= 1) 189 print_unknown_data(ndo,cp+4,"\n\t",length-4); 190 break; 191 } 192 193 if (SLARP_MAX_LEN < length && ndo->ndo_vflag) 194 ND_PRINT(", (trailing junk: %u bytes)", length - SLARP_MAX_LEN); 195 if (ndo->ndo_vflag > 1) 196 print_unknown_data(ndo,cp+4,"\n\t",length-4); 197 return; 198 199 trunc: 200 nd_print_trunc(ndo); 201 } 202