]> The Tcpdump Group git mirrors - tcpdump/blob - print-pflog.c
Replace some command name 'Tcpdump' with 'tcpdump'
[tcpdump] / print-pflog.c
1 /*
2 * Copyright (c) 1990, 1991, 1993, 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 /* \summary: *BSD/Darwin packet filter log file printer */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include "netdissect-stdinc.h"
29
30 #include "netdissect.h"
31 #include "extract.h"
32 #include "af.h"
33
34 /*
35 * pflog headers, at least as they exist now.
36 */
37 #define PFLOG_IFNAMSIZ 16
38 #define PFLOG_RULESET_NAME_SIZE 16
39
40 struct pf_addr {
41 union {
42 nd_ipv4 v4;
43 nd_ipv6 v6;
44 } pfa; /* 128-bit address */
45 #define v4 pfa.v4
46 #define v6 pfa.v6
47 };
48
49 struct pfloghdr {
50 nd_uint8_t length;
51 nd_uint8_t af;
52 nd_uint8_t action;
53 nd_uint8_t reason;
54 char ifname[PFLOG_IFNAMSIZ];
55 char ruleset[PFLOG_RULESET_NAME_SIZE];
56 nd_uint32_t rulenr;
57 nd_uint32_t subrulenr;
58 nd_uint32_t uid;
59 nd_int32_t pid;
60 nd_uint32_t rule_uid;
61 nd_int32_t rule_pid;
62 nd_uint8_t dir;
63 /* Minimum header length (without padding): 61 */
64 #define MIN_PFLOG_HDRLEN 61
65 #if defined(__OpenBSD__)
66 nd_uint8_t rewritten;
67 nd_uint8_t naf;
68 nd_uint8_t pad[1];
69 #else
70 nd_uint8_t pad[3];
71 #endif
72 #if defined(__FreeBSD__)
73 nd_uint32_t ridentifier;
74 nd_uint8_t reserve;
75 nd_uint8_t pad2[3];
76 #elif defined(__OpenBSD__)
77 struct pf_addr saddr;
78 struct pf_addr daddr;
79 nd_uint16_t sport;
80 nd_uint16_t dport;
81 #endif
82 };
83
84 /*
85 * Reason values.
86 */
87 #define PFRES_MATCH 0
88 #define PFRES_BADOFF 1
89 #define PFRES_FRAG 2
90 #define PFRES_SHORT 3
91 #define PFRES_NORM 4
92 #define PFRES_MEMORY 5
93 #define PFRES_TS 6
94 #define PFRES_CONGEST 7
95 #define PFRES_IPOPTIONS 8
96 #define PFRES_PROTCKSUM 9
97 #define PFRES_BADSTATE 10
98 #define PFRES_STATEINS 11
99 #define PFRES_MAXSTATES 12
100 #define PFRES_SRCLIMIT 13
101 #define PFRES_SYNPROXY 14
102 #if defined(__FreeBSD__)
103 #define PFRES_MAPFAILED 15
104 #elif defined(__NetBSD__)
105 #define PFRES_STATELOCKED 15
106 #elif defined(__OpenBSD__)
107 #define PFRES_TRANSLATE 15
108 #define PFRES_NOROUTE 16
109 #elif defined(__APPLE__)
110 #define PFRES_DUMMYNET 15
111 #endif
112
113 static const struct tok pf_reasons[] = {
114 { PFRES_MATCH, "0(match)" },
115 { PFRES_BADOFF, "1(bad-offset)" },
116 { PFRES_FRAG, "2(fragment)" },
117 { PFRES_SHORT, "3(short)" },
118 { PFRES_NORM, "4(normalize)" },
119 { PFRES_MEMORY, "5(memory)" },
120 { PFRES_TS, "6(bad-timestamp)" },
121 { PFRES_CONGEST, "7(congestion)" },
122 { PFRES_IPOPTIONS, "8(ip-option)" },
123 { PFRES_PROTCKSUM, "9(proto-cksum)" },
124 { PFRES_BADSTATE, "10(state-mismatch)" },
125 { PFRES_STATEINS, "11(state-insert)" },
126 { PFRES_MAXSTATES, "12(state-limit)" },
127 { PFRES_SRCLIMIT, "13(src-limit)" },
128 { PFRES_SYNPROXY, "14(synproxy)" },
129 #if defined(__FreeBSD__)
130 { PFRES_MAPFAILED, "15(map-failed)" },
131 #elif defined(__NetBSD__)
132 { PFRES_STATELOCKED, "15(state-locked)" },
133 #elif defined(__OpenBSD__)
134 { PFRES_TRANSLATE, "15(translate)" },
135 { PFRES_NOROUTE, "16(no-route)" },
136 #elif defined(__APPLE__)
137 { PFRES_DUMMYNET, "15(dummynet)" },
138 #endif
139 { 0, NULL }
140 };
141
142 /*
143 * Action values.
144 */
145 #define PF_PASS 0
146 #define PF_DROP 1
147 #define PF_SCRUB 2
148 #define PF_NOSCRUB 3
149 #define PF_NAT 4
150 #define PF_NONAT 5
151 #define PF_BINAT 6
152 #define PF_NOBINAT 7
153 #define PF_RDR 8
154 #define PF_NORDR 9
155 #define PF_SYNPROXY_DROP 10
156 #if defined(__FreeBSD__)
157 #define PF_DEFER 11
158 #elif defined(__OpenBSD__)
159 #define PF_DEFER 11
160 #define PF_MATCH 12
161 #define PF_DIVERT 13
162 #define PF_RT 14
163 #define PF_AFRT 15
164 #elif defined(__APPLE__)
165 #define PF_DUMMYNET 11
166 #define PF_NODUMMYNET 12
167 #define PF_NAT64 13
168 #define PF_NONAT64 14
169 #endif
170
171 static const struct tok pf_actions[] = {
172 { PF_PASS, "pass" },
173 { PF_DROP, "block" },
174 { PF_SCRUB, "scrub" },
175 { PF_NAT, "nat" },
176 { PF_NONAT, "nonat" },
177 { PF_BINAT, "binat" },
178 { PF_NOBINAT, "nobinat" },
179 { PF_RDR, "rdr" },
180 { PF_NORDR, "nordr" },
181 { PF_SYNPROXY_DROP, "synproxy-drop" },
182 #if defined(__FreeBSD__)
183 { PF_DEFER, "defer" },
184 #elif defined(__OpenBSD__)
185 { PF_DEFER, "defer" },
186 { PF_MATCH, "match" },
187 { PF_DIVERT, "divert" },
188 { PF_RT, "rt" },
189 { PF_AFRT, "afrt" },
190 #elif defined(__APPLE__)
191 { PF_DUMMYNET, "dummynet" },
192 { PF_NODUMMYNET, "nodummynet" },
193 { PF_NAT64, "nat64" },
194 { PF_NONAT64, "nonat64" },
195 #endif
196 { 0, NULL }
197 };
198
199 /*
200 * Direction values.
201 */
202 #define PF_INOUT 0
203 #define PF_IN 1
204 #define PF_OUT 2
205 #if defined(__OpenBSD__)
206 #define PF_FWD 3
207 #endif
208
209 static const struct tok pf_directions[] = {
210 { PF_INOUT, "in/out" },
211 { PF_IN, "in" },
212 { PF_OUT, "out" },
213 #if defined(__OpenBSD__)
214 { PF_FWD, "fwd" },
215 #endif
216 { 0, NULL }
217 };
218
219 static void
220 pflog_print(netdissect_options *ndo, const struct pfloghdr *hdr)
221 {
222 uint32_t rulenr, subrulenr;
223
224 ndo->ndo_protocol = "pflog";
225 rulenr = GET_BE_U_4(hdr->rulenr);
226 subrulenr = GET_BE_U_4(hdr->subrulenr);
227 if (subrulenr == (uint32_t)-1)
228 ND_PRINT("rule %u/", rulenr);
229 else {
230 ND_PRINT("rule %u.", rulenr);
231 nd_printjnp(ndo, (const u_char*)hdr->ruleset, PFLOG_RULESET_NAME_SIZE);
232 ND_PRINT(".%u/", subrulenr);
233 }
234
235 ND_PRINT("%s: %s %s on ",
236 tok2str(pf_reasons, "unkn(%u)", GET_U_1(hdr->reason)),
237 tok2str(pf_actions, "unkn(%u)", GET_U_1(hdr->action)),
238 tok2str(pf_directions, "unkn(%u)", GET_U_1(hdr->dir)));
239 nd_printjnp(ndo, (const u_char*)hdr->ifname, PFLOG_IFNAMSIZ);
240 ND_PRINT(": ");
241 }
242
243 void
244 pflog_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h,
245 const u_char *p)
246 {
247 u_int length = h->len;
248 u_int hdrlen;
249 u_int caplen = h->caplen;
250 const struct pfloghdr *hdr;
251 uint8_t af;
252
253 ndo->ndo_protocol = "pflog";
254 /* check length */
255 if (caplen < sizeof(uint8_t)) {
256 nd_print_trunc(ndo);
257 ndo->ndo_ll_hdr_len += h->caplen;
258 return;
259 }
260
261 hdr = (const struct pfloghdr *)p;
262 hdrlen = GET_U_1(hdr->length);
263 if (hdrlen < MIN_PFLOG_HDRLEN) {
264 ND_PRINT("[pflog: invalid header length!]");
265 ndo->ndo_ll_hdr_len += hdrlen; /* XXX: not really */
266 return;
267 }
268 hdrlen = roundup2(hdrlen, 4);
269
270 if (caplen < hdrlen) {
271 nd_print_trunc(ndo);
272 ndo->ndo_ll_hdr_len += hdrlen; /* XXX: true? */
273 return;
274 }
275
276 /* print what we know */
277 ND_TCHECK_SIZE(hdr);
278 if (ndo->ndo_eflag)
279 pflog_print(ndo, hdr);
280
281 /* skip to the real packet */
282 af = GET_U_1(hdr->af);
283 length -= hdrlen;
284 caplen -= hdrlen;
285 p += hdrlen;
286 switch (af) {
287
288 /*
289 * If there's a system that doesn't use the AF_INET
290 * from 4.2BSD, feel free to add its value to af.h
291 * and use it here.
292 *
293 * Hopefully, there isn't.
294 */
295 case BSD_AF_INET:
296 ip_print(ndo, p, length);
297 break;
298
299 /*
300 * Try all AF_INET6 values for all systems with pflog,
301 * including Darwin.
302 */
303 case BSD_AF_INET6_BSD:
304 case BSD_AF_INET6_FREEBSD:
305 case BSD_AF_INET6_DARWIN:
306 ip6_print(ndo, p, length);
307 break;
308
309 default:
310 /* address family not handled, print raw packet */
311 if (!ndo->ndo_eflag)
312 pflog_print(ndo, hdr);
313 if (!ndo->ndo_suppress_default_print)
314 ND_DEFAULTPRINT(p, caplen);
315 }
316
317 ndo->ndo_ll_hdr_len += hdrlen;
318 return;
319 trunc:
320 nd_print_trunc(ndo);
321 ndo->ndo_ll_hdr_len += hdrlen;
322 }