xref: /dragonfly/sys/net/ipfw3_basic/ip_fw3_log.c (revision e6d22e9b)
1 /*
2  * Copyright (c) 2002-2009 Luigi Rizzo, Universita` di Pisa
3  *
4  * Copyright (c) 2015 - 2018 The DragonFly Project.  All rights reserved.
5  *
6  * This code is derived from software contributed to The DragonFly Project
7  * by Bill Yuan <bycn82@dragonflybsd.org>
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
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.
22  *
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.
35  */
36 
37 #include <sys/cdefs.h>
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/mbuf.h>
41 #include <sys/kernel.h>
42 #include <sys/socket.h>
43 #include <sys/sysctl.h>
44 #include <sys/syslog.h>
45 #include <sys/ucred.h>
46 #include <sys/lock.h>
47 #include <net/ethernet.h>	/* for ETHERTYPE_IP */
48 #include <net/if.h>
49 #include <net/if_var.h>
50 #include <net/ifq_var.h>
51 #include <net/if_clone.h>
52 #include <net/if_types.h>	/* for IFT_PFLOG */
53 #include <net/bpf.h>		/* for BPF */
54 
55 #include <netinet/in.h>
56 #include <netinet/ip.h>
57 #include <netinet/ip_icmp.h>
58 #include <netinet/ip_var.h>
59 #include <netinet/tcp_var.h>
60 #include <netinet/udp.h>
61 
62 #include <net/ipfw3/ip_fw.h>
63 #include <net/ipfw3_basic/ip_fw3_log.h>
64 
65 extern int sysctl_var_fw3_verbose;
66 extern struct if_clone *if_clone_lookup(const char *, int *);
67 
68 static const char ipfw3_log_ifname[] = "ipfw";
69 static int log_if_count;
70 struct ifnet *log_if_table[LOG_IF_MAX];
71 struct lock log_if_lock;
72 
73 
74 u_char fake_eh[14] = {0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
75 			0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x08, 0x00};
76 
77 static const u_char ipfwbroadcastaddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
78 
79 #define	LOGIF_LOCK_INIT(x) lockinit(&log_if_lock, "fw3log_lk", 0, LK_CANRECURSE)
80 #define	LOGIF_LOCK_DESTROY(x) lockuninit(&log_if_lock)
81 #define	LOGIF_RLOCK(x) lockmgr(&log_if_lock, LK_SHARED)
82 #define	LOGIF_RUNLOCK(x) lockmgr(&log_if_lock, LK_RELEASE)
83 #define	LOGIF_WLOCK(x) lockmgr(&log_if_lock, LK_EXCLUSIVE)
84 #define	LOGIF_WUNLOCK(x) lockmgr(&log_if_lock, LK_RELEASE)
85 
86 
87 /* we use this dummy function for all ifnet callbacks */
88 static int
89 ip_fw3_log_dummy(struct ifnet *ifp, u_long cmd, caddr_t addr, struct ucred *uc)
90 {
91 	return EINVAL;
92 }
93 
94 static int
95 ip_fw3_log_output(struct ifnet *ifp, struct mbuf *m,
96 		struct sockaddr *dst, struct rtentry *rtent)
97 {
98 	if (m != NULL) {
99 		m_freem(m);
100 	}
101 	return EINVAL;
102 }
103 
104 static void
105 ip_fw3_log_start(struct ifnet* ifp, struct ifaltq_subque *subque)
106 {
107 }
108 
109 /*
110  * bpf_mtap into the ipfw interface.
111  * eh == NULL when mbuf is a packet, then use the fake_eh
112  * the ip_len need to be twisted before and after bpf copy.
113  */
114 void
115 ip_fw3_log(struct mbuf *m, struct ether_header *eh, uint16_t id)
116 {
117 	struct ifnet *the_if = NULL;
118 
119 	if (sysctl_var_fw3_verbose) {
120 #ifndef WITHOUT_BPF
121 		LOGIF_RLOCK();
122 		the_if = log_if_table[id];
123 		if (the_if == NULL || the_if->if_bpf == NULL) {
124 			LOGIF_RUNLOCK();
125 			return;
126 		}
127 		if (eh != NULL) {
128 			bpf_gettoken();
129 			bpf_mtap_hdr(the_if->if_bpf, (caddr_t)eh,
130 					ETHER_HDR_LEN, m, 0);
131 			bpf_reltoken();
132 
133 		} else {
134 			struct ip *ip;
135 			ip = mtod(m, struct ip *);
136 			/* twist the ip_len for the bpf copy */
137 			ip->ip_len =htons(ip->ip_len);
138 
139 			bpf_gettoken();
140 			bpf_mtap_hdr(the_if->if_bpf, (caddr_t)fake_eh,
141 					ETHER_HDR_LEN, m, 0);
142 			bpf_reltoken();
143 			ip->ip_len =ntohs(ip->ip_len);
144 
145 		}
146 		LOGIF_RUNLOCK();
147 #endif	/* !WITHOUT_BPF */
148 	}
149 }
150 
151 static int
152 ip_fw3_log_clone_create(struct if_clone *ifc, int unit,
153 			caddr_t params __unused, caddr_t data __unused)
154 {
155 	struct ifnet *ifp;
156 
157 	if (unit < 0 || unit >= LOG_IF_MAX) {
158 		return EINVAL;
159 	}
160 	if (log_if_table[unit] != NULL) {
161 		return EINVAL;
162 	}
163 
164 	ifp = if_alloc(IFT_PFLOG);
165 	if_initname(ifp, ipfw3_log_ifname, unit);
166 	ifq_set_maxlen(&ifp->if_snd, ifqmaxlen);
167 	ifq_set_ready(&ifp->if_snd);
168 
169 	ifp->if_mtu = 65536;
170 	ifp->if_flags = IFF_UP | IFF_SIMPLEX | IFF_MULTICAST;
171 	ifp->if_init = (void *)ip_fw3_log_dummy;
172 	ifp->if_ioctl = ip_fw3_log_dummy;
173 	ifp->if_start = ip_fw3_log_start;
174 	ifp->if_output = ip_fw3_log_output;
175 	ifp->if_addrlen = 6;
176 	ifp->if_hdrlen = 14;
177 	ifp->if_broadcastaddr = ipfwbroadcastaddr;
178 	ifp->if_baudrate = IF_Mbps(10);
179 
180 	LOGIF_WLOCK();
181 	log_if_table[unit] = ifp;
182 	log_if_count++;
183 	if_attach(ifp, NULL);
184 	bpfattach(ifp, DLT_EN10MB, ETHER_HDR_LEN);
185 	LOGIF_WUNLOCK();
186 
187 	return (0);
188 }
189 
190 static int
191 ip_fw3_log_clone_destroy(struct ifnet *ifp)
192 {
193 	int unit;
194 
195 	if (ifp == NULL)
196 		return (0);
197 
198 	unit = ifp->if_dunit;
199 	if (unit < 0 || unit >= LOG_IF_MAX) {
200 		return EINVAL;
201 	}
202 	if (log_if_table[unit] == NULL) {
203 		return EINVAL;
204 	}
205 	LOGIF_WLOCK();
206 	log_if_table[unit] = NULL;
207 	bpfdetach(ifp);
208 	if_detach(ifp);
209 	if_free(ifp);
210 	log_if_count--;
211 	LOGIF_WUNLOCK();
212 
213 	return (0);
214 }
215 
216 static eventhandler_tag ip_fw3_log_ifdetach_cookie;
217 static struct if_clone ipfw3_log_cloner = IF_CLONE_INITIALIZER(ipfw3_log_ifname,
218 		ip_fw3_log_clone_create, ip_fw3_log_clone_destroy, 0, 9);
219 
220 
221 void ip_fw3_log_modevent(int type){
222 	struct ifnet *tmpif;
223 	int i;
224 
225 	switch (type) {
226 	case MOD_LOAD:
227 		LOGIF_LOCK_INIT();
228 		log_if_count = 0;
229 		if_clone_attach(&ipfw3_log_cloner);
230 		ip_fw3_log_ifdetach_cookie =
231 			EVENTHANDLER_REGISTER(ifnet_detach_event,
232 				ip_fw3_log_clone_destroy, &ipfw3_log_cloner,
233 				EVENTHANDLER_PRI_ANY);
234 		break;
235 	case MOD_UNLOAD:
236 		EVENTHANDLER_DEREGISTER(ifnet_detach_event,
237 					ip_fw3_log_ifdetach_cookie);
238 		if_clone_detach(&ipfw3_log_cloner);
239 		for(i = 0; log_if_count > 0 && i < LOG_IF_MAX; i++){
240 			tmpif = log_if_table[i];
241 			if (tmpif != NULL) {
242 				ip_fw3_log_clone_destroy(tmpif);
243 			}
244 		}
245 		LOGIF_LOCK_DESTROY();
246 		break;
247 
248 	default:
249 		break;
250 	}
251 }
252 
253 /* end of file */
254