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

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

diff -u --recursive --new-file v2.1.29/linux/net/ipv6/icmp.c linux/net/ipv6/icmp.c
@@ -5,6 +5,8 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>
  *
+ *	$Id: icmp.c,v 1.8 1997/03/18 18:24:30 davem Exp $
+ *
  *	Based on net/ipv4/icmp.c
  *
  *	RFC 1885
@@ -28,17 +30,9 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/kernel.h>
-#include <linux/major.h>
 #include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/string.h>
 #include <linux/sockios.h>
 #include <linux/net.h>
-#include <linux/fcntl.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
 #include <linux/skbuff.h>
 
 #include <linux/inet.h>
@@ -49,15 +43,13 @@
 #include <net/sock.h>
 
 #include <net/ipv6.h>
+#include <net/checksum.h>
 #include <net/protocol.h>
-#include <net/route.h>
-#include <net/ndisc.h>
 #include <net/raw.h>
-#include <net/inet_common.h>
+#include <net/rawv6.h>
 #include <net/transp_v6.h>
-#include <net/ipv6_route.h>
+#include <net/ip6_route.h>
 #include <net/addrconf.h>
-#include <net/rawv6.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -88,7 +80,7 @@
 
 
 struct icmpv6_msg {
-	struct icmpv6hdr	icmph;
+	struct icmp6hdr		icmph;
 	__u8 			*data;
 	struct in6_addr		*daddr;
 	int			len;
@@ -106,7 +98,7 @@
 			   char *buff, unsigned int offset, unsigned int len)
 {
 	struct icmpv6_msg *msg = (struct icmpv6_msg *) data;
-	struct icmpv6hdr *icmph;
+	struct icmp6hdr *icmph;
 	__u32 csum;
 
 	/* 
@@ -115,26 +107,25 @@
 	 *	on an echo reply. (those are the rules on RFC 1883)
 	 */
 
-	if (offset)
-	{
+	if (offset) {
 		csum = csum_partial_copy((void *) msg->data +
-					 offset - sizeof(struct icmpv6hdr), 
+					 offset - sizeof(struct icmp6hdr), 
 					 buff, len, msg->csum);
 		msg->csum = csum;
 		return 0;
 	}
 
 	csum = csum_partial_copy((void *) &msg->icmph, buff,
-				 sizeof(struct icmpv6hdr), msg->csum);
+				 sizeof(struct icmp6hdr), msg->csum);
 
 	csum = csum_partial_copy((void *) msg->data, 
-				 buff + sizeof(struct icmpv6hdr),
-				 len - sizeof(struct icmpv6hdr), csum);
+				 buff + sizeof(struct icmp6hdr),
+				 len - sizeof(struct icmp6hdr), csum);
 
-	icmph = (struct icmpv6hdr *) buff;
+	icmph = (struct icmp6hdr *) buff;
 
-	icmph->checksum = csum_ipv6_magic(saddr, msg->daddr, msg->len,
-					  IPPROTO_ICMPV6, csum);
+	icmph->icmp6_cksum = csum_ipv6_magic(saddr, msg->daddr, msg->len,
+					     IPPROTO_ICMPV6, csum);
 	return 0; 
 }
 
@@ -163,6 +154,7 @@
 	struct in6_addr *saddr = NULL;
 	struct device *src_dev = NULL;
 	struct icmpv6_msg msg;
+	struct flowi fl;
 	int addr_type = 0;
 	int optlen;
 	int len;
@@ -171,9 +163,8 @@
 	 *	sanity check pointer in case of parameter problem
 	 */
 
-	if (type == ICMPV6_PARAMETER_PROB && 
-	    (info > (skb->tail - ((unsigned char *) hdr))))
-	{
+	if (type == ICMPV6_PARAMPROB && 
+	    (info > (skb->tail - ((unsigned char *) hdr)))) {
 		printk(KERN_DEBUG "icmpv6_send: bug! pointer > skb\n");
 		return;
 	}
@@ -188,23 +179,18 @@
 	addr_type = ipv6_addr_type(&hdr->daddr);
 
 	if (ipv6_chk_addr(&hdr->daddr))
-	{
 		saddr = &hdr->daddr;
-	}
 
 	/*
 	 *	Dest addr check
 	 */
 
-	if ((addr_type & IPV6_ADDR_MULTICAST || skb->pkt_type != PACKET_HOST))
-	{
+	if ((addr_type & IPV6_ADDR_MULTICAST || skb->pkt_type != PACKET_HOST)) {
 		if (type != ICMPV6_PKT_TOOBIG &&
-		    !(type == ICMPV6_PARAMETER_PROB && 
+		    !(type == ICMPV6_PARAMPROB && 
 		      code == ICMPV6_UNK_OPTION && 
 		      (opt_unrec(skb, info))))
-		{
 			return;
-		}
 
 		saddr = NULL;
 	}
@@ -216,16 +202,13 @@
 	 */
 
 	if (addr_type & IPV6_ADDR_LINKLOCAL)
-	{
 		src_dev = skb->dev;
-	}
 
 	/*
 	 *	Must not send if we know that source is Anycast also.
 	 *	for now we don't know that.
 	 */
-	if ((addr_type == IPV6_ADDR_ANY) || (addr_type & IPV6_ADDR_MULTICAST))
-	{
+	if ((addr_type == IPV6_ADDR_ANY) || (addr_type & IPV6_ADDR_MULTICAST)) {
 		printk(KERN_DEBUG "icmpv6_send: addr_any/mcast source\n");
 		return;
 	}
@@ -235,9 +218,9 @@
 	 *	getfrag_t callback.
 	 */
 
-	msg.icmph.type = type;
-	msg.icmph.code = code;
-	msg.icmph.checksum = 0;
+	msg.icmph.icmp6_type = type;
+	msg.icmph.icmp6_code = code;
+	msg.icmph.icmp6_cksum = 0;
 	msg.icmph.icmp6_pointer = htonl(info);
 
 	msg.data = skb->nh.raw;
@@ -252,31 +235,37 @@
 	optlen = 0;
 
 	len = min(skb->tail - ((unsigned char *) hdr), 
-		  576 - sizeof(struct ipv6hdr) - sizeof(struct icmpv6hdr)
+		  576 - sizeof(struct ipv6hdr) - sizeof(struct icmp6hdr)
 		  - optlen);
 
-	if (len < 0)
-	{
+	if (len < 0) {
 		printk(KERN_DEBUG "icmp: len problem\n");
 		return;
 	}
 
-	len += sizeof(struct icmpv6hdr);
+	len += sizeof(struct icmp6hdr);
 
 	msg.len = len;
 
+	fl.proto = IPPROTO_ICMPV6;
+	fl.nl_u.ip6_u.daddr = &hdr->saddr;
+	fl.nl_u.ip6_u.saddr = saddr;
+	fl.dev = src_dev;
+	fl.uli_u.icmpt.type = type;
+	fl.uli_u.icmpt.code = code;
 
-	ipv6_build_xmit(sk, icmpv6_getfrag, &msg, &hdr->saddr, len,
-			saddr, src_dev, NULL, IPPROTO_ICMPV6, 0, 1);
+	ip6_build_xmit(sk, icmpv6_getfrag, &msg, &fl, len, NULL, -1,
+		       MSG_DONTWAIT);
 }
 
 static void icmpv6_echo_reply(struct sk_buff *skb)
 {
 	struct sock *sk = icmpv6_socket->sk;
 	struct ipv6hdr *hdr = skb->nh.ipv6h;
-	struct icmpv6hdr *icmph = (struct icmpv6hdr *) skb->h.raw;
+	struct icmp6hdr *icmph = (struct icmp6hdr *) skb->h.raw;
 	struct in6_addr *saddr;
 	struct icmpv6_msg msg;
+	struct flowi fl;
 	unsigned char *data;
 	int len;
 
@@ -288,11 +277,11 @@
 		saddr = NULL;
 
 	len = skb->tail - data;
-	len += sizeof(struct icmpv6hdr);
+	len += sizeof(struct icmp6hdr);
 
-	msg.icmph.type = ICMPV6_ECHO_REPLY;
-	msg.icmph.code = 0;
-	msg.icmph.checksum = 0;
+	msg.icmph.icmp6_type = ICMPV6_ECHO_REPLY;
+	msg.icmph.icmp6_code = 0;
+	msg.icmph.icmp6_cksum = 0;
 	msg.icmph.icmp6_identifier = icmph->icmp6_identifier;
 	msg.icmph.icmp6_sequence = icmph->icmp6_sequence;
 
@@ -300,9 +289,16 @@
 	msg.csum = 0;
 	msg.len = len;
 	msg.daddr = &hdr->saddr;
-       
-	ipv6_build_xmit(sk, icmpv6_getfrag, &msg, &hdr->saddr, len, saddr,
-			skb->dev, NULL, IPPROTO_ICMPV6, 0, 1);
+
+	fl.proto = IPPROTO_ICMPV6;
+	fl.nl_u.ip6_u.daddr = &hdr->saddr;
+	fl.nl_u.ip6_u.saddr = saddr;
+	fl.dev = skb->dev;
+	fl.uli_u.icmpt.type = ICMPV6_ECHO_REPLY;
+	fl.uli_u.icmpt.code = 0;
+
+	ip6_build_xmit(sk, icmpv6_getfrag, &msg, &fl, len, NULL, -1,
+		       MSG_DONTWAIT);
 }
 
 static __inline__ int ipv6_ext_hdr(u8 nexthdr)
@@ -339,19 +335,24 @@
 	pbuff = (char *) (hdr + 1);
 	len -= sizeof(struct ipv6hdr);
 
-	while (ipv6_ext_hdr(nexthdr)) 
-	{
+	while (ipv6_ext_hdr(nexthdr)) {
 		int hdrlen;
 
 		if (nexthdr == NEXTHDR_NONE)
 			return;
 
 		nexthdr = *pbuff;
+
+		/* Header length is size in 8-octet units, not
+		 * including the first 8 octets.
+		 */
 		hdrlen = *(pbuff+1);
+		hdrlen = (hdrlen + 1) << 3;
 
-		if (((hdrlen + 1) << 3) > len)
+		if (hdrlen > len)
 			return;
 		
+		/* Now this is right. */
 		pbuff += hdrlen;
 		len -= hdrlen;
 	}
@@ -360,16 +361,13 @@
 
 	for (ipprot = (struct inet6_protocol *) inet6_protos[hash]; 
 	     ipprot != NULL; 
-	     ipprot=(struct inet6_protocol *)ipprot->next)
-	{
+	     ipprot=(struct inet6_protocol *)ipprot->next) {
 		if (ipprot->protocol != nexthdr)
 			continue;
 
 		if (ipprot->err_handler) 
-		{
 			ipprot->err_handler(type, code, pbuff, info,
 					    saddr, daddr, ipprot);
-		}
 		return;
 	}
 
@@ -378,16 +376,12 @@
 	sk = raw_v6_htable[hash];
 
 	if (sk == NULL)
-	{
 		return;
-	}
 
 	while((sk = raw_v6_lookup(sk, nexthdr, daddr, saddr))) {
 		rawv6_err(sk, type, code, pbuff, saddr, daddr);
 		sk = sk->next;
 	}
-
-	return;
 }
   
 /*
@@ -400,32 +394,29 @@
 	       int redo, struct inet6_protocol *protocol)
 {
 	struct ipv6hdr *orig_hdr;
-	struct icmpv6hdr *hdr = (struct icmpv6hdr *) skb->h.raw;
+	struct icmp6hdr *hdr = (struct icmp6hdr *) skb->h.raw;
 	int ulen;
 
-	/* perform checksum */
-
-
+	/* Perform checksum. */
 	switch (skb->ip_summed) {	
 	case CHECKSUM_NONE:
 		skb->csum = csum_partial((char *)hdr, len, 0);
 	case CHECKSUM_HW:
 		if (csum_ipv6_magic(saddr, daddr, len, IPPROTO_ICMPV6, 
-				    skb->csum))
-		{
+				    skb->csum)) {
 			printk(KERN_DEBUG "icmpv6 checksum failed\n");
 			goto discard_it;
 		}
 	default:
 		/* CHECKSUM_UNNECESSARY */
-	}
+	};
 
 	/*
 	 *	length of original packet carried in skb
 	 */
 	ulen = skb->tail - (unsigned char *) (hdr + 1);
 	
-	switch (hdr->type) {
+	switch (hdr->icmp6_type) {
 
 	case ICMPV6_ECHO_REQUEST:
 		icmpv6_echo_reply(skb);
@@ -438,20 +429,19 @@
 	case ICMPV6_PKT_TOOBIG:
 		orig_hdr = (struct ipv6hdr *) (hdr + 1);
 		if (ulen >= sizeof(struct ipv6hdr))
-		{
-			rt6_handle_pmtu(&orig_hdr->daddr,
-					ntohl(hdr->icmp6_mtu));
-		}
+			rt6_pmtu_discovery(&orig_hdr->daddr, dev,
+					   ntohl(hdr->icmp6_mtu));
 
 		/*
-		 * Drop through to notify
+		 *	Drop through to notify
 		 */
 
 	case ICMPV6_DEST_UNREACH:
-	case ICMPV6_TIME_EXCEEDED:
-	case ICMPV6_PARAMETER_PROB:
+	case ICMPV6_TIME_EXCEED:
+	case ICMPV6_PARAMPROB:
 
-		icmpv6_notify(hdr->type, hdr->code, (char *) (hdr + 1), ulen,
+		icmpv6_notify(hdr->icmp6_type, hdr->icmp6_code,
+			      (char *) (hdr + 1), ulen,
 			      saddr, daddr, protocol);
 		break;
 
@@ -463,32 +453,35 @@
 		ndisc_rcv(skb, dev, saddr, daddr, opt, len);		
 		break;
 
-	case ICMPV6_MEMBERSHIP_QUERY:
-	case ICMPV6_MEMBERSHIP_REPORT:
-	case ICMPV6_MEMBERSHIP_REDUCTION:
-		/* forward the packet to the igmp module */
+	case ICMPV6_MGM_QUERY:
+		igmp6_event_query(skb, hdr, len);
+		break;
+
+	case ICMPV6_MGM_REPORT:
+		igmp6_event_report(skb, hdr, len);
+		break;
+
+	case ICMPV6_MGM_REDUCTION:
 		break;
 
 	default:
 		printk(KERN_DEBUG "icmpv6: msg of unkown type\n");
 		
 		/* informational */
-		if (hdr->type & 0x80)
-		{
+		if (hdr->icmp6_type & 0x80)
 			goto discard_it;
-		}
 
 		/* 
 		 * error of unkown type. 
 		 * must pass to upper level 
 		 */
 
-		icmpv6_notify(hdr->type, hdr->code, (char *) (hdr + 1), ulen,
+		icmpv6_notify(hdr->icmp6_type, hdr->icmp6_code,
+			      (char *) (hdr + 1), ulen,
 			      saddr, daddr, protocol);	
-	}
-
-  discard_it:
+	};
 
+discard_it:
 	kfree_skb(skb, FREE_READ);
 	return 0;
 }
@@ -509,7 +502,7 @@
 
 	if((err=ops->create(icmpv6_socket, IPPROTO_ICMPV6))<0)
 		printk(KERN_DEBUG 
-		       "Failed to create the ICMP control socket.\n");
+		       "Failed to create the ICMP6 control socket.\n");
 
 	MOD_DEC_USE_COUNT;
 
@@ -518,6 +511,9 @@
 	sk->num = 256;			/* Don't receive any data */
 
 	inet6_add_protocol(&icmpv6_protocol);
+
+	ndisc_init(ops);
+	igmp6_init(ops);
 }
 
 static struct icmp6_err {
@@ -539,8 +535,7 @@
 
 	switch (type) {
 	case ICMPV6_DEST_UNREACH:
-		if (code <= ICMPV6_PORT_UNREACH)
-		{
+		if (code <= ICMPV6_PORT_UNREACH) {
 			*err  = tab_unreach[code].err;
 			fatal = tab_unreach[code].fatal;
 		}
@@ -550,7 +545,7 @@
 		*err = EMSGSIZE;
 		break;
 		
-	case ICMPV6_PARAMETER_PROB:
+	case ICMPV6_PARAMPROB:
 		*err = EPROTO;
 		fatal = 1;
 		break;
@@ -558,9 +553,3 @@
 
 	return fatal;
 }
-
-/*
- * Local variables:
- *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strength-reduce -pipe -m486 -DCPU=486 -DMODULE -DMODVERSIONS -include /usr/src/linux/include/linux/modversions.h  -c -o icmp.o icmp.c"
- * End:
- */

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