git://ftp.safe.ca
/
safe
/
jmp
/
linux-2.6
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
x25: use limited socket backlog
[safe/jmp/linux-2.6]
/
net
/
x25
/
af_x25.c
diff --git
a/net/x25/af_x25.c
b/net/x25/af_x25.c
index
8f76f40
..
9796f3e
100644
(file)
--- a/
net/x25/af_x25.c
+++ b/
net/x25/af_x25.c
@@
-40,6
+40,7
@@
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/sched.h>
+#include <linux/smp_lock.h>
#include <linux/timer.h>
#include <linux/string.h>
#include <linux/net.h>
#include <linux/timer.h>
#include <linux/string.h>
#include <linux/net.h>
@@
-54,6
+55,7
@@
#include <linux/notifier.h>
#include <linux/init.h>
#include <linux/compat.h>
#include <linux/notifier.h>
#include <linux/init.h>
#include <linux/compat.h>
+#include <linux/ctype.h>
#include <net/x25.h>
#include <net/compat.h>
#include <net/x25.h>
#include <net/compat.h>
@@
-332,14
+334,14
@@
static unsigned int x25_new_lci(struct x25_neigh *nb)
/*
* Deferred destroy.
*/
/*
* Deferred destroy.
*/
-
void
x25_destroy_socket(struct sock *);
+
static void __
x25_destroy_socket(struct sock *);
/*
* handler for deferred kills.
*/
static void x25_destroy_timer(unsigned long data)
{
/*
* handler for deferred kills.
*/
static void x25_destroy_timer(unsigned long data)
{
- x25_destroy_socket((struct sock *)data);
+ x25_destroy_socket
_from_timer
((struct sock *)data);
}
/*
}
/*
@@
-349,12
+351,10
@@
static void x25_destroy_timer(unsigned long data)
* will touch it and we are (fairly 8-) ) safe.
* Not static as it's used by the timer
*/
* will touch it and we are (fairly 8-) ) safe.
* Not static as it's used by the timer
*/
-
void
x25_destroy_socket(struct sock *sk)
+
static void __
x25_destroy_socket(struct sock *sk)
{
struct sk_buff *skb;
{
struct sk_buff *skb;
- sock_hold(sk);
- lock_sock(sk);
x25_stop_heartbeat(sk);
x25_stop_timer(sk);
x25_stop_heartbeat(sk);
x25_stop_timer(sk);
@@
-374,8
+374,7
@@
void x25_destroy_socket(struct sock *sk)
kfree_skb(skb);
}
kfree_skb(skb);
}
- if (atomic_read(&sk->sk_wmem_alloc) ||
- atomic_read(&sk->sk_rmem_alloc)) {
+ if (sk_has_allocations(sk)) {
/* Defer: outstanding buffers */
sk->sk_timer.expires = jiffies + 10 * HZ;
sk->sk_timer.function = x25_destroy_timer;
/* Defer: outstanding buffers */
sk->sk_timer.expires = jiffies + 10 * HZ;
sk->sk_timer.function = x25_destroy_timer;
@@
-385,7
+384,22
@@
void x25_destroy_socket(struct sock *sk)
/* drop last reference so sock_put will free */
__sock_put(sk);
}
/* drop last reference so sock_put will free */
__sock_put(sk);
}
+}
+void x25_destroy_socket_from_timer(struct sock *sk)
+{
+ sock_hold(sk);
+ bh_lock_sock(sk);
+ __x25_destroy_socket(sk);
+ bh_unlock_sock(sk);
+ sock_put(sk);
+}
+
+static void x25_destroy_socket(struct sock *sk)
+{
+ sock_hold(sk);
+ lock_sock(sk);
+ __x25_destroy_socket(sk);
release_sock(sk);
sock_put(sk);
}
release_sock(sk);
sock_put(sk);
}
@@
-396,12
+410,13
@@
void x25_destroy_socket(struct sock *sk)
*/
static int x25_setsockopt(struct socket *sock, int level, int optname,
*/
static int x25_setsockopt(struct socket *sock, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval,
unsigned
int optlen)
{
int opt;
struct sock *sk = sock->sk;
int rc = -ENOPROTOOPT;
{
int opt;
struct sock *sk = sock->sk;
int rc = -ENOPROTOOPT;
+ lock_kernel();
if (level != SOL_X25 || optname != X25_QBITINCL)
goto out;
if (level != SOL_X25 || optname != X25_QBITINCL)
goto out;
@@
-416,6
+431,7
@@
static int x25_setsockopt(struct socket *sock, int level, int optname,
x25_sk(sk)->qbitincl = !!opt;
rc = 0;
out:
x25_sk(sk)->qbitincl = !!opt;
rc = 0;
out:
+ unlock_kernel();
return rc;
}
return rc;
}
@@
-425,6
+441,7
@@
static int x25_getsockopt(struct socket *sock, int level, int optname,
struct sock *sk = sock->sk;
int val, len, rc = -ENOPROTOOPT;
struct sock *sk = sock->sk;
int val, len, rc = -ENOPROTOOPT;
+ lock_kernel();
if (level != SOL_X25 || optname != X25_QBITINCL)
goto out;
if (level != SOL_X25 || optname != X25_QBITINCL)
goto out;
@@
-445,6
+462,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:
val = x25_sk(sk)->qbitincl;
rc = copy_to_user(optval, &val, len) ? -EFAULT : 0;
out:
+ unlock_kernel();
return rc;
}
return rc;
}
@@
-453,12
+471,14
@@
static int x25_listen(struct socket *sock, int backlog)
struct sock *sk = sock->sk;
int rc = -EOPNOTSUPP;
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;
}
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;
}
return rc;
}
@@
-488,19
+508,25
@@
out:
return sk;
}
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;
{
struct sock *sk;
struct x25_sock *x25;
- int rc = -ESOCKTNOSUPPORT;
+ int rc = -EAFNOSUPPORT;
+
+ if (!net_eq(net, &init_net))
+ goto out;
- if (net != &init_net)
- return -EAFNOSUPPORT;
+ rc = -ESOCKTNOSUPPORT;
+ if (sock->type != SOCK_SEQPACKET)
+ goto out;
- if (sock->type != SOCK_SEQPACKET || protocol)
+ rc = -EINVAL;
+ if (protocol)
goto out;
goto out;
- rc = -ENO
MEM
;
+ rc = -ENO
BUFS
;
if ((sk = x25_alloc_socket(net)) == NULL)
goto out;
if ((sk = x25_alloc_socket(net)) == NULL)
goto out;
@@
-584,6
+610,7
@@
static int x25_release(struct socket *sock)
struct sock *sk = sock->sk;
struct x25_sock *x25;
struct sock *sk = sock->sk;
struct x25_sock *x25;
+ lock_kernel();
if (!sk)
goto out;
if (!sk)
goto out;
@@
-614,6
+641,7
@@
static int x25_release(struct socket *sock)
sock_orphan(sk);
out:
sock_orphan(sk);
out:
+ unlock_kernel();
return 0;
}
return 0;
}
@@
-621,18
+649,31
@@
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;
{
struct sock *sk = sock->sk;
struct sockaddr_x25 *addr = (struct sockaddr_x25 *)uaddr;
+ int len, i, rc = 0;
+ lock_kernel();
if (!sock_flag(sk, SOCK_ZAPPED) ||
addr_len != sizeof(struct sockaddr_x25) ||
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;
+ }
+
+ len = strlen(addr->sx25_addr.x25_addr);
+ for (i = 0; i < len; i++) {
+ if (!isdigit(addr->sx25_addr.x25_addr[i])) {
+ 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");
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)
}
static int x25_wait_for_connection_establishment(struct sock *sk)
@@
-673,6
+714,7
@@
static int x25_connect(struct socket *sock, struct sockaddr *uaddr,
struct x25_route *rt;
int rc = 0;
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;
lock_sock(sk);
if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {
sock->state = SS_CONNECTED;
@@
-750,6
+792,7
@@
out_put_route:
x25_route_put(rt);
out:
release_sock(sk);
x25_route_put(rt);
out:
release_sock(sk);
+ unlock_kernel();
return rc;
}
return rc;
}
@@
-789,6
+832,7
@@
static int x25_accept(struct socket *sock, struct socket *newsock, int flags)
struct sk_buff *skb;
int rc = -EINVAL;
struct sk_buff *skb;
int rc = -EINVAL;
+ lock_kernel();
if (!sk || sk->sk_state != TCP_LISTEN)
goto out;
if (!sk || sk->sk_state != TCP_LISTEN)
goto out;
@@
-816,6
+860,7
@@
static int x25_accept(struct socket *sock, struct socket *newsock, int flags)
out2:
release_sock(sk);
out:
out2:
release_sock(sk);
out:
+ unlock_kernel();
return rc;
}
return rc;
}
@@
-825,10
+870,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);
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 (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;
sx25->sx25_addr = x25->dest_addr;
} else
sx25->sx25_addr = x25->source_addr;
@@
-836,7
+885,21
@@
static int x25_getname(struct socket *sock, struct sockaddr *uaddr,
sx25->sx25_family = AF_X25;
*uaddr_len = sizeof(*sx25);
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,
}
int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
@@
-951,10
+1014,8
@@
int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
/*
* Incoming Call User Data.
*/
/*
* Incoming Call User Data.
*/
- if (skb->len >= 0) {
- skb_copy_from_linear_data(skb, makex25->calluserdata.cuddata, skb->len);
- makex25->calluserdata.cudlength = skb->len;
- }
+ skb_copy_from_linear_data(skb, makex25->calluserdata.cuddata, skb->len);
+ makex25->calluserdata.cudlength = skb->len;
sk->sk_ack_backlog++;
sk->sk_ack_backlog++;
@@
-991,6
+1052,7
@@
static int x25_sendmsg(struct kiocb *iocb, struct socket *sock,
size_t size;
int qbit = 0, rc = -EINVAL;
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;
if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_OOB|MSG_EOR|MSG_CMSG_COMPAT))
goto out;
@@
-1037,6
+1099,12
@@
static int x25_sendmsg(struct kiocb *iocb, struct socket *sock,
sx25.sx25_addr = x25->dest_addr;
}
sx25.sx25_addr = x25->dest_addr;
}
+ /* Sanity check the packet size */
+ if (len > 65535) {
+ rc = -EMSGSIZE;
+ goto out;
+ }
+
SOCK_DEBUG(sk, "x25_sendmsg: sendto: Addresses built.\n");
/* Build a packet */
SOCK_DEBUG(sk, "x25_sendmsg: sendto: Addresses built.\n");
/* Build a packet */
@@
-1122,8
+1190,9
@@
static int x25_sendmsg(struct kiocb *iocb, struct socket *sock,
if (msg->msg_flags & MSG_OOB)
skb_queue_tail(&x25->interrupt_out_queue, skb);
else {
if (msg->msg_flags & MSG_OOB)
skb_queue_tail(&x25->interrupt_out_queue, skb);
else {
- len = x25_output(sk, skb);
- if (len < 0)
+ rc = x25_output(sk, skb);
+ len = rc;
+ if (rc < 0)
kfree_skb(skb);
else if (x25->qbitincl)
len++;
kfree_skb(skb);
else if (x25->qbitincl)
len++;
@@
-1148,6
+1217,7
@@
static int x25_sendmsg(struct kiocb *iocb, struct socket *sock,
release_sock(sk);
rc = len;
out:
release_sock(sk);
rc = len;
out:
+ unlock_kernel();
return rc;
out_kfree_skb:
kfree_skb(skb);
return rc;
out_kfree_skb:
kfree_skb(skb);
@@
-1168,6
+1238,7
@@
static int x25_recvmsg(struct kiocb *iocb, struct socket *sock,
unsigned char *asmptr;
int rc = -ENOTCONN;
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
/*
* This works for seqpacket too. The receiver has ordered the queue for
* us! We do one quick check first though
@@
-1241,6
+1312,7
@@
static int x25_recvmsg(struct kiocb *iocb, struct socket *sock,
out_free_dgram:
skb_free_datagram(sk, skb);
out:
out_free_dgram:
skb_free_datagram(sk, skb);
out:
+ unlock_kernel();
return rc;
}
return rc;
}
@@
-1252,10
+1324,11
@@
static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
void __user *argp = (void __user *)arg;
int rc;
void __user *argp = (void __user *)arg;
int rc;
+ lock_kernel();
switch (cmd) {
case TIOCOUTQ: {
switch (cmd) {
case TIOCOUTQ: {
- int amount = sk->sk_sndbuf -
- atomic_read(&sk->sk_wmem_alloc);
+ int amount = sk->sk_sndbuf -
sk_wmem_alloc_get(sk);
+
if (amount < 0)
amount = 0;
rc = put_user(amount, (unsigned int __user *)argp);
if (amount < 0)
amount = 0;
rc = put_user(amount, (unsigned int __user *)argp);
@@
-1345,7
+1418,7
@@
static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
facilities.throughput > 0xDD)
break;
if (facilities.reverse &&
facilities.throughput > 0xDD)
break;
if (facilities.reverse &&
- (facilities.reverse
| 0x81)
!= 0x81)
+ (facilities.reverse
& 0x81)
!= 0x81)
break;
x25->facilities = facilities;
rc = 0;
break;
x25->facilities = facilities;
rc = 0;
@@
-1412,6
+1485,17
@@
static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
break;
}
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;
case SIOCX25SCUDMATCHLEN: {
struct x25_subaddr sub_addr;
rc = -EINVAL;
@@
-1454,11
+1538,12
@@
static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
rc = -ENOIOCTLCMD;
break;
}
rc = -ENOIOCTLCMD;
break;
}
+ unlock_kernel();
return rc;
}
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,
.family = AF_X25,
.create = x25_create,
.owner = THIS_MODULE,
@@
-1524,15
+1609,19
@@
static int compat_x25_ioctl(struct socket *sock, unsigned int cmd,
break;
case SIOCGSTAMP:
rc = -EINVAL;
break;
case SIOCGSTAMP:
rc = -EINVAL;
+ lock_kernel();
if (sk)
rc = compat_sock_get_timestamp(sk,
(struct timeval __user*)argp);
if (sk)
rc = compat_sock_get_timestamp(sk,
(struct timeval __user*)argp);
+ unlock_kernel();
break;
case SIOCGSTAMPNS:
rc = -EINVAL;
break;
case SIOCGSTAMPNS:
rc = -EINVAL;
+ lock_kernel();
if (sk)
rc = compat_sock_get_timestampns(sk,
(struct timespec __user*)argp);
if (sk)
rc = compat_sock_get_timestampns(sk,
(struct timespec __user*)argp);
+ unlock_kernel();
break;
case SIOCGIFADDR:
case SIOCSIFADDR:
break;
case SIOCGIFADDR:
case SIOCSIFADDR:
@@
-1551,16
+1640,22
@@
static int compat_x25_ioctl(struct socket *sock, unsigned int cmd,
rc = -EPERM;
if (!capable(CAP_NET_ADMIN))
break;
rc = -EPERM;
if (!capable(CAP_NET_ADMIN))
break;
+ lock_kernel();
rc = x25_route_ioctl(cmd, argp);
rc = x25_route_ioctl(cmd, argp);
+ unlock_kernel();
break;
case SIOCX25GSUBSCRIP:
break;
case SIOCX25GSUBSCRIP:
+ lock_kernel();
rc = compat_x25_subscr_ioctl(cmd, argp);
rc = compat_x25_subscr_ioctl(cmd, argp);
+ unlock_kernel();
break;
case SIOCX25SSUBSCRIP:
rc = -EPERM;
if (!capable(CAP_NET_ADMIN))
break;
break;
case SIOCX25SSUBSCRIP:
rc = -EPERM;
if (!capable(CAP_NET_ADMIN))
break;
+ lock_kernel();
rc = compat_x25_subscr_ioctl(cmd, argp);
rc = compat_x25_subscr_ioctl(cmd, argp);
+ unlock_kernel();
break;
case SIOCX25GFACILITIES:
case SIOCX25SFACILITIES:
break;
case SIOCX25GFACILITIES:
case SIOCX25SFACILITIES:
@@
-1569,6
+1664,7
@@
static int compat_x25_ioctl(struct socket *sock, unsigned int cmd,
case SIOCX25GCALLUSERDATA:
case SIOCX25SCALLUSERDATA:
case SIOCX25GCAUSEDIAG:
case SIOCX25GCALLUSERDATA:
case SIOCX25SCALLUSERDATA:
case SIOCX25GCAUSEDIAG:
+ case SIOCX25SCAUSEDIAG:
case SIOCX25SCUDMATCHLEN:
case SIOCX25CALLACCPTAPPRV:
case SIOCX25SENDCALLACCPT:
case SIOCX25SCUDMATCHLEN:
case SIOCX25CALLACCPTAPPRV:
case SIOCX25SENDCALLACCPT:
@@
-1582,7
+1678,7
@@
static int compat_x25_ioctl(struct socket *sock, unsigned int cmd,
}
#endif
}
#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,
.family = AF_X25,
.owner = THIS_MODULE,
.release = x25_release,
@@
-1591,7
+1687,7
@@
static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {
.socketpair = sock_no_socketpair,
.accept = x25_accept,
.getname = x25_getname,
.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,
.ioctl = x25_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = compat_x25_ioctl,
@@
-1606,9
+1702,7
@@
static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {
.sendpage = sock_no_sendpage,
};
.sendpage = sock_no_sendpage,
};
-SOCKOPS_WRAP(x25_proto, AF_X25);
-
-static struct packet_type x25_packet_type = {
+static struct packet_type x25_packet_type __read_mostly = {
.type = cpu_to_be16(ETH_P_X25),
.func = x25_lapb_receive_frame,
};
.type = cpu_to_be16(ETH_P_X25),
.func = x25_lapb_receive_frame,
};
@@
-1641,20
+1735,31
@@
static int __init x25_init(void)
if (rc != 0)
goto out;
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);
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");
printk(KERN_INFO "X.25 for Linux Version 0.2\n");
-#ifdef CONFIG_SYSCTL
x25_register_sysctl();
x25_register_sysctl();
-#endif
- x25_proc_init();
+ rc = x25_proc_init();
+ if (rc != 0)
+ goto out_dev;
out:
return rc;
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);
}
module_init(x25_init);
@@
-1664,9
+1769,7
@@
static void __exit x25_exit(void)
x25_link_free();
x25_route_free();
x25_link_free();
x25_route_free();
-#ifdef CONFIG_SYSCTL
x25_unregister_sysctl();
x25_unregister_sysctl();
-#endif
unregister_netdevice_notifier(&x25_dev_notifier);
unregister_netdevice_notifier(&x25_dev_notifier);