xref: /dflybsd-src/sys/net/ipfw3_basic/ip_fw3_log.c (revision 8a93af2a9b3a6586d0d394bec8454562ee76044f)
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