#include <linux/socket.h>
#include <linux/in.h>
#include <linux/kernel.h>
-#include <linux/sched.h>
#include <linux/timer.h>
#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>
while (rose_node != NULL) {
if ((rose_node->mask == rose_route->mask) &&
(rosecmpm(&rose_route->address, &rose_node->address,
- rose_route->mask) == 0))
+ rose_route->mask) == 0))
break;
rose_node = rose_node->next;
}
rose_neigh = rose_neigh_list;
while (rose_neigh != NULL) {
- if (ax25cmp(&rose_route->neighbour, &rose_neigh->callsign) == 0
- && rose_neigh->dev == dev)
+ if (ax25cmp(&rose_route->neighbour,
+ &rose_neigh->callsign) == 0 &&
+ rose_neigh->dev == dev)
break;
rose_neigh = rose_neigh->next;
}
if ((s = rose_neigh_list) == rose_neigh) {
rose_neigh_list = rose_neigh->next;
+ if (rose_neigh->ax25)
+ ax25_cb_put(rose_neigh->ax25);
kfree(rose_neigh->digipeat);
kfree(rose_neigh);
return;
while (s != NULL && s->next != NULL) {
if (s->next == rose_neigh) {
s->next = rose_neigh->next;
+ if (rose_neigh->ax25)
+ ax25_cb_put(rose_neigh->ax25);
kfree(rose_neigh->digipeat);
kfree(rose_neigh);
return;
while (rose_node != NULL) {
if ((rose_node->mask == rose_route->mask) &&
(rosecmpm(&rose_route->address, &rose_node->address,
- rose_route->mask) == 0))
+ rose_route->mask) == 0))
break;
rose_node = rose_node->next;
}
rose_neigh = rose_neigh_list;
while (rose_neigh != NULL) {
- if (ax25cmp(&rose_route->neighbour, &rose_neigh->callsign) == 0
- && rose_neigh->dev == dev)
+ if (ax25cmp(&rose_route->neighbour,
+ &rose_neigh->callsign) == 0 &&
+ rose_neigh->dev == dev)
break;
rose_neigh = rose_neigh->next;
}
/*
* Add the loopback neighbour.
*/
-int rose_add_loopback_neigh(void)
+void rose_add_loopback_neigh(void)
{
- if ((rose_loopback_neigh = kmalloc(sizeof(struct rose_neigh), GFP_ATOMIC)) == NULL)
- return -ENOMEM;
+ struct rose_neigh *sn;
- rose_loopback_neigh->callsign = null_ax25_address;
- rose_loopback_neigh->digipeat = NULL;
- rose_loopback_neigh->ax25 = NULL;
- rose_loopback_neigh->dev = NULL;
- rose_loopback_neigh->count = 0;
- rose_loopback_neigh->use = 0;
- rose_loopback_neigh->dce_mode = 1;
- rose_loopback_neigh->loopback = 1;
- rose_loopback_neigh->number = rose_neigh_no++;
- rose_loopback_neigh->restarted = 1;
+ rose_loopback_neigh = kmalloc(sizeof(struct rose_neigh), GFP_KERNEL);
+ if (!rose_loopback_neigh)
+ return;
+ sn = rose_loopback_neigh;
+
+ sn->callsign = null_ax25_address;
+ sn->digipeat = NULL;
+ sn->ax25 = NULL;
+ sn->dev = NULL;
+ sn->count = 0;
+ sn->use = 0;
+ sn->dce_mode = 1;
+ sn->loopback = 1;
+ sn->number = rose_neigh_no++;
+ sn->restarted = 1;
- skb_queue_head_init(&rose_loopback_neigh->queue);
+ skb_queue_head_init(&sn->queue);
- init_timer(&rose_loopback_neigh->ftimer);
- init_timer(&rose_loopback_neigh->t0timer);
+ init_timer(&sn->ftimer);
+ init_timer(&sn->t0timer);
spin_lock_bh(&rose_neigh_list_lock);
- rose_loopback_neigh->next = rose_neigh_list;
- rose_neigh_list = rose_loopback_neigh;
+ sn->next = rose_neigh_list;
+ rose_neigh_list = sn;
spin_unlock_bh(&rose_neigh_list_lock);
-
- return 0;
}
/*
/*
* Check that the device given is a valid AX.25 interface that is "up".
+ * called whith RTNL
*/
-static struct net_device *rose_ax25_dev_get(char *devname)
+static struct net_device *rose_ax25_dev_find(char *devname)
{
struct net_device *dev;
- if ((dev = dev_get_by_name(devname)) == NULL)
+ if ((dev = __dev_get_by_name(&init_net, devname)) == NULL)
return NULL;
if ((dev->flags & IFF_UP) && dev->type == ARPHRD_AX25)
return dev;
- dev_put(dev);
return NULL;
}
{
struct net_device *dev, *first = NULL;
- read_lock(&dev_base_lock);
- for (dev = dev_base; dev != NULL; dev = dev->next) {
+ rcu_read_lock();
+ for_each_netdev_rcu(&init_net, dev) {
if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE)
if (first == NULL || strncmp(dev->name, first->name, 3) < 0)
first = dev;
}
- read_unlock(&dev_base_lock);
+ rcu_read_unlock();
return first;
}
{
struct net_device *dev;
- read_lock(&dev_base_lock);
- for (dev = dev_base; dev != NULL; dev = dev->next) {
+ rcu_read_lock();
+ for_each_netdev_rcu(&init_net, dev) {
if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE && rosecmp(addr, (rose_address *)dev->dev_addr) == 0) {
dev_hold(dev);
goto out;
}
}
+ dev = NULL;
out:
- read_unlock(&dev_base_lock);
+ rcu_read_unlock();
return dev;
}
{
struct net_device *dev;
- read_lock(&dev_base_lock);
- for (dev = dev_base; dev != NULL; dev = dev->next) {
+ rcu_read_lock();
+ for_each_netdev_rcu(&init_net, dev) {
if ((dev->flags & IFF_UP) && dev->type == ARPHRD_ROSE && rosecmp(addr, (rose_address *)dev->dev_addr) == 0)
goto out;
}
+ dev = NULL;
out:
- read_unlock(&dev_base_lock);
+ rcu_read_unlock();
return dev != NULL;
}
}
/*
- * Find a neighbour given a ROSE address.
+ * Find a neighbour or a route given a ROSE address.
*/
struct rose_neigh *rose_get_neigh(rose_address *addr, unsigned char *cause,
- unsigned char *diagnostic)
+ unsigned char *diagnostic, int new)
{
struct rose_neigh *res = NULL;
struct rose_node *node;
int failed = 0;
int i;
- spin_lock_bh(&rose_node_list_lock);
+ if (!new) spin_lock_bh(&rose_node_list_lock);
for (node = rose_node_list; node != NULL; node = node->next) {
if (rosecmpm(addr, &node->address, node->mask) == 0) {
for (i = 0; i < node->count; i++) {
- if (!rose_ftimer_running(node->neighbour[i])) {
- res = node->neighbour[i];
- goto out;
- } else
- failed = 1;
+ if (new) {
+ if (node->neighbour[i]->restarted) {
+ res = node->neighbour[i];
+ goto out;
+ }
+ }
+ else {
+ if (!rose_ftimer_running(node->neighbour[i])) {
+ res = node->neighbour[i];
+ goto out;
+ } else
+ failed = 1;
+ }
}
- break;
}
}
}
out:
- spin_unlock_bh(&rose_node_list_lock);
+ if (!new) spin_unlock_bh(&rose_node_list_lock);
return res;
}
case SIOCADDRT:
if (copy_from_user(&rose_route, arg, sizeof(struct rose_route_struct)))
return -EFAULT;
- if ((dev = rose_ax25_dev_get(rose_route.device)) == NULL)
+ if ((dev = rose_ax25_dev_find(rose_route.device)) == NULL)
return -EINVAL;
- if (rose_dev_exists(&rose_route.address)) { /* Can't add routes to ourself */
- dev_put(dev);
+ if (rose_dev_exists(&rose_route.address)) /* Can't add routes to ourself */
return -EINVAL;
- }
if (rose_route.mask > 10) /* Mask can't be more than 10 digits */
return -EINVAL;
if (rose_route.ndigis > AX25_MAX_DIGIS)
return -EINVAL;
err = rose_add_node(&rose_route, dev);
- dev_put(dev);
return err;
case SIOCDELRT:
if (copy_from_user(&rose_route, arg, sizeof(struct rose_route_struct)))
return -EFAULT;
- if ((dev = rose_ax25_dev_get(rose_route.device)) == NULL)
+ if ((dev = rose_ax25_dev_find(rose_route.device)) == NULL)
return -EINVAL;
err = rose_del_node(&rose_route, dev);
- dev_put(dev);
return err;
case SIOCRSCLRRT:
if (rose_neigh != NULL) {
rose_neigh->ax25 = NULL;
+ ax25_cb_put(ax25);
rose_del_route_by_neigh(rose_neigh);
rose_kill_by_neigh(rose_neigh);
src_addr = (rose_address *)(skb->data + 9);
dest_addr = (rose_address *)(skb->data + 4);
- spin_lock_bh(&rose_node_list_lock);
spin_lock_bh(&rose_neigh_list_lock);
spin_lock_bh(&rose_route_list_lock);
}
}
else {
- skb->h.raw = skb->data;
+ skb_reset_transport_header(skb);
res = rose_process_rx_frame(sk, skb);
goto out;
}
goto out;
}
- len = (((skb->data[3] >> 4) & 0x0F) + 1) / 2;
- len += (((skb->data[3] >> 0) & 0x0F) + 1) / 2;
+ len = (((skb->data[3] >> 4) & 0x0F) + 1) >> 1;
+ len += (((skb->data[3] >> 0) & 0x0F) + 1) >> 1;
memset(&facilities, 0x00, sizeof(struct rose_facilities_struct));
rose_route = rose_route->next;
}
- if ((new_neigh = rose_get_neigh(dest_addr, &cause, &diagnostic)) == NULL) {
+ if ((new_neigh = rose_get_neigh(dest_addr, &cause, &diagnostic, 1)) == NULL) {
rose_transmit_clear_request(rose_neigh, lci, cause, diagnostic);
goto out;
}
out:
spin_unlock_bh(&rose_route_list_lock);
spin_unlock_bh(&rose_neigh_list_lock);
- spin_unlock_bh(&rose_node_list_lock);
return res;
}
#ifdef CONFIG_PROC_FS
static void *rose_node_start(struct seq_file *seq, loff_t *pos)
+ __acquires(rose_node_list_lock)
{
struct rose_node *rose_node;
int i = 1;
- spin_lock_bh(&rose_neigh_list_lock);
+ spin_lock_bh(&rose_node_list_lock);
if (*pos == 0)
return SEQ_START_TOKEN;
- for (rose_node = rose_node_list; rose_node && i < *pos;
+ for (rose_node = rose_node_list; rose_node && i < *pos;
rose_node = rose_node->next, ++i);
return (i == *pos) ? rose_node : NULL;
static void *rose_node_next(struct seq_file *seq, void *v, loff_t *pos)
{
++*pos;
-
- return (v == SEQ_START_TOKEN) ? rose_node_list
+
+ return (v == SEQ_START_TOKEN) ? rose_node_list
: ((struct rose_node *)v)->next;
}
static void rose_node_stop(struct seq_file *seq, void *v)
+ __releases(rose_node_list_lock)
{
- spin_unlock_bh(&rose_neigh_list_lock);
+ spin_unlock_bh(&rose_node_list_lock);
}
static int rose_node_show(struct seq_file *seq, void *v)
{
+ char rsbuf[11];
int i;
if (v == SEQ_START_TOKEN)
const struct rose_node *rose_node = v;
/* if (rose_node->loopback) {
seq_printf(seq, "%-10s %04d 1 loopback\n",
- rose2asc(&rose_node->address),
- rose_node->mask);
+ rose2asc(rsbuf, &rose_node->address),
+ rose_node->mask);
} else { */
seq_printf(seq, "%-10s %04d %d",
- rose2asc(&rose_node->address),
- rose_node->mask,
- rose_node->count);
+ rose2asc(rsbuf, &rose_node->address),
+ rose_node->mask,
+ rose_node->count);
for (i = 0; i < rose_node->count; i++)
seq_printf(seq, " %05d",
return 0;
}
-static struct seq_operations rose_node_seqops = {
+static const struct seq_operations rose_node_seqops = {
.start = rose_node_start,
.next = rose_node_next,
.stop = rose_node_stop,
return seq_open(file, &rose_node_seqops);
}
-struct file_operations rose_nodes_fops = {
+const struct file_operations rose_nodes_fops = {
.owner = THIS_MODULE,
.open = rose_nodes_open,
.read = seq_read,
};
static void *rose_neigh_start(struct seq_file *seq, loff_t *pos)
+ __acquires(rose_neigh_list_lock)
{
struct rose_neigh *rose_neigh;
int i = 1;
if (*pos == 0)
return SEQ_START_TOKEN;
- for (rose_neigh = rose_neigh_list; rose_neigh && i < *pos;
+ for (rose_neigh = rose_neigh_list; rose_neigh && i < *pos;
rose_neigh = rose_neigh->next, ++i);
return (i == *pos) ? rose_neigh : NULL;
static void *rose_neigh_next(struct seq_file *seq, void *v, loff_t *pos)
{
++*pos;
-
- return (v == SEQ_START_TOKEN) ? rose_neigh_list
+
+ return (v == SEQ_START_TOKEN) ? rose_neigh_list
: ((struct rose_neigh *)v)->next;
}
static void rose_neigh_stop(struct seq_file *seq, void *v)
+ __releases(rose_neigh_list_lock)
{
spin_unlock_bh(&rose_neigh_list_lock);
}
int i;
if (v == SEQ_START_TOKEN)
- seq_puts(seq,
+ seq_puts(seq,
"addr callsign dev count use mode restart t0 tf digipeaters\n");
else {
struct rose_neigh *rose_neigh = v;
}
-static struct seq_operations rose_neigh_seqops = {
+static const struct seq_operations rose_neigh_seqops = {
.start = rose_neigh_start,
.next = rose_neigh_next,
.stop = rose_neigh_stop,
return seq_open(file, &rose_neigh_seqops);
}
-struct file_operations rose_neigh_fops = {
+const struct file_operations rose_neigh_fops = {
.owner = THIS_MODULE,
.open = rose_neigh_open,
.read = seq_read,
static void *rose_route_start(struct seq_file *seq, loff_t *pos)
+ __acquires(rose_route_list_lock)
{
struct rose_route *rose_route;
int i = 1;
if (*pos == 0)
return SEQ_START_TOKEN;
- for (rose_route = rose_route_list; rose_route && i < *pos;
+ for (rose_route = rose_route_list; rose_route && i < *pos;
rose_route = rose_route->next, ++i);
return (i == *pos) ? rose_route : NULL;
static void *rose_route_next(struct seq_file *seq, void *v, loff_t *pos)
{
++*pos;
-
- return (v == SEQ_START_TOKEN) ? rose_route_list
+
+ return (v == SEQ_START_TOKEN) ? rose_route_list
: ((struct rose_route *)v)->next;
}
static void rose_route_stop(struct seq_file *seq, void *v)
+ __releases(rose_route_list_lock)
{
spin_unlock_bh(&rose_route_list_lock);
}
static int rose_route_show(struct seq_file *seq, void *v)
{
- char buf[11];
+ char buf[11], rsbuf[11];
if (v == SEQ_START_TOKEN)
- seq_puts(seq,
+ seq_puts(seq,
"lci address callsign neigh <-> lci address callsign neigh\n");
else {
struct rose_route *rose_route = v;
- if (rose_route->neigh1)
+ if (rose_route->neigh1)
seq_printf(seq,
"%3.3X %-10s %-9s %05d ",
rose_route->lci1,
- rose2asc(&rose_route->src_addr),
+ rose2asc(rsbuf, &rose_route->src_addr),
ax2asc(buf, &rose_route->src_call),
rose_route->neigh1->number);
- else
- seq_puts(seq,
+ else
+ seq_puts(seq,
"000 * * 00000 ");
- if (rose_route->neigh2)
+ if (rose_route->neigh2)
seq_printf(seq,
"%3.3X %-10s %-9s %05d\n",
- rose_route->lci2,
- rose2asc(&rose_route->dest_addr),
- ax2asc(buf, &rose_route->dest_call),
- rose_route->neigh2->number);
- else
+ rose_route->lci2,
+ rose2asc(rsbuf, &rose_route->dest_addr),
+ ax2asc(buf, &rose_route->dest_call),
+ rose_route->neigh2->number);
+ else
seq_puts(seq,
"000 * * 00000\n");
}
return 0;
}
-static struct seq_operations rose_route_seqops = {
+static const struct seq_operations rose_route_seqops = {
.start = rose_route_start,
.next = rose_route_next,
.stop = rose_route_stop,
return seq_open(file, &rose_route_seqops);
}
-struct file_operations rose_routes_fops = {
+const struct file_operations rose_routes_fops = {
.owner = THIS_MODULE,
.open = rose_route_open,
.read = seq_read,