1 /* $OpenBSD: if_pflog.c,v 1.27 2007/12/20 02:53:02 brad Exp $ */
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).
7 * This code was written by John Ioannidis for BSD/OS in Athens, Greece,
10 * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
11 * by Angelos D. Keromytis.
13 * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
16 * Copyright (C) 1995, 1996, 1997, 1998 by John Ioannidis, Angelos D. Keromytis
18 * Copyright (c) 2001, Angelos D. Keromytis, Niels Provos.
20 * Copyright (c) 2010 The DragonFly Project. All rights reserved.
22 * Permission to use, copy, and modify this software with or without fee
23 * is hereby granted, provided that this entire notice is included in
24 * all copies of any software which is or includes a copy or
25 * modification of this software.
26 * You may use this code under the GNU public license if you so wish. Please
27 * contribute changes back to the authors under this freer than GPL license
28 * so that we may further the use of strong encryption without limitations to
31 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
32 * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
33 * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
34 * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
39 #include "opt_inet6.h"
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/in_cksum.h>
47 #include <sys/socket.h>
48 #include <sys/kernel.h>
49 #include <sys/malloc.h>
50 #include <sys/module.h>
51 #include <sys/sockio.h>
52 #include <sys/thread2.h>
55 #include <net/if_types.h>
56 #include <net/ifq_var.h>
57 #include <net/route.h>
61 #include <netinet/in.h>
62 #include <netinet/in_var.h>
63 #include <netinet/in_systm.h>
64 #include <netinet/ip.h>
69 #include <netinet/in.h>
71 #include <netinet6/nd6.h>
74 #include <net/pf/pfvar.h>
75 #include <net/pf/if_pflog.h>
77 #define PFLOGNAME "pflog"
79 #define PFLOGMTU (32768 + MHLEN + MLEN)
82 #define DPRINTF(x) do { if (pflogdebug) kprintf x ; } while (0)
87 static void pflogattach(void);
88 static int pflogoutput(struct ifnet
*, struct mbuf
*,
89 struct sockaddr
*, struct rtentry
*);
90 static int pflogioctl(struct ifnet
*, u_long
, caddr_t __unused
,
91 struct ucred
* __unused
);
92 static void pflogstart(struct ifnet
*, struct ifaltq_subque
*);
93 static int pflog_clone_create(struct if_clone
*, int, caddr_t
, caddr_t
);
94 static int pflog_clone_destroy(struct ifnet
*);
96 static struct if_clone pflog_cloner
= IF_CLONE_INITIALIZER(
97 PFLOGNAME
, pflog_clone_create
, pflog_clone_destroy
, 1, 1);
99 static LIST_HEAD(, pflog_softc
) pflogif_list
;
100 static struct ifnet
*pflogifs
[PFLOGIFS_MAX
]; /* for fast access */
106 LIST_INIT(&pflogif_list
);
107 for (i
= 0; i
< PFLOGIFS_MAX
; i
++)
109 if_clone_attach(&pflog_cloner
);
113 pflog_clone_create(struct if_clone
*ifc
, int unit
,
114 caddr_t params __unused
, caddr_t data __unused
)
117 struct pflog_softc
*pflogif
;
119 lwkt_gettoken(&pf_token
);
121 if (unit
>= PFLOGIFS_MAX
) {
122 lwkt_reltoken(&pf_token
);
126 pflogif
= kmalloc(sizeof(*pflogif
), M_DEVBUF
, M_WAITOK
| M_ZERO
);
127 pflogif
->sc_unit
= unit
;
128 lwkt_reltoken(&pf_token
);
130 ifp
= &pflogif
->sc_if
;
131 if_initname(ifp
, ifc
->ifc_name
, unit
);
132 ifp
->if_softc
= pflogif
;
133 ifp
->if_mtu
= PFLOGMTU
;
134 ifp
->if_ioctl
= pflogioctl
;
135 ifp
->if_output
= pflogoutput
;
136 ifp
->if_start
= pflogstart
;
137 ifp
->if_type
= IFT_PFLOG
;
138 ifq_set_maxlen(&ifp
->if_snd
, ifqmaxlen
);
139 ifp
->if_hdrlen
= PFLOG_HDRLEN
;
141 if_attach(ifp
, NULL
);
143 bpfattach(&pflogif
->sc_if
, DLT_PFLOG
, PFLOG_HDRLEN
);
146 lwkt_gettoken(&pf_token
);
148 LIST_INSERT_HEAD(&pflogif_list
, pflogif
, sc_list
);
149 pflogifs
[unit
] = ifp
;
151 lwkt_reltoken(&pf_token
);
157 pflog_clone_destroy(struct ifnet
*ifp
)
159 struct pflog_softc
*pflogif
= ifp
->if_softc
;
161 lwkt_gettoken(&pf_token
);
164 pflogifs
[pflogif
->sc_unit
] = NULL
;
165 LIST_REMOVE(pflogif
, sc_list
);
168 lwkt_reltoken(&pf_token
);
173 lwkt_gettoken(&pf_token
);
174 kfree(pflogif
, M_DEVBUF
);
175 lwkt_reltoken(&pf_token
);
181 * Start output on the pflog interface.
184 pflogstart(struct ifnet
*ifp
, struct ifaltq_subque
*ifsq
)
188 ASSERT_ALTQ_SQ_DEFAULT(ifp
, ifsq
);
189 ASSERT_LWKT_TOKEN_HELD(&pf_token
);
192 m
= ifsq_dequeue(ifsq
);
201 pflogoutput(struct ifnet
*ifp
, struct mbuf
*m
, struct sockaddr
*dst
,
209 pflogioctl(struct ifnet
*ifp
, u_long cmd
, caddr_t data __unused
,
210 struct ucred
*cr __unused
)
213 lwkt_gettoken(&pf_token
);
217 lwkt_reltoken(&pf_token
);
218 if (ifp
->if_flags
& IFF_UP
)
219 ifp
->if_flags
|= IFF_RUNNING
;
221 ifp
->if_flags
&= ~IFF_RUNNING
;
222 lwkt_gettoken(&pf_token
);
225 lwkt_reltoken(&pf_token
);
229 lwkt_reltoken(&pf_token
);
234 pflog_packet(struct pfi_kif
*kif
, struct mbuf
*m
, sa_family_t af
, u_int8_t dir
,
235 u_int8_t reason
, struct pf_rule
*rm
, struct pf_rule
*am
,
236 struct pf_ruleset
*ruleset
, struct pf_pdesc
*pd
)
238 struct ifnet
*ifn
= NULL
;
241 ASSERT_LWKT_TOKEN_HELD(&pf_token
);
243 if (kif
== NULL
|| m
== NULL
|| rm
== NULL
)
246 if ((ifn
= pflogifs
[rm
->logif
]) == NULL
|| !ifn
->if_bpf
)
249 bzero(&hdr
, sizeof(hdr
));
250 hdr
.length
= PFLOG_REAL_HDRLEN
;
252 hdr
.action
= rm
->action
;
254 memcpy(hdr
.ifname
, kif
->pfik_name
, sizeof(hdr
.ifname
));
257 hdr
.rulenr
= htonl(rm
->nr
);
260 hdr
.rulenr
= htonl(am
->nr
);
261 hdr
.subrulenr
= htonl(rm
->nr
);
262 if (ruleset
!= NULL
&& ruleset
->anchor
!= NULL
)
263 strlcpy(hdr
.ruleset
, ruleset
->anchor
->name
,
264 sizeof(hdr
.ruleset
));
266 if (rm
->log
& PF_LOG_SOCKET_LOOKUP
&& !pd
->lookup
.done
)
267 pd
->lookup
.done
= pf_socket_lookup(dir
, pd
);
268 if (pd
->lookup
.done
> 0) {
269 hdr
.uid
= pd
->lookup
.uid
;
270 hdr
.pid
= pd
->lookup
.pid
;
275 hdr
.rule_uid
= rm
->cuid
;
276 hdr
.rule_pid
= rm
->cpid
;
282 ip
= mtod(m
, struct ip
*);
286 ip
->ip_sum
= in_cksum(m
, ip
->ip_hl
<< 2);
291 IFNET_STAT_INC(ifn
, opackets
, 1);
292 IFNET_STAT_INC(ifn
, obytes
, m
->m_pkthdr
.len
);
296 bpf_mtap_hdr(ifn
->if_bpf
, (char *)&hdr
, PFLOG_HDRLEN
, m
,
306 pflog_modevent(module_t mod
, int type
, void *data
)
310 struct pflog_softc
*pflogif
, *tmp
;
312 lwkt_gettoken(&pf_token
);
316 lwkt_reltoken(&pf_token
);
318 lwkt_gettoken(&pf_token
);
322 lwkt_reltoken(&pf_token
);
323 if_clone_detach(&pflog_cloner
);
324 LIST_FOREACH_MUTABLE(pflogif
, &pflogif_list
, sc_list
, tmp
)
325 pflog_clone_destroy(&pflogif
->sc_if
);
326 lwkt_gettoken(&pf_token
);
333 lwkt_reltoken(&pf_token
);
337 static moduledata_t pflog_mod
= {
343 DECLARE_MODULE(pflog
, pflog_mod
, SI_SUB_PSEUDO
, SI_ORDER_ANY
);
344 MODULE_VERSION(pflog
, PFLOG_MODVER
);
345 /* Do not run before pf is initialized. */
346 MODULE_DEPEND(pflog
, pf
, PF_MODVER
, PF_MODVER
, PF_MODVER
);