aboutsummaryrefslogtreecommitdiff
path: root/net/ax25
diff options
context:
space:
mode:
Diffstat (limited to 'net/ax25')
-rw-r--r--net/ax25/Kconfig8
-rw-r--r--net/ax25/af_ax25.c223
-rw-r--r--net/ax25/ax25_addr.c7
-rw-r--r--net/ax25/ax25_dev.c12
-rw-r--r--net/ax25/ax25_ds_in.c1
-rw-r--r--net/ax25/ax25_ds_subr.c8
-rw-r--r--net/ax25/ax25_ds_timer.c6
-rw-r--r--net/ax25/ax25_iface.c21
-rw-r--r--net/ax25/ax25_in.c50
-rw-r--r--net/ax25/ax25_ip.c6
-rw-r--r--net/ax25/ax25_out.c10
-rw-r--r--net/ax25/ax25_route.c11
-rw-r--r--net/ax25/ax25_std_in.c1
-rw-r--r--net/ax25/ax25_std_subr.c1
-rw-r--r--net/ax25/ax25_std_timer.c1
-rw-r--r--net/ax25/ax25_subr.c13
-rw-r--r--net/ax25/ax25_timer.c1
-rw-r--r--net/ax25/ax25_uid.c56
-rw-r--r--net/ax25/sysctl_net_ax25.c159
19 files changed, 242 insertions, 353 deletions
diff --git a/net/ax25/Kconfig b/net/ax25/Kconfig
index 2a72aa96a56..705e53ef4af 100644
--- a/net/ax25/Kconfig
+++ b/net/ax25/Kconfig
@@ -7,7 +7,7 @@ menuconfig HAMRADIO
bool "Amateur Radio support"
help
If you want to connect your Linux box to an amateur radio, answer Y
- here. You want to read <http://www.tapr.org/tapr/html/pkthome.html>
+ here. You want to read <http://www.tapr.org/>
and more specifically about AX.25 on Linux
<http://www.linux-ax25.org/>.
@@ -42,7 +42,7 @@ config AX25
check out the file <file:Documentation/networking/ax25.txt> in the
kernel source. More information about digital amateur radio in
general is on the WWW at
- <http://www.tapr.org/tapr/html/pkthome.html>.
+ <http://www.tapr.org/>.
To compile this driver as a module, choose M here: the
module will be called ax25.
@@ -89,7 +89,7 @@ config NETROM
<http://www.linux-ax25.org>. You also might want to check out the
file <file:Documentation/networking/ax25.txt>. More information about
digital amateur radio in general is on the WWW at
- <http://www.tapr.org/tapr/html/pkthome.html>.
+ <http://www.tapr.org/>.
To compile this driver as a module, choose M here: the
module will be called netrom.
@@ -108,7 +108,7 @@ config ROSE
<http://www.linux-ax25.org>. You also might want to check out the
file <file:Documentation/networking/ax25.txt>. More information about
digital amateur radio in general is on the WWW at
- <http://www.tapr.org/tapr/html/pkthome.html>.
+ <http://www.tapr.org/>.
To compile this driver as a module, choose M here: the
module will be called rose.
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index 48bfcc741f2..c35c3f48fc0 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -25,6 +25,7 @@
#include <linux/string.h>
#include <linux/sockios.h>
#include <linux/net.h>
+#include <linux/slab.h>
#include <net/ax25.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
@@ -32,7 +33,6 @@
#include <linux/skbuff.h>
#include <net/sock.h>
#include <asm/uaccess.h>
-#include <asm/system.h>
#include <linux/fcntl.h>
#include <linux/termios.h> /* For TIOCINQ/OUTQ */
#include <linux/mm.h>
@@ -81,14 +81,13 @@ static void ax25_kill_by_device(struct net_device *dev)
{
ax25_dev *ax25_dev;
ax25_cb *s;
- struct hlist_node *node;
if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL)
return;
spin_lock_bh(&ax25_list_lock);
again:
- ax25_for_each(s, node, &ax25_list) {
+ ax25_for_each(s, &ax25_list) {
if (s->ax25_dev == ax25_dev) {
s->ax25_dev = NULL;
spin_unlock_bh(&ax25_list_lock);
@@ -112,11 +111,11 @@ again:
* Handle device status changes.
*/
static int ax25_device_event(struct notifier_block *this, unsigned long event,
- void *ptr)
+ void *ptr)
{
- struct net_device *dev = (struct net_device *)ptr;
+ struct net_device *dev = netdev_notifier_info_to_dev(ptr);
- if (dev->nd_net != &init_net)
+ if (!net_eq(dev_net(dev), &init_net))
return NOTIFY_DONE;
/* Reject non AX.25 devices */
@@ -158,10 +157,9 @@ struct sock *ax25_find_listener(ax25_address *addr, int digi,
struct net_device *dev, int type)
{
ax25_cb *s;
- struct hlist_node *node;
spin_lock(&ax25_list_lock);
- ax25_for_each(s, node, &ax25_list) {
+ ax25_for_each(s, &ax25_list) {
if ((s->iamdigi && !digi) || (!s->iamdigi && digi))
continue;
if (s->sk && !ax25cmp(&s->source_addr, addr) &&
@@ -187,10 +185,9 @@ struct sock *ax25_get_socket(ax25_address *my_addr, ax25_address *dest_addr,
{
struct sock *sk = NULL;
ax25_cb *s;
- struct hlist_node *node;
spin_lock(&ax25_list_lock);
- ax25_for_each(s, node, &ax25_list) {
+ ax25_for_each(s, &ax25_list) {
if (s->sk && !ax25cmp(&s->source_addr, my_addr) &&
!ax25cmp(&s->dest_addr, dest_addr) &&
s->sk->sk_type == type) {
@@ -213,10 +210,9 @@ ax25_cb *ax25_find_cb(ax25_address *src_addr, ax25_address *dest_addr,
ax25_digi *digi, struct net_device *dev)
{
ax25_cb *s;
- struct hlist_node *node;
spin_lock_bh(&ax25_list_lock);
- ax25_for_each(s, node, &ax25_list) {
+ ax25_for_each(s, &ax25_list) {
if (s->sk && s->sk->sk_type != SOCK_SEQPACKET)
continue;
if (s->ax25_dev == NULL)
@@ -248,10 +244,9 @@ void ax25_send_to_raw(ax25_address *addr, struct sk_buff *skb, int proto)
{
ax25_cb *s;
struct sk_buff *copy;
- struct hlist_node *node;
spin_lock(&ax25_list_lock);
- ax25_for_each(s, node, &ax25_list) {
+ ax25_for_each(s, &ax25_list) {
if (s->sk != NULL && ax25cmp(&s->source_addr, addr) == 0 &&
s->sk->sk_type == SOCK_RAW &&
s->sk->sk_protocol == proto &&
@@ -317,6 +312,9 @@ void ax25_destroy_socket(ax25_cb *ax25)
/* Queue the unaccepted socket for death */
sock_orphan(skb->sk);
+ /* 9A4GL: hack to release unaccepted sockets */
+ skb->sk->sk_state = TCP_LISTEN;
+
ax25_start_heartbeat(sax25);
sax25->state = AX25_STATE_0;
}
@@ -327,8 +325,7 @@ void ax25_destroy_socket(ax25_cb *ax25)
}
if (ax25->sk != NULL) {
- if (atomic_read(&ax25->sk->sk_wmem_alloc) ||
- atomic_read(&ax25->sk->sk_rmem_alloc)) {
+ if (sk_has_allocations(ax25->sk)) {
/* Defer: outstanding buffers */
setup_timer(&ax25->dtimer, ax25_destroy_timer,
(unsigned long)ax25);
@@ -356,6 +353,7 @@ static int ax25_ctl_ioctl(const unsigned int cmd, void __user *arg)
ax25_dev *ax25_dev;
ax25_cb *ax25;
unsigned int k;
+ int ret = 0;
if (copy_from_user(&ax25_ctl, arg, sizeof(ax25_ctl)))
return -EFAULT;
@@ -366,6 +364,9 @@ static int ax25_ctl_ioctl(const unsigned int cmd, void __user *arg)
if (ax25_ctl.digi_count > AX25_MAX_DIGIS)
return -EINVAL;
+ if (ax25_ctl.arg > ULONG_MAX / HZ && ax25_ctl.cmd != AX25_KILL)
+ return -EINVAL;
+
digi.ndigi = ax25_ctl.digi_count;
for (k = 0; k < digi.ndigi; k++)
digi.calls[k] = ax25_ctl.digi_addr[k];
@@ -386,57 +387,64 @@ static int ax25_ctl_ioctl(const unsigned int cmd, void __user *arg)
case AX25_WINDOW:
if (ax25->modulus == AX25_MODULUS) {
if (ax25_ctl.arg < 1 || ax25_ctl.arg > 7)
- return -EINVAL;
+ goto einval_put;
} else {
if (ax25_ctl.arg < 1 || ax25_ctl.arg > 63)
- return -EINVAL;
+ goto einval_put;
}
ax25->window = ax25_ctl.arg;
break;
case AX25_T1:
- if (ax25_ctl.arg < 1)
- return -EINVAL;
+ if (ax25_ctl.arg < 1 || ax25_ctl.arg > ULONG_MAX / HZ)
+ goto einval_put;
ax25->rtt = (ax25_ctl.arg * HZ) / 2;
ax25->t1 = ax25_ctl.arg * HZ;
break;
case AX25_T2:
- if (ax25_ctl.arg < 1)
- return -EINVAL;
+ if (ax25_ctl.arg < 1 || ax25_ctl.arg > ULONG_MAX / HZ)
+ goto einval_put;
ax25->t2 = ax25_ctl.arg * HZ;
break;
case AX25_N2:
if (ax25_ctl.arg < 1 || ax25_ctl.arg > 31)
- return -EINVAL;
+ goto einval_put;
ax25->n2count = 0;
ax25->n2 = ax25_ctl.arg;
break;
case AX25_T3:
- if (ax25_ctl.arg < 0)
- return -EINVAL;
+ if (ax25_ctl.arg > ULONG_MAX / HZ)
+ goto einval_put;
ax25->t3 = ax25_ctl.arg * HZ;
break;
case AX25_IDLE:
- if (ax25_ctl.arg < 0)
- return -EINVAL;
+ if (ax25_ctl.arg > ULONG_MAX / (60 * HZ))
+ goto einval_put;
+
ax25->idle = ax25_ctl.arg * 60 * HZ;
break;
case AX25_PACLEN:
if (ax25_ctl.arg < 16 || ax25_ctl.arg > 65535)
- return -EINVAL;
+ goto einval_put;
ax25->paclen = ax25_ctl.arg;
break;
default:
- return -EINVAL;
+ goto einval_put;
}
- return 0;
+out_put:
+ ax25_cb_put(ax25);
+ return ret;
+
+einval_put:
+ ret = -EINVAL;
+ goto out_put;
}
static void ax25_fillin_cb_from_dev(ax25_cb *ax25, ax25_dev *ax25_dev)
@@ -525,21 +533,22 @@ ax25_cb *ax25_create_cb(void)
*/
static int ax25_setsockopt(struct socket *sock, int level, int optname,
- char __user *optval, int optlen)
+ char __user *optval, unsigned int optlen)
{
struct sock *sk = sock->sk;
ax25_cb *ax25;
struct net_device *dev;
char devname[IFNAMSIZ];
- int opt, res = 0;
+ unsigned long opt;
+ int res = 0;
if (level != SOL_AX25)
return -ENOPROTOOPT;
- if (optlen < sizeof(int))
+ if (optlen < sizeof(unsigned int))
return -EINVAL;
- if (get_user(opt, (int __user *)optval))
+ if (get_user(opt, (unsigned int __user *)optval))
return -EFAULT;
lock_sock(sk);
@@ -562,7 +571,7 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname,
break;
case AX25_T1:
- if (opt < 1) {
+ if (opt < 1 || opt > ULONG_MAX / HZ) {
res = -EINVAL;
break;
}
@@ -571,7 +580,7 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname,
break;
case AX25_T2:
- if (opt < 1) {
+ if (opt < 1 || opt > ULONG_MAX / HZ) {
res = -EINVAL;
break;
}
@@ -587,7 +596,7 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname,
break;
case AX25_T3:
- if (opt < 1) {
+ if (opt < 1 || opt > ULONG_MAX / HZ) {
res = -EINVAL;
break;
}
@@ -595,7 +604,7 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname,
break;
case AX25_IDLE:
- if (opt < 0) {
+ if (opt > ULONG_MAX / (60 * HZ)) {
res = -EINVAL;
break;
}
@@ -603,7 +612,7 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname,
break;
case AX25_BACKOFF:
- if (opt < 0 || opt > 2) {
+ if (opt > 2) {
res = -EINVAL;
break;
}
@@ -632,15 +641,10 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname,
case SO_BINDTODEVICE:
if (optlen > IFNAMSIZ)
- optlen=IFNAMSIZ;
- if (copy_from_user(devname, optval, optlen)) {
- res = -EFAULT;
- break;
- }
+ optlen = IFNAMSIZ;
- dev = dev_get_by_name(&init_net, devname);
- if (dev == NULL) {
- res = -ENODEV;
+ if (copy_from_user(devname, optval, optlen)) {
+ res = -EFAULT;
break;
}
@@ -648,12 +652,18 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname,
(sock->state != SS_UNCONNECTED ||
sk->sk_state == TCP_LISTEN)) {
res = -EADDRNOTAVAIL;
- dev_put(dev);
+ break;
+ }
+
+ dev = dev_get_by_name(&init_net, devname);
+ if (!dev) {
+ res = -ENODEV;
break;
}
ax25->ax25_dev = ax25_dev_ax25dev(dev);
ax25_fillin_cb(ax25, ax25->ax25_dev);
+ dev_put(dev);
break;
default:
@@ -790,12 +800,13 @@ static struct proto ax25_proto = {
.obj_size = sizeof(struct sock),
};
-static int ax25_create(struct net *net, struct socket *sock, int protocol)
+static int ax25_create(struct net *net, struct socket *sock, int protocol,
+ int kern)
{
struct sock *sk;
ax25_cb *ax25;
- if (net != &init_net)
+ if (!net_eq(net, &init_net))
return -EAFNOSUPPORT;
switch (sock->type) {
@@ -826,6 +837,7 @@ static int ax25_create(struct net *net, struct socket *sock, int protocol)
case AX25_P_NETROM:
if (ax25_protocol_is_registered(AX25_P_NETROM))
return -ESOCKTNOSUPPORT;
+ break;
#endif
#ifdef CONFIG_ROSE_MODULE
case AX25_P_ROSE:
@@ -869,7 +881,7 @@ struct sock *ax25_make_new(struct sock *osk, struct ax25_dev *ax25_dev)
struct sock *sk;
ax25_cb *ax25, *oax25;
- sk = sk_alloc(osk->sk_net, PF_AX25, GFP_ATOMIC, osk->sk_prot);
+ sk = sk_alloc(sock_net(osk), PF_AX25, GFP_ATOMIC, osk->sk_prot);
if (sk == NULL)
return NULL;
@@ -891,15 +903,12 @@ struct sock *ax25_make_new(struct sock *osk, struct ax25_dev *ax25_dev)
sock_init_data(NULL, sk);
- sk->sk_destruct = ax25_free_sock;
sk->sk_type = osk->sk_type;
- sk->sk_socket = osk->sk_socket;
sk->sk_priority = osk->sk_priority;
sk->sk_protocol = osk->sk_protocol;
sk->sk_rcvbuf = osk->sk_rcvbuf;
sk->sk_sndbuf = osk->sk_sndbuf;
sk->sk_state = TCP_ESTABLISHED;
- sk->sk_sleep = osk->sk_sleep;
sock_copy_flags(sk, osk);
oax25 = ax25_sk(osk);
@@ -931,6 +940,7 @@ struct sock *ax25_make_new(struct sock *osk, struct ax25_dev *ax25_dev)
}
sk->sk_protinfo = ax25;
+ sk->sk_destruct = ax25_free_sock;
ax25->sk = sk;
return sk;
@@ -1044,7 +1054,7 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
if (addr->fsa_ax25.sax25_family != AF_AX25)
return -EINVAL;
- user = ax25_findbyuid(current->euid);
+ user = ax25_findbyuid(current_euid());
if (user) {
call = user->call;
ax25_uid_put(user);
@@ -1094,7 +1104,7 @@ done:
out:
release_sock(sk);
- return 0;
+ return err;
}
/*
@@ -1272,7 +1282,7 @@ static int __must_check ax25_connect(struct socket *sock,
DEFINE_WAIT(wait);
for (;;) {
- prepare_to_wait(sk->sk_sleep, &wait,
+ prepare_to_wait(sk_sleep(sk), &wait,
TASK_INTERRUPTIBLE);
if (sk->sk_state != TCP_SYN_SENT)
break;
@@ -1285,7 +1295,7 @@ static int __must_check ax25_connect(struct socket *sock,
err = -ERESTARTSYS;
break;
}
- finish_wait(sk->sk_sleep, &wait);
+ finish_wait(sk_sleep(sk), &wait);
if (err)
goto out_release;
@@ -1337,7 +1347,7 @@ static int ax25_accept(struct socket *sock, struct socket *newsock, int flags)
* hooked into the SABM we saved
*/
for (;;) {
- prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
+ prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
skb = skb_dequeue(&sk->sk_receive_queue);
if (skb)
break;
@@ -1355,19 +1365,17 @@ static int ax25_accept(struct socket *sock, struct socket *newsock, int flags)
err = -ERESTARTSYS;
break;
}
- finish_wait(sk->sk_sleep, &wait);
+ finish_wait(sk_sleep(sk), &wait);
if (err)
goto out;
newsk = skb->sk;
- newsk->sk_socket = newsock;
- newsk->sk_sleep = &newsock->wait;
+ sock_graft(newsk, newsock);
/* Now attach up the new socket */
kfree_skb(skb);
sk->sk_ack_backlog--;
- newsock->sk = newsk;
newsock->state = SS_CONNECTED;
out:
@@ -1385,6 +1393,7 @@ static int ax25_getname(struct socket *sock, struct sockaddr *uaddr,
ax25_cb *ax25;
int err = 0;
+ memset(fsa, 0, sizeof(*fsa));
lock_sock(sk);
ax25 = ax25_sk(sk);
@@ -1396,7 +1405,6 @@ static int ax25_getname(struct socket *sock, struct sockaddr *uaddr,
fsa->fsa_ax25.sax25_family = AF_AX25;
fsa->fsa_ax25.sax25_call = ax25->dest_addr;
- fsa->fsa_ax25.sax25_ndigis = 0;
if (ax25->digipeat != NULL) {
ndigi = ax25->digipeat->ndigi;
@@ -1427,7 +1435,7 @@ out:
static int ax25_sendmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t len)
{
- struct sockaddr_ax25 *usax = (struct sockaddr_ax25 *)msg->msg_name;
+ DECLARE_SOCKADDR(struct sockaddr_ax25 *, usax, msg->msg_name);
struct sock *sk = sock->sk;
struct sockaddr_ax25 sax;
struct sk_buff *skb;
@@ -1530,11 +1538,7 @@ static int ax25_sendmsg(struct kiocb *iocb, struct socket *sock,
dp = ax25->digipeat;
}
- SOCK_DEBUG(sk, "AX.25: sendto: Addresses built.\n");
-
/* Build a packet */
- SOCK_DEBUG(sk, "AX.25: sendto: building packet.\n");
-
/* Assume the worst case */
size = len + ax25->ax25_dev->dev->hard_header_len;
@@ -1544,8 +1548,6 @@ static int ax25_sendmsg(struct kiocb *iocb, struct socket *sock,
skb_reserve(skb, size - len);
- SOCK_DEBUG(sk, "AX.25: Appending user data\n");
-
/* User data follows immediately after the AX.25 data */
if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
err = -EFAULT;
@@ -1559,8 +1561,6 @@ static int ax25_sendmsg(struct kiocb *iocb, struct socket *sock,
if (!ax25->pidincl)
*skb_push(skb, 1) = sk->sk_protocol;
- SOCK_DEBUG(sk, "AX.25: Transmitting buffer\n");
-
if (sk->sk_type == SOCK_SEQPACKET) {
/* Connected mode sockets go via the LAPB machine */
if (sk->sk_state != TCP_ESTABLISHED) {
@@ -1578,22 +1578,14 @@ static int ax25_sendmsg(struct kiocb *iocb, struct socket *sock,
skb_push(skb, 1 + ax25_addr_size(dp));
- SOCK_DEBUG(sk, "Building AX.25 Header (dp=%p).\n", dp);
-
- if (dp != NULL)
- SOCK_DEBUG(sk, "Num digipeaters=%d\n", dp->ndigi);
+ /* Building AX.25 Header */
/* Build an AX.25 header */
lv = ax25_addr_build(skb->data, &ax25->source_addr, &sax.sax25_call,
dp, AX25_COMMAND, AX25_MODULUS);
- SOCK_DEBUG(sk, "Built header (%d bytes)\n",lv);
-
skb_set_transport_header(skb, lv);
- SOCK_DEBUG(sk, "base=%p pos=%p\n",
- skb->data, skb_transport_header(skb));
-
*skb_transport_header(skb) = AX25_UI;
/* Datagram frames go straight out of the door as UI */
@@ -1644,12 +1636,13 @@ static int ax25_recvmsg(struct kiocb *iocb, struct socket *sock,
skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
- if (msg->msg_namelen != 0) {
- struct sockaddr_ax25 *sax = (struct sockaddr_ax25 *)msg->msg_name;
+ if (msg->msg_name) {
ax25_digi digi;
ax25_address src;
const unsigned char *mac = skb_mac_header(skb);
+ DECLARE_SOCKADDR(struct sockaddr_ax25 *, sax, msg->msg_name);
+ memset(sax, 0, sizeof(struct full_sockaddr_ax25));
ax25_addr_parse(mac + 1, skb->data - mac - 1, &src, NULL,
&digi, NULL, NULL);
sax->sax25_family = AF_AX25;
@@ -1694,7 +1687,8 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
switch (cmd) {
case TIOCOUTQ: {
long amount;
- amount = sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc);
+
+ amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
if (amount < 0)
amount = 0;
res = put_user(amount, (int __user *)argp);
@@ -1741,7 +1735,7 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
res = -EFAULT;
break;
}
- if (amount > AX25_NOUID_BLOCK) {
+ if (amount < 0 || amount > AX25_NOUID_BLOCK) {
res = -EINVAL;
break;
}
@@ -1784,8 +1778,8 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
ax25_info.idletimer = ax25_display_timer(&ax25->idletimer) / (60 * HZ);
ax25_info.n2count = ax25->n2count;
ax25_info.state = ax25->state;
- ax25_info.rcv_q = atomic_read(&sk->sk_rmem_alloc);
- ax25_info.snd_q = atomic_read(&sk->sk_wmem_alloc);
+ ax25_info.rcv_q = sk_rmem_alloc_get(sk);
+ ax25_info.snd_q = sk_wmem_alloc_get(sk);
ax25_info.vs = ax25->vs;
ax25_info.vr = ax25->vr;
ax25_info.va = ax25->va;
@@ -1858,25 +1852,13 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
static void *ax25_info_start(struct seq_file *seq, loff_t *pos)
__acquires(ax25_list_lock)
{
- struct ax25_cb *ax25;
- struct hlist_node *node;
- int i = 0;
-
spin_lock_bh(&ax25_list_lock);
- ax25_for_each(ax25, node, &ax25_list) {
- if (i == *pos)
- return ax25;
- ++i;
- }
- return NULL;
+ return seq_hlist_start(&ax25_list, *pos);
}
static void *ax25_info_next(struct seq_file *seq, void *v, loff_t *pos)
{
- ++*pos;
-
- return hlist_entry( ((struct ax25_cb *)v)->ax25_node.next,
- struct ax25_cb, ax25_node);
+ return seq_hlist_next(v, &ax25_list, pos);
}
static void ax25_info_stop(struct seq_file *seq, void *v)
@@ -1887,7 +1869,7 @@ static void ax25_info_stop(struct seq_file *seq, void *v)
static int ax25_info_show(struct seq_file *seq, void *v)
{
- ax25_cb *ax25 = v;
+ ax25_cb *ax25 = hlist_entry(v, struct ax25_cb, ax25_node);
char buf[11];
int k;
@@ -1925,8 +1907,8 @@ static int ax25_info_show(struct seq_file *seq, void *v)
if (ax25->sk != NULL) {
seq_printf(seq, " %d %d %lu\n",
- atomic_read(&ax25->sk->sk_wmem_alloc),
- atomic_read(&ax25->sk->sk_rmem_alloc),
+ sk_wmem_alloc_get(ax25->sk),
+ sk_rmem_alloc_get(ax25->sk),
sock_i_ino(ax25->sk));
} else {
seq_puts(seq, " * * *\n");
@@ -1956,7 +1938,7 @@ static const struct file_operations ax25_info_fops = {
#endif
-static struct net_proto_family ax25_family_ops = {
+static const struct net_proto_family ax25_family_ops = {
.family = PF_AX25,
.create = ax25_create,
.owner = THIS_MODULE,
@@ -1986,14 +1968,13 @@ static const struct proto_ops ax25_proto_ops = {
/*
* Called by socket.c on kernel start up
*/
-static struct packet_type ax25_packet_type = {
- .type = __constant_htons(ETH_P_AX25),
- .dev = NULL, /* All devices */
+static struct packet_type ax25_packet_type __read_mostly = {
+ .type = cpu_to_be16(ETH_P_AX25),
.func = ax25_kiss_rcv,
};
static struct notifier_block ax25_dev_notifier = {
- .notifier_call =ax25_device_event,
+ .notifier_call = ax25_device_event,
};
static int __init ax25_init(void)
@@ -2006,11 +1987,11 @@ static int __init ax25_init(void)
sock_register(&ax25_family_ops);
dev_add_pack(&ax25_packet_type);
register_netdevice_notifier(&ax25_dev_notifier);
- ax25_register_sysctl();
- proc_net_fops_create(&init_net, "ax25_route", S_IRUGO, &ax25_route_fops);
- proc_net_fops_create(&init_net, "ax25", S_IRUGO, &ax25_info_fops);
- proc_net_fops_create(&init_net, "ax25_calls", S_IRUGO, &ax25_uid_fops);
+ proc_create("ax25_route", S_IRUGO, init_net.proc_net,
+ &ax25_route_fops);
+ proc_create("ax25", S_IRUGO, init_net.proc_net, &ax25_info_fops);
+ proc_create("ax25_calls", S_IRUGO, init_net.proc_net, &ax25_uid_fops);
out:
return rc;
}
@@ -2024,19 +2005,19 @@ MODULE_ALIAS_NETPROTO(PF_AX25);
static void __exit ax25_exit(void)
{
- proc_net_remove(&init_net, "ax25_route");
- proc_net_remove(&init_net, "ax25");
- proc_net_remove(&init_net, "ax25_calls");
- ax25_rt_free();
- ax25_uid_free();
- ax25_dev_free();
+ remove_proc_entry("ax25_route", init_net.proc_net);
+ remove_proc_entry("ax25", init_net.proc_net);
+ remove_proc_entry("ax25_calls", init_net.proc_net);
- ax25_unregister_sysctl();
unregister_netdevice_notifier(&ax25_dev_notifier);
dev_remove_pack(&ax25_packet_type);
sock_unregister(PF_AX25);
proto_unregister(&ax25_proto);
+
+ ax25_rt_free();
+ ax25_uid_free();
+ ax25_dev_free();
}
module_exit(ax25_exit);
diff --git a/net/ax25/ax25_addr.c b/net/ax25/ax25_addr.c
index 7e7964dd987..e7c9b0ea17a 100644
--- a/net/ax25/ax25_addr.c
+++ b/net/ax25/ax25_addr.c
@@ -22,7 +22,6 @@
#include <linux/skbuff.h>
#include <net/sock.h>
#include <asm/uaccess.h>
-#include <asm/system.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
@@ -190,8 +189,10 @@ const unsigned char *ax25_addr_parse(const unsigned char *buf, int len,
digi->ndigi = 0;
while (!(buf[-1] & AX25_EBIT)) {
- if (d >= AX25_MAX_DIGIS) return NULL; /* Max of 6 digis */
- if (len < 7) return NULL; /* Short packet */
+ if (d >= AX25_MAX_DIGIS)
+ return NULL;
+ if (len < AX25_ADDR_LEN)
+ return NULL;
memcpy(&digi->calls[d], buf, AX25_ADDR_LEN);
digi->ndigi = d + 1;
diff --git a/net/ax25/ax25_dev.c b/net/ax25/ax25_dev.c
index a7a0e0c9698..3d106767b27 100644
--- a/net/ax25/ax25_dev.c
+++ b/net/ax25/ax25_dev.c
@@ -9,6 +9,7 @@
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
+#include <linux/slab.h>
#include <linux/in.h>
#include <linux/kernel.h>
#include <linux/timer.h>
@@ -23,7 +24,6 @@
#include <linux/skbuff.h>
#include <net/sock.h>
#include <asm/uaccess.h>
-#include <asm/system.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
@@ -59,8 +59,6 @@ void ax25_dev_device_up(struct net_device *dev)
return;
}
- ax25_unregister_sysctl();
-
dev->ax25_ptr = ax25_dev;
ax25_dev->dev = dev;
dev_hold(dev);
@@ -90,7 +88,7 @@ void ax25_dev_device_up(struct net_device *dev)
ax25_dev_list = ax25_dev;
spin_unlock_bh(&ax25_dev_lock);
- ax25_register_sysctl();
+ ax25_register_dev_sysctl(ax25_dev);
}
void ax25_dev_device_down(struct net_device *dev)
@@ -100,7 +98,7 @@ void ax25_dev_device_down(struct net_device *dev)
if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL)
return;
- ax25_unregister_sysctl();
+ ax25_unregister_dev_sysctl(ax25_dev);
spin_lock_bh(&ax25_dev_lock);
@@ -120,7 +118,6 @@ void ax25_dev_device_down(struct net_device *dev)
spin_unlock_bh(&ax25_dev_lock);
dev_put(dev);
kfree(ax25_dev);
- ax25_register_sysctl();
return;
}
@@ -130,7 +127,6 @@ void ax25_dev_device_down(struct net_device *dev)
spin_unlock_bh(&ax25_dev_lock);
dev_put(dev);
kfree(ax25_dev);
- ax25_register_sysctl();
return;
}
@@ -138,8 +134,6 @@ void ax25_dev_device_down(struct net_device *dev)
}
spin_unlock_bh(&ax25_dev_lock);
dev->ax25_ptr = NULL;
-
- ax25_register_sysctl();
}
int ax25_fwd_ioctl(unsigned int cmd, struct ax25_fwd_struct *fwd)
diff --git a/net/ax25/ax25_ds_in.c b/net/ax25/ax25_ds_in.c
index 8273b1200ee..9bd31e88aec 100644
--- a/net/ax25/ax25_ds_in.c
+++ b/net/ax25/ax25_ds_in.c
@@ -23,7 +23,6 @@
#include <net/sock.h>
#include <net/tcp_states.h>
#include <asm/uaccess.h>
-#include <asm/system.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
diff --git a/net/ax25/ax25_ds_subr.c b/net/ax25/ax25_ds_subr.c
index b5e59787be2..e05bd57b5af 100644
--- a/net/ax25/ax25_ds_subr.c
+++ b/net/ax25/ax25_ds_subr.c
@@ -17,13 +17,13 @@
#include <linux/sockios.h>
#include <linux/spinlock.h>
#include <linux/net.h>
+#include <linux/gfp.h>
#include <net/ax25.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <net/sock.h>
#include <asm/uaccess.h>
-#include <asm/system.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
@@ -39,7 +39,6 @@ void ax25_ds_nr_error_recovery(ax25_cb *ax25)
void ax25_ds_enquiry_response(ax25_cb *ax25)
{
ax25_cb *ax25o;
- struct hlist_node *node;
/* Please note that neither DK4EG's nor DG2FEF's
* DAMA spec mention the following behaviour as seen
@@ -80,7 +79,7 @@ void ax25_ds_enquiry_response(ax25_cb *ax25)
ax25_ds_set_timer(ax25->ax25_dev);
spin_lock(&ax25_list_lock);
- ax25_for_each(ax25o, node, &ax25_list) {
+ ax25_for_each(ax25o, &ax25_list) {
if (ax25o == ax25)
continue;
@@ -159,10 +158,9 @@ static int ax25_check_dama_slave(ax25_dev *ax25_dev)
{
ax25_cb *ax25;
int res = 0;
- struct hlist_node *node;
spin_lock(&ax25_list_lock);
- ax25_for_each(ax25, node, &ax25_list)
+ ax25_for_each(ax25, &ax25_list)
if (ax25->ax25_dev == ax25_dev && (ax25->condition & AX25_COND_DAMA_MODE) && ax25->state > AX25_STATE_1) {
res = 1;
break;
diff --git a/net/ax25/ax25_ds_timer.c b/net/ax25/ax25_ds_timer.c
index 2ce79df0068..951cd57bb07 100644
--- a/net/ax25/ax25_ds_timer.c
+++ b/net/ax25/ax25_ds_timer.c
@@ -25,7 +25,6 @@
#include <linux/skbuff.h>
#include <net/sock.h>
#include <asm/uaccess.h>
-#include <asm/system.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
@@ -71,7 +70,6 @@ static void ax25_ds_timeout(unsigned long arg)
{
ax25_dev *ax25_dev = (struct ax25_dev *) arg;
ax25_cb *ax25;
- struct hlist_node *node;
if (ax25_dev == NULL || !ax25_dev->dama.slave)
return; /* Yikes! */
@@ -82,7 +80,7 @@ static void ax25_ds_timeout(unsigned long arg)
}
spin_lock(&ax25_list_lock);
- ax25_for_each(ax25, node, &ax25_list) {
+ ax25_for_each(ax25, &ax25_list) {
if (ax25->ax25_dev != ax25_dev || !(ax25->condition & AX25_COND_DAMA_MODE))
continue;
@@ -112,8 +110,8 @@ void ax25_ds_heartbeat_expiry(ax25_cb *ax25)
if (sk) {
sock_hold(sk);
ax25_destroy_socket(ax25);
- sock_put(sk);
bh_unlock_sock(sk);
+ sock_put(sk);
} else
ax25_destroy_socket(ax25);
return;
diff --git a/net/ax25/ax25_iface.c b/net/ax25/ax25_iface.c
index 8443af57a37..7f16e8a931b 100644
--- a/net/ax25/ax25_iface.c
+++ b/net/ax25/ax25_iface.c
@@ -17,13 +17,13 @@
#include <linux/string.h>
#include <linux/sockios.h>
#include <linux/net.h>
+#include <linux/slab.h>
#include <net/ax25.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <net/sock.h>
#include <asm/uaccess.h>
-#include <asm/system.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
@@ -57,31 +57,27 @@ EXPORT_SYMBOL_GPL(ax25_register_pid);
void ax25_protocol_release(unsigned int pid)
{
- struct ax25_protocol *s, *protocol;
+ struct ax25_protocol *protocol;
write_lock_bh(&protocol_list_lock);
protocol = protocol_list;
- if (protocol == NULL) {
- write_unlock_bh(&protocol_list_lock);
- return;
- }
+ if (protocol == NULL)
+ goto out;
if (protocol->pid == pid) {
protocol_list = protocol->next;
- write_unlock_bh(&protocol_list_lock);
- return;
+ goto out;
}
while (protocol != NULL && protocol->next != NULL) {
if (protocol->next->pid == pid) {
- s = protocol->next;
protocol->next = protocol->next->next;
- write_unlock_bh(&protocol_list_lock);
- return;
+ goto out;
}
protocol = protocol->next;
}
+out:
write_unlock_bh(&protocol_list_lock);
}
@@ -197,10 +193,9 @@ int ax25_listen_mine(ax25_address *callsign, struct net_device *dev)
void ax25_link_failed(ax25_cb *ax25, int reason)
{
struct ax25_linkfail *lf;
- struct hlist_node *node;
spin_lock_bh(&linkfail_lock);
- hlist_for_each_entry(lf, node, &ax25_linkfail_list, lf_node)
+ hlist_for_each_entry(lf, &ax25_linkfail_list, lf_node)
lf->func(ax25, reason);
spin_unlock_bh(&linkfail_lock);
}
diff --git a/net/ax25/ax25_in.c b/net/ax25/ax25_in.c
index d1be080dcb2..7ed8ab72481 100644
--- a/net/ax25/ax25_in.c
+++ b/net/ax25/ax25_in.c
@@ -18,6 +18,7 @@
#include <linux/string.h>
#include <linux/sockios.h>
#include <linux/net.h>
+#include <linux/slab.h>
#include <net/ax25.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
@@ -26,7 +27,6 @@
#include <net/sock.h>
#include <net/tcp_states.h>
#include <asm/uaccess.h>
-#include <asm/system.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
@@ -200,19 +200,15 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev,
skb_reset_transport_header(skb);
- if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL) {
- kfree_skb(skb);
- return 0;
- }
+ if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL)
+ goto free;
/*
* Parse the address header.
*/
- if (ax25_addr_parse(skb->data, skb->len, &src, &dest, &dp, &type, &dama) == NULL) {
- kfree_skb(skb);
- return 0;
- }
+ if (ax25_addr_parse(skb->data, skb->len, &src, &dest, &dp, &type, &dama) == NULL)
+ goto free;
/*
* Ours perhaps ?
@@ -239,10 +235,8 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev,
ax25_send_to_raw(&dest, skb, skb->data[1]);
- if (!mine && ax25cmp(&dest, (ax25_address *)dev->broadcast) != 0) {
- kfree_skb(skb);
- return 0;
- }
+ if (!mine && ax25cmp(&dest, (ax25_address *)dev->broadcast) != 0)
+ goto free;
/* Now we are pointing at the pid byte */
switch (skb->data[1]) {
@@ -301,10 +295,8 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev,
* If not, should we DM the incoming frame (except DMs) or
* silently ignore them. For now we stay quiet.
*/
- if (ax25_dev->values[AX25_VALUES_CONMODE] == 0) {
- kfree_skb(skb);
- return 0;
- }
+ if (ax25_dev->values[AX25_VALUES_CONMODE] == 0)
+ goto free;
/* LAPB */
@@ -339,8 +331,7 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev,
if ((*skb->data & ~AX25_PF) != AX25_DM && mine)
ax25_return_dm(dev, &src, &dest, &dp);
- kfree_skb(skb);
- return 0;
+ goto free;
}
/* b) received SABM(E) */
@@ -372,15 +363,12 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev,
sk->sk_ack_backlog++;
bh_unlock_sock(sk);
} else {
- if (!mine) {
- kfree_skb(skb);
- return 0;
- }
+ if (!mine)
+ goto free;
if ((ax25 = ax25_create_cb()) == NULL) {
ax25_return_dm(dev, &src, &dest, &dp);
- kfree_skb(skb);
- return 0;
+ goto free;
}
ax25_fillin_cb(ax25, ax25_dev);
@@ -434,11 +422,12 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev,
if (sk) {
if (!sock_flag(sk, SOCK_DEAD))
- sk->sk_data_ready(sk, skb->len);
+ sk->sk_data_ready(sk);
sock_put(sk);
- } else
+ } else {
+free:
kfree_skb(skb);
-
+ }
return 0;
}
@@ -448,10 +437,9 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev,
int ax25_kiss_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *ptype, struct net_device *orig_dev)
{
- skb->sk = NULL; /* Initially we don't know who it's for */
- skb->destructor = NULL; /* Who initializes this, dammit?! */
+ skb_orphan(skb);
- if (dev->nd_net != &init_net) {
+ if (!net_eq(dev_net(dev), &init_net)) {
kfree_skb(skb);
return 0;
}
diff --git a/net/ax25/ax25_ip.c b/net/ax25/ax25_ip.c
index f047a57aa95..67de6b33f2c 100644
--- a/net/ax25/ax25_ip.c
+++ b/net/ax25/ax25_ip.c
@@ -16,6 +16,7 @@
#include <linux/string.h>
#include <linux/sockios.h>
#include <linux/net.h>
+#include <linux/slab.h>
#include <net/ax25.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
@@ -23,7 +24,6 @@
#include <linux/skbuff.h>
#include <net/sock.h>
#include <asm/uaccess.h>
-#include <asm/system.h>
#include <linux/fcntl.h>
#include <linux/termios.h> /* For TIOCINQ/OUTQ */
#include <linux/mm.h>
@@ -48,7 +48,7 @@
int ax25_hard_header(struct sk_buff *skb, struct net_device *dev,
unsigned short type, const void *daddr,
- const void *saddr, unsigned len)
+ const void *saddr, unsigned int len)
{
unsigned char *buff;
@@ -219,7 +219,7 @@ put:
int ax25_hard_header(struct sk_buff *skb, struct net_device *dev,
unsigned short type, const void *daddr,
- const void *saddr, unsigned len)
+ const void *saddr, unsigned int len)
{
return -AX25_HEADER_LEN;
}
diff --git a/net/ax25/ax25_out.c b/net/ax25/ax25_out.c
index bf706f83a5c..be2acab9be9 100644
--- a/net/ax25/ax25_out.c
+++ b/net/ax25/ax25_out.c
@@ -19,6 +19,7 @@
#include <linux/sockios.h>
#include <linux/spinlock.h>
#include <linux/net.h>
+#include <linux/slab.h>
#include <net/ax25.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
@@ -26,7 +27,6 @@
#include <linux/netfilter.h>
#include <net/sock.h>
#include <asm/uaccess.h>
-#include <asm/system.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
@@ -92,6 +92,12 @@ ax25_cb *ax25_send_frame(struct sk_buff *skb, int paclen, ax25_address *src, ax2
#endif
}
+ /*
+ * There is one ref for the state machine; a caller needs
+ * one more to put it back, just like with the existing one.
+ */
+ ax25_cb_hold(ax25);
+
ax25_cb_add(ax25);
ax25->state = AX25_STATE_1;
@@ -344,7 +350,7 @@ void ax25_transmit_buffer(ax25_cb *ax25, struct sk_buff *skb, int type)
if (skb->sk != NULL)
skb_set_owner_w(skbn, skb->sk);
- kfree_skb(skb);
+ consume_skb(skb);
skb = skbn;
}
diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c
index 8672cd84fdf..d39097737e3 100644
--- a/net/ax25/ax25_route.c
+++ b/net/ax25/ax25_route.c
@@ -23,6 +23,7 @@
#include <linux/string.h>
#include <linux/sockios.h>
#include <linux/net.h>
+#include <linux/slab.h>
#include <net/ax25.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
@@ -31,12 +32,12 @@
#include <linux/spinlock.h>
#include <net/sock.h>
#include <asm/uaccess.h>
-#include <asm/system.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/seq_file.h>
+#include <linux/export.h>
static ax25_route *ax25_route_list;
static DEFINE_RWLOCK(ax25_route_lock);
@@ -411,7 +412,7 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr)
{
ax25_uid_assoc *user;
ax25_route *ax25_rt;
- int err;
+ int err = 0;
if ((ax25_rt = ax25_get_route(addr, NULL)) == NULL)
return -EHOSTUNREACH;
@@ -421,7 +422,7 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr)
goto put;
}
- user = ax25_findbyuid(current->euid);
+ user = ax25_findbyuid(current_euid());
if (user) {
ax25->source_addr = user->call;
ax25_uid_put(user);
@@ -452,7 +453,7 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr)
put:
ax25_put_route(ax25_rt);
- return 0;
+ return err;
}
struct sk_buff *ax25_rt_build_path(struct sk_buff *skb, ax25_address *src,
@@ -473,7 +474,7 @@ struct sk_buff *ax25_rt_build_path(struct sk_buff *skb, ax25_address *src,
if (skb->sk != NULL)
skb_set_owner_w(skbn, skb->sk);
- kfree_skb(skb);
+ consume_skb(skb);
skb = skbn;
}
diff --git a/net/ax25/ax25_std_in.c b/net/ax25/ax25_std_in.c
index a8eef88d865..3fbf8f7b2cf 100644
--- a/net/ax25/ax25_std_in.c
+++ b/net/ax25/ax25_std_in.c
@@ -30,7 +30,6 @@
#include <net/sock.h>
#include <net/tcp_states.h>
#include <asm/uaccess.h>
-#include <asm/system.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
diff --git a/net/ax25/ax25_std_subr.c b/net/ax25/ax25_std_subr.c
index 277f81bb979..8b66a41e538 100644
--- a/net/ax25/ax25_std_subr.c
+++ b/net/ax25/ax25_std_subr.c
@@ -21,7 +21,6 @@
#include <linux/skbuff.h>
#include <net/sock.h>
#include <asm/uaccess.h>
-#include <asm/system.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
diff --git a/net/ax25/ax25_std_timer.c b/net/ax25/ax25_std_timer.c
index 96e4b927325..004467c9e6e 100644
--- a/net/ax25/ax25_std_timer.c
+++ b/net/ax25/ax25_std_timer.c
@@ -25,7 +25,6 @@
#include <net/sock.h>
#include <net/tcp_states.h>
#include <asm/uaccess.h>
-#include <asm/system.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
diff --git a/net/ax25/ax25_subr.c b/net/ax25/ax25_subr.c
index d8f21573317..1997538a5d2 100644
--- a/net/ax25/ax25_subr.c
+++ b/net/ax25/ax25_subr.c
@@ -18,6 +18,7 @@
#include <linux/string.h>
#include <linux/sockios.h>
#include <linux/net.h>
+#include <linux/slab.h>
#include <net/ax25.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
@@ -25,7 +26,6 @@
#include <net/sock.h>
#include <net/tcp_states.h>
#include <asm/uaccess.h>
-#include <asm/system.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
@@ -64,20 +64,15 @@ void ax25_frames_acked(ax25_cb *ax25, unsigned short nr)
void ax25_requeue_frames(ax25_cb *ax25)
{
- struct sk_buff *skb, *skb_prev = NULL;
+ struct sk_buff *skb;
/*
* Requeue all the un-ack-ed frames on the output queue to be picked
* up by ax25_kick called from the timer. This arrangement handles the
* possibility of an empty output queue.
*/
- while ((skb = skb_dequeue(&ax25->ack_queue)) != NULL) {
- if (skb_prev == NULL)
- skb_queue_head(&ax25->write_queue, skb);
- else
- skb_append(skb_prev, skb, &ax25->write_queue);
- skb_prev = skb;
- }
+ while ((skb = skb_dequeue_tail(&ax25->ack_queue)) != NULL)
+ skb_queue_head(&ax25->write_queue, skb);
}
/*
diff --git a/net/ax25/ax25_timer.c b/net/ax25/ax25_timer.c
index db29ea71e80..c3cffa79baf 100644
--- a/net/ax25/ax25_timer.c
+++ b/net/ax25/ax25_timer.c
@@ -29,7 +29,6 @@
#include <linux/skbuff.h>
#include <net/sock.h>
#include <asm/uaccess.h>
-#include <asm/system.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
diff --git a/net/ax25/ax25_uid.c b/net/ax25/ax25_uid.c
index 5f4eb73fb9d..71c4badbc80 100644
--- a/net/ax25/ax25_uid.c
+++ b/net/ax25/ax25_uid.c
@@ -18,6 +18,7 @@
#include <linux/sockios.h>
#include <linux/net.h>
#include <linux/spinlock.h>
+#include <linux/slab.h>
#include <net/ax25.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
@@ -25,7 +26,6 @@
#include <linux/skbuff.h>
#include <net/sock.h>
#include <asm/uaccess.h>
-#include <asm/system.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
@@ -36,6 +36,7 @@
#include <linux/stat.h>
#include <linux/netfilter.h>
#include <linux/sysctl.h>
+#include <linux/export.h>
#include <net/ip.h>
#include <net/arp.h>
@@ -50,14 +51,13 @@ int ax25_uid_policy;
EXPORT_SYMBOL(ax25_uid_policy);
-ax25_uid_assoc *ax25_findbyuid(uid_t uid)
+ax25_uid_assoc *ax25_findbyuid(kuid_t uid)
{
ax25_uid_assoc *ax25_uid, *res = NULL;
- struct hlist_node *node;
read_lock(&ax25_uid_lock);
- ax25_uid_for_each(ax25_uid, node, &ax25_uid_list) {
- if (ax25_uid->uid == uid) {
+ ax25_uid_for_each(ax25_uid, &ax25_uid_list) {
+ if (uid_eq(ax25_uid->uid, uid)) {
ax25_uid_hold(ax25_uid);
res = ax25_uid;
break;
@@ -73,7 +73,6 @@ EXPORT_SYMBOL(ax25_findbyuid);
int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
{
ax25_uid_assoc *ax25_uid;
- struct hlist_node *node;
ax25_uid_assoc *user;
unsigned long res;
@@ -81,9 +80,9 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
case SIOCAX25GETUID:
res = -ENOENT;
read_lock(&ax25_uid_lock);
- ax25_uid_for_each(ax25_uid, node, &ax25_uid_list) {
+ ax25_uid_for_each(ax25_uid, &ax25_uid_list) {
if (ax25cmp(&sax->sax25_call, &ax25_uid->call) == 0) {
- res = ax25_uid->uid;
+ res = from_kuid_munged(current_user_ns(), ax25_uid->uid);
break;
}
}
@@ -92,9 +91,14 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
return res;
case SIOCAX25ADDUID:
+ {
+ kuid_t sax25_kuid;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
- user = ax25_findbyuid(sax->sax25_uid);
+ sax25_kuid = make_kuid(current_user_ns(), sax->sax25_uid);
+ if (!uid_valid(sax25_kuid))
+ return -EINVAL;
+ user = ax25_findbyuid(sax25_kuid);
if (user) {
ax25_uid_put(user);
return -EEXIST;
@@ -105,7 +109,7 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
return -ENOMEM;
atomic_set(&ax25_uid->refcount, 1);
- ax25_uid->uid = sax->sax25_uid;
+ ax25_uid->uid = sax25_kuid;
ax25_uid->call = sax->sax25_call;
write_lock(&ax25_uid_lock);
@@ -113,14 +117,14 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
write_unlock(&ax25_uid_lock);
return 0;
-
+ }
case SIOCAX25DELUID:
if (!capable(CAP_NET_ADMIN))
return -EPERM;
ax25_uid = NULL;
write_lock(&ax25_uid_lock);
- ax25_uid_for_each(ax25_uid, node, &ax25_uid_list) {
+ ax25_uid_for_each(ax25_uid, &ax25_uid_list) {
if (ax25cmp(&sax->sax25_call, &ax25_uid->call) == 0)
break;
}
@@ -146,25 +150,13 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
static void *ax25_uid_seq_start(struct seq_file *seq, loff_t *pos)
__acquires(ax25_uid_lock)
{
- struct ax25_uid_assoc *pt;
- struct hlist_node *node;
- int i = 0;
-
read_lock(&ax25_uid_lock);
- ax25_uid_for_each(pt, node, &ax25_uid_list) {
- if (i == *pos)
- return pt;
- ++i;
- }
- return NULL;
+ return seq_hlist_start_head(&ax25_uid_list, *pos);
}
static void *ax25_uid_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
- ++*pos;
-
- return hlist_entry(((ax25_uid_assoc *)v)->uid_node.next,
- ax25_uid_assoc, uid_node);
+ return seq_hlist_next(v, &ax25_uid_list, pos);
}
static void ax25_uid_seq_stop(struct seq_file *seq, void *v)
@@ -180,9 +172,12 @@ static int ax25_uid_seq_show(struct seq_file *seq, void *v)
if (v == SEQ_START_TOKEN)
seq_printf(seq, "Policy: %d\n", ax25_uid_policy);
else {
- struct ax25_uid_assoc *pt = v;
+ struct ax25_uid_assoc *pt;
- seq_printf(seq, "%6d %s\n", pt->uid, ax2asc(buf, &pt->call));
+ pt = hlist_entry(v, struct ax25_uid_assoc, uid_node);
+ seq_printf(seq, "%6d %s\n",
+ from_kuid_munged(seq_user_ns(seq), pt->uid),
+ ax2asc(buf, &pt->call));
}
return 0;
}
@@ -215,12 +210,13 @@ const struct file_operations ax25_uid_fops = {
void __exit ax25_uid_free(void)
{
ax25_uid_assoc *ax25_uid;
- struct hlist_node *node;
write_lock(&ax25_uid_lock);
- ax25_uid_for_each(ax25_uid, node, &ax25_uid_list) {
+again:
+ ax25_uid_for_each(ax25_uid, &ax25_uid_list) {
hlist_del_init(&ax25_uid->uid_node);
ax25_uid_put(ax25_uid);
+ goto again;
}
write_unlock(&ax25_uid_lock);
}
diff --git a/net/ax25/sysctl_net_ax25.c b/net/ax25/sysctl_net_ax25.c
index f597987b242..919a5ce4751 100644
--- a/net/ax25/sysctl_net_ax25.c
+++ b/net/ax25/sysctl_net_ax25.c
@@ -7,6 +7,7 @@
* Copyright (C) 1996 Mike Shaver (shaver@zeroknowledge.com)
*/
#include <linux/mm.h>
+#include <linux/slab.h>
#include <linux/sysctl.h>
#include <linux/spinlock.h>
#include <net/ax25.h>
@@ -24,220 +25,160 @@ static int min_idle[1], max_idle[] = {65535000};
static int min_n2[] = {1}, max_n2[] = {31};
static int min_paclen[] = {1}, max_paclen[] = {512};
static int min_proto[1], max_proto[] = { AX25_PROTO_MAX };
+#ifdef CONFIG_AX25_DAMA_SLAVE
static int min_ds_timeout[1], max_ds_timeout[] = {65535000};
+#endif
-static struct ctl_table_header *ax25_table_header;
-
-static ctl_table *ax25_table;
-static int ax25_table_size;
-
-static struct ctl_path ax25_path[] = {
- { .procname = "net", .ctl_name = CTL_NET, },
- { .procname = "ax25", .ctl_name = NET_AX25, },
- { }
-};
-static const ctl_table ax25_param_table[] = {
+static const struct ctl_table ax25_param_table[] = {
{
- .ctl_name = NET_AX25_IP_DEFAULT_MODE,
.procname = "ip_default_mode",
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = &proc_dointvec_minmax,
- .strategy = &sysctl_intvec,
+ .proc_handler = proc_dointvec_minmax,
.extra1 = &min_ipdefmode,
.extra2 = &max_ipdefmode
},
{
- .ctl_name = NET_AX25_DEFAULT_MODE,
.procname = "ax25_default_mode",
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = &proc_dointvec_minmax,
- .strategy = &sysctl_intvec,
+ .proc_handler = proc_dointvec_minmax,
.extra1 = &min_axdefmode,
.extra2 = &max_axdefmode
},
{
- .ctl_name = NET_AX25_BACKOFF_TYPE,
.procname = "backoff_type",
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = &proc_dointvec_minmax,
- .strategy = &sysctl_intvec,
+ .proc_handler = proc_dointvec_minmax,
.extra1 = &min_backoff,
.extra2 = &max_backoff
},
{
- .ctl_name = NET_AX25_CONNECT_MODE,
.procname = "connect_mode",
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = &proc_dointvec_minmax,
- .strategy = &sysctl_intvec,
+ .proc_handler = proc_dointvec_minmax,
.extra1 = &min_conmode,
.extra2 = &max_conmode
},
{
- .ctl_name = NET_AX25_STANDARD_WINDOW,
.procname = "standard_window_size",
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = &proc_dointvec_minmax,
- .strategy = &sysctl_intvec,
+ .proc_handler = proc_dointvec_minmax,
.extra1 = &min_window,
.extra2 = &max_window
},
{
- .ctl_name = NET_AX25_EXTENDED_WINDOW,
.procname = "extended_window_size",
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = &proc_dointvec_minmax,
- .strategy = &sysctl_intvec,
+ .proc_handler = proc_dointvec_minmax,
.extra1 = &min_ewindow,
.extra2 = &max_ewindow
},
{
- .ctl_name = NET_AX25_T1_TIMEOUT,
.procname = "t1_timeout",
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = &proc_dointvec_minmax,
- .strategy = &sysctl_intvec,
+ .proc_handler = proc_dointvec_minmax,
.extra1 = &min_t1,
.extra2 = &max_t1
},
{
- .ctl_name = NET_AX25_T2_TIMEOUT,
.procname = "t2_timeout",
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = &proc_dointvec_minmax,
- .strategy = &sysctl_intvec,
+ .proc_handler = proc_dointvec_minmax,
.extra1 = &min_t2,
.extra2 = &max_t2
},
{
- .ctl_name = NET_AX25_T3_TIMEOUT,
.procname = "t3_timeout",
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = &proc_dointvec_minmax,
- .strategy = &sysctl_intvec,
+ .proc_handler = proc_dointvec_minmax,
.extra1 = &min_t3,
.extra2 = &max_t3
},
{
- .ctl_name = NET_AX25_IDLE_TIMEOUT,
.procname = "idle_timeout",
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = &proc_dointvec_minmax,
- .strategy = &sysctl_intvec,
+ .proc_handler = proc_dointvec_minmax,
.extra1 = &min_idle,
.extra2 = &max_idle
},
{
- .ctl_name = NET_AX25_N2,
.procname = "maximum_retry_count",
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = &proc_dointvec_minmax,
- .strategy = &sysctl_intvec,
+ .proc_handler = proc_dointvec_minmax,
.extra1 = &min_n2,
.extra2 = &max_n2
},
{
- .ctl_name = NET_AX25_PACLEN,
.procname = "maximum_packet_length",
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = &proc_dointvec_minmax,
- .strategy = &sysctl_intvec,
+ .proc_handler = proc_dointvec_minmax,
.extra1 = &min_paclen,
.extra2 = &max_paclen
},
{
- .ctl_name = NET_AX25_PROTOCOL,
.procname = "protocol",
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = &proc_dointvec_minmax,
- .strategy = &sysctl_intvec,
+ .proc_handler = proc_dointvec_minmax,
.extra1 = &min_proto,
.extra2 = &max_proto
},
+#ifdef CONFIG_AX25_DAMA_SLAVE
{
- .ctl_name = NET_AX25_DAMA_SLAVE_TIMEOUT,
.procname = "dama_slave_timeout",
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = &proc_dointvec_minmax,
- .strategy = &sysctl_intvec,
+ .proc_handler = proc_dointvec_minmax,
.extra1 = &min_ds_timeout,
.extra2 = &max_ds_timeout
},
- { .ctl_name = 0 } /* that's all, folks! */
-};
-
-void ax25_register_sysctl(void)
-{
- ax25_dev *ax25_dev;
- int n, k;
-
- spin_lock_bh(&ax25_dev_lock);
- for (ax25_table_size = sizeof(ctl_table), ax25_dev = ax25_dev_list; ax25_dev != NULL; ax25_dev = ax25_dev->next)
- ax25_table_size += sizeof(ctl_table);
-
- if ((ax25_table = kzalloc(ax25_table_size, GFP_ATOMIC)) == NULL) {
- spin_unlock_bh(&ax25_dev_lock);
- return;
- }
-
- for (n = 0, ax25_dev = ax25_dev_list; ax25_dev != NULL; ax25_dev = ax25_dev->next) {
- struct ctl_table *child = kmemdup(ax25_param_table,
- sizeof(ax25_param_table),
- GFP_ATOMIC);
- if (!child) {
- while (n--)
- kfree(ax25_table[n].child);
- kfree(ax25_table);
- spin_unlock_bh(&ax25_dev_lock);
- return;
- }
- ax25_table[n].child = ax25_dev->systable = child;
- ax25_table[n].ctl_name = n + 1;
- ax25_table[n].procname = ax25_dev->dev->name;
- ax25_table[n].mode = 0555;
-
-#ifndef CONFIG_AX25_DAMA_SLAVE
- /*
- * We do not wish to have a representation of this parameter
- * in /proc/sys/ when configured *not* to include the
- * AX.25 DAMA slave code, do we?
- */
-
- child[AX25_VALUES_DS_TIMEOUT].procname = NULL;
#endif
- child[AX25_MAX_VALUES].ctl_name = 0; /* just in case... */
-
- for (k = 0; k < AX25_MAX_VALUES; k++)
- child[k].data = &ax25_dev->values[k];
+ { } /* that's all, folks! */
+};
- n++;
+int ax25_register_dev_sysctl(ax25_dev *ax25_dev)
+{
+ char path[sizeof("net/ax25/") + IFNAMSIZ];
+ int k;
+ struct ctl_table *table;
+
+ table = kmemdup(ax25_param_table, sizeof(ax25_param_table), GFP_KERNEL);
+ if (!table)
+ return -ENOMEM;
+
+ for (k = 0; k < AX25_MAX_VALUES; k++)
+ table[k].data = &ax25_dev->values[k];
+
+ snprintf(path, sizeof(path), "net/ax25/%s", ax25_dev->dev->name);
+ ax25_dev->sysheader = register_net_sysctl(&init_net, path, table);
+ if (!ax25_dev->sysheader) {
+ kfree(table);
+ return -ENOMEM;
}
- spin_unlock_bh(&ax25_dev_lock);
-
- ax25_table_header = register_sysctl_paths(ax25_path, ax25_table);
+ return 0;
}
-void ax25_unregister_sysctl(void)
+void ax25_unregister_dev_sysctl(ax25_dev *ax25_dev)
{
- ctl_table *p;
- unregister_sysctl_table(ax25_table_header);
-
- for (p = ax25_table; p->ctl_name; p++)
- kfree(p->child);
- kfree(ax25_table);
+ struct ctl_table_header *header = ax25_dev->sysheader;
+ struct ctl_table *table;
+
+ if (header) {
+ ax25_dev->sysheader = NULL;
+ table = header->ctl_table_arg;
+ unregister_net_sysctl_table(header);
+ kfree(table);
+ }
}