mtree(8): Fix crc() prototype.
[dragonfly.git] / sys / net / ipfw3 / ip_fw3_log.c
1 /*
2  * Copyright (c) 2002-2009 Luigi Rizzo, Universita` di Pisa
3  *
4  * Copyright (c) 2015 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 "opt_inet.h"
38 #ifndef INET
39 #error IPFIREWALL3 requires INET.
40 #endif
41
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 */
60
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>
67
68 #ifdef INET6
69 #include <netinet/ip6.h>
70 #include <netinet/icmp6.h>
71 #include <netinet6/in6_var.h>   /* ip6_sprintf() */
72 #endif
73
74 #include <net/ipfw3/ip_fw.h>
75 #include <net/ipfw3/ip_fw3_log.h>
76
77 extern int fw_verbose;
78 extern struct if_clone *if_clone_lookup(const char *, int *);
79
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;
84
85
86 u_char fake_eh[14] = {0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
87                         0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x08, 0x00};
88
89 static const u_char ipfwbroadcastaddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
90
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)
97
98
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)
102 {
103         return EINVAL;
104 }
105
106 static int
107 ipfw_log_output(struct ifnet *ifp, struct mbuf *m,
108                 struct sockaddr *dst, struct rtentry *rtent)
109 {
110         if (m != NULL) {
111                 m_freem(m);
112         }
113         return EINVAL;
114 }
115
116 static void
117 ipfw_log_start(struct ifnet* ifp, struct ifaltq_subque *subque)
118 {
119 }
120
121 /*
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.
125  */
126 void
127 ipfw_log(struct mbuf *m, struct ether_header *eh, uint16_t id)
128 {
129         struct ifnet *the_if = NULL;
130
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;
138                 }
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();
144
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);
150
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);
156
157                 }
158                 LOGIF_RUNLOCK();
159 #endif  /* !WITHOUT_BPF */
160         }
161 }
162
163 static int
164 ipfw_log_clone_create(struct if_clone *ifc, int unit, caddr_t param __unused)
165 {
166         struct ifnet *ifp;
167
168         if (unit < 0 || unit >= LOG_IF_MAX) {
169                 return EINVAL;
170         }
171         if (log_if_table[unit] != NULL) {
172                 return EINVAL;
173         }
174
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);
179
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);
190
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();
197
198         return (0);
199 }
200
201 static int
202 ipfw_log_clone_destroy(struct ifnet *ifp)
203 {
204         int unit;
205
206         if (ifp == NULL)
207                 return (0);
208
209         unit = ifp->if_dunit;
210         if (unit < 0 || unit >= LOG_IF_MAX) {
211                 return EINVAL;
212         }
213         if (log_if_table[unit] == NULL) {
214                 return EINVAL;
215         }
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();
223
224         return (0);
225 }
226
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);
230
231
232 void ipfw3_log_modevent(int type){
233         struct ifnet *tmpif;
234         int i;
235
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);
254                         }
255                 }
256                 LOGIF_LOCK_DESTROY();
257                 break;
258
259         default:
260                 break;
261         }
262 }
263
264 /* end of file */