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"
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/in_cksum.h>
46 #include <sys/socket.h>
47 #include <sys/kernel.h>
48 #include <sys/malloc.h>
49 #include <sys/module.h>
50 #include <sys/sockio.h>
51 #include <sys/thread2.h>
54 #include <net/if_types.h>
55 #include <net/ifq_var.h>
56 #include <net/route.h>
60 #include <netinet/in.h>
61 #include <netinet/in_var.h>
62 #include <netinet/in_systm.h>
63 #include <netinet/ip.h>
68 #include <netinet/in.h>
70 #include <netinet6/nd6.h>
73 #include <net/pf/pfvar.h>
74 #include <net/pf/if_pflog.h>
76 #define PFLOGNAME "pflog"
78 #define PFLOGMTU (32768 + MHLEN + MLEN)
81 #define DPRINTF(x) do { if (pflogdebug) kprintf x ; } while (0)
86 void pflogattach(int);
87 int pflogoutput(struct ifnet
*, struct mbuf
*, struct sockaddr
*,
89 int pflogioctl(struct ifnet
*, u_long
, caddr_t
, struct ucred
*);
90 void pflogrtrequest(int, struct rtentry
*, struct sockaddr
*);
91 void pflogstart(struct ifnet
*, struct ifaltq_subque
*);
92 int pflog_clone_create(struct if_clone
*, int, caddr_t
);
93 int pflog_clone_destroy(struct ifnet
*);
95 LIST_HEAD(, pflog_softc
) pflogif_list
;
96 struct if_clone pflog_cloner
=
97 IF_CLONE_INITIALIZER("pflog", pflog_clone_create
, pflog_clone_destroy
, 1, 1);
99 struct ifnet
*pflogifs
[PFLOGIFS_MAX
]; /* for fast access */
102 pflogattach(int npflog
)
105 LIST_INIT(&pflogif_list
);
106 for (i
= 0; i
< PFLOGIFS_MAX
; i
++)
108 if_clone_attach(&pflog_cloner
);
112 pflog_clone_create(struct if_clone
*ifc
, int unit
, caddr_t param __unused
)
115 struct pflog_softc
*pflogif
;
117 lwkt_gettoken(&pf_token
);
119 if (unit
>= PFLOGIFS_MAX
) {
120 lwkt_reltoken(&pf_token
);
124 if ((pflogif
= kmalloc(sizeof(*pflogif
),
125 M_DEVBUF
, M_WAITOK
|M_ZERO
)) == NULL
) {
126 lwkt_reltoken(&pf_token
);
130 pflogif
->sc_unit
= unit
;
131 lwkt_reltoken(&pf_token
);
132 ifp
= &pflogif
->sc_if
;
133 ksnprintf(ifp
->if_xname
, sizeof ifp
->if_xname
, "pflog%d", unit
);
134 ifp
->if_softc
= pflogif
;
135 ifp
->if_mtu
= PFLOGMTU
;
136 ifp
->if_ioctl
= pflogioctl
;
137 ifp
->if_output
= pflogoutput
;
138 ifp
->if_start
= pflogstart
;
139 ifp
->if_type
= IFT_PFLOG
;
140 ifq_set_maxlen(&ifp
->if_snd
, ifqmaxlen
);
141 ifp
->if_hdrlen
= PFLOG_HDRLEN
;
142 if_attach(ifp
, NULL
);
144 bpfattach(&pflogif
->sc_if
, DLT_PFLOG
, PFLOG_HDRLEN
);
145 lwkt_gettoken(&pf_token
);
148 LIST_INSERT_HEAD(&pflogif_list
, pflogif
, sc_list
);
149 pflogifs
[unit
] = ifp
;
152 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
,
210 pflogrtrequest(int cmd
, struct rtentry
*rt
, struct sockaddr
*sa
)
213 rt
->rt_rmx
.rmx_mtu
= PFLOGMTU
;
218 pflogioctl(struct ifnet
*ifp
, u_long cmd
, caddr_t data
, struct ucred
*cr
)
221 lwkt_gettoken(&pf_token
);
225 lwkt_reltoken(&pf_token
);
226 if (ifp
->if_flags
& IFF_UP
)
227 ifp
->if_flags
|= IFF_RUNNING
;
229 ifp
->if_flags
&= ~IFF_RUNNING
;
230 lwkt_gettoken(&pf_token
);
233 lwkt_reltoken(&pf_token
);
237 lwkt_reltoken(&pf_token
);
242 pflog_packet(struct pfi_kif
*kif
, struct mbuf
*m
, sa_family_t af
, u_int8_t dir
,
243 u_int8_t reason
, struct pf_rule
*rm
, struct pf_rule
*am
,
244 struct pf_ruleset
*ruleset
, struct pf_pdesc
*pd
)
246 struct ifnet
*ifn
= NULL
;
249 ASSERT_LWKT_TOKEN_HELD(&pf_token
);
251 if (kif
== NULL
|| m
== NULL
|| rm
== NULL
)
254 if ((ifn
= pflogifs
[rm
->logif
]) == NULL
|| !ifn
->if_bpf
)
257 bzero(&hdr
, sizeof(hdr
));
258 hdr
.length
= PFLOG_REAL_HDRLEN
;
260 hdr
.action
= rm
->action
;
262 memcpy(hdr
.ifname
, kif
->pfik_name
, sizeof(hdr
.ifname
));
265 hdr
.rulenr
= htonl(rm
->nr
);
268 hdr
.rulenr
= htonl(am
->nr
);
269 hdr
.subrulenr
= htonl(rm
->nr
);
270 if (ruleset
!= NULL
&& ruleset
->anchor
!= NULL
)
271 strlcpy(hdr
.ruleset
, ruleset
->anchor
->name
,
272 sizeof(hdr
.ruleset
));
274 if (rm
->log
& PF_LOG_SOCKET_LOOKUP
&& !pd
->lookup
.done
)
275 pd
->lookup
.done
= pf_socket_lookup(dir
, pd
);
276 if (pd
->lookup
.done
> 0) {
277 hdr
.uid
= pd
->lookup
.uid
;
278 hdr
.pid
= pd
->lookup
.pid
;
283 hdr
.rule_uid
= rm
->cuid
;
284 hdr
.rule_pid
= rm
->cpid
;
290 ip
= mtod(m
, struct ip
*);
291 ip
->ip_len
= htons(ip
->ip_len
);
292 ip
->ip_off
= htons(ip
->ip_off
);
296 ip
->ip_sum
= in_cksum(m
, ip
->ip_hl
<< 2);
301 IFNET_STAT_INC(ifn
, opackets
, 1);
302 IFNET_STAT_INC(ifn
, obytes
, m
->m_pkthdr
.len
);
306 bpf_mtap_hdr(ifn
->if_bpf
, (char *)&hdr
, PFLOG_HDRLEN
, m
,
314 struct ip
*ip
= mtod(m
, struct ip
*);
316 ip
->ip_len
= ntohs(ip
->ip_len
);
317 ip
->ip_off
= ntohs(ip
->ip_off
);
325 pflog_modevent(module_t mod
, int type
, void *data
)
329 struct pflog_softc
*pflogif
, *tmp
;
331 lwkt_gettoken(&pf_token
);
335 LIST_INIT(&pflogif_list
);
336 lwkt_reltoken(&pf_token
);
337 if_clone_attach(&pflog_cloner
);
338 lwkt_gettoken(&pf_token
);
342 lwkt_reltoken(&pf_token
);
343 if_clone_detach(&pflog_cloner
);
344 LIST_FOREACH_MUTABLE(pflogif
, &pflogif_list
, sc_list
, tmp
) {
345 pflog_clone_destroy(&pflogif
->sc_if
);
347 lwkt_gettoken(&pf_token
);
354 lwkt_reltoken(&pf_token
);
358 static moduledata_t pflog_mod
= {
364 DECLARE_MODULE(pflog
, pflog_mod
, SI_SUB_PSEUDO
, SI_ORDER_ANY
);
365 MODULE_VERSION(pflog
, PFLOG_MODVER
);