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