Main Page | Class List | File List | Class Members | File Members

ip_fw_compat.c

Go to the documentation of this file.
00001 /* Compatibility framework for ipchains and ipfwadm support; designed 00002 to look as much like the 2.2 infrastructure as possible. */ 00003 struct notifier_block; 00004 00005 #include <linux/netfilter_ipv4.h> 00006 #include <linux/ip.h> 00007 #include <net/icmp.h> 00008 #include <linux/if.h> 00009 #include <linux/inetdevice.h> 00010 #include <linux/netdevice.h> 00011 #include <linux/module.h> 00012 #include <asm/uaccess.h> 00013 #include <net/ip.h> 00014 #include <net/route.h> 00015 #include <linux/netfilter_ipv4/compat_firewall.h> 00016 #include <linux/netfilter_ipv4/ip_conntrack.h> 00017 #include <linux/netfilter_ipv4/ip_conntrack_core.h> 00018 00019 /* Theoretically, we could one day use 2.4 helpers, but for now it 00020 just confuses depmod --RR */ 00021 EXPORT_NO_SYMBOLS; 00022 00023 static struct firewall_ops *fwops; 00024 00025 /* From ip_fw_compat_redir.c */ 00026 extern unsigned int 00027 do_redirect(struct sk_buff *skb, 00028 const struct net_device *dev, 00029 u_int16_t redirpt); 00030 00031 extern void 00032 check_for_redirect(struct sk_buff *skb); 00033 00034 extern void 00035 check_for_unredirect(struct sk_buff *skb); 00036 00037 /* From ip_fw_compat_masq.c */ 00038 extern unsigned int 00039 do_masquerade(struct sk_buff **pskb, const struct net_device *dev); 00040 00041 extern unsigned int 00042 check_for_masq_error(struct sk_buff *pskb); 00043 00044 extern unsigned int 00045 check_for_demasq(struct sk_buff **pskb); 00046 00047 extern int __init masq_init(void); 00048 extern void masq_cleanup(void); 00049 00050 #ifdef CONFIG_IP_VS 00051 /* From ip_vs_core.c */ 00052 extern unsigned int 00053 check_for_ip_vs_out(struct sk_buff **skb_p, int (*okfn)(struct sk_buff *)); 00054 #endif 00055 00056 /* They call these; we do what they want. */ 00057 int register_firewall(int pf, struct firewall_ops *fw) 00058 { 00059 if (pf != PF_INET) { 00060 printk("Attempt to register non-IP firewall module.\n"); 00061 return -EINVAL; 00062 } 00063 if (fwops) { 00064 printk("Attempt to register multiple firewall modules.\n"); 00065 return -EBUSY; 00066 } 00067 00068 fwops = fw; 00069 return 0; 00070 } 00071 00072 int unregister_firewall(int pf, struct firewall_ops *fw) 00073 { 00074 fwops = NULL; 00075 return 0; 00076 } 00077 00078 static unsigned int 00079 fw_in(unsigned int hooknum, 00080 struct sk_buff **pskb, 00081 const struct net_device *in, 00082 const struct net_device *out, 00083 int (*okfn)(struct sk_buff *)) 00084 { 00085 int ret = FW_BLOCK; 00086 u_int16_t redirpt; 00087 00088 /* Assume worse case: any hook could change packet */ 00089 (*pskb)->nfcache |= NFC_UNKNOWN | NFC_ALTERED; 00090 if ((*pskb)->ip_summed == CHECKSUM_HW) 00091 (*pskb)->ip_summed = CHECKSUM_NONE; 00092 00093 /* Firewall rules can alter TOS: raw socket (tcpdump) may have 00094 clone of incoming skb: don't disturb it --RR */ 00095 if (skb_cloned(*pskb) && !(*pskb)->sk) { 00096 struct sk_buff *nskb = skb_copy(*pskb, GFP_ATOMIC); 00097 if (!nskb) 00098 return NF_DROP; 00099 kfree_skb(*pskb); 00100 *pskb = nskb; 00101 } 00102 00103 switch (hooknum) { 00104 case NF_IP_PRE_ROUTING: 00105 if (fwops->fw_acct_in) 00106 fwops->fw_acct_in(fwops, PF_INET, 00107 (struct net_device *)in, 00108 (*pskb)->nh.raw, &redirpt, pskb); 00109 00110 if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) { 00111 *pskb = ip_ct_gather_frags(*pskb); 00112 00113 if (!*pskb) 00114 return NF_STOLEN; 00115 } 00116 00117 ret = fwops->fw_input(fwops, PF_INET, (struct net_device *)in, 00118 (*pskb)->nh.raw, &redirpt, pskb); 00119 break; 00120 00121 case NF_IP_FORWARD: 00122 /* Connection will only be set if it was 00123 demasqueraded: if so, skip forward chain. */ 00124 if ((*pskb)->nfct) 00125 ret = FW_ACCEPT; 00126 else ret = fwops->fw_forward(fwops, PF_INET, 00127 (struct net_device *)out, 00128 (*pskb)->nh.raw, &redirpt, pskb); 00129 break; 00130 00131 case NF_IP_POST_ROUTING: 00132 ret = fwops->fw_output(fwops, PF_INET, 00133 (struct net_device *)out, 00134 (*pskb)->nh.raw, &redirpt, pskb); 00135 if (ret == FW_ACCEPT || ret == FW_SKIP) { 00136 if (fwops->fw_acct_out) 00137 fwops->fw_acct_out(fwops, PF_INET, 00138 (struct net_device *)out, 00139 (*pskb)->nh.raw, &redirpt, 00140 pskb); 00141 00142 /* ip_conntrack_confirm return NF_DROP or NF_ACCEPT */ 00143 if (ip_conntrack_confirm(*pskb) == NF_DROP) 00144 ret = FW_BLOCK; 00145 } 00146 break; 00147 } 00148 00149 switch (ret) { 00150 case FW_REJECT: { 00151 /* Alexey says: 00152 * 00153 * Generally, routing is THE FIRST thing to make, when 00154 * packet enters IP stack. Before packet is routed you 00155 * cannot call any service routines from IP stack. */ 00156 struct iphdr *iph = (*pskb)->nh.iph; 00157 00158 if ((*pskb)->dst != NULL 00159 || ip_route_input(*pskb, iph->daddr, iph->saddr, iph->tos, 00160 (struct net_device *)in) == 0) 00161 icmp_send(*pskb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 00162 0); 00163 return NF_DROP; 00164 } 00165 00166 case FW_ACCEPT: 00167 case FW_SKIP: 00168 if (hooknum == NF_IP_PRE_ROUTING) { 00169 check_for_demasq(pskb); 00170 check_for_redirect(*pskb); 00171 } else if (hooknum == NF_IP_POST_ROUTING) { 00172 check_for_unredirect(*pskb); 00173 /* Handle ICMP errors from client here */ 00174 if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP 00175 && (*pskb)->nfct) 00176 check_for_masq_error(*pskb); 00177 } 00178 return NF_ACCEPT; 00179 00180 case FW_MASQUERADE: 00181 if (hooknum == NF_IP_FORWARD) { 00182 #ifdef CONFIG_IP_VS 00183 /* check if it is for ip_vs */ 00184 if (check_for_ip_vs_out(pskb, okfn) == NF_STOLEN) 00185 return NF_STOLEN; 00186 #endif 00187 return do_masquerade(pskb, out); 00188 } 00189 else return NF_ACCEPT; 00190 00191 case FW_REDIRECT: 00192 if (hooknum == NF_IP_PRE_ROUTING) 00193 return do_redirect(*pskb, in, redirpt); 00194 else return NF_ACCEPT; 00195 00196 default: 00197 /* FW_BLOCK */ 00198 return NF_DROP; 00199 } 00200 } 00201 00202 static unsigned int fw_confirm(unsigned int hooknum, 00203 struct sk_buff **pskb, 00204 const struct net_device *in, 00205 const struct net_device *out, 00206 int (*okfn)(struct sk_buff *)) 00207 { 00208 return ip_conntrack_confirm(*pskb); 00209 } 00210 00211 extern int ip_fw_ctl(int optval, void *m, unsigned int len); 00212 00213 static int sock_fn(struct sock *sk, int optval, void *user, unsigned int len) 00214 { 00215 /* MAX of: 00216 2.2: sizeof(struct ip_fwtest) (~14x4 + 3x4 = 17x4) 00217 2.2: sizeof(struct ip_fwnew) (~1x4 + 15x4 + 3x4 + 3x4 = 22x4) 00218 2.0: sizeof(struct ip_fw) (~25x4) 00219 00220 We can't include both 2.0 and 2.2 headers, they conflict. 00221 Hence, 200 is a good number. --RR */ 00222 char tmp_fw[200]; 00223 if (!capable(CAP_NET_ADMIN)) 00224 return -EPERM; 00225 00226 if (len > sizeof(tmp_fw) || len < 1) 00227 return -EINVAL; 00228 00229 if (copy_from_user(&tmp_fw, user, len)) 00230 return -EFAULT; 00231 00232 return -ip_fw_ctl(optval, &tmp_fw, len); 00233 } 00234 00235 static struct nf_hook_ops preroute_ops 00236 = { { NULL, NULL }, fw_in, PF_INET, NF_IP_PRE_ROUTING, NF_IP_PRI_FILTER }; 00237 00238 static struct nf_hook_ops postroute_ops 00239 = { { NULL, NULL }, fw_in, PF_INET, NF_IP_POST_ROUTING, NF_IP_PRI_FILTER }; 00240 00241 static struct nf_hook_ops forward_ops 00242 = { { NULL, NULL }, fw_in, PF_INET, NF_IP_FORWARD, NF_IP_PRI_FILTER }; 00243 00244 static struct nf_hook_ops local_in_ops 00245 = { { NULL, NULL }, fw_confirm, PF_INET, NF_IP_LOCAL_IN, NF_IP_PRI_LAST - 1 }; 00246 00247 static struct nf_sockopt_ops sock_ops 00248 = { { NULL, NULL }, PF_INET, 64, 64 + 1024 + 1, &sock_fn, 0, 0, NULL, 00249 0, NULL }; 00250 00251 extern int ipfw_init_or_cleanup(int init); 00252 00253 static int init_or_cleanup(int init) 00254 { 00255 int ret = 0; 00256 00257 if (!init) goto cleanup; 00258 00259 ret = nf_register_sockopt(&sock_ops); 00260 00261 if (ret < 0) 00262 goto cleanup_nothing; 00263 00264 ret = ipfw_init_or_cleanup(1); 00265 if (ret < 0) 00266 goto cleanup_sockopt; 00267 00268 ret = masq_init(); 00269 if (ret < 0) 00270 goto cleanup_ipfw; 00271 00272 nf_register_hook(&preroute_ops); 00273 nf_register_hook(&postroute_ops); 00274 nf_register_hook(&forward_ops); 00275 nf_register_hook(&local_in_ops); 00276 00277 return ret; 00278 00279 cleanup: 00280 nf_unregister_hook(&preroute_ops); 00281 nf_unregister_hook(&postroute_ops); 00282 nf_unregister_hook(&forward_ops); 00283 nf_unregister_hook(&local_in_ops); 00284 00285 masq_cleanup(); 00286 00287 cleanup_ipfw: 00288 ipfw_init_or_cleanup(0); 00289 00290 cleanup_sockopt: 00291 nf_unregister_sockopt(&sock_ops); 00292 00293 cleanup_nothing: 00294 return ret; 00295 } 00296 00297 static int __init init(void) 00298 { 00299 return init_or_cleanup(1); 00300 } 00301 00302 static void __exit fini(void) 00303 { 00304 init_or_cleanup(0); 00305 } 00306 00307 module_init(init); 00308 module_exit(fini);

Generated on Wed Dec 1 21:25:30 2004 for Linux 2.4.23 Networking by doxygen 1.3.8