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
ip_fw3_log_dummy(struct ifnet * ifp,u_long cmd,caddr_t addr,struct ucred * uc)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
ip_fw3_log_output(struct ifnet * ifp,struct mbuf * m,struct sockaddr * dst,struct rtentry * rtent)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
ip_fw3_log_start(struct ifnet * ifp,struct ifaltq_subque * subque)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 */
113 void
ip_fw3_log(struct mbuf * m,struct ether_header * eh,uint16_t id)114 ip_fw3_log(struct mbuf *m, struct ether_header *eh, uint16_t id)
115 {
116 struct ifnet *the_if = NULL;
117
118 if (sysctl_var_fw3_verbose) {
119 #ifndef WITHOUT_BPF
120 LOGIF_RLOCK();
121 the_if = log_if_table[id];
122 if (the_if == NULL || the_if->if_bpf == NULL) {
123 LOGIF_RUNLOCK();
124 return;
125 }
126 if (eh != NULL) {
127 bpf_gettoken();
128 bpf_mtap_hdr(the_if->if_bpf, (caddr_t)eh,
129 ETHER_HDR_LEN, m, 0);
130 bpf_reltoken();
131
132 } else {
133 bpf_gettoken();
134 bpf_mtap_hdr(the_if->if_bpf, (caddr_t)fake_eh,
135 ETHER_HDR_LEN, m, 0);
136 bpf_reltoken();
137 }
138 LOGIF_RUNLOCK();
139 #endif /* !WITHOUT_BPF */
140 }
141 }
142
143 static int
ip_fw3_log_clone_create(struct if_clone * ifc,int unit,caddr_t params __unused,caddr_t data __unused)144 ip_fw3_log_clone_create(struct if_clone *ifc, int unit,
145 caddr_t params __unused, caddr_t data __unused)
146 {
147 struct ifnet *ifp;
148
149 if (unit < 0 || unit >= LOG_IF_MAX) {
150 return EINVAL;
151 }
152 if (log_if_table[unit] != NULL) {
153 return EINVAL;
154 }
155
156 ifp = if_alloc(IFT_PFLOG);
157 if_initname(ifp, ipfw3_log_ifname, unit);
158 ifq_set_maxlen(&ifp->if_snd, ifqmaxlen);
159 ifq_set_ready(&ifp->if_snd);
160
161 ifp->if_mtu = 65536;
162 ifp->if_flags = IFF_UP | IFF_SIMPLEX | IFF_MULTICAST;
163 ifp->if_init = (void *)ip_fw3_log_dummy;
164 ifp->if_ioctl = ip_fw3_log_dummy;
165 ifp->if_start = ip_fw3_log_start;
166 ifp->if_output = ip_fw3_log_output;
167 ifp->if_addrlen = 6;
168 ifp->if_hdrlen = 14;
169 ifp->if_broadcastaddr = ipfwbroadcastaddr;
170 ifp->if_baudrate = IF_Mbps(10);
171
172 LOGIF_WLOCK();
173 log_if_table[unit] = ifp;
174 log_if_count++;
175 if_attach(ifp, NULL);
176 bpfattach(ifp, DLT_EN10MB, ETHER_HDR_LEN);
177 LOGIF_WUNLOCK();
178
179 return (0);
180 }
181
182 static int
ip_fw3_log_clone_destroy(struct ifnet * ifp)183 ip_fw3_log_clone_destroy(struct ifnet *ifp)
184 {
185 int unit;
186
187 if (ifp == NULL)
188 return (0);
189
190 unit = ifp->if_dunit;
191 if (unit < 0 || unit >= LOG_IF_MAX) {
192 return EINVAL;
193 }
194 if (log_if_table[unit] == NULL) {
195 return EINVAL;
196 }
197 LOGIF_WLOCK();
198 log_if_table[unit] = NULL;
199 bpfdetach(ifp);
200 if_detach(ifp);
201 if_free(ifp);
202 log_if_count--;
203 LOGIF_WUNLOCK();
204
205 return (0);
206 }
207
208 static eventhandler_tag ip_fw3_log_ifdetach_cookie;
209 static struct if_clone ipfw3_log_cloner = IF_CLONE_INITIALIZER(ipfw3_log_ifname,
210 ip_fw3_log_clone_create, ip_fw3_log_clone_destroy, 0, 9);
211
212
ip_fw3_log_modevent(int type)213 void ip_fw3_log_modevent(int type){
214 struct ifnet *tmpif;
215 int i;
216
217 switch (type) {
218 case MOD_LOAD:
219 LOGIF_LOCK_INIT();
220 log_if_count = 0;
221 if_clone_attach(&ipfw3_log_cloner);
222 ip_fw3_log_ifdetach_cookie =
223 EVENTHANDLER_REGISTER(ifnet_detach_event,
224 ip_fw3_log_clone_destroy, &ipfw3_log_cloner,
225 EVENTHANDLER_PRI_ANY);
226 break;
227 case MOD_UNLOAD:
228 EVENTHANDLER_DEREGISTER(ifnet_detach_event,
229 ip_fw3_log_ifdetach_cookie);
230 if_clone_detach(&ipfw3_log_cloner);
231 for(i = 0; log_if_count > 0 && i < LOG_IF_MAX; i++){
232 tmpif = log_if_table[i];
233 if (tmpif != NULL) {
234 ip_fw3_log_clone_destroy(tmpif);
235 }
236 }
237 LOGIF_LOCK_DESTROY();
238 break;
239
240 default:
241 break;
242 }
243 }
244
245 /* end of file */
246