1
2/*
3* Copyright (C) 2012 by Darren Reed.
4*
5* Redistribution and use in source and binary forms are permitted
6* provided that this notice is preserved and due credit is given
7* to the original author and the contributors.
8*/
9
10#include <sys/param.h>
11#include <sys/types.h>
12#include <sys/time.h>
13#include <sys/socket.h>
14#if defined(__FreeBSD__)
15# if defined(_KERNEL)
16#  include <sys/libkern.h>
17# else
18#  include <sys/unistd.h>
19# endif
20#else
21# include <sys/systm.h>
22#endif
23#include <sys/errno.h>
24#include <sys/param.h>
25#if !defined(__SVR4)
26# include <sys/mbuf.h>
27#endif
28#if defined(__FreeBSD__)
29# include <sys/sockio.h>
30#if defined(_KERNEL)
31#include <net/vnet.h>
32#else
33#define CURVNET_SET(arg)
34#define CURVNET_RESTORE()
35#define	VNET_DEFINE(_t, _v)	_t _v
36#define	VNET_DECLARE(_t, _v)	extern _t _v
37#define	VNET(arg)	arg
38#endif
39#else
40# include <sys/ioctl.h>
41#endif /* FreeBSD */
42#include <net/if.h>
43#include <netinet/in.h>
44#include <netinet/in_systm.h>
45#include <netinet/ip.h>
46#include <netinet/tcp.h>
47#include "netinet/ip_compat.h"
48#include "netinet/ip_fil.h"
49
50#include "netinet/ip_rules.h"
51
52#ifndef _KERNEL
53# include <string.h>
54#endif /* _KERNEL */
55
56#ifdef IPFILTER_COMPILED
57
58VNET_DECLARE(ipf_main_softc_t, ipfmain);
59#define	V_ipfmain		VNET(ipfmain)
60
61
62static u_long in_rule__0[] = {
630, 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
64};
65
66static u_long out_rule__0[] = {
670, 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
68};
69
70frentry_t *ipf_rules_in_[1] = {
71	(frentry_t *)&in_rule__0
72};
73
74/* XXX	This file (ip_rules.c) is not part of the ipfilter tarball, it is
75   XXX	generated by the ipfilter build process. Unfortunately the build
76   XXX  process did not generate the following lines so they are added
77   XXX	by hand here. This is a bit of a hack but it works for now. Future
78   XXX  imports/merges of ipfilter may generate this so the following will
79   XXX	need to be removed following some future merge.
80   XXX	*/
81frentry_t *ipf_rules_out_[1] = {
82	(frentry_t *)&out_rule__0
83};
84
85frentry_t *ipfrule_match_in_(fin, passp)
86fr_info_t *fin;
87u_32_t *passp;
88{
89	frentry_t *fr = NULL;
90
91	fr = (frentry_t *)&in_rule__0;
92	return (fr);
93}
94
95frentry_t *ipfrule_match_out_(fin, passp)
96fr_info_t *fin;
97u_32_t *passp;
98{
99	frentry_t *fr = NULL;
100
101	fr = (frentry_t *)&out_rule__0;
102	return (fr);
103}
104static frentry_t ipfrule_out_;
105
106int ipfrule_add_out_(void)
107{
108	int i, j, err = 0, max;
109	frentry_t *fp;
110
111	max = sizeof(ipf_rules_out_)/sizeof(frentry_t *);
112	for (i = 0; i < max; i++) {
113		fp = ipf_rules_out_[i];
114		fp->fr_next = NULL;
115		for (j = i + 1; j < max; j++)
116			if (strncmp(fp->fr_names + fp->fr_group,
117				    ipf_rules_out_[j]->fr_names +
118				    ipf_rules_out_[j]->fr_group,
119				    FR_GROUPLEN) == 0) {
120				if (ipf_rules_out_[j] != NULL)
121					ipf_rules_out_[j]->fr_pnext =
122					    &fp->fr_next;
123				fp->fr_pnext = &ipf_rules_out_[j];
124				fp->fr_next = ipf_rules_out_[j];
125				break;
126			}
127	}
128
129	fp = &ipfrule_out_;
130	bzero((char *)fp, sizeof(*fp));
131	fp->fr_type = FR_T_CALLFUNC_BUILTIN;
132	fp->fr_flags = FR_OUTQUE|FR_NOMATCH;
133	fp->fr_data = (void *)ipf_rules_out_[0];
134	fp->fr_dsize = sizeof(ipf_rules_out_[0]);
135	fp->fr_family = AF_INET;
136	fp->fr_func = (ipfunc_t)ipfrule_match_out_;
137	err = frrequest(&V_ipfmain, IPL_LOGIPF, SIOCADDFR, (caddr_t)fp,
138			V_ipfmain.ipf_active, 0);
139	return (err);
140}
141
142
143int ipfrule_remove_out_(void)
144{
145	int err = 0, i;
146	frentry_t *fp;
147
148	/*
149	 * Try to remove the outbound rule.
150	 */
151	if (ipfrule_out_.fr_ref > 0) {
152		err = EBUSY;
153	} else {
154		i = sizeof(ipf_rules_out_)/sizeof(frentry_t *) - 1;
155		for (; i >= 0; i--) {
156			fp = ipf_rules_out_[i];
157			if (fp->fr_ref > 1) {
158				err = EBUSY;
159				break;
160			}
161		}
162	}
163	if (err == 0)
164		err = frrequest(&V_ipfmain, IPL_LOGIPF, SIOCDELFR,
165				(caddr_t)&ipfrule_out_,
166				V_ipfmain.ipf_active, 0);
167	if (err)
168		return (err);
169
170
171	return (err);
172}
173static frentry_t ipfrule_in_;
174
175int ipfrule_add_in_(void)
176{
177	int i, j, err = 0, max;
178	frentry_t *fp;
179
180	max = sizeof(ipf_rules_in_)/sizeof(frentry_t *);
181	for (i = 0; i < max; i++) {
182		fp = ipf_rules_in_[i];
183		fp->fr_next = NULL;
184		for (j = i + 1; j < max; j++)
185			if (strncmp(fp->fr_names + fp->fr_group,
186				    ipf_rules_in_[j]->fr_names +
187				    ipf_rules_in_[j]->fr_group,
188				    FR_GROUPLEN) == 0) {
189				if (ipf_rules_in_[j] != NULL)
190					ipf_rules_in_[j]->fr_pnext =
191					    &fp->fr_next;
192				fp->fr_pnext = &ipf_rules_in_[j];
193				fp->fr_next = ipf_rules_in_[j];
194				break;
195			}
196	}
197
198	fp = &ipfrule_in_;
199	bzero((char *)fp, sizeof(*fp));
200	fp->fr_type = FR_T_CALLFUNC_BUILTIN;
201	fp->fr_flags = FR_INQUE|FR_NOMATCH;
202	fp->fr_data = (void *)ipf_rules_in_[0];
203	fp->fr_dsize = sizeof(ipf_rules_in_[0]);
204	fp->fr_family = AF_INET;
205	fp->fr_func = (ipfunc_t)ipfrule_match_in_;
206	err = frrequest(&V_ipfmain, IPL_LOGIPF, SIOCADDFR, (caddr_t)fp,
207			V_ipfmain.ipf_active, 0);
208	return (err);
209}
210
211
212int ipfrule_remove_in_(void)
213{
214	int err = 0, i;
215	frentry_t *fp;
216
217	/*
218	 * Try to remove the inbound rule.
219	 */
220	if (ipfrule_in_.fr_ref > 0) {
221		err = EBUSY;
222	} else {
223		i = sizeof(ipf_rules_in_)/sizeof(frentry_t *) - 1;
224		for (; i >= 0; i--) {
225			fp = ipf_rules_in_[i];
226			if (fp->fr_ref > 1) {
227				err = EBUSY;
228				break;
229			}
230		}
231	}
232	if (err == 0)
233		err = frrequest(&V_ipfmain, IPL_LOGIPF, SIOCDELFR,
234				(caddr_t)&ipfrule_in_,
235				V_ipfmain.ipf_active, 0);
236	if (err)
237		return (err);
238
239
240	return (err);
241}
242
243int ipfrule_add(void)
244{
245	int err;
246
247	err = ipfrule_add_out_();
248	if (err != 0)
249		return (err);
250	err = ipfrule_add_in_();
251	if (err != 0)
252		return (err);
253	return (0);
254}
255
256
257int ipfrule_remove(void)
258{
259	int err;
260
261	err = ipfrule_remove_out_();
262	if (err != 0)
263		return (err);
264	err = ipfrule_remove_in_();
265	if (err != 0)
266		return (err);
267	return (0);
268}
269#endif /* IPFILTER_COMPILED */
270