diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-12-16 05:34:03 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1997-12-16 05:34:03 +0000 |
commit | 967c65a99059fd459b956c1588ce0ba227912c4e (patch) | |
tree | 8224d013ff5d255420713d05610c7efebd204d2a /net/core/sock.c | |
parent | e20c1cc1656a66a2773bca4591a895cbc12696ff (diff) |
Merge with Linux 2.1.72, part 1.
Diffstat (limited to 'net/core/sock.c')
-rw-r--r-- | net/core/sock.c | 55 |
1 files changed, 49 insertions, 6 deletions
diff --git a/net/core/sock.c b/net/core/sock.c index 65cee3b62..725474887 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -75,6 +75,7 @@ * protocol private data. * Steve Whitehouse: Added various other default routines * common to several socket families. + * Chris Evans : Call suser() check last on F_SETOWN * * To Fix: * @@ -101,6 +102,7 @@ #include <linux/mm.h> #include <linux/slab.h> #include <linux/interrupt.h> +#include <linux/poll.h> #include <asm/uaccess.h> #include <asm/system.h> @@ -143,6 +145,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname, int valbool; int err; struct linger ling; + struct ifreq req; int ret = 0; /* @@ -241,7 +244,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname, break; case SO_PRIORITY: - if (val >= 0 && val < DEV_NUMBUFFS) + if (val >= 0 && val <= 7) sk->priority = val; else return(-EINVAL); @@ -317,6 +320,46 @@ int sock_setsockopt(struct socket *sock, int level, int optname, return -EINVAL; break; #endif + case SO_BINDTODEVICE: + /* Bind this socket to a particular device like "eth0", + * as specified in an ifreq structure. If the device + * is "", socket is NOT bound to a device. + */ + + if (!valbool) { + sk->bound_dev_if = 0; + } + else { + if (copy_from_user(&req, optval, sizeof(req)) < 0) + return -EFAULT; + + /* Remove any cached route for this socket. */ + if (sk->dst_cache) { + ip_rt_put((struct rtable*)sk->dst_cache); + sk->dst_cache = NULL; + } + + if (req.ifr_ifrn.ifrn_name[0] == '\0') { + sk->bound_dev_if = 0; + } + else { + struct device *dev = dev_get(req.ifr_ifrn.ifrn_name); + if (!dev) + return -EINVAL; + sk->bound_dev_if = dev->ifindex; + if (sk->daddr) { + int ret; + ret = ip_route_output((struct rtable**)&sk->dst_cache, + sk->daddr, sk->saddr, + sk->ip_tos, sk->bound_dev_if); + if (ret) + return ret; + } + } + } + return 0; + + /* We implement the SO_SNDLOWAT etc to not be settable (1003.1g 5.3) */ default: @@ -627,7 +670,7 @@ struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size, unsigne produce annoying no free page messages still.... */ skb = sock_wmalloc(sk, size, 0 , GFP_BUFFER); if(!skb) - skb=sock_wmalloc(sk, fallback, 0, GFP_KERNEL); + skb=sock_wmalloc(sk, fallback, 0, sk->allocation); } /* @@ -669,7 +712,7 @@ struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size, unsigne * In any case I'd delete this check at all, or * change it to: */ - if (atomic_read(&sk->wmem_alloc) + size >= sk->sndbuf) + if (atomic_read(&sk->wmem_alloc) >= sk->sndbuf) #endif { sk->socket->flags &= ~SO_NOSPACE; @@ -896,8 +939,9 @@ int sock_no_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg) * way to make sure that you can't send a sigurg to * another process. */ - if (!suser() && current->pgrp != -arg && - current->pid != arg) return(-EPERM); + if (current->pgrp != -arg && + current->pid != arg && + !suser()) return(-EPERM); sk->proc = arg; return(0); case F_GETOWN: @@ -967,7 +1011,6 @@ void sock_init_data(struct socket *sock, struct sock *sk) sk->allocation = GFP_KERNEL; sk->rcvbuf = sysctl_rmem_default*2; sk->sndbuf = sysctl_wmem_default*2; - sk->priority = SOPRI_NORMAL; sk->state = TCP_CLOSE; sk->zapped = 1; sk->socket = sock; |