1335640Shselasky/*
2335640Shselasky * Copyright (c) 1990, 1991, 1992, 1994, 1995, 1996
3335640Shselasky *	The Regents of the University of California.  All rights reserved.
4335640Shselasky *
5335640Shselasky * Redistribution and use in source and binary forms, with or without
6335640Shselasky * modification, are permitted provided that: (1) source code distributions
7335640Shselasky * retain the above copyright notice and this paragraph in its entirety, (2)
8335640Shselasky * distributions including binary code include the above copyright notice and
9335640Shselasky * this paragraph in its entirety in the documentation or other materials
10335640Shselasky * provided with the distribution, and (3) all advertising materials mentioning
11335640Shselasky * features or use of this software display the following acknowledgement:
12335640Shselasky * ``This product includes software developed by the University of California,
13335640Shselasky * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14335640Shselasky * the University nor the names of its contributors may be used to endorse
15335640Shselasky * or promote products derived from this software without specific prior
16335640Shselasky * written permission.
17335640Shselasky * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18335640Shselasky * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19335640Shselasky * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20335640Shselasky */
21335640Shselasky
22335640Shselasky#ifdef HAVE_CONFIG_H
23335640Shselasky#include <config.h>
24335640Shselasky#endif
25335640Shselasky
26335640Shselasky#include <pcap-types.h>
27335640Shselasky
28335640Shselasky#include <stdio.h>
29335640Shselasky#include <string.h>
30335640Shselasky
31335640Shselasky#include "pcap-int.h"
32335640Shselasky
33335640Shselasky#ifdef HAVE_OS_PROTO_H
34335640Shselasky#include "os-proto.h"
35335640Shselasky#endif
36335640Shselasky
37335640Shselaskychar *
38335640Shselaskybpf_image(const struct bpf_insn *p, int n)
39335640Shselasky{
40335640Shselasky	const char *op;
41335640Shselasky	static char image[256];
42335640Shselasky	char operand_buf[64];
43335640Shselasky	const char *operand;
44335640Shselasky
45335640Shselasky	switch (p->code) {
46335640Shselasky
47335640Shselasky	default:
48335640Shselasky		op = "unimp";
49335640Shselasky		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "0x%x", p->code);
50335640Shselasky		operand = operand_buf;
51335640Shselasky		break;
52335640Shselasky
53335640Shselasky	case BPF_RET|BPF_K:
54335640Shselasky		op = "ret";
55335640Shselasky		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
56335640Shselasky		operand = operand_buf;
57335640Shselasky		break;
58335640Shselasky
59335640Shselasky	case BPF_RET|BPF_A:
60335640Shselasky		op = "ret";
61335640Shselasky		operand = "";
62335640Shselasky		break;
63335640Shselasky
64335640Shselasky	case BPF_LD|BPF_W|BPF_ABS:
65335640Shselasky		op = "ld";
66335640Shselasky		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "[%d]", p->k);
67335640Shselasky		operand = operand_buf;
68335640Shselasky		break;
69335640Shselasky
70335640Shselasky	case BPF_LD|BPF_H|BPF_ABS:
71335640Shselasky		op = "ldh";
72335640Shselasky		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "[%d]", p->k);
73335640Shselasky		operand = operand_buf;
74335640Shselasky		break;
75335640Shselasky
76335640Shselasky	case BPF_LD|BPF_B|BPF_ABS:
77335640Shselasky		op = "ldb";
78335640Shselasky		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "[%d]", p->k);
79335640Shselasky		operand = operand_buf;
80335640Shselasky		break;
81335640Shselasky
82335640Shselasky	case BPF_LD|BPF_W|BPF_LEN:
83335640Shselasky		op = "ld";
84335640Shselasky		operand = "#pktlen";
85335640Shselasky		break;
86335640Shselasky
87335640Shselasky	case BPF_LD|BPF_W|BPF_IND:
88335640Shselasky		op = "ld";
89335640Shselasky		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "[x + %d]", p->k);
90335640Shselasky		operand = operand_buf;
91335640Shselasky		break;
92335640Shselasky
93335640Shselasky	case BPF_LD|BPF_H|BPF_IND:
94335640Shselasky		op = "ldh";
95335640Shselasky		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "[x + %d]", p->k);
96335640Shselasky		operand = operand_buf;
97335640Shselasky		break;
98335640Shselasky
99335640Shselasky	case BPF_LD|BPF_B|BPF_IND:
100335640Shselasky		op = "ldb";
101335640Shselasky		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "[x + %d]", p->k);
102335640Shselasky		operand = operand_buf;
103335640Shselasky		break;
104335640Shselasky
105335640Shselasky	case BPF_LD|BPF_IMM:
106335640Shselasky		op = "ld";
107335640Shselasky		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
108335640Shselasky		operand = operand_buf;
109335640Shselasky		break;
110335640Shselasky
111335640Shselasky	case BPF_LDX|BPF_IMM:
112335640Shselasky		op = "ldx";
113335640Shselasky		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
114335640Shselasky		operand = operand_buf;
115335640Shselasky		break;
116335640Shselasky
117335640Shselasky	case BPF_LDX|BPF_MSH|BPF_B:
118335640Shselasky		op = "ldxb";
119335640Shselasky		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "4*([%d]&0xf)", p->k);
120335640Shselasky		operand = operand_buf;
121335640Shselasky		break;
122335640Shselasky
123335640Shselasky	case BPF_LD|BPF_MEM:
124335640Shselasky		op = "ld";
125335640Shselasky		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "M[%d]", p->k);
126335640Shselasky		operand = operand_buf;
127335640Shselasky		break;
128335640Shselasky
129335640Shselasky	case BPF_LDX|BPF_MEM:
130335640Shselasky		op = "ldx";
131335640Shselasky		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "M[%d]", p->k);
132335640Shselasky		operand = operand_buf;
133335640Shselasky		break;
134335640Shselasky
135335640Shselasky	case BPF_ST:
136335640Shselasky		op = "st";
137335640Shselasky		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "M[%d]", p->k);
138335640Shselasky		operand = operand_buf;
139335640Shselasky		break;
140335640Shselasky
141335640Shselasky	case BPF_STX:
142335640Shselasky		op = "stx";
143335640Shselasky		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "M[%d]", p->k);
144335640Shselasky		operand = operand_buf;
145335640Shselasky		break;
146335640Shselasky
147335640Shselasky	case BPF_JMP|BPF_JA:
148335640Shselasky		op = "ja";
149335640Shselasky		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "%d", n + 1 + p->k);
150335640Shselasky		operand = operand_buf;
151335640Shselasky		break;
152335640Shselasky
153335640Shselasky	case BPF_JMP|BPF_JGT|BPF_K:
154335640Shselasky		op = "jgt";
155335640Shselasky		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
156335640Shselasky		operand = operand_buf;
157335640Shselasky		break;
158335640Shselasky
159335640Shselasky	case BPF_JMP|BPF_JGE|BPF_K:
160335640Shselasky		op = "jge";
161335640Shselasky		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
162335640Shselasky		operand = operand_buf;
163335640Shselasky		break;
164335640Shselasky
165335640Shselasky	case BPF_JMP|BPF_JEQ|BPF_K:
166335640Shselasky		op = "jeq";
167335640Shselasky		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
168335640Shselasky		operand = operand_buf;
169335640Shselasky		break;
170335640Shselasky
171335640Shselasky	case BPF_JMP|BPF_JSET|BPF_K:
172335640Shselasky		op = "jset";
173335640Shselasky		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
174335640Shselasky		operand = operand_buf;
175335640Shselasky		break;
176335640Shselasky
177335640Shselasky	case BPF_JMP|BPF_JGT|BPF_X:
178335640Shselasky		op = "jgt";
179335640Shselasky		operand = "x";
180335640Shselasky		break;
181335640Shselasky
182335640Shselasky	case BPF_JMP|BPF_JGE|BPF_X:
183335640Shselasky		op = "jge";
184335640Shselasky		operand = "x";
185335640Shselasky		break;
186335640Shselasky
187335640Shselasky	case BPF_JMP|BPF_JEQ|BPF_X:
188335640Shselasky		op = "jeq";
189335640Shselasky		operand = "x";
190335640Shselasky		break;
191335640Shselasky
192335640Shselasky	case BPF_JMP|BPF_JSET|BPF_X:
193335640Shselasky		op = "jset";
194335640Shselasky		operand = "x";
195335640Shselasky		break;
196335640Shselasky
197335640Shselasky	case BPF_ALU|BPF_ADD|BPF_X:
198335640Shselasky		op = "add";
199335640Shselasky		operand = "x";
200335640Shselasky		break;
201335640Shselasky
202335640Shselasky	case BPF_ALU|BPF_SUB|BPF_X:
203335640Shselasky		op = "sub";
204335640Shselasky		operand = "x";
205335640Shselasky		break;
206335640Shselasky
207335640Shselasky	case BPF_ALU|BPF_MUL|BPF_X:
208335640Shselasky		op = "mul";
209335640Shselasky		operand = "x";
210335640Shselasky		break;
211335640Shselasky
212335640Shselasky	case BPF_ALU|BPF_DIV|BPF_X:
213335640Shselasky		op = "div";
214335640Shselasky		operand = "x";
215335640Shselasky		break;
216335640Shselasky
217335640Shselasky	case BPF_ALU|BPF_MOD|BPF_X:
218335640Shselasky		op = "mod";
219335640Shselasky		operand = "x";
220335640Shselasky		break;
221335640Shselasky
222335640Shselasky	case BPF_ALU|BPF_AND|BPF_X:
223335640Shselasky		op = "and";
224335640Shselasky		operand = "x";
225335640Shselasky		break;
226335640Shselasky
227335640Shselasky	case BPF_ALU|BPF_OR|BPF_X:
228335640Shselasky		op = "or";
229335640Shselasky		operand = "x";
230335640Shselasky		break;
231335640Shselasky
232335640Shselasky	case BPF_ALU|BPF_XOR|BPF_X:
233335640Shselasky		op = "xor";
234335640Shselasky		operand = "x";
235335640Shselasky		break;
236335640Shselasky
237335640Shselasky	case BPF_ALU|BPF_LSH|BPF_X:
238335640Shselasky		op = "lsh";
239335640Shselasky		operand = "x";
240335640Shselasky		break;
241335640Shselasky
242335640Shselasky	case BPF_ALU|BPF_RSH|BPF_X:
243335640Shselasky		op = "rsh";
244335640Shselasky		operand = "x";
245335640Shselasky		break;
246335640Shselasky
247335640Shselasky	case BPF_ALU|BPF_ADD|BPF_K:
248335640Shselasky		op = "add";
249335640Shselasky		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
250335640Shselasky		operand = operand_buf;
251335640Shselasky		break;
252335640Shselasky
253335640Shselasky	case BPF_ALU|BPF_SUB|BPF_K:
254335640Shselasky		op = "sub";
255335640Shselasky		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
256335640Shselasky		operand = operand_buf;
257335640Shselasky		break;
258335640Shselasky
259335640Shselasky	case BPF_ALU|BPF_MUL|BPF_K:
260335640Shselasky		op = "mul";
261335640Shselasky		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
262335640Shselasky		operand = operand_buf;
263335640Shselasky		break;
264335640Shselasky
265335640Shselasky	case BPF_ALU|BPF_DIV|BPF_K:
266335640Shselasky		op = "div";
267335640Shselasky		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
268335640Shselasky		operand = operand_buf;
269335640Shselasky		break;
270335640Shselasky
271335640Shselasky	case BPF_ALU|BPF_MOD|BPF_K:
272335640Shselasky		op = "mod";
273335640Shselasky		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
274335640Shselasky		operand = operand_buf;
275335640Shselasky		break;
276335640Shselasky
277335640Shselasky	case BPF_ALU|BPF_AND|BPF_K:
278335640Shselasky		op = "and";
279335640Shselasky		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
280335640Shselasky		operand = operand_buf;
281335640Shselasky		break;
282335640Shselasky
283335640Shselasky	case BPF_ALU|BPF_OR|BPF_K:
284335640Shselasky		op = "or";
285335640Shselasky		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
286335640Shselasky		operand = operand_buf;
287335640Shselasky		break;
288335640Shselasky
289335640Shselasky	case BPF_ALU|BPF_XOR|BPF_K:
290335640Shselasky		op = "xor";
291335640Shselasky		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
292335640Shselasky		operand = operand_buf;
293335640Shselasky		break;
294335640Shselasky
295335640Shselasky	case BPF_ALU|BPF_LSH|BPF_K:
296335640Shselasky		op = "lsh";
297335640Shselasky		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
298335640Shselasky		operand = operand_buf;
299335640Shselasky		break;
300335640Shselasky
301335640Shselasky	case BPF_ALU|BPF_RSH|BPF_K:
302335640Shselasky		op = "rsh";
303335640Shselasky		(void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
304335640Shselasky		operand = operand_buf;
305335640Shselasky		break;
306335640Shselasky
307335640Shselasky	case BPF_ALU|BPF_NEG:
308335640Shselasky		op = "neg";
309335640Shselasky		operand = "";
310335640Shselasky		break;
311335640Shselasky
312335640Shselasky	case BPF_MISC|BPF_TAX:
313335640Shselasky		op = "tax";
314335640Shselasky		operand = "";
315335640Shselasky		break;
316335640Shselasky
317335640Shselasky	case BPF_MISC|BPF_TXA:
318335640Shselasky		op = "txa";
319335640Shselasky		operand = "";
320335640Shselasky		break;
321335640Shselasky	}
322335640Shselasky	if (BPF_CLASS(p->code) == BPF_JMP && BPF_OP(p->code) != BPF_JA) {
323335640Shselasky		(void)pcap_snprintf(image, sizeof image,
324335640Shselasky			      "(%03d) %-8s %-16s jt %d\tjf %d",
325335640Shselasky			      n, op, operand, n + 1 + p->jt, n + 1 + p->jf);
326335640Shselasky	} else {
327335640Shselasky		(void)pcap_snprintf(image, sizeof image,
328335640Shselasky			      "(%03d) %-8s %s",
329335640Shselasky			      n, op, operand);
330335640Shselasky	}
331335640Shselasky	return image;
332335640Shselasky}
333