xref: /openbsd-src/usr.sbin/tcpdump/print-pflog.c (revision 7bbe964f6b7d22ad07ca46292495604f942eba4e)
1 /*	$OpenBSD: print-pflog.c,v 1.20 2009/10/27 23:59:55 deraadt 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 #include <sys/param.h>
25 #include <sys/time.h>
26 #include <sys/socket.h>
27 #include <sys/file.h>
28 #include <sys/ioctl.h>
29 #include <sys/mbuf.h>
30 #include <sys/proc.h>
31 
32 #ifndef NO_PID
33 #define NO_PID	(32766+1)
34 #endif
35 
36 struct rtentry;
37 #include <net/if.h>
38 #include <net/if_pflog.h>
39 
40 #include <netinet/in.h>
41 #include <netinet/in_systm.h>
42 #include <netinet/ip.h>
43 
44 #include <net/pfvar.h>
45 
46 #include <ctype.h>
47 #include <netdb.h>
48 #include <pcap.h>
49 #include <signal.h>
50 #include <stdio.h>
51 
52 #include "interface.h"
53 #include "addrtoname.h"
54 
55 char *pf_reasons[PFRES_MAX+2] = PFRES_NAMES;
56 
57 void
58 pflog_if_print(u_char *user, const struct pcap_pkthdr *h,
59      register const u_char *p)
60 {
61 	u_int length = h->len;
62 	u_int hdrlen;
63 	u_int caplen = h->caplen;
64 	const struct ip *ip;
65 #ifdef INET6
66 	const struct ip6_hdr *ip6;
67 #endif
68 	const struct pfloghdr *hdr;
69 	u_int8_t af;
70 
71 	ts_print(&h->ts);
72 
73 	/* check length */
74 	if (caplen < sizeof(u_int8_t)) {
75 		printf("[|pflog]");
76 		goto out;
77 	}
78 
79 #define MIN_PFLOG_HDRLEN	45
80 	hdr = (struct pfloghdr *)p;
81 	if (hdr->length < MIN_PFLOG_HDRLEN) {
82 		printf("[pflog: invalid header length!]");
83 		goto out;
84 	}
85 	hdrlen = BPF_WORDALIGN(hdr->length);
86 
87 	if (caplen < hdrlen) {
88 		printf("[|pflog]");
89 		goto out;
90 	}
91 
92 	/*
93 	 * Some printers want to get back at the link level addresses,
94 	 * and/or check that they're not walking off the end of the packet.
95 	 * Rather than pass them all the way down, we set these globals.
96 	 */
97 	packetp = p;
98 	snapend = p + caplen;
99 
100 	hdr = (struct pfloghdr *)p;
101 	if (eflag) {
102 		printf("rule ");
103 		if (ntohl(hdr->rulenr) == (u_int32_t) -1)
104 			printf("def");
105 		else {
106 			printf("%u", ntohl(hdr->rulenr));
107 			if (hdr->ruleset[0]) {
108 				printf(".%s", hdr->ruleset);
109 				if (ntohl(hdr->subrulenr) == (u_int32_t) -1)
110 					printf(".def");
111 				else
112 					printf(".%u", ntohl(hdr->subrulenr));
113 			}
114 		}
115 		if (hdr->reason < PFRES_MAX)
116 			printf("/(%s) ", pf_reasons[hdr->reason]);
117 		else
118 			printf("/(unkn %u) ", (unsigned)hdr->reason);
119 		if (vflag)
120 			printf("[uid %u, pid %u] ", (unsigned)hdr->rule_uid,
121 			    (unsigned)hdr->rule_pid);
122 
123 		switch (hdr->action) {
124 		case PF_MATCH:
125 			printf("match");
126 			break;
127 		case PF_SCRUB:
128 			printf("scrub");
129 			break;
130 		case PF_PASS:
131 			printf("pass");
132 			break;
133 		case PF_DROP:
134 			printf("block");
135 			break;
136 		case PF_NAT:
137 		case PF_NONAT:
138 			printf("nat");
139 			break;
140 		case PF_BINAT:
141 		case PF_NOBINAT:
142 			printf("binat");
143 			break;
144 		case PF_RDR:
145 		case PF_NORDR:
146 			printf("rdr");
147 			break;
148 		}
149 		printf(" %s on %s: ",
150 		    hdr->dir == PF_OUT ? "out" : "in",
151 		    hdr->ifname);
152 		if (vflag && hdr->pid != NO_PID)
153 			printf("[uid %u, pid %u] ", (unsigned)hdr->uid,
154 			    (unsigned)hdr->pid);
155 	}
156 	af = hdr->af;
157 	length -= hdrlen;
158 	if (af == AF_INET) {
159 		ip = (struct ip *)(p + hdrlen);
160 		ip_print((const u_char *)ip, length);
161 		if (xflag)
162 			default_print((const u_char *)ip,
163 			    caplen - hdrlen);
164 	} else {
165 #ifdef INET6
166 		ip6 = (struct ip6_hdr *)(p + hdrlen);
167 		ip6_print((const u_char *)ip6, length);
168 		if (xflag)
169 			default_print((const u_char *)ip6,
170 			    caplen - hdrlen);
171 #endif
172 	}
173 
174 out:
175 	putchar('\n');
176 }
177 
178 
179 void
180 pflog_old_if_print(u_char *user, const struct pcap_pkthdr *h,
181      register const u_char *p)
182 {
183 	u_int length = h->len;
184 	u_int caplen = h->caplen;
185 	const struct ip *ip;
186 #ifdef INET6
187 	const struct ip6_hdr *ip6;
188 #endif
189 	const struct old_pfloghdr *hdr;
190 	u_short res;
191 	char reason[128], *why;
192 	u_int8_t af;
193 
194 	ts_print(&h->ts);
195 
196 	if (caplen < OLD_PFLOG_HDRLEN) {
197 		printf("[|pflog]");
198 		goto out;
199 	}
200 
201 	/*
202 	 * Some printers want to get back at the link level addresses,
203 	 * and/or check that they're not walking off the end of the packet.
204 	 * Rather than pass them all the way down, we set these globals.
205 	 */
206 	packetp = p;
207 	snapend = p + caplen;
208 
209 	hdr = (struct old_pfloghdr *)p;
210 	if (eflag) {
211 		res = ntohs(hdr->reason);
212 		why = (res < PFRES_MAX) ? pf_reasons[res] : "unkn";
213 
214 		snprintf(reason, sizeof(reason), "%d(%s)", res, why);
215 
216 		printf("rule %d/%s: ",
217 		    (short)ntohs(hdr->rnr), reason);
218 		switch (ntohs(hdr->action)) {
219 		case PF_MATCH:
220 			printf("match");
221 			break;
222 		case PF_SCRUB:
223 			printf("scrub");
224 			break;
225 		case PF_PASS:
226 			printf("pass");
227 			break;
228 		case PF_DROP:
229 			printf("block");
230 			break;
231 		case PF_NAT:
232 		case PF_NONAT:
233 			printf("nat");
234 			break;
235 		case PF_BINAT:
236 		case PF_NOBINAT:
237 			printf("binat");
238 			break;
239 		case PF_RDR:
240 		case PF_NORDR:
241 			printf("rdr");
242 			break;
243 		}
244 		printf(" %s on %s: ",
245 		    ntohs(hdr->dir) == PF_OUT ? "out" : "in",
246 		    hdr->ifname);
247 	}
248 	af = ntohl(hdr->af);
249 	length -= OLD_PFLOG_HDRLEN;
250 	if (af == AF_INET) {
251 		ip = (struct ip *)(p + OLD_PFLOG_HDRLEN);
252 		ip_print((const u_char *)ip, length);
253 		if (xflag)
254 			default_print((const u_char *)ip,
255 			    caplen - OLD_PFLOG_HDRLEN);
256 	} else {
257 #ifdef INET6
258 		ip6 = (struct ip6_hdr *)(p + OLD_PFLOG_HDRLEN);
259 		ip6_print((const u_char *)ip6, length);
260 		if (xflag)
261 			default_print((const u_char *)ip6,
262 			    caplen - OLD_PFLOG_HDRLEN);
263 #endif
264 	}
265 
266 out:
267 	putchar('\n');
268 }
269