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

📄 ipfwadm_core.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Minor modifications to fit on compatibility framework:   Rusty.Russell@rustcorp.com.au*/#include <linux/config.h>#define CONFIG_IP_FIREWALL#define CONFIG_IP_FIREWALL_VERBOSE#define CONFIG_IP_MASQUERADE#define CONFIG_IP_ACCT#define CONFIG_IP_TRANSPARENT_PROXY#if defined(CONFIG_NETLINK_DEV) || defined(CONFIG_NETLINK_DEV_MODULE)#define CONFIG_IP_FIREWALL_NETLINK#endif/* *	IP firewalling code. This is taken from 4.4BSD. Please note the *	copyright message below. As per the GPL it must be maintained *	and the licenses thus do not conflict. While this port is subject *	to the GPL I also place my modifications under the original *	license in recognition of the original copyright. *				-- Alan Cox. * *	$Id: ipfwadm_core.c,v 1.9.2.2 2002/01/24 15:50:42 davem Exp $ * *	Ported from BSD to Linux, *		Alan Cox 22/Nov/1994. *	Zeroing /proc and other additions *		Jos Vos 4/Feb/1995. *	Merged and included the FreeBSD-Current changes at Ugen's request *	(but hey it's a lot cleaner now). Ugen would prefer in some ways *	we waited for his final product but since Linux 1.2.0 is about to *	appear it's not practical - Read: It works, it's not clean but please *	don't consider it to be his standard of finished work. *		Alan Cox 12/Feb/1995 *	Porting bidirectional entries from BSD, fixing accounting issues, *	adding struct ip_fwpkt for checking packets with interface address *		Jos Vos 5/Mar/1995. *	Established connections (ACK check), ACK check on bidirectional rules, *	ICMP type check. *		Wilfred Mollenvanger 7/7/1995. *	TCP attack protection. *		Alan Cox 25/8/95, based on information from bugtraq. *	ICMP type printk, IP_FW_F_APPEND *		Bernd Eckenfels 1996-01-31 *	Split blocking chain into input and output chains, add new "insert" and *	"append" commands to replace semi-intelligent "add" command, let "delete". *	only delete the first matching entry, use 0xFFFF (0xFF) as ports (ICMP *	types) when counting packets being 2nd and further fragments. *		Jos Vos <jos@xos.nl> 8/2/1996. *	Add support for matching on device names. *		Jos Vos <jos@xos.nl> 15/2/1996. *	Transparent proxying support. *		Willy Konynenberg <willy@xos.nl> 10/5/96. *	Make separate accounting on incoming and outgoing packets possible. *		Jos Vos <jos@xos.nl> 18/5/1996. *	Added trap out of bad frames. *		Alan Cox <alan@cymru.net> 17/11/1996 * * * Masquerading functionality * * Copyright (c) 1994 Pauline Middelink * * The pieces which added masquerading functionality are totally * my responsibility and have nothing to with the original authors * copyright or doing. * * Parts distributed under GPL. * * Fixes: *	Pauline Middelink	:	Added masquerading. *	Alan Cox		:	Fixed an error in the merge. *	Thomas Quinot		:	Fixed port spoofing. *	Alan Cox		:	Cleaned up retransmits in spoofing. *	Alan Cox		:	Cleaned up length setting. *	Wouter Gadeyne		:	Fixed masquerading support of ftp PORT commands * *	Juan Jose Ciarlante	:	Masquerading code moved to ip_masq.c *	Andi Kleen :		Print frag_offsets and the ip flags properly. * *	All the real work was done by ..... * *//* * 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. */#include <asm/uaccess.h>#include <asm/system.h>#include <linux/types.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/string.h>#include <linux/errno.h>#include <linux/module.h>#include <linux/socket.h>#include <linux/sockios.h>#include <linux/in.h>#include <linux/inet.h>#include <linux/netdevice.h>#include <linux/icmp.h>#include <linux/udp.h>#include <net/ip.h>#include <net/protocol.h>#include <net/route.h>#include <net/tcp.h>#include <net/udp.h>#include <net/sock.h>#include <net/icmp.h>#include <linux/netlink.h>#include <linux/init.h>#include <linux/netfilter_ipv4/ipfwadm_core.h>#include <linux/netfilter_ipv4/compat_firewall.h>#include <net/checksum.h>#include <linux/proc_fs.h>#include <linux/stat.h>#include <linux/version.h>/* *	Implement IP packet firewall */#ifdef DEBUG_IP_FIREWALL#define dprintf1(a)		printk(a)#define dprintf2(a1,a2)		printk(a1,a2)#define dprintf3(a1,a2,a3)	printk(a1,a2,a3)#define dprintf4(a1,a2,a3,a4)	printk(a1,a2,a3,a4)#else#define dprintf1(a)#define dprintf2(a1,a2)#define dprintf3(a1,a2,a3)#define dprintf4(a1,a2,a3,a4)#endif#define print_ip(a)	 printk("%u.%u.%u.%u", NIPQUAD(a));#ifdef DEBUG_IP_FIREWALL#define dprint_ip(a)	print_ip(a)#else#define dprint_ip(a)#endif#if defined(CONFIG_IP_ACCT) || defined(CONFIG_IP_FIREWALL)struct ip_fw *ip_fw_fwd_chain;struct ip_fw *ip_fw_in_chain;struct ip_fw *ip_fw_out_chain;struct ip_fw *ip_acct_chain;struct ip_fw *ip_masq_chain;static struct ip_fw **chains[] =	{&ip_fw_fwd_chain, &ip_fw_in_chain, &ip_fw_out_chain, &ip_acct_chain,	 &ip_masq_chain	};#endif /* CONFIG_IP_ACCT || CONFIG_IP_FIREWALL */#ifdef CONFIG_IP_FIREWALLint ip_fw_fwd_policy=IP_FW_F_ACCEPT;int ip_fw_in_policy=IP_FW_F_ACCEPT;int ip_fw_out_policy=IP_FW_F_ACCEPT;static int *policies[] =	{&ip_fw_fwd_policy, &ip_fw_in_policy, &ip_fw_out_policy};#endif#ifdef CONFIG_IP_FIREWALL_NETLINKstruct sock *ipfwsk;#endif/* *	Returns 1 if the port is matched by the vector, 0 otherwise */extern inline int port_match(unsigned short *portptr,int nports,unsigned 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);}#if defined(CONFIG_IP_ACCT) || defined(CONFIG_IP_FIREWALL)#ifdef CONFIG_IP_FIREWALL_VERBOSE/* *	VERY ugly piece of code which actually makes kernel printf for * 	matching packets. */static char *chain_name(struct ip_fw *chain, int mode){	switch (mode) {	case IP_FW_MODE_ACCT_IN: return "acct in";	case IP_FW_MODE_ACCT_OUT: return "acct out";	default:		if (chain == ip_fw_fwd_chain)			return "fw-fwd";		else if (chain == ip_fw_in_chain)			return "fw-in";		else			return "fw-out";	}}static char *rule_name(struct ip_fw *f, int mode, char *buf){	if (mode == IP_FW_MODE_ACCT_IN || mode == IP_FW_MODE_ACCT_OUT)		return "";	if(f->fw_flg&IP_FW_F_ACCEPT) {		if(f->fw_flg&IP_FW_F_REDIR) {			sprintf(buf, "acc/r%d ", f->fw_pts[f->fw_nsp+f->fw_ndp]);			return buf;		} else if(f->fw_flg&IP_FW_F_MASQ)			return "acc/masq ";		else			return "acc ";	} else if(f->fw_flg&IP_FW_F_ICMPRPL) {		return "rej ";	} else {		return "deny ";	}}static void print_packet(struct iphdr *ip,			 u16 src_port, u16 dst_port, u16 icmp_type,			 char *chain, char *rule, char *devname){	__u32 *opt = (__u32 *) (ip + 1);	int opti;	__u16 foff = ntohs(ip->frag_off);	printk(KERN_INFO "IP %s %s%s", chain, rule, devname);	switch(ip->protocol)	{	case IPPROTO_TCP:		printk(" TCP ");		break;	case IPPROTO_UDP:		printk(" UDP ");		break;	case IPPROTO_ICMP:		printk(" ICMP/%d ", icmp_type);		break;	default:		printk(" PROTO=%d ", ip->protocol);		break;	}	print_ip(ip->saddr);	if(ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP)		printk(":%hu", src_port);	printk(" ");	print_ip(ip->daddr);	if(ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP)		printk(":%hu", dst_port);	printk(" L=%hu S=0x%2.2hX I=%hu FO=0x%4.4hX T=%hu",	       ntohs(ip->tot_len), ip->tos, ntohs(ip->id),	       foff & IP_OFFSET, ip->ttl);	if (foff & IP_DF) printk(" DF=1");	if (foff & IP_MF) printk(" MF=1");	for (opti = 0; opti < (ip->ihl - sizeof(struct iphdr) / 4); opti++)		printk(" O=0x%8.8X", *opt++);	printk("\n");}#endif/* *	Returns one of the generic firewall policies, like FW_ACCEPT. *	Also does accounting so you can feed it the accounting chain. * *	The modes is either IP_FW_MODE_FW (normal firewall mode), *	IP_FW_MODE_ACCT_IN or IP_FW_MODE_ACCT_OUT (accounting mode, *	steps through the entire chain and handles fragments *	differently), or IP_FW_MODE_CHK (handles user-level check, *	counters are not updated). */int ip_fw_chk(struct iphdr *ip, struct net_device *rif, __u16 *redirport,	      struct ip_fw *chain, int policy, int mode){	struct ip_fw *f;	struct tcphdr		*tcp=(struct tcphdr *)((__u32 *)ip+ip->ihl);	struct udphdr		*udp=(struct udphdr *)((__u32 *)ip+ip->ihl);	struct icmphdr		*icmp=(struct icmphdr *)((__u32 *)ip+ip->ihl);	__u32			src, dst;	__u16			src_port=0xFFFF, dst_port=0xFFFF, icmp_type=0xFF;	unsigned short		f_prt=0, prt;	char			notcpsyn=0, notcpack=0, match;	unsigned short		offset;	int			answer;	unsigned char		tosand, tosxor;	/*	 *	If the chain is empty follow policy. The BSD one	 *	accepts anything giving you a time window while	 *	flushing and rebuilding the tables.	 */	src = ip->saddr;	dst = ip->daddr;	/*	 *	This way we handle fragmented packets.	 *	we ignore all fragments but the first one	 *	so the whole packet can't be reassembled.	 *	This way we relay on the full info which	 *	stored only in first packet.	 *	 *	Note that this theoretically allows partial packet	 *	spoofing. Not very dangerous but paranoid people may	 *	wish to play with this. It also allows the so called	 *	"fragment bomb" denial of service attack on some types	 *	of system.	 */	offset = ntohs(ip->frag_off) & IP_OFFSET;	/*	 *	Don't allow a fragment of TCP 8 bytes in. Nobody	 *	normal causes this. Its a cracker trying to break	 *	in by doing a flag overwrite to pass the direction	 *	checks.	 */	if (offset == 1 && ip->protocol == IPPROTO_TCP)		return FW_BLOCK;	if (offset!=0 && !(mode & (IP_FW_MODE_ACCT_IN|IP_FW_MODE_ACCT_OUT)) &&		(ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP ||			ip->protocol == IPPROTO_ICMP))		return FW_ACCEPT;	/*	 *	 Header fragment for TCP is too small to check the bits.	 */	if(ip->protocol==IPPROTO_TCP && (ip->ihl<<2)+16 > ntohs(ip->tot_len))		return FW_BLOCK;	/*	 *	Too short.	 *	 *	But only too short for a packet with ports...	 */	else if((ntohs(ip->tot_len)<8+(ip->ihl<<2))&&(ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP))		return FW_BLOCK;	src = ip->saddr;	dst = ip->daddr;	/*	 *	If we got interface from which packet came	 *	we can use the address directly. This is unlike	 *	4.4BSD derived systems that have an address chain	 *	per device. We have a device per address with dummy	 *	devices instead.	 */	dprintf1("Packet ");	switch(ip->protocol)	{		case IPPROTO_TCP:			dprintf1("TCP ");			/* ports stay 0xFFFF if it is not the first fragment */			if (!offset) {				src_port=ntohs(tcp->source);				dst_port=ntohs(tcp->dest);				if(!tcp->ack && !tcp->rst)					/* We do NOT have ACK, value TRUE */					notcpack=1;				if(!tcp->syn || !notcpack)					/* We do NOT have SYN, value TRUE */					notcpsyn=1;			}			prt=IP_FW_F_TCP;			break;		case IPPROTO_UDP:			dprintf1("UDP ");			/* ports stay 0xFFFF if it is not the first fragment */			if (!offset) {				src_port=ntohs(udp->source);				dst_port=ntohs(udp->dest);			}			prt=IP_FW_F_UDP;			break;		case IPPROTO_ICMP:			/* icmp_type stays 255 if it is not the first fragment */			if (!offset)				icmp_type=(__u16)(icmp->type);			dprintf2("ICMP:%d ",icmp_type);			prt=IP_FW_F_ICMP;			break;		default:			dprintf2("p=%d ",ip->protocol);			prt=IP_FW_F_ALL;			break;	}#ifdef DEBUG_IP_FIREWALL	dprint_ip(ip->saddr);	if (ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP)		/* This will print 65535 when it is not the first fragment! */		dprintf2(":%d ", src_port);	dprint_ip(ip->daddr);	if (ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP)		/* This will print 65535 when it is not the first fragment! */		dprintf2(":%d ",dst_port);	dprintf1("\n");#endif	for (f=chain;f;f=f->fw_next)	{		/*		 *	This is a bit simpler as we don't have to walk		 *	an interface chain as you do in BSD - same logic		 *	however.		 */		/*		 *	Match can become 0x01 (a "normal" match was found),		 *	0x02 (a reverse match was found), and 0x03 (the		 *	IP addresses match in both directions).		 *	Now we know in which direction(s) we should look

⌨️ 快捷键说明

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