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
58 VNET_DECLARE(ipf_main_softc_t, ipfmain);
59 #define V_ipfmain VNET(ipfmain)
60
61
62 static u_long in_rule__0[] = {
63 0, 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
66 static u_long out_rule__0[] = {
67 0, 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
70 frentry_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 */
81 frentry_t *ipf_rules_out_[1] = {
82 (frentry_t *)&out_rule__0
83 };
84
ipfrule_match_in_(fin,passp)85 frentry_t *ipfrule_match_in_(fin, passp)
86 fr_info_t *fin;
87 u_32_t *passp;
88 {
89 frentry_t *fr = NULL;
90
91 fr = (frentry_t *)&in_rule__0;
92 return (fr);
93 }
94
ipfrule_match_out_(fin,passp)95 frentry_t *ipfrule_match_out_(fin, passp)
96 fr_info_t *fin;
97 u_32_t *passp;
98 {
99 frentry_t *fr = NULL;
100
101 fr = (frentry_t *)&out_rule__0;
102 return (fr);
103 }
104 static frentry_t ipfrule_out_;
105
ipfrule_add_out_(void)106 int 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
ipfrule_remove_out_(void)143 int 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 }
173 static frentry_t ipfrule_in_;
174
ipfrule_add_in_(void)175 int 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
ipfrule_remove_in_(void)212 int 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
ipfrule_add(void)243 int 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
ipfrule_remove(void)257 int 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