diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1998-03-17 22:05:47 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1998-03-17 22:05:47 +0000 |
commit | 27cfca1ec98e91261b1a5355d10a8996464b63af (patch) | |
tree | 8e895a53e372fa682b4c0a585b9377d67ed70d0e /net/ipv6/raw.c | |
parent | 6a76fb7214c477ccf6582bd79c5b4ccc4f9c41b1 (diff) |
Look Ma' what I found on my harddisk ...
o New faster syscalls for 2.1.x, too
o Upgrade to 2.1.89.
Don't try to run this. It's flaky as hell. But feel free to debug ...
Diffstat (limited to 'net/ipv6/raw.c')
-rw-r--r-- | net/ipv6/raw.c | 65 |
1 files changed, 32 insertions, 33 deletions
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 17af36fe6..4ee1b13ad 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.13 1997/09/14 08:32:14 davem Exp $ + * $Id: raw.c,v 1.16 1997/12/29 19:52:48 kuznet Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -25,6 +25,7 @@ #include <linux/netdevice.h> #include <linux/if_arp.h> #include <linux/icmpv6.h> +#include <asm/uaccess.h> #include <net/sock.h> #include <net/snmp.h> @@ -98,7 +99,7 @@ static void raw_v6_rehash(struct sock *sk) SOCKHASH_UNLOCK(); } -static int __inline__ inet6_mc_check(struct sock *sk, struct in6_addr *addr) +static __inline__ int inet6_mc_check(struct sock *sk, struct in6_addr *addr) { struct ipv6_mc_socklist *mc; @@ -165,7 +166,7 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) */ v4addr = LOOPBACK4_IPV6; if (!(addr_type & IPV6_ADDR_MULTICAST)) { - if (ipv6_chk_addr(&addr->sin6_addr) == NULL) + if (ipv6_chk_addr(&addr->sin6_addr, NULL, 0) == NULL) return(-EADDRNOTAVAIL); } } @@ -193,7 +194,7 @@ static inline int rawv6_rcv_skb(struct sock * sk, struct sk_buff * skb) /* Charge it to the socket. */ if (sock_queue_rcv_skb(sk,skb)<0) { /* ip_statistics.IpInDiscards++; */ - kfree_skb(skb, FREE_READ); + kfree_skb(skb); return 0; } @@ -235,13 +236,11 @@ int rawv6_rcv(struct sk_buff *skb, struct device *dev, */ int rawv6_recvmsg(struct sock *sk, struct msghdr *msg, int len, - int noblock, int flags,int *addr_len) + int noblock, int flags, int *addr_len) { - struct sockaddr_in6 *sin6=(struct sockaddr_in6 *)msg->msg_name; + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)msg->msg_name; struct sk_buff *skb; - int copied=0; - int err; - + int copied, err; if (flags & MSG_OOB) return -EOPNOTSUPP; @@ -252,32 +251,32 @@ int rawv6_recvmsg(struct sock *sk, struct msghdr *msg, int len, if (addr_len) *addr_len=sizeof(*sin6); - skb=skb_recv_datagram(sk, flags, noblock, &err); - if(skb==NULL) - return err; + skb = skb_recv_datagram(sk, flags, noblock, &err); + if (!skb) + goto out; copied = min(len, skb->tail - skb->h.raw); err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); sk->stamp=skb->stamp; - if (err) - return err; + goto out_free; /* Copy the address. */ if (sin6) { sin6->sin6_family = AF_INET6; memcpy(&sin6->sin6_addr, &skb->nh.ipv6h->saddr, sizeof(struct in6_addr)); - - *addr_len = sizeof(struct sockaddr_in6); } if (msg->msg_controllen) datagram_recv_ctl(sk, msg, skb); + err = copied; +out_free: skb_free_datagram(sk, skb); - return (copied); +out: + return err; } /* @@ -359,7 +358,15 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, int len) int hlimit = -1; u16 proto; int err; - + + /* Rough check on arithmetic overflow, + better check is made in ip6_build_xmit + + When jumbo header will be implemeted we will remove it + at all (len will be size_t) + */ + if (len < 0 || len > 0xFFFF) + return -EMSGSIZE; /* Mirror BSD error message compatibility */ if (msg->msg_flags & MSG_OOB) @@ -389,9 +396,12 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, int len) daddr = &sin6->sin6_addr; - if (np->dst && ipv6_addr_cmp(daddr, &np->daddr)) { - dst_release(np->dst); - np->dst = NULL; + /* BUGGGG If route is not cloned, this check always + fails, hence dst_cache only slows down tramsmission --ANK + */ + if (sk->dst_cache && ipv6_addr_cmp(daddr, &np->daddr)) { + dst_release(sk->dst_cache); + sk->dst_cache = NULL; } } else { if (sk->state != TCP_ESTABLISHED) @@ -409,12 +419,6 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, int len) return(-EINVAL); } - /* - * We don't allow > 64K sends yet. - */ - if (len + (sk->ip_hdrincl ? 0 : sizeof(struct ipv6hdr)) > 65535) - return -EMSGSIZE; - if (msg->msg_controllen) { opt = &opt_space; memset(opt, 0, sizeof(struct ipv6_options)); @@ -592,14 +596,9 @@ static int rawv6_getsockopt(struct sock *sk, int level, int optname, static void rawv6_close(struct sock *sk, unsigned long timeout) { - struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6; - sk->state = TCP_CLOSE; - - if (np->dst) - dst_release(np->dst); - ipv6_sock_mc_close(sk); + sk->dead = 1; destroy_sock(sk); } |