Some minor bugfixes for netlogon
[obnox/wireshark/wip.git] / packet-pflog.c
1 /* packet-pflog.c
2  * Routines for pflog (OpenBSD Firewall Logging) packet disassembly
3  *
4  * $Id: packet-pflog.c,v 1.3 2002/02/05 00:43:59 guy Exp $
5  *
6  * Copyright 2001 Mike Frantzen
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  *    - Redistributions of source code must retain the above copyright
14  *      notice, this list of conditions and the following disclaimer.
15  *      with the distribution.
16  *          
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.
29  */
30
31 #ifdef HAVE_CONFIG_H
32 # include "config.h"
33 #endif
34
35 #ifdef HAVE_SYS_TYPES_H
36 # include <sys/types.h>
37 #endif
38
39 #include <string.h>
40 #include <glib.h>
41 #include <epan/packet.h>
42 #include "etypes.h"
43 #include <epan/resolv.h>
44 #include "packet-ip.h"
45 #include "packet-ipv6.h"
46 #include "packet-pflog.h"
47
48 #ifndef offsetof
49 /* Can't trust stddef.h to be there for us */
50 # define offsetof(type, member) ((size_t)(&((type *)0)->member))
51 #endif
52
53 static dissector_handle_t  data_handle, ip_handle, ipv6_handle, pflog_handle;
54
55 /* header fields */
56 static int proto_pflog = -1;
57 static int hf_pflog_af = -1;
58 static int hf_pflog_ifname = -1;
59 static int hf_pflog_rnr = -1;
60 static int hf_pflog_reason = -1;
61 static int hf_pflog_action = -1;
62 static int hf_pflog_dir = -1;
63
64 static gint ett_pflog = -1;
65
66 void
67 capture_pflog(const u_char *pd, int offset, int len, packet_counts *ld)
68 {
69   struct pfloghdr pflogh;
70
71   if (!BYTES_ARE_IN_FRAME(offset, len, (int)PFLOG_HDRLEN)) {
72     ld->other++;
73     return;
74   }
75
76   offset += PFLOG_HDRLEN;
77   
78   /* Copy out the pflog header to insure alignment */
79   memcpy(&pflogh, pd, sizeof(pflogh));
80   NTOHL(pflogh.af);
81
82   switch (pflogh.af) {
83
84   case BSD_PF_INET:
85     capture_ip(pd, offset, len, ld);
86     break;
87
88 #ifdef notyet
89   case BSD_PF_INET6:
90     capture_ipv6(pd, offset, len, ld);
91     break;
92 #endif
93
94   default:
95     ld->other++;
96     break;
97   }
98 }
99
100 static const value_string af_vals[] = {
101   { BSD_PF_INET,  "IPv4" },
102   { BSD_PF_INET6, "IPv6" },
103   { 0,            NULL }
104 };
105
106 static const value_string reason_vals[] = {
107   { 0, "match" },
108   { 1, "bad-offset" },
109   { 2, "fragment" },
110   { 3, "short" },
111   { 4, "normalize" },
112   { 5, "memory" },
113   { 0, NULL }
114 };
115
116 static const value_string action_vals[] = {
117   { PF_PASS,  "passed" },
118   { PF_DROP,  "dropped" },
119   { PF_SCRUB, "scrubbed" },
120   { 0,        NULL }
121 };
122
123 static const value_string dir_vals[] = {
124   { PF_IN,  "in" },
125   { PF_OUT, "out" },
126   { 0,      NULL }
127 };
128
129 static void
130 dissect_pflog(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
131 {
132   struct pfloghdr pflogh;
133   tvbuff_t *next_tvb;
134   proto_tree *pflog_tree;
135   proto_item *ti;
136
137   if (check_col(pinfo->cinfo, COL_PROTOCOL))
138     col_set_str(pinfo->cinfo, COL_PROTOCOL, "PFLOG");
139
140   /* Copy out the pflog header to insure alignment */
141   tvb_memcpy(tvb, (guint8 *)&pflogh, 0, sizeof(pflogh));
142
143   /* Byteswap the header now */
144   NTOHL(pflogh.af);
145   NTOHS(pflogh.rnr);
146   NTOHS(pflogh.reason);
147   NTOHS(pflogh.action);
148   NTOHS(pflogh.dir);
149
150   if (tree) {
151     ti = proto_tree_add_protocol_format(tree, proto_pflog, tvb, 0,
152              PFLOG_HDRLEN,
153              "PF Log %s %s on %s by rule %d",
154              val_to_str(pflogh.af, af_vals, "unknown (%u)"),
155              val_to_str(pflogh.action, action_vals, "unknown (%u)"),
156              pflogh.ifname,
157              pflogh.rnr);
158     pflog_tree = proto_item_add_subtree(ti, ett_pflog);
159
160     proto_tree_add_uint(pflog_tree, hf_pflog_af, tvb,
161              offsetof(struct pfloghdr, af), sizeof(pflogh.af),
162              pflogh.af);
163     proto_tree_add_int(pflog_tree, hf_pflog_rnr, tvb,
164              offsetof(struct pfloghdr, rnr), sizeof(pflogh.rnr),
165              pflogh.rnr);
166     proto_tree_add_string(pflog_tree, hf_pflog_ifname, tvb,
167              offsetof(struct pfloghdr, ifname), sizeof(pflogh.ifname),
168              pflogh.ifname);
169     proto_tree_add_uint(pflog_tree, hf_pflog_reason, tvb,
170              offsetof(struct pfloghdr, reason), sizeof(pflogh.reason),
171              pflogh.reason);
172     proto_tree_add_uint(pflog_tree, hf_pflog_action, tvb,
173              offsetof(struct pfloghdr, action), sizeof(pflogh.action),
174              pflogh.action);
175     proto_tree_add_uint(pflog_tree, hf_pflog_dir, tvb,
176              offsetof(struct pfloghdr, dir), sizeof(pflogh.dir),
177              pflogh.dir);
178   }
179
180   /* Set the tvbuff for the payload after the header */
181   next_tvb = tvb_new_subset(tvb, PFLOG_HDRLEN, -1, -1);
182
183   switch (pflogh.af) {
184
185   case BSD_PF_INET:
186     call_dissector(ip_handle, next_tvb, pinfo, tree);
187     break;
188
189   case BSD_PF_INET6:
190     call_dissector(ipv6_handle, next_tvb, pinfo, tree);
191     break;
192
193   default:
194     call_dissector(data_handle, next_tvb, pinfo, tree);
195     break;
196   }
197
198   if (check_col(pinfo->cinfo, COL_INFO)) {
199     col_prepend_fstr(pinfo->cinfo, COL_INFO, "[%s %s/#%d] ",
200         val_to_str(pflogh.action, action_vals, "unknown (%u)"),
201         pflogh.ifname,
202         pflogh.rnr);
203   }
204 }
205
206 void
207 proto_register_pflog(void)
208 {
209   static hf_register_info hf[] = {
210     { &hf_pflog_af,
211       { "Address Family", "pflog.af", FT_UINT32, BASE_DEC, VALS(af_vals), 0x0,
212         "Protocol (IPv4 vs IPv6)", HFILL }},
213     { &hf_pflog_ifname,
214       { "Interface", "pflog.ifname", FT_STRING, BASE_NONE, NULL, 0x0,
215         "Interface", HFILL }},
216     { &hf_pflog_rnr,
217       { "Rule Number", "pflog.rnr", FT_INT16, BASE_DEC, NULL, 0x0,
218         "Last matched firewall rule number", HFILL }},
219     { &hf_pflog_reason,
220       { "Reason", "pflog.reason", FT_UINT16, BASE_DEC, VALS(reason_vals), 0x0,
221         "Reason for logging the packet", HFILL }},
222     { &hf_pflog_action,
223       { "Action", "pflog.action", FT_UINT16, BASE_DEC, VALS(action_vals), 0x0,
224         "Action taken by PF on the packet", HFILL }},
225     { &hf_pflog_dir,
226       { "Direction", "pflog.dir", FT_UINT16, BASE_DEC, VALS(dir_vals), 0x0,
227         "Direction of packet in stack (inbound versus outbound)", HFILL }},
228   };
229   static gint *ett[] = { &ett_pflog };
230
231   proto_pflog = proto_register_protocol("OpenBSD Packet Filter log file",
232                                         "PFLOG", "pflog");
233   proto_register_field_array(proto_pflog, hf, array_length(hf));
234   proto_register_subtree_array(ett, array_length(ett));
235
236   register_dissector("pflog", dissect_pflog, proto_pflog);
237 }
238
239 void
240 proto_reg_handoff_pflog(void)
241 {
242   dissector_handle_t pflog_handle;
243
244   pflog_handle = find_dissector("pflog");
245   ip_handle = find_dissector("ip");
246   ipv6_handle = find_dissector("ipv6");
247   data_handle = find_dissector("data");
248   dissector_add("wtap_encap", WTAP_ENCAP_PFLOG, pflog_handle);
249 }