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