⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ip_nat_core.c

📁 LINUX 2.6.17.4的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
		invert_tuplepr(&reply, &new_tuple);		ip_conntrack_alter_reply(conntrack, &reply);		/* Non-atomic: we own this at the moment. */		if (maniptype == IP_NAT_MANIP_SRC)			conntrack->status |= IPS_SRC_NAT;		else			conntrack->status |= IPS_DST_NAT;	}	/* Place in source hash if this is the first time. */	if (have_to_hash) {		unsigned int srchash			= hash_by_src(&conntrack->tuplehash[IP_CT_DIR_ORIGINAL]				      .tuple);		write_lock_bh(&ip_nat_lock);		list_add(&info->bysource, &bysource[srchash]);		write_unlock_bh(&ip_nat_lock);	}	/* It's done. */	if (maniptype == IP_NAT_MANIP_DST)		set_bit(IPS_DST_NAT_DONE_BIT, &conntrack->status);	else		set_bit(IPS_SRC_NAT_DONE_BIT, &conntrack->status);	return NF_ACCEPT;}EXPORT_SYMBOL(ip_nat_setup_info);/* Returns true if succeeded. */static intmanip_pkt(u_int16_t proto,	  struct sk_buff **pskb,	  unsigned int iphdroff,	  const struct ip_conntrack_tuple *target,	  enum ip_nat_manip_type maniptype){	struct iphdr *iph;	struct ip_nat_protocol *p;	if (!skb_make_writable(pskb, iphdroff + sizeof(*iph)))		return 0;	iph = (void *)(*pskb)->data + iphdroff;	/* Manipulate protcol part. */	p = ip_nat_proto_find_get(proto);	if (!p->manip_pkt(pskb, iphdroff, target, maniptype)) {		ip_nat_proto_put(p);		return 0;	}	ip_nat_proto_put(p);	iph = (void *)(*pskb)->data + iphdroff;	if (maniptype == IP_NAT_MANIP_SRC) {		iph->check = ip_nat_cheat_check(~iph->saddr, target->src.ip,						iph->check);		iph->saddr = target->src.ip;	} else {		iph->check = ip_nat_cheat_check(~iph->daddr, target->dst.ip,						iph->check);		iph->daddr = target->dst.ip;	}	return 1;}/* Do packet manipulations according to ip_nat_setup_info. */unsigned int ip_nat_packet(struct ip_conntrack *ct,			   enum ip_conntrack_info ctinfo,			   unsigned int hooknum,			   struct sk_buff **pskb){	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);	unsigned long statusbit;	enum ip_nat_manip_type mtype = HOOK2MANIP(hooknum);	if (mtype == IP_NAT_MANIP_SRC)		statusbit = IPS_SRC_NAT;	else		statusbit = IPS_DST_NAT;	/* Invert if this is reply dir. */	if (dir == IP_CT_DIR_REPLY)		statusbit ^= IPS_NAT_MASK;	/* Non-atomic: these bits don't change. */	if (ct->status & statusbit) {		struct ip_conntrack_tuple target;		/* We are aiming to look like inverse of other direction. */		invert_tuplepr(&target, &ct->tuplehash[!dir].tuple);		if (!manip_pkt(target.dst.protonum, pskb, 0, &target, mtype))			return NF_DROP;	}	return NF_ACCEPT;}EXPORT_SYMBOL_GPL(ip_nat_packet);/* Dir is direction ICMP is coming from (opposite to packet it contains) */int ip_nat_icmp_reply_translation(struct sk_buff **pskb,				  struct ip_conntrack *ct,				  enum ip_nat_manip_type manip,				  enum ip_conntrack_dir dir){	struct {		struct icmphdr icmp;		struct iphdr ip;	} *inside;	struct ip_conntrack_tuple inner, target;	int hdrlen = (*pskb)->nh.iph->ihl * 4;	unsigned long statusbit;	if (!skb_make_writable(pskb, hdrlen + sizeof(*inside)))		return 0;	inside = (void *)(*pskb)->data + (*pskb)->nh.iph->ihl*4;	/* We're actually going to mangle it beyond trivial checksum	   adjustment, so make sure the current checksum is correct. */	if ((*pskb)->ip_summed != CHECKSUM_UNNECESSARY) {		hdrlen = (*pskb)->nh.iph->ihl * 4;		if ((u16)csum_fold(skb_checksum(*pskb, hdrlen,						(*pskb)->len - hdrlen, 0)))			return 0;	}	/* Must be RELATED */	IP_NF_ASSERT((*pskb)->nfctinfo == IP_CT_RELATED ||		     (*pskb)->nfctinfo == IP_CT_RELATED+IP_CT_IS_REPLY);	/* Redirects on non-null nats must be dropped, else they'll           start talking to each other without our translation, and be           confused... --RR */	if (inside->icmp.type == ICMP_REDIRECT) {		/* If NAT isn't finished, assume it and drop. */		if ((ct->status & IPS_NAT_DONE_MASK) != IPS_NAT_DONE_MASK)			return 0;		if (ct->status & IPS_NAT_MASK)			return 0;	}	DEBUGP("icmp_reply_translation: translating error %p manp %u dir %s\n",	       *pskb, manip, dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY");	if (!ip_ct_get_tuple(&inside->ip, *pskb, (*pskb)->nh.iph->ihl*4 +	                     sizeof(struct icmphdr) + inside->ip.ihl*4,	                     &inner,			     __ip_conntrack_proto_find(inside->ip.protocol)))		return 0;	/* Change inner back to look like incoming packet.  We do the	   opposite manip on this hook to normal, because it might not	   pass all hooks (locally-generated ICMP).  Consider incoming	   packet: PREROUTING (DST manip), routing produces ICMP, goes	   through POSTROUTING (which must correct the DST manip). */	if (!manip_pkt(inside->ip.protocol, pskb,		       (*pskb)->nh.iph->ihl*4		       + sizeof(inside->icmp),		       &ct->tuplehash[!dir].tuple,		       !manip))		return 0;	/* Reloading "inside" here since manip_pkt inner. */	inside = (void *)(*pskb)->data + (*pskb)->nh.iph->ihl*4;	inside->icmp.checksum = 0;	inside->icmp.checksum = csum_fold(skb_checksum(*pskb, hdrlen,						       (*pskb)->len - hdrlen,						       0));	/* Change outer to look the reply to an incoming packet	 * (proto 0 means don't invert per-proto part). */	if (manip == IP_NAT_MANIP_SRC)		statusbit = IPS_SRC_NAT;	else		statusbit = IPS_DST_NAT;	/* Invert if this is reply dir. */	if (dir == IP_CT_DIR_REPLY)		statusbit ^= IPS_NAT_MASK;	if (ct->status & statusbit) {		invert_tuplepr(&target, &ct->tuplehash[!dir].tuple);		if (!manip_pkt(0, pskb, 0, &target, manip))			return 0;	}	return 1;}EXPORT_SYMBOL_GPL(ip_nat_icmp_reply_translation);/* Protocol registration. */int ip_nat_protocol_register(struct ip_nat_protocol *proto){	int ret = 0;	write_lock_bh(&ip_nat_lock);	if (ip_nat_protos[proto->protonum] != &ip_nat_unknown_protocol) {		ret = -EBUSY;		goto out;	}	ip_nat_protos[proto->protonum] = proto; out:	write_unlock_bh(&ip_nat_lock);	return ret;}EXPORT_SYMBOL(ip_nat_protocol_register);/* Noone stores the protocol anywhere; simply delete it. */void ip_nat_protocol_unregister(struct ip_nat_protocol *proto){	write_lock_bh(&ip_nat_lock);	ip_nat_protos[proto->protonum] = &ip_nat_unknown_protocol;	write_unlock_bh(&ip_nat_lock);	/* Someone could be still looking at the proto in a bh. */	synchronize_net();}EXPORT_SYMBOL(ip_nat_protocol_unregister);#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \    defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)intip_nat_port_range_to_nfattr(struct sk_buff *skb, 			    const struct ip_nat_range *range){	NFA_PUT(skb, CTA_PROTONAT_PORT_MIN, sizeof(u_int16_t),		&range->min.tcp.port);	NFA_PUT(skb, CTA_PROTONAT_PORT_MAX, sizeof(u_int16_t),		&range->max.tcp.port);	return 0;nfattr_failure:	return -1;}intip_nat_port_nfattr_to_range(struct nfattr *tb[], struct ip_nat_range *range){	int ret = 0;		/* we have to return whether we actually parsed something or not */	if (tb[CTA_PROTONAT_PORT_MIN-1]) {		ret = 1;		range->min.tcp.port = 			*(u_int16_t *)NFA_DATA(tb[CTA_PROTONAT_PORT_MIN-1]);	}		if (!tb[CTA_PROTONAT_PORT_MAX-1]) {		if (ret) 			range->max.tcp.port = range->min.tcp.port;	} else {		ret = 1;		range->max.tcp.port = 			*(u_int16_t *)NFA_DATA(tb[CTA_PROTONAT_PORT_MAX-1]);	}	return ret;}EXPORT_SYMBOL_GPL(ip_nat_port_nfattr_to_range);EXPORT_SYMBOL_GPL(ip_nat_port_range_to_nfattr);#endifstatic int __init ip_nat_init(void){	size_t i;	/* Leave them the same for the moment. */	ip_nat_htable_size = ip_conntrack_htable_size;	/* One vmalloc for both hash tables */	bysource = vmalloc(sizeof(struct list_head) * ip_nat_htable_size);	if (!bysource)		return -ENOMEM;	/* Sew in builtin protocols. */	write_lock_bh(&ip_nat_lock);	for (i = 0; i < MAX_IP_NAT_PROTO; i++)		ip_nat_protos[i] = &ip_nat_unknown_protocol;	ip_nat_protos[IPPROTO_TCP] = &ip_nat_protocol_tcp;	ip_nat_protos[IPPROTO_UDP] = &ip_nat_protocol_udp;	ip_nat_protos[IPPROTO_ICMP] = &ip_nat_protocol_icmp;	write_unlock_bh(&ip_nat_lock);	for (i = 0; i < ip_nat_htable_size; i++) {		INIT_LIST_HEAD(&bysource[i]);	}	/* FIXME: Man, this is a hack.  <SIGH> */	IP_NF_ASSERT(ip_conntrack_destroyed == NULL);	ip_conntrack_destroyed = &ip_nat_cleanup_conntrack;	/* Initialize fake conntrack so that NAT will skip it */	ip_conntrack_untracked.status |= IPS_NAT_DONE_MASK;	return 0;}/* Clear NAT section of all conntracks, in case we're loaded again. */static int clean_nat(struct ip_conntrack *i, void *data){	memset(&i->nat, 0, sizeof(i->nat));	i->status &= ~(IPS_NAT_MASK | IPS_NAT_DONE_MASK | IPS_SEQ_ADJUST);	return 0;}static void __exit ip_nat_cleanup(void){	ip_ct_iterate_cleanup(&clean_nat, NULL);	ip_conntrack_destroyed = NULL;	vfree(bysource);}MODULE_LICENSE("GPL");module_init(ip_nat_init);module_exit(ip_nat_cleanup);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -