xref: /openbsd-src/usr.sbin/tcpdump/print-pflog.c (revision a28daedfc357b214be5c701aa8ba8adb29a7f1c2)
1 /*	$OpenBSD: print-pflog.c,v 1.19 2009/04/06 12:09:06 henning Exp $	*/
2 
3 /*
4  * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that: (1) source code distributions
9  * retain the above copyright notice and this paragraph in its entirety, (2)
10  * distributions including binary code include the above copyright notice and
11  * this paragraph in its entirety in the documentation or other materials
12  * provided with the distribution, and (3) all advertising materials mentioning
13  * features or use of this software display the following acknowledgement:
14  * ``This product includes software developed by the University of California,
15  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
16  * the University nor the names of its contributors may be used to endorse
17  * or promote products derived from this software without specific prior
18  * written permission.
19  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
20  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
21  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22  */
23 
24 #ifndef lint
25 static const char rcsid[] =
26     "@(#) $Id: print-pflog.c,v 1.19 2009/04/06 12:09:06 henning Exp $ (LBL)";
27 #endif
28 
29 #include <sys/param.h>
30 #include <sys/time.h>
31 #include <sys/socket.h>
32 #include <sys/file.h>
33 #include <sys/ioctl.h>
34 #include <sys/mbuf.h>
35 #include <sys/proc.h>
36 
37 #ifndef NO_PID
38 #define NO_PID	(32766+1)
39 #endif
40 
41 struct rtentry;
42 #include <net/if.h>
43 #include <net/if_pflog.h>
44 
45 #include <netinet/in.h>
46 #include <netinet/in_systm.h>
47 #include <netinet/ip.h>
48 
49 #include <net/pfvar.h>
50 
51 #include <ctype.h>
52 #include <netdb.h>
53 #include <pcap.h>
54 #include <signal.h>
55 #include <stdio.h>
56 
57 #include "interface.h"
58 #include "addrtoname.h"
59 
60 char *pf_reasons[PFRES_MAX+2] = PFRES_NAMES;
61 
62 void
63 pflog_if_print(u_char *user, const struct pcap_pkthdr *h,
64      register const u_char *p)
65 {
66 	u_int length = h->len;
67 	u_int hdrlen;
68 	u_int caplen = h->caplen;
69 	const struct ip *ip;
70 #ifdef INET6
71 	const struct ip6_hdr *ip6;
72 #endif
73 	const struct pfloghdr *hdr;
74 	u_int8_t af;
75 
76 	ts_print(&h->ts);
77 
78 	/* check length */
79 	if (caplen < sizeof(u_int8_t)) {
80 		printf("[|pflog]");
81 		goto out;
82 	}
83 
84 #define MIN_PFLOG_HDRLEN	45
85 	hdr = (struct pfloghdr *)p;
86 	if (hdr->length < MIN_PFLOG_HDRLEN) {
87 		printf("[pflog: invalid header length!]");
88 		goto out;
89 	}
90 	hdrlen = BPF_WORDALIGN(hdr->length);
91 
92 	if (caplen < hdrlen) {
93 		printf("[|pflog]");
94 		goto out;
95 	}
96 
97 	/*
98 	 * Some printers want to get back at the link level addresses,
99 	 * and/or check that they're not walking off the end of the packet.
100 	 * Rather than pass them all the way down, we set these globals.
101 	 */
102 	packetp = p;
103 	snapend = p + caplen;
104 
105 	hdr = (struct pfloghdr *)p;
106 	if (eflag) {
107 		printf("rule ");
108 		if (ntohl(hdr->rulenr) == (u_int32_t) -1)
109 			printf("def");
110 		else {
111 			printf("%u", ntohl(hdr->rulenr));
112 			if (hdr->ruleset[0]) {
113 				printf(".%s", hdr->ruleset);
114 				if (ntohl(hdr->subrulenr) == (u_int32_t) -1)
115 					printf(".def");
116 				else
117 					printf(".%u", ntohl(hdr->subrulenr));
118 			}
119 		}
120 		if (hdr->reason < PFRES_MAX)
121 			printf("/(%s) ", pf_reasons[hdr->reason]);
122 		else
123 			printf("/(unkn %u) ", (unsigned)hdr->reason);
124 		if (vflag)
125 			printf("[uid %u, pid %u] ", (unsigned)hdr->rule_uid,
126 			    (unsigned)hdr->rule_pid);
127 
128 		switch (hdr->action) {
129 		case PF_MATCH:
130 			printf("match");
131 			break;
132 		case PF_SCRUB:
133 			printf("scrub");
134 			break;
135 		case PF_PASS:
136 			printf("pass");
137 			break;
138 		case PF_DROP:
139 			printf("block");
140 			break;
141 		case PF_NAT:
142 		case PF_NONAT:
143 			printf("nat");
144 			break;
145 		case PF_BINAT:
146 		case PF_NOBINAT:
147 			printf("binat");
148 			break;
149 		case PF_RDR:
150 		case PF_NORDR:
151 			printf("rdr");
152 			break;
153 		}
154 		printf(" %s on %s: ",
155 		    hdr->dir == PF_OUT ? "out" : "in",
156 		    hdr->ifname);
157 		if (vflag && hdr->pid != NO_PID)
158 			printf("[uid %u, pid %u] ", (unsigned)hdr->uid,
159 			    (unsigned)hdr->pid);
160 	}
161 	af = hdr->af;
162 	length -= hdrlen;
163 	if (af == AF_INET) {
164 		ip = (struct ip *)(p + hdrlen);
165 		ip_print((const u_char *)ip, length);
166 		if (xflag)
167 			default_print((const u_char *)ip,
168 			    caplen - hdrlen);
169 	} else {
170 #ifdef INET6
171 		ip6 = (struct ip6_hdr *)(p + hdrlen);
172 		ip6_print((const u_char *)ip6, length);
173 		if (xflag)
174 			default_print((const u_char *)ip6,
175 			    caplen - hdrlen);
176 #endif
177 	}
178 
179 out:
180 	putchar('\n');
181 }
182 
183 
184 void
185 pflog_old_if_print(u_char *user, const struct pcap_pkthdr *h,
186      register const u_char *p)
187 {
188 	u_int length = h->len;
189 	u_int caplen = h->caplen;
190 	const struct ip *ip;
191 #ifdef INET6
192 	const struct ip6_hdr *ip6;
193 #endif
194 	const struct old_pfloghdr *hdr;
195 	u_short res;
196 	char reason[128], *why;
197 	u_int8_t af;
198 
199 	ts_print(&h->ts);
200 
201 	if (caplen < OLD_PFLOG_HDRLEN) {
202 		printf("[|pflog]");
203 		goto out;
204 	}
205 
206 	/*
207 	 * Some printers want to get back at the link level addresses,
208 	 * and/or check that they're not walking off the end of the packet.
209 	 * Rather than pass them all the way down, we set these globals.
210 	 */
211 	packetp = p;
212 	snapend = p + caplen;
213 
214 	hdr = (struct old_pfloghdr *)p;
215 	if (eflag) {
216 		res = ntohs(hdr->reason);
217 		why = (res < PFRES_MAX) ? pf_reasons[res] : "unkn";
218 
219 		snprintf(reason, sizeof(reason), "%d(%s)", res, why);
220 
221 		printf("rule %d/%s: ",
222 		    (short)ntohs(hdr->rnr), reason);
223 		switch (ntohs(hdr->action)) {
224 		case PF_MATCH:
225 			printf("match");
226 			break;
227 		case PF_SCRUB:
228 			printf("scrub");
229 			break;
230 		case PF_PASS:
231 			printf("pass");
232 			break;
233 		case PF_DROP:
234 			printf("block");
235 			break;
236 		case PF_NAT:
237 		case PF_NONAT:
238 			printf("nat");
239 			break;
240 		case PF_BINAT:
241 		case PF_NOBINAT:
242 			printf("binat");
243 			break;
244 		case PF_RDR:
245 		case PF_NORDR:
246 			printf("rdr");
247 			break;
248 		}
249 		printf(" %s on %s: ",
250 		    ntohs(hdr->dir) == PF_OUT ? "out" : "in",
251 		    hdr->ifname);
252 	}
253 	af = ntohl(hdr->af);
254 	length -= OLD_PFLOG_HDRLEN;
255 	if (af == AF_INET) {
256 		ip = (struct ip *)(p + OLD_PFLOG_HDRLEN);
257 		ip_print((const u_char *)ip, length);
258 		if (xflag)
259 			default_print((const u_char *)ip,
260 			    caplen - OLD_PFLOG_HDRLEN);
261 	} else {
262 #ifdef INET6
263 		ip6 = (struct ip6_hdr *)(p + OLD_PFLOG_HDRLEN);
264 		ip6_print((const u_char *)ip6, length);
265 		if (xflag)
266 			default_print((const u_char *)ip6,
267 			    caplen - OLD_PFLOG_HDRLEN);
268 #endif
269 	}
270 
271 out:
272 	putchar('\n');
273 }
274