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