14408d548SBill Yuan /*
24408d548SBill Yuan * Copyright (c) 2002-2009 Luigi Rizzo, Universita` di Pisa
34408d548SBill Yuan *
44408d548SBill Yuan * Copyright (c) 2015 - 2018 The DragonFly Project. All rights reserved.
54408d548SBill Yuan *
64408d548SBill Yuan * This code is derived from software contributed to The DragonFly Project
74408d548SBill Yuan * by Bill Yuan <bycn82@dragonflybsd.org>
84408d548SBill Yuan *
94408d548SBill Yuan * Redistribution and use in source and binary forms, with or without
104408d548SBill Yuan * modification, are permitted provided that the following conditions
114408d548SBill Yuan * are met:
124408d548SBill Yuan *
134408d548SBill Yuan * 1. Redistributions of source code must retain the above copyright
144408d548SBill Yuan * notice, this list of conditions and the following disclaimer.
154408d548SBill Yuan * 2. Redistributions in binary form must reproduce the above copyright
164408d548SBill Yuan * notice, this list of conditions and the following disclaimer in
174408d548SBill Yuan * the documentation and/or other materials provided with the
184408d548SBill Yuan * distribution.
194408d548SBill Yuan * 3. Neither the name of The DragonFly Project nor the names of its
204408d548SBill Yuan * contributors may be used to endorse or promote products derived
214408d548SBill Yuan * from this software without specific, prior written permission.
224408d548SBill Yuan *
234408d548SBill Yuan * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
244408d548SBill Yuan * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
254408d548SBill Yuan * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
264408d548SBill Yuan * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
274408d548SBill Yuan * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
284408d548SBill Yuan * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
294408d548SBill Yuan * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
304408d548SBill Yuan * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
314408d548SBill Yuan * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
324408d548SBill Yuan * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
334408d548SBill Yuan * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
344408d548SBill Yuan * SUCH DAMAGE.
354408d548SBill Yuan */
364408d548SBill Yuan
374408d548SBill Yuan #include <sys/cdefs.h>
384408d548SBill Yuan #include <sys/param.h>
394408d548SBill Yuan #include <sys/systm.h>
404408d548SBill Yuan #include <sys/mbuf.h>
414408d548SBill Yuan #include <sys/kernel.h>
424408d548SBill Yuan #include <sys/socket.h>
434408d548SBill Yuan #include <sys/sysctl.h>
444408d548SBill Yuan #include <sys/syslog.h>
454408d548SBill Yuan #include <sys/ucred.h>
464408d548SBill Yuan #include <sys/lock.h>
474408d548SBill Yuan #include <net/ethernet.h> /* for ETHERTYPE_IP */
484408d548SBill Yuan #include <net/if.h>
494408d548SBill Yuan #include <net/if_var.h>
504408d548SBill Yuan #include <net/ifq_var.h>
514408d548SBill Yuan #include <net/if_clone.h>
524408d548SBill Yuan #include <net/if_types.h> /* for IFT_PFLOG */
534408d548SBill Yuan #include <net/bpf.h> /* for BPF */
544408d548SBill Yuan
554408d548SBill Yuan #include <netinet/in.h>
564408d548SBill Yuan #include <netinet/ip.h>
574408d548SBill Yuan #include <netinet/ip_icmp.h>
584408d548SBill Yuan #include <netinet/ip_var.h>
594408d548SBill Yuan #include <netinet/tcp_var.h>
604408d548SBill Yuan #include <netinet/udp.h>
614408d548SBill Yuan
624408d548SBill Yuan #include <net/ipfw3/ip_fw.h>
634408d548SBill Yuan #include <net/ipfw3_basic/ip_fw3_log.h>
644408d548SBill Yuan
654408d548SBill Yuan extern int sysctl_var_fw3_verbose;
664408d548SBill Yuan extern struct if_clone *if_clone_lookup(const char *, int *);
674408d548SBill Yuan
684408d548SBill Yuan static const char ipfw3_log_ifname[] = "ipfw";
694408d548SBill Yuan static int log_if_count;
704408d548SBill Yuan struct ifnet *log_if_table[LOG_IF_MAX];
714408d548SBill Yuan struct lock log_if_lock;
724408d548SBill Yuan
734408d548SBill Yuan
744408d548SBill Yuan u_char fake_eh[14] = {0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
754408d548SBill Yuan 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x08, 0x00};
764408d548SBill Yuan
774408d548SBill Yuan static const u_char ipfwbroadcastaddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
784408d548SBill Yuan
794408d548SBill Yuan #define LOGIF_LOCK_INIT(x) lockinit(&log_if_lock, "fw3log_lk", 0, LK_CANRECURSE)
804408d548SBill Yuan #define LOGIF_LOCK_DESTROY(x) lockuninit(&log_if_lock)
814408d548SBill Yuan #define LOGIF_RLOCK(x) lockmgr(&log_if_lock, LK_SHARED)
824408d548SBill Yuan #define LOGIF_RUNLOCK(x) lockmgr(&log_if_lock, LK_RELEASE)
834408d548SBill Yuan #define LOGIF_WLOCK(x) lockmgr(&log_if_lock, LK_EXCLUSIVE)
844408d548SBill Yuan #define LOGIF_WUNLOCK(x) lockmgr(&log_if_lock, LK_RELEASE)
854408d548SBill Yuan
864408d548SBill Yuan
874408d548SBill Yuan /* we use this dummy function for all ifnet callbacks */
884408d548SBill Yuan static int
ip_fw3_log_dummy(struct ifnet * ifp,u_long cmd,caddr_t addr,struct ucred * uc)894408d548SBill Yuan ip_fw3_log_dummy(struct ifnet *ifp, u_long cmd, caddr_t addr, struct ucred *uc)
904408d548SBill Yuan {
914408d548SBill Yuan return EINVAL;
924408d548SBill Yuan }
934408d548SBill Yuan
944408d548SBill Yuan static int
ip_fw3_log_output(struct ifnet * ifp,struct mbuf * m,struct sockaddr * dst,struct rtentry * rtent)954408d548SBill Yuan ip_fw3_log_output(struct ifnet *ifp, struct mbuf *m,
964408d548SBill Yuan struct sockaddr *dst, struct rtentry *rtent)
974408d548SBill Yuan {
984408d548SBill Yuan if (m != NULL) {
994408d548SBill Yuan m_freem(m);
1004408d548SBill Yuan }
1014408d548SBill Yuan return EINVAL;
1024408d548SBill Yuan }
1034408d548SBill Yuan
1044408d548SBill Yuan static void
ip_fw3_log_start(struct ifnet * ifp,struct ifaltq_subque * subque)1054408d548SBill Yuan ip_fw3_log_start(struct ifnet* ifp, struct ifaltq_subque *subque)
1064408d548SBill Yuan {
1074408d548SBill Yuan }
1084408d548SBill Yuan
1094408d548SBill Yuan /*
1104408d548SBill Yuan * bpf_mtap into the ipfw interface.
111*8a93af2aSMatthew Dillon * eh == NULL when mbuf is a packet, then use the fake_eh.
1124408d548SBill Yuan */
1134408d548SBill Yuan void
ip_fw3_log(struct mbuf * m,struct ether_header * eh,uint16_t id)1144408d548SBill Yuan ip_fw3_log(struct mbuf *m, struct ether_header *eh, uint16_t id)
1154408d548SBill Yuan {
1164408d548SBill Yuan struct ifnet *the_if = NULL;
1174408d548SBill Yuan
1184408d548SBill Yuan if (sysctl_var_fw3_verbose) {
1194408d548SBill Yuan #ifndef WITHOUT_BPF
1204408d548SBill Yuan LOGIF_RLOCK();
1214408d548SBill Yuan the_if = log_if_table[id];
1224408d548SBill Yuan if (the_if == NULL || the_if->if_bpf == NULL) {
1234408d548SBill Yuan LOGIF_RUNLOCK();
1244408d548SBill Yuan return;
1254408d548SBill Yuan }
1264408d548SBill Yuan if (eh != NULL) {
1274408d548SBill Yuan bpf_gettoken();
1284408d548SBill Yuan bpf_mtap_hdr(the_if->if_bpf, (caddr_t)eh,
1294408d548SBill Yuan ETHER_HDR_LEN, m, 0);
1304408d548SBill Yuan bpf_reltoken();
1314408d548SBill Yuan
1324408d548SBill Yuan } else {
1334408d548SBill Yuan bpf_gettoken();
1344408d548SBill Yuan bpf_mtap_hdr(the_if->if_bpf, (caddr_t)fake_eh,
1354408d548SBill Yuan ETHER_HDR_LEN, m, 0);
1364408d548SBill Yuan bpf_reltoken();
1374408d548SBill Yuan }
1384408d548SBill Yuan LOGIF_RUNLOCK();
1394408d548SBill Yuan #endif /* !WITHOUT_BPF */
1404408d548SBill Yuan }
1414408d548SBill Yuan }
1424408d548SBill Yuan
1434408d548SBill Yuan static int
ip_fw3_log_clone_create(struct if_clone * ifc,int unit,caddr_t params __unused,caddr_t data __unused)144bb54c3a2SAaron LI ip_fw3_log_clone_create(struct if_clone *ifc, int unit,
145bb54c3a2SAaron LI caddr_t params __unused, caddr_t data __unused)
1464408d548SBill Yuan {
1474408d548SBill Yuan struct ifnet *ifp;
1484408d548SBill Yuan
1494408d548SBill Yuan if (unit < 0 || unit >= LOG_IF_MAX) {
1504408d548SBill Yuan return EINVAL;
1514408d548SBill Yuan }
1524408d548SBill Yuan if (log_if_table[unit] != NULL) {
1534408d548SBill Yuan return EINVAL;
1544408d548SBill Yuan }
1554408d548SBill Yuan
1564408d548SBill Yuan ifp = if_alloc(IFT_PFLOG);
1574408d548SBill Yuan if_initname(ifp, ipfw3_log_ifname, unit);
1584408d548SBill Yuan ifq_set_maxlen(&ifp->if_snd, ifqmaxlen);
1594408d548SBill Yuan ifq_set_ready(&ifp->if_snd);
1604408d548SBill Yuan
1614408d548SBill Yuan ifp->if_mtu = 65536;
1624408d548SBill Yuan ifp->if_flags = IFF_UP | IFF_SIMPLEX | IFF_MULTICAST;
1634408d548SBill Yuan ifp->if_init = (void *)ip_fw3_log_dummy;
1644408d548SBill Yuan ifp->if_ioctl = ip_fw3_log_dummy;
1654408d548SBill Yuan ifp->if_start = ip_fw3_log_start;
1664408d548SBill Yuan ifp->if_output = ip_fw3_log_output;
1674408d548SBill Yuan ifp->if_addrlen = 6;
1684408d548SBill Yuan ifp->if_hdrlen = 14;
1694408d548SBill Yuan ifp->if_broadcastaddr = ipfwbroadcastaddr;
1704408d548SBill Yuan ifp->if_baudrate = IF_Mbps(10);
1714408d548SBill Yuan
1724408d548SBill Yuan LOGIF_WLOCK();
1734408d548SBill Yuan log_if_table[unit] = ifp;
1744408d548SBill Yuan log_if_count++;
1754408d548SBill Yuan if_attach(ifp, NULL);
1764408d548SBill Yuan bpfattach(ifp, DLT_EN10MB, ETHER_HDR_LEN);
1774408d548SBill Yuan LOGIF_WUNLOCK();
1784408d548SBill Yuan
1794408d548SBill Yuan return (0);
1804408d548SBill Yuan }
1814408d548SBill Yuan
1824408d548SBill Yuan static int
ip_fw3_log_clone_destroy(struct ifnet * ifp)1834408d548SBill Yuan ip_fw3_log_clone_destroy(struct ifnet *ifp)
1844408d548SBill Yuan {
1854408d548SBill Yuan int unit;
1864408d548SBill Yuan
1874408d548SBill Yuan if (ifp == NULL)
1884408d548SBill Yuan return (0);
1894408d548SBill Yuan
1904408d548SBill Yuan unit = ifp->if_dunit;
1914408d548SBill Yuan if (unit < 0 || unit >= LOG_IF_MAX) {
1924408d548SBill Yuan return EINVAL;
1934408d548SBill Yuan }
1944408d548SBill Yuan if (log_if_table[unit] == NULL) {
1954408d548SBill Yuan return EINVAL;
1964408d548SBill Yuan }
1974408d548SBill Yuan LOGIF_WLOCK();
1984408d548SBill Yuan log_if_table[unit] = NULL;
1994408d548SBill Yuan bpfdetach(ifp);
2004408d548SBill Yuan if_detach(ifp);
2014408d548SBill Yuan if_free(ifp);
2024408d548SBill Yuan log_if_count--;
2034408d548SBill Yuan LOGIF_WUNLOCK();
2044408d548SBill Yuan
2054408d548SBill Yuan return (0);
2064408d548SBill Yuan }
2074408d548SBill Yuan
2084408d548SBill Yuan static eventhandler_tag ip_fw3_log_ifdetach_cookie;
2094408d548SBill Yuan static struct if_clone ipfw3_log_cloner = IF_CLONE_INITIALIZER(ipfw3_log_ifname,
2104408d548SBill Yuan ip_fw3_log_clone_create, ip_fw3_log_clone_destroy, 0, 9);
2114408d548SBill Yuan
2124408d548SBill Yuan
ip_fw3_log_modevent(int type)2134408d548SBill Yuan void ip_fw3_log_modevent(int type){
2144408d548SBill Yuan struct ifnet *tmpif;
2154408d548SBill Yuan int i;
2164408d548SBill Yuan
2174408d548SBill Yuan switch (type) {
2184408d548SBill Yuan case MOD_LOAD:
2194408d548SBill Yuan LOGIF_LOCK_INIT();
2204408d548SBill Yuan log_if_count = 0;
2214408d548SBill Yuan if_clone_attach(&ipfw3_log_cloner);
2224408d548SBill Yuan ip_fw3_log_ifdetach_cookie =
2234408d548SBill Yuan EVENTHANDLER_REGISTER(ifnet_detach_event,
2244408d548SBill Yuan ip_fw3_log_clone_destroy, &ipfw3_log_cloner,
2254408d548SBill Yuan EVENTHANDLER_PRI_ANY);
2264408d548SBill Yuan break;
2274408d548SBill Yuan case MOD_UNLOAD:
2284408d548SBill Yuan EVENTHANDLER_DEREGISTER(ifnet_detach_event,
2294408d548SBill Yuan ip_fw3_log_ifdetach_cookie);
2304408d548SBill Yuan if_clone_detach(&ipfw3_log_cloner);
2314408d548SBill Yuan for(i = 0; log_if_count > 0 && i < LOG_IF_MAX; i++){
2324408d548SBill Yuan tmpif = log_if_table[i];
2334408d548SBill Yuan if (tmpif != NULL) {
2344408d548SBill Yuan ip_fw3_log_clone_destroy(tmpif);
2354408d548SBill Yuan }
2364408d548SBill Yuan }
2374408d548SBill Yuan LOGIF_LOCK_DESTROY();
2384408d548SBill Yuan break;
2394408d548SBill Yuan
2404408d548SBill Yuan default:
2414408d548SBill Yuan break;
2424408d548SBill Yuan }
2434408d548SBill Yuan }
2444408d548SBill Yuan
2454408d548SBill Yuan /* end of file */
246