xref: /openbsd-src/sys/net/if_pflog.c (revision db3296cf5c1dd9058ceecc3a29fe4aaa0bd26000)
1 /*	$OpenBSD: if_pflog.c,v 1.9 2003/05/14 08:42:00 canacar Exp $	*/
2 /*
3  * The authors of this code are John Ioannidis (ji@tla.org),
4  * Angelos D. Keromytis (kermit@csd.uch.gr) and
5  * Niels Provos (provos@physnet.uni-hamburg.de).
6  *
7  * This code was written by John Ioannidis for BSD/OS in Athens, Greece,
8  * in November 1995.
9  *
10  * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
11  * by Angelos D. Keromytis.
12  *
13  * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
14  * and Niels Provos.
15  *
16  * Copyright (C) 1995, 1996, 1997, 1998 by John Ioannidis, Angelos D. Keromytis
17  * and Niels Provos.
18  * Copyright (c) 2001, Angelos D. Keromytis, Niels Provos.
19  *
20  * Permission to use, copy, and modify this software with or without fee
21  * is hereby granted, provided that this entire notice is included in
22  * all copies of any software which is or includes a copy or
23  * modification of this software.
24  * You may use this code under the GNU public license if you so wish. Please
25  * contribute changes back to the authors under this freer than GPL license
26  * so that we may further the use of strong encryption without limitations to
27  * all.
28  *
29  * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
30  * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
31  * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
32  * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
33  * PURPOSE.
34  */
35 
36 #include "bpfilter.h"
37 #include "pflog.h"
38 
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/mbuf.h>
42 #include <sys/socket.h>
43 #include <sys/ioctl.h>
44 
45 #include <net/if.h>
46 #include <net/if_types.h>
47 #include <net/route.h>
48 #include <net/bpf.h>
49 
50 #ifdef	INET
51 #include <netinet/in.h>
52 #include <netinet/in_var.h>
53 #include <netinet/in_systm.h>
54 #include <netinet/ip.h>
55 #endif
56 
57 #ifdef INET6
58 #ifndef INET
59 #include <netinet/in.h>
60 #endif
61 #include <netinet6/nd6.h>
62 #endif /* INET6 */
63 
64 #include <net/pfvar.h>
65 #include <net/if_pflog.h>
66 
67 #define PFLOGMTU	(32768 + MHLEN + MLEN)
68 
69 #ifdef PFLOGDEBUG
70 #define DPRINTF(x)    do { if (pflogdebug) printf x ; } while (0)
71 #else
72 #define DPRINTF(x)
73 #endif
74 
75 struct pflog_softc pflogif[NPFLOG];
76 
77 void	pflogattach(int);
78 int	pflogoutput(struct ifnet *, struct mbuf *, struct sockaddr *,
79 	    	       struct rtentry *);
80 int	pflogioctl(struct ifnet *, u_long, caddr_t);
81 void	pflogrtrequest(int, struct rtentry *, struct sockaddr *);
82 void	pflogstart(struct ifnet *);
83 
84 extern int ifqmaxlen;
85 
86 void
87 pflogattach(int npflog)
88 {
89 	struct ifnet *ifp;
90 	int i;
91 
92 	bzero(pflogif, sizeof(pflogif));
93 
94 	for (i = 0; i < NPFLOG; i++) {
95 		ifp = &pflogif[i].sc_if;
96 		snprintf(ifp->if_xname, sizeof ifp->if_xname, "pflog%d", i);
97 		ifp->if_softc = &pflogif[i];
98 		ifp->if_mtu = PFLOGMTU;
99 		ifp->if_ioctl = pflogioctl;
100 		ifp->if_output = pflogoutput;
101 		ifp->if_start = pflogstart;
102 		ifp->if_type = IFT_PFLOG;
103 		ifp->if_snd.ifq_maxlen = ifqmaxlen;
104 		ifp->if_hdrlen = PFLOG_HDRLEN;
105 		if_attach(ifp);
106 		if_alloc_sadl(ifp);
107 
108 #if NBPFILTER > 0
109 		bpfattach(&pflogif[i].sc_if.if_bpf, ifp, DLT_PFLOG,
110 			  PFLOG_HDRLEN);
111 #endif
112 	}
113 }
114 
115 /*
116  * Start output on the pflog interface.
117  */
118 void
119 pflogstart(struct ifnet *ifp)
120 {
121 	struct mbuf *m;
122 	int s;
123 
124 	for (;;) {
125 		s = splimp();
126 		IF_DROP(&ifp->if_snd);
127 		IF_DEQUEUE(&ifp->if_snd, m);
128 		splx(s);
129 
130 		if (m == NULL)
131 			return;
132 		else
133 			m_freem(m);
134 	}
135 }
136 
137 int
138 pflogoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
139 	struct rtentry *rt)
140 {
141 	m_freem(m);
142 	return (0);
143 }
144 
145 /* ARGSUSED */
146 void
147 pflogrtrequest(int cmd, struct rtentry *rt, struct sockaddr *sa)
148 {
149 	if (rt)
150 		rt->rt_rmx.rmx_mtu = PFLOGMTU;
151 }
152 
153 /* ARGSUSED */
154 int
155 pflogioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
156 {
157 	switch (cmd) {
158 	case SIOCSIFADDR:
159 	case SIOCAIFADDR:
160 	case SIOCSIFDSTADDR:
161 	case SIOCSIFFLAGS:
162 		if (ifp->if_flags & IFF_UP)
163 			ifp->if_flags |= IFF_RUNNING;
164 		else
165 			ifp->if_flags &= ~IFF_RUNNING;
166 		break;
167 	default:
168 		return (EINVAL);
169 	}
170 
171 	return (0);
172 }
173 
174 int
175 pflog_packet(struct ifnet *ifp, struct mbuf *m, sa_family_t af, u_int8_t dir,
176     u_int8_t reason, struct pf_rule *rm, struct pf_rule *am,
177     struct pf_ruleset *ruleset)
178 {
179 #if NBPFILTER > 0
180 	struct ifnet *ifn;
181 	struct pfloghdr hdr;
182 	struct mbuf m1;
183 
184 	if (ifp == NULL || m == NULL || rm == NULL)
185 		return (-1);
186 
187 	hdr.length = PFLOG_REAL_HDRLEN;
188 	hdr.af = af;
189 	hdr.action = rm->action;
190 	hdr.reason = reason;
191 	memcpy(hdr.ifname, ifp->if_xname, sizeof(hdr.ifname));
192 
193 	if (am == NULL) {
194 		hdr.rulenr = htonl(rm->nr);
195 		hdr.subrulenr = -1;
196 		bzero(hdr.ruleset, sizeof(hdr.ruleset));
197 	} else {
198 		hdr.rulenr = htonl(am->nr);
199 		hdr.subrulenr = htonl(rm->nr);
200 		if (ruleset == NULL)
201 			bzero(hdr.ruleset, sizeof(hdr.ruleset));
202 		else
203 			memcpy(hdr.ruleset, ruleset->name,
204 			    sizeof(hdr.ruleset));
205 
206 
207 	}
208 	hdr.dir = dir;
209 
210 #ifdef INET
211 	if (af == AF_INET && dir == PF_OUT) {
212 		struct ip *ip;
213 
214 		ip = mtod(m, struct ip *);
215 		ip->ip_sum = 0;
216 		ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
217 	}
218 #endif /* INET */
219 
220 	m1.m_next = m;
221 	m1.m_len = PFLOG_HDRLEN;
222 	m1.m_data = (char *) &hdr;
223 
224 	ifn = &(pflogif[0].sc_if);
225 
226 	if (ifn->if_bpf)
227 		bpf_mtap(ifn->if_bpf, &m1);
228 #endif
229 
230 	return (0);
231 }
232