~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/ipv4/netfilter/ip_fw_compat.c

Version: ~ [ linux-5.8 ] ~ [ linux-5.7.14 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.57 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.138 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.193 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.232 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.232 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* Compatibility framework for ipchains and ipfwadm support; designed
  2    to look as much like the 2.2 infrastructure as possible. */
  3 struct notifier_block;
  4 
  5 #include <linux/netfilter_ipv4.h>
  6 #include <linux/ip.h>
  7 #include <net/icmp.h>
  8 #include <linux/if.h>
  9 #include <linux/inetdevice.h>
 10 #include <linux/netdevice.h>
 11 #include <linux/module.h>
 12 #include <asm/uaccess.h>
 13 #include <net/ip.h>
 14 #include <net/route.h>
 15 #include <linux/netfilter_ipv4/compat_firewall.h>
 16 #include <linux/netfilter_ipv4/ip_conntrack.h>
 17 #include <linux/netfilter_ipv4/ip_conntrack_core.h>
 18 #include "ip_fw_compat.h"
 19 
 20 static struct firewall_ops *fwops;
 21 
 22 #ifdef CONFIG_IP_VS
 23 /* From ip_vs_core.c */
 24 extern unsigned int
 25 check_for_ip_vs_out(struct sk_buff **skb_p, int (*okfn)(struct sk_buff *));
 26 #endif
 27 
 28 /* They call these; we do what they want. */
 29 int register_firewall(int pf, struct firewall_ops *fw)
 30 {
 31         if (pf != PF_INET) {
 32                 printk("Attempt to register non-IP firewall module.\n");
 33                 return -EINVAL;
 34         }
 35         if (fwops) {
 36                 printk("Attempt to register multiple firewall modules.\n");
 37                 return -EBUSY;
 38         }
 39 
 40         fwops = fw;
 41         return 0;
 42 }
 43 
 44 int unregister_firewall(int pf, struct firewall_ops *fw)
 45 {
 46         fwops = NULL;
 47         return 0;
 48 }
 49 
 50 static unsigned int
 51 fw_in(unsigned int hooknum,
 52       struct sk_buff **pskb,
 53       const struct net_device *in,
 54       const struct net_device *out,
 55       int (*okfn)(struct sk_buff *))
 56 {
 57         int ret = FW_BLOCK;
 58         u_int16_t redirpt;
 59 
 60         /* Assume worse case: any hook could change packet */
 61         (*pskb)->nfcache |= NFC_UNKNOWN | NFC_ALTERED;
 62         if ((*pskb)->ip_summed == CHECKSUM_HW)
 63                 (*pskb)->ip_summed = CHECKSUM_NONE;
 64 
 65         switch (hooknum) {
 66         case NF_IP_PRE_ROUTING:
 67                 if (fwops->fw_acct_in)
 68                         fwops->fw_acct_in(fwops, PF_INET,
 69                                           (struct net_device *)in,
 70                                           &redirpt, pskb);
 71 
 72                 if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
 73                         *pskb = ip_ct_gather_frags(*pskb);
 74 
 75                         if (!*pskb)
 76                                 return NF_STOLEN;
 77                 }
 78 
 79                 ret = fwops->fw_input(fwops, PF_INET, (struct net_device *)in,
 80                                       &redirpt, pskb);
 81                 break;
 82 
 83         case NF_IP_FORWARD:
 84                 /* Connection will only be set if it was
 85                    demasqueraded: if so, skip forward chain. */
 86                 if ((*pskb)->nfct)
 87                         ret = FW_ACCEPT;
 88                 else ret = fwops->fw_forward(fwops, PF_INET,
 89                                              (struct net_device *)out,
 90                                              &redirpt, pskb);
 91                 break;
 92 
 93         case NF_IP_POST_ROUTING:
 94                 ret = fwops->fw_output(fwops, PF_INET,
 95                                        (struct net_device *)out,
 96                                        &redirpt, pskb);
 97                 if (ret == FW_ACCEPT || ret == FW_SKIP) {
 98                         if (fwops->fw_acct_out)
 99                                 fwops->fw_acct_out(fwops, PF_INET,
100                                                    (struct net_device *)out,
101                                                    &redirpt,
102                                                    pskb);
103 
104                         /* ip_conntrack_confirm return NF_DROP or NF_ACCEPT */
105                         if (ip_conntrack_confirm(*pskb) == NF_DROP)
106                                 ret = FW_BLOCK;
107                 }
108                 break;
109         }
110 
111         switch (ret) {
112         case FW_REJECT: {
113                 /* Alexey says:
114                  *
115                  * Generally, routing is THE FIRST thing to make, when
116                  * packet enters IP stack. Before packet is routed you
117                  * cannot call any service routines from IP stack.  */
118                 struct iphdr *iph = (*pskb)->nh.iph;
119 
120                 if ((*pskb)->dst != NULL
121                     || ip_route_input(*pskb, iph->daddr, iph->saddr, iph->tos,
122                                       (struct net_device *)in) == 0)
123                         icmp_send(*pskb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH,
124                                   0);
125                 return NF_DROP;
126         }
127 
128         case FW_ACCEPT:
129         case FW_SKIP:
130                 if (hooknum == NF_IP_PRE_ROUTING) {
131                         check_for_demasq(pskb);
132                         check_for_redirect(*pskb);
133                 } else if (hooknum == NF_IP_POST_ROUTING) {
134                         check_for_unredirect(*pskb);
135                         /* Handle ICMP errors from client here */
136                         if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP
137                             && (*pskb)->nfct)
138                                 check_for_masq_error(pskb);
139                 }
140                 return NF_ACCEPT;
141 
142         case FW_MASQUERADE:
143                 if (hooknum == NF_IP_FORWARD) {
144 #ifdef CONFIG_IP_VS
145                         /* check if it is for ip_vs */
146                         if (check_for_ip_vs_out(pskb, okfn) == NF_STOLEN)
147                                 return NF_STOLEN;
148 #endif
149                         return do_masquerade(pskb, out);
150                 }
151                 else return NF_ACCEPT;
152 
153         case FW_REDIRECT:
154                 if (hooknum == NF_IP_PRE_ROUTING)
155                         return do_redirect(*pskb, in, redirpt);
156                 else return NF_ACCEPT;
157 
158         default:
159                 /* FW_BLOCK */
160                 return NF_DROP;
161         }
162 }
163 
164 static unsigned int fw_confirm(unsigned int hooknum,
165                                struct sk_buff **pskb,
166                                const struct net_device *in,
167                                const struct net_device *out,
168                                int (*okfn)(struct sk_buff *))
169 {
170         return ip_conntrack_confirm(*pskb);
171 }
172 
173 extern int ip_fw_ctl(int optval, void *m, unsigned int len);
174 
175 static int sock_fn(struct sock *sk, int optval, void *user, unsigned int len)
176 {
177         /* MAX of:
178            2.2: sizeof(struct ip_fwtest) (~14x4 + 3x4 = 17x4)
179            2.2: sizeof(struct ip_fwnew) (~1x4 + 15x4 + 3x4 + 3x4 = 22x4)
180            2.0: sizeof(struct ip_fw) (~25x4)
181 
182            We can't include both 2.0 and 2.2 headers, they conflict.
183            Hence, 200 is a good number. --RR */
184         char tmp_fw[200];
185         if (!capable(CAP_NET_ADMIN))
186                 return -EPERM;
187 
188         if (len > sizeof(tmp_fw) || len < 1)
189                 return -EINVAL;
190 
191         if (copy_from_user(&tmp_fw, user, len))
192                 return -EFAULT;
193 
194         return -ip_fw_ctl(optval, &tmp_fw, len);
195 }
196 
197 static struct nf_hook_ops preroute_ops = {
198         .hook           = fw_in,
199         .owner          = THIS_MODULE,
200         .pf             = PF_INET,
201         .hooknum        = NF_IP_PRE_ROUTING,
202         .priority       = NF_IP_PRI_FILTER,
203 };
204 
205 static struct nf_hook_ops postroute_ops = {
206         .hook           = fw_in,
207         .owner          = THIS_MODULE,
208         .pf             = PF_INET,
209         .hooknum        = NF_IP_POST_ROUTING,
210         .priority       = NF_IP_PRI_FILTER,
211 };
212 
213 static struct nf_hook_ops forward_ops = {
214         .hook           = fw_in,
215         .owner          = THIS_MODULE,
216         .pf             = PF_INET,
217         .hooknum        = NF_IP_FORWARD,
218         .priority       = NF_IP_PRI_FILTER,
219 };
220 
221 static struct nf_hook_ops local_in_ops = {
222         .hook           = fw_confirm,
223         .owner          = THIS_MODULE,
224         .pf             = PF_INET,
225         .hooknum        = NF_IP_LOCAL_IN,
226         .priority       = NF_IP_PRI_LAST - 1,
227 };
228 
229 static struct nf_sockopt_ops sock_ops = {
230         .pf             = PF_INET,
231         .set_optmin     = 64,
232         .set_optmax     = 64 + 1024 + 1,
233         .set            = &sock_fn,
234 };
235 
236 extern int ipfw_init_or_cleanup(int init);
237 
238 static int init_or_cleanup(int init)
239 {
240         int ret = 0;
241 
242         if (!init) goto cleanup;
243 
244         ret = nf_register_sockopt(&sock_ops);
245 
246         if (ret < 0)
247                 goto cleanup_nothing;
248 
249         ret = ipfw_init_or_cleanup(1);
250         if (ret < 0)
251                 goto cleanup_sockopt;
252 
253         ret = masq_init();
254         if (ret < 0)
255                 goto cleanup_ipfw;
256 
257         nf_register_hook(&preroute_ops);
258         nf_register_hook(&postroute_ops);
259         nf_register_hook(&forward_ops);
260         nf_register_hook(&local_in_ops);
261 
262         return ret;
263 
264  cleanup:
265         nf_unregister_hook(&preroute_ops);
266         nf_unregister_hook(&postroute_ops);
267         nf_unregister_hook(&forward_ops);
268         nf_unregister_hook(&local_in_ops);
269 
270         masq_cleanup();
271 
272  cleanup_ipfw:
273         ipfw_init_or_cleanup(0);
274 
275  cleanup_sockopt:
276         nf_unregister_sockopt(&sock_ops);
277 
278  cleanup_nothing:
279         return ret;
280 }
281 
282 static int __init init(void)
283 {
284         return init_or_cleanup(1);
285 }
286 
287 static void __exit fini(void)
288 {
289         init_or_cleanup(0);
290 }
291 
292 module_init(init);
293 module_exit(fini);
294 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp