1145516Sdarrenr/*	$FreeBSD$	*/
2145516Sdarrenr
3145516Sdarrenr/*
4145516Sdarrenr* Copyright (C) 1993-2000 by Darren Reed.
5145516Sdarrenr*
6145516Sdarrenr* Redistribution and use in source and binary forms are permitted
7145516Sdarrenr* provided that this notice is preserved and due credit is given
8145516Sdarrenr* to the original author and the contributors.
9145516Sdarrenr*/
10145516Sdarrenr
11145516Sdarrenr#include <sys/types.h>
12145516Sdarrenr#include <sys/time.h>
13145516Sdarrenr#include <sys/socket.h>
14145516Sdarrenr#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__sgi)
15145516Sdarrenr# include <sys/systm.h>
16145516Sdarrenr#endif
17145516Sdarrenr#include <sys/errno.h>
18145516Sdarrenr#include <sys/param.h>
19145516Sdarrenr#if !defined(__SVR4) && !defined(__svr4__) && !defined(__hpux)
20145516Sdarrenr# include <sys/mbuf.h>
21145516Sdarrenr#endif
22145516Sdarrenr#if defined(__FreeBSD__) && (__FreeBSD_version > 220000)
23145516Sdarrenr# include <sys/sockio.h>
24145516Sdarrenr#else
25145516Sdarrenr# include <sys/ioctl.h>
26145516Sdarrenr#endif /* FreeBSD */
27145516Sdarrenr#include <net/if.h>
28145516Sdarrenr#include <netinet/in.h>
29145516Sdarrenr#include <netinet/in_systm.h>
30145516Sdarrenr#include <netinet/ip.h>
31145516Sdarrenr#include <netinet/tcp.h>
32145516Sdarrenr#include "netinet/ip_compat.h"
33145516Sdarrenr#include "netinet/ip_fil.h"
34145516Sdarrenr
35145516Sdarrenr#include "netinet/ip_rules.h"
36145516Sdarrenr
37145516Sdarrenr#ifndef _KERNEL
38145516Sdarrenr# include <string.h>
39145516Sdarrenr#endif /* _KERNEL */
40145516Sdarrenr
41145516Sdarrenr#ifdef IPFILTER_COMPILED
42145516Sdarrenr
43145516Sdarrenrstatic u_long in_rule__0[] = {
44145516Sdarrenr0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xffffffff, 0, 0, 0, 0, 0, 0, 0x1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80000000, 0x8002, 0, 0, 0, 0xffff, 0, 0, 0x4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
45145516Sdarrenr};
46145516Sdarrenr
47145516Sdarrenrstatic u_long out_rule__0[] = {
48145516Sdarrenr0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xffffffff, 0, 0, 0, 0, 0, 0, 0x1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80000000, 0x4002, 0, 0, 0, 0xffff, 0, 0, 0x4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
49145516Sdarrenr};
50145516Sdarrenr
51145516Sdarrenrfrentry_t *ipf_rules_in_[1] = {
52145516Sdarrenr	(frentry_t *)&in_rule__0
53145516Sdarrenr};
54145516Sdarrenr
55145516Sdarrenrfrentry_t *ipfrule_match_in_(fin, passp)
56145516Sdarrenrfr_info_t *fin;
57145516Sdarrenru_32_t *passp;
58145516Sdarrenr{
59145516Sdarrenr	frentry_t *fr = NULL;
60145516Sdarrenr
61145516Sdarrenr	fr = (frentry_t *)&in_rule__0;
62145516Sdarrenr	return fr;
63145516Sdarrenr}
64145516Sdarrenr
65145516Sdarrenrfrentry_t *ipf_rules_out_[1] = {
66145516Sdarrenr	(frentry_t *)&out_rule__0
67145516Sdarrenr};
68145516Sdarrenr
69145516Sdarrenrfrentry_t *ipfrule_match_out_(fin, passp)
70145516Sdarrenrfr_info_t *fin;
71145516Sdarrenru_32_t *passp;
72145516Sdarrenr{
73145516Sdarrenr	frentry_t *fr = NULL;
74145516Sdarrenr
75145516Sdarrenr	fr = (frentry_t *)&out_rule__0;
76145516Sdarrenr	return fr;
77145516Sdarrenr}
78145516Sdarrenrstatic frentry_t ipfrule_out_;
79145516Sdarrenr
80145516Sdarrenrint ipfrule_add_out_()
81145516Sdarrenr{
82145516Sdarrenr	int i, j, err = 0, max;
83145516Sdarrenr	frentry_t *fp;
84145516Sdarrenr
85145516Sdarrenr	max = sizeof(ipf_rules_out_)/sizeof(frentry_t *);
86145516Sdarrenr	for (i = 0; i < max; i++) {
87145516Sdarrenr		fp = ipf_rules_out_[i];
88145516Sdarrenr		fp->fr_next = NULL;
89145516Sdarrenr		for (j = i + 1; j < max; j++)
90145516Sdarrenr			if (strncmp(fp->fr_group,
91145516Sdarrenr				    ipf_rules_out_[j]->fr_group,
92145516Sdarrenr				    FR_GROUPLEN) == 0) {
93145516Sdarrenr				fp->fr_next = ipf_rules_out_[j];
94145516Sdarrenr				break;
95145516Sdarrenr			}
96145516Sdarrenr	}
97145516Sdarrenr
98145516Sdarrenr	fp = &ipfrule_out_;
99145516Sdarrenr	bzero((char *)fp, sizeof(*fp));
100145516Sdarrenr	fp->fr_type = FR_T_CALLFUNC|FR_T_BUILTIN;
101145516Sdarrenr	fp->fr_flags = FR_OUTQUE|FR_NOMATCH;
102145516Sdarrenr	fp->fr_data = (void *)ipf_rules_out_[0];
103145516Sdarrenr	fp->fr_dsize = sizeof(ipf_rules_out_[0]);
104145516Sdarrenr	fp->fr_v = 4;
105145516Sdarrenr	fp->fr_func = (ipfunc_t)ipfrule_match_out_;
106145516Sdarrenr	err = frrequest(IPL_LOGIPF, SIOCADDFR, (caddr_t)fp, fr_active, 0);
107145516Sdarrenr	return err;
108145516Sdarrenr}
109145516Sdarrenr
110145516Sdarrenr
111145516Sdarrenrint ipfrule_remove_out_()
112145516Sdarrenr{
113145516Sdarrenr	int err = 0, i;
114145516Sdarrenr	frentry_t *fp;
115145516Sdarrenr
116145516Sdarrenr	/*
117145516Sdarrenr	 * Try to remove the outbound rule.
118145516Sdarrenr	 */
119145516Sdarrenr	if (ipfrule_out_.fr_ref > 0) {
120145516Sdarrenr		err = EBUSY;
121145516Sdarrenr	} else {
122145516Sdarrenr		i = sizeof(ipf_rules_out_)/sizeof(frentry_t *) - 1;
123145516Sdarrenr		for (; i >= 0; i--) {
124145516Sdarrenr			fp = ipf_rules_out_[i];
125145516Sdarrenr			if (fp->fr_ref > 1) {
126145516Sdarrenr				err = EBUSY;
127145516Sdarrenr				break;
128145516Sdarrenr			}
129145516Sdarrenr		}
130145516Sdarrenr	}
131145516Sdarrenr	if (err == 0)
132145516Sdarrenr		err = frrequest(IPL_LOGIPF, SIOCDELFR,
133145516Sdarrenr				(caddr_t)&ipfrule_out_, fr_active, 0);
134145516Sdarrenr	if (err)
135145516Sdarrenr		return err;
136145516Sdarrenr
137145516Sdarrenr
138145516Sdarrenr	return err;
139145516Sdarrenr}
140145516Sdarrenrstatic frentry_t ipfrule_in_;
141145516Sdarrenr
142145516Sdarrenrint ipfrule_add_in_()
143145516Sdarrenr{
144145516Sdarrenr	int i, j, err = 0, max;
145145516Sdarrenr	frentry_t *fp;
146145516Sdarrenr
147145516Sdarrenr	max = sizeof(ipf_rules_in_)/sizeof(frentry_t *);
148145516Sdarrenr	for (i = 0; i < max; i++) {
149145516Sdarrenr		fp = ipf_rules_in_[i];
150145516Sdarrenr		fp->fr_next = NULL;
151145516Sdarrenr		for (j = i + 1; j < max; j++)
152145516Sdarrenr			if (strncmp(fp->fr_group,
153145516Sdarrenr				    ipf_rules_in_[j]->fr_group,
154145516Sdarrenr				    FR_GROUPLEN) == 0) {
155145516Sdarrenr				fp->fr_next = ipf_rules_in_[j];
156145516Sdarrenr				break;
157145516Sdarrenr			}
158145516Sdarrenr	}
159145516Sdarrenr
160145516Sdarrenr	fp = &ipfrule_in_;
161145516Sdarrenr	bzero((char *)fp, sizeof(*fp));
162145516Sdarrenr	fp->fr_type = FR_T_CALLFUNC|FR_T_BUILTIN;
163145516Sdarrenr	fp->fr_flags = FR_INQUE|FR_NOMATCH;
164145516Sdarrenr	fp->fr_data = (void *)ipf_rules_in_[0];
165145516Sdarrenr	fp->fr_dsize = sizeof(ipf_rules_in_[0]);
166145516Sdarrenr	fp->fr_v = 4;
167145516Sdarrenr	fp->fr_func = (ipfunc_t)ipfrule_match_in_;
168145516Sdarrenr	err = frrequest(IPL_LOGIPF, SIOCADDFR, (caddr_t)fp, fr_active, 0);
169145516Sdarrenr	return err;
170145516Sdarrenr}
171145516Sdarrenr
172145516Sdarrenr
173145516Sdarrenrint ipfrule_remove_in_()
174145516Sdarrenr{
175145516Sdarrenr	int err = 0, i;
176145516Sdarrenr	frentry_t *fp;
177145516Sdarrenr
178145516Sdarrenr	/*
179145516Sdarrenr	 * Try to remove the inbound rule.
180145516Sdarrenr	 */
181145516Sdarrenr	if (ipfrule_in_.fr_ref > 0) {
182145516Sdarrenr		err = EBUSY;
183145516Sdarrenr	} else {
184145516Sdarrenr		i = sizeof(ipf_rules_in_)/sizeof(frentry_t *) - 1;
185145516Sdarrenr		for (; i >= 0; i--) {
186145516Sdarrenr			fp = ipf_rules_in_[i];
187145516Sdarrenr			if (fp->fr_ref > 1) {
188145516Sdarrenr				err = EBUSY;
189145516Sdarrenr				break;
190145516Sdarrenr			}
191145516Sdarrenr		}
192145516Sdarrenr	}
193145516Sdarrenr	if (err == 0)
194145516Sdarrenr		err = frrequest(IPL_LOGIPF, SIOCDELFR,
195145516Sdarrenr				(caddr_t)&ipfrule_in_, fr_active, 0);
196145516Sdarrenr	if (err)
197145516Sdarrenr		return err;
198145516Sdarrenr
199145516Sdarrenr
200145516Sdarrenr	return err;
201145516Sdarrenr}
202145516Sdarrenr
203145516Sdarrenrint ipfrule_add()
204145516Sdarrenr{
205145516Sdarrenr	int err;
206145516Sdarrenr
207145516Sdarrenr	err = ipfrule_add_out_();
208145516Sdarrenr	if (err != 0)
209145516Sdarrenr		return err;
210145516Sdarrenr	err = ipfrule_add_in_();
211145516Sdarrenr	if (err != 0)
212145516Sdarrenr		return err;
213145516Sdarrenr	return 0;
214145516Sdarrenr}
215145516Sdarrenr
216145516Sdarrenr
217145516Sdarrenrint ipfrule_remove()
218145516Sdarrenr{
219145516Sdarrenr	int err;
220145516Sdarrenr
221145516Sdarrenr	err = ipfrule_remove_out_();
222145516Sdarrenr	if (err != 0)
223145516Sdarrenr		return err;
224145516Sdarrenr	err = ipfrule_remove_in_();
225145516Sdarrenr	if (err != 0)
226145516Sdarrenr		return err;
227145516Sdarrenr	return 0;
228145516Sdarrenr}
229145516Sdarrenr#endif /* IPFILTER_COMPILED */
230