summaryrefslogtreecommitdiffstats
path: root/net/core/sock.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1997-12-16 05:34:03 +0000
committerRalf Baechle <ralf@linux-mips.org>1997-12-16 05:34:03 +0000
commit967c65a99059fd459b956c1588ce0ba227912c4e (patch)
tree8224d013ff5d255420713d05610c7efebd204d2a /net/core/sock.c
parente20c1cc1656a66a2773bca4591a895cbc12696ff (diff)
Merge with Linux 2.1.72, part 1.
Diffstat (limited to 'net/core/sock.c')
-rw-r--r--net/core/sock.c55
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;