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

📄 ip_masq.c

📁 GNU Hurd 源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
static int ip_masq_unhash(struct ip_masq *ms){        if (!(ms->flags & IP_MASQ_F_HASHED)) {                IP_MASQ_ERR( "ip_masq_unhash(): request for unhash flagged, called from %p\n",			__builtin_return_address(0));                return 0;        }	list_del(&ms->m_list);	list_del(&ms->s_list);	list_del(&ms->d_list);	atomic_sub(IP_MASQ_NTABLES, &ms->refcnt);        ms->flags &= ~IP_MASQ_F_HASHED;        return 1;}/* *	Returns ip_masq associated with supplied parameters, either *	broken out of the ip/tcp headers or directly supplied for those *	pathological protocols with address/port in the data stream *	(ftp, irc).  addresses and ports are in network order. *	called for pkts coming from OUTside-to-INside the firewall. * *	s_addr, s_port: pkt source address (foreign host) *	d_addr, d_port: pkt dest address (firewall) * * 	NB. Cannot check destination address, just for the incoming port. * 	reason: archie.doc.ac.uk has 6 interfaces, you send to * 	phoenix and get a reply from any other interface(==dst)! * * 	[Only for UDP] - AC *	 *	Caller must lock tables */static struct ip_masq * __ip_masq_in_get(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port){        unsigned hash;        struct ip_masq *ms = NULL;	struct list_head *l,*e;	hash = ip_masq_hash_key(protocol, d_addr^s_addr, d_port^s_port);	l = &ip_masq_m_table[hash];	for (e=l->next; e!=l; e=e->next) {		ms = list_entry(e, struct ip_masq, m_list);		if (s_port==ms->dport && s_addr==ms->daddr &&		    d_port==ms->mport && protocol==ms->protocol &&		    d_addr==ms->maddr &&		    ((ms->flags & (MASQ_DADDR_PASS | MASQ_DPORT_PASS)) == 0)		    ) {			IP_MASQ_DEBUG(2, "look/in %d %08X:%04hX->%08X:%04hX OK\n",			       protocol,			       s_addr,			       s_port,			       d_addr,			       d_port);			atomic_inc(&ms->refcnt);                        goto out;		}        }        hash = ip_masq_hash_key(protocol, d_addr, d_port);	l = &ip_masq_m_table[hash];	for (e=l->next; e!=l; e=e->next) {		ms = list_entry(e, struct ip_masq, m_list);		if (protocol==ms->protocol && 		    (d_addr==ms->maddr && d_port==ms->mport) &&		    (s_addr==ms->daddr || ms->flags & MASQ_DADDR_PASS) &&		    (s_port==ms->dport || ms->flags & MASQ_DPORT_PASS)		    ) {			IP_MASQ_DEBUG(2, "look/in %d %08X:%04hX->%08X:%04hX OK\n",			       protocol,			       s_addr,			       s_port,			       d_addr,			       d_port);			atomic_inc(&ms->refcnt);                        goto out;		}        }	IP_MASQ_DEBUG(2, "look/in %d %08X:%04hX->%08X:%04hX fail\n",	       protocol,	       s_addr,	       s_port,	       d_addr,	       d_port);	ms = NULL;out:        return ms;}/* *	Returns ip_masq associated with supplied parameters, either *	broken out of the ip/tcp headers or directly supplied for those *	pathological protocols with address/port in the data stream *	(ftp, irc).  addresses and ports are in network order. *	called for pkts coming from inside-to-OUTside the firewall. * *	Normally we know the source address and port but for some protocols *	(e.g. ftp PASV) we do not know the source port initially.  Alas the *	hash is keyed on source port so if the first lookup fails then try again *	with a zero port, this time only looking at entries marked "no source *	port". *	 *	Caller must lock tables */static struct ip_masq * __ip_masq_out_get(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port){        unsigned hash;        struct ip_masq *ms = NULL;	struct list_head *l,*e;	/*		 *	Check for "full" addressed entries	 */	hash = ip_masq_hash_key(protocol, s_addr^d_addr, s_port^d_port);	l = &ip_masq_s_table[hash];	for (e=l->next; e!=l; e=e->next) {		ms = list_entry(e, struct ip_masq, s_list);		if (d_addr==ms->daddr && d_port==ms->dport &&		   s_addr==ms->saddr && s_port==ms->sport &&		   protocol==ms->protocol &&		   ((ms->flags & (MASQ_DADDR_PASS | MASQ_DPORT_PASS |		   IP_MASQ_F_NO_SADDR | IP_MASQ_F_NO_SPORT)) == 0)                   ) {			IP_MASQ_DEBUG(2, "lk/out0 %d %08X:%04hX->%08X:%04hX OK\n",			       protocol,			       s_addr,			       s_port,			       d_addr,			       d_port);			atomic_inc(&ms->refcnt);			goto out;		}        }        hash = ip_masq_hash_key(protocol, s_addr, s_port);		l = &ip_masq_s_table[hash];	for (e=l->next; e!=l; e=e->next) {		ms = list_entry(e, struct ip_masq, s_list);		if (protocol == ms->protocol &&		    s_addr == ms->saddr && s_port == ms->sport &&		    (d_addr==ms->daddr || ms->flags & MASQ_DADDR_PASS) &&		    (d_port==ms->dport || ms->flags & MASQ_DPORT_PASS)                   ) {			IP_MASQ_DEBUG(2, "lk/out1 %d %08X:%04hX->%08X:%04hX OK\n",			       protocol,			       s_addr,			       s_port,			       d_addr,			       d_port);			atomic_inc(&ms->refcnt);			goto out;		}        }	/*		 *	Check for NO_SPORT entries	 */        hash = ip_masq_hash_key(protocol, s_addr, 0);	l = &ip_masq_s_table[hash];	for (e=l->next; e!=l; e=e->next) {		ms = list_entry(e, struct ip_masq, s_list);		if (ms->flags & IP_MASQ_F_NO_SPORT &&		    protocol == ms->protocol &&		    s_addr == ms->saddr && 		    (d_addr==ms->daddr || ms->flags & MASQ_DADDR_PASS) &&		    (d_port==ms->dport || ms->flags & MASQ_DPORT_PASS)                    ) {			IP_MASQ_DEBUG(2, "lk/out2 %d %08X:%04hX->%08X:%04hX OK\n",			       protocol,			       s_addr,			       s_port,			       d_addr,			       d_port);			atomic_inc(&ms->refcnt);                        goto out;		}        }	IP_MASQ_DEBUG(2, "lk/out1 %d %08X:%04hX->%08X:%04hX fail\n",	       protocol,	       s_addr,	       s_port,	       d_addr,	       d_port);	ms = NULL;out:        return ms;}#ifdef CONFIG_IP_MASQ_NREUSE/* *	Returns ip_masq for given proto,m_addr,m_port. *      called by allocation routine to find an unused m_port. *	 *	Caller must lock tables */static struct ip_masq * __ip_masq_getbym(int protocol, __u32 m_addr, __u16 m_port){        unsigned hash;        struct ip_masq *ms = NULL;        hash = ip_masq_hash_key(protocol, m_addr, m_port);        for(ms = ip_masq_m_tab[hash]; ms ; ms = ms->m_link) { 		if ( protocol==ms->protocol &&                    (m_addr==ms->maddr && m_port==ms->mport)) {			atomic_inc(&ms->refcnt);			goto out;		}        }out:        return ms;}#endifstruct ip_masq * ip_masq_out_get(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port) {	struct ip_masq *ms;	read_lock(&__ip_masq_lock);	ms = __ip_masq_out_get(protocol, s_addr, s_port, d_addr, d_port);	read_unlock(&__ip_masq_lock);	if (ms)		__ip_masq_set_expire(ms, 0);	return ms;}struct ip_masq * ip_masq_in_get(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port){	struct ip_masq *ms;	read_lock(&__ip_masq_lock);	ms =  __ip_masq_in_get(protocol, s_addr, s_port, d_addr, d_port);	read_unlock(&__ip_masq_lock);	if (ms)		__ip_masq_set_expire(ms, 0);	return ms;}static __inline__ void __ip_masq_put(struct ip_masq *ms) {	atomic_dec(&ms->refcnt);}void ip_masq_put(struct ip_masq *ms){	/*	 *	Decrement refcnt	 */	__ip_masq_put(ms);	/*	 *	if refcnt==IP_MASQ_NTABLES	 */	if (atomic_read(&ms->refcnt)==IP_MASQ_NTABLES) {		__ip_masq_set_expire(ms, ms->timeout);	} else {		IP_MASQ_DEBUG(0, "did not set timer with refcnt=%d, called from %p\n",			atomic_read(&ms->refcnt),			__builtin_return_address(0));	}}extern int sysctl_ip_always_defrag;static void masq_expire(unsigned long data){	struct ip_masq *ms = (struct ip_masq *)data;	ms->timeout = MASQUERADE_EXPIRE_RETRY;	/*	 *	hey, I'm using it	 */	atomic_inc(&ms->refcnt);	IP_MASQ_DEBUG(1, "Masqueraded %s %08lX:%04X expired\n",			masq_proto_name(ms->protocol),			ntohl(ms->saddr),ntohs(ms->sport));	write_lock(&__ip_masq_lock);#if 0000	/*	 *	Already locked, do bounce ...	 */	if (ip_masq_nlocks(&__ip_masq_lock) != 1) {		goto masq_expire_later;	}#endif	/*	 * 	do I control anybody?	 */	if (atomic_read(&ms->n_control)) 		goto masq_expire_later;	/* 		 *	does anybody controls me?	 */	if (ms->control) 		ip_masq_control_del(ms);        if (ip_masq_unhash(ms)) {		if (ms->flags&IP_MASQ_F_MPORT) {			atomic_dec(&mport_count);		} else {			atomic_inc(ip_masq_free_ports + masq_proto_num(ms->protocol));		}		ip_masq_unbind_app(ms);        }	/*	 *	refcnt==1 implies I'm the only one referrer	 */	if (atomic_read(&ms->refcnt) == 1) {		kfree_s(ms,sizeof(*ms));		sysctl_ip_always_defrag--;		MOD_DEC_USE_COUNT;		goto masq_expire_out;	}masq_expire_later:	IP_MASQ_DEBUG(0, "masq_expire delayed: %s %08lX:%04X->%08lX:%04X masq.refcnt-1=%d masq.n_control=%d\n",		masq_proto_name(ms->protocol),		ntohl(ms->saddr), ntohs(ms->sport),		ntohl(ms->daddr), ntohs(ms->dport),		atomic_read(&ms->refcnt)-1,		atomic_read(&ms->n_control));	ip_masq_put(ms);masq_expire_out:	write_unlock(&__ip_masq_lock);}static __u16 get_next_mport(void){	__u16 mport;		spin_lock_irq(&masq_port_lock);	/*	 *	Try the next available port number	 */	mport = htons(masq_port++);	if (masq_port==PORT_MASQ_END) masq_port = PORT_MASQ_BEGIN;	spin_unlock_irq(&masq_port_lock);	return mport;}/* * 	Create a new masquerade list entry, also allocate an * 	unused mport, keeping the portnumber between the * 	given boundaries MASQ_BEGIN and MASQ_END. * * 	Be careful, it can be called from u-space */struct ip_masq * ip_masq_new(int proto, __u32 maddr, __u16 mport, __u32 saddr, __u16 sport, __u32 daddr, __u16 dport, unsigned mflags){        struct ip_masq *ms, *mst;        int ports_tried;	atomic_t *free_ports_p = NULL;        static int n_fails = 0;	int prio;	if (masq_proto_num(proto)!=-1 && mport == 0) {		free_ports_p = ip_masq_free_ports + masq_proto_num(proto);		if (atomic_read(free_ports_p) == 0) {			if (++n_fails < 5)				IP_MASQ_ERR( "ip_masq_new(proto=%s): no free ports.\n",				       masq_proto_name(proto));			return NULL;		}	}	prio = (mflags&IP_MASQ_F_USER) ? GFP_KERNEL : GFP_ATOMIC;        ms = (struct ip_masq *) kmalloc(sizeof(struct ip_masq), prio);        if (ms == NULL) {                if (++n_fails < 5)                        IP_MASQ_ERR("ip_masq_new(proto=%s): no memory available.\n",                               masq_proto_name(proto));                return NULL;        }	MOD_INC_USE_COUNT;	sysctl_ip_always_defrag++;        memset(ms, 0, sizeof(*ms));	INIT_LIST_HEAD(&ms->s_list);	INIT_LIST_HEAD(&ms->m_list);	INIT_LIST_HEAD(&ms->d_list);	init_timer(&ms->timer);	ms->timer.data     = (unsigned long)ms;	ms->timer.function = masq_expire;        ms->protocol	   = proto;        ms->saddr    	   = saddr;        ms->sport	   = sport;        ms->daddr	   = daddr;        ms->dport	   = dport;        ms->flags	   = mflags;        ms->app_data	   = NULL;        ms->control	   = NULL;		atomic_set(&ms->n_control,0);	atomic_set(&ms->refcnt,0);        if (proto == IPPROTO_UDP && !mport)#ifdef CONFIG_IP_MASQ_LOOSE_DEFAULT		/*		 *	Flag this tunnel as "dest loose"		 *			 */		ms->flags |= IP_MASQ_F_DLOOSE;#else                ms->flags |= IP_MASQ_F_NO_DADDR;#endif                /* get masq address from rif */        ms->maddr	   = maddr;        /*         *	This flag will allow masq. addr (ms->maddr)         *	to follow forwarding interface address.         */        ms->flags         |= IP_MASQ_F_NO_REPLY;    	/*	 * 	We want a specific mport. Be careful.	 */	if (masq_proto_num(proto) == -1 || mport) {		ms->mport = mport;		/* 		 *	Check 5-upla uniqueness		 */		if (mflags & IP_MASQ_F_USER) 				write_lock_bh(&__ip_masq_lock);		else 			write_lock(&__ip_masq_lock);                mst = __ip_masq_in_get(proto, daddr, dport, maddr, mport);		if (mst==NULL) {			ms->flags |= IP_MASQ_F_MPORT;			atomic_inc(&mport_count);                        ip_masq_hash(ms);			if (mflags & IP_MASQ_F_USER) 					write_unlock_bh(&__ip_masq_lock);			else 				write_unlock(&__ip_masq_lock);			ip_masq_bind_app(ms);			atomic_inc(&ms->refcnt);			masq_set_state_timeout(ms, IP_MASQ_S_NONE);			return ms;		}		if (mflags & IP_MASQ_F_USER) 				write_unlock_bh(&__ip_masq_lock);		else 			write_unlock(&__ip_masq_lock);		__ip_masq_put(mst);		IP_MASQ_ERR( "Already used connection: %s, %d.%d.%d.%d:%d => %d.%d.%d.%d:%d, called from %p\n",			masq_proto_name(proto),			NIPQUAD(maddr), ntohs(mport),			NIPQUAD(daddr), ntohs(dport),			__builtin_return_address(0));		goto mport_nono;	}	        for (ports_tried = 0; 	     (atomic_read(free_ports_p) && (ports_tried <= (PORT_MASQ_END - PORT_MASQ_BEGIN)));	     ports_tried++){		mport = ms->mport = get_next_mport();		/*		 *	lookup to find out if this connection is used.		 */		if (mflags & IP_MASQ_F_USER) 			write_lock_bh(&__ip_masq_lock);		else

⌨️ 快捷键说明

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