1 /* $FreeBSD: src/sys/contrib/pf/net/if_pflog.c,v 1.9 2004/06/22 20:13:24 brooks Exp $ */
2 /* $OpenBSD: if_pflog.c,v 1.11 2003/12/31 11:18:25 cedric Exp $ */
3 /* $DragonFly: src/sys/net/pf/if_pflog.c,v 1.6 2006/12/22 23:44:57 swildner Exp $ */
6 * The authors of this code are John Ioannidis (ji@tla.org),
7 * Angelos D. Keromytis (kermit@csd.uch.gr) and
8 * Niels Provos (provos@physnet.uni-hamburg.de).
10 * This code was written by John Ioannidis for BSD/OS in Athens, Greece,
13 * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
14 * by Angelos D. Keromytis.
16 * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
19 * Copyright (C) 1995, 1996, 1997, 1998 by John Ioannidis, Angelos D. Keromytis
21 * Copyright (c) 2001, Angelos D. Keromytis, Niels Provos.
23 * Copyright (c) 2004 The DragonFly Project. All rights reserved.
25 * Permission to use, copy, and modify this software with or without fee
26 * is hereby granted, provided that this entire notice is included in
27 * all copies of any software which is or includes a copy or
28 * modification of this software.
29 * You may use this code under the GNU public license if you so wish. Please
30 * contribute changes back to the authors under this freer than GPL license
31 * so that we may further the use of strong encryption without limitations to
34 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
35 * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
36 * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
37 * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
42 #include "opt_inet6.h"
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/in_cksum.h>
48 #include <sys/socket.h>
49 #include <sys/kernel.h>
50 #include <sys/malloc.h>
51 #include <sys/module.h>
52 #include <sys/sockio.h>
53 #include <sys/thread2.h>
54 #include <vm/vm_zone.h>
57 #include <net/if_types.h>
58 #include <net/route.h>
62 #include <netinet/in.h>
63 #include <netinet/in_var.h>
64 #include <netinet/in_systm.h>
65 #include <netinet/ip.h>
70 #include <netinet/in.h>
72 #include <netinet6/nd6.h>
75 #include <net/pf/pfvar.h>
76 #include <net/pf/if_pflog.h>
78 #define PFLOGNAME "pflog"
80 #define PFLOGMTU (32768 + MHLEN + MLEN)
83 #define DPRINTF(x) do { if (pflogdebug) kprintf x ; } while (0)
89 static void pflog_clone_destroy(struct ifnet
*);
90 static int pflog_clone_create(struct if_clone
*, int);
91 int pflogoutput(struct ifnet
*, struct mbuf
*, struct sockaddr
*,
93 int pflogioctl(struct ifnet
*, u_long
, caddr_t
, struct ucred
*);
94 void pflogrtrequest(int, struct rtentry
*, struct sockaddr
*);
95 void pflogstart(struct ifnet
*);
97 static MALLOC_DEFINE(M_PFLOG
, PFLOGNAME
, "Packet Filter Logging Interface");
98 static LIST_HEAD(pflog_list
, pflog_softc
) pflog_list
;
99 struct if_clone pflog_cloner
= IF_CLONE_INITIALIZER("pflog", pflog_clone_create
,
100 pflog_clone_destroy
, 1, 1);
103 pflog_clone_destroy(struct ifnet
*ifp
)
105 struct pflog_softc
*sc
;
110 * Do we really need this?
112 IF_DRAIN(&ifp
->if_snd
);
116 LIST_REMOVE(sc
, sc_next
);
121 pflog_clone_create(struct if_clone
*ifc
, int unit
)
123 struct pflog_softc
*sc
;
125 MALLOC(sc
, struct pflog_softc
*, sizeof(*sc
), M_PFLOG
, M_WAITOK
|M_ZERO
);
127 if_initname(&sc
->sc_if
, ifc
->ifc_name
, unit
);
128 sc
->sc_if
.if_mtu
= PFLOGMTU
;
129 sc
->sc_if
.if_ioctl
= pflogioctl
;
130 sc
->sc_if
.if_output
= pflogoutput
;
131 sc
->sc_if
.if_start
= pflogstart
;
132 sc
->sc_if
.if_type
= IFT_PFLOG
;
133 sc
->sc_if
.if_snd
.ifq_maxlen
= ifqmaxlen
;
134 sc
->sc_if
.if_hdrlen
= PFLOG_HDRLEN
;
135 sc
->sc_if
.if_softc
= sc
;
136 if_attach(&sc
->sc_if
, NULL
);
138 LIST_INSERT_HEAD(&pflog_list
, sc
, sc_next
);
139 bpfattach(&sc
->sc_if
, DLT_PFLOG
, PFLOG_HDRLEN
);
145 * Start output on the pflog interface.
148 pflogstart(struct ifnet
*ifp
)
151 IF_DROP(&ifp
->if_snd
);
152 IF_DRAIN(&ifp
->if_snd
);
157 pflogoutput(struct ifnet
*ifp
, struct mbuf
*m
, struct sockaddr
*dst
,
166 pflogrtrequest(int cmd
, struct rtentry
*rt
, struct sockaddr
*sa
)
169 rt
->rt_rmx
.rmx_mtu
= PFLOGMTU
;
174 pflogioctl(struct ifnet
*ifp
, u_long cmd
, caddr_t data
, struct ucred
*cr
)
181 if (ifp
->if_flags
& IFF_UP
)
182 ifp
->if_flags
|= IFF_RUNNING
;
184 ifp
->if_flags
&= ~IFF_RUNNING
;
194 pflog_packet(struct pfi_kif
*kif
, struct mbuf
*m
, sa_family_t af
, u_int8_t dir
,
195 u_int8_t reason
, struct pf_rule
*rm
, struct pf_rule
*am
,
196 struct pf_ruleset
*ruleset
)
202 if (kif
== NULL
|| m
== NULL
|| rm
== NULL
)
205 bzero(&hdr
, sizeof(hdr
));
206 hdr
.length
= PFLOG_REAL_HDRLEN
;
208 hdr
.action
= rm
->action
;
210 memcpy(hdr
.ifname
, kif
->pfik_name
, sizeof(hdr
.ifname
));
213 hdr
.rulenr
= htonl(rm
->nr
);
216 hdr
.rulenr
= htonl(am
->nr
);
217 hdr
.subrulenr
= htonl(rm
->nr
);
219 memcpy(hdr
.ruleset
, ruleset
->name
,
220 sizeof(hdr
.ruleset
));
228 struct ip
*ip
= mtod(m
, struct ip
*);
230 ip
->ip_len
= htons(ip
->ip_len
);
231 ip
->ip_off
= htons(ip
->ip_off
);
235 ip
->ip_sum
= in_cksum(m
, ip
->ip_hl
<< 2);
241 m1
.m_len
= PFLOG_HDRLEN
;
242 m1
.m_data
= (char *) &hdr
;
244 KASSERT((!LIST_EMPTY(&pflog_list
)), ("pflog: no interface"));
245 ifn
= &LIST_FIRST(&pflog_list
)->sc_if
;
251 struct ip
*ip
= mtod(m
, struct ip
*);
253 ip
->ip_len
= ntohs(ip
->ip_len
);
254 ip
->ip_off
= ntohs(ip
->ip_off
);
262 pflog_modevent(module_t mod
, int type
, void *data
)
268 LIST_INIT(&pflog_list
);
269 if_clone_attach(&pflog_cloner
);
273 if_clone_detach(&pflog_cloner
);
274 while (!LIST_EMPTY(&pflog_list
))
276 &LIST_FIRST(&pflog_list
)->sc_if
);
287 static moduledata_t pflog_mod
= {
293 #define PFLOG_MODVER 1
295 DECLARE_MODULE(pflog
, pflog_mod
, SI_SUB_PSEUDO
, SI_ORDER_ANY
);
296 MODULE_VERSION(pflog
, PFLOG_MODVER
);