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

📄 ip_fw.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1993 Daniel Boulet * Copyright (c) 1994 Ugen J.S.Antsilevich * * Redistribution and use in source forms, with and without modification, * are permitted provided that this entire comment appears intact. * * Redistribution in binary form may occur without any restrictions. * Obviously, it would be nice if you gave credit where credit is due * but requiring it would be too onerous. * * This software is provided ``AS IS'' without any warranties of any kind. * *//* * Implement IP packet firewall */#include <sys/param.h>#include <sys/systm.h>#include <sys/malloc.h>#include <sys/mbuf.h>#include <sys/queue.h>#include <sys/kernel.h>#if 0 /* XXX -current, but not -stable */#include <sys/sysctl.h>#endif#include <net/if.h>#include <netinet/in.h>#include <netinet/in_systm.h>#include <netinet/ip.h>#include <netinet/tcp.h>#include <netinet/udp.h>#include <netinet/ip_icmp.h>#include <netinet/ip_fw.h>static int fw_debug = 1;#ifdef IPFIREWALL_VERBOSEstatic int fw_verbose = 1;#elsestatic int fw_verbose = 0;#endif#ifdef IPFIREWALL_VERBOSE_LIMITstatic int fw_verbose_limit = IPFIREWALL_VERBOSE_LIMIT;#elsestatic int fw_verbose_limit = 0;#endifLIST_HEAD (ip_fw_head, ip_fw_chain) ip_fw_chain;#ifdef SYSCTL_NODESYSCTL_NODE(net_inet_ip, OID_AUTO, fw, CTLFLAG_RW, 0, "Firewall");SYSCTL_INT(net_inet_ip_fw, OID_AUTO, debug, CTLFLAG_RW, &fw_debug, 0, "");SYSCTL_INT(net_inet_ip_fw, OID_AUTO, verbose, CTLFLAG_RW, &fw_verbose, 0, "");SYSCTL_INT(net_inet_ip_fw, OID_AUTO, verbose_limit, CTLFLAG_RW, &fw_verbose_limit, 0, "");#endif#define dprintf(a)	if (!fw_debug); else printf a#define print_ip(a)	 printf("%ld.%ld.%ld.%ld",(ntohl(a.s_addr)>>24)&0xFF,\				 		  (ntohl(a.s_addr)>>16)&0xFF,\						  (ntohl(a.s_addr)>>8)&0xFF,\						  (ntohl(a.s_addr))&0xFF);#define dprint_ip(a)	if (!fw_debug); else print_ip(a)static int	add_entry __P((struct ip_fw_head *chainptr, struct ip_fw *frwl));static int	del_entry __P((struct ip_fw_head *chainptr, struct ip_fw *frwl));static int	zero_entry __P((struct mbuf *m));static struct ip_fw *		check_ipfw_struct __P(( struct mbuf *m));static int	ipopts_match __P((struct ip *ip, struct ip_fw *f));static int	port_match __P((u_short *portptr, int nports, u_short port,				int range_flag));static int	tcpflg_match __P((struct tcphdr *tcp, struct ip_fw *f));static void	ipfw_report __P((char *txt, int rule, struct ip *ip, int counter));/* * Returns 1 if the port is matched by the vector, 0 otherwise */static inline int port_match(portptr, nports, port, range_flag)	u_short *portptr;	int nports;	u_short port;	int range_flag;{	if (!nports)		return 1;	if (range_flag) {		if (portptr[0] <= port && port <= portptr[1]) {			return 1;		}		nports -= 2;		portptr += 2;	}	while (nports-- > 0) {		if (*portptr++ == port) {			return 1;		}	}	return 0;}static inttcpflg_match(tcp, f)	struct tcphdr		*tcp;	struct ip_fw		*f;{	u_char		flg_set, flg_clr;		if ((f->fw_tcpf & IP_FW_TCPF_ESTAB) &&	    (tcp->th_flags & (IP_FW_TCPF_RST | IP_FW_TCPF_ACK)))		return 1;	flg_set = tcp->th_flags & f->fw_tcpf;	flg_clr = tcp->th_flags & f->fw_tcpnf;	if (flg_set != f->fw_tcpf)		return 0;	if (flg_clr)		return 0;	return 1;}static inticmptype_match(struct icmp *icmp, struct ip_fw *f){	int type;	if (!(f->fw_flg & IP_FW_F_ICMPBIT))		return(1);	type = icmp->icmp_type;	/* check for matching type in the bitmap */	if (f->fw_icmptypes[type / (sizeof(unsigned) * 8)] & 		(1U << (type % (8 * sizeof(unsigned)))))		return(1);	return(0); /* no match */}static intipopts_match(ip, f)	struct ip 	*ip;	struct ip_fw	*f;{	register u_char *cp;	int opt, optlen, cnt;	u_char	opts, nopts, nopts_sve;	cp = (u_char *)(ip + 1);	cnt = (ip->ip_hl << 2) - sizeof (struct ip);	opts = f->fw_ipopt;	nopts = nopts_sve = f->fw_ipnopt;	for (; cnt > 0; cnt -= optlen, cp += optlen) {		opt = cp[IPOPT_OPTVAL];		if (opt == IPOPT_EOL)			break;		if (opt == IPOPT_NOP)			optlen = 1;		else {			optlen = cp[IPOPT_OLEN];			if (optlen <= 0 || optlen > cnt) {				return 0; /*XXX*/			}		}		switch (opt) {		default:			break;		case IPOPT_LSRR:			opts &= ~IP_FW_IPOPT_LSRR;			nopts &= ~IP_FW_IPOPT_LSRR;			break;		case IPOPT_SSRR:			opts &= ~IP_FW_IPOPT_SSRR;			nopts &= ~IP_FW_IPOPT_SSRR;			break;		case IPOPT_RR:			opts &= ~IP_FW_IPOPT_RR;			nopts &= ~IP_FW_IPOPT_RR;			break;		case IPOPT_TS:			opts &= ~IP_FW_IPOPT_TS;			nopts &= ~IP_FW_IPOPT_TS;			break;		}		if (opts == nopts)			break;	}	if (opts == 0 && nopts == nopts_sve)		return 1;	else		return 0;}static voidipfw_report(char *txt, int rule, struct ip *ip, int counter){	struct tcphdr *tcp = (struct tcphdr *) ((u_long *) ip + ip->ip_hl);	struct udphdr *udp = (struct udphdr *) ((u_long *) ip + ip->ip_hl);	struct icmp *icmp = (struct icmp *) ((u_long *) ip + ip->ip_hl);	if (!fw_verbose)		return;	if (fw_verbose_limit != 0 && counter > fw_verbose_limit)		return;	printf("ipfw: %d %s ",rule, txt);	switch (ip->ip_p) {	case IPPROTO_TCP:		printf("TCP ");		print_ip(ip->ip_src);		printf(":%d ", ntohs(tcp->th_sport));		print_ip(ip->ip_dst);		printf(":%d", ntohs(tcp->th_dport));		break;	case IPPROTO_UDP:		printf("UDP ");		print_ip(ip->ip_src);		printf(":%d ", ntohs(udp->uh_sport));		print_ip(ip->ip_dst);		printf(":%d", ntohs(udp->uh_dport));		break;	case IPPROTO_ICMP:		printf("ICMP:%u.%u ", icmp->icmp_type, icmp->icmp_code);		print_ip(ip->ip_src);		printf(" ");		print_ip(ip->ip_dst);		break;	default:		printf("P:%d ", ip->ip_p);		print_ip(ip->ip_src);		printf(" ");		print_ip(ip->ip_dst);		break;	}	if ((ip->ip_off & IP_OFFMASK)) 		printf(" Fragment = %d",ip->ip_off & IP_OFFMASK);	printf("\n");}/* * Returns 1 if it should be accepted, 0 otherwise. */int ip_fw_chk(m, ip, rif, dir)	struct mbuf *m;	struct ip *ip;	struct ifnet *rif;	int dir;{	struct ip_fw_chain *chain;	register struct ip_fw *f = NULL;	struct tcphdr *tcp = (struct tcphdr *) ((u_long *) ip + ip->ip_hl);	struct udphdr *udp = (struct udphdr *) ((u_long *) ip + ip->ip_hl);	struct icmp *icmp = (struct icmp *) ((u_long *) ip + ip->ip_hl);	struct ifaddr *ia = NULL, *ia_p;	struct in_addr src, dst, ia_i;	u_short src_port = 0, dst_port = 0;	u_short f_prt = 0, prt, len = 0;	/*	 * ... else if non-zero, highly unusual and interesting, but 	 * we're not going to pass it...	 */	if ((ip->ip_off & IP_OFFMASK) == 1) {		static int frag_counter = 0;		++frag_counter;		ipfw_report("Refuse", -1, ip, frag_counter);		m_freem(m);		return 0;	}	src = ip->ip_src;	dst = ip->ip_dst;	/*	 * If we got interface from which packet came-store pointer to it's	 * first adress	 */	if (rif != NULL)		ia = rif->if_addrlist;	/*	 * Determine the protocol and extract some useful stuff	 */	switch (ip->ip_p) {	case IPPROTO_TCP:		src_port = ntohs(tcp->th_sport);		dst_port = ntohs(tcp->th_dport);		prt = IP_FW_F_TCP;		len = sizeof (*tcp);		break;	case IPPROTO_UDP:		src_port = ntohs(udp->uh_sport);		dst_port = ntohs(udp->uh_dport);		prt = IP_FW_F_UDP;		len = sizeof (*udp);		break;	case IPPROTO_ICMP:		prt = IP_FW_F_ICMP;		len = sizeof (*icmp);		break;	default:		prt = IP_FW_F_ALL;		break;	}	/* XXX Check that we have sufficient header for TCP analysis */	/*	 * Go down the chain, looking for enlightment	 */	for (chain=ip_fw_chain.lh_first; chain; chain = chain->chain.le_next) {		f = chain->rule;		/* Check direction inbound */		if (!dir && !(f->fw_flg & IP_FW_F_IN))			continue;		/* Check direction outbound */		if (dir && !(f->fw_flg & IP_FW_F_OUT))			continue;		/* Fragments */		if ((f->fw_flg & IP_FW_F_FRAG) && !(ip->ip_off & IP_OFFMASK))			continue;		/* If src-addr doesn't match, not this rule. */		if ((src.s_addr & f->fw_smsk.s_addr) != f->fw_src.s_addr)			continue;		/* If dest-addr doesn't match, not this rule. */		if ((dst.s_addr & f->fw_dmsk.s_addr) != f->fw_dst.s_addr)			continue;		/* If a i/f name was specified, and we don't know */		if ((f->fw_flg & IP_FW_F_IFNAME) && !rif)			continue;		/* If a i/f name was specified, check it */		if ((f->fw_flg & IP_FW_F_IFNAME) && f->fw_via_name[0]) {			/* Not same unit, don't match */			if (!(f->fw_flg & IP_FW_F_IFUWILD) && rif->if_unit != f->fw_via_unit)				continue;			/* Not same name */			if (strncmp(rif->if_name, f->fw_via_name, FW_IFNLEN))				continue;		}		/* If a i/f addr was specified, check it */		if (!(f->fw_flg & IP_FW_F_IFNAME) && f->fw_via_ip.s_addr) {			int match = 0;			for (ia_p = ia; ia_p != NULL; ia_p = ia_p->ifa_next) {				if ((ia_p->ifa_addr == NULL))					continue;				if (ia_p->ifa_addr->sa_family != AF_INET)					continue;				ia_i.s_addr =				    ((struct sockaddr_in *)				    (ia_p->ifa_addr))->sin_addr.s_addr;				if (ia_i.s_addr != f->fw_via_ip.s_addr)					continue;				match = 1;				break;			}			if (!match)				continue;		}		/* 		 * Check IP options		 */		if (f->fw_ipopt != f->fw_ipnopt)			if (!ipopts_match(ip, f))				continue;					/*		 * Check protocol		 */

⌨️ 快捷键说明

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