13b9b51feSCy Schubert 
23b9b51feSCy Schubert /*
33b9b51feSCy Schubert * Copyright (C) 2012 by Darren Reed.
43b9b51feSCy Schubert *
53b9b51feSCy Schubert * Redistribution and use in source and binary forms are permitted
63b9b51feSCy Schubert * provided that this notice is preserved and due credit is given
73b9b51feSCy Schubert * to the original author and the contributors.
83b9b51feSCy Schubert */
93b9b51feSCy Schubert 
103b9b51feSCy Schubert #include <sys/param.h>
113b9b51feSCy Schubert #include <sys/types.h>
123b9b51feSCy Schubert #include <sys/time.h>
133b9b51feSCy Schubert #include <sys/socket.h>
143b9b51feSCy Schubert #if defined(__FreeBSD__)
153b9b51feSCy Schubert # if defined(_KERNEL)
163b9b51feSCy Schubert #  include <sys/libkern.h>
173b9b51feSCy Schubert # else
183b9b51feSCy Schubert #  include <sys/unistd.h>
193b9b51feSCy Schubert # endif
203b9b51feSCy Schubert #else
213b9b51feSCy Schubert # include <sys/systm.h>
223b9b51feSCy Schubert #endif
233b9b51feSCy Schubert #include <sys/errno.h>
243b9b51feSCy Schubert #include <sys/param.h>
253b9b51feSCy Schubert #if !defined(__SVR4)
263b9b51feSCy Schubert # include <sys/mbuf.h>
273b9b51feSCy Schubert #endif
283b9b51feSCy Schubert #if defined(__FreeBSD__)
293b9b51feSCy Schubert # include <sys/sockio.h>
303b9b51feSCy Schubert #if defined(_KERNEL)
313b9b51feSCy Schubert #include <net/vnet.h>
323b9b51feSCy Schubert #else
333b9b51feSCy Schubert #define CURVNET_SET(arg)
343b9b51feSCy Schubert #define CURVNET_RESTORE()
353b9b51feSCy Schubert #define	VNET_DEFINE(_t, _v)	_t _v
363b9b51feSCy Schubert #define	VNET_DECLARE(_t, _v)	extern _t _v
373b9b51feSCy Schubert #define	VNET(arg)	arg
383b9b51feSCy Schubert #endif
393b9b51feSCy Schubert #else
403b9b51feSCy Schubert # include <sys/ioctl.h>
413b9b51feSCy Schubert #endif /* FreeBSD */
423b9b51feSCy Schubert #include <net/if.h>
433b9b51feSCy Schubert #include <netinet/in.h>
443b9b51feSCy Schubert #include <netinet/in_systm.h>
453b9b51feSCy Schubert #include <netinet/ip.h>
463b9b51feSCy Schubert #include <netinet/tcp.h>
473b9b51feSCy Schubert #include "netinet/ip_compat.h"
483b9b51feSCy Schubert #include "netinet/ip_fil.h"
493b9b51feSCy Schubert 
503b9b51feSCy Schubert #include "netinet/ip_rules.h"
513b9b51feSCy Schubert 
523b9b51feSCy Schubert #ifndef _KERNEL
533b9b51feSCy Schubert # include <string.h>
543b9b51feSCy Schubert #endif /* _KERNEL */
553b9b51feSCy Schubert 
563b9b51feSCy Schubert #ifdef IPFILTER_COMPILED
573b9b51feSCy Schubert 
583b9b51feSCy Schubert VNET_DECLARE(ipf_main_softc_t, ipfmain);
593b9b51feSCy Schubert #define	V_ipfmain		VNET(ipfmain)
603b9b51feSCy Schubert 
613b9b51feSCy Schubert 
623b9b51feSCy Schubert static u_long in_rule__0[] = {
633b9b51feSCy Schubert 0, 0, 0, 0, 0, 0, 0, 0x8070d88, 0, 0, 0, 0xffffffff, 0, 0, 0, 0, 0, 0, 0, 0xffffffff, 0x1b0, 0x1, 0, 0, 0, 0x2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x40000000, 0x8002, 0, 0, 0, 0xffff, 0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xffffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0xffffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0xffffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xffffffff, 0, 0, 0, 0
643b9b51feSCy Schubert };
653b9b51feSCy Schubert 
663b9b51feSCy Schubert static u_long out_rule__0[] = {
673b9b51feSCy Schubert 0, 0, 0, 0, 0, 0, 0, 0x8070d88, 0, 0, 0, 0xffffffff, 0, 0, 0, 0, 0, 0, 0, 0xffffffff, 0x1b0, 0x1, 0, 0, 0, 0x3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x40000000, 0x4002, 0, 0, 0, 0xffff, 0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xffffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0xffffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0xffffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xffffffff, 0, 0, 0, 0
683b9b51feSCy Schubert };
693b9b51feSCy Schubert 
703b9b51feSCy Schubert frentry_t *ipf_rules_in_[1] = {
713b9b51feSCy Schubert 	(frentry_t *)&in_rule__0
723b9b51feSCy Schubert };
733b9b51feSCy Schubert 
743b9b51feSCy Schubert /* XXX	This file (ip_rules.c) is not part of the ipfilter tarball, it is
753b9b51feSCy Schubert    XXX	generated by the ipfilter build process. Unfortunately the build
763b9b51feSCy Schubert    XXX  process did not generate the following lines so they are added
773b9b51feSCy Schubert    XXX	by hand here. This is a bit of a hack but it works for now. Future
783b9b51feSCy Schubert    XXX  imports/merges of ipfilter may generate this so the following will
793b9b51feSCy Schubert    XXX	need to be removed following some future merge.
803b9b51feSCy Schubert    XXX	*/
813b9b51feSCy Schubert frentry_t *ipf_rules_out_[1] = {
823b9b51feSCy Schubert 	(frentry_t *)&out_rule__0
833b9b51feSCy Schubert };
843b9b51feSCy Schubert 
ipfrule_match_in_(fin,passp)853b9b51feSCy Schubert frentry_t *ipfrule_match_in_(fin, passp)
863b9b51feSCy Schubert fr_info_t *fin;
873b9b51feSCy Schubert u_32_t *passp;
883b9b51feSCy Schubert {
893b9b51feSCy Schubert 	frentry_t *fr = NULL;
903b9b51feSCy Schubert 
913b9b51feSCy Schubert 	fr = (frentry_t *)&in_rule__0;
928c82b374SCy Schubert 	return (fr);
933b9b51feSCy Schubert }
943b9b51feSCy Schubert 
ipfrule_match_out_(fin,passp)953b9b51feSCy Schubert frentry_t *ipfrule_match_out_(fin, passp)
963b9b51feSCy Schubert fr_info_t *fin;
973b9b51feSCy Schubert u_32_t *passp;
983b9b51feSCy Schubert {
993b9b51feSCy Schubert 	frentry_t *fr = NULL;
1003b9b51feSCy Schubert 
1013b9b51feSCy Schubert 	fr = (frentry_t *)&out_rule__0;
1028c82b374SCy Schubert 	return (fr);
1033b9b51feSCy Schubert }
1043b9b51feSCy Schubert static frentry_t ipfrule_out_;
1053b9b51feSCy Schubert 
ipfrule_add_out_(void)106064a5a95SCy Schubert int ipfrule_add_out_(void)
1073b9b51feSCy Schubert {
1083b9b51feSCy Schubert 	int i, j, err = 0, max;
1093b9b51feSCy Schubert 	frentry_t *fp;
1103b9b51feSCy Schubert 
1113b9b51feSCy Schubert 	max = sizeof(ipf_rules_out_)/sizeof(frentry_t *);
1123b9b51feSCy Schubert 	for (i = 0; i < max; i++) {
1133b9b51feSCy Schubert 		fp = ipf_rules_out_[i];
1143b9b51feSCy Schubert 		fp->fr_next = NULL;
1153b9b51feSCy Schubert 		for (j = i + 1; j < max; j++)
1163b9b51feSCy Schubert 			if (strncmp(fp->fr_names + fp->fr_group,
1173b9b51feSCy Schubert 				    ipf_rules_out_[j]->fr_names +
1183b9b51feSCy Schubert 				    ipf_rules_out_[j]->fr_group,
1193b9b51feSCy Schubert 				    FR_GROUPLEN) == 0) {
1203b9b51feSCy Schubert 				if (ipf_rules_out_[j] != NULL)
1213b9b51feSCy Schubert 					ipf_rules_out_[j]->fr_pnext =
1223b9b51feSCy Schubert 					    &fp->fr_next;
1233b9b51feSCy Schubert 				fp->fr_pnext = &ipf_rules_out_[j];
1243b9b51feSCy Schubert 				fp->fr_next = ipf_rules_out_[j];
1253b9b51feSCy Schubert 				break;
1263b9b51feSCy Schubert 			}
1273b9b51feSCy Schubert 	}
1283b9b51feSCy Schubert 
1293b9b51feSCy Schubert 	fp = &ipfrule_out_;
1303b9b51feSCy Schubert 	bzero((char *)fp, sizeof(*fp));
1313b9b51feSCy Schubert 	fp->fr_type = FR_T_CALLFUNC_BUILTIN;
1323b9b51feSCy Schubert 	fp->fr_flags = FR_OUTQUE|FR_NOMATCH;
1333b9b51feSCy Schubert 	fp->fr_data = (void *)ipf_rules_out_[0];
1343b9b51feSCy Schubert 	fp->fr_dsize = sizeof(ipf_rules_out_[0]);
1353b9b51feSCy Schubert 	fp->fr_family = AF_INET;
1363b9b51feSCy Schubert 	fp->fr_func = (ipfunc_t)ipfrule_match_out_;
1373b9b51feSCy Schubert 	err = frrequest(&V_ipfmain, IPL_LOGIPF, SIOCADDFR, (caddr_t)fp,
1383b9b51feSCy Schubert 			V_ipfmain.ipf_active, 0);
1398c82b374SCy Schubert 	return (err);
1403b9b51feSCy Schubert }
1413b9b51feSCy Schubert 
1423b9b51feSCy Schubert 
ipfrule_remove_out_(void)143064a5a95SCy Schubert int ipfrule_remove_out_(void)
1443b9b51feSCy Schubert {
1453b9b51feSCy Schubert 	int err = 0, i;
1463b9b51feSCy Schubert 	frentry_t *fp;
1473b9b51feSCy Schubert 
1483b9b51feSCy Schubert 	/*
1493b9b51feSCy Schubert 	 * Try to remove the outbound rule.
1503b9b51feSCy Schubert 	 */
1513b9b51feSCy Schubert 	if (ipfrule_out_.fr_ref > 0) {
1523b9b51feSCy Schubert 		err = EBUSY;
1533b9b51feSCy Schubert 	} else {
1543b9b51feSCy Schubert 		i = sizeof(ipf_rules_out_)/sizeof(frentry_t *) - 1;
1553b9b51feSCy Schubert 		for (; i >= 0; i--) {
1563b9b51feSCy Schubert 			fp = ipf_rules_out_[i];
1573b9b51feSCy Schubert 			if (fp->fr_ref > 1) {
1583b9b51feSCy Schubert 				err = EBUSY;
1593b9b51feSCy Schubert 				break;
1603b9b51feSCy Schubert 			}
1613b9b51feSCy Schubert 		}
1623b9b51feSCy Schubert 	}
1633b9b51feSCy Schubert 	if (err == 0)
1643b9b51feSCy Schubert 		err = frrequest(&V_ipfmain, IPL_LOGIPF, SIOCDELFR,
1653b9b51feSCy Schubert 				(caddr_t)&ipfrule_out_,
1663b9b51feSCy Schubert 				V_ipfmain.ipf_active, 0);
1673b9b51feSCy Schubert 	if (err)
1688c82b374SCy Schubert 		return (err);
1693b9b51feSCy Schubert 
1703b9b51feSCy Schubert 
1718c82b374SCy Schubert 	return (err);
1723b9b51feSCy Schubert }
1733b9b51feSCy Schubert static frentry_t ipfrule_in_;
1743b9b51feSCy Schubert 
ipfrule_add_in_(void)175064a5a95SCy Schubert int ipfrule_add_in_(void)
1763b9b51feSCy Schubert {
1773b9b51feSCy Schubert 	int i, j, err = 0, max;
1783b9b51feSCy Schubert 	frentry_t *fp;
1793b9b51feSCy Schubert 
1803b9b51feSCy Schubert 	max = sizeof(ipf_rules_in_)/sizeof(frentry_t *);
1813b9b51feSCy Schubert 	for (i = 0; i < max; i++) {
1823b9b51feSCy Schubert 		fp = ipf_rules_in_[i];
1833b9b51feSCy Schubert 		fp->fr_next = NULL;
1843b9b51feSCy Schubert 		for (j = i + 1; j < max; j++)
1853b9b51feSCy Schubert 			if (strncmp(fp->fr_names + fp->fr_group,
1863b9b51feSCy Schubert 				    ipf_rules_in_[j]->fr_names +
1873b9b51feSCy Schubert 				    ipf_rules_in_[j]->fr_group,
1883b9b51feSCy Schubert 				    FR_GROUPLEN) == 0) {
1893b9b51feSCy Schubert 				if (ipf_rules_in_[j] != NULL)
1903b9b51feSCy Schubert 					ipf_rules_in_[j]->fr_pnext =
1913b9b51feSCy Schubert 					    &fp->fr_next;
1923b9b51feSCy Schubert 				fp->fr_pnext = &ipf_rules_in_[j];
1933b9b51feSCy Schubert 				fp->fr_next = ipf_rules_in_[j];
1943b9b51feSCy Schubert 				break;
1953b9b51feSCy Schubert 			}
1963b9b51feSCy Schubert 	}
1973b9b51feSCy Schubert 
1983b9b51feSCy Schubert 	fp = &ipfrule_in_;
1993b9b51feSCy Schubert 	bzero((char *)fp, sizeof(*fp));
2003b9b51feSCy Schubert 	fp->fr_type = FR_T_CALLFUNC_BUILTIN;
2013b9b51feSCy Schubert 	fp->fr_flags = FR_INQUE|FR_NOMATCH;
2023b9b51feSCy Schubert 	fp->fr_data = (void *)ipf_rules_in_[0];
2033b9b51feSCy Schubert 	fp->fr_dsize = sizeof(ipf_rules_in_[0]);
2043b9b51feSCy Schubert 	fp->fr_family = AF_INET;
2053b9b51feSCy Schubert 	fp->fr_func = (ipfunc_t)ipfrule_match_in_;
2063b9b51feSCy Schubert 	err = frrequest(&V_ipfmain, IPL_LOGIPF, SIOCADDFR, (caddr_t)fp,
2073b9b51feSCy Schubert 			V_ipfmain.ipf_active, 0);
2088c82b374SCy Schubert 	return (err);
2093b9b51feSCy Schubert }
2103b9b51feSCy Schubert 
2113b9b51feSCy Schubert 
ipfrule_remove_in_(void)212064a5a95SCy Schubert int ipfrule_remove_in_(void)
2133b9b51feSCy Schubert {
2143b9b51feSCy Schubert 	int err = 0, i;
2153b9b51feSCy Schubert 	frentry_t *fp;
2163b9b51feSCy Schubert 
2173b9b51feSCy Schubert 	/*
2183b9b51feSCy Schubert 	 * Try to remove the inbound rule.
2193b9b51feSCy Schubert 	 */
2203b9b51feSCy Schubert 	if (ipfrule_in_.fr_ref > 0) {
2213b9b51feSCy Schubert 		err = EBUSY;
2223b9b51feSCy Schubert 	} else {
2233b9b51feSCy Schubert 		i = sizeof(ipf_rules_in_)/sizeof(frentry_t *) - 1;
2243b9b51feSCy Schubert 		for (; i >= 0; i--) {
2253b9b51feSCy Schubert 			fp = ipf_rules_in_[i];
2263b9b51feSCy Schubert 			if (fp->fr_ref > 1) {
2273b9b51feSCy Schubert 				err = EBUSY;
2283b9b51feSCy Schubert 				break;
2293b9b51feSCy Schubert 			}
2303b9b51feSCy Schubert 		}
2313b9b51feSCy Schubert 	}
2323b9b51feSCy Schubert 	if (err == 0)
2333b9b51feSCy Schubert 		err = frrequest(&V_ipfmain, IPL_LOGIPF, SIOCDELFR,
2343b9b51feSCy Schubert 				(caddr_t)&ipfrule_in_,
2353b9b51feSCy Schubert 				V_ipfmain.ipf_active, 0);
2363b9b51feSCy Schubert 	if (err)
2378c82b374SCy Schubert 		return (err);
2383b9b51feSCy Schubert 
2393b9b51feSCy Schubert 
2408c82b374SCy Schubert 	return (err);
2413b9b51feSCy Schubert }
2423b9b51feSCy Schubert 
ipfrule_add(void)243064a5a95SCy Schubert int ipfrule_add(void)
2443b9b51feSCy Schubert {
2453b9b51feSCy Schubert 	int err;
2463b9b51feSCy Schubert 
2473b9b51feSCy Schubert 	err = ipfrule_add_out_();
2483b9b51feSCy Schubert 	if (err != 0)
2498c82b374SCy Schubert 		return (err);
2503b9b51feSCy Schubert 	err = ipfrule_add_in_();
2513b9b51feSCy Schubert 	if (err != 0)
2528c82b374SCy Schubert 		return (err);
2538c82b374SCy Schubert 	return (0);
2543b9b51feSCy Schubert }
2553b9b51feSCy Schubert 
2563b9b51feSCy Schubert 
ipfrule_remove(void)257064a5a95SCy Schubert int ipfrule_remove(void)
2583b9b51feSCy Schubert {
2593b9b51feSCy Schubert 	int err;
2603b9b51feSCy Schubert 
2613b9b51feSCy Schubert 	err = ipfrule_remove_out_();
2623b9b51feSCy Schubert 	if (err != 0)
2638c82b374SCy Schubert 		return (err);
2643b9b51feSCy Schubert 	err = ipfrule_remove_in_();
2653b9b51feSCy Schubert 	if (err != 0)
2668c82b374SCy Schubert 		return (err);
2678c82b374SCy Schubert 	return (0);
2683b9b51feSCy Schubert }
2693b9b51feSCy Schubert #endif /* IPFILTER_COMPILED */
270