1 /* $NetBSD: if_pflog.c,v 1.14 2008/12/19 18:49:38 cegger Exp $ */
2 /* $OpenBSD: if_pflog.c,v 1.24 2007/05/26 17:13:30 jason Exp $ */
5 * The authors of this code are John Ioannidis (ji@tla.org),
6 * Angelos D. Keromytis (kermit@csd.uch.gr) and
7 * Niels Provos (provos@physnet.uni-hamburg.de).
9 * This code was written by John Ioannidis for BSD/OS in Athens, Greece,
12 * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
13 * by Angelos D. Keromytis.
15 * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
18 * Copyright (C) 1995, 1996, 1997, 1998 by John Ioannidis, Angelos D. Keromytis
20 * Copyright (c) 2001, Angelos D. Keromytis, Niels Provos.
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
38 #include <sys/cdefs.h>
39 __KERNEL_RCSID(0, "$NetBSD: if_pflog.c,v 1.14 2008/12/19 18:49:38 cegger Exp $");
48 #include <sys/param.h>
49 #include <sys/systm.h>
52 #include <sys/socket.h>
53 #include <sys/ioctl.h>
56 #include <net/if_types.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/pfvar.h>
75 #include <net/if_pflog.h>
77 #define PFLOGMTU (32768 + MHLEN + MLEN)
80 #define DPRINTF(x) do { if (pflogdebug) printf x ; } while (0)
85 void pflogattach(int);
86 int pflogoutput(struct ifnet
*, struct mbuf
*, const struct sockaddr
*,
88 int pflogioctl(struct ifnet
*, u_long
, void *);
89 void pflogstart(struct ifnet
*);
90 int pflog_clone_create(struct if_clone
*, int);
91 int pflog_clone_destroy(struct ifnet
*);
93 LIST_HEAD(, pflog_softc
) pflogif_list
;
94 struct if_clone pflog_cloner
=
95 IF_CLONE_INITIALIZER("pflog", pflog_clone_create
, pflog_clone_destroy
);
97 struct ifnet
*pflogifs
[PFLOGIFS_MAX
]; /* for fast access */
100 pflogattach(int npflog
)
104 LIST_INIT(&pflogif_list
);
105 for (i
= 0; i
< PFLOGIFS_MAX
; i
++)
107 if_clone_attach(&pflog_cloner
);
111 pflog_clone_create(struct if_clone
*ifc
, int unit
)
114 struct pflog_softc
*pflogif
;
117 if (unit
>= PFLOGIFS_MAX
)
120 if ((pflogif
= malloc(sizeof(*pflogif
), M_DEVBUF
, M_NOWAIT
|M_ZERO
)) == NULL
)
123 pflogif
->sc_unit
= unit
;
124 ifp
= &pflogif
->sc_if
;
125 snprintf(ifp
->if_xname
, sizeof ifp
->if_xname
, "pflog%d", unit
);
126 ifp
->if_softc
= pflogif
;
127 ifp
->if_mtu
= PFLOGMTU
;
128 ifp
->if_ioctl
= pflogioctl
;
129 ifp
->if_output
= pflogoutput
;
130 ifp
->if_start
= pflogstart
;
131 ifp
->if_type
= IFT_PFLOG
;
133 ifp
->if_snd
.ifq_maxlen
= ifqmaxlen
;
134 #endif /* !__NetBSD__ */
135 ifp
->if_hdrlen
= PFLOG_HDRLEN
;
141 bpfattach(ifp
, DLT_PFLOG
, PFLOG_HDRLEN
);
143 bpfattach(&pflogif
->sc_if
.if_bpf
, ifp
, DLT_PFLOG
, PFLOG_HDRLEN
);
144 #endif /* !__NetBSD__ */
148 LIST_INSERT_HEAD(&pflogif_list
, pflogif
, sc_list
);
149 pflogifs
[unit
] = ifp
;
156 pflog_clone_destroy(struct ifnet
*ifp
)
158 struct pflog_softc
*pflogif
= ifp
->if_softc
;
162 pflogifs
[pflogif
->sc_unit
] = NULL
;
163 LIST_REMOVE(pflogif
, sc_list
);
170 free(pflogif
, M_DEVBUF
);
175 * Start output on the pflog interface.
178 pflogstart(struct ifnet
*ifp
)
185 IF_DROP(&ifp
->if_snd
);
186 IF_DEQUEUE(&ifp
->if_snd
, m
);
197 pflogoutput(struct ifnet
*ifp
, struct mbuf
*m
,
198 const struct sockaddr
*dst
, struct rtentry
*rt
)
206 pflogioctl(struct ifnet
*ifp
, u_long cmd
, void *data
)
212 if ((error
= ifioctl_common(ifp
, cmd
, data
)) != 0)
218 if (ifp
->if_flags
& IFF_UP
)
219 ifp
->if_flags
|= IFF_RUNNING
;
221 ifp
->if_flags
&= ~IFF_RUNNING
;
224 error
= ifioctl_common(ifp
, cmd
, data
);
231 pflog_packet(struct pfi_kif
*kif
, struct mbuf
*m
, sa_family_t af
, u_int8_t dir
,
232 u_int8_t reason
, struct pf_rule
*rm
, struct pf_rule
*am
,
233 struct pf_ruleset
*ruleset
, struct pf_pdesc
*pd
)
239 if (kif
== NULL
|| m
== NULL
|| rm
== NULL
|| pd
== NULL
)
242 if ((ifn
= pflogifs
[rm
->logif
]) == NULL
|| !ifn
->if_bpf
)
245 bzero(&hdr
, sizeof(hdr
));
246 hdr
.length
= PFLOG_REAL_HDRLEN
;
248 hdr
.action
= rm
->action
;
250 memcpy(hdr
.ifname
, kif
->pfik_name
, sizeof(hdr
.ifname
));
253 hdr
.rulenr
= htonl(rm
->nr
);
256 hdr
.rulenr
= htonl(am
->nr
);
257 hdr
.subrulenr
= htonl(rm
->nr
);
258 if (ruleset
!= NULL
&& ruleset
->anchor
!= NULL
)
259 strlcpy(hdr
.ruleset
, ruleset
->anchor
->name
,
260 sizeof(hdr
.ruleset
));
262 if (rm
->log
& PF_LOG_SOCKET_LOOKUP
&& !pd
->lookup
.done
)
263 pd
->lookup
.done
= pf_socket_lookup(dir
, pd
);
264 if (pd
->lookup
.done
> 0) {
265 hdr
.uid
= pd
->lookup
.uid
;
266 hdr
.pid
= pd
->lookup
.pid
;
271 hdr
.rule_uid
= rm
->cuid
;
272 hdr
.rule_pid
= rm
->cpid
;
276 if (af
== AF_INET
&& dir
== PF_OUT
) {
279 ip
= mtod(m
, struct ip
*);
281 ip
->ip_sum
= in_cksum(m
, ip
->ip_hl
<< 2);
286 ifn
->if_obytes
+= m
->m_pkthdr
.len
;
289 bpf_mtap2(ifn
->if_bpf
, &hdr
, PFLOG_HDRLEN
, m
);
291 bpf_mtap_hdr(ifn
->if_bpf
, (char *)&hdr
, PFLOG_HDRLEN
, m
,
293 #endif /* !__NetBSD__ */