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

📄 ip_nat.c

📁 NAT协议完整源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		 */		if (n->in_space) {			if ((n->in_flags & IPN_IPRANGE) != 0)				n->in_space += 1;			else				n->in_space -= 1;		} else			n->in_space = 1;		if ((n->in_outmsk != 0xffffffff) && (n->in_outmsk != 0) &&		    ((n->in_flags & (IPN_IPRANGE|IPN_SPLIT)) == 0))			n->in_nip = ntohl(n->in_outip) + 1;		else if ((n->in_flags & IPN_SPLIT) &&			 (n->in_redir & NAT_REDIRECT))			n->in_nip = ntohl(n->in_inip);		else			n->in_nip = ntohl(n->in_outip);		if (n->in_redir & NAT_MAP) {			n->in_pnext = ntohs(n->in_pmin);			/*			 * Multiply by the number of ports made available.			 */			if (ntohs(n->in_pmax) >= ntohs(n->in_pmin)) {				n->in_space *= (ntohs(n->in_pmax) -						ntohs(n->in_pmin) + 1);				/*				 * Because two different sources can map to				 * different destinations but use the same				 * local IP#/port #.				 * If the result is smaller than in_space, then				 * we may have wrapped around 32bits.				 */				i = n->in_inmsk;				if ((i != 0) && (i != 0xffffffff)) {					j = n->in_space * (~ntohl(i) + 1);					if (j >= n->in_space)						n->in_space = j;					else						n->in_space = 0xffffffff;				}			}			/*			 * If no protocol is specified, multiple by 256.			 */			if ((n->in_flags & IPN_TCPUDP) == 0) {					j = n->in_space * 256;					if (j >= n->in_space)						n->in_space = j;					else						n->in_space = 0xffffffff;			}		}		/* Otherwise, these fields are preset */		n = NULL;		nat_stats.ns_rules++;		break;	case SIOCRMNAT :		if (!(mode & FWRITE)) {			error = EPERM;			n = NULL;			break;		}		if (!n) {			error = ESRCH;			break;		}		if (n->in_redir & NAT_REDIRECT)			nat_delrdr(n);		if (n->in_redir & (NAT_MAPBLK|NAT_MAP))			nat_delnat(n);		if (nat_list == NULL) {			nat_masks = 0;			rdr_masks = 0;		}		*np = n->in_next;		if (!n->in_use) {			if (n->in_apr)				appr_free(n->in_apr);			KFREE(n);			nat_stats.ns_rules--;		} else {			n->in_flags |= IPN_DELETE;			n->in_next = NULL;		}		n = NULL;		break;	case SIOCGNATS :		MUTEX_DOWNGRADE(&ipf_nat);		nat_stats.ns_table[0] = nat_table[0];		nat_stats.ns_table[1] = nat_table[1];		nat_stats.ns_list = nat_list;		nat_stats.ns_nattab_sz = ipf_nattable_sz;		nat_stats.ns_rultab_sz = ipf_natrules_sz;		nat_stats.ns_rdrtab_sz = ipf_rdrrules_sz;		nat_stats.ns_instances = nat_instances;		nat_stats.ns_apslist = ap_sess_list;		error = IWCOPYPTR((char *)&nat_stats, (char *)data,				  sizeof(nat_stats));		break;	case SIOCGNATL :	    {		natlookup_t nl;		MUTEX_DOWNGRADE(&ipf_nat);		error = IRCOPYPTR((char *)data, (char *)&nl, sizeof(nl));		if (error)			break;		if (nat_lookupredir(&nl)) {			error = IWCOPYPTR((char *)&nl, (char *)data,					  sizeof(nl));		} else			error = ESRCH;		break;	    }	case SIOCIPFFL :	/* old SIOCFLNAT & SIOCCNATL */		if (!(mode & FWRITE)) {			error = EPERM;			break;		}		error = 0;		if (arg == 0)			ret = nat_flushtable();		else if (arg == 1)			ret = nat_clearlist();		else			error = EINVAL;		MUTEX_DOWNGRADE(&ipf_nat);		if (!error) {			error = IWCOPY((caddr_t)&ret, data, sizeof(ret));			if (error)				error = EFAULT;		}		break;	case SIOCSTLCK :		error = IRCOPY(data, (caddr_t)&arg, sizeof(arg));		if (!error) {			error = IWCOPY((caddr_t)&fr_nat_lock, data,					sizeof(fr_nat_lock));			if (!error)				fr_nat_lock = arg;		} else			error = EFAULT;		break;	case SIOCSTPUT :		if (fr_nat_lock)			error = fr_natputent(data);		else			error = EACCES;		break;	case SIOCSTGSZ :		if (fr_nat_lock)			error = fr_natgetsz(data);		else			error = EACCES;		break;	case SIOCSTGET :		if (fr_nat_lock)			error = fr_natgetent(data);		else			error = EACCES;		break;	case FIONREAD :#ifdef	IPFILTER_LOG		arg = (int)iplused[IPL_LOGNAT];		MUTEX_DOWNGRADE(&ipf_nat);		error = IWCOPY((caddr_t)&arg, (caddr_t)data, sizeof(arg));		if (error)			error = EFAULT;#endif		break;	default :		error = EINVAL;		break;	}	RWLOCK_EXIT(&ipf_nat);			/* READ/WRITE */done:	if (nt)		KFREE(nt);	return error;}static int fr_natgetsz(data)caddr_t data;{	ap_session_t *aps;	nat_t *nat, *n;	int error = 0;	natget_t ng;	error = IRCOPY(data, (caddr_t)&ng, sizeof(ng));	if (error)		return EFAULT;	nat = ng.ng_ptr;	if (!nat) {		nat = nat_instances;		ng.ng_sz = 0;		if (nat == NULL) {			error = IWCOPY((caddr_t)&ng, data, sizeof(ng));			if (error)				error = EFAULT;			return error;		}	} else {		/*		 * Make sure the pointer we're copying from exists in the		 * current list of entries.  Security precaution to prevent		 * copying of random kernel data.		 */		for (n = nat_instances; n; n = n->nat_next)			if (n == nat)				break;		if (!n)			return ESRCH;	}	ng.ng_sz = sizeof(nat_save_t);	aps = nat->nat_aps;	if ((aps != NULL) && (aps->aps_data != 0)) {		ng.ng_sz += sizeof(ap_session_t);		ng.ng_sz += aps->aps_psiz;	}	error = IWCOPY((caddr_t)&ng, data, sizeof(ng));	if (error)		error = EFAULT;	return error;}static int fr_natgetent(data)caddr_t data;{	nat_save_t ipn, *ipnp, *ipnn = NULL;	register nat_t *n, *nat;	ap_session_t *aps;	int error;	error = IRCOPY(data, (caddr_t)&ipnp, sizeof(ipnp));	if (error)		return EFAULT;	error = IRCOPY((caddr_t)ipnp, (caddr_t)&ipn, sizeof(ipn));	if (error)		return EFAULT;	nat = ipn.ipn_next;	if (!nat) {		nat = nat_instances;		if (nat == NULL) {			if (nat_instances == NULL)				return ENOENT;			return 0;		}	} else {		/*		 * Make sure the pointer we're copying from exists in the		 * current list of entries.  Security precaution to prevent		 * copying of random kernel data.		 */		for (n = nat_instances; n; n = n->nat_next)			if (n == nat)				break;		if (!n)			return ESRCH;	}	ipn.ipn_next = nat->nat_next;	ipn.ipn_dsize = 0;	bcopy((char *)nat, (char *)&ipn.ipn_nat, sizeof(ipn.ipn_nat));	ipn.ipn_nat.nat_data = NULL;	if (nat->nat_ptr) {		bcopy((char *)nat->nat_ptr, (char *)&ipn.ipn_ipnat,		      sizeof(ipn.ipn_ipnat));	}	if (nat->nat_fr)		bcopy((char *)nat->nat_fr, (char *)&ipn.ipn_rule,		      sizeof(ipn.ipn_rule));	if ((aps = nat->nat_aps)) {		ipn.ipn_dsize = sizeof(*aps);		if (aps->aps_data)			ipn.ipn_dsize += aps->aps_psiz;		KMALLOCS(ipnn, nat_save_t *, sizeof(*ipnn) + ipn.ipn_dsize);		if (ipnn == NULL)			return ENOMEM;		bcopy((char *)&ipn, (char *)ipnn, sizeof(ipn));		bcopy((char *)aps, ipnn->ipn_data, sizeof(*aps));		if (aps->aps_data) {			bcopy(aps->aps_data, ipnn->ipn_data + sizeof(*aps),			      aps->aps_psiz);			ipnn->ipn_dsize += aps->aps_psiz;		}		error = IWCOPY((caddr_t)ipnn, ipnp,			       sizeof(ipn) + ipn.ipn_dsize);		if (error)			error = EFAULT;		KFREES(ipnn, sizeof(*ipnn) + ipn.ipn_dsize);	} else {		error = IWCOPY((caddr_t)&ipn, ipnp, sizeof(ipn));		if (error)			error = EFAULT;	}	return error;}static int fr_natputent(data)caddr_t data;{	nat_save_t ipn, *ipnp, *ipnn = NULL;	register nat_t *n, *nat;	ap_session_t *aps;	frentry_t *fr;	ipnat_t *in;	int error;	error = IRCOPY(data, (caddr_t)&ipnp, sizeof(ipnp));	if (error)		return EFAULT;	error = IRCOPY((caddr_t)ipnp, (caddr_t)&ipn, sizeof(ipn));	if (error)		return EFAULT;	nat = NULL;	if (ipn.ipn_dsize) {		KMALLOCS(ipnn, nat_save_t *, sizeof(ipn) + ipn.ipn_dsize);		if (ipnn == NULL)			return ENOMEM;		bcopy((char *)&ipn, (char *)ipnn, sizeof(ipn));		error = IRCOPY((caddr_t)ipnp, (caddr_t)ipn.ipn_data,			       ipn.ipn_dsize);		if (error) {			error = EFAULT;			goto junkput;		}	} else		ipnn = NULL;	KMALLOC(nat, nat_t *);	if (nat == NULL) {		error = EFAULT;		goto junkput;	}	bcopy((char *)&ipn.ipn_nat, (char *)nat, sizeof(*nat));	/*	 * Initialize all these so that nat_delete() doesn't cause a crash.	 */	nat->nat_phnext[0] = NULL;	nat->nat_phnext[1] = NULL;	fr = nat->nat_fr;	nat->nat_fr = NULL;	aps = nat->nat_aps;	nat->nat_aps = NULL;	in = nat->nat_ptr;	nat->nat_ptr = NULL;	nat->nat_data = NULL;	/*	 * Restore the rule associated with this nat session	 */	if (in) {		KMALLOC(in, ipnat_t *);		if (in == NULL) {			error = ENOMEM;			goto junkput;		}		nat->nat_ptr = in;		bcopy((char *)&ipn.ipn_ipnat, (char *)in, sizeof(*in));		in->in_use = 1;		in->in_flags |= IPN_DELETE;		in->in_next = NULL;		in->in_rnext = NULL;		in->in_prnext = NULL;		in->in_mnext = NULL;		in->in_pmnext = NULL;		in->in_ifp = GETUNIT(in->in_ifname, 4);		if (in->in_plabel[0] != '\0') {			in->in_apr = appr_match(in->in_p, in->in_plabel);		}	}	/*	 * Restore ap_session_t structure.  Include the private data allocated	 * if it was there.	 */	if (aps) {		KMALLOC(aps, ap_session_t *);		if (aps == NULL) {			error = ENOMEM;			goto junkput;		}		nat->nat_aps = aps;		aps->aps_next = ap_sess_list;		ap_sess_list = aps;		bcopy(ipnn->ipn_data, (char *)aps, sizeof(*aps));		if (in)			aps->aps_apr = in->in_apr;		if (aps->aps_psiz) {			KMALLOCS(aps->aps_data, void *, aps->aps_psiz);			if (aps->aps_data == NULL) {				error = ENOMEM;				goto junkput;			}			bcopy(ipnn->ipn_data + sizeof(*aps), aps->aps_data,			      aps->aps_psiz);		} else {			aps->aps_psiz = 0;			aps->aps_data = NULL;		}	}	/*	 * If there was a filtering rule associated with this entry then	 * build up a new one.	 */	if (fr != NULL) {		if (nat->nat_flags & FI_NEWFR) {			KMALLOC(fr, frentry_t *);			nat->nat_fr = fr;			if (fr == NULL) {				error = ENOMEM;				goto junkput;			}			bcopy((char *)&ipn.ipn_fr, (char *)fr, sizeof(*fr));			ipn.ipn_nat.nat_fr = fr;			error = IWCOPY((caddr_t)&ipn, ipnp, sizeof(ipn));			if (error) {				error = EFAULT;				goto junkput;			}		} else {			for (n = nat_instances; n; n = n->nat_next)				if (n->nat_fr == fr)					break;			if (!n) {				error = ESRCH;				goto junkput;			}		}	}	if (ipnn)		KFREES(ipnn, sizeof(ipn) + ipn.ipn_dsize);	nat_insert(nat);	return 0;junkput:	if (ipnn)		KFREES(ipnn, sizeof(ipn) + ipn.ipn_dsize);	if (nat)		nat_delete(nat);	return error;}/* * Delete a nat entry from the various lists and table. */static void nat_delete(natd)struct nat *natd;{	struct ipnat *ipn;	if (natd->nat_flags & FI_WILDP)		nat_stats.ns_wilds--;	if (natd->nat_hnext[0])		natd->nat_hnext[0]->nat_phnext[0] = natd->nat_phnext[0];	*natd->nat_phnext[0] = natd->nat_hnext[0];	if (natd->nat_hnext[1])		natd->nat_hnext[1]->nat_phnext[1] = natd->nat_phnext[1];	*natd->nat_phnext[1] = natd->nat_hnext[1];	if (natd->nat_fr != NULL) {		ATOMIC_DEC32(natd->nat_fr->fr_ref);	}	if (natd->nat_hm != NULL)		nat_hostmapdel(natd->nat_hm);	/*	 * If there is an active reference from the nat entry to its parent	 * rule, decrement the rule's reference count and free it too if no	 * longer being used.	 */	ipn = natd->nat_ptr;	if (ipn != NULL) {		ipn->in_space++;		ipn->in_use--;		if (!ipn->in_use && (ipn->in_flags & IPN_DELETE)) {			if (ipn->in_apr)				appr_free(ipn->in_apr);			KFREE(ipn);			nat_stats.ns_rules--;		}	}	MUTEX_DESTROY(&natd->nat_lock);	/*	 * If there's a fragment table entry too for this nat entry, then	 * dereference that as well.	 */	ipfr_forget((void *)natd);	aps_free(natd->nat_aps);	nat_stats.ns_inuse--;	KFREE(natd);}/* * nat_flushtable - clear the NAT table of all mapping entries. */static int nat_flushtable(){	register nat_t *nat, **natp;	register int j = 0;	/*	 * ALL NAT mappings deleted, so lets just make the deletions	 * quicker.	 */	if (nat_table[0] != NULL)		bzero((char *)nat_table[0],		      sizeof(nat_table[0]) * ipf_nattable_sz);	if (nat_table[1] != NULL)		bzero((char *)nat_table[1],		      sizeof(nat_table[1]) * ipf_nattable_sz);	for (natp = &nat_instances; (nat = *natp); ) {		*natp = nat->nat_next;#ifdef	IPFILTER_LOG		nat_log(nat, NL_FLUSH);#endif		nat_delete(nat);

⌨️ 快捷键说明

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