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