1 /* $OpenBSD: print-llc.c,v 1.22 2020/01/24 22:46:37 procter Exp $ */ 2 3 /* 4 * Copyright (c) 1992, 1993, 1994, 1995, 1996, 1997 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that: (1) source code distributions 9 * retain the above copyright notice and this paragraph in its entirety, (2) 10 * distributions including binary code include the above copyright notice and 11 * this paragraph in its entirety in the documentation or other materials 12 * provided with the distribution, and (3) all advertising materials mentioning 13 * features or use of this software display the following acknowledgement: 14 * ``This product includes software developed by the University of California, 15 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 16 * the University nor the names of its contributors may be used to endorse 17 * or promote products derived from this software without specific prior 18 * written permission. 19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 20 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 22 * 23 * Code by Matt Thomas, Digital Equipment Corporation 24 * with an awful lot of hacking by Jeffrey Mogul, DECWRL 25 */ 26 27 #include <sys/time.h> 28 29 #include <netinet/in.h> 30 31 #include <ctype.h> 32 #include <netdb.h> 33 #include <signal.h> 34 #include <stdio.h> 35 #include <string.h> 36 37 #include "interface.h" 38 #include "addrtoname.h" 39 #include "extract.h" /* must come after interface.h */ 40 #include "ethertype.h" 41 42 #include "llc.h" 43 44 static struct tok cmd2str[] = { 45 { LLC_UI, "ui" }, 46 { LLC_TEST, "test" }, 47 { LLC_XID, "xid" }, 48 { LLC_UA, "ua" }, 49 { LLC_DISC, "disc" }, 50 { LLC_DM, "dm" }, 51 { LLC_SABME, "sabme" }, 52 { LLC_FRMR, "frmr" }, 53 { 0, NULL } 54 }; 55 56 /* 57 * Returns non-zero IFF it succeeds in printing the header 58 */ 59 int 60 llc_print(const u_char *p, u_int length, u_int caplen, 61 const u_char *esrc, const u_char *edst) 62 { 63 struct llc llc; 64 u_short et; 65 #if 0 66 u_short control; 67 #endif 68 int ret; 69 70 if (caplen < 3) { 71 printf("[|llc]"); 72 default_print((u_char *)p, caplen); 73 return(0); 74 } 75 76 /* Watch out for possible alignment problems */ 77 memcpy((char *)&llc, (char *)p, min(caplen, sizeof(llc))); 78 79 if (llc.ssap == LLCSAP_GLOBAL && llc.dsap == LLCSAP_GLOBAL) { 80 ipx_print(p, length); 81 return (1); 82 } 83 #ifdef notyet 84 else if (p[0] == 0xf0 && p[1] == 0xf0) 85 netbios_print(p, length); 86 #endif 87 if (llc.ssap == LLCSAP_ISONS && llc.dsap == LLCSAP_ISONS 88 && llc.llcui == LLC_UI) { 89 isoclns_print(p + 3, length - 3, caplen - 3, esrc, edst); 90 return (1); 91 } 92 93 if (llc.ssap == LLCSAP_SNAP && llc.dsap == LLCSAP_SNAP 94 && llc.llcui == LLC_UI) { 95 if (caplen < sizeof(llc)) { 96 printf("[|llc-snap]"); 97 default_print((u_char *)p, caplen); 98 return (0); 99 } 100 101 /* Cisco Discovery Protocol - SNAP & ether type 0x2000 */ 102 if (llc.ethertype[0] == 0x20 && llc.ethertype[1] == 0x00) { 103 cdp_print(p, length, caplen, 8); 104 return (1); 105 } 106 /* Shared Spanning Tree Protocol - SNAP & ether type 0x010b */ 107 if (llc.ethertype[0] == 0x01 && llc.ethertype[1] == 0x0b) { 108 stp_print(p, length); 109 return (1); 110 } 111 112 if (vflag) 113 printf("snap %s ", protoid_string(llc.llcpi)); 114 115 caplen -= sizeof(llc); 116 length -= sizeof(llc); 117 p += sizeof(llc); 118 119 /* This is an encapsulated Ethernet packet */ 120 et = EXTRACT_16BITS(&llc.ethertype[0]); 121 122 /* 123 * Some protocols have special handling if they are 802.3 124 * SNAP encapsulated vs vers II encapsulated. Handle 125 * those special protocols here, and hand the rest to 126 * print-ether.c so we don't have to duplicate 127 * all that code here. 128 */ 129 switch (et) { 130 case ETHERTYPE_ATALK: 131 atalk_print(p, length); 132 ret = 1; 133 break; 134 default: 135 ret = ether_encap_print(et, p, length, caplen); 136 break; 137 } 138 139 if (ret) 140 return (ret); 141 } 142 143 if (llc.ssap == LLCSAP_8021D && llc.dsap == LLCSAP_8021D) { 144 stp_print(p, length); 145 return (1); 146 } 147 148 #if 0 149 if (llc.ssap == 0xf0 && llc.dsap == 0xf0) { 150 /* 151 * we don't actually have a full netbeui parser yet, but the 152 * smb parser can handle many smb-in-netbeui packets, which 153 * is very useful, so we call that 154 */ 155 156 /* 157 * Skip the DSAP and LSAP. 158 */ 159 p += 2; 160 length -= 2; 161 caplen -= 2; 162 163 /* 164 * OK, what type of LLC frame is this? The length 165 * of the control field depends on that - S or I 166 * frames have a two-byte control field, and U frames 167 * have a one-byte control field. 168 */ 169 if ((llc.llcu & LLC_U_FMT) == LLC_U_FMT) { 170 control = llc.llcu; 171 p += 1; 172 length -= 1; 173 caplen -= 1; 174 } else { 175 control = llc.llcis; 176 p += 2; 177 length -= 2; 178 caplen -= 2; 179 } 180 181 netbeui_print(control, p, p + min(caplen, length)); 182 return (1); 183 } 184 #endif 185 186 if ((llc.ssap & ~LLC_GSAP) == llc.dsap) { 187 if (eflag) 188 printf("%s ", llcsap_string(llc.dsap)); 189 else 190 printf("%s > %s %s ", 191 etheraddr_string(esrc), 192 etheraddr_string(edst), 193 llcsap_string(llc.dsap)); 194 } else { 195 if (eflag) 196 printf("%s > %s ", 197 llcsap_string(llc.ssap & ~LLC_GSAP), 198 llcsap_string(llc.dsap)); 199 else 200 printf("%s %s > %s %s ", 201 etheraddr_string(esrc), 202 llcsap_string(llc.ssap & ~LLC_GSAP), 203 etheraddr_string(edst), 204 llcsap_string(llc.dsap)); 205 } 206 207 if ((llc.llcu & LLC_U_FMT) == LLC_U_FMT) { 208 const char *m; 209 char f; 210 m = tok2str(cmd2str, "%02x", LLC_U_CMD(llc.llcu)); 211 switch ((llc.ssap & LLC_GSAP) | (llc.llcu & LLC_U_POLL)) { 212 case 0: f = 'C'; break; 213 case LLC_GSAP: f = 'R'; break; 214 case LLC_U_POLL: f = 'P'; break; 215 case LLC_GSAP|LLC_U_POLL: f = 'F'; break; 216 default: f = '?'; break; 217 } 218 219 printf("%s/%c", m, f); 220 221 if (caplen < 6) { 222 default_print_unaligned(p, caplen); 223 return (0); 224 } 225 p += 3; 226 length -= 3; 227 caplen -= 3; 228 229 if ((llc.llcu & ~LLC_U_POLL) == LLC_XID) { 230 if (*p == LLC_XID_FI) { 231 printf(": %02x %02x", p[1], p[2]); 232 p += 3; 233 length -= 3; 234 caplen -= 3; 235 } 236 } 237 238 #if 0 239 if (!strcmp(m,"ui") && f=='C') { 240 /* 241 * we don't have a proper ipx decoder yet, but there 242 * is a partial one in the smb code 243 */ 244 ipx_netbios_print(p,p+min(caplen,length)); 245 } 246 #endif 247 248 } else { 249 char f; 250 if (caplen < 4) { 251 default_print_unaligned(p, caplen); 252 return (0); 253 } 254 llc.llcis = ntohs(llc.llcis); 255 switch ((llc.ssap & LLC_GSAP) | (llc.llcu & LLC_U_POLL)) { 256 case 0: f = 'C'; break; 257 case LLC_GSAP: f = 'R'; break; 258 case LLC_U_POLL: f = 'P'; break; 259 case LLC_GSAP|LLC_U_POLL: f = 'F'; break; 260 default: f = '?'; break; 261 } 262 263 if ((llc.llcu & LLC_S_FMT) == LLC_S_FMT) { 264 static char *llc_s[] = { "rr", "rej", "rnr", "03" }; 265 printf("%s (r=%d,%c)", 266 llc_s[LLC_S_CMD(llc.llcis)], 267 LLC_IS_NR(llc.llcis), 268 f); 269 } else { 270 printf("I (s=%d,r=%d,%c)", 271 LLC_I_NS(llc.llcis), 272 LLC_IS_NR(llc.llcis), 273 f); 274 } 275 p += 4; 276 length -= 4; 277 caplen -= 4; 278 } 279 printf(" len=%d", length); 280 return(1); 281 } 282