Commit 752728c2 authored by Ralf Bächle's avatar Ralf Bächle

Redo locking of ax25_list with spinlocks.

parent 3b89dbbd
...@@ -3,11 +3,12 @@ ...@@ -3,11 +3,12 @@
* *
* Alan Cox (GW4PTS) 10/11/93 * Alan Cox (GW4PTS) 10/11/93
*/ */
#ifndef _AX25_H #ifndef _AX25_H
#define _AX25_H #define _AX25_H
#include <linux/config.h> #include <linux/config.h>
#include <linux/ax25.h> #include <linux/ax25.h>
#include <linux/spinlock.h>
#define AX25_T1CLAMPLO 1 #define AX25_T1CLAMPLO 1
#define AX25_T1CLAMPHI (30 * HZ) #define AX25_T1CLAMPHI (30 * HZ)
...@@ -197,7 +198,8 @@ typedef struct ax25_cb { ...@@ -197,7 +198,8 @@ typedef struct ax25_cb {
#define ax25_sk(__sk) ((ax25_cb *)(__sk)->protinfo) #define ax25_sk(__sk) ((ax25_cb *)(__sk)->protinfo)
/* af_ax25.c */ /* 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_free_cb(ax25_cb *);
extern void ax25_insert_socket(ax25_cb *); extern void ax25_insert_socket(ax25_cb *);
struct sock *ax25_find_listener(ax25_address *, int, struct net_device *, int); struct sock *ax25_find_listener(ax25_address *, int, struct net_device *, int);
......
...@@ -134,13 +134,15 @@ ...@@ -134,13 +134,15 @@
#include <linux/netfilter.h> #include <linux/netfilter.h>
#include <linux/sysctl.h> #include <linux/sysctl.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/spinlock.h>
#include <net/tcp.h> #include <net/tcp.h>
#include <net/ip.h> #include <net/ip.h>
#include <net/arp.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; static struct proto_ops ax25_proto_ops;
...@@ -173,25 +175,25 @@ static void ax25_remove_socket(ax25_cb *ax25) ...@@ -173,25 +175,25 @@ static void ax25_remove_socket(ax25_cb *ax25)
ax25_cb *s; ax25_cb *s;
unsigned long flags; unsigned long flags;
save_flags(flags); cli(); spin_lock_irqsave(&ax25_list_lock, flags);
if ((s = ax25_list) == ax25) { if ((s = ax25_list) == ax25) {
ax25_list = s->next; ax25_list = s->next;
restore_flags(flags); spin_unlock_irqrestore(&ax25_list_lock, flags);
return; return;
} }
while (s != NULL && s->next != NULL) { while (s != NULL && s->next != NULL) {
if (s->next == ax25) { if (s->next == ax25) {
s->next = ax25->next; s->next = ax25->next;
restore_flags(flags); spin_unlock_irqrestore(&ax25_list_lock, flags);
return; return;
} }
s = s->next; 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) ...@@ -199,18 +201,21 @@ static void ax25_remove_socket(ax25_cb *ax25)
*/ */
static void ax25_kill_by_device(struct net_device *dev) static void ax25_kill_by_device(struct net_device *dev)
{ {
unsigned long flags;
ax25_dev *ax25_dev; ax25_dev *ax25_dev;
ax25_cb *s; ax25_cb *s;
if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL) if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL)
return; return;
spin_lock_irqsave(&ax25_list_lock, flags);
for (s = ax25_list; s != NULL; s = s->next) { for (s = ax25_list; s != NULL; s = s->next) {
if (s->ax25_dev == ax25_dev) { if (s->ax25_dev == ax25_dev) {
s->ax25_dev = NULL; s->ax25_dev = NULL;
ax25_disconnect(s, ENETUNREACH); ax25_disconnect(s, ENETUNREACH);
} }
} }
spin_unlock_irqrestore(&ax25_list_lock, flags);
} }
/* /*
...@@ -247,13 +252,10 @@ void ax25_insert_socket(ax25_cb *ax25) ...@@ -247,13 +252,10 @@ void ax25_insert_socket(ax25_cb *ax25)
{ {
unsigned long flags; unsigned long flags;
save_flags(flags); spin_lock_irqsave(&ax25_list_lock, flags);
cli();
ax25->next = ax25_list; ax25->next = ax25_list;
ax25_list = ax25; ax25_list = ax25;
spin_unlock_irqrestore(&ax25_list_lock, flags);
restore_flags(flags);
} }
/* /*
...@@ -265,22 +267,21 @@ struct sock *ax25_find_listener(ax25_address *addr, int digi, struct net_device ...@@ -265,22 +267,21 @@ struct sock *ax25_find_listener(ax25_address *addr, int digi, struct net_device
unsigned long flags; unsigned long flags;
ax25_cb *s; ax25_cb *s;
save_flags(flags); spin_lock_irqsave(&ax25_list_lock, flags);
cli();
for (s = ax25_list; s != NULL; s = s->next) { for (s = ax25_list; s != NULL; s = s->next) {
if ((s->iamdigi && !digi) || (!s->iamdigi && digi)) if ((s->iamdigi && !digi) || (!s->iamdigi && digi))
continue; continue;
if (s->sk != NULL && ax25cmp(&s->source_addr, addr) == 0 && s->sk->type == type && s->sk->state == TCP_LISTEN) { 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 device is null we match any device */
if (s->ax25_dev == NULL || s->ax25_dev->dev == dev) { if (s->ax25_dev == NULL || s->ax25_dev->dev == dev) {
restore_flags(flags); spin_unlock_irqrestore(&ax25_list_lock, flags);
return s->sk; return s->sk;
} }
} }
} }
spin_unlock_irqrestore(&ax25_list_lock, flags);
restore_flags(flags);
return NULL; return NULL;
} }
...@@ -292,17 +293,15 @@ struct sock *ax25_find_socket(ax25_address *my_addr, ax25_address *dest_addr, in ...@@ -292,17 +293,15 @@ struct sock *ax25_find_socket(ax25_address *my_addr, ax25_address *dest_addr, in
ax25_cb *s; ax25_cb *s;
unsigned long flags; unsigned long flags;
save_flags(flags); spin_lock_irqsave(&ax25_list_lock, flags);
cli();
for (s = ax25_list; s != NULL; s = s->next) { 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) { 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; return s->sk;
} }
} }
spin_unlock_irqrestore(&ax25_list_lock, flags);
restore_flags(flags);
return NULL; return NULL;
} }
...@@ -316,9 +315,7 @@ ax25_cb *ax25_find_cb(ax25_address *src_addr, ax25_address *dest_addr, ax25_digi ...@@ -316,9 +315,7 @@ ax25_cb *ax25_find_cb(ax25_address *src_addr, ax25_address *dest_addr, ax25_digi
ax25_cb *s; ax25_cb *s;
unsigned long flags; unsigned long flags;
save_flags(flags); spin_lock_irqsave(&ax25_list_lock, flags);
cli();
for (s = ax25_list; s != NULL; s = s->next) { for (s = ax25_list; s != NULL; s = s->next) {
if (s->sk != NULL && s->sk->type != SOCK_SEQPACKET) if (s->sk != NULL && s->sk->type != SOCK_SEQPACKET)
continue; continue;
...@@ -334,12 +331,12 @@ ax25_cb *ax25_find_cb(ax25_address *src_addr, ax25_address *dest_addr, ax25_digi ...@@ -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) if (s->digipeat != NULL && s->digipeat->ndigi != 0)
continue; continue;
} }
restore_flags(flags); spin_unlock_irqrestore(&ax25_list_lock, flags);
return s; return s;
} }
} }
spin_unlock_irqrestore(&ax25_list_lock, flags);
restore_flags(flags);
return NULL; return NULL;
} }
...@@ -352,17 +349,14 @@ struct sock *ax25_addr_match(ax25_address *addr) ...@@ -352,17 +349,14 @@ struct sock *ax25_addr_match(ax25_address *addr)
unsigned long flags; unsigned long flags;
ax25_cb *s; ax25_cb *s;
save_flags(flags); spin_lock_irqsave(&ax25_list_lock, flags);
cli();
for (s = ax25_list; s != NULL; s = s->next) { for (s = ax25_list; s != NULL; s = s->next) {
if (s->sk != NULL && ax25cmp(&s->source_addr, addr) == 0 && s->sk->type == SOCK_RAW) { 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; return s->sk;
} }
} }
spin_unlock_irqrestore(&ax25_list_lock, flags);
restore_flags(flags);
return NULL; return NULL;
} }
...@@ -1738,13 +1732,14 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) ...@@ -1738,13 +1732,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) static int ax25_get_info(char *buffer, char **start, off_t offset, int length)
{ {
unsigned long flags;
ax25_cb *ax25; ax25_cb *ax25;
int k; int k;
int len = 0; int len = 0;
off_t pos = 0; off_t pos = 0;
off_t begin = 0; off_t begin = 0;
cli(); spin_lock_irqsave(&ax25_list_lock, flags);
/* /*
* New format: * New format:
...@@ -1799,7 +1794,7 @@ static int ax25_get_info(char *buffer, char **start, off_t offset, int length) ...@@ -1799,7 +1794,7 @@ static int ax25_get_info(char *buffer, char **start, off_t offset, int length)
break; break;
} }
sti(); spin_unlock_irqrestore(&ax25_list_lock, flags);
*start = buffer + (offset - begin); *start = buffer + (offset - begin);
len -= (offset - begin); len -= (offset - begin);
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/sockios.h> #include <linux/sockios.h>
#include <linux/spinlock.h>
#include <linux/net.h> #include <linux/net.h>
#include <net/ax25.h> #include <net/ax25.h>
#include <linux/inet.h> #include <linux/inet.h>
...@@ -53,6 +54,7 @@ void ax25_ds_nr_error_recovery(ax25_cb *ax25) ...@@ -53,6 +54,7 @@ void ax25_ds_nr_error_recovery(ax25_cb *ax25)
*/ */
void ax25_ds_enquiry_response(ax25_cb *ax25) void ax25_ds_enquiry_response(ax25_cb *ax25)
{ {
unsigned long flags;
ax25_cb *ax25o; ax25_cb *ax25o;
/* Please note that neither DK4EGs nor DG2FEFs /* Please note that neither DK4EGs nor DG2FEFs
...@@ -93,6 +95,7 @@ void ax25_ds_enquiry_response(ax25_cb *ax25) ...@@ -93,6 +95,7 @@ void ax25_ds_enquiry_response(ax25_cb *ax25)
ax25_start_t3timer(ax25); ax25_start_t3timer(ax25);
ax25_ds_set_timer(ax25->ax25_dev); ax25_ds_set_timer(ax25->ax25_dev);
spin_lock_irqsave(&ax25_list_lock, flags);
for (ax25o = ax25_list; ax25o != NULL; ax25o = ax25o->next) { for (ax25o = ax25_list; ax25o != NULL; ax25o = ax25o->next) {
if (ax25o == ax25) if (ax25o == ax25)
continue; continue;
...@@ -118,6 +121,7 @@ void ax25_ds_enquiry_response(ax25_cb *ax25) ...@@ -118,6 +121,7 @@ void ax25_ds_enquiry_response(ax25_cb *ax25)
if (ax25o->state != AX25_STATE_0) if (ax25o->state != AX25_STATE_0)
ax25_start_t3timer(ax25o); ax25_start_t3timer(ax25o);
} }
spin_unlock_irqrestore(&ax25_list_lock, flags);
} }
void ax25_ds_establish_data_link(ax25_cb *ax25) 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 ...@@ -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) static int ax25_check_dama_slave(ax25_dev *ax25_dev)
{ {
unsigned long flags;
ax25_cb *ax25; ax25_cb *ax25;
int res = 0;
spin_lock_irqsave(&ax25_list_lock, flags);
for (ax25 = ax25_list; ax25 != NULL ; ax25 = ax25->next) 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) if (ax25->ax25_dev == ax25_dev && (ax25->condition & AX25_COND_DAMA_MODE) && ax25->state > AX25_STATE_1) {
return 1; res = 1;
break;
}
spin_unlock_irqrestore(&ax25_list_lock, flags);
return 0; return res;
} }
void ax25_dev_dama_on(ax25_dev *ax25_dev) void ax25_dev_dama_on(ax25_dev *ax25_dev)
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/socket.h> #include <linux/socket.h>
#include <linux/spinlock.h>
#include <linux/in.h> #include <linux/in.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
...@@ -79,6 +80,7 @@ void ax25_ds_set_timer(ax25_dev *ax25_dev) ...@@ -79,6 +80,7 @@ void ax25_ds_set_timer(ax25_dev *ax25_dev)
static void ax25_ds_timeout(unsigned long arg) static void ax25_ds_timeout(unsigned long arg)
{ {
ax25_dev *ax25_dev = (struct ax25_dev *) arg; ax25_dev *ax25_dev = (struct ax25_dev *) arg;
unsigned long flags;
ax25_cb *ax25; ax25_cb *ax25;
if (ax25_dev == NULL || !ax25_dev->dama.slave) if (ax25_dev == NULL || !ax25_dev->dama.slave)
...@@ -89,6 +91,7 @@ static void ax25_ds_timeout(unsigned long arg) ...@@ -89,6 +91,7 @@ static void ax25_ds_timeout(unsigned long arg)
return; return;
} }
spin_lock_irqsave(&ax25_list_lock, flags);
for (ax25=ax25_list; ax25 != NULL; ax25 = ax25->next) { for (ax25=ax25_list; ax25 != NULL; ax25 = ax25->next) {
if (ax25->ax25_dev != ax25_dev || !(ax25->condition & AX25_COND_DAMA_MODE)) if (ax25->ax25_dev != ax25_dev || !(ax25->condition & AX25_COND_DAMA_MODE))
continue; continue;
...@@ -96,6 +99,7 @@ static void ax25_ds_timeout(unsigned long arg) ...@@ -96,6 +99,7 @@ static void ax25_ds_timeout(unsigned long arg)
ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND); ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
ax25_disconnect(ax25, ETIMEDOUT); ax25_disconnect(ax25, ETIMEDOUT);
} }
spin_unlock_irqrestore(&ax25_list_lock, flags);
ax25_dev_dama_off(ax25_dev); ax25_dev_dama_off(ax25_dev);
} }
......
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