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