1 /* $OpenBSD: print-llc.c,v 1.18 2009/10/27 23:59:55 deraadt 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/param.h> 28 #include <sys/time.h> 29 30 #include <netinet/in.h> 31 32 #include <ctype.h> 33 #include <netdb.h> 34 #include <signal.h> 35 #include <stdio.h> 36 #include <string.h> 37 38 #include "interface.h" 39 #include "addrtoname.h" 40 #include "extract.h" /* must come after interface.h */ 41 #include "ethertype.h" 42 43 #include "llc.h" 44 45 static struct tok cmd2str[] = { 46 { LLC_UI, "ui" }, 47 { LLC_TEST, "test" }, 48 { LLC_XID, "xid" }, 49 { LLC_UA, "ua" }, 50 { LLC_DISC, "disc" }, 51 { LLC_DM, "dm" }, 52 { LLC_SABME, "sabme" }, 53 { LLC_FRMR, "frmr" }, 54 { 0, NULL } 55 }; 56 57 /* 58 * Returns non-zero IFF it succeeds in printing the header 59 */ 60 int 61 llc_print(const u_char *p, u_int length, u_int caplen, 62 const u_char *esrc, const u_char *edst) 63 { 64 struct llc llc; 65 register u_short et; 66 #if 0 67 u_short control; 68 #endif 69 register int ret; 70 71 if (caplen < 3) { 72 (void)printf("[|llc]"); 73 default_print((u_char *)p, caplen); 74 return(0); 75 } 76 77 /* Watch out for possible alignment problems */ 78 memcpy((char *)&llc, (char *)p, min(caplen, sizeof(llc))); 79 80 if (llc.ssap == LLCSAP_GLOBAL && llc.dsap == LLCSAP_GLOBAL) { 81 ipx_print(p, length); 82 return (1); 83 } 84 #ifdef notyet 85 else if (p[0] == 0xf0 && p[1] == 0xf0) 86 netbios_print(p, length); 87 #endif 88 if (llc.ssap == LLCSAP_ISONS && llc.dsap == LLCSAP_ISONS 89 && llc.llcui == LLC_UI) { 90 isoclns_print(p + 3, length - 3, caplen - 3, esrc, edst); 91 return (1); 92 } 93 94 if (llc.ssap == LLCSAP_SNAP && llc.dsap == LLCSAP_SNAP 95 && llc.llcui == LLC_UI) { 96 if (caplen < sizeof(llc)) { 97 (void)printf("[|llc-snap]"); 98 default_print((u_char *)p, caplen); 99 return (0); 100 } 101 102 /* Cisco Discovery Protocol - SNAP & ether type 0x2000 */ 103 if (llc.ethertype[0] == 0x20 && llc.ethertype[1] == 0x00) { 104 cdp_print(p, length, caplen, esrc, edst); 105 return (1); 106 } 107 /* Shared Spanning Tree Protocol - SNAP & ether type 0x010b */ 108 if (llc.ethertype[0] == 0x01 && llc.ethertype[1] == 0x0b) { 109 stp_print(p, length); 110 return (1); 111 } 112 113 if (vflag) 114 (void)printf("snap %s ", protoid_string(llc.llcpi)); 115 116 caplen -= sizeof(llc); 117 length -= sizeof(llc); 118 p += sizeof(llc); 119 120 /* This is an encapsulated Ethernet packet */ 121 et = EXTRACT_16BITS(&llc.ethertype[0]); 122 123 /* 124 * Some protocols have special handling if they are 802.3 125 * SNAP encapsulated vs vers II encapsulated. Handle 126 * those special protocols here, and hand the rest to 127 * print-ether.c so we don't have to duplicate 128 * all that code here. 129 */ 130 switch (et) { 131 case ETHERTYPE_ATALK: 132 atalk_print(p, length); 133 ret = 1; 134 break; 135 default: 136 ret = ether_encap_print(et, p, length, caplen); 137 break; 138 } 139 140 if (ret) 141 return (ret); 142 } 143 144 if (llc.ssap == LLCSAP_8021D && llc.dsap == LLCSAP_8021D) { 145 stp_print(p, length); 146 return (1); 147 } 148 149 #if 0 150 if (llc.ssap == 0xf0 && llc.dsap == 0xf0) { 151 /* 152 * we don't actually have a full netbeui parser yet, but the 153 * smb parser can handle many smb-in-netbeui packets, which 154 * is very useful, so we call that 155 */ 156 157 /* 158 * Skip the DSAP and LSAP. 159 */ 160 p += 2; 161 length -= 2; 162 caplen -= 2; 163 164 /* 165 * OK, what type of LLC frame is this? The length 166 * of the control field depends on that - S or I 167 * frames have a two-byte control field, and U frames 168 * have a one-byte control field. 169 */ 170 if ((llc.llcu & LLC_U_FMT) == LLC_U_FMT) { 171 control = llc.llcu; 172 p += 1; 173 length -= 1; 174 caplen -= 1; 175 } else { 176 control = llc.llcis; 177 p += 2; 178 length -= 2; 179 caplen -= 2; 180 } 181 182 netbeui_print(control, p, p + min(caplen, length)); 183 return (1); 184 } 185 #endif 186 187 if ((llc.ssap & ~LLC_GSAP) == llc.dsap) { 188 if (eflag) 189 (void)printf("%s ", llcsap_string(llc.dsap)); 190 else 191 (void)printf("%s > %s %s ", 192 etheraddr_string(esrc), 193 etheraddr_string(edst), 194 llcsap_string(llc.dsap)); 195 } else { 196 if (eflag) 197 (void)printf("%s > %s ", 198 llcsap_string(llc.ssap & ~LLC_GSAP), 199 llcsap_string(llc.dsap)); 200 else 201 (void)printf("%s %s > %s %s ", 202 etheraddr_string(esrc), 203 llcsap_string(llc.ssap & ~LLC_GSAP), 204 etheraddr_string(edst), 205 llcsap_string(llc.dsap)); 206 } 207 208 if ((llc.llcu & LLC_U_FMT) == LLC_U_FMT) { 209 const char *m; 210 char f; 211 m = tok2str(cmd2str, "%02x", LLC_U_CMD(llc.llcu)); 212 switch ((llc.ssap & LLC_GSAP) | (llc.llcu & LLC_U_POLL)) { 213 case 0: f = 'C'; break; 214 case LLC_GSAP: f = 'R'; break; 215 case LLC_U_POLL: f = 'P'; break; 216 case LLC_GSAP|LLC_U_POLL: f = 'F'; break; 217 default: f = '?'; break; 218 } 219 220 printf("%s/%c", m, f); 221 222 if (caplen < 6) { 223 default_print_unaligned(p, caplen); 224 return (0); 225 } 226 p += 3; 227 length -= 3; 228 caplen -= 3; 229 230 if ((llc.llcu & ~LLC_U_POLL) == LLC_XID) { 231 if (*p == LLC_XID_FI) { 232 printf(": %02x %02x", p[1], p[2]); 233 p += 3; 234 length -= 3; 235 caplen -= 3; 236 } 237 } 238 239 #if 0 240 if (!strcmp(m,"ui") && f=='C') { 241 /* 242 * we don't have a proper ipx decoder yet, but there 243 * is a partial one in the smb code 244 */ 245 ipx_netbios_print(p,p+min(caplen,length)); 246 } 247 #endif 248 249 } else { 250 char f; 251 if (caplen < 4) { 252 default_print_unaligned(p, caplen); 253 return (0); 254 } 255 llc.llcis = ntohs(llc.llcis); 256 switch ((llc.ssap & LLC_GSAP) | (llc.llcu & LLC_U_POLL)) { 257 case 0: f = 'C'; break; 258 case LLC_GSAP: f = 'R'; break; 259 case LLC_U_POLL: f = 'P'; break; 260 case LLC_GSAP|LLC_U_POLL: f = 'F'; break; 261 default: f = '?'; break; 262 } 263 264 if ((llc.llcu & LLC_S_FMT) == LLC_S_FMT) { 265 static char *llc_s[] = { "rr", "rej", "rnr", "03" }; 266 (void)printf("%s (r=%d,%c)", 267 llc_s[LLC_S_CMD(llc.llcis)], 268 LLC_IS_NR(llc.llcis), 269 f); 270 } else { 271 (void)printf("I (s=%d,r=%d,%c)", 272 LLC_I_NS(llc.llcis), 273 LLC_IS_NR(llc.llcis), 274 f); 275 } 276 p += 4; 277 length -= 4; 278 caplen -= 4; 279 } 280 (void)printf(" len=%d", length); 281 return(1); 282 } 283