1 /*	$FreeBSD: stable/9/sys/contrib/ipfilter/netinet/ip_rules.c 145517 2005-04-25 18:15:41Z darrenr $	*/
2 
3 /*
4 * Copyright (C) 1993-2000 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/types.h>
12 #include <sys/time.h>
13 #include <sys/socket.h>
14 #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__sgi)
15 # include <sys/systm.h>
16 #endif
17 #include <sys/errno.h>
18 #include <sys/param.h>
19 #if !defined(__SVR4) && !defined(__svr4__) && !defined(__hpux)
20 # include <sys/mbuf.h>
21 #endif
22 #if defined(__FreeBSD__) && (__FreeBSD_version > 220000)
23 # include <sys/sockio.h>
24 #else
25 # include <sys/ioctl.h>
26 #endif /* FreeBSD */
27 #include <net/if.h>
28 #include <netinet/in.h>
29 #include <netinet/in_systm.h>
30 #include <netinet/ip.h>
31 #include <netinet/tcp.h>
32 #include "netinet/ip_compat.h"
33 #include "netinet/ip_fil.h"
34 
35 #include "netinet/ip_rules.h"
36 
37 #ifndef _KERNEL
38 # include <string.h>
39 #endif /* _KERNEL */
40 
41 #ifdef IPFILTER_COMPILED
42 
43 static u_long in_rule__0[] = {
44 0, 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
45 };
46 
47 static u_long out_rule__0[] = {
48 0, 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
49 };
50 
51 frentry_t *ipf_rules_in_[1] = {
52 	(frentry_t *)&in_rule__0
53 };
54 
ipfrule_match_in_(fin,passp)55 frentry_t *ipfrule_match_in_(fin, passp)
56 fr_info_t *fin;
57 u_32_t *passp;
58 {
59 	frentry_t *fr = NULL;
60 
61 	fr = (frentry_t *)&in_rule__0;
62 	return fr;
63 }
64 
65 frentry_t *ipf_rules_out_[1] = {
66 	(frentry_t *)&out_rule__0
67 };
68 
ipfrule_match_out_(fin,passp)69 frentry_t *ipfrule_match_out_(fin, passp)
70 fr_info_t *fin;
71 u_32_t *passp;
72 {
73 	frentry_t *fr = NULL;
74 
75 	fr = (frentry_t *)&out_rule__0;
76 	return fr;
77 }
78 static frentry_t ipfrule_out_;
79 
ipfrule_add_out_()80 int ipfrule_add_out_()
81 {
82 	int i, j, err = 0, max;
83 	frentry_t *fp;
84 
85 	max = sizeof(ipf_rules_out_)/sizeof(frentry_t *);
86 	for (i = 0; i < max; i++) {
87 		fp = ipf_rules_out_[i];
88 		fp->fr_next = NULL;
89 		for (j = i + 1; j < max; j++)
90 			if (strncmp(fp->fr_group,
91 				    ipf_rules_out_[j]->fr_group,
92 				    FR_GROUPLEN) == 0) {
93 				fp->fr_next = ipf_rules_out_[j];
94 				break;
95 			}
96 	}
97 
98 	fp = &ipfrule_out_;
99 	bzero((char *)fp, sizeof(*fp));
100 	fp->fr_type = FR_T_CALLFUNC|FR_T_BUILTIN;
101 	fp->fr_flags = FR_OUTQUE|FR_NOMATCH;
102 	fp->fr_data = (void *)ipf_rules_out_[0];
103 	fp->fr_dsize = sizeof(ipf_rules_out_[0]);
104 	fp->fr_v = 4;
105 	fp->fr_func = (ipfunc_t)ipfrule_match_out_;
106 	err = frrequest(IPL_LOGIPF, SIOCADDFR, (caddr_t)fp, fr_active, 0);
107 	return err;
108 }
109 
110 
ipfrule_remove_out_()111 int ipfrule_remove_out_()
112 {
113 	int err = 0, i;
114 	frentry_t *fp;
115 
116 	/*
117 	 * Try to remove the outbound rule.
118 	 */
119 	if (ipfrule_out_.fr_ref > 0) {
120 		err = EBUSY;
121 	} else {
122 		i = sizeof(ipf_rules_out_)/sizeof(frentry_t *) - 1;
123 		for (; i >= 0; i--) {
124 			fp = ipf_rules_out_[i];
125 			if (fp->fr_ref > 1) {
126 				err = EBUSY;
127 				break;
128 			}
129 		}
130 	}
131 	if (err == 0)
132 		err = frrequest(IPL_LOGIPF, SIOCDELFR,
133 				(caddr_t)&ipfrule_out_, fr_active, 0);
134 	if (err)
135 		return err;
136 
137 
138 	return err;
139 }
140 static frentry_t ipfrule_in_;
141 
ipfrule_add_in_()142 int ipfrule_add_in_()
143 {
144 	int i, j, err = 0, max;
145 	frentry_t *fp;
146 
147 	max = sizeof(ipf_rules_in_)/sizeof(frentry_t *);
148 	for (i = 0; i < max; i++) {
149 		fp = ipf_rules_in_[i];
150 		fp->fr_next = NULL;
151 		for (j = i + 1; j < max; j++)
152 			if (strncmp(fp->fr_group,
153 				    ipf_rules_in_[j]->fr_group,
154 				    FR_GROUPLEN) == 0) {
155 				fp->fr_next = ipf_rules_in_[j];
156 				break;
157 			}
158 	}
159 
160 	fp = &ipfrule_in_;
161 	bzero((char *)fp, sizeof(*fp));
162 	fp->fr_type = FR_T_CALLFUNC|FR_T_BUILTIN;
163 	fp->fr_flags = FR_INQUE|FR_NOMATCH;
164 	fp->fr_data = (void *)ipf_rules_in_[0];
165 	fp->fr_dsize = sizeof(ipf_rules_in_[0]);
166 	fp->fr_v = 4;
167 	fp->fr_func = (ipfunc_t)ipfrule_match_in_;
168 	err = frrequest(IPL_LOGIPF, SIOCADDFR, (caddr_t)fp, fr_active, 0);
169 	return err;
170 }
171 
172 
ipfrule_remove_in_()173 int ipfrule_remove_in_()
174 {
175 	int err = 0, i;
176 	frentry_t *fp;
177 
178 	/*
179 	 * Try to remove the inbound rule.
180 	 */
181 	if (ipfrule_in_.fr_ref > 0) {
182 		err = EBUSY;
183 	} else {
184 		i = sizeof(ipf_rules_in_)/sizeof(frentry_t *) - 1;
185 		for (; i >= 0; i--) {
186 			fp = ipf_rules_in_[i];
187 			if (fp->fr_ref > 1) {
188 				err = EBUSY;
189 				break;
190 			}
191 		}
192 	}
193 	if (err == 0)
194 		err = frrequest(IPL_LOGIPF, SIOCDELFR,
195 				(caddr_t)&ipfrule_in_, fr_active, 0);
196 	if (err)
197 		return err;
198 
199 
200 	return err;
201 }
202 
ipfrule_add()203 int ipfrule_add()
204 {
205 	int err;
206 
207 	err = ipfrule_add_out_();
208 	if (err != 0)
209 		return err;
210 	err = ipfrule_add_in_();
211 	if (err != 0)
212 		return err;
213 	return 0;
214 }
215 
216 
ipfrule_remove()217 int ipfrule_remove()
218 {
219 	int err;
220 
221 	err = ipfrule_remove_out_();
222 	if (err != 0)
223 		return err;
224 	err = ipfrule_remove_in_();
225 	if (err != 0)
226 		return err;
227 	return 0;
228 }
229 #endif /* IPFILTER_COMPILED */
230