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

📄 ipchains_core.c

📁 上传linux-jx2410的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/*	This function returns a pointer to the first chain with a label *	that matches the one given. */static struct ip_chain *find_label(ip_chainlabel label){	struct ip_chain *tmp;	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,	      struct iphdr *ip,	      const char *rif,	      const ip_chainlabel label,	      struct sk_buff *skb,	      unsigned int slot,	      __u16 src_port, __u16 dst_port,	      unsigned int count,	      int tcpsyn){	f->counters[slot].bcnt+=ntohs(ip->tot_len);	f->counters[slot].pcnt++;	if (f->ipfw.fw_flg & IP_FW_F_PRN) {		dump_packet(ip,rif,f,label,src_port,dst_port,count,tcpsyn);	}	ip->tos = (ip->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) {		skb->nfmark = f->ipfw.fw_mark;	} else {		skb->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(ip->tot_len))			+ sizeof(__u32) + sizeof(skb->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))) = skb->nfmark;			strcpy(outskb->data+sizeof(__u32)*2, rif);			memcpy(outskb->data+sizeof(__u32)*2+IFNAMSIZ, ip,			       len-(sizeof(__u32)*2+IFNAMSIZ));			netlink_broadcast(ipfwsk, outskb, 0, ~0, GFP_KERNEL);		}		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(struct iphdr *ip,	    const char *rif,	    __u16 *redirport,	    struct ip_chain *chain,	    struct sk_buff *skb,	    unsigned int slot,	    int testing){	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;	char			tcpsyn=0;	__u16			offset;	unsigned char		oldtos;	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(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)	{		if (!testing && net_ratelimit()) {			printk("Suspect TCP fragment.\n");			dump_packet(ip,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 (ip->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(ip->tot_len) < (ip->ihl<<2)+size_req) {			if (!testing && net_ratelimit()) {				printk("Suspect short first fragment.\n");				dump_packet(ip,rif,NULL,NULL,0,0,0,0);			}			return FW_BLOCK;		}	}	src = ip->saddr;	dst = ip->daddr;	oldtos = ip->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(ip->protocol)	{		case IPPROTO_TCP:			dprintf("TCP ");			if (!offset) {				src_port=ntohs(tcp->source);				dst_port=ntohs(tcp->dest);				/* Connection initilisation can only				 * be made when the syn bit is set and				 * neither of the ack or reset is				 * set. */				if(tcp->syn && !(tcp->ack || tcp->rst))					tcpsyn=1;			}			break;		case IPPROTO_UDP:			dprintf("UDP ");			if (!offset) {				src_port=ntohs(udp->source);				dst_port=ntohs(udp->dest);			}			break;		case IPPROTO_ICMP:			if (!offset) {				src_port=(__u16)icmp->type;				dst_port=(__u16)icmp->code;			}			dprintf("ICMP ");			break;		default:			dprintf("p=%d ",ip->protocol);			break;	}#ifdef DEBUG_IP_FIREWALL	print_ip(ip->saddr);	if (offset)		dprintf(":fragment (%i) ", ((int)offset)<<2);	else if (ip->protocol==IPPROTO_TCP || ip->protocol==IPPROTO_UDP		 || ip->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,ip,					  tcpsyn,src_port,dst_port,offset)) {				if (!testing				    && !ip_fw_domatch(f, ip, rif, chain->label,						      skb, slot,						      src_port, dst_port,						      count, tcpsyn)) {					ret = FW_BLOCK;					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(ip->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 (ip->tos != oldtos	    && ret != FW_REJECT && ret != FW_BLOCK	    && !testing)		ip_send_check(ip);	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;		MOD_DEC_USE_COUNT;	}	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);	/* 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;		if (rule->branch) rule->branch->refcount++;		goto append_successful;	}	/* Find the rule before the end of the chain */	for (i = chainptr->chain; i->next; i = i->next);	i->next = rule;	if (rule->branch) rule->branch->refcount++;append_successful:	MOD_INC_USE_COUNT;	return 0;}/* This function inserts a rule at the position of position in the

⌨️ 快捷键说明

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