Пример #1
0
/* IP input processing comes here for RAW socket delivery.
 * Caller owns SKB, so we must make clones.
 *
 * RFC 1122: SHOULD pass TOS value up to the transport layer.
 * -> It does. And not only TOS, but all IP header.
 */
static int raw_v4_input(struct sk_buff *skb, const struct iphdr *iph, int hash)
{
	struct sock *sk;
	struct hlist_head *head;
	int delivered = 0;
	struct net *net;

	read_lock(&raw_v4_hashinfo.lock);
	head = &raw_v4_hashinfo.ht[hash];
	if (hlist_empty(head))
		goto out;

	net = dev_net(skb->dev);
	sk = __raw_v4_lookup(net, __sk_head(head), iph->protocol,
			     iph->saddr, iph->daddr,
			     skb->dev->ifindex);

	while (sk) {
		delivered = 1;
		if (iph->protocol != IPPROTO_ICMP || !icmp_filter(sk, skb)) {
			struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC);

			/* Not releasing hash table! */
			if (clone)
				raw_rcv(sk, clone);
		}
		sk = __raw_v4_lookup(net, sk_next(sk), iph->protocol,
				     iph->saddr, iph->daddr,
				     skb->dev->ifindex);
	}
out:
	read_unlock(&raw_v4_hashinfo.lock);
	return delivered;
}
Пример #2
0
/* IP input processing comes here for RAW socket delivery.
 * Caller owns SKB, so we must make clones.
 *
 * RFC 1122: SHOULD pass TOS value up to the transport layer.
 * -> It does. And not only TOS, but all IP header.
 */
void raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash)
{
	struct sock *sk;
	struct hlist_head *head;

	read_lock(&raw_v4_lock);
	head = &raw_v4_htable[hash];
	if (hlist_empty(head))
		goto out;
	sk = __raw_v4_lookup(__sk_head(head), iph->protocol,
			     iph->saddr, iph->daddr,
			     skb->dev->ifindex);

	while (sk) {
		if (iph->protocol != IPPROTO_ICMP || !icmp_filter(sk, skb)) {
			struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC);

			/* Not releasing hash table! */
			if (clone)
				raw_rcv(sk, clone);
		}
		sk = __raw_v4_lookup(sk_next(sk), iph->protocol,
				     iph->saddr, iph->daddr,
				     skb->dev->ifindex);
	}
out:
	read_unlock(&raw_v4_lock);
}
Пример #3
0
/* IP input processing comes here for RAW socket delivery.
 * Caller owns SKB, so we must make clones.
 *
 * RFC 1122: SHOULD pass TOS value up to the transport layer.
 * -> It does. And not only TOS, but all IP header.
 */
static int raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash)
{
	struct sock *sk;
	struct hlist_head *head;
	int delivered = 0;
	struct net *net;

	read_lock(&raw_v4_hashinfo.lock);
	head = &raw_v4_hashinfo.ht[hash];
	if (hlist_empty(head))
		goto out;
	//head就是指向一个链表...该链表的结点都是protocol相同的struct sock...
	//然后遍历该链表来确定是否有哪个struct sock来处理该数据包啦..
	net = dev_net(skb->dev);
	sk = __raw_v4_lookup(net, __sk_head(head), iph->protocol, iph->saddr, iph->daddr, skb->dev->ifindex);

	while (sk) {
		//来到这里代表至少说有一个struct sock可以处理该数据包....因此设置返回值为1...
		delivered = 1;
		if (iph->protocol != IPPROTO_ICMP || !icmp_filter(sk, skb)) {
			struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC);

			/* Not releasing hash table! */
			if (clone)
				raw_rcv(sk, clone);
		}
		//可能存在多个struct sock同时处理一个数据包啦...主要还是看匹配规则(lookup)..
		//这里看到只是匹配协议/源地址/目的地址.
		sk = __raw_v4_lookup(net, sk_next(sk), iph->protocol, iph->saddr, iph->daddr, skb->dev->ifindex);
	}
out:
	read_unlock(&raw_v4_hashinfo.lock);
	return delivered;
}
Пример #4
0
/* IP input processing comes here for RAW socket delivery.
 * 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.
 */
struct sock *raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash)
{
	struct sock *sk;

	read_lock(&raw_v4_lock);
	if ((sk = raw_v4_htable[hash]) == NULL)
		goto out;
	sk = __raw_v4_lookup(sk, iph->protocol,
			     iph->saddr, iph->daddr,
			     skb->dev->ifindex);

	while (sk) {
		struct sock *sknext = __raw_v4_lookup(sk->next, iph->protocol,
						      iph->saddr, iph->daddr,
						      skb->dev->ifindex);
		if (iph->protocol != IPPROTO_ICMP ||
		    !icmp_filter(sk, skb)) {
			struct sk_buff *clone;

			if (!sknext)
				break;
			clone = skb_clone(skb, GFP_ATOMIC);
			/* Not releasing hash table! */
			if (clone)
				raw_rcv(sk, clone);
		}
		sk = sknext;
	}
out:
	if (sk)
		sock_hold(sk);
	read_unlock(&raw_v4_lock);

	return sk;
}
Пример #5
0
/*
 * 	Deliver IP Packets to the higher protocol layers.
 */ 
int ip_local_deliver(struct sk_buff *skb)
{
	struct iphdr *iph = skb->nh.iph;
	struct inet_protocol *ipprot;
	struct sock *raw_sk=NULL;
	unsigned char hash;
	int flag = 0;

#ifndef CONFIG_IP_ALWAYS_DEFRAG
	/*
	 *	Reassemble IP fragments.
	 */

	if (iph->frag_off & htons(IP_MF|IP_OFFSET)) {
		skb = ip_defrag(skb);
		if (!skb)
			return 0;
		iph = skb->nh.iph;
	}
#endif

#ifdef CONFIG_IP_MASQUERADE
	/*
	 * Do we need to de-masquerade this packet?
	 */
        {
		int ret = ip_fw_demasquerade(&skb);
		if (ret < 0) {
			kfree_skb(skb);
			return 0;
		}

		if (ret) {
			iph=skb->nh.iph;
			IPCB(skb)->flags |= IPSKB_MASQUERADED;
			dst_release(skb->dst);
			skb->dst = NULL;
			if (ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, skb->dev)) {
				kfree_skb(skb);
				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);
}