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

📄 ip_fw.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 2 页
字号:
			if (f->fw_divert_port == ignport)				continue;       /* ignore this rule */			break;		}		/* Update statistics */		f->fw_pcnt += 1;		f->fw_bcnt += ip->ip_len;		f->timestamp = rtems_bsdnet_seconds_since_boot();		/* Log to console if desired */		if ((f->fw_flg & IP_FW_F_PRN) && fw_verbose)			ipfw_report(f, ip, rif, oif);		/* Take appropriate action */		switch (f->fw_flg & IP_FW_F_COMMAND) {		case IP_FW_F_ACCEPT:			return(0);		case IP_FW_F_COUNT:			continue;		case IP_FW_F_DIVERT:			return(f->fw_divert_port);		case IP_FW_F_TEE:			/*			 * XXX someday tee packet here, but beware that you			 * can't use m_copym() or m_copypacket() because			 * the divert input routine modifies the mbuf			 * (and these routines only increment reference			 * counts in the case of mbuf clusters), so need			 * to write custom routine.			 */			continue;		case IP_FW_F_SKIPTO:#ifdef DIAGNOSTIC			while (chain->chain.le_next			    && chain->chain.le_next->rule->fw_number				< f->fw_skipto_rule)#else			while (chain->chain.le_next->rule->fw_number			    < f->fw_skipto_rule)#endif				chain = chain->chain.le_next;			continue;		}		/* Deny/reject this packet using this rule */		rule = f;		break;	}#ifdef DIAGNOSTIC	/* Rule 65535 should always be there and should always match */	if (!chain)		panic("ip_fw: chain");#endif	/*	 * At this point, we're going to drop the packet.	 * Send a reject notice if all of the following are true:	 *	 * - The packet matched a reject rule	 * - The packet is not an ICMP packet	 * - The packet is not a multicast or broadcast packet	 */	if ((rule->fw_flg & IP_FW_F_COMMAND) == IP_FW_F_REJECT	    && ip->ip_p != IPPROTO_ICMP	    && !((*m)->m_flags & (M_BCAST|M_MCAST))	    && !IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {		switch (rule->fw_reject_code) {		case IP_FW_REJECT_RST:		  {			struct tcphdr *const tcp =				(struct tcphdr *) ((u_long *)ip + ip->ip_hl);			struct tcpiphdr ti, *const tip = (struct tcpiphdr *) ip;			if (offset != 0 || (tcp->th_flags & TH_RST))				break;			ti.ti_i = *((struct ipovly *) ip);			ti.ti_t = *tcp;			bcopy(&ti, ip, sizeof(ti));			NTOHL(tip->ti_seq);			NTOHL(tip->ti_ack);			tip->ti_len = ip->ip_len - hlen - (tip->ti_off << 2);			if (tcp->th_flags & TH_ACK) {				tcp_respond(NULL, tip, *m,				    (tcp_seq)0, ntohl(tcp->th_ack), TH_RST);			} else {				if (tcp->th_flags & TH_SYN)					tip->ti_len++;				tcp_respond(NULL, tip, *m, tip->ti_seq				    + tip->ti_len, (tcp_seq)0, TH_RST|TH_ACK);			}			*m = NULL;			break;		  }		default:	/* Send an ICMP unreachable using code */			icmp_error(*m, ICMP_UNREACH,			    rule->fw_reject_code, 0L, 0);			*m = NULL;			break;		}	}dropit:	/*	 * Finally, drop the packet.	 */	if (*m) {		m_freem(*m);		*m = NULL;	}	return(0);}static intadd_entry(struct ip_fw_head *chainptr, struct ip_fw *frwl){	struct ip_fw *ftmp = 0;	struct ip_fw_chain *fwc = 0, *fcp, *fcpl = 0;	u_short nbr = 0;	int s;	fwc = malloc(sizeof *fwc, M_IPFW, M_DONTWAIT);	ftmp = malloc(sizeof *ftmp, M_IPFW, M_DONTWAIT);	if (!fwc || !ftmp) {		dprintf(("%s malloc said no\n", err_prefix));		if (fwc)  free(fwc, M_IPFW);		if (ftmp) free(ftmp, M_IPFW);		return (ENOSPC);	}	bcopy(frwl, ftmp, sizeof(struct ip_fw));	ftmp->fw_in_if.fu_via_if.name[FW_IFNLEN - 1] = '\0';	ftmp->fw_pcnt = 0L;	ftmp->fw_bcnt = 0L;	fwc->rule = ftmp;		s = splnet();	if (!chainptr->lh_first) {		LIST_INSERT_HEAD(chainptr, fwc, chain);		splx(s);		return(0);        } else if (ftmp->fw_number == (u_short)-1) {		if (fwc)  free(fwc, M_IPFW);		if (ftmp) free(ftmp, M_IPFW);		splx(s);		dprintf(("%s bad rule number\n", err_prefix));		return (EINVAL);        }	/* If entry number is 0, find highest numbered rule and add 100 */	if (ftmp->fw_number == 0) {		for (fcp = chainptr->lh_first; fcp; fcp = fcp->chain.le_next) {			if (fcp->rule->fw_number != (u_short)-1)				nbr = fcp->rule->fw_number;			else				break;		}		if (nbr < (u_short)-1 - 100)			nbr += 100;		ftmp->fw_number = nbr;	}	/* Got a valid number; now insert it, keeping the list ordered */	for (fcp = chainptr->lh_first; fcp; fcp = fcp->chain.le_next) {		if (fcp->rule->fw_number > ftmp->fw_number) {			if (fcpl) {				LIST_INSERT_AFTER(fcpl, fwc, chain);			} else {				LIST_INSERT_HEAD(chainptr, fwc, chain);			}			break;		} else {			fcpl = fcp;		}	}	splx(s);	return (0);}static intdel_entry(struct ip_fw_head *chainptr, u_short number){	struct ip_fw_chain *fcp;	int s;	s = splnet();	fcp = chainptr->lh_first; 	if (number != (u_short)-1) {		for (; fcp; fcp = fcp->chain.le_next) {			if (fcp->rule->fw_number == number) {				LIST_REMOVE(fcp, chain);				splx(s);				free(fcp->rule, M_IPFW);				free(fcp, M_IPFW);				return 0;			}		}	}	splx(s);	return (EINVAL);}static intzero_entry(struct mbuf *m){	struct ip_fw *frwl;	struct ip_fw_chain *fcp;	int s;	if (m) {		if (m->m_len != sizeof(struct ip_fw))			return(EINVAL);		frwl = mtod(m, struct ip_fw *);	}	else		frwl = NULL;	/*	 *	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.	 */	s = splnet();	for (fcp = ip_fw_chain.lh_first; fcp; fcp = fcp->chain.le_next)		if (!frwl || frwl->fw_number == fcp->rule->fw_number) {			fcp->rule->fw_bcnt = fcp->rule->fw_pcnt = 0;			fcp->rule->timestamp = 0;		}	splx(s);	if (fw_verbose) {		if (frwl)			printf("ipfw: Entry %d cleared.\n", frwl->fw_number);		else			printf("ipfw: Accounting cleared.\n");	}	return(0);}static struct ip_fw *check_ipfw_mbuf(struct mbuf *m){	/* Check length */	if (m->m_len != sizeof(struct ip_fw)) {		dprintf(("%s len=%d, want %d\n", err_prefix, m->m_len,		    (int)sizeof(struct ip_fw)));		return (NULL);	}	return(check_ipfw_struct(mtod(m, struct ip_fw *)));}static struct ip_fw *check_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 (NULL);	}	/* 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 (NULL);	}	/* 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 (NULL);	}	/* 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 (NULL);	}	/* 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 (NULL);	}	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 (NULL);	}	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 (NULL);	}	/*	 *	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(NULL);	}	/*	 *	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(NULL);	}	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(NULL);		}		if (frwl->fw_prot == IPPROTO_TCP &&			frwl->fw_tcpf != frwl->fw_tcpnf) {			dprintf(("%s cannot mix 'frag' with TCP flags\n", err_prefix));			return(NULL);		}	}	/* 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(NULL);		}		break;	case IP_FW_F_DIVERT:		/* Diverting to port zero 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 (NULL);		}		break;	case IP_FW_F_DENY:	case IP_FW_F_ACCEPT:	case IP_FW_F_COUNT:	case IP_FW_F_SKIPTO:		break;	default:		dprintf(("%s invalid command\n", err_prefix));		return(NULL);	}	return frwl;}static intip_fw_ctl(int stage, struct mbuf **mm){	int error;	struct mbuf *m;	if (stage == IP_FW_GET) {		struct ip_fw_chain *fcp = ip_fw_chain.lh_first;		*mm = m = m_get(M_WAIT, MT_SOOPTS);		for (; fcp; fcp = fcp->chain.le_next) {			memcpy(m->m_data, fcp->rule, sizeof *(fcp->rule));			m->m_len = sizeof *(fcp->rule);			m->m_next = m_get(M_WAIT, MT_SOOPTS);			m = m->m_next;			m->m_len = 0;		}		return (0);	}	m = *mm;	/* only allow get calls if secure mode > 2 */	if (securelevel > 2) {		if (m) (void)m_free(m);		return(EPERM);	}	if (stage == IP_FW_FLUSH) {		while (ip_fw_chain.lh_first != NULL && 		    ip_fw_chain.lh_first->rule->fw_number != (u_short)-1) {			struct ip_fw_chain *fcp = ip_fw_chain.lh_first;			int s = splnet();			LIST_REMOVE(ip_fw_chain.lh_first, chain);			splx(s);			free(fcp->rule, M_IPFW);			free(fcp, M_IPFW);		}		if (m) (void)m_free(m);		return (0);	}	if (stage == IP_FW_ZERO) {		error = zero_entry(m);		if (m) (void)m_free(m);		return (error);	}	if (m == NULL) {		printf("%s NULL mbuf ptr\n", err_prefix);		return (EINVAL);	}	if (stage == IP_FW_ADD) {		struct ip_fw *frwl = check_ipfw_mbuf(m);		if (!frwl)			error = EINVAL;		else			error = add_entry(&ip_fw_chain, frwl);		if (m) (void)m_free(m);		return error;	}	if (stage == IP_FW_DEL) {		if (m->m_len != sizeof(struct ip_fw)) {			dprintf(("%s len=%d, want %d\n", err_prefix, m->m_len,			    (int)sizeof(struct ip_fw)));			error = EINVAL;		} else if (mtod(m, struct ip_fw *)->fw_number == (u_short)-1) {			dprintf(("%s can't delete rule 65535\n", err_prefix));			error = EINVAL;		} else			error = del_entry(&ip_fw_chain,			    mtod(m, struct ip_fw *)->fw_number);		if (m) (void)m_free(m);		return error;	}	dprintf(("%s unknown request %d\n", err_prefix, stage));	if (m) (void)m_free(m);	return (EINVAL);}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 = (u_short)-1;#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) == NULL ||		add_entry(&ip_fw_chain, &default_rule))		panic(__FUNCTION__);	printf("IP packet filtering initialized, "#ifdef IPDIVERT		"divert enabled, ");#else		"divert 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}#ifdef IPFIREWALL_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 (ip_fw_chain.lh_first != NULL) {		struct ip_fw_chain *fcp = ip_fw_chain.lh_first;		LIST_REMOVE(ip_fw_chain.lh_first, 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){	DISPATCH(lkmtp, cmd, ver, ipfw_load, ipfw_unload, lkm_nullcmd);}#endif

⌨️ 快捷键说明

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