summaryrefslogtreecommitdiffstats
path: root/net/x25/af_x25.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/x25/af_x25.c')
-rw-r--r--net/x25/af_x25.c115
1 files changed, 93 insertions, 22 deletions
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index 7fa9c7ad3d3b..e3219e4cd044 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -415,6 +415,7 @@ static int x25_setsockopt(struct socket *sock, int level, int optname,
struct sock *sk = sock->sk;
int rc = -ENOPROTOOPT;
+ lock_kernel();
if (level != SOL_X25 || optname != X25_QBITINCL)
goto out;
@@ -429,6 +430,7 @@ static int x25_setsockopt(struct socket *sock, int level, int optname,
x25_sk(sk)->qbitincl = !!opt;
rc = 0;
out:
+ unlock_kernel();
return rc;
}
@@ -438,6 +440,7 @@ static int x25_getsockopt(struct socket *sock, int level, int optname,
struct sock *sk = sock->sk;
int val, len, rc = -ENOPROTOOPT;
+ lock_kernel();
if (level != SOL_X25 || optname != X25_QBITINCL)
goto out;
@@ -458,6 +461,7 @@ static int x25_getsockopt(struct socket *sock, int level, int optname,
val = x25_sk(sk)->qbitincl;
rc = copy_to_user(optval, &val, len) ? -EFAULT : 0;
out:
+ unlock_kernel();
return rc;
}
@@ -466,12 +470,14 @@ static int x25_listen(struct socket *sock, int backlog)
struct sock *sk = sock->sk;
int rc = -EOPNOTSUPP;
+ lock_kernel();
if (sk->sk_state != TCP_LISTEN) {
memset(&x25_sk(sk)->dest_addr, 0, X25_ADDR_LEN);
sk->sk_max_ack_backlog = backlog;
sk->sk_state = TCP_LISTEN;
rc = 0;
}
+ unlock_kernel();
return rc;
}
@@ -501,13 +507,14 @@ out:
return sk;
}
-static int x25_create(struct net *net, struct socket *sock, int protocol)
+static int x25_create(struct net *net, struct socket *sock, int protocol,
+ int kern)
{
struct sock *sk;
struct x25_sock *x25;
int rc = -ESOCKTNOSUPPORT;
- if (net != &init_net)
+ if (!net_eq(net, &init_net))
return -EAFNOSUPPORT;
if (sock->type != SOCK_SEQPACKET || protocol)
@@ -597,6 +604,7 @@ static int x25_release(struct socket *sock)
struct sock *sk = sock->sk;
struct x25_sock *x25;
+ lock_kernel();
if (!sk)
goto out;
@@ -627,6 +635,7 @@ static int x25_release(struct socket *sock)
sock_orphan(sk);
out:
+ unlock_kernel();
return 0;
}
@@ -634,18 +643,23 @@ static int x25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
{
struct sock *sk = sock->sk;
struct sockaddr_x25 *addr = (struct sockaddr_x25 *)uaddr;
+ int rc = 0;
+ lock_kernel();
if (!sock_flag(sk, SOCK_ZAPPED) ||
addr_len != sizeof(struct sockaddr_x25) ||
- addr->sx25_family != AF_X25)
- return -EINVAL;
+ addr->sx25_family != AF_X25) {
+ rc = -EINVAL;
+ goto out;
+ }
x25_sk(sk)->source_addr = addr->sx25_addr;
x25_insert_socket(sk);
sock_reset_flag(sk, SOCK_ZAPPED);
SOCK_DEBUG(sk, "x25_bind: socket is bound\n");
-
- return 0;
+out:
+ unlock_kernel();
+ return rc;
}
static int x25_wait_for_connection_establishment(struct sock *sk)
@@ -686,6 +700,7 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr,
struct x25_route *rt;
int rc = 0;
+ lock_kernel();
lock_sock(sk);
if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {
sock->state = SS_CONNECTED;
@@ -763,6 +778,7 @@ out_put_route:
x25_route_put(rt);
out:
release_sock(sk);
+ unlock_kernel();
return rc;
}
@@ -802,6 +818,7 @@ static int x25_accept(struct socket *sock, struct socket *newsock, int flags)
struct sk_buff *skb;
int rc = -EINVAL;
+ lock_kernel();
if (!sk || sk->sk_state != TCP_LISTEN)
goto out;
@@ -829,6 +846,7 @@ static int x25_accept(struct socket *sock, struct socket *newsock, int flags)
out2:
release_sock(sk);
out:
+ unlock_kernel();
return rc;
}
@@ -838,10 +856,14 @@ static int x25_getname(struct socket *sock, struct sockaddr *uaddr,
struct sockaddr_x25 *sx25 = (struct sockaddr_x25 *)uaddr;
struct sock *sk = sock->sk;
struct x25_sock *x25 = x25_sk(sk);
+ int rc = 0;
+ lock_kernel();
if (peer) {
- if (sk->sk_state != TCP_ESTABLISHED)
- return -ENOTCONN;
+ if (sk->sk_state != TCP_ESTABLISHED) {
+ rc = -ENOTCONN;
+ goto out;
+ }
sx25->sx25_addr = x25->dest_addr;
} else
sx25->sx25_addr = x25->source_addr;
@@ -849,7 +871,21 @@ static int x25_getname(struct socket *sock, struct sockaddr *uaddr,
sx25->sx25_family = AF_X25;
*uaddr_len = sizeof(*sx25);
- return 0;
+out:
+ unlock_kernel();
+ return rc;
+}
+
+static unsigned int x25_datagram_poll(struct file *file, struct socket *sock,
+ poll_table *wait)
+{
+ int rc;
+
+ lock_kernel();
+ rc = datagram_poll(file, sock, wait);
+ unlock_kernel();
+
+ return rc;
}
int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
@@ -1002,6 +1038,7 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock,
size_t size;
int qbit = 0, rc = -EINVAL;
+ lock_kernel();
if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_OOB|MSG_EOR|MSG_CMSG_COMPAT))
goto out;
@@ -1166,6 +1203,7 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock,
release_sock(sk);
rc = len;
out:
+ unlock_kernel();
return rc;
out_kfree_skb:
kfree_skb(skb);
@@ -1186,6 +1224,7 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock,
unsigned char *asmptr;
int rc = -ENOTCONN;
+ lock_kernel();
/*
* This works for seqpacket too. The receiver has ordered the queue for
* us! We do one quick check first though
@@ -1259,6 +1298,7 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock,
out_free_dgram:
skb_free_datagram(sk, skb);
out:
+ unlock_kernel();
return rc;
}
@@ -1270,6 +1310,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
void __user *argp = (void __user *)arg;
int rc;
+ lock_kernel();
switch (cmd) {
case TIOCOUTQ: {
int amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
@@ -1363,7 +1404,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
facilities.throughput > 0xDD)
break;
if (facilities.reverse &&
- (facilities.reverse | 0x81)!= 0x81)
+ (facilities.reverse & 0x81) != 0x81)
break;
x25->facilities = facilities;
rc = 0;
@@ -1430,6 +1471,17 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
break;
}
+ case SIOCX25SCAUSEDIAG: {
+ struct x25_causediag causediag;
+ rc = -EFAULT;
+ if (copy_from_user(&causediag, argp, sizeof(causediag)))
+ break;
+ x25->causediag = causediag;
+ rc = 0;
+ break;
+
+ }
+
case SIOCX25SCUDMATCHLEN: {
struct x25_subaddr sub_addr;
rc = -EINVAL;
@@ -1472,11 +1524,12 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
rc = -ENOIOCTLCMD;
break;
}
+ unlock_kernel();
return rc;
}
-static struct net_proto_family x25_family_ops = {
+static const struct net_proto_family x25_family_ops = {
.family = AF_X25,
.create = x25_create,
.owner = THIS_MODULE,
@@ -1542,15 +1595,19 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd,
break;
case SIOCGSTAMP:
rc = -EINVAL;
+ lock_kernel();
if (sk)
rc = compat_sock_get_timestamp(sk,
(struct timeval __user*)argp);
+ unlock_kernel();
break;
case SIOCGSTAMPNS:
rc = -EINVAL;
+ lock_kernel();
if (sk)
rc = compat_sock_get_timestampns(sk,
(struct timespec __user*)argp);
+ unlock_kernel();
break;
case SIOCGIFADDR:
case SIOCSIFADDR:
@@ -1569,16 +1626,22 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd,
rc = -EPERM;
if (!capable(CAP_NET_ADMIN))
break;
+ lock_kernel();
rc = x25_route_ioctl(cmd, argp);
+ unlock_kernel();
break;
case SIOCX25GSUBSCRIP:
+ lock_kernel();
rc = compat_x25_subscr_ioctl(cmd, argp);
+ unlock_kernel();
break;
case SIOCX25SSUBSCRIP:
rc = -EPERM;
if (!capable(CAP_NET_ADMIN))
break;
+ lock_kernel();
rc = compat_x25_subscr_ioctl(cmd, argp);
+ unlock_kernel();
break;
case SIOCX25GFACILITIES:
case SIOCX25SFACILITIES:
@@ -1587,6 +1650,7 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd,
case SIOCX25GCALLUSERDATA:
case SIOCX25SCALLUSERDATA:
case SIOCX25GCAUSEDIAG:
+ case SIOCX25SCAUSEDIAG:
case SIOCX25SCUDMATCHLEN:
case SIOCX25CALLACCPTAPPRV:
case SIOCX25SENDCALLACCPT:
@@ -1600,7 +1664,7 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd,
}
#endif
-static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {
+static const struct proto_ops x25_proto_ops = {
.family = AF_X25,
.owner = THIS_MODULE,
.release = x25_release,
@@ -1609,7 +1673,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {
.socketpair = sock_no_socketpair,
.accept = x25_accept,
.getname = x25_getname,
- .poll = datagram_poll,
+ .poll = x25_datagram_poll,
.ioctl = x25_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = compat_x25_ioctl,
@@ -1624,8 +1688,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {
.sendpage = sock_no_sendpage,
};
-SOCKOPS_WRAP(x25_proto, AF_X25);
-
static struct packet_type x25_packet_type __read_mostly = {
.type = cpu_to_be16(ETH_P_X25),
.func = x25_lapb_receive_frame,
@@ -1659,20 +1721,31 @@ static int __init x25_init(void)
if (rc != 0)
goto out;
- sock_register(&x25_family_ops);
+ rc = sock_register(&x25_family_ops);
+ if (rc != 0)
+ goto out_proto;
dev_add_pack(&x25_packet_type);
- register_netdevice_notifier(&x25_dev_notifier);
+ rc = register_netdevice_notifier(&x25_dev_notifier);
+ if (rc != 0)
+ goto out_sock;
printk(KERN_INFO "X.25 for Linux Version 0.2\n");
-#ifdef CONFIG_SYSCTL
x25_register_sysctl();
-#endif
- x25_proc_init();
+ rc = x25_proc_init();
+ if (rc != 0)
+ goto out_dev;
out:
return rc;
+out_dev:
+ unregister_netdevice_notifier(&x25_dev_notifier);
+out_sock:
+ sock_unregister(AF_X25);
+out_proto:
+ proto_unregister(&x25_proto);
+ goto out;
}
module_init(x25_init);
@@ -1682,9 +1755,7 @@ static void __exit x25_exit(void)
x25_link_free();
x25_route_free();
-#ifdef CONFIG_SYSCTL
x25_unregister_sysctl();
-#endif
unregister_netdevice_notifier(&x25_dev_notifier);