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

📄 ipchains_core.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	FWC_HAVE_LOCK(fwc_rlocks | fwc_wlocks);	for (tmp = ip_fw_chains; tmp; tmp = tmp->next)		if (strcmp(tmp->label,label) == 0)			break;	return tmp;}/* This function returns a boolean which when true sets answer to one   of the FW_*. */static int find_special(ip_chainlabel label, int *answer){	if (label[0] == '\0') {		*answer = FW_SKIP; /* => pass-through rule */		return 1;	} else if (strcmp(label,IP_FW_LABEL_ACCEPT) == 0) {		*answer = FW_ACCEPT;		return 1;	} else if (strcmp(label,IP_FW_LABEL_BLOCK) == 0) {		*answer = FW_BLOCK;		return 1;	} else if (strcmp(label,IP_FW_LABEL_REJECT) == 0) {		*answer = FW_REJECT;		return 1;	} else if (strcmp(label,IP_FW_LABEL_REDIRECT) == 0) {		*answer = FW_REDIRECT;		return 1;	} else if (strcmp(label,IP_FW_LABEL_MASQUERADE) == 0) {		*answer = FW_MASQUERADE;		return 1;	} else if (strcmp(label, IP_FW_LABEL_RETURN) == 0) {		*answer = FW_SKIP+1;		return 1;	} else {		return 0;	}}/* This function cleans up the prevchain and prevrule.  If the verbose * flag is set then he names of the chains will be printed as it * cleans up.  */static void cleanup(struct ip_chain *chain,		    const int verbose,		    unsigned int slot){	struct ip_chain *tmpchain = chain->reent[slot].prevchain;	if (verbose)		printk(KERN_ERR "Chain backtrace: ");	while (tmpchain) {		if (verbose)			printk("%s<-",chain->label);		chain->reent[slot].prevchain = NULL;		chain = tmpchain;		tmpchain = chain->reent[slot].prevchain;	}	if (verbose)		printk("%s\n",chain->label);}static inline intip_fw_domatch(struct ip_fwkernel *f,	      const char *rif,	      const ip_chainlabel label,	      struct sk_buff **pskb,	      unsigned int slot,	      __u16 src_port, __u16 dst_port,	      unsigned int count,	      int tcpsyn,	      unsigned char *tos){	f->counters[slot].bcnt+=ntohs((*pskb)->nh.iph->tot_len);	f->counters[slot].pcnt++;	if (f->ipfw.fw_flg & IP_FW_F_PRN) {		dump_packet(pskb,rif,f,label,src_port,dst_port,count,tcpsyn);	}	*tos = (*tos & f->ipfw.fw_tosand) ^ f->ipfw.fw_tosxor;/* This functionality is useless in stock 2.0.x series, but we don't * discard the mark thing altogether, to avoid breaking ipchains (and, * more importantly, the ipfwadm wrapper) --PR */	if (f->ipfw.fw_flg & IP_FW_F_MARKABS) {		(*pskb)->nfmark = f->ipfw.fw_mark;	} else {		(*pskb)->nfmark += f->ipfw.fw_mark;	}	if (f->ipfw.fw_flg & IP_FW_F_NETLINK) {#if defined(CONFIG_NETLINK_DEV) || defined(CONFIG_NETLINK_DEV_MODULE)		size_t len = min_t(unsigned int, f->ipfw.fw_outputsize, ntohs((*pskb)->nh.iph->tot_len))			+ sizeof(__u32) + sizeof((*pskb)->nfmark) + IFNAMSIZ;		struct sk_buff *outskb=alloc_skb(len, GFP_ATOMIC);		duprintf("Sending packet out NETLINK (length = %u).\n",			 (unsigned int)len);		if (outskb) {			/* Prepend length, mark & interface */			skb_put(outskb, len);			*((__u32 *)outskb->data) = (__u32)len;			*((__u32 *)(outskb->data+sizeof(__u32))) =				(*pskb)->nfmark;			strcpy(outskb->data+sizeof(__u32)*2, rif);			skb_copy_bits(*pskb,				((char *)(*pskb)->nh.iph - (char *)(*pskb)->data),				outskb->data+sizeof(__u32)*2+IFNAMSIZ,				len-(sizeof(__u32)*2+IFNAMSIZ));			netlink_broadcast(ipfwsk, outskb, 0, ~0, GFP_ATOMIC);		}		else {#endif			if (net_ratelimit())				printk(KERN_WARNING "ip_fw: packet drop due to "				       "netlink failure\n");			return 0;#if defined(CONFIG_NETLINK_DEV) || defined(CONFIG_NETLINK_DEV_MODULE)		}#endif	}	return 1;}/* *	Returns one of the generic firewall policies, like FW_ACCEPT. * *	The testing is either false for normal firewall mode or true for *	user checking mode (counters are not updated, TOS & mark not done). */static intip_fw_check(const char *rif,	    __u16 *redirport,	    struct ip_chain *chain,	    struct sk_buff **pskb,	    unsigned int slot,	    int testing){	__u32			src, dst;	__u16			src_port = 0xFFFF, dst_port = 0xFFFF;	char			tcpsyn=0;	__u16			offset;	unsigned char		tos;	struct ip_fwkernel	*f;	int			ret = FW_SKIP+2;	unsigned int		count;	/* We handle fragments by dealing with the first fragment as	 * if it was a normal packet.  All other fragments are treated	 * normally, except that they will NEVER match rules that ask	 * things we don't know, ie. tcp syn flag or ports).  If the	 * rule is also a fragment-specific rule, non-fragments won't	 * match it. */	offset = ntohs((*pskb)->nh.iph->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 && (*pskb)->nh.iph->protocol == IPPROTO_TCP) {		if (!testing && net_ratelimit()) {			printk("Suspect TCP fragment.\n");			dump_packet(pskb,rif,NULL,NULL,0,0,0,0);		}		return FW_BLOCK;	}	/* If we can't investigate ports, treat as fragment.  It's	 * either a trucated whole packet, or a truncated first	 * fragment, or a TCP first fragment of length 8-15, in which	 * case the above rule stops reassembly.	 */	if (offset == 0) {		unsigned int size_req;		switch ((*pskb)->nh.iph->protocol) {		case IPPROTO_TCP:			/* Don't care about things past flags word */			size_req = 16;			break;		case IPPROTO_UDP:		case IPPROTO_ICMP:			size_req = 8;			break;		default:			size_req = 0;		}		/* If it is a truncated first fragment then it can be		 * used to rewrite port information, and thus should		 * be blocked.		 */		if (ntohs((*pskb)->nh.iph->tot_len) <		    ((*pskb)->nh.iph->ihl<<2)+size_req) {			if (!testing && net_ratelimit()) {				printk("Suspect short first fragment.\n");				dump_packet(pskb,rif,NULL,NULL,0,0,0,0);			}			return FW_BLOCK;		}	}	src = (*pskb)->nh.iph->saddr;	dst = (*pskb)->nh.iph->daddr;	tos = (*pskb)->nh.iph->tos;	/*	 *	If we got interface from which packet came	 *	we can use the address directly. Linux 2.1 now uses address	 *	chains per device too, but unlike BSD we first check if the	 *	incoming packet matches a device address and the routing	 *	table before calling the firewall.	 */	dprintf("Packet ");	switch ((*pskb)->nh.iph->protocol) {		case IPPROTO_TCP:			dprintf("TCP ");			if (!offset) {				struct tcphdr tcph;				if (skb_copy_bits(*pskb,						  (*pskb)->nh.iph->ihl * 4,						  &tcph, sizeof(tcph)))					return FW_BLOCK;				src_port = ntohs(tcph.source);				dst_port = ntohs(tcph.dest);				/* Connection initilisation can only				 * be made when the syn bit is set and				 * neither of the ack or reset is				 * set. */				if (tcph.syn && !(tcph.ack || tcph.rst))					tcpsyn = 1;			}			break;		case IPPROTO_UDP:			dprintf("UDP ");			if (!offset) {				struct udphdr udph;				if (skb_copy_bits(*pskb,						  (*pskb)->nh.iph->ihl * 4,						  &udph, sizeof(udph)))					return FW_BLOCK;				src_port = ntohs(udph.source);				dst_port = ntohs(udph.dest);			}			break;		case IPPROTO_ICMP:			if (!offset) {				struct icmphdr icmph;				if (skb_copy_bits(*pskb,						  (*pskb)->nh.iph->ihl * 4,						  &icmph, sizeof(icmph)))					return FW_BLOCK;				src_port = (__u16) icmph.type;				dst_port = (__u16) icmph.code;			}			dprintf("ICMP ");			break;		default:			dprintf("p=%d ", (*pskb)->nh.iph->protocol);			break;	}#ifdef DEBUG_IP_FIREWALL	print_ip((*pskb)->nh.iph->saddr);	if (offset)		dprintf(":fragment (%i) ", ((int)offset)<<2);	else if ((*pskb)->nh.iph->protocol == IPPROTO_TCP ||		 (*pskb)->nh.iph->protocol == IPPROTO_UDP ||		 (*pskb)->nh.iph->protocol == IPPROTO_ICMP)		dprintf(":%hu:%hu", src_port, dst_port);	dprintf("\n");#endif	if (!testing) FWC_READ_LOCK(&ip_fw_lock);	else FWC_HAVE_LOCK(fwc_rlocks);	f = chain->chain;	do {		count = 0;		for (; f; f = f->next) {			count++;			if (ip_rule_match(f, rif, pskb,					  tcpsyn, src_port, dst_port,					  offset)) {				if (!testing				    && !ip_fw_domatch(f, rif, chain->label,						      pskb, slot,						      src_port, dst_port,						      count, tcpsyn, &tos)) {					ret = FW_BLOCK;					cleanup(chain, 0, slot);					goto out;				}				break;			}		}		if (f) {			if (f->branch) {				/* Do sanity check to see if we have                                 * already set prevchain and if so we                                 * must be in a loop */				if (f->branch->reent[slot].prevchain) {					if (!testing) {						printk(KERN_ERR						       "IP firewall: "						       "Loop detected "						       "at `%s'.\n",						       f->branch->label);						cleanup(chain, 1, slot);						ret = FW_BLOCK;					} else {						cleanup(chain, 0, slot);						ret = FW_SKIP+1;					}				}				else {					f->branch->reent[slot].prevchain						= chain;					f->branch->reent[slot].prevrule						= f->next;					chain = f->branch;					f = chain->chain;				}			}			else if (f->simplebranch == FW_SKIP)				f = f->next;			else if (f->simplebranch == FW_SKIP+1) {				/* Just like falling off the chain */				goto fall_off_chain;			} else {				cleanup(chain, 0, slot);				ret = f->simplebranch;			}		} /* f == NULL */		else {		fall_off_chain:			if (chain->reent[slot].prevchain) {				struct ip_chain *tmp = chain;				f = chain->reent[slot].prevrule;				chain = chain->reent[slot].prevchain;				tmp->reent[slot].prevchain = NULL;			}			else {				ret = chain->policy;				if (!testing) {					chain->reent[slot].counters.pcnt++;					chain->reent[slot].counters.bcnt						+= ntohs((*pskb)->nh.iph->tot_len);				}			}		}	} while (ret == FW_SKIP+2); out:	if (!testing) FWC_READ_UNLOCK(&ip_fw_lock);	/* Recalculate checksum if not going to reject, and TOS changed. */	if ((*pskb)->nh.iph->tos != tos	    && ret != FW_REJECT && ret != FW_BLOCK	    && !testing) {		if (!skb_ip_make_writable(pskb, offsetof(struct iphdr, tos)+1))			ret = FW_BLOCK;		else {			(*pskb)->nh.iph->tos = tos;			ip_send_check((*pskb)->nh.iph);		}	}	if (ret == FW_REDIRECT && redirport) {		if ((*redirport = htons(f->ipfw.fw_redirpt)) == 0) {			/* Wildcard redirection.			 * Note that redirport will become			 * 0xFFFF for non-TCP/UDP packets.			 */			*redirport = htons(dst_port);		}	}#ifdef DEBUG_ALLOW_ALL	return (testing ? ret : FW_ACCEPT);#else	return ret;#endif}/* Must have write lock & interrupts off for any of these *//* This function sets all the byte counters in a chain to zero.  The * input is a pointer to the chain required for zeroing */static int zero_fw_chain(struct ip_chain *chainptr){	struct ip_fwkernel *i;	FWC_HAVE_LOCK(fwc_wlocks);	for (i = chainptr->chain; i; i = i->next)		memset(i->counters, 0, sizeof(struct ip_counters)*NUM_SLOTS);	return 0;}static int clear_fw_chain(struct ip_chain *chainptr){	struct ip_fwkernel *i= chainptr->chain;	FWC_HAVE_LOCK(fwc_wlocks);	chainptr->chain=NULL;	while (i) {		struct ip_fwkernel *tmp = i->next;		if (i->branch)			i->branch->refcount--;		kfree(i);		i = tmp;		/* We will block in cleanup's unregister sockopt if unloaded,		   so this is safe. */		module_put(THIS_MODULE);	}	return 0;}static int replace_in_chain(struct ip_chain *chainptr,			    struct ip_fwkernel *frwl,			    __u32 position){	struct ip_fwkernel *f = chainptr->chain;	FWC_HAVE_LOCK(fwc_wlocks);	while (--position && f != NULL) f = f->next;	if (f == NULL)		return EINVAL;	if (f->branch) f->branch->refcount--;	if (frwl->branch) frwl->branch->refcount++;	frwl->next = f->next;	memcpy(f,frwl,sizeof(struct ip_fwkernel));	kfree(frwl);	return 0;}static int append_to_chain(struct ip_chain *chainptr, struct ip_fwkernel *rule){	struct ip_fwkernel *i;	FWC_HAVE_LOCK(fwc_wlocks);	/* Are we unloading now?  We will block on nf_unregister_sockopt */	if (!try_module_get(THIS_MODULE))		return ENOPROTOOPT;	/* Special case if no rules already present */	if (chainptr->chain == NULL) {		/* If pointer writes are atomic then turning off		 * interrupts is not necessary. */		chainptr->chain = rule;

⌨️ 快捷键说明

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