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