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

Next file: linux/net/ipv6/ip6_output.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.123/linux/net/ipv6/icmp.c linux/net/ipv6/icmp.c
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>
  *
- *	$Id: icmp.c,v 1.19 1998/08/26 12:04:52 davem Exp $
+ *	$Id: icmp.c,v 1.20 1998/10/03 09:38:31 davem Exp $
  *
  *	Based on net/ipv4/icmp.c
  *
@@ -334,7 +334,7 @@
 	msg.daddr = &hdr->saddr;
 
 	len = min((skb->tail - ((unsigned char *) hdr)) + sizeof(struct icmp6hdr), 
-		  IPV6_MIN_MTU - sizeof(struct icmp6hdr));
+		  IPV6_MIN_MTU - sizeof(struct ipv6hdr));
 
 	if (len < 0) {
 		printk(KERN_DEBUG "icmp: len problem\n");
@@ -396,7 +396,7 @@
 }
 
 static void icmpv6_notify(struct sk_buff *skb,
-			  int type, int code, unsigned char *buff, int len)
+			  int type, int code, u32 info, unsigned char *buff, int len)
 {
 	struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
 	struct in6_addr *daddr = &skb->nh.ipv6h->daddr;
@@ -404,7 +404,6 @@
 	struct inet6_protocol *ipprot;
 	struct sock *sk;
 	u8 *pb;
-	__u32 info = 0;
 	int hash;
 	u8 nexthdr;
 
@@ -436,11 +435,8 @@
 
 		if (ipprot->err_handler)
 			ipprot->err_handler(skb, hdr, NULL, type, code, pb, info);
-		return;
 	}
 
-	/* delivery to upper layer protocols failed. try raw sockets */
-
 	sk = raw_v6_htable[hash];
 
 	if (sk == NULL)
@@ -468,6 +464,9 @@
 
 	icmpv6_statistics.Icmp6InMsgs++;
 
+	if (len < sizeof(struct icmp6hdr))
+		goto discard_it;
+
 	/* Perform checksum. */
 	switch (skb->ip_summed) {	
 	case CHECKSUM_NONE:
@@ -538,7 +537,7 @@
 	case ICMPV6_DEST_UNREACH:
 	case ICMPV6_TIME_EXCEED:
 	case ICMPV6_PARAMPROB:
-		icmpv6_notify(skb, type, hdr->icmp6_code,
+		icmpv6_notify(skb, type, hdr->icmp6_code, hdr->icmp6_mtu,
 			      (char *) (hdr + 1), ulen);
 		break;
 
@@ -574,7 +573,7 @@
 		 * must pass to upper level 
 		 */
 
-		icmpv6_notify(skb, type, hdr->icmp6_code,
+		icmpv6_notify(skb, type, hdr->icmp6_code, hdr->icmp6_mtu,
 			      (char *) (hdr + 1), ulen);
 	};
 	kfree_skb(skb);
@@ -586,7 +585,7 @@
 	return 0;
 }
 
-__initfunc(int icmpv6_init(struct net_proto_family *ops))
+int __init icmpv6_init(struct net_proto_family *ops)
 {
 	struct sock *sk;
 	int err;
@@ -632,7 +631,7 @@
 } tab_unreach[] = {
 	{ ENETUNREACH,	0},	/* NOROUTE		*/
 	{ EACCES,	1},	/* ADM_PROHIBITED	*/
-	{ 0,		0},	/* Was NOT_NEIGHBOUR, now reserved */
+	{ EHOSTUNREACH,	0},	/* Was NOT_NEIGHBOUR, now reserved */
 	{ EHOSTUNREACH,	0},	/* ADDR_UNREACH		*/
 	{ ECONNREFUSED,	1},	/* PORT_UNREACH		*/
 };
@@ -641,10 +640,11 @@
 {
 	int fatal = 0;
 
-	*err = 0;
+	*err = EPROTO;
 
 	switch (type) {
 	case ICMPV6_DEST_UNREACH:
+		fatal = 1;
 		if (code <= ICMPV6_PORT_UNREACH) {
 			*err  = tab_unreach[code].err;
 			fatal = tab_unreach[code].fatal;
@@ -658,6 +658,10 @@
 	case ICMPV6_PARAMPROB:
 		*err = EPROTO;
 		fatal = 1;
+		break;
+
+	case ICMPV6_TIME_EXCEED:
+		*err = EHOSTUNREACH;
 		break;
 	};
 

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