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

📄 ip_fw.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
			break;		} else {			fcpl = fcp;		}	}	flush_rule_ptrs();	splx(s);	return (0);}static intdel_entry(struct ip_fw_head *chainptr, u_short number){	struct ip_fw_chain *fcp;	fcp = LIST_FIRST(chainptr);	if (number != (u_short)-1) {		for (; fcp; fcp = LIST_NEXT(fcp, chain)) {			if (fcp->rule->fw_number == number) {				int s;				/* prevent access to rules while removing them */				s = splnet();				while (fcp && fcp->rule->fw_number == number) {					struct ip_fw_chain *next;					next = LIST_NEXT(fcp, chain);					LIST_REMOVE(fcp, chain);#ifdef DUMMYNET					dn_rule_delete(fcp) ;#endif					flush_rule_ptrs();					free(fcp->rule, M_IPFW);					free(fcp, M_IPFW);					fcp = next;				}				splx(s);				return 0;			}		}	}	return (EINVAL);}static intzero_entry(struct ip_fw *frwl){	struct ip_fw_chain *fcp;	int s, cleared;	if (frwl == 0) {		s = splnet();		for (fcp = LIST_FIRST(&ip_fw_chain); fcp; fcp = LIST_NEXT(fcp, chain)) {			fcp->rule->fw_bcnt = fcp->rule->fw_pcnt = 0;			fcp->rule->timestamp = 0;		}		splx(s);	}	else {		cleared = 0;		/*		 *	It's possible to insert multiple chain entries with the		 *	same number, so we don't stop after finding the first		 *	match if zeroing a specific entry.		 */		for (fcp = LIST_FIRST(&ip_fw_chain); fcp; fcp = LIST_NEXT(fcp, chain))			if (frwl->fw_number == fcp->rule->fw_number) {				s = splnet();				while (fcp && frwl->fw_number == fcp->rule->fw_number) {					fcp->rule->fw_bcnt = fcp->rule->fw_pcnt = 0;					fcp->rule->timestamp = 0;					fcp = LIST_NEXT(fcp, chain);				}				splx(s);				cleared = 1;				break;			}		if (!cleared)	/* we didn't find any matching rules */			return (EINVAL);	}	if (fw_verbose) {		if (frwl)			printf("ipfw: Entry %d cleared.\n", frwl->fw_number);		else			printf("ipfw: Accounting cleared.\n");	}	return (0);}static intcheck_ipfw_struct(struct ip_fw *frwl){	/* Check for invalid flag bits */	if ((frwl->fw_flg & ~IP_FW_F_MASK) != 0) {		dprintf(("%s undefined flag bits set (flags=%x)\n",		    err_prefix, frwl->fw_flg));		return (EINVAL);	}	/* Must apply to incoming or outgoing (or both) */	if (!(frwl->fw_flg & (IP_FW_F_IN | IP_FW_F_OUT))) {		dprintf(("%s neither in nor out\n", err_prefix));		return (EINVAL);	}	/* Empty interface name is no good */	if (((frwl->fw_flg & IP_FW_F_IIFNAME)	      && !*frwl->fw_in_if.fu_via_if.name)	    || ((frwl->fw_flg & IP_FW_F_OIFNAME)	      && !*frwl->fw_out_if.fu_via_if.name)) {		dprintf(("%s empty interface name\n", err_prefix));		return (EINVAL);	}	/* Sanity check interface matching */	if ((frwl->fw_flg & IF_FW_F_VIAHACK) == IF_FW_F_VIAHACK) {		;		/* allow "via" backwards compatibility */	} else if ((frwl->fw_flg & IP_FW_F_IN)	    && (frwl->fw_flg & IP_FW_F_OIFACE)) {		dprintf(("%s outgoing interface check on incoming\n",		    err_prefix));		return (EINVAL);	}	/* Sanity check port ranges */	if ((frwl->fw_flg & IP_FW_F_SRNG) && IP_FW_GETNSRCP(frwl) < 2) {		dprintf(("%s src range set but n_src_p=%d\n",		    err_prefix, IP_FW_GETNSRCP(frwl)));		return (EINVAL);	}	if ((frwl->fw_flg & IP_FW_F_DRNG) && IP_FW_GETNDSTP(frwl) < 2) {		dprintf(("%s dst range set but n_dst_p=%d\n",		    err_prefix, IP_FW_GETNDSTP(frwl)));		return (EINVAL);	}	if (IP_FW_GETNSRCP(frwl) + IP_FW_GETNDSTP(frwl) > IP_FW_MAX_PORTS) {		dprintf(("%s too many ports (%d+%d)\n",		    err_prefix, IP_FW_GETNSRCP(frwl), IP_FW_GETNDSTP(frwl)));		return (EINVAL);	}	/*	 *	Protocols other than TCP/UDP don't use port range	 */	if ((frwl->fw_prot != IPPROTO_TCP) &&	    (frwl->fw_prot != IPPROTO_UDP) &&	    (IP_FW_GETNSRCP(frwl) || IP_FW_GETNDSTP(frwl))) {		dprintf(("%s port(s) specified for non TCP/UDP rule\n",		    err_prefix));		return (EINVAL);	}	/*	 *	Rather than modify the entry to make such entries work, 	 *	we reject this rule and require user level utilities	 *	to enforce whatever policy they deem appropriate.	 */	if ((frwl->fw_src.s_addr & (~frwl->fw_smsk.s_addr)) || 		(frwl->fw_dst.s_addr & (~frwl->fw_dmsk.s_addr))) {		dprintf(("%s rule never matches\n", err_prefix));		return (EINVAL);	}	if ((frwl->fw_flg & IP_FW_F_FRAG) &&		(frwl->fw_prot == IPPROTO_UDP || frwl->fw_prot == IPPROTO_TCP)) {		if (frwl->fw_nports) {			dprintf(("%s cannot mix 'frag' and ports\n", err_prefix));			return (EINVAL);		}		if (frwl->fw_prot == IPPROTO_TCP &&			frwl->fw_tcpf != frwl->fw_tcpnf) {			dprintf(("%s cannot mix 'frag' and TCP flags\n", err_prefix));			return (EINVAL);		}	}	/* Check command specific stuff */	switch (frwl->fw_flg & IP_FW_F_COMMAND)	{	case IP_FW_F_REJECT:		if (frwl->fw_reject_code >= 0x100		    && !(frwl->fw_prot == IPPROTO_TCP		      && frwl->fw_reject_code == IP_FW_REJECT_RST)) {			dprintf(("%s unknown reject code\n", err_prefix));			return (EINVAL);		}		break;	case IP_FW_F_DIVERT:		/* Diverting to port zero is invalid */	case IP_FW_F_PIPE:              /* piping through 0 is invalid */	case IP_FW_F_TEE:		if (frwl->fw_divert_port == 0) {			dprintf(("%s can't divert to port 0\n", err_prefix));			return (EINVAL);		}		break;	case IP_FW_F_DENY:	case IP_FW_F_ACCEPT:	case IP_FW_F_COUNT:	case IP_FW_F_SKIPTO:#ifdef IPFIREWALL_FORWARD	case IP_FW_F_FWD:#endif		break;	default:		dprintf(("%s invalid command\n", err_prefix));		return (EINVAL);	}	return 0;}static intip_fw_ctl(struct sockopt *sopt){	int error, s;	size_t size;	char *buf, *bp;	struct ip_fw_chain *fcp;	struct ip_fw frwl;	/* Disallow sets in really-really secure mode. */	if (sopt->sopt_dir == SOPT_SET && securelevel >= 3)			return (EPERM);	error = 0;	switch (sopt->sopt_name) {	case IP_FW_GET:		for (fcp = LIST_FIRST(&ip_fw_chain), size = 0; fcp;		     fcp = LIST_NEXT(fcp, chain))			size += sizeof *fcp->rule;		buf = malloc(size, M_TEMP, M_WAITOK);		if (buf == 0) {			error = ENOBUFS;			break;		}		for (fcp = LIST_FIRST(&ip_fw_chain), bp = buf; fcp;		     fcp = LIST_NEXT(fcp, chain)) {			bcopy(fcp->rule, bp, sizeof *fcp->rule);			bp += sizeof *fcp->rule;		}		error = sooptcopyout(sopt, buf, size);		FREE(buf, M_TEMP);		break;	case IP_FW_FLUSH:		for (fcp = ip_fw_chain.lh_first; 		     fcp != 0 && fcp->rule->fw_number != IPFW_DEFAULT_RULE;		     fcp = ip_fw_chain.lh_first) {			s = splnet();			LIST_REMOVE(fcp, chain);			FREE(fcp->rule, M_IPFW);			FREE(fcp, M_IPFW);			splx(s);		}		break;	case IP_FW_ZERO:		if (sopt->sopt_val != 0) {			error = sooptcopyin(sopt, &frwl, sizeof frwl,					    sizeof frwl);			if (error || (error = zero_entry(&frwl)))				break;		} else {			error = zero_entry(0);		}		break;	case IP_FW_ADD:		error = sooptcopyin(sopt, &frwl, sizeof frwl, sizeof frwl);		if (error || (error = check_ipfw_struct(&frwl)))			break;		if (frwl.fw_number == IPFW_DEFAULT_RULE) {			dprintf(("%s can't add rule %u\n", err_prefix,				 (unsigned)IPFW_DEFAULT_RULE));			error = EINVAL;		} else {			error = add_entry(&ip_fw_chain, &frwl);		}		break;	case IP_FW_DEL:		error = sooptcopyin(sopt, &frwl, sizeof frwl, sizeof frwl);		if (error)			break;		if (frwl.fw_number == IPFW_DEFAULT_RULE) {			dprintf(("%s can't delete rule %u\n", err_prefix,				 (unsigned)IPFW_DEFAULT_RULE));			error = EINVAL;		} else {			error = del_entry(&ip_fw_chain, frwl.fw_number);		}		break;	default:		printf("ip_fw_ctl invalid option %d\n", sopt->sopt_name);		error = EINVAL ;	}	return (error);}struct ip_fw_chain *ip_fw_default_rule ;voidip_fw_init(void){	struct ip_fw default_rule;	ip_fw_chk_ptr = ip_fw_chk;	ip_fw_ctl_ptr = ip_fw_ctl;	LIST_INIT(&ip_fw_chain);	bzero(&default_rule, sizeof default_rule);	default_rule.fw_prot = IPPROTO_IP;	default_rule.fw_number = IPFW_DEFAULT_RULE;#ifdef IPFIREWALL_DEFAULT_TO_ACCEPT	default_rule.fw_flg |= IP_FW_F_ACCEPT;#else	default_rule.fw_flg |= IP_FW_F_DENY;#endif	default_rule.fw_flg |= IP_FW_F_IN | IP_FW_F_OUT;	if (check_ipfw_struct(&default_rule) != 0 ||	    add_entry(&ip_fw_chain, &default_rule))		panic("ip_fw_init");	ip_fw_default_rule = ip_fw_chain.lh_first ;	printf("IP packet filtering initialized, "#ifdef IPDIVERT		"divert enabled, ");#else		"divert disabled, ");#endif#ifdef IPFIREWALL_FORWARD	printf("rule-based forwarding enabled, ");#else	printf("rule-based forwarding disabled, ");#endif#ifdef IPFIREWALL_DEFAULT_TO_ACCEPT	printf("default to accept, ");#endif#ifndef IPFIREWALL_VERBOSE	printf("logging disabled\n");#else	if (fw_verbose_limit == 0)		printf("unlimited logging\n");	else		printf("logging limited to %d packets/entry\n",		    fw_verbose_limit);#endif}static ip_fw_chk_t *old_chk_ptr;static ip_fw_ctl_t *old_ctl_ptr;#if defined(IPFIREWALL_MODULE) && !defined(KLD_MODULE)#include <sys/exec.h>#include <sys/sysent.h>#include <sys/lkm.h>MOD_MISC(ipfw);static intipfw_load(struct lkm_table *lkmtp, int cmd){	int s=splnet();	old_chk_ptr = ip_fw_chk_ptr;	old_ctl_ptr = ip_fw_ctl_ptr;	ip_fw_init();	splx(s);	return 0;}static intipfw_unload(struct lkm_table *lkmtp, int cmd){	int s=splnet();	ip_fw_chk_ptr =  old_chk_ptr;	ip_fw_ctl_ptr =  old_ctl_ptr;	while (LIST_FIRST(&ip_fw_chain) != NULL) {		struct ip_fw_chain *fcp = LIST_FIRST(&ip_fw_chain);		LIST_REMOVE(LIST_FIRST(&ip_fw_chain), chain);		free(fcp->rule, M_IPFW);		free(fcp, M_IPFW);	}		splx(s);	printf("IP firewall unloaded\n");	return 0;}intipfw_mod(struct lkm_table *lkmtp, int cmd, int ver){	MOD_DISPATCH(ipfw, lkmtp, cmd, ver,		ipfw_load, ipfw_unload, lkm_nullcmd);}#elsestatic intipfw_modevent(module_t mod, int type, void *unused){	int s;		switch (type) {	case MOD_LOAD:		s = splnet();		old_chk_ptr = ip_fw_chk_ptr;		old_ctl_ptr = ip_fw_ctl_ptr;		ip_fw_init();		splx(s);		return 0;	case MOD_UNLOAD:		s = splnet();		ip_fw_chk_ptr =  old_chk_ptr;		ip_fw_ctl_ptr =  old_ctl_ptr;		while (LIST_FIRST(&ip_fw_chain) != NULL) {			struct ip_fw_chain *fcp = LIST_FIRST(&ip_fw_chain);			LIST_REMOVE(LIST_FIRST(&ip_fw_chain), chain);			free(fcp->rule, M_IPFW);			free(fcp, M_IPFW);		}			splx(s);		printf("IP firewall unloaded\n");		return 0;	default:		break;	}	return 0;}static moduledata_t ipfwmod = {	"ipfw",	ipfw_modevent,	0};#ifndef OSKITDECLARE_MODULE(ipfw, ipfwmod, SI_SUB_PSEUDO, SI_ORDER_ANY);#elsevoidoskit_freebsd_net_ipfw_init() /* XXX:  HACK HACK HACK */{	ipfw_modevent(NULL, MOD_LOAD, NULL);}#endif /* #ifndef OSKIT */#endif

⌨️ 快捷键说明

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