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

📄 ip_input.c

📁 GNU Hurd 源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
				return 0;			}			return skb->dst->input(skb);		}        }#endif        /*	 *	Point into the IP datagram, just past the header.	 */        skb->h.raw = skb->nh.raw + iph->ihl*4;	/*	 *	Deliver to raw sockets. This is fun as to avoid copies we want to make no 	 *	surplus copies.	 *	 *	RFC 1122: SHOULD pass TOS value up to the transport layer.	 *	-> It does. And not only TOS, but all IP header.	 */ 	/* Note: See raw.c and net/raw.h, RAWV4_HTABLE_SIZE==MAX_INET_PROTOS */	hash = iph->protocol & (MAX_INET_PROTOS - 1);	/* 	 *	If there maybe a raw socket we must check - if not we don't care less 	 */		 	if((raw_sk = raw_v4_htable[hash]) != NULL) {		struct sock *sknext = NULL;		struct sk_buff *skb1;		raw_sk = raw_v4_lookup(raw_sk, iph->protocol, iph->saddr, iph->daddr, skb->dev->ifindex);		if(raw_sk) {	/* Any raw sockets */			do {				/* Find the next */				sknext = raw_v4_lookup(raw_sk->next, iph->protocol,						       iph->saddr, iph->daddr, skb->dev->ifindex);				if (iph->protocol != IPPROTO_ICMP || !icmp_filter(raw_sk, skb)) {					if (sknext == NULL)						break;					skb1 = skb_clone(skb, GFP_ATOMIC);					if(skb1)					{						raw_rcv(raw_sk, skb1);					}				}				raw_sk = sknext;			} while(raw_sk!=NULL);							/*	Here either raw_sk is the last raw socket, or NULL if			 *	none.  We deliver to the last raw socket AFTER the			 *	protocol checks as it avoids a surplus copy.			 */		}	}		/*	 *	skb->h.raw now points at the protocol beyond the IP header.	 */		for (ipprot = (struct inet_protocol *)inet_protos[hash];ipprot != NULL;ipprot=(struct inet_protocol *)ipprot->next)	{		struct sk_buff *skb2;			if (ipprot->protocol != iph->protocol)			continue;		/*		 * 	See if we need to make a copy of it.  This will		 * 	only be set if more than one protocol wants it.		 * 	and then not for the last one. If there is a pending		 *	raw delivery wait for that		 */			if (ipprot->copy || raw_sk)		{			skb2 = skb_clone(skb, GFP_ATOMIC);			if(skb2==NULL)				continue;		}		else		{			skb2 = skb;		}		flag = 1;		/*		 *	Pass on the datagram to each protocol that wants it,		 *	based on the datagram protocol.  We should really		 *	check the protocol handler's return values here...		 */		ipprot->handler(skb2, ntohs(iph->tot_len) - (iph->ihl * 4));	}	/*	 *	All protocols checked.	 *	If this packet was a broadcast, we may *not* reply to it, since that	 *	causes (proven, grin) ARP storms and a leakage of memory (i.e. all	 *	ICMP reply messages get queued up for transmission...)	 */	if(raw_sk!=NULL)	/* Shift to last raw user */	{		raw_rcv(raw_sk, skb);	}	else if (!flag)		/* Free and report errors */	{		icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0);			kfree_skb(skb);	}	return(0);}/* * 	Main IP Receive routine. */ int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt){	struct iphdr *iph = skb->nh.iph;#ifdef	CONFIG_FIREWALL	int fwres;	u16 rport;#endif /* CONFIG_FIREWALL */	/*	 * 	When the interface is in promisc. mode, drop all the crap	 * 	that it receives, do not try to analyse it.	 */	if (skb->pkt_type == PACKET_OTHERHOST)		goto drop;	ip_statistics.IpInReceives++;	/*	 *	RFC1122: 3.1.2.2 MUST silently discard any IP frame that fails the checksum.	 *	 *	Is the datagram acceptable?	 *	 *	1.	Length at least the size of an ip header	 *	2.	Version of 4	 *	3.	Checksums correctly. [Speed optimisation for later, skip loopback checksums]	 *	4.	Doesn't have a bogus length	 */	if (skb->len < sizeof(struct iphdr))		goto inhdr_error; 	if (skb->len < (iph->ihl << 2))		goto inhdr_error;	if (iph->ihl < 5 || iph->version != 4 || ip_fast_csum((u8 *)iph, iph->ihl) != 0)		goto inhdr_error; 	{	__u32 len = ntohs(iph->tot_len); 	if (skb->len < len)		goto inhdr_error; 	if (len <  (iph->ihl << 2))		goto inhdr_error; 	/*	 *	Our transport medium may have padded the buffer out. Now we know it	 *	is IP we can trim to the true length of the frame.	 *	Note this now means skb->len holds ntohs(iph->tot_len).	 */	__skb_trim(skb, len);	}		/* Won't send ICMP reply, since skb->dst == NULL. --RR */        if (sysctl_ip_always_defrag != 0 &&            iph->frag_off & htons(IP_MF|IP_OFFSET)) {		skb = ip_defrag(skb);		if (!skb)			return 0;		iph = skb->nh.iph;		ip_send_check(iph);	}#ifdef CONFIG_FIREWALL	/*	 *	See if the firewall wants to dispose of the packet. 	 *	 * We can't do ICMP reply or local delivery before routing,	 * so we delay those decisions until after route. --RR	 */	fwres = call_in_firewall(PF_INET, dev, iph, &rport, &skb);	if (fwres < FW_ACCEPT && fwres != FW_REJECT)		goto drop;	iph = skb->nh.iph;#endif /* CONFIG_FIREWALL */	/*	 *	Initialise the virtual path cache for the packet. It describes	 *	how the packet travels inside Linux networking.	 */ 	if (skb->dst == NULL) {		if (ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, dev))			goto drop; #ifdef CONFIG_CPU_IS_SLOW		if (net_cpu_congestion > 10 && !(iph->tos&IPTOS_RELIABILITY) &&		    IPTOS_PREC(iph->tos) < IPTOS_PREC_INTERNETCONTROL) {			goto drop;		}#endif	}#ifdef CONFIG_NET_CLS_ROUTE	if (skb->dst->tclassid) {		u32 idx = skb->dst->tclassid;		ip_rt_acct[idx&0xFF].o_packets++;		ip_rt_acct[idx&0xFF].o_bytes+=skb->len;		ip_rt_acct[(idx>>16)&0xFF].i_packets++;		ip_rt_acct[(idx>>16)&0xFF].i_bytes+=skb->len;	}#endif	if (iph->ihl > 5) {		struct ip_options *opt;		/* It looks as overkill, because not all		   IP options require packet mangling.		   But it is the easiest for now, especially taking		   into account that combination of IP options		   and running sniffer is extremely rare condition.		                                      --ANK (980813)		*/		skb = skb_cow(skb, skb_headroom(skb));		if (skb == NULL)			return 0;		iph = skb->nh.iph;		skb->ip_summed = 0;		if (ip_options_compile(NULL, skb))			goto inhdr_error;		opt = &(IPCB(skb)->opt);		if (opt->srr) {			struct in_device *in_dev = dev->ip_ptr;			if (in_dev && !IN_DEV_SOURCE_ROUTE(in_dev)) {				if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit())					printk(KERN_INFO "source route option %d.%d.%d.%d -> %d.%d.%d.%d\n",					       NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));				goto drop;			}			if (ip_options_rcv_srr(skb))				goto drop;		}	}#ifdef CONFIG_FIREWALL#ifdef	CONFIG_IP_TRANSPARENT_PROXY	if (fwres == FW_REDIRECT && (IPCB(skb)->redirport = rport) != 0)		return ip_local_deliver(skb);#endif /* CONFIG_IP_TRANSPARENT_PROXY */	if (fwres == FW_REJECT) {		icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);		goto drop;	}#endif /* CONFIG_FIREWALL */	return skb->dst->input(skb);inhdr_error:	ip_statistics.IpInHdrErrors++;drop:        kfree_skb(skb);        return(0);}

⌨️ 快捷键说明

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