1/* $NetBSD: bpf_image.c,v 1.4 2018/09/03 15:26:43 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.4 2018/09/03 15:26:43 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#include "pcap-int.h"
37
38#ifdef HAVE_OS_PROTO_H
39#include "os-proto.h"
40#endif
41
42char *
43bpf_image(const struct bpf_insn *p, int n)
44{
45 const char *op;
46 static char image[256];
47 char operand_buf[64];
48 const char *operand;
49
50 switch (p->code) {
51
52 default:
53 op = "unimp";
54 (void)pcap_snprintf(operand_buf, sizeof operand_buf, "0x%x", p->code);
55 operand = operand_buf;
56 break;
57
58 case BPF_RET|BPF_K:
59 op = "ret";
60 (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
61 operand = operand_buf;
62 break;
63
64 case BPF_RET|BPF_A:
65 op = "ret";
66 operand = "";
67 break;
68
69 case BPF_LD|BPF_W|BPF_ABS:
70 op = "ld";
71 (void)pcap_snprintf(operand_buf, sizeof operand_buf, "[%d]", p->k);
72 operand = operand_buf;
73 break;
74
75 case BPF_LD|BPF_H|BPF_ABS:
76 op = "ldh";
77 (void)pcap_snprintf(operand_buf, sizeof operand_buf, "[%d]", p->k);
78 operand = operand_buf;
79 break;
80
81 case BPF_LD|BPF_B|BPF_ABS:
82 op = "ldb";
83 (void)pcap_snprintf(operand_buf, sizeof operand_buf, "[%d]", p->k);
84 operand = operand_buf;
85 break;
86
87 case BPF_LD|BPF_W|BPF_LEN:
88 op = "ld";
89 operand = "#pktlen";
90 break;
91
92 case BPF_LD|BPF_W|BPF_IND:
93 op = "ld";
94 (void)pcap_snprintf(operand_buf, sizeof operand_buf, "[x + %d]", p->k);
95 operand = operand_buf;
96 break;
97
98 case BPF_LD|BPF_H|BPF_IND:
99 op = "ldh";
100 (void)pcap_snprintf(operand_buf, sizeof operand_buf, "[x + %d]", p->k);
101 operand = operand_buf;
102 break;
103
104 case BPF_LD|BPF_B|BPF_IND:
105 op = "ldb";
106 (void)pcap_snprintf(operand_buf, sizeof operand_buf, "[x + %d]", p->k);
107 operand = operand_buf;
108 break;
109
110 case BPF_LD|BPF_IMM:
111 op = "ld";
112 (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
113 operand = operand_buf;
114 break;
115
116 case BPF_LDX|BPF_IMM:
117 op = "ldx";
118 (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
119 operand = operand_buf;
120 break;
121
122 case BPF_LDX|BPF_MSH|BPF_B:
123 op = "ldxb";
124 (void)pcap_snprintf(operand_buf, sizeof operand_buf, "4*([%d]&0xf)", p->k);
125 operand = operand_buf;
126 break;
127
128 case BPF_LD|BPF_MEM:
129 op = "ld";
130 (void)pcap_snprintf(operand_buf, sizeof operand_buf, "M[%d]", p->k);
131 operand = operand_buf;
132 break;
133
134 case BPF_LDX|BPF_MEM:
135 op = "ldx";
136 (void)pcap_snprintf(operand_buf, sizeof operand_buf, "M[%d]", p->k);
137 operand = operand_buf;
138 break;
139
140 case BPF_ST:
141 op = "st";
142 (void)pcap_snprintf(operand_buf, sizeof operand_buf, "M[%d]", p->k);
143 operand = operand_buf;
144 break;
145
146 case BPF_STX:
147 op = "stx";
148 (void)pcap_snprintf(operand_buf, sizeof operand_buf, "M[%d]", p->k);
149 operand = operand_buf;
150 break;
151
152 case BPF_JMP|BPF_JA:
153 op = "ja";
154 (void)pcap_snprintf(operand_buf, sizeof operand_buf, "%d", n + 1 + p->k);
155 operand = operand_buf;
156 break;
157
158 case BPF_JMP|BPF_JGT|BPF_K:
159 op = "jgt";
160 (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
161 operand = operand_buf;
162 break;
163
164 case BPF_JMP|BPF_JGE|BPF_K:
165 op = "jge";
166 (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
167 operand = operand_buf;
168 break;
169
170 case BPF_JMP|BPF_JEQ|BPF_K:
171 op = "jeq";
172 (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
173 operand = operand_buf;
174 break;
175
176 case BPF_JMP|BPF_JSET|BPF_K:
177 op = "jset";
178 (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
179 operand = operand_buf;
180 break;
181
182 case BPF_JMP|BPF_JGT|BPF_X:
183 op = "jgt";
184 operand = "x";
185 break;
186
187 case BPF_JMP|BPF_JGE|BPF_X:
188 op = "jge";
189 operand = "x";
190 break;
191
192 case BPF_JMP|BPF_JEQ|BPF_X:
193 op = "jeq";
194 operand = "x";
195 break;
196
197 case BPF_JMP|BPF_JSET|BPF_X:
198 op = "jset";
199 operand = "x";
200 break;
201
202 case BPF_ALU|BPF_ADD|BPF_X:
203 op = "add";
204 operand = "x";
205 break;
206
207 case BPF_ALU|BPF_SUB|BPF_X:
208 op = "sub";
209 operand = "x";
210 break;
211
212 case BPF_ALU|BPF_MUL|BPF_X:
213 op = "mul";
214 operand = "x";
215 break;
216
217 case BPF_ALU|BPF_DIV|BPF_X:
218 op = "div";
219 operand = "x";
220 break;
221
222 case BPF_ALU|BPF_MOD|BPF_X:
223 op = "mod";
224 operand = "x";
225 break;
226
227 case BPF_ALU|BPF_AND|BPF_X:
228 op = "and";
229 operand = "x";
230 break;
231
232 case BPF_ALU|BPF_OR|BPF_X:
233 op = "or";
234 operand = "x";
235 break;
236
237 case BPF_ALU|BPF_XOR|BPF_X:
238 op = "xor";
239 operand = "x";
240 break;
241
242 case BPF_ALU|BPF_LSH|BPF_X:
243 op = "lsh";
244 operand = "x";
245 break;
246
247 case BPF_ALU|BPF_RSH|BPF_X:
248 op = "rsh";
249 operand = "x";
250 break;
251
252 case BPF_ALU|BPF_ADD|BPF_K:
253 op = "add";
254 (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
255 operand = operand_buf;
256 break;
257
258 case BPF_ALU|BPF_SUB|BPF_K:
259 op = "sub";
260 (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
261 operand = operand_buf;
262 break;
263
264 case BPF_ALU|BPF_MUL|BPF_K:
265 op = "mul";
266 (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
267 operand = operand_buf;
268 break;
269
270 case BPF_ALU|BPF_DIV|BPF_K:
271 op = "div";
272 (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
273 operand = operand_buf;
274 break;
275
276 case BPF_ALU|BPF_MOD|BPF_K:
277 op = "mod";
278 (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
279 operand = operand_buf;
280 break;
281
282 case BPF_ALU|BPF_AND|BPF_K:
283 op = "and";
284 (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
285 operand = operand_buf;
286 break;
287
288 case BPF_ALU|BPF_OR|BPF_K:
289 op = "or";
290 (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
291 operand = operand_buf;
292 break;
293
294 case BPF_ALU|BPF_XOR|BPF_K:
295 op = "xor";
296 (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
297 operand = operand_buf;
298 break;
299
300 case BPF_ALU|BPF_LSH|BPF_K:
301 op = "lsh";
302 (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
303 operand = operand_buf;
304 break;
305
306 case BPF_ALU|BPF_RSH|BPF_K:
307 op = "rsh";
308 (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
309 operand = operand_buf;
310 break;
311
312 case BPF_ALU|BPF_NEG:
313 op = "neg";
314 operand = "";
315 break;
316
317 case BPF_MISC|BPF_TAX:
318 op = "tax";
319 operand = "";
320 break;
321
322 case BPF_MISC|BPF_TXA:
323 op = "txa";
324 operand = "";
325 break;
326 }
327 if (BPF_CLASS(p->code) == BPF_JMP && BPF_OP(p->code) != BPF_JA) {
328 (void)pcap_snprintf(image, sizeof image,
329 "(%03d) %-8s %-16s jt %d\tjf %d",
330 n, op, operand, n + 1 + p->jt, n + 1 + p->jf);
331 } else {
332 (void)pcap_snprintf(image, sizeof image,
333 "(%03d) %-8s %s",
334 n, op, operand);
335 }
336 return image;
337}
338