2 * Routines for pflog (OpenBSD Firewall Logging) packet disassembly
6 * Copyright 2001 Mike Frantzen
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * - Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
31 /* Specifications... :
32 http://www.openbsd.org/cgi-bin/cvsweb/src/sys/net/if_pflog.c
33 http://www.openbsd.org/cgi-bin/cvsweb/src/sys/net/if_pflog.h
39 #include <epan/packet.h>
41 #include <epan/aftypes.h>
42 #include <epan/etypes.h>
43 #include <epan/addr_resolv.h>
44 #include <epan/expert.h>
46 static dissector_handle_t data_handle, ip_handle, ipv6_handle;
49 static int proto_pflog = -1;
50 static int hf_pflog_length = -1;
51 static int hf_pflog_af = -1;
52 static int hf_pflog_action = -1;
53 static int hf_pflog_reason = -1;
54 static int hf_pflog_ifname = -1;
55 static int hf_pflog_ruleset = -1;
56 static int hf_pflog_rulenr = -1;
57 static int hf_pflog_subrulenr = -1;
58 static int hf_pflog_uid = -1;
59 static int hf_pflog_pid = -1;
60 static int hf_pflog_rule_uid = -1;
61 static int hf_pflog_rule_pid = -1;
62 static int hf_pflog_dir = -1;
63 static int hf_pflog_rewritten = -1;
64 static int hf_pflog_pad = -1;
65 static int hf_pflog_saddr_ipv4 = -1;
66 static int hf_pflog_daddr_ipv4 = -1;
67 static int hf_pflog_saddr_ipv6 = -1;
68 static int hf_pflog_daddr_ipv6 = -1;
69 static int hf_pflog_saddr = -1;
70 static int hf_pflog_daddr = -1;
71 static int hf_pflog_sport = -1;
72 static int hf_pflog_dport = -1;
73 static gint ett_pflog = -1;
76 static int proto_old_pflog = -1;
77 static int hf_old_pflog_af = -1;
78 static int hf_old_pflog_ifname = -1;
79 static int hf_old_pflog_rnr = -1;
80 static int hf_old_pflog_reason = -1;
81 static int hf_old_pflog_action = -1;
82 static int hf_old_pflog_dir = -1;
84 static gint ett_old_pflog = -1;
86 #define LEN_PFLOG_BSD34 48
87 #define LEN_PFLOG_BSD38 64
88 #define LEN_PFLOG_BSD49 100
90 static const value_string pflog_af_vals[] = {
91 { BSD_AF_INET, "IPv4" },
92 { BSD_AF_INET6_BSD, "IPv6" },
96 static const value_string pflog_reason_vals[] = {
106 { 9, "proto-cksum" },
107 { 10, "state-mismatch" },
108 { 11, "state-ins-fail" },
109 { 12, "max-states" },
110 { 13, "srcnode-limit" },
116 enum { PF_PASS, PF_DROP, PF_SCRUB, PF_NOSCRUB, PF_NAT, PF_NONAT,
117 PF_BINAT, PF_NOBINAT, PF_RDR, PF_NORDR, PF_SYNPROXY_DROP, PF_DEFER,
118 PF_MATCH, PF_DIVERT, PF_RT };
120 static const value_string pflog_action_vals[] = {
121 { PF_MATCH, "match" },
122 { PF_SCRUB, "scrub" },
124 { PF_DROP, "block" },
125 { PF_DIVERT, "divert" },
128 { PF_BINAT, "binat" },
129 { PF_NOBINAT, "binat" },
143 static const value_string pflog_old_dir_vals[] = {
145 { PF_OLD_OUT, "out" },
149 static const value_string pflog_dir_vals[] = {
150 { PF_INOUT, "inout" },
157 dissect_pflog(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
160 proto_tree *pflog_tree = NULL;
161 proto_item *ti = NULL, *ti_len;
169 col_set_str(pinfo->cinfo, COL_PROTOCOL, "PFLOG");
172 ti = proto_tree_add_item(tree, proto_pflog, tvb, offset, 0, ENC_NA);
174 pflog_tree = proto_item_add_subtree(ti, ett_pflog);
176 length = tvb_get_guint8(tvb, offset) + pad_len;
178 ti_len = proto_tree_add_item(pflog_tree, hf_pflog_length, tvb, offset, 1, ENC_BIG_ENDIAN);
179 if(length < LEN_PFLOG_BSD34)
181 expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR, "Invalid header length %u", length);
186 proto_tree_add_item(pflog_tree, hf_pflog_af, tvb, offset, 1, ENC_BIG_ENDIAN);
187 af = tvb_get_guint8(tvb, offset);
190 proto_tree_add_item(pflog_tree, hf_pflog_action, tvb, offset, 1, ENC_BIG_ENDIAN);
191 action = tvb_get_guint8(tvb, offset);
194 proto_tree_add_item(pflog_tree, hf_pflog_reason, tvb, offset, 1, ENC_BIG_ENDIAN);
197 proto_tree_add_item(pflog_tree, hf_pflog_ifname, tvb, offset, 16, ENC_ASCII|ENC_NA);
198 ifname = tvb_get_ephemeral_string(tvb, offset, 16);
201 proto_tree_add_item(pflog_tree, hf_pflog_ruleset, tvb, offset, 16, ENC_ASCII|ENC_NA);
204 proto_tree_add_item(pflog_tree, hf_pflog_rulenr, tvb, offset, 4, ENC_BIG_ENDIAN);
205 rulenr = tvb_get_ntohs(tvb, offset);
208 proto_tree_add_item(pflog_tree, hf_pflog_subrulenr, tvb, offset, 4, ENC_BIG_ENDIAN);
211 if(length >= LEN_PFLOG_BSD38)
213 proto_tree_add_item(pflog_tree, hf_pflog_uid, tvb, offset, 4, ENC_BIG_ENDIAN);
216 proto_tree_add_item(pflog_tree, hf_pflog_pid, tvb, offset, 4, ENC_BIG_ENDIAN);
219 proto_tree_add_item(pflog_tree, hf_pflog_rule_uid, tvb, offset, 4, ENC_BIG_ENDIAN);
222 proto_tree_add_item(pflog_tree, hf_pflog_rule_pid, tvb, offset, 4, ENC_BIG_ENDIAN);
225 proto_tree_add_item(pflog_tree, hf_pflog_dir, tvb, offset, 1, ENC_BIG_ENDIAN);
228 if(length >= LEN_PFLOG_BSD49)
231 length -= 3; /* With OpenBSD >= 4.8 the length is the length of full Header (with padding..) */
232 proto_tree_add_item(pflog_tree, hf_pflog_rewritten, tvb, offset, 1, ENC_BIG_ENDIAN);
236 proto_tree_add_item(pflog_tree, hf_pflog_pad, tvb, offset, pad_len, ENC_NA);
239 if(length >= LEN_PFLOG_BSD49)
244 proto_tree_add_item(pflog_tree, hf_pflog_saddr_ipv4, tvb, offset, 4, ENC_BIG_ENDIAN);
247 proto_tree_add_item(pflog_tree, hf_pflog_daddr_ipv4, tvb, offset, 4, ENC_BIG_ENDIAN);
251 case BSD_AF_INET6_BSD:
252 proto_tree_add_item(pflog_tree, hf_pflog_saddr_ipv6, tvb, offset, 16, ENC_NA);
255 proto_tree_add_item(pflog_tree, hf_pflog_daddr_ipv6, tvb, offset, 16, ENC_NA);
260 proto_tree_add_item(pflog_tree, hf_pflog_saddr, tvb, offset, 16, ENC_NA);
263 proto_tree_add_item(pflog_tree, hf_pflog_daddr, tvb, offset, 16, ENC_NA);
268 proto_tree_add_item(pflog_tree, hf_pflog_sport, tvb, offset, 2, ENC_BIG_ENDIAN);
271 proto_tree_add_item(pflog_tree, hf_pflog_dport, tvb, offset, 2, ENC_BIG_ENDIAN);
275 proto_item_set_text(ti, "PF Log %s %s on %s by rule %u",
276 val_to_str(af, pflog_af_vals, "unknown (%u)"),
277 val_to_str(action, pflog_action_vals, "unknown (%u)"),
280 proto_item_set_len(ti, offset);
284 /* Set the tvbuff for the payload after the header */
285 next_tvb = tvb_new_subset_remaining(tvb, length);
290 call_dissector(ip_handle, next_tvb, pinfo, tree);
293 case BSD_AF_INET6_BSD:
294 call_dissector(ipv6_handle, next_tvb, pinfo, tree);
298 call_dissector(data_handle, next_tvb, pinfo, tree);
302 if (check_col(pinfo->cinfo, COL_INFO)) {
303 col_prepend_fstr(pinfo->cinfo, COL_INFO, "[%s %s/%u] ",
304 val_to_str(action, pflog_action_vals, "unknown (%u)"),
311 proto_register_pflog(void)
313 static hf_register_info hf[] = {
315 { "Header Length", "pflog.length", FT_UINT8, BASE_DEC, NULL, 0x0,
316 "Length of Header", HFILL }},
318 { "Address Family", "pflog.af", FT_UINT32, BASE_DEC, VALS(pflog_af_vals), 0x0,
319 "Protocol (IPv4 vs IPv6)", HFILL }},
321 { "Action", "pflog.action", FT_UINT8, BASE_DEC, VALS(pflog_action_vals), 0x0,
322 "Action taken by PF on the packet", HFILL }},
324 { "Reason", "pflog.reason", FT_UINT8, BASE_DEC, VALS(pflog_reason_vals), 0x0,
325 "Reason for logging the packet", HFILL }},
327 { "Interface", "pflog.ifname", FT_STRING, BASE_NONE, NULL, 0x0,
330 { "Ruleset", "pflog.ruleset", FT_STRING, BASE_NONE, NULL, 0x0,
331 "Ruleset name in anchor", HFILL }},
333 { "Rule Number", "pflog.rulenr", FT_INT32, BASE_DEC, NULL, 0x0,
334 "Last matched firewall main ruleset rule number", HFILL }},
335 { &hf_pflog_subrulenr,
336 { "Sub Rule Number", "pflog.subrulenr", FT_INT32, BASE_DEC, NULL, 0x0,
337 "Last matched firewall anchored ruleset rule number", HFILL }},
339 { "UID", "pflog.uid", FT_INT32, BASE_DEC, NULL, 0x0,
342 { "PID", "pflog.pid", FT_INT32, BASE_DEC, NULL, 0x0,
344 { &hf_pflog_rule_uid,
345 { "Rule UID", "pflog.rule_uid", FT_INT32, BASE_DEC, NULL, 0x0,
347 { &hf_pflog_rule_pid,
348 { "Rule PID", "pflog.rule_pid", FT_INT32, BASE_DEC, NULL, 0x0,
350 { &hf_pflog_rewritten,
351 { "Rewritten", "pflog.rewritten", FT_UINT8, BASE_DEC, NULL, 0x0,
354 { "Padding", "pflog.pad", FT_BYTES, BASE_NONE, NULL, 0x0,
355 "Must be Zero", HFILL }},
356 { &hf_pflog_saddr_ipv4,
357 { "Source Address", "pflog.saddr", FT_IPv4, BASE_NONE, NULL, 0x0,
359 { &hf_pflog_daddr_ipv4,
360 { "Destination Address", "pflog.daddr", FT_IPv4, BASE_NONE, NULL, 0x0,
362 { &hf_pflog_saddr_ipv6,
363 { "Source Address", "pflog.saddr", FT_IPv6, BASE_NONE, NULL, 0x0,
365 { &hf_pflog_daddr_ipv6,
366 { "Destination Address", "pflog.daddr", FT_IPv6, BASE_NONE, NULL, 0x0,
369 { "Source Address", "pflog.saddr", FT_BYTES, BASE_NONE, NULL, 0x0,
372 { "Destination Address", "pflog.daddr", FT_BYTES, BASE_NONE, NULL, 0x0,
375 { "Source Port", "pflog.sport", FT_UINT16, BASE_DEC, NULL, 0x0,
378 { "Destination Port", "pflog.dport", FT_UINT16, BASE_DEC, NULL, 0x0,
381 { "Direction", "pflog.dir", FT_UINT8, BASE_DEC, VALS(pflog_dir_vals), 0x0,
382 "Direction of packet in stack (inbound versus outbound)", HFILL }},
384 static gint *ett[] = { &ett_pflog };
386 proto_pflog = proto_register_protocol("OpenBSD Packet Filter log file",
388 proto_register_field_array(proto_pflog, hf, array_length(hf));
389 proto_register_subtree_array(ett, array_length(ett));
393 proto_reg_handoff_pflog(void)
395 dissector_handle_t pflog_handle;
397 ip_handle = find_dissector("ip");
398 ipv6_handle = find_dissector("ipv6");
399 data_handle = find_dissector("data");
401 pflog_handle = create_dissector_handle(dissect_pflog, proto_pflog);
402 dissector_add_uint("wtap_encap", WTAP_ENCAP_PFLOG, pflog_handle);
406 dissect_old_pflog(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
409 proto_tree *pflog_tree = NULL;
410 proto_item *ti = NULL;
416 col_set_str(pinfo->cinfo, COL_PROTOCOL, "PFLOG-OLD");
419 ti = proto_tree_add_item(tree, proto_old_pflog, tvb, 0, 0, ENC_NA);
421 pflog_tree = proto_item_add_subtree(ti, ett_pflog);
423 proto_tree_add_item(pflog_tree, hf_old_pflog_af, tvb, offset, 4, ENC_BIG_ENDIAN);
425 af = tvb_get_ntohl(tvb, offset);
429 proto_tree_add_item(pflog_tree, hf_old_pflog_ifname, tvb, offset, 16, ENC_ASCII|ENC_NA);
431 ifname = tvb_get_ephemeral_string(tvb, offset, 16);
435 proto_tree_add_item(pflog_tree, hf_old_pflog_rnr, tvb, offset, 2, ENC_BIG_ENDIAN);
437 rnr = tvb_get_ntohs(tvb, offset);
441 proto_tree_add_item(pflog_tree, hf_old_pflog_reason, tvb, offset, 2, ENC_BIG_ENDIAN);
446 proto_tree_add_item(pflog_tree, hf_old_pflog_action, tvb, offset, 2, ENC_BIG_ENDIAN);
448 action = tvb_get_ntohs(tvb, offset);
452 proto_tree_add_item(pflog_tree, hf_old_pflog_dir, tvb, offset, 2, ENC_BIG_ENDIAN);
457 proto_item_set_text(ti, "PF Log (pre 3.4) %s %s on %s by rule %d",
458 val_to_str(af, pflog_af_vals, "unknown (%u)"),
459 val_to_str(action, pflog_action_vals, "unknown (%u)"),
462 proto_item_set_len(ti, offset);
466 /* Set the tvbuff for the payload after the header */
467 next_tvb = tvb_new_subset_remaining(tvb, offset);
472 offset += call_dissector(ip_handle, next_tvb, pinfo, tree);
475 case BSD_AF_INET6_BSD:
476 offset += call_dissector(ipv6_handle, next_tvb, pinfo, tree);
480 offset += call_dissector(data_handle, next_tvb, pinfo, tree);
484 if (check_col(pinfo->cinfo, COL_INFO)) {
485 col_prepend_fstr(pinfo->cinfo, COL_INFO, "[%s %s/#%d] ",
486 val_to_str(action, pflog_action_vals, "unknown (%u)"),
494 proto_register_old_pflog(void)
496 static hf_register_info hf[] = {
498 { "Address Family", "pflog.af", FT_UINT32, BASE_DEC, VALS(pflog_af_vals), 0x0,
499 "Protocol (IPv4 vs IPv6)", HFILL }},
500 { &hf_old_pflog_ifname,
501 { "Interface", "pflog.ifname", FT_STRING, BASE_NONE, NULL, 0x0,
504 { "Rule Number", "pflog.rnr", FT_INT16, BASE_DEC, NULL, 0x0,
505 "Last matched firewall rule number", HFILL }},
506 { &hf_old_pflog_reason,
507 { "Reason", "pflog.reason", FT_UINT16, BASE_DEC, VALS(pflog_reason_vals), 0x0,
508 "Reason for logging the packet", HFILL }},
509 { &hf_old_pflog_action,
510 { "Action", "pflog.action", FT_UINT16, BASE_DEC, VALS(pflog_action_vals), 0x0,
511 "Action taken by PF on the packet", HFILL }},
513 { "Direction", "pflog.dir", FT_UINT16, BASE_DEC, VALS(pflog_old_dir_vals), 0x0,
514 "Direction of packet in stack (inbound versus outbound)", HFILL }},
516 static gint *ett[] = { &ett_old_pflog };
518 proto_old_pflog = proto_register_protocol(
519 "OpenBSD Packet Filter log file, pre 3.4",
520 "PFLOG-OLD", "pflog-old");
521 proto_register_field_array(proto_old_pflog, hf, array_length(hf));
522 proto_register_subtree_array(ett, array_length(ett));
526 proto_reg_handoff_old_pflog(void)
528 dissector_handle_t pflog_handle;
530 ip_handle = find_dissector("ip");
531 ipv6_handle = find_dissector("ipv6");
532 data_handle = find_dissector("data");
534 pflog_handle = new_create_dissector_handle(dissect_old_pflog, proto_old_pflog);
535 dissector_add_uint("wtap_encap", WTAP_ENCAP_OLD_PFLOG, pflog_handle);
543 * indent-tabs-mode: nil
546 * ex: set shiftwidth=2 tabstop=8 expandtab:
547 * :indentSize=2:tabSize=8:noTabs=true: