diff options
| author | Linus Torvalds <torvalds@athlon.transmeta.com> | 2002-02-04 18:11:38 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@athlon.transmeta.com> | 2002-02-04 18:11:38 -0800 |
| commit | 1a0153507ffae9cf3350e76c12d441788c0191e1 (patch) | |
| tree | d05a502b4fc05202c84c1667019460c08ea088cd /net/ipv6/raw.c | |
| parent | b0683ac8928c4cf40646a6ce3eb6ffe94605acfa (diff) | |
v2.4.3.2 -> v2.4.3.3
- Hui-Fen Hsu: sis900 driver update
- NIIBE Yutaka: Super-H update
- Alan Cox: more resyncs (ARM down, but more to go)
- David Miller: network zerocopy, Sparc sync, qlogic,FC fix, etc.
- David Miller/me: get rid of various drivers hacks to do mmap
alignment behind the back of the VM layer. Create a real
protocol for it.
Diffstat (limited to 'net/ipv6/raw.c')
| -rw-r--r-- | net/ipv6/raw.c | 41 |
1 files changed, 23 insertions, 18 deletions
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 1a4c44a39222..ed7c8260546d 100644 --- a/net/ipv6/raw.c +++ b/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 @@ static __inline__ int icmpv6_filter(struct sock *sk, struct sk_buff *skb) 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 @@ static __inline__ int icmpv6_filter(struct sock *sk, struct sk_buff *skb) * (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 @@ struct sock * ipv6_raw_deliver(struct sk_buff *skb, buff = skb_clone(skb, GFP_ATOMIC); if (buff) - rawv6_rcv(sk2, buff, len); + rawv6_rcv(sk2, buff); } } @@ -177,8 +179,6 @@ out: 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 @@ out: 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 @@ void rawv6_err(struct sock *sk, struct sk_buff *skb, struct ipv6hdr *hdr, 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 @@ static inline int rawv6_rcv_skb(struct sock * sk, struct sk_buff * skb) * 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 @@ int rawv6_recvmsg(struct sock *sk, struct msghdr *msg, int len, 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 @@ static int rawv6_geticmpfilter(struct sock *sk, int level, int optname, 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)) |
