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