1 /* 2 * Copyright (c) 1990, 1991, 1992, 1994, 1995, 1996 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 <config.h> 23 24 #include <pcap-types.h> 25 26 #include <stdio.h> 27 #include <string.h> 28 29 #ifdef __linux__ 30 #include <linux/types.h> 31 #include <linux/if_packet.h> 32 #include <linux/filter.h> 33 34 /* 35 * We want our versions of these #defines, not Linux's version. 36 * (The two should be the same; if not, we have a problem; all BPF 37 * implementations *should* be source-compatible supersets of ours.) 38 */ 39 #undef BPF_STMT 40 #undef BPF_JUMP 41 #endif 42 43 #include "pcap-int.h" 44 45 #include "thread-local.h" 46 47 #ifdef HAVE_OS_PROTO_H 48 #include "os-proto.h" 49 #endif 50 51 #ifdef SKF_AD_OFF 52 /* 53 * Symbolic names for offsets that refer to the special Linux BPF locations. 54 */ 55 static const char *offsets[SKF_AD_MAX] = { 56 #ifdef SKF_AD_PROTOCOL 57 [SKF_AD_PROTOCOL] = "proto", 58 #endif 59 #ifdef SKF_AD_PKTTYPE 60 [SKF_AD_PKTTYPE] = "type", 61 #endif 62 #ifdef SKF_AD_IFINDEX 63 [SKF_AD_IFINDEX] = "ifidx", 64 #endif 65 #ifdef SKF_AD_NLATTR 66 [SKF_AD_NLATTR] = "nla", 67 #endif 68 #ifdef SKF_AD_NLATTR_NEST 69 [SKF_AD_NLATTR_NEST] = "nlan", 70 #endif 71 #ifdef SKF_AD_MARK 72 [SKF_AD_MARK] = "mark", 73 #endif 74 #ifdef SKF_AD_QUEUE 75 [SKF_AD_QUEUE] = "queue", 76 #endif 77 #ifdef SKF_AD_HATYPE 78 [SKF_AD_HATYPE] = "hatype", 79 #endif 80 #ifdef SKF_AD_RXHASH 81 [SKF_AD_RXHASH] = "rxhash", 82 #endif 83 #ifdef SKF_AD_CPU 84 [SKF_AD_CPU] = "cpu", 85 #endif 86 #ifdef SKF_AD_ALU_XOR_X 87 [SKF_AD_ALU_XOR_X] = "xor_x", 88 #endif 89 #ifdef SKF_AD_VLAN_TAG 90 [SKF_AD_VLAN_TAG] = "vlan_tci", 91 #endif 92 #ifdef SKF_AD_VLAN_TAG_PRESENT 93 [SKF_AD_VLAN_TAG_PRESENT] = "vlanp", 94 #endif 95 #ifdef SKF_AD_PAY_OFFSET 96 [SKF_AD_PAY_OFFSET] = "poff", 97 #endif 98 #ifdef SKF_AD_RANDOM 99 [SKF_AD_RANDOM] = "random", 100 #endif 101 #ifdef SKF_AD_VLAN_TPID 102 [SKF_AD_VLAN_TPID] = "vlan_tpid" 103 #endif 104 }; 105 #endif 106 107 static void 108 bpf_print_abs_load_operand(char *buf, size_t bufsize, const struct bpf_insn *p) 109 { 110 #ifdef SKF_AD_OFF 111 const char *sym; 112 113 /* 114 * It's an absolute load. 115 * Is the offset a special Linux offset that we know about? 116 */ 117 if (p->k >= (bpf_u_int32)SKF_AD_OFF && 118 p->k < (bpf_u_int32)(SKF_AD_OFF + SKF_AD_MAX) && 119 (sym = offsets[p->k - (bpf_u_int32)SKF_AD_OFF]) != NULL) { 120 /* 121 * Yes. Print the offset symbolically. 122 */ 123 (void)snprintf(buf, bufsize, "[%s]", sym); 124 } else 125 #endif 126 (void)snprintf(buf, bufsize, "[%d]", p->k); 127 } 128 129 char * 130 bpf_image(const struct bpf_insn *p, int n) 131 { 132 const char *op; 133 static thread_local char image[256]; 134 char operand_buf[64]; 135 const char *operand; 136 137 switch (p->code) { 138 139 default: 140 op = "unimp"; 141 (void)snprintf(operand_buf, sizeof operand_buf, "0x%x", p->code); 142 operand = operand_buf; 143 break; 144 145 case BPF_RET|BPF_K: 146 op = "ret"; 147 (void)snprintf(operand_buf, sizeof operand_buf, "#%d", p->k); 148 operand = operand_buf; 149 break; 150 151 case BPF_RET|BPF_A: 152 op = "ret"; 153 operand = ""; 154 break; 155 156 case BPF_LD|BPF_W|BPF_ABS: 157 op = "ld"; 158 bpf_print_abs_load_operand(operand_buf, sizeof operand_buf, p); 159 operand = operand_buf; 160 break; 161 162 case BPF_LD|BPF_H|BPF_ABS: 163 op = "ldh"; 164 bpf_print_abs_load_operand(operand_buf, sizeof operand_buf, p); 165 operand = operand_buf; 166 break; 167 168 case BPF_LD|BPF_B|BPF_ABS: 169 op = "ldb"; 170 bpf_print_abs_load_operand(operand_buf, sizeof operand_buf, p); 171 operand = operand_buf; 172 break; 173 174 case BPF_LD|BPF_W|BPF_LEN: 175 op = "ld"; 176 operand = "#pktlen"; 177 break; 178 179 case BPF_LD|BPF_W|BPF_IND: 180 op = "ld"; 181 (void)snprintf(operand_buf, sizeof operand_buf, "[x + %d]", p->k); 182 operand = operand_buf; 183 break; 184 185 case BPF_LD|BPF_H|BPF_IND: 186 op = "ldh"; 187 (void)snprintf(operand_buf, sizeof operand_buf, "[x + %d]", p->k); 188 operand = operand_buf; 189 break; 190 191 case BPF_LD|BPF_B|BPF_IND: 192 op = "ldb"; 193 (void)snprintf(operand_buf, sizeof operand_buf, "[x + %d]", p->k); 194 operand = operand_buf; 195 break; 196 197 case BPF_LD|BPF_IMM: 198 op = "ld"; 199 (void)snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k); 200 operand = operand_buf; 201 break; 202 203 case BPF_LDX|BPF_IMM: 204 op = "ldx"; 205 (void)snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k); 206 operand = operand_buf; 207 break; 208 209 case BPF_LDX|BPF_MSH|BPF_B: 210 op = "ldxb"; 211 (void)snprintf(operand_buf, sizeof operand_buf, "4*([%d]&0xf)", p->k); 212 operand = operand_buf; 213 break; 214 215 case BPF_LD|BPF_MEM: 216 op = "ld"; 217 (void)snprintf(operand_buf, sizeof operand_buf, "M[%d]", p->k); 218 operand = operand_buf; 219 break; 220 221 case BPF_LDX|BPF_MEM: 222 op = "ldx"; 223 (void)snprintf(operand_buf, sizeof operand_buf, "M[%d]", p->k); 224 operand = operand_buf; 225 break; 226 227 case BPF_ST: 228 op = "st"; 229 (void)snprintf(operand_buf, sizeof operand_buf, "M[%d]", p->k); 230 operand = operand_buf; 231 break; 232 233 case BPF_STX: 234 op = "stx"; 235 (void)snprintf(operand_buf, sizeof operand_buf, "M[%d]", p->k); 236 operand = operand_buf; 237 break; 238 239 case BPF_JMP|BPF_JA: 240 op = "ja"; 241 (void)snprintf(operand_buf, sizeof operand_buf, "%d", n + 1 + p->k); 242 operand = operand_buf; 243 break; 244 245 case BPF_JMP|BPF_JGT|BPF_K: 246 op = "jgt"; 247 (void)snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k); 248 operand = operand_buf; 249 break; 250 251 case BPF_JMP|BPF_JGE|BPF_K: 252 op = "jge"; 253 (void)snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k); 254 operand = operand_buf; 255 break; 256 257 case BPF_JMP|BPF_JEQ|BPF_K: 258 op = "jeq"; 259 (void)snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k); 260 operand = operand_buf; 261 break; 262 263 case BPF_JMP|BPF_JSET|BPF_K: 264 op = "jset"; 265 (void)snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k); 266 operand = operand_buf; 267 break; 268 269 case BPF_JMP|BPF_JGT|BPF_X: 270 op = "jgt"; 271 operand = "x"; 272 break; 273 274 case BPF_JMP|BPF_JGE|BPF_X: 275 op = "jge"; 276 operand = "x"; 277 break; 278 279 case BPF_JMP|BPF_JEQ|BPF_X: 280 op = "jeq"; 281 operand = "x"; 282 break; 283 284 case BPF_JMP|BPF_JSET|BPF_X: 285 op = "jset"; 286 operand = "x"; 287 break; 288 289 case BPF_ALU|BPF_ADD|BPF_X: 290 op = "add"; 291 operand = "x"; 292 break; 293 294 case BPF_ALU|BPF_SUB|BPF_X: 295 op = "sub"; 296 operand = "x"; 297 break; 298 299 case BPF_ALU|BPF_MUL|BPF_X: 300 op = "mul"; 301 operand = "x"; 302 break; 303 304 case BPF_ALU|BPF_DIV|BPF_X: 305 op = "div"; 306 operand = "x"; 307 break; 308 309 case BPF_ALU|BPF_MOD|BPF_X: 310 op = "mod"; 311 operand = "x"; 312 break; 313 314 case BPF_ALU|BPF_AND|BPF_X: 315 op = "and"; 316 operand = "x"; 317 break; 318 319 case BPF_ALU|BPF_OR|BPF_X: 320 op = "or"; 321 operand = "x"; 322 break; 323 324 case BPF_ALU|BPF_XOR|BPF_X: 325 op = "xor"; 326 operand = "x"; 327 break; 328 329 case BPF_ALU|BPF_LSH|BPF_X: 330 op = "lsh"; 331 operand = "x"; 332 break; 333 334 case BPF_ALU|BPF_RSH|BPF_X: 335 op = "rsh"; 336 operand = "x"; 337 break; 338 339 case BPF_ALU|BPF_ADD|BPF_K: 340 op = "add"; 341 (void)snprintf(operand_buf, sizeof operand_buf, "#%d", p->k); 342 operand = operand_buf; 343 break; 344 345 case BPF_ALU|BPF_SUB|BPF_K: 346 op = "sub"; 347 (void)snprintf(operand_buf, sizeof operand_buf, "#%d", p->k); 348 operand = operand_buf; 349 break; 350 351 case BPF_ALU|BPF_MUL|BPF_K: 352 op = "mul"; 353 (void)snprintf(operand_buf, sizeof operand_buf, "#%d", p->k); 354 operand = operand_buf; 355 break; 356 357 case BPF_ALU|BPF_DIV|BPF_K: 358 op = "div"; 359 (void)snprintf(operand_buf, sizeof operand_buf, "#%d", p->k); 360 operand = operand_buf; 361 break; 362 363 case BPF_ALU|BPF_MOD|BPF_K: 364 op = "mod"; 365 (void)snprintf(operand_buf, sizeof operand_buf, "#%d", p->k); 366 operand = operand_buf; 367 break; 368 369 case BPF_ALU|BPF_AND|BPF_K: 370 op = "and"; 371 (void)snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k); 372 operand = operand_buf; 373 break; 374 375 case BPF_ALU|BPF_OR|BPF_K: 376 op = "or"; 377 (void)snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k); 378 operand = operand_buf; 379 break; 380 381 case BPF_ALU|BPF_XOR|BPF_K: 382 op = "xor"; 383 (void)snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k); 384 operand = operand_buf; 385 break; 386 387 case BPF_ALU|BPF_LSH|BPF_K: 388 op = "lsh"; 389 (void)snprintf(operand_buf, sizeof operand_buf, "#%d", p->k); 390 operand = operand_buf; 391 break; 392 393 case BPF_ALU|BPF_RSH|BPF_K: 394 op = "rsh"; 395 (void)snprintf(operand_buf, sizeof operand_buf, "#%d", p->k); 396 operand = operand_buf; 397 break; 398 399 case BPF_ALU|BPF_NEG: 400 op = "neg"; 401 operand = ""; 402 break; 403 404 case BPF_MISC|BPF_TAX: 405 op = "tax"; 406 operand = ""; 407 break; 408 409 case BPF_MISC|BPF_TXA: 410 op = "txa"; 411 operand = ""; 412 break; 413 } 414 if (BPF_CLASS(p->code) == BPF_JMP && BPF_OP(p->code) != BPF_JA) { 415 (void)snprintf(image, sizeof image, 416 "(%03d) %-8s %-16s jt %d\tjf %d", 417 n, op, operand, n + 1 + p->jt, n + 1 + p->jf); 418 } else { 419 (void)snprintf(image, sizeof image, 420 "(%03d) %-8s %s", 421 n, op, operand); 422 } 423 return image; 424 } 425