Commit be0eacc3 authored by Ralf Bächle's avatar Ralf Bächle

Eleminate SOCKOPS_WRAPPED by using the BKL directly.

parent b9ff5bc5
...@@ -114,6 +114,7 @@ ...@@ -114,6 +114,7 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/smp_lock.h>
#include <linux/sockios.h> #include <linux/sockios.h>
#include <linux/net.h> #include <linux/net.h>
#include <net/ax25.h> #include <net/ax25.h>
...@@ -628,10 +629,10 @@ ax25_cb *ax25_create_cb(void) ...@@ -628,10 +629,10 @@ ax25_cb *ax25_create_cb(void)
static int ax25_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen) static int ax25_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen)
{ {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
ax25_cb *ax25 = ax25_sk(sk); ax25_cb *ax25;
struct net_device *dev; struct net_device *dev;
char devname[IFNAMSIZ]; char devname[IFNAMSIZ];
int opt; int opt, res = 0;
if (level != SOL_AX25) if (level != SOL_AX25)
return -ENOPROTOOPT; return -ENOPROTOOPT;
...@@ -642,98 +643,129 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname, char *op ...@@ -642,98 +643,129 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname, char *op
if (get_user(opt, (int *)optval)) if (get_user(opt, (int *)optval))
return -EFAULT; return -EFAULT;
lock_kernel();
ax25 = ax25_sk(sk);
switch (optname) { switch (optname) {
case AX25_WINDOW: case AX25_WINDOW:
if (ax25->modulus == AX25_MODULUS) { if (ax25->modulus == AX25_MODULUS) {
if (opt < 1 || opt > 7) if (opt < 1 || opt > 7) {
return -EINVAL; res = -EINVAL;
break;
}
} else { } else {
if (opt < 1 || opt > 63) if (opt < 1 || opt > 63) {
return -EINVAL; res = -EINVAL;
break;
}
} }
ax25->window = opt; ax25->window = opt;
return 0; break;
case AX25_T1: case AX25_T1:
if (opt < 1) if (opt < 1) {
return -EINVAL; res = -EINVAL;
break;
}
ax25->rtt = (opt * HZ) / 2; ax25->rtt = (opt * HZ) / 2;
ax25->t1 = opt * HZ; ax25->t1 = opt * HZ;
return 0; break;
case AX25_T2: case AX25_T2:
if (opt < 1) if (opt < 1) {
return -EINVAL; res = -EINVAL;
break;
}
ax25->t2 = opt * HZ; ax25->t2 = opt * HZ;
return 0; break;
case AX25_N2: case AX25_N2:
if (opt < 1 || opt > 31) if (opt < 1 || opt > 31) {
return -EINVAL; res = -EINVAL;
break;
}
ax25->n2 = opt; ax25->n2 = opt;
return 0; break;
case AX25_T3: case AX25_T3:
if (opt < 1) if (opt < 1) {
return -EINVAL; res = -EINVAL;
break;
}
ax25->t3 = opt * HZ; ax25->t3 = opt * HZ;
return 0; break;
case AX25_IDLE: case AX25_IDLE:
if (opt < 0) if (opt < 0) {
return -EINVAL; res = -EINVAL;
break;
}
ax25->idle = opt * 60 * HZ; ax25->idle = opt * 60 * HZ;
return 0; break;
case AX25_BACKOFF: case AX25_BACKOFF:
if (opt < 0 || opt > 2) if (opt < 0 || opt > 2) {
return -EINVAL; res = -EINVAL;
break;
}
ax25->backoff = opt; ax25->backoff = opt;
return 0; break;
case AX25_EXTSEQ: case AX25_EXTSEQ:
ax25->modulus = opt ? AX25_EMODULUS : AX25_MODULUS; ax25->modulus = opt ? AX25_EMODULUS : AX25_MODULUS;
return 0; break;
case AX25_PIDINCL: case AX25_PIDINCL:
ax25->pidincl = opt ? 1 : 0; ax25->pidincl = opt ? 1 : 0;
return 0; break;
case AX25_IAMDIGI: case AX25_IAMDIGI:
ax25->iamdigi = opt ? 1 : 0; ax25->iamdigi = opt ? 1 : 0;
return 0; break;
case AX25_PACLEN: case AX25_PACLEN:
if (opt < 16 || opt > 65535) if (opt < 16 || opt > 65535) {
return -EINVAL; res = -EINVAL;
break;
}
ax25->paclen = opt; ax25->paclen = opt;
return 0; break;
case SO_BINDTODEVICE: case SO_BINDTODEVICE:
if (optlen > IFNAMSIZ) optlen=IFNAMSIZ; if (optlen > IFNAMSIZ) optlen=IFNAMSIZ;
if (copy_from_user(devname, optval, optlen)) if (copy_from_user(devname, optval, optlen)) {
return -EFAULT; res = -EFAULT;
break;
}
dev = dev_get_by_name(devname); dev = dev_get_by_name(devname);
if (dev == NULL) return -ENODEV; if (dev == NULL) {
res = -ENODEV;
break;
}
if (sk->type == SOCK_SEQPACKET && if (sk->type == SOCK_SEQPACKET &&
(sock->state != SS_UNCONNECTED || sk->state == TCP_LISTEN)) (sock->state != SS_UNCONNECTED || sk->state == TCP_LISTEN)) {
return -EADDRNOTAVAIL; res = -EADDRNOTAVAIL;
break;
}
ax25->ax25_dev = ax25_dev_ax25dev(dev); ax25->ax25_dev = ax25_dev_ax25dev(dev);
ax25_fillin_cb(ax25, ax25->ax25_dev); ax25_fillin_cb(ax25, ax25->ax25_dev);
return 0; break;
default: default:
return -ENOPROTOOPT; res = -ENOPROTOOPT;
} }
unlock_kernel();
return res;
} }
static int ax25_getsockopt(struct socket *sock, int level, int optname, char *optval, int *optlen) static int ax25_getsockopt(struct socket *sock, int level, int optname, char *optval, int *optlen)
{ {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
ax25_cb *ax25 = ax25_sk(sk); ax25_cb *ax25;
struct ax25_dev *ax25_dev; struct ax25_dev *ax25_dev;
char devname[IFNAMSIZ]; char devname[IFNAMSIZ];
void *valptr; void *valptr;
...@@ -752,6 +784,9 @@ static int ax25_getsockopt(struct socket *sock, int level, int optname, char *op ...@@ -752,6 +784,9 @@ static int ax25_getsockopt(struct socket *sock, int level, int optname, char *op
valptr = (void *) &val; valptr = (void *) &val;
length = min_t(unsigned int, maxlen, sizeof(int)); length = min_t(unsigned int, maxlen, sizeof(int));
lock_kernel();
ax25 = ax25_sk(sk);
switch (optname) { switch (optname) {
case AX25_WINDOW: case AX25_WINDOW:
val = ax25->window; val = ax25->window;
...@@ -813,8 +848,10 @@ static int ax25_getsockopt(struct socket *sock, int level, int optname, char *op ...@@ -813,8 +848,10 @@ static int ax25_getsockopt(struct socket *sock, int level, int optname, char *op
break; break;
default: default:
unlock_kernel();
return -ENOPROTOOPT; return -ENOPROTOOPT;
} }
unlock_kernel();
if (put_user(length, optlen)) if (put_user(length, optlen))
return -EFAULT; return -EFAULT;
...@@ -826,11 +863,14 @@ static int ax25_listen(struct socket *sock, int backlog) ...@@ -826,11 +863,14 @@ static int ax25_listen(struct socket *sock, int backlog)
{ {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
lock_kernel();
if (sk->type == SOCK_SEQPACKET && sk->state != TCP_LISTEN) { if (sk->type == SOCK_SEQPACKET && sk->state != TCP_LISTEN) {
sk->max_ack_backlog = backlog; sk->max_ack_backlog = backlog;
sk->state = TCP_LISTEN; sk->state = TCP_LISTEN;
unlock_kernel();
return 0; return 0;
} }
unlock_kernel();
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
...@@ -979,7 +1019,11 @@ static int ax25_release(struct socket *sock) ...@@ -979,7 +1019,11 @@ static int ax25_release(struct socket *sock)
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
ax25_cb *ax25; ax25_cb *ax25;
if (sk == NULL) return 0; lock_kernel();
if (sk == NULL) {
unlock_kernel();
return 0;
}
ax25 = ax25_sk(sk); ax25 = ax25_sk(sk);
...@@ -1042,6 +1086,7 @@ static int ax25_release(struct socket *sock) ...@@ -1042,6 +1086,7 @@ static int ax25_release(struct socket *sock)
sock->sk = NULL; sock->sk = NULL;
sk->socket = NULL; /* Not used, but we should do this */ sk->socket = NULL; /* Not used, but we should do this */
unlock_kernel();
return 0; return 0;
} }
...@@ -1060,26 +1105,35 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) ...@@ -1060,26 +1105,35 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
ax25_address *call; ax25_address *call;
ax25_dev *ax25_dev = NULL; ax25_dev *ax25_dev = NULL;
if (sk->zapped == 0) lock_kernel();
if (sk->zapped == 0) {
unlock_kernel();
return -EINVAL; return -EINVAL;
}
if (addr_len != sizeof(struct sockaddr_ax25) && if (addr_len != sizeof(struct sockaddr_ax25) &&
addr_len != sizeof(struct full_sockaddr_ax25)) { addr_len != sizeof(struct full_sockaddr_ax25)) {
/* support for old structure may go away some time */ /* support for old structure may go away some time */
if ((addr_len < sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 6) || if ((addr_len < sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 6) ||
(addr_len > sizeof(struct full_sockaddr_ax25))) (addr_len > sizeof(struct full_sockaddr_ax25))) {
unlock_kernel();
return -EINVAL; return -EINVAL;
}
printk(KERN_WARNING "ax25_bind(): %s uses old (6 digipeater) socket structure.\n", printk(KERN_WARNING "ax25_bind(): %s uses old (6 digipeater) socket structure.\n",
current->comm); current->comm);
} }
if (addr->fsa_ax25.sax25_family != AF_AX25) if (addr->fsa_ax25.sax25_family != AF_AX25) {
unlock_kernel();
return -EINVAL; return -EINVAL;
}
call = ax25_findbyuid(current->euid); call = ax25_findbyuid(current->euid);
if (call == NULL && ax25_uid_policy && !capable(CAP_NET_ADMIN)) if (call == NULL && ax25_uid_policy && !capable(CAP_NET_ADMIN)) {
unlock_kernel();
return -EACCES; return -EACCES;
}
if (call == NULL) if (call == NULL)
ax25->source_addr = addr->fsa_ax25.sax25_call; ax25->source_addr = addr->fsa_ax25.sax25_call;
...@@ -1095,11 +1149,15 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) ...@@ -1095,11 +1149,15 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
if (addr_len > sizeof(struct sockaddr_ax25) && addr->fsa_ax25.sax25_ndigis == 1) { if (addr_len > sizeof(struct sockaddr_ax25) && addr->fsa_ax25.sax25_ndigis == 1) {
if (ax25cmp(&addr->fsa_digipeater[0], &null_ax25_address) != 0 && if (ax25cmp(&addr->fsa_digipeater[0], &null_ax25_address) != 0 &&
(ax25_dev = ax25_addr_ax25dev(&addr->fsa_digipeater[0])) == NULL) (ax25_dev = ax25_addr_ax25dev(&addr->fsa_digipeater[0])) == NULL) {
unlock_kernel();
return -EADDRNOTAVAIL; return -EADDRNOTAVAIL;
}
} else { } else {
if ((ax25_dev = ax25_addr_ax25dev(&addr->fsa_ax25.sax25_call)) == NULL) if ((ax25_dev = ax25_addr_ax25dev(&addr->fsa_ax25.sax25_call)) == NULL) {
unlock_kernel();
return -EADDRNOTAVAIL; return -EADDRNOTAVAIL;
}
} }
if (ax25_dev != NULL) if (ax25_dev != NULL)
...@@ -1108,6 +1166,8 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) ...@@ -1108,6 +1166,8 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
done: done:
ax25_insert_socket(ax25); ax25_insert_socket(ax25);
sk->zapped = 0; sk->zapped = 0;
unlock_kernel();
return 0; return 0;
} }
...@@ -1122,24 +1182,30 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le ...@@ -1122,24 +1182,30 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
ax25_digi *digi = NULL; ax25_digi *digi = NULL;
int ct = 0, err; int ct = 0, err;
lock_kernel();
/* deal with restarts */ /* deal with restarts */
if (sock->state == SS_CONNECTING) { if (sock->state == SS_CONNECTING) {
switch (sk->state) { switch (sk->state) {
case TCP_SYN_SENT: /* still trying */ case TCP_SYN_SENT: /* still trying */
unlock_kernel();
return -EINPROGRESS; return -EINPROGRESS;
case TCP_ESTABLISHED: /* connection established */ case TCP_ESTABLISHED: /* connection established */
unlock_kernel();
sock->state = SS_CONNECTED; sock->state = SS_CONNECTED;
return 0; return 0;
case TCP_CLOSE: /* connection refused */ case TCP_CLOSE: /* connection refused */
unlock_kernel();
sock->state = SS_UNCONNECTED; sock->state = SS_UNCONNECTED;
return -ECONNREFUSED; return -ECONNREFUSED;
} }
} }
if (sk->state == TCP_ESTABLISHED && sk->type == SOCK_SEQPACKET) if (sk->state == TCP_ESTABLISHED && sk->type == SOCK_SEQPACKET) {
unlock_kernel();
return -EISCONN; /* No reconnect on a seqpacket socket */ return -EISCONN; /* No reconnect on a seqpacket socket */
}
sk->state = TCP_CLOSE; sk->state = TCP_CLOSE;
sock->state = SS_UNCONNECTED; sock->state = SS_UNCONNECTED;
...@@ -1156,15 +1222,19 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le ...@@ -1156,15 +1222,19 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
else if (addr_len != sizeof(struct full_sockaddr_ax25)) { else if (addr_len != sizeof(struct full_sockaddr_ax25)) {
/* support for old structure may go away some time */ /* support for old structure may go away some time */
if ((addr_len < sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 6) || if ((addr_len < sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 6) ||
(addr_len > sizeof(struct full_sockaddr_ax25))) (addr_len > sizeof(struct full_sockaddr_ax25))) {
unlock_kernel();
return -EINVAL; return -EINVAL;
}
printk(KERN_WARNING "ax25_connect(): %s uses old (6 digipeater) socket structure.\n", printk(KERN_WARNING "ax25_connect(): %s uses old (6 digipeater) socket structure.\n",
current->comm); current->comm);
} }
if (fsa->fsa_ax25.sax25_family != AF_AX25) if (fsa->fsa_ax25.sax25_family != AF_AX25) {
unlock_kernel();
return -EINVAL; return -EINVAL;
}
if (ax25->digipeat != NULL) { if (ax25->digipeat != NULL) {
kfree(ax25->digipeat); kfree(ax25->digipeat);
...@@ -1176,11 +1246,15 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le ...@@ -1176,11 +1246,15 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
*/ */
if (addr_len > sizeof(struct sockaddr_ax25) && fsa->fsa_ax25.sax25_ndigis != 0) { if (addr_len > sizeof(struct sockaddr_ax25) && fsa->fsa_ax25.sax25_ndigis != 0) {
/* Valid number of digipeaters ? */ /* Valid number of digipeaters ? */
if (fsa->fsa_ax25.sax25_ndigis < 1 || fsa->fsa_ax25.sax25_ndigis > AX25_MAX_DIGIS) if (fsa->fsa_ax25.sax25_ndigis < 1 || fsa->fsa_ax25.sax25_ndigis > AX25_MAX_DIGIS) {
unlock_kernel();
return -EINVAL; return -EINVAL;
}
if ((digi = kmalloc(sizeof(ax25_digi), GFP_KERNEL)) == NULL) if ((digi = kmalloc(sizeof(ax25_digi), GFP_KERNEL)) == NULL) {
unlock_kernel();
return -ENOBUFS; return -ENOBUFS;
}
digi->ndigi = fsa->fsa_ax25.sax25_ndigis; digi->ndigi = fsa->fsa_ax25.sax25_ndigis;
digi->lastrepeat = -1; digi->lastrepeat = -1;
...@@ -1212,14 +1286,18 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le ...@@ -1212,14 +1286,18 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
ax25_fillin_cb(ax25, ax25->ax25_dev); ax25_fillin_cb(ax25, ax25->ax25_dev);
ax25_insert_socket(ax25); ax25_insert_socket(ax25);
} else { } else {
if (ax25->ax25_dev == NULL) if (ax25->ax25_dev == NULL) {
unlock_kernel();
return -EHOSTUNREACH; return -EHOSTUNREACH;
}
} }
if (sk->type == SOCK_SEQPACKET && if (sk->type == SOCK_SEQPACKET &&
ax25_find_cb(&ax25->source_addr, &fsa->fsa_ax25.sax25_call, digi, ax25_find_cb(&ax25->source_addr, &fsa->fsa_ax25.sax25_call, digi,
ax25->ax25_dev->dev)) { ax25->ax25_dev->dev)) {
if (digi != NULL) kfree(digi); if (digi != NULL)
kfree(digi);
unlock_kernel();
return -EADDRINUSE; /* Already such a connection */ return -EADDRINUSE; /* Already such a connection */
} }
...@@ -1230,6 +1308,7 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le ...@@ -1230,6 +1308,7 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
if (sk->type != SOCK_SEQPACKET) { if (sk->type != SOCK_SEQPACKET) {
sock->state = SS_CONNECTED; sock->state = SS_CONNECTED;
sk->state = TCP_ESTABLISHED; sk->state = TCP_ESTABLISHED;
unlock_kernel();
return 0; return 0;
} }
...@@ -1261,8 +1340,10 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le ...@@ -1261,8 +1340,10 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
ax25_start_heartbeat(ax25); ax25_start_heartbeat(ax25);
/* Now the loop */ /* Now the loop */
if (sk->state != TCP_ESTABLISHED && (flags & O_NONBLOCK)) if (sk->state != TCP_ESTABLISHED && (flags & O_NONBLOCK)) {
unlock_kernel();
return -EINPROGRESS; return -EINPROGRESS;
}
if (sk->state == TCP_SYN_SENT) { if (sk->state == TCP_SYN_SENT) {
struct task_struct *tsk = current; struct task_struct *tsk = current;
...@@ -1290,6 +1371,7 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le ...@@ -1290,6 +1371,7 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
} }
sock->state = SS_CONNECTED; sock->state = SS_CONNECTED;
unlock_kernel();
return 0; return 0;
} }
...@@ -1301,17 +1383,26 @@ static int ax25_accept(struct socket *sock, struct socket *newsock, int flags) ...@@ -1301,17 +1383,26 @@ static int ax25_accept(struct socket *sock, struct socket *newsock, int flags)
struct sock *newsk; struct sock *newsk;
struct sk_buff *skb; struct sk_buff *skb;
if (sock->state != SS_UNCONNECTED) lock_kernel();
if (sock->state != SS_UNCONNECTED) {
unlock_kernel();
return -EINVAL; return -EINVAL;
}
if ((sk = sock->sk) == NULL) if ((sk = sock->sk) == NULL) {
unlock_kernel();
return -EINVAL; return -EINVAL;
}
if (sk->type != SOCK_SEQPACKET) if (sk->type != SOCK_SEQPACKET) {
unlock_kernel();
return -EOPNOTSUPP; return -EOPNOTSUPP;
}
if (sk->state != TCP_LISTEN) if (sk->state != TCP_LISTEN) {
unlock_kernel();
return -EINVAL; return -EINVAL;
}
/* /*
* The read queue this time is holding sockets ready to use * The read queue this time is holding sockets ready to use
...@@ -1319,12 +1410,16 @@ static int ax25_accept(struct socket *sock, struct socket *newsock, int flags) ...@@ -1319,12 +1410,16 @@ static int ax25_accept(struct socket *sock, struct socket *newsock, int flags)
*/ */
do { do {
if ((skb = skb_dequeue(&sk->receive_queue)) == NULL) { if ((skb = skb_dequeue(&sk->receive_queue)) == NULL) {
if (flags & O_NONBLOCK) if (flags & O_NONBLOCK) {
unlock_kernel();
return -EWOULDBLOCK; return -EWOULDBLOCK;
}
interruptible_sleep_on(sk->sleep); interruptible_sleep_on(sk->sleep);
if (signal_pending(current)) if (signal_pending(current)) {
unlock_kernel();
return -ERESTARTSYS; return -ERESTARTSYS;
}
} }
} while (skb == NULL); } while (skb == NULL);
...@@ -1338,20 +1433,27 @@ static int ax25_accept(struct socket *sock, struct socket *newsock, int flags) ...@@ -1338,20 +1433,27 @@ static int ax25_accept(struct socket *sock, struct socket *newsock, int flags)
sk->ack_backlog--; sk->ack_backlog--;
newsock->sk = newsk; newsock->sk = newsk;
newsock->state = SS_CONNECTED; newsock->state = SS_CONNECTED;
unlock_kernel();
return 0; return 0;
} }
static int ax25_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer) static int ax25_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer)
{ {
struct sock *sk = sock->sk; struct sock *sk;
ax25_cb *ax25 = ax25_sk(sk); ax25_cb *ax25;
struct full_sockaddr_ax25 *fsa = (struct full_sockaddr_ax25 *)uaddr; struct full_sockaddr_ax25 *fsa = (struct full_sockaddr_ax25 *)uaddr;
unsigned char ndigi, i; unsigned char ndigi, i;
lock_kernel();
sk = sock->sk;
ax25 = ax25_sk(sk);
if (peer != 0) { if (peer != 0) {
if (sk->state != TCP_ESTABLISHED) if (sk->state != TCP_ESTABLISHED) {
unlock_kernel();
return -ENOTCONN; return -ENOTCONN;
}
fsa->fsa_ax25.sax25_family = AF_AX25; fsa->fsa_ax25.sax25_family = AF_AX25;
fsa->fsa_ax25.sax25_call = ax25->dest_addr; fsa->fsa_ax25.sax25_call = ax25->dest_addr;
...@@ -1376,13 +1478,15 @@ static int ax25_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_ ...@@ -1376,13 +1478,15 @@ static int ax25_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_
} }
} }
*uaddr_len = sizeof (struct full_sockaddr_ax25); *uaddr_len = sizeof (struct full_sockaddr_ax25);
unlock_kernel();
return 0; return 0;
} }
static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm) static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm)
{ {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
ax25_cb *ax25 = ax25_sk(sk); ax25_cb *ax25;
struct sockaddr_ax25 *usax = (struct sockaddr_ax25 *)msg->msg_name; struct sockaddr_ax25 *usax = (struct sockaddr_ax25 *)msg->msg_name;
int err; int err;
struct sockaddr_ax25 sax; struct sockaddr_ax25 sax;
...@@ -1394,23 +1498,34 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct ...@@ -1394,23 +1498,34 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
int lv; int lv;
int addr_len = msg->msg_namelen; int addr_len = msg->msg_namelen;
if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_EOR)) if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_EOR)) {
return -EINVAL; return -EINVAL;
}
lock_kernel();
ax25 = ax25_sk(sk);
if (sk->zapped) if (sk->zapped) {
unlock_kernel();
return -EADDRNOTAVAIL; return -EADDRNOTAVAIL;
}
if (sk->shutdown & SEND_SHUTDOWN) { if (sk->shutdown & SEND_SHUTDOWN) {
unlock_kernel();
send_sig(SIGPIPE, current, 0); send_sig(SIGPIPE, current, 0);
return -EPIPE; return -EPIPE;
} }
if (ax25->ax25_dev == NULL) if (ax25->ax25_dev == NULL) {
unlock_kernel();
return -ENETUNREACH; return -ENETUNREACH;
}
if (usax != NULL) { if (usax != NULL) {
if (usax->sax25_family != AF_AX25) if (usax->sax25_family != AF_AX25) {
unlock_kernel();
return -EINVAL; return -EINVAL;
}
if (addr_len == sizeof(struct sockaddr_ax25)) { if (addr_len == sizeof(struct sockaddr_ax25)) {
printk(KERN_WARNING "ax25_sendmsg(): %s uses obsolete socket structure\n", printk(KERN_WARNING "ax25_sendmsg(): %s uses obsolete socket structure\n",
...@@ -1419,8 +1534,10 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct ...@@ -1419,8 +1534,10 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
else if (addr_len != sizeof(struct full_sockaddr_ax25)) { else if (addr_len != sizeof(struct full_sockaddr_ax25)) {
/* support for old structure may go away some time */ /* support for old structure may go away some time */
if ((addr_len < sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 6) || if ((addr_len < sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 6) ||
(addr_len > sizeof(struct full_sockaddr_ax25))) (addr_len > sizeof(struct full_sockaddr_ax25))) {
unlock_kernel();
return -EINVAL; return -EINVAL;
}
printk(KERN_WARNING "ax25_sendmsg(): %s uses old (6 digipeater) socket structure.\n", printk(KERN_WARNING "ax25_sendmsg(): %s uses old (6 digipeater) socket structure.\n",
current->comm); current->comm);
...@@ -1431,8 +1548,10 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct ...@@ -1431,8 +1548,10 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
struct full_sockaddr_ax25 *fsa = (struct full_sockaddr_ax25 *)usax; struct full_sockaddr_ax25 *fsa = (struct full_sockaddr_ax25 *)usax;
/* Valid number of digipeaters ? */ /* Valid number of digipeaters ? */
if (usax->sax25_ndigis < 1 || usax->sax25_ndigis > AX25_MAX_DIGIS) if (usax->sax25_ndigis < 1 || usax->sax25_ndigis > AX25_MAX_DIGIS) {
unlock_kernel();
return -EINVAL; return -EINVAL;
}
dtmp.ndigi = usax->sax25_ndigis; dtmp.ndigi = usax->sax25_ndigis;
...@@ -1446,8 +1565,10 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct ...@@ -1446,8 +1565,10 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
} }
sax = *usax; sax = *usax;
if (sk->type == SOCK_SEQPACKET && ax25cmp(&ax25->dest_addr, &sax.sax25_call) != 0) if (sk->type == SOCK_SEQPACKET && ax25cmp(&ax25->dest_addr, &sax.sax25_call) != 0) {
unlock_kernel();
return -EISCONN; return -EISCONN;
}
if (usax->sax25_ndigis == 0) if (usax->sax25_ndigis == 0)
dp = NULL; dp = NULL;
else else
...@@ -1473,8 +1594,10 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct ...@@ -1473,8 +1594,10 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
/* Assume the worst case */ /* Assume the worst case */
size = len + 3 + ax25_addr_size(dp) + AX25_BPQ_HEADER_LEN; size = len + 3 + ax25_addr_size(dp) + AX25_BPQ_HEADER_LEN;
if ((skb = sock_alloc_send_skb(sk, size, msg->msg_flags & MSG_DONTWAIT, &err)) == NULL) if ((skb = sock_alloc_send_skb(sk, size, msg->msg_flags & MSG_DONTWAIT, &err)) == NULL) {
unlock_kernel();
return err; return err;
}
skb_reserve(skb, size - len); skb_reserve(skb, size - len);
...@@ -1496,11 +1619,13 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct ...@@ -1496,11 +1619,13 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
/* Connected mode sockets go via the LAPB machine */ /* Connected mode sockets go via the LAPB machine */
if (sk->state != TCP_ESTABLISHED) { if (sk->state != TCP_ESTABLISHED) {
kfree_skb(skb); kfree_skb(skb);
unlock_kernel();
return -ENOTCONN; return -ENOTCONN;
} }
/* Shove it onto the queue and kick */ /* Shove it onto the queue and kick */
ax25_output(ax25, ax25->paclen, skb); ax25_output(ax25, ax25->paclen, skb);
unlock_kernel();
return len; return len;
} else { } else {
...@@ -1528,6 +1653,7 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct ...@@ -1528,6 +1653,7 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
skb->dev = ax25->ax25_dev->dev; skb->dev = ax25->ax25_dev->dev;
ax25_queue_xmit(skb); ax25_queue_xmit(skb);
unlock_kernel();
return len; return len;
} }
...@@ -1535,21 +1661,28 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct ...@@ -1535,21 +1661,28 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
static int ax25_recvmsg(struct socket *sock, struct msghdr *msg, int size, int flags, struct scm_cookie *scm) static int ax25_recvmsg(struct socket *sock, struct msghdr *msg, int size, int flags, struct scm_cookie *scm)
{ {
struct sock *sk = sock->sk; struct sock *sk;
int copied; int copied;
struct sk_buff *skb; struct sk_buff *skb;
int er; int er;
lock_kernel();
sk = sock->sk;
/* /*
* This works for seqpacket too. The receiver has ordered the * This works for seqpacket too. The receiver has ordered the
* queue for us! We do one quick check first though * queue for us! We do one quick check first though
*/ */
if (sk->type == SOCK_SEQPACKET && sk->state != TCP_ESTABLISHED) if (sk->type == SOCK_SEQPACKET && sk->state != TCP_ESTABLISHED) {
unlock_kernel();
return -ENOTCONN; return -ENOTCONN;
}
/* Now we can treat all alike */ /* Now we can treat all alike */
if ((skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, flags & MSG_DONTWAIT, &er)) == NULL) if ((skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, flags & MSG_DONTWAIT, &er)) == NULL) {
unlock_kernel();
return er; return er;
}
if (!ax25_sk(sk)->pidincl) if (!ax25_sk(sk)->pidincl)
skb_pull(skb, 1); /* Remove PID */ skb_pull(skb, 1); /* Remove PID */
...@@ -1589,6 +1722,7 @@ static int ax25_recvmsg(struct socket *sock, struct msghdr *msg, int size, int f ...@@ -1589,6 +1722,7 @@ static int ax25_recvmsg(struct socket *sock, struct msghdr *msg, int size, int f
} }
skb_free_datagram(sk, skb); skb_free_datagram(sk, skb);
unlock_kernel();
return copied; return copied;
} }
...@@ -1602,14 +1736,17 @@ static int ax25_shutdown(struct socket *sk, int how) ...@@ -1602,14 +1736,17 @@ static int ax25_shutdown(struct socket *sk, int how)
static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{ {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
int res = 0;
lock_kernel();
switch (cmd) { switch (cmd) {
case TIOCOUTQ: { case TIOCOUTQ: {
long amount; long amount;
amount = sk->sndbuf - atomic_read(&sk->wmem_alloc); amount = sk->sndbuf - atomic_read(&sk->wmem_alloc);
if (amount < 0) if (amount < 0)
amount = 0; amount = 0;
return put_user(amount, (int *)arg); res = put_user(amount, (int *)arg);
break;
} }
case TIOCINQ: { case TIOCINQ: {
...@@ -1618,49 +1755,70 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) ...@@ -1618,49 +1755,70 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
/* These two are safe on a single CPU system as only user tasks fiddle here */ /* These two are safe on a single CPU system as only user tasks fiddle here */
if ((skb = skb_peek(&sk->receive_queue)) != NULL) if ((skb = skb_peek(&sk->receive_queue)) != NULL)
amount = skb->len; amount = skb->len;
return put_user(amount, (int *)arg); res = put_user(amount, (int *)arg);
break;
} }
case SIOCGSTAMP: case SIOCGSTAMP:
if (sk != NULL) { if (sk != NULL) {
if (sk->stamp.tv_sec == 0) if (sk->stamp.tv_sec == 0) {
return -ENOENT; res = -ENOENT;
return copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)) ? -EFAULT : 0; break;
}
res = copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)) ? -EFAULT : 0;
break;
} }
return -EINVAL; res = -EINVAL;
break;
case SIOCAX25ADDUID: /* Add a uid to the uid/call map table */ case SIOCAX25ADDUID: /* Add a uid to the uid/call map table */
case SIOCAX25DELUID: /* Delete a uid from the uid/call map table */ case SIOCAX25DELUID: /* Delete a uid from the uid/call map table */
case SIOCAX25GETUID: { case SIOCAX25GETUID: {
struct sockaddr_ax25 sax25; struct sockaddr_ax25 sax25;
if (copy_from_user(&sax25, (void *)arg, sizeof(sax25))) if (copy_from_user(&sax25, (void *)arg, sizeof(sax25))) {
return -EFAULT; res = -EFAULT;
return ax25_uid_ioctl(cmd, &sax25); break;
}
res = ax25_uid_ioctl(cmd, &sax25);
break;
} }
case SIOCAX25NOUID: { /* Set the default policy (default/bar) */ case SIOCAX25NOUID: { /* Set the default policy (default/bar) */
long amount; long amount;
if (!capable(CAP_NET_ADMIN)) if (!capable(CAP_NET_ADMIN)) {
return -EPERM; res = -EPERM;
if (get_user(amount, (long *)arg)) break;
return -EFAULT; }
if (amount > AX25_NOUID_BLOCK) if (get_user(amount, (long *)arg)) {
return -EINVAL; res = -EFAULT;
break;
}
if (amount > AX25_NOUID_BLOCK) {
res = -EINVAL;
break;
}
ax25_uid_policy = amount; ax25_uid_policy = amount;
return 0; res = 0;
break;
} }
case SIOCADDRT: case SIOCADDRT:
case SIOCDELRT: case SIOCDELRT:
case SIOCAX25OPTRT: case SIOCAX25OPTRT:
if (!capable(CAP_NET_ADMIN)) if (!capable(CAP_NET_ADMIN)) {
return -EPERM; res = -EPERM;
return ax25_rt_ioctl(cmd, (void *)arg); break;
}
res = ax25_rt_ioctl(cmd, (void *)arg);
break;
case SIOCAX25CTLCON: case SIOCAX25CTLCON:
if (!capable(CAP_NET_ADMIN)) if (!capable(CAP_NET_ADMIN)) {
return -EPERM; res = -EPERM;
return ax25_ctl_ioctl(cmd, (void *)arg); break;
}
res = ax25_ctl_ioctl(cmd, (void *)arg);
break;
case SIOCAX25GETINFO: case SIOCAX25GETINFO:
case SIOCAX25GETINFOOLD: { case SIOCAX25GETINFOOLD: {
...@@ -1696,23 +1854,33 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) ...@@ -1696,23 +1854,33 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
warned=1; warned=1;
} }
if (copy_to_user((void *)arg, &ax25_info, sizeof(struct ax25_info_struct_depreciated))) if (copy_to_user((void *)arg, &ax25_info, sizeof(struct ax25_info_struct_depreciated))) {
return -EFAULT; res = -EFAULT;
break;
}
} else { } else {
if (copy_to_user((void *)arg, &ax25_info, sizeof(struct ax25_info_struct))) if (copy_to_user((void *)arg, &ax25_info, sizeof(struct ax25_info_struct))) {
return -EINVAL; res = -EINVAL;
break;
}
} }
return 0; res = 0;
break;
} }
case SIOCAX25ADDFWD: case SIOCAX25ADDFWD:
case SIOCAX25DELFWD: { case SIOCAX25DELFWD: {
struct ax25_fwd_struct ax25_fwd; struct ax25_fwd_struct ax25_fwd;
if (!capable(CAP_NET_ADMIN)) if (!capable(CAP_NET_ADMIN)) {
return -EPERM; res = -EPERM;
if (copy_from_user(&ax25_fwd, (void *)arg, sizeof(ax25_fwd))) break;
return -EFAULT; }
return ax25_fwd_ioctl(cmd, &ax25_fwd); if (copy_from_user(&ax25_fwd, (void *)arg, sizeof(ax25_fwd))) {
res = -EFAULT;
break;
}
res = ax25_fwd_ioctl(cmd, &ax25_fwd);
break;
} }
case SIOCGIFADDR: case SIOCGIFADDR:
...@@ -1725,14 +1893,16 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) ...@@ -1725,14 +1893,16 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
case SIOCSIFNETMASK: case SIOCSIFNETMASK:
case SIOCGIFMETRIC: case SIOCGIFMETRIC:
case SIOCSIFMETRIC: case SIOCSIFMETRIC:
return -EINVAL; res = -EINVAL;
break;
default: default:
return dev_ioctl(cmd, (void *)arg); res = dev_ioctl(cmd, (void *)arg);
break;
} }
/*NOTREACHED*/ unlock_kernel();
return 0; return res;
} }
static int ax25_get_info(char *buffer, char **start, off_t offset, int length) static int ax25_get_info(char *buffer, char **start, off_t offset, int length)
...@@ -1814,7 +1984,7 @@ static struct net_proto_family ax25_family_ops = { ...@@ -1814,7 +1984,7 @@ static struct net_proto_family ax25_family_ops = {
create: ax25_create, create: ax25_create,
}; };
static struct proto_ops SOCKOPS_WRAPPED(ax25_proto_ops) = { static struct proto_ops ax25_proto_ops = {
family: PF_AX25, family: PF_AX25,
release: ax25_release, release: ax25_release,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment