patch-2.4.4 linux/net/ipv6/raw.c

Next file: linux/net/ipv6/reassembly.c
Previous file: linux/net/ipv6/netfilter/Makefile
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.3/linux/net/ipv6/raw.c linux/net/ipv6/raw.c
@@ -7,7 +7,7 @@
  *
  *	Adapted from linux/net/ipv4/raw.c
  *
- *	$Id: raw.c,v 1.42 2000/11/28 13:38:38 davem Exp $
+ *	$Id: raw.c,v 1.45 2001/02/18 09:10:42 davem Exp $
  *
  *	Fixes:
  *	Hideaki YOSHIFUJI	:	sin6_scope_id support
@@ -116,8 +116,11 @@
 	struct raw6_opt *opt;
 
 	opt = &sk->tp_pinfo.tp_raw;
-	icmph = (struct icmp6hdr *) (skb->nh.ipv6h + 1);
-	return test_bit(icmph->icmp6_type, &opt->filter);
+	if (pskb_may_pull(skb, sizeof(struct icmp6hdr))) {
+		icmph = (struct icmp6hdr *) skb->data;
+		return test_bit(icmph->icmp6_type, &opt->filter);
+	}
+	return 0;
 }
 
 /*
@@ -125,8 +128,7 @@
  *	(should consider queueing the skb in the sock receive_queue
  *	without calling rawv6.c)
  */
-struct sock * ipv6_raw_deliver(struct sk_buff *skb,
-			       int nexthdr, unsigned long len)
+struct sock * ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
 {
 	struct in6_addr *saddr;
 	struct in6_addr *daddr;
@@ -163,7 +165,7 @@
 
 			buff = skb_clone(skb, GFP_ATOMIC);
 			if (buff)
-				rawv6_rcv(sk2, buff, len);
+				rawv6_rcv(sk2, buff);
 		}
 	}
 
@@ -177,8 +179,6 @@
 	return sk;
 }
 
-
-
 /* This cleans up af_inet6 a bit. -DaveM */
 static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 {
@@ -239,16 +239,13 @@
 	return err;
 }
 
-void rawv6_err(struct sock *sk, struct sk_buff *skb, struct ipv6hdr *hdr,
+void rawv6_err(struct sock *sk, struct sk_buff *skb,
 	       struct inet6_skb_parm *opt,
-	       int type, int code, unsigned char *buff, u32 info)
+	       int type, int code, int offset, u32 info)
 {
 	int err;
 	int harderr;
 
-	if (buff > skb->tail)
-		return;
-
 	/* Report error on raw socket, if:
 	   1. User requested recverr.
 	   2. Socket is connected (otherwise the error indication
@@ -261,8 +258,12 @@
 	if (type == ICMPV6_PKT_TOOBIG)
 		harderr = (sk->net_pinfo.af_inet6.pmtudisc == IPV6_PMTUDISC_DO);
 
-	if (sk->net_pinfo.af_inet6.recverr)
-		ipv6_icmp_error(sk, skb, err, 0, ntohl(info), buff);
+	if (sk->net_pinfo.af_inet6.recverr) {
+		u8 *payload = skb->data;
+		if (!sk->protinfo.af_inet.hdrincl)
+			payload += offset;
+		ipv6_icmp_error(sk, skb, err, 0, ntohl(info), payload);
+	}
 
 	if (sk->net_pinfo.af_inet6.recverr || harderr) {
 		sk->err = err;
@@ -290,10 +291,12 @@
  *	maybe we could have the network decide uppon a hint if it 
  *	should call raw_rcv for demultiplexing
  */
-int rawv6_rcv(struct sock *sk, struct sk_buff *skb, unsigned long len)
+int rawv6_rcv(struct sock *sk, struct sk_buff *skb)
 {
-	if (sk->protinfo.af_inet.hdrincl)
+	if (sk->protinfo.af_inet.hdrincl) {
+		__skb_push(skb, skb->nh.raw - skb->data);
 		skb->h.raw = skb->nh.raw;
+	}
 
 	rawv6_rcv_skb(sk, skb);
 	return 0;
@@ -325,7 +328,7 @@
 	if (!skb)
 		goto out;
 
-	copied = skb->tail - skb->h.raw;
+	copied = skb->len;
   	if (copied > len) {
   		copied = len;
   		msg->msg_flags |= MSG_TRUNC;
@@ -594,6 +597,8 @@
 	case ICMPV6_FILTER:
 		if (get_user(len, optlen))
 			return -EFAULT;
+		if (len < 0)
+			return -EINVAL;
 		if (len > sizeof(struct icmp6_filter))
 			len = sizeof(struct icmp6_filter);
 		if (put_user(len, optlen))

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)