分类: LINUX
2006-06-13 23:30:51
118 case IP_CT_NEW: 119 info = &ct->nat.info; 120 121 /* Seen it before? This can happen for loopback, retrans, 122 or local packets.. */ 123 if (!ip_nat_initialized(ct, maniptype)) { 124 unsigned int ret; 125 126 if (unlikely(is_confirmed(ct))) 127 /* NAT module was loaded late */ 128 ret = alloc_null_binding_confirmed(ct, info, 129 hooknum); 130 else if (hooknum == NF_IP_LOCAL_IN) 131 /* LOCAL_IN hook doesn't have a chain! */ 132 ret = alloc_null_binding(ct, info, hooknum); 133 else 134 ret = ip_nat_rule_find(pskb, hooknum, 135 in, out, ct, 136 info); 137 138 if (ret != NF_ACCEPT) { 139 return ret; 140 } 141 } else 142 DEBUGP("Already setup manip %s for ct %p\n", 143 maniptype == IP_NAT_MANIP_SRC ? "SRC" : "DST", 144 ct); 145 break; 146 |
380 static inline int ip_nat_initialized(struct ip_conntrack *conntrack, 381 enum ip_nat_manip_type manip) 382 { 383 if (manip == IP_NAT_MANIP_SRC) 384 return test_bit(IPS_SRC_NAT_DONE_BIT, &conntrack->status); 385 return test_bit(IPS_DST_NAT_DONE_BIT, &conntrack->status); 386 } |
261 static struct nf_hook_ops ip_nat_in_ops = { 262 .hook = ip_nat_in, 263 .owner = THIS_MODULE, 264 .pf = PF_INET, 265 .hooknum = NF_IP_PRE_ROUTING, 266 .priority = NF_IP_PRI_NAT_DST, 267 }; 268 269 /* After packet filtering, change source */ 270 static struct nf_hook_ops ip_nat_out_ops = { 271 .hook = ip_nat_out, 272 .owner = THIS_MODULE, 273 .pf = PF_INET, 274 .hooknum = NF_IP_POST_ROUTING, 275 .priority = NF_IP_PRI_NAT_SRC, 276 }; ... ... 287 /* Before packet filtering, change destination */ 288 static struct nf_hook_ops ip_nat_local_out_ops = { 289 .hook = ip_nat_local_fn, 290 .owner = THIS_MODULE, 291 .pf = PF_INET, 292 .hooknum = NF_IP_LOCAL_OUT, 293 .priority = NF_IP_PRI_NAT_DST, 294 }; 295 296 /* After packet filtering, change source for reply packets of LOCAL_OUT DNAT */ 297 static struct nf_hook_ops ip_nat_local_in_ops = { 298 .hook = ip_nat_fn, 299 .owner = THIS_MODULE, 300 .pf = PF_INET, 301 .hooknum = NF_IP_LOCAL_IN, 302 .priority = NF_IP_PRI_NAT_SRC, 303 }; 304 |
279 int ip_nat_rule_find(struct sk_buff **pskb, 280 unsigned int hooknum, 281 const struct net_device *in, 282 const struct net_device *out, 283 struct ip_conntrack *ct, 284 struct ip_nat_info *info) 285 { 286 int ret; 287 288 ret = ipt_do_table(pskb, hooknum, in, out, &nat_table, NULL); 289 290 if (ret == NF_ACCEPT) { 291 if (!ip_nat_initialized(ct, HOOK2MANIP(hooknum))) 292 /* NUL mapping */ 293 ret = alloc_null_binding(ct, info, hooknum); 294 } 295 return ret; 296 } |
237 inline unsigned int 238 alloc_null_binding(struct ip_conntrack *conntrack, 239 struct ip_nat_info *info, 240 unsigned int hooknum) 241 { 242 /* Force range to this IP; let proto decide mapping for 243 per-proto parts (hence not IP_NAT_RANGE_PROTO_SPECIFIED). 244 Use reply in case it's already been mangled (eg local packet). 245 */ 246 u_int32_t ip 247 = (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC 248 ? conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip 249 : conntrack->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip); 250 struct ip_nat_range range 251 = { IP_NAT_RANGE_MAP_IPS, ip, ip, { 0 }, { 0 } }; 252 253 DEBUGP("Allocating NULL binding for %p (%u.%u.%u.%u)\n", conntrack, 254 NIPQUAD(ip)); 255 return ip_nat_setup_info(conntrack, &range, hooknum); 256 } |
344 /* It's done. */ 345 if (maniptype == IP_NAT_MANIP_DST) 346 set_bit(IPS_DST_NAT_DONE_BIT, &conntrack->status); 347 else 348 set_bit(IPS_SRC_NAT_DONE_BIT, &conntrack->status); 349 350 return NF_ACCEPT; 351 } |