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