patch-2.1.30 linux/net/ipv6/ipv6_input.c

Next file: linux/net/ipv6/ipv6_output.c
Previous file: linux/net/ipv6/ip6_output.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.29/linux/net/ipv6/ipv6_input.c linux/net/ipv6/ipv6_input.c
@@ -1,445 +0,0 @@
-/*
- *	IPv6 input
- *	Linux INET6 implementation 
- *
- *	Authors:
- *	Pedro Roque		<roque@di.fc.ul.pt>
- *	Ian P. Morris		<I.P.Morris@soton.ac.uk>
- *
- *	Based in linux/net/ipv4/ip_input.c
- *
- *	$Id: ipv6_input.c,v 1.4 1997/02/28 09:56:33 davem Exp $
- *
- *	This program is free software; you can redistribute it and/or
- *      modify it under the terms of the GNU General Public License
- *      as published by the Free Software Foundation; either version
- *      2 of the License, or (at your option) any later version.
- */
-
-
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/sched.h>
-#include <linux/net.h>
-#include <linux/netdevice.h>
-#include <linux/in6.h>
-#include <linux/icmpv6.h>
-
-#include <net/sock.h>
-#include <net/snmp.h>
-
-#include <net/ipv6.h>
-#include <net/protocol.h>
-#include <net/transp_v6.h>
-#include <net/rawv6.h>
-#include <net/ndisc.h>
-#include <net/ipv6_route.h>
-#include <net/addrconf.h>
-
-/*
- *	Header processing function list
- *	We process headers in order (as per RFC)
- *	If the processing function returns 0 the packet is considered 
- *	delivered else it returns the value of the nexthdr.
- *	The ptr field of the function points to the previous nexthdr field.
- *	This is allows the processing function to change it if it's sematics
- *	is: return a new packet without this header (like fragmentation).
- *	When a next_header value is not within the list 
- *	the inet protocol list is searched (i.e. to deliver to 
- *	TCP for instance)
- */
-
-static int ipv6_dest_opt(struct sk_buff **skb_ptr, struct device *dev, __u8 *nhptr,
-			 struct ipv6_options *opt);
-
-
-struct hdrtype_proc {
-	u8	type;
-	int	(*func) (struct sk_buff **, struct device *dev, __u8 *ptr,
-			 struct ipv6_options *opt);
-} hdrproc_lst[] = {
-  /*
-	TODO
-
-	{NEXTHDR_HOP,		ipv6_hop_by_hop}
-   */
-	{NEXTHDR_ROUTING,	ipv6_routing_header},
-	{NEXTHDR_FRAGMENT,	ipv6_reassembly},
-  
-	{NEXTHDR_DEST,		ipv6_dest_opt},
-   /*	
-	{NEXTHDR_AUTH,		ipv6_auth_hdr},
-	{NEXTHDR_ESP,		ipv6_esp_hdr},
-    */
-	{NEXTHDR_MAX,		NULL}
-};
-
-/* New header structures */
-
-
-struct ipv6_tlvtype {
-	u8 type;
-	u8 len;
-};
-
-struct ipv6_destopt_hdr {
-	u8 nexthdr;
-	u8 hdrlen;
-};
-
-
-struct tlvtype_proc {
-	u8	type;
-	int	(*func) (struct sk_buff *, struct device *dev, __u8 *ptr,
-			 struct ipv6_options *opt); 
-	
-	/* these functions do NOT  update skb->h.raw */
-			 
-} tlvprocdestopt_lst[] = {
-	{255,			NULL}
-};
-
-
-static int parse_tlv(struct tlvtype_proc *procs, struct sk_buff *skb,
-		     struct device *dev, __u8 *nhptr, struct ipv6_options *opt,
-		     void *lastopt)
-{
-	struct ipv6_tlvtype *hdr;
-	struct tlvtype_proc *curr;
-	int pos;
-
-	while ((hdr=(struct ipv6_tlvtype *)skb->h.raw) != lastopt)
-		switch (hdr->type & 0x3F)
-		{
-		case 0: /* TLV encoded Pad1 */
-			skb->h.raw++;
-			break;
-
-		case 1: /* TLV encoded PadN */
-			skb->h.raw += hdr->len+2;
-			break;
-
-		default: /* Other TLV code so scan list */
-			for (curr=procs; curr->type != 255; curr++)
-				if (curr->type == (hdr->type & 0x3F))
-				{
-					curr->func(skb, dev, nhptr, opt);
-					skb->h.raw += hdr->len+2;
-					break;
-				}
-		
-			if (curr->type==255)
-			{ 
-				/* unkown type */
-				pos= (__u8 *) skb->h.raw - (__u8 *) skb->nh.raw;
-				/* I think this is correct please check - IPM */
-
-				switch ((hdr->type & 0xC0) >> 6) {
-					case 0: /* ignore */
-						skb->h.raw += hdr->len+2;
-						break;
-						
-					case 1: /* drop packet */
-						kfree_skb(skb, FREE_READ);
-						return 0;
-
-					case 2: /* send ICMP PARM PROB regardless and 
-						   drop packet */
-						icmpv6_send(skb, ICMPV6_PARAMETER_PROB, 
-							    2, pos, dev);
-						kfree_skb(skb, FREE_READ);
-						return 0;
-
-					case 3: /* Send ICMP if not a multicast address 
-						   and drop packet */
-						if (!(ipv6_addr_type(&(skb->nh.ipv6h->daddr)) & IPV6_ADDR_MULTICAST) )
-							icmpv6_send(skb, ICMPV6_PARAMETER_PROB, 2, pos, dev);
-						kfree_skb(skb, FREE_READ);
-						return 0;
-					}
-			}
-			break;
-		}
-	
-	return 1;
-}
- 
-
-
-static int ipv6_dest_opt(struct sk_buff **skb_ptr, struct device *dev, __u8 *nhptr,
-			 struct ipv6_options *opt)
-{
-	struct sk_buff *skb=*skb_ptr;
-	struct ipv6_destopt_hdr *hdr = (struct ipv6_destopt_hdr *) skb->h.raw;
-	
-	if (parse_tlv(tlvprocdestopt_lst, skb, dev, nhptr, opt,skb->h.raw+hdr->hdrlen))
-		return hdr->nexthdr;
-	else
-		return 0;
-}
-
-
-
-/*
- *	0 - deliver
- *	1 - block
- */
-static __inline__ int icmpv6_filter(struct sock *sk, struct sk_buff *skb)
-{
-	struct icmpv6hdr *icmph;
-	struct raw6_opt *opt;
-
-	opt = &sk->tp_pinfo.tp_raw;
-	icmph = (struct icmpv6hdr *) (skb->nh.ipv6h + 1);
-	return test_bit(icmph->type, &opt->filter);
-}
-
-/*
- *	demultiplex raw sockets.
- *	(should consider queueing the skb in the sock receive_queue
- *	without calling rawv6.c)
- */
-static struct sock * ipv6_raw_deliver(struct sk_buff *skb,
-				      struct device *dev,
-				      struct ipv6_options *opt,
-				      __u16 nexthdr,
-				      __u16 len,
-				      struct in6_addr *saddr,
-				      struct in6_addr *daddr)
-{
-	struct sock *sk, *sk2;
-	__u8 hash;
-
-	hash = nexthdr & (MAX_INET_PROTOS - 1);
-
-	sk = raw_v6_htable[hash];
-
-	/*
-	 *	The first socket found will be delivered after
-	 *	delivery to transport protocols.
-	 */
-
-	if (sk == NULL)
-		return NULL;
-	
-	sk = raw_v6_lookup(sk, nexthdr, daddr, saddr);
-
-	if (sk)
-	{
-		sk2 = sk;
-
-		while ((sk2 = raw_v6_lookup(sk2->next, nexthdr, daddr, saddr)))
-		{
-			struct sk_buff *buff;
-
-			if (nexthdr == IPPROTO_ICMPV6 &&
-			    icmpv6_filter(sk2, skb))
-			{
-				continue;
-			}
-			buff = skb_clone(skb, GFP_ATOMIC);
-			buff->sk = sk2;
-			rawv6_rcv(buff, dev, saddr, daddr, opt, len);
-		}
-	}
-
-	if (sk && nexthdr == IPPROTO_ICMPV6 && icmpv6_filter(sk, skb))
-	{
-		sk = NULL;
-	}   
-	
-	return sk;
-}
-
-int ipv6_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
-{
-	struct inet6_ifaddr	*ifp;
-	struct ipv6_options	*opt = (struct ipv6_options *) skb->cb;
-	struct ipv6hdr		*hdr;
-	u8			hash;
-	u8			addr_type;
-	struct inet6_protocol	*ipprot;
-	struct sock		*raw_sk;
-	int			found = 0;
-	int			nexthdr = 0;
-	__u8			*nhptr;
-	int			pkt_len;
-
-	if (skb->pkt_type == PACKET_OTHERHOST) {
-		kfree_skb(skb, FREE_READ);
-		return 0;
-	}
-
-	hdr = skb->nh.ipv6h;
-	skb->h.raw = (__u8*)hdr;
-
-	if (skb->len < sizeof(struct ipv6hdr) || hdr->version != 6)
-	{
-		ipv6_statistics.Ip6InHdrErrors++;
-		printk(KERN_DEBUG "ipv6_rcv: broken header\n");
-		kfree_skb(skb, FREE_READ);
-		return 0;
-	}
-
-	pkt_len = ntohs(hdr->payload_len);
-
-	if (pkt_len + sizeof(struct ipv6hdr) > skb->len)
-	{
-		printk(KERN_DEBUG "ipv6_rcv: invalid payload length\n");
-		kfree_skb(skb, FREE_READ);
-		return 0;
-	}
-
-	skb_trim(skb, pkt_len + sizeof(struct ipv6hdr));
-
-	/* check daddr */
-
-	/* Accounting & Firewall check */
-
-	addr_type = ipv6_addr_type(&hdr->daddr);
-
-	if (addr_type & IPV6_ADDR_MULTICAST)
-	{
-		/* 
-		 * if mcast address is not for one of our groups
-		 * either pass it to mcast router or discard it 
-		 */
-
-		if (ipv6_chk_mcast_addr(dev, &hdr->daddr) == 0)
-		{
-			/* something like:
-			   if (acting_as_router)
-				ipv6_mcast_route(skb, ...)
-			   else	
-			   */
-			kfree_skb(skb, FREE_READ);
-			return 0;
-		}
-	}
-
-	if (addr_type & IPV6_ADDR_MULTICAST ||
-	    (ifp = ipv6_chk_addr(&hdr->daddr)))	    
-	{
-
-		/* loop in a cicle parsing nexthdrs */
-
-		skb->h.raw   += sizeof(struct ipv6hdr);
- 
-		/* extension header processing must update skb->h.raw */
-
-		nexthdr = hdr->nexthdr;
-		nhptr = &hdr->nexthdr;
-
-
-		while(1)
-		{
-			struct hdrtype_proc *hdrt;
-
-			/* check for extension header */
-
-			for (hdrt=hdrproc_lst; hdrt->type != NEXTHDR_MAX; hdrt++)
-			{
-				if (hdrt->type == nexthdr)
-				{
-					if ((nexthdr = hdrt->func(&skb, dev, nhptr, opt)))
-					{
-						nhptr = skb->h.raw;
-						hdr = skb->nh.ipv6h;
-						continue;
-					}
-					return 0;
-				}
-			}
-			break;
-
-		}
-
-		/* 
-		 * deliver to raw sockets
-		 * should we deliver raw after or before parsing 
-		 * extension headers ?
-		 * delivering after means we do reassembly of datagrams
-		 * in ip.
-		 */
-
-		pkt_len = skb->tail - skb->h.raw;
-
-		raw_sk = ipv6_raw_deliver(skb, dev, opt, nexthdr, pkt_len,
-					  &hdr->saddr, &hdr->daddr);
-
-		/* check inet6_protocol list */
-
-		hash = nexthdr & (MAX_INET_PROTOS -1);
-		for (ipprot = (struct inet6_protocol *) inet6_protos[hash]; 
-		     ipprot != NULL; 
-		     ipprot = (struct inet6_protocol *) ipprot->next)
-		{
-			struct sk_buff *buff = skb;
-
-			if (ipprot->protocol != nexthdr)
-				continue;
-
-			if (ipprot->copy || raw_sk)
-				buff = skb_clone(skb, GFP_ATOMIC);
-
-
-			ipprot->handler(buff, dev, 
-					&hdr->saddr, &hdr->daddr,
-					opt, pkt_len,
-					0, ipprot);
-			found = 1;
-		}
-
-		if (raw_sk)
-		{
-			skb->sk = raw_sk;
-			rawv6_rcv(skb, dev, &hdr->saddr, &hdr->daddr, opt,
-				  htons(hdr->payload_len));
-			found = 1;
-		}
- 	       
-		/* not found: send ICMP parameter problem back */
-
-		if (!found)
-		{
-			printk(KERN_DEBUG "proto not found %d\n", nexthdr);
-			kfree_skb(skb, FREE_READ);
-		}
-			
-	}
-	else
-	{
-		if (skb->pkt_type != PACKET_HOST) {
-			kfree_skb(skb, FREE_READ);
-			return 0;
-		}
-
-		if (ipv6_forwarding)
-		{
-			if (addr_type & IPV6_ADDR_LINKLOCAL)
-			{
-				printk(KERN_DEBUG
-				       "link local pkt to forward\n");
-				kfree_skb(skb, FREE_READ);
-				return 0;
-			}
-			ipv6_forward(skb, dev, 0);
-		}
-		else
-		{
-			printk(KERN_WARNING "IPV6: packet to forward -"
-			       "host not configured as router\n");
-			kfree_skb(skb, FREE_READ);
-		}
-	}
-
-	return 0;
-}
-
-/*
- * Local variables:
- * c-file-style: "Linux"
- * End:
- */

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov