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