hammer2 - Fix flush issues with unmounted PFSs and shutdown panic
[dragonfly.git] / sys / net / ipfw3 / ip_fw3_log.c
blob16423d8446934da43277ad134bcf88cd96bd43ae
1 /*
2 * Copyright (c) 2002-2009 Luigi Rizzo, Universita` di Pisa
4 * Copyright (c) 2015 The DragonFly Project. All rights reserved.
6 * This code is derived from software contributed to The DragonFly Project
7 * by Bill Yuan <bycn82@dragonflybsd.org>
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 * 3. Neither the name of The DragonFly Project nor the names of its
20 * contributors may be used to endorse or promote products derived
21 * from this software without specific, prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
31 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
37 #include "opt_inet.h"
38 #ifndef INET
39 #error IPFIREWALL3 requires INET.
40 #endif
42 #include <sys/cdefs.h>
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/mbuf.h>
46 #include <sys/kernel.h>
47 #include <sys/socket.h>
48 #include <sys/sysctl.h>
49 #include <sys/syslog.h>
50 #include <sys/ucred.h>
51 #include <sys/lock.h>
52 #include <sys/lock.h>
53 #include <net/ethernet.h> /* for ETHERTYPE_IP */
54 #include <net/if.h>
55 #include <net/if_var.h>
56 #include <net/ifq_var.h>
57 #include <net/if_clone.h>
58 #include <net/if_types.h> /* for IFT_PFLOG */
59 #include <net/bpf.h> /* for BPF */
61 #include <netinet/in.h>
62 #include <netinet/ip.h>
63 #include <netinet/ip_icmp.h>
64 #include <netinet/ip_var.h>
65 #include <netinet/tcp_var.h>
66 #include <netinet/udp.h>
68 #ifdef INET6
69 #include <netinet/ip6.h>
70 #include <netinet/icmp6.h>
71 #include <netinet6/in6_var.h> /* ip6_sprintf() */
72 #endif
74 #include <net/ipfw3/ip_fw.h>
75 #include <net/ipfw3/ip_fw3_log.h>
77 extern int fw_verbose;
78 extern struct if_clone *if_clone_lookup(const char *, int *);
80 static const char ipfw_log_ifname[] = "ipfw";
81 static int log_if_count;
82 struct ifnet *log_if_table[LOG_IF_MAX];
83 struct lock log_if_lock;
86 u_char fake_eh[14] = {0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
87 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x08, 0x00};
89 static const u_char ipfwbroadcastaddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
91 #define LOGIF_LOCK_INIT(x) lockinit(&log_if_lock, "fw3log_lk", 0, LK_CANRECURSE)
92 #define LOGIF_LOCK_DESTROY(x) lockuninit(&log_if_lock)
93 #define LOGIF_RLOCK(x) lockmgr(&log_if_lock, LK_SHARED)
94 #define LOGIF_RUNLOCK(x) lockmgr(&log_if_lock, LK_RELEASE)
95 #define LOGIF_WLOCK(x) lockmgr(&log_if_lock, LK_EXCLUSIVE)
96 #define LOGIF_WUNLOCK(x) lockmgr(&log_if_lock, LK_RELEASE)
99 /* we use this dummy function for all ifnet callbacks */
100 static int
101 log_dummy(struct ifnet *ifp, u_long cmd, caddr_t addr, struct ucred *uc)
103 return EINVAL;
106 static int
107 ipfw_log_output(struct ifnet *ifp, struct mbuf *m,
108 struct sockaddr *dst, struct rtentry *rtent)
110 if (m != NULL) {
111 m_freem(m);
113 return EINVAL;
116 static void
117 ipfw_log_start(struct ifnet* ifp, struct ifaltq_subque *subque)
122 * bpf_mtap into the ipfw interface.
123 * eh == NULL when mbuf is a packet, then use the fake_eh
124 * the ip_len need to be twisted before and after bpf copy.
126 void
127 ipfw_log(struct mbuf *m, struct ether_header *eh, uint16_t id)
129 struct ifnet *the_if = NULL;
131 if (fw_verbose) {
132 #ifndef WITHOUT_BPF
133 LOGIF_RLOCK();
134 the_if = log_if_table[id];
135 if (the_if == NULL || the_if->if_bpf == NULL) {
136 LOGIF_RUNLOCK();
137 return;
139 if (eh != NULL) {
140 bpf_gettoken();
141 bpf_mtap_hdr(the_if->if_bpf, (caddr_t)eh,
142 ETHER_HDR_LEN, m, 0);
143 bpf_reltoken();
145 } else {
146 struct ip *ip;
147 ip = mtod(m, struct ip *);
148 /* twist the ip_len for the bpf copy */
149 ip->ip_len =htons(ip->ip_len);
151 bpf_gettoken();
152 bpf_mtap_hdr(the_if->if_bpf, (caddr_t)fake_eh,
153 ETHER_HDR_LEN, m, 0);
154 bpf_reltoken();
155 ip->ip_len =ntohs(ip->ip_len);
158 LOGIF_RUNLOCK();
159 #endif /* !WITHOUT_BPF */
163 static int
164 ipfw_log_clone_create(struct if_clone *ifc, int unit, caddr_t param __unused)
166 struct ifnet *ifp;
168 if (unit < 0 || unit >= LOG_IF_MAX) {
169 return EINVAL;
171 if (log_if_table[unit] != NULL) {
172 return EINVAL;
175 ifp = if_alloc(IFT_PFLOG);
176 if_initname(ifp, ipfw_log_ifname, unit);
177 ifq_set_maxlen(&ifp->if_snd, ifqmaxlen);
178 ifq_set_ready(&ifp->if_snd);
180 ifp->if_mtu = 65536;
181 ifp->if_flags = IFF_UP | IFF_SIMPLEX | IFF_MULTICAST;
182 ifp->if_init = (void *)log_dummy;
183 ifp->if_ioctl = log_dummy;
184 ifp->if_start = ipfw_log_start;
185 ifp->if_output = ipfw_log_output;
186 ifp->if_addrlen = 6;
187 ifp->if_hdrlen = 14;
188 ifp->if_broadcastaddr = ipfwbroadcastaddr;
189 ifp->if_baudrate = IF_Mbps(10);
191 LOGIF_WLOCK();
192 log_if_table[unit] = ifp;
193 log_if_count++;
194 if_attach(ifp, NULL);
195 bpfattach(ifp, DLT_EN10MB, ETHER_HDR_LEN);
196 LOGIF_WUNLOCK();
198 return (0);
201 static int
202 ipfw_log_clone_destroy(struct ifnet *ifp)
204 int unit;
206 if (ifp == NULL)
207 return (0);
209 unit = ifp->if_dunit;
210 if (unit < 0 || unit >= LOG_IF_MAX) {
211 return EINVAL;
213 if (log_if_table[unit] == NULL) {
214 return EINVAL;
216 LOGIF_WLOCK();
217 log_if_table[unit] = NULL;
218 bpfdetach(ifp);
219 if_detach(ifp);
220 if_free(ifp);
221 log_if_count--;
222 LOGIF_WUNLOCK();
224 return (0);
227 static eventhandler_tag ipfw_log_ifdetach_cookie;
228 static struct if_clone ipfw_log_cloner = IF_CLONE_INITIALIZER(ipfw_log_ifname,
229 ipfw_log_clone_create, ipfw_log_clone_destroy, 0, 9);
232 void ipfw3_log_modevent(int type){
233 struct ifnet *tmpif;
234 int i;
236 switch (type) {
237 case MOD_LOAD:
238 LOGIF_LOCK_INIT();
239 log_if_count = 0;
240 if_clone_attach(&ipfw_log_cloner);
241 ipfw_log_ifdetach_cookie =
242 EVENTHANDLER_REGISTER(ifnet_detach_event,
243 ipfw_log_clone_destroy, &ipfw_log_cloner,
244 EVENTHANDLER_PRI_ANY);
245 break;
246 case MOD_UNLOAD:
247 EVENTHANDLER_DEREGISTER(ifnet_detach_event,
248 ipfw_log_ifdetach_cookie);
249 if_clone_detach(&ipfw_log_cloner);
250 for(i = 0; log_if_count > 0 && i < LOG_IF_MAX; i++){
251 tmpif = log_if_table[i];
252 if (tmpif != NULL) {
253 ipfw_log_clone_destroy(tmpif);
256 LOGIF_LOCK_DESTROY();
257 break;
259 default:
260 break;
264 /* end of file */