if_pflog.c revision 1.1 1 /* $OpenBSD: if_pflog.c,v 1.11 2003/12/31 11:18:25 cedric Exp $ */
2 /*
3 * The authors of this code are John Ioannidis (ji (at) tla.org),
4 * Angelos D. Keromytis (kermit (at) csd.uch.gr) and
5 * Niels Provos (provos (at) 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 pfi_kif *kif, 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 (kif == NULL || m == NULL || rm == NULL)
185 return (-1);
186
187 bzero(&hdr, sizeof(hdr));
188 hdr.length = PFLOG_REAL_HDRLEN;
189 hdr.af = af;
190 hdr.action = rm->action;
191 hdr.reason = reason;
192 memcpy(hdr.ifname, kif->pfik_name, sizeof(hdr.ifname));
193
194 if (am == NULL) {
195 hdr.rulenr = htonl(rm->nr);
196 hdr.subrulenr = -1;
197 } else {
198 hdr.rulenr = htonl(am->nr);
199 hdr.subrulenr = htonl(rm->nr);
200 if (ruleset != NULL)
201 memcpy(hdr.ruleset, ruleset->name,
202 sizeof(hdr.ruleset));
203
204
205 }
206 hdr.dir = dir;
207
208 #ifdef INET
209 if (af == AF_INET && dir == PF_OUT) {
210 struct ip *ip;
211
212 ip = mtod(m, struct ip *);
213 ip->ip_sum = 0;
214 ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
215 }
216 #endif /* INET */
217
218 m1.m_next = m;
219 m1.m_len = PFLOG_HDRLEN;
220 m1.m_data = (char *) &hdr;
221
222 ifn = &(pflogif[0].sc_if);
223
224 if (ifn->if_bpf)
225 bpf_mtap(ifn->if_bpf, &m1);
226 #endif
227
228 return (0);
229 }
230