Commit 3652c0a0 authored by Ralf Bächle's avatar Ralf Bächle

Merge dea.linux-mips.net:/usr/src/bk/linux-2.5

into dea.linux-mips.net:/home/ralf/src/ax25/linux-2.5
parents 46979afd ee30cd4f
......@@ -3,11 +3,12 @@
*
* Alan Cox (GW4PTS) 10/11/93
*/
#ifndef _AX25_H
#define _AX25_H
#include <linux/config.h>
#include <linux/ax25.h>
#include <linux/spinlock.h>
#define AX25_T1CLAMPLO 1
#define AX25_T1CLAMPHI (30 * HZ)
......@@ -197,7 +198,8 @@ typedef struct ax25_cb {
#define ax25_sk(__sk) ((ax25_cb *)(__sk)->protinfo)
/* af_ax25.c */
extern ax25_cb *volatile ax25_list;
extern ax25_cb *ax25_list;
extern spinlock_t ax25_list_lock;
extern void ax25_free_cb(ax25_cb *);
extern void ax25_insert_socket(ax25_cb *);
struct sock *ax25_find_listener(ax25_address *, int, struct net_device *, int);
......@@ -224,6 +226,7 @@ extern void ax25_digi_invert(ax25_digi *, ax25_digi *);
/* ax25_dev.c */
extern ax25_dev *ax25_dev_list;
extern spinlock_t ax25_dev_lock;
extern ax25_dev *ax25_dev_ax25dev(struct net_device *);
extern ax25_dev *ax25_addr_ax25dev(ax25_address *);
extern void ax25_dev_device_up(struct net_device *);
......
af_ax25.c:ax25_connect:
There is a race with changing the socket state here which should be
fixed by introduction of proper socket locking:
if (sk->state != TCP_ESTABLISHED) {
/* Not in ABM, not in WAIT_UA -> failed */
sock->state = SS_UNCONNECTED;
return sock_error(sk); /* Always set at this point */
}
Do the ax25_list_lock, ax25_uid_lock, ax25_route_lock, protocol_list_lock,
ax25_dev_lock, linkfail_lockreally and ax25_frag_lock have to be interrupt
safe?
What locking will be needed for listen_list?
......@@ -134,13 +134,15 @@
#include <linux/netfilter.h>
#include <linux/sysctl.h>
#include <linux/init.h>
#include <linux/spinlock.h>
#include <net/tcp.h>
#include <net/ip.h>
#include <net/arp.h>
ax25_cb *volatile ax25_list;
ax25_cb *ax25_list;
spinlock_t ax25_list_lock = SPIN_LOCK_UNLOCKED;
static struct proto_ops ax25_proto_ops;
......@@ -173,25 +175,25 @@ static void ax25_remove_socket(ax25_cb *ax25)
ax25_cb *s;
unsigned long flags;
save_flags(flags); cli();
spin_lock_irqsave(&ax25_list_lock, flags);
if ((s = ax25_list) == ax25) {
ax25_list = s->next;
restore_flags(flags);
spin_unlock_irqrestore(&ax25_list_lock, flags);
return;
}
while (s != NULL && s->next != NULL) {
if (s->next == ax25) {
s->next = ax25->next;
restore_flags(flags);
spin_unlock_irqrestore(&ax25_list_lock, flags);
return;
}
s = s->next;
}
restore_flags(flags);
spin_unlock_irqrestore(&ax25_list_lock, flags);
}
/*
......@@ -199,18 +201,21 @@ static void ax25_remove_socket(ax25_cb *ax25)
*/
static void ax25_kill_by_device(struct net_device *dev)
{
unsigned long flags;
ax25_dev *ax25_dev;
ax25_cb *s;
if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL)
return;
spin_lock_irqsave(&ax25_list_lock, flags);
for (s = ax25_list; s != NULL; s = s->next) {
if (s->ax25_dev == ax25_dev) {
s->ax25_dev = NULL;
ax25_disconnect(s, ENETUNREACH);
}
}
spin_unlock_irqrestore(&ax25_list_lock, flags);
}
/*
......@@ -247,13 +252,10 @@ void ax25_insert_socket(ax25_cb *ax25)
{
unsigned long flags;
save_flags(flags);
cli();
spin_lock_irqsave(&ax25_list_lock, flags);
ax25->next = ax25_list;
ax25_list = ax25;
restore_flags(flags);
spin_unlock_irqrestore(&ax25_list_lock, flags);
}
/*
......@@ -265,22 +267,21 @@ struct sock *ax25_find_listener(ax25_address *addr, int digi, struct net_device
unsigned long flags;
ax25_cb *s;
save_flags(flags);
cli();
spin_lock_irqsave(&ax25_list_lock, flags);
for (s = ax25_list; s != NULL; s = s->next) {
if ((s->iamdigi && !digi) || (!s->iamdigi && digi))
continue;
if (s->sk != NULL && ax25cmp(&s->source_addr, addr) == 0 && s->sk->type == type && s->sk->state == TCP_LISTEN) {
/* If device is null we match any device */
if (s->ax25_dev == NULL || s->ax25_dev->dev == dev) {
restore_flags(flags);
spin_unlock_irqrestore(&ax25_list_lock, flags);
return s->sk;
}
}
}
spin_unlock_irqrestore(&ax25_list_lock, flags);
restore_flags(flags);
return NULL;
}
......@@ -292,17 +293,15 @@ struct sock *ax25_find_socket(ax25_address *my_addr, ax25_address *dest_addr, in
ax25_cb *s;
unsigned long flags;
save_flags(flags);
cli();
spin_lock_irqsave(&ax25_list_lock, flags);
for (s = ax25_list; s != NULL; s = s->next) {
if (s->sk != NULL && ax25cmp(&s->source_addr, my_addr) == 0 && ax25cmp(&s->dest_addr, dest_addr) == 0 && s->sk->type == type) {
restore_flags(flags);
spin_unlock_irqrestore(&ax25_list_lock, flags);
return s->sk;
}
}
restore_flags(flags);
spin_unlock_irqrestore(&ax25_list_lock, flags);
return NULL;
}
......@@ -316,9 +315,7 @@ ax25_cb *ax25_find_cb(ax25_address *src_addr, ax25_address *dest_addr, ax25_digi
ax25_cb *s;
unsigned long flags;
save_flags(flags);
cli();
spin_lock_irqsave(&ax25_list_lock, flags);
for (s = ax25_list; s != NULL; s = s->next) {
if (s->sk != NULL && s->sk->type != SOCK_SEQPACKET)
continue;
......@@ -334,12 +331,12 @@ ax25_cb *ax25_find_cb(ax25_address *src_addr, ax25_address *dest_addr, ax25_digi
if (s->digipeat != NULL && s->digipeat->ndigi != 0)
continue;
}
restore_flags(flags);
spin_unlock_irqrestore(&ax25_list_lock, flags);
return s;
}
}
restore_flags(flags);
spin_unlock_irqrestore(&ax25_list_lock, flags);
return NULL;
}
......@@ -352,17 +349,14 @@ struct sock *ax25_addr_match(ax25_address *addr)
unsigned long flags;
ax25_cb *s;
save_flags(flags);
cli();
spin_lock_irqsave(&ax25_list_lock, flags);
for (s = ax25_list; s != NULL; s = s->next) {
if (s->sk != NULL && ax25cmp(&s->source_addr, addr) == 0 && s->sk->type == SOCK_RAW) {
restore_flags(flags);
spin_unlock_irqrestore(&ax25_list_lock, flags);
return s->sk;
}
}
restore_flags(flags);
spin_unlock_irqrestore(&ax25_list_lock, flags);
return NULL;
}
......@@ -1270,28 +1264,33 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
if (sk->state != TCP_ESTABLISHED && (flags & O_NONBLOCK))
return -EINPROGRESS;
cli(); /* To avoid races on the sleep */
if (sk->state == TCP_SYN_SENT) {
struct task_struct *tsk = current;
DECLARE_WAITQUEUE(wait, tsk);
/* A DM or timeout will go to closed, a UA will go to ABM */
while (sk->state == TCP_SYN_SENT) {
interruptible_sleep_on(sk->sleep);
if (signal_pending(current)) {
sti();
add_wait_queue(sk->sleep, &wait);
for (;;) {
set_current_state(TASK_INTERRUPTIBLE);
if (sk->state != TCP_SYN_SENT)
break;
if (!signal_pending(tsk)) {
schedule();
continue;
}
return -ERESTARTSYS;
}
current->state = TASK_RUNNING;
remove_wait_queue(sk->sleep, &wait);
}
if (sk->state != TCP_ESTABLISHED) {
/* Not in ABM, not in WAIT_UA -> failed */
sti();
sock->state = SS_UNCONNECTED;
return sock_error(sk); /* Always set at this point */
}
sock->state = SS_CONNECTED;
sti();
return 0;
}
......@@ -1738,13 +1737,14 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
static int ax25_get_info(char *buffer, char **start, off_t offset, int length)
{
unsigned long flags;
ax25_cb *ax25;
int k;
int len = 0;
off_t pos = 0;
off_t begin = 0;
cli();
spin_lock_irqsave(&ax25_list_lock, flags);
/*
* New format:
......@@ -1799,7 +1799,7 @@ static int ax25_get_info(char *buffer, char **start, off_t offset, int length)
break;
}
sti();
spin_unlock_irqrestore(&ax25_list_lock, flags);
*start = buffer + (offset - begin);
len -= (offset - begin);
......
......@@ -27,6 +27,7 @@
#include <linux/string.h>
#include <linux/sockios.h>
#include <linux/net.h>
#include <linux/spinlock.h>
#include <net/ax25.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
......@@ -41,27 +42,37 @@
#include <linux/init.h>
ax25_dev *ax25_dev_list;
spinlock_t ax25_dev_lock = SPIN_LOCK_UNLOCKED;
ax25_dev *ax25_dev_ax25dev(struct net_device *dev)
{
ax25_dev *ax25_dev;
ax25_dev *ax25_dev, *res = NULL;
unsigned long flags;
spin_lock_irqsave(&ax25_dev_lock, flags);
for (ax25_dev = ax25_dev_list; ax25_dev != NULL; ax25_dev = ax25_dev->next)
if (ax25_dev->dev == dev)
return ax25_dev;
if (ax25_dev->dev == dev) {
res = ax25_dev;
break;
}
spin_unlock_irqrestore(&ax25_dev_lock, flags);
return NULL;
return res;
}
ax25_dev *ax25_addr_ax25dev(ax25_address *addr)
{
ax25_dev *ax25_dev;
ax25_dev *ax25_dev, *res = NULL;
unsigned long flags;
spin_lock_irqsave(&ax25_dev_lock, flags);
for (ax25_dev = ax25_dev_list; ax25_dev != NULL; ax25_dev = ax25_dev->next)
if (ax25cmp(addr, (ax25_address *)ax25_dev->dev->dev_addr) == 0)
return ax25_dev;
if (ax25cmp(addr, (ax25_address *)ax25_dev->dev->dev_addr) == 0) {
res = ax25_dev;
}
spin_unlock_irqrestore(&ax25_dev_lock, flags);
return NULL;
return res;
}
/*
......@@ -100,10 +111,10 @@ void ax25_dev_device_up(struct net_device *dev)
ax25_dev->values[AX25_VALUES_PROTOCOL] = AX25_DEF_PROTOCOL;
ax25_dev->values[AX25_VALUES_DS_TIMEOUT]= AX25_DEF_DS_TIMEOUT;
save_flags(flags); cli();
spin_lock_irqsave(&ax25_dev_lock, flags);
ax25_dev->next = ax25_dev_list;
ax25_dev_list = ax25_dev;
restore_flags(flags);
spin_unlock_irqrestore(&ax25_dev_lock, flags);
ax25_register_sysctl();
}
......@@ -118,7 +129,7 @@ void ax25_dev_device_down(struct net_device *dev)
ax25_unregister_sysctl();
save_flags(flags); cli();
spin_lock_irqsave(&ax25_dev_lock, flags);
#ifdef CONFIG_AX25_DAMA_SLAVE
ax25_ds_del_timer(ax25_dev);
......@@ -133,7 +144,7 @@ void ax25_dev_device_down(struct net_device *dev)
if ((s = ax25_dev_list) == ax25_dev) {
ax25_dev_list = s->next;
restore_flags(flags);
spin_unlock_irqrestore(&ax25_dev_lock, flags);
kfree(ax25_dev);
ax25_register_sysctl();
return;
......@@ -142,7 +153,7 @@ void ax25_dev_device_down(struct net_device *dev)
while (s != NULL && s->next != NULL) {
if (s->next == ax25_dev) {
s->next = ax25_dev->next;
restore_flags(flags);
spin_unlock_irqrestore(&ax25_dev_lock, flags);
kfree(ax25_dev);
ax25_register_sysctl();
return;
......@@ -150,8 +161,8 @@ void ax25_dev_device_down(struct net_device *dev)
s = s->next;
}
spin_unlock_irqrestore(&ax25_dev_lock, flags);
restore_flags(flags);
ax25_register_sysctl();
}
......@@ -202,12 +213,17 @@ struct net_device *ax25_fwd_dev(struct net_device *dev)
*/
void __exit ax25_dev_free(void)
{
ax25_dev *s, *ax25_dev = ax25_dev_list;
ax25_dev *s, *ax25_dev;
unsigned long flags;
spin_lock_irqsave(&ax25_dev_lock, flags);
ax25_dev = ax25_dev_list;
while (ax25_dev != NULL) {
s = ax25_dev;
ax25_dev = ax25_dev->next;
kfree(s);
}
ax25_dev_list = NULL;
spin_unlock_irqrestore(&ax25_dev_lock, flags);
}
......@@ -31,6 +31,7 @@
#include <linux/timer.h>
#include <linux/string.h>
#include <linux/sockios.h>
#include <linux/spinlock.h>
#include <linux/net.h>
#include <net/ax25.h>
#include <linux/inet.h>
......@@ -53,6 +54,7 @@ void ax25_ds_nr_error_recovery(ax25_cb *ax25)
*/
void ax25_ds_enquiry_response(ax25_cb *ax25)
{
unsigned long flags;
ax25_cb *ax25o;
/* Please note that neither DK4EGs nor DG2FEFs
......@@ -93,6 +95,7 @@ void ax25_ds_enquiry_response(ax25_cb *ax25)
ax25_start_t3timer(ax25);
ax25_ds_set_timer(ax25->ax25_dev);
spin_lock_irqsave(&ax25_list_lock, flags);
for (ax25o = ax25_list; ax25o != NULL; ax25o = ax25o->next) {
if (ax25o == ax25)
continue;
......@@ -118,6 +121,7 @@ void ax25_ds_enquiry_response(ax25_cb *ax25)
if (ax25o->state != AX25_STATE_0)
ax25_start_t3timer(ax25o);
}
spin_unlock_irqrestore(&ax25_list_lock, flags);
}
void ax25_ds_establish_data_link(ax25_cb *ax25)
......@@ -170,13 +174,19 @@ static void ax25_kiss_cmd(ax25_dev *ax25_dev, unsigned char cmd, unsigned char p
*/
static int ax25_check_dama_slave(ax25_dev *ax25_dev)
{
unsigned long flags;
ax25_cb *ax25;
int res = 0;
spin_lock_irqsave(&ax25_list_lock, flags);
for (ax25 = ax25_list; ax25 != NULL ; ax25 = ax25->next)
if (ax25->ax25_dev == ax25_dev && (ax25->condition & AX25_COND_DAMA_MODE) && ax25->state > AX25_STATE_1)
return 1;
if (ax25->ax25_dev == ax25_dev && (ax25->condition & AX25_COND_DAMA_MODE) && ax25->state > AX25_STATE_1) {
res = 1;
break;
}
spin_unlock_irqrestore(&ax25_list_lock, flags);
return 0;
return res;
}
void ax25_dev_dama_on(ax25_dev *ax25_dev)
......
......@@ -18,6 +18,7 @@
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
#include <linux/spinlock.h>
#include <linux/in.h>
#include <linux/kernel.h>
#include <linux/jiffies.h>
......@@ -79,6 +80,7 @@ void ax25_ds_set_timer(ax25_dev *ax25_dev)
static void ax25_ds_timeout(unsigned long arg)
{
ax25_dev *ax25_dev = (struct ax25_dev *) arg;
unsigned long flags;
ax25_cb *ax25;
if (ax25_dev == NULL || !ax25_dev->dama.slave)
......@@ -89,6 +91,7 @@ static void ax25_ds_timeout(unsigned long arg)
return;
}
spin_lock_irqsave(&ax25_list_lock, flags);
for (ax25=ax25_list; ax25 != NULL; ax25 = ax25->next) {
if (ax25->ax25_dev != ax25_dev || !(ax25->condition & AX25_COND_DAMA_MODE))
continue;
......@@ -96,6 +99,7 @@ static void ax25_ds_timeout(unsigned long arg)
ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
ax25_disconnect(ax25, ETIMEDOUT);
}
spin_unlock_irqrestore(&ax25_list_lock, flags);
ax25_dev_dama_off(ax25_dev);
}
......
......@@ -20,6 +20,7 @@
#include <linux/in.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/timer.h>
#include <linux/string.h>
#include <linux/sockios.h>
......@@ -40,11 +41,13 @@ static struct protocol_struct {
unsigned int pid;
int (*func)(struct sk_buff *, ax25_cb *);
} *protocol_list;
static spinlock_t protocol_list_lock = SPIN_LOCK_UNLOCKED;
static struct linkfail_struct {
struct linkfail_struct *next;
void (*func)(ax25_cb *, int);
} *linkfail_list;
static spinlock_t linkfail_lock = SPIN_LOCK_UNLOCKED;
static struct listen_struct {
struct listen_struct *next;
......@@ -69,31 +72,29 @@ int ax25_protocol_register(unsigned int pid, int (*func)(struct sk_buff *, ax25_
protocol->pid = pid;
protocol->func = func;
save_flags(flags);
cli();
spin_lock_irqsave(&protocol_list_lock, flags);
protocol->next = protocol_list;
protocol_list = protocol;
restore_flags(flags);
spin_unlock_irqrestore(&protocol_list_lock, flags);
return 1;
}
void ax25_protocol_release(unsigned int pid)
{
struct protocol_struct *s, *protocol = protocol_list;
struct protocol_struct *s, *protocol;
unsigned long flags;
if (protocol == NULL)
spin_lock_irqsave(&protocol_list_lock, flags);
protocol = protocol_list;
if (protocol == NULL) {
spin_unlock_irqrestore(&protocol_list_lock, flags);
return;
save_flags(flags);
cli();
}
if (protocol->pid == pid) {
protocol_list = protocol->next;
restore_flags(flags);
spin_unlock_irqrestore(&protocol_list_lock, flags);
kfree(protocol);
return;
}
......@@ -102,15 +103,14 @@ void ax25_protocol_release(unsigned int pid)
if (protocol->next->pid == pid) {
s = protocol->next;
protocol->next = protocol->next->next;
restore_flags(flags);
spin_unlock_irqrestore(&protocol_list_lock, flags);
kfree(s);
return;
}
protocol = protocol->next;
}
restore_flags(flags);
spin_unlock_irqrestore(&protocol_list_lock, flags);
}
int ax25_linkfail_register(void (*func)(ax25_cb *, int))
......@@ -123,31 +123,27 @@ int ax25_linkfail_register(void (*func)(ax25_cb *, int))
linkfail->func = func;
save_flags(flags);
cli();
spin_lock_irqsave(&linkfail_lock, flags);
linkfail->next = linkfail_list;
linkfail_list = linkfail;
restore_flags(flags);
spin_unlock_irqrestore(&linkfail_lock, flags);
return 1;
}
void ax25_linkfail_release(void (*func)(ax25_cb *, int))
{
struct linkfail_struct *s, *linkfail = linkfail_list;
struct linkfail_struct *s, *linkfail;
unsigned long flags;
spin_lock_irqsave(&linkfail_lock, flags);
linkfail = linkfail_list;
if (linkfail == NULL)
return;
save_flags(flags);
cli();
if (linkfail->func == func) {
linkfail_list = linkfail->next;
restore_flags(flags);
spin_unlock_irqrestore(&linkfail_lock, flags);
kfree(linkfail);
return;
}
......@@ -156,15 +152,14 @@ void ax25_linkfail_release(void (*func)(ax25_cb *, int))
if (linkfail->next->func == func) {
s = linkfail->next;
linkfail->next = linkfail->next->next;
restore_flags(flags);
spin_unlock_irqrestore(&linkfail_lock, flags);
kfree(s);
return;
}
linkfail = linkfail->next;
}
restore_flags(flags);
spin_unlock_irqrestore(&linkfail_lock, flags);
}
int ax25_listen_register(ax25_address *callsign, struct net_device *dev)
......@@ -227,13 +222,19 @@ void ax25_listen_release(ax25_address *callsign, struct net_device *dev)
int (*ax25_protocol_function(unsigned int pid))(struct sk_buff *, ax25_cb *)
{
int (*res)(struct sk_buff *, ax25_cb *) = NULL;
struct protocol_struct *protocol;
unsigned long flags;
spin_lock_irqsave(&protocol_list_lock, flags);
for (protocol = protocol_list; protocol != NULL; protocol = protocol->next)
if (protocol->pid == pid)
return protocol->func;
if (protocol->pid == pid) {
res = protocol->func;
break;
}
spin_unlock_irqrestore(&protocol_list_lock, flags);
return NULL;
return res;
}
int ax25_listen_mine(ax25_address *callsign, struct net_device *dev)
......@@ -250,19 +251,27 @@ int ax25_listen_mine(ax25_address *callsign, struct net_device *dev)
void ax25_link_failed(ax25_cb *ax25, int reason)
{
struct linkfail_struct *linkfail;
unsigned long flags;
spin_lock_irqsave(&linkfail_lock, flags);
for (linkfail = linkfail_list; linkfail != NULL; linkfail = linkfail->next)
(linkfail->func)(ax25, reason);
spin_unlock_irqrestore(&linkfail_lock, flags);
}
int ax25_protocol_is_registered(unsigned int pid)
{
struct protocol_struct *protocol;
unsigned long flags;
int res = 0;
spin_lock_irqsave(&protocol_list_lock, flags);
for (protocol = protocol_list; protocol != NULL; protocol = protocol->next)
if (protocol->pid == pid)
return 1;
if (protocol->pid == pid) {
res = 1;
break;
}
spin_unlock_irqrestore(&protocol_list_lock, flags);
return 0;
return res;
}
......@@ -44,6 +44,7 @@
#include <linux/timer.h>
#include <linux/string.h>
#include <linux/sockios.h>
#include <linux/spinlock.h>
#include <linux/net.h>
#include <net/ax25.h>
#include <linux/inet.h>
......@@ -57,6 +58,8 @@
#include <linux/mm.h>
#include <linux/interrupt.h>
static spinlock_t ax25_frag_lock = SPIN_LOCK_UNLOCKED;
ax25_cb *ax25_send_frame(struct sk_buff *skb, int paclen, ax25_address *src, ax25_address *dest, ax25_digi *digi, struct net_device *dev)
{
ax25_dev *ax25_dev;
......@@ -155,11 +158,9 @@ void ax25_output(ax25_cb *ax25, int paclen, struct sk_buff *skb)
frontlen = skb_headroom(skb); /* Address space + CTRL */
while (skb->len > 0) {
save_flags(flags);
cli();
spin_lock_irqsave(&ax25_frag_lock, flags);
if ((skbn = alloc_skb(paclen + 2 + frontlen, GFP_ATOMIC)) == NULL) {
restore_flags(flags);
spin_unlock_irqrestore(&ax25_frag_lock, flags);
printk(KERN_CRIT "AX.25: ax25_output - out of memory\n");
return;
}
......@@ -167,7 +168,7 @@ void ax25_output(ax25_cb *ax25, int paclen, struct sk_buff *skb)
if (skb->sk != NULL)
skb_set_owner_w(skbn, skb->sk);
restore_flags(flags);
spin_unlock_irqrestore(&ax25_frag_lock, flags);
len = (paclen > skb->len) ? skb->len : paclen;
......
......@@ -56,6 +56,7 @@
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <net/sock.h>
#include <asm/uaccess.h>
#include <asm/system.h>
......@@ -65,6 +66,7 @@
#include <linux/init.h>
static ax25_route *ax25_route_list;
static spinlock_t ax25_route_lock = SPIN_LOCK_UNLOCKED;
static ax25_route *ax25_find_route(ax25_address *, struct net_device *);
......@@ -86,8 +88,11 @@ static inline void ax25_route_invert(ax25_digi *in, ax25_digi *out)
void ax25_rt_device_down(struct net_device *dev)
{
ax25_route *s, *t, *ax25_rt = ax25_route_list;
ax25_route *s, *t, *ax25_rt;
unsigned long flags;
spin_lock_irqsave(&ax25_route_lock, flags);
ax25_rt = ax25_route_list;
while (ax25_rt != NULL) {
s = ax25_rt;
ax25_rt = ax25_rt->next;
......@@ -111,6 +116,7 @@ void ax25_rt_device_down(struct net_device *dev)
}
}
}
spin_unlock_irqrestore(&ax25_route_lock, flags);
}
int ax25_rt_ioctl(unsigned int cmd, void *arg)
......@@ -167,10 +173,11 @@ int ax25_rt_ioctl(unsigned int cmd, void *arg)
ax25_rt->digipeat->calls[i] = route.digi_addr[i];
}
}
save_flags(flags); cli();
spin_lock_irqsave(&ax25_route_lock, flags);
ax25_rt->next = ax25_route_list;
ax25_route_list = ax25_rt;
restore_flags(flags);
spin_unlock_irqrestore(&ax25_route_lock, flags);
break;
case SIOCDELRT:
......@@ -239,13 +246,14 @@ int ax25_rt_ioctl(unsigned int cmd, void *arg)
int ax25_rt_get_info(char *buffer, char **start, off_t offset, int length)
{
ax25_route *ax25_rt;
unsigned long flags;
int len = 0;
off_t pos = 0;
off_t begin = 0;
char *callsign;
int i;
cli();
spin_lock_irqsave(&ax25_route_lock, flags);
len += sprintf(buffer, "callsign dev mode digipeaters\n");
......@@ -286,13 +294,13 @@ int ax25_rt_get_info(char *buffer, char **start, off_t offset, int length)
if (pos > offset + length)
break;
}
sti();
spin_unlock_irqrestore(&ax25_route_lock, flags);
*start = buffer + (offset - begin);
len -= (offset - begin);
if (len > length) len = length;
if (len > length)
len = length;
return len;
}
......
......@@ -23,6 +23,7 @@
#include <linux/string.h>
#include <linux/sockios.h>
#include <linux/net.h>
#include <linux/spinlock.h>
#include <net/ax25.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
......@@ -47,17 +48,24 @@
*/
static ax25_uid_assoc *ax25_uid_list;
static spinlock_t ax25_uid_lock = SPIN_LOCK_UNLOCKED;
int ax25_uid_policy = 0;
ax25_address *ax25_findbyuid(uid_t uid)
{
ax25_uid_assoc *ax25_uid;
ax25_address *res = NULL;
unsigned long flags;
spin_lock_irqsave(&ax25_uid_lock, flags);
for (ax25_uid = ax25_uid_list; ax25_uid != NULL; ax25_uid = ax25_uid->next) {
if (ax25_uid->uid == uid)
return &ax25_uid->call;
if (ax25_uid->uid == uid) {
res = &ax25_uid->call;
break;
}
}
spin_lock_irqsave(&ax25_uid_lock, flags);
return NULL;
}
......@@ -66,14 +74,21 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
{
ax25_uid_assoc *s, *ax25_uid;
unsigned long flags;
unsigned long res;
switch (cmd) {
case SIOCAX25GETUID:
res = -ENOENT;
spin_lock_irqsave(&ax25_uid_lock, flags);
for (ax25_uid = ax25_uid_list; ax25_uid != NULL; ax25_uid = ax25_uid->next) {
if (ax25cmp(&sax->sax25_call, &ax25_uid->call) == 0)
return ax25_uid->uid;
if (ax25cmp(&sax->sax25_call, &ax25_uid->call) == 0) {
res = ax25_uid->uid;
break;
}
return -ENOENT;
}
spin_lock_irqsave(&ax25_uid_lock, flags);
return res;
case SIOCAX25ADDUID:
if (!capable(CAP_NET_ADMIN))
......@@ -84,40 +99,48 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
return -EINVAL;
if ((ax25_uid = kmalloc(sizeof(*ax25_uid), GFP_KERNEL)) == NULL)
return -ENOMEM;
ax25_uid->uid = sax->sax25_uid;
ax25_uid->call = sax->sax25_call;
save_flags(flags); cli();
spin_lock_irqsave(&ax25_uid_lock, flags);
ax25_uid->next = ax25_uid_list;
ax25_uid_list = ax25_uid;
restore_flags(flags);
spin_unlock_irqrestore(&ax25_uid_lock, flags);
return 0;
case SIOCAX25DELUID:
if (!capable(CAP_NET_ADMIN))
return -EPERM;
spin_lock_irqsave(&ax25_uid_lock, flags);
for (ax25_uid = ax25_uid_list; ax25_uid != NULL; ax25_uid = ax25_uid->next) {
if (ax25cmp(&sax->sax25_call, &ax25_uid->call) == 0)
if (ax25cmp(&sax->sax25_call, &ax25_uid->call) == 0) {
break;
}
if (ax25_uid == NULL)
}
if (ax25_uid == NULL) {
spin_unlock_irqrestore(&ax25_uid_lock, flags);
return -ENOENT;
save_flags(flags); cli();
}
if ((s = ax25_uid_list) == ax25_uid) {
ax25_uid_list = s->next;
restore_flags(flags);
spin_unlock_irqrestore(&ax25_uid_lock, flags);
kfree(ax25_uid);
return 0;
}
while (s != NULL && s->next != NULL) {
if (s->next == ax25_uid) {
s->next = ax25_uid->next;
restore_flags(flags);
spin_unlock_irqrestore(&ax25_uid_lock, flags);
kfree(ax25_uid);
return 0;
}
s = s->next;
}
restore_flags(flags);
spin_unlock_irqrestore(&ax25_uid_lock, flags);
return -ENOENT;
default:
......@@ -129,13 +152,13 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
int ax25_uid_get_info(char *buffer, char **start, off_t offset, int length)
{
unsigned long flags;
ax25_uid_assoc *pt;
int len = 0;
off_t pos = 0;
off_t begin = 0;
cli();
spin_lock_irqsave(&ax25_uid_lock, flags);
len += sprintf(buffer, "Policy: %d\n", ax25_uid_policy);
for (pt = ax25_uid_list; pt != NULL; pt = pt->next) {
......@@ -151,13 +174,13 @@ int ax25_uid_get_info(char *buffer, char **start, off_t offset, int length)
if (pos > offset + length)
break;
}
sti();
spin_unlock_irqrestore(&ax25_uid_lock, flags);
*start = buffer + (offset - begin);
len -= offset - begin;
if (len > length) len = length;
if (len > length)
len = length;
return len;
}
......@@ -167,12 +190,17 @@ int ax25_uid_get_info(char *buffer, char **start, off_t offset, int length)
*/
void __exit ax25_uid_free(void)
{
ax25_uid_assoc *s, *ax25_uid = ax25_uid_list;
ax25_uid_assoc *s, *ax25_uid;
unsigned long flags;
spin_lock_irqsave(&ax25_uid_lock, flags);
ax25_uid = ax25_uid_list;
while (ax25_uid != NULL) {
s = ax25_uid;
ax25_uid = ax25_uid->next;
kfree(s);
}
ax25_uid_list = NULL;
spin_unlock_irqrestore(&ax25_uid_lock, flags);
}
......@@ -8,6 +8,7 @@
#include <linux/config.h>
#include <linux/mm.h>
#include <linux/sysctl.h>
#include <linux/spinlock.h>
#include <net/ax25.h>
static int min_ipdefmode[] = {0}, max_ipdefmode[] = {1};
......@@ -102,9 +103,11 @@ static const ctl_table ax25_param_table[] = {
void ax25_register_sysctl(void)
{
unsigned long flags;
ax25_dev *ax25_dev;
int n, k;
spin_lock_irqsave(&ax25_dev_lock, flags);
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);
......@@ -119,6 +122,7 @@ void ax25_register_sysctl(void)
while (n--)
kfree(ax25_table[n].child);
kfree(ax25_table);
spin_unlock_irqrestore(&ax25_dev_lock, flags);
return;
}
memcpy(child, ax25_param_table, sizeof(ax25_param_table));
......@@ -144,6 +148,7 @@ void ax25_register_sysctl(void)
n++;
}
spin_unlock_irqrestore(&ax25_dev_lock, flags);
ax25_dir_table[0].child = ax25_table;
......
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