Commit 6244be2f authored by Ralf Bächle's avatar Ralf Bächle

Convert ax25_route_list by a rw_lock, no longer an interrup-save

spinlock.
Reformat switch statements.
parent be0eacc3
This diff is collapsed.
...@@ -174,22 +174,22 @@ int ax25_fwd_ioctl(unsigned int cmd, struct ax25_fwd_struct *fwd) ...@@ -174,22 +174,22 @@ int ax25_fwd_ioctl(unsigned int cmd, struct ax25_fwd_struct *fwd)
return -EINVAL; return -EINVAL;
switch (cmd) { switch (cmd) {
case SIOCAX25ADDFWD: case SIOCAX25ADDFWD:
if ((fwd_dev = ax25_addr_ax25dev(&fwd->port_to)) == NULL) if ((fwd_dev = ax25_addr_ax25dev(&fwd->port_to)) == NULL)
return -EINVAL; return -EINVAL;
if (ax25_dev->forward != NULL) if (ax25_dev->forward != NULL)
return -EINVAL; return -EINVAL;
ax25_dev->forward = fwd_dev->dev; ax25_dev->forward = fwd_dev->dev;
break; break;
case SIOCAX25DELFWD:
if (ax25_dev->forward == NULL)
return -EINVAL;
ax25_dev->forward = NULL;
break;
default: case SIOCAX25DELFWD:
if (ax25_dev->forward == NULL)
return -EINVAL; return -EINVAL;
ax25_dev->forward = NULL;
break;
default:
return -EINVAL;
} }
return 0; return 0;
......
This diff is collapsed.
...@@ -108,28 +108,28 @@ void ax25_ds_heartbeat_expiry(ax25_cb *ax25) ...@@ -108,28 +108,28 @@ void ax25_ds_heartbeat_expiry(ax25_cb *ax25)
{ {
switch (ax25->state) { switch (ax25->state) {
case AX25_STATE_0: case AX25_STATE_0:
/* Magic here: If we listen() and a new link dies before it /* Magic here: If we listen() and a new link dies before it
is accepted() it isn't 'dead' so doesn't get removed. */ is accepted() it isn't 'dead' so doesn't get removed. */
if (ax25->sk == NULL || ax25->sk->destroy || (ax25->sk->state == TCP_LISTEN && ax25->sk->dead)) { if (ax25->sk == NULL || ax25->sk->destroy || (ax25->sk->state == TCP_LISTEN && ax25->sk->dead)) {
ax25_destroy_socket(ax25); ax25_destroy_socket(ax25);
return; return;
} }
break; break;
case AX25_STATE_3: case AX25_STATE_3:
/* /*
* Check the state of the receive buffer. * Check the state of the receive buffer.
*/ */
if (ax25->sk != NULL) { if (ax25->sk != NULL) {
if (atomic_read(&ax25->sk->rmem_alloc) < (ax25->sk->rcvbuf / 2) && if (atomic_read(&ax25->sk->rmem_alloc) < (ax25->sk->rcvbuf / 2) &&
(ax25->condition & AX25_COND_OWN_RX_BUSY)) { (ax25->condition & AX25_COND_OWN_RX_BUSY)) {
ax25->condition &= ~AX25_COND_OWN_RX_BUSY; ax25->condition &= ~AX25_COND_OWN_RX_BUSY;
ax25->condition &= ~AX25_COND_ACK_PENDING; ax25->condition &= ~AX25_COND_ACK_PENDING;
break; break;
}
} }
break; }
break;
} }
ax25_start_heartbeat(ax25); ax25_start_heartbeat(ax25);
...@@ -182,46 +182,45 @@ void ax25_ds_idletimer_expiry(ax25_cb *ax25) ...@@ -182,46 +182,45 @@ void ax25_ds_idletimer_expiry(ax25_cb *ax25)
void ax25_ds_t1_timeout(ax25_cb *ax25) void ax25_ds_t1_timeout(ax25_cb *ax25)
{ {
switch (ax25->state) { switch (ax25->state) {
case AX25_STATE_1:
case AX25_STATE_1: if (ax25->n2count == ax25->n2) {
if (ax25->n2count == ax25->n2) { if (ax25->modulus == AX25_MODULUS) {
if (ax25->modulus == AX25_MODULUS) {
ax25_disconnect(ax25, ETIMEDOUT);
return;
} else {
ax25->modulus = AX25_MODULUS;
ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW];
ax25->n2count = 0;
ax25_send_control(ax25, AX25_SABM, AX25_POLLOFF, AX25_COMMAND);
}
} else {
ax25->n2count++;
if (ax25->modulus == AX25_MODULUS)
ax25_send_control(ax25, AX25_SABM, AX25_POLLOFF, AX25_COMMAND);
else
ax25_send_control(ax25, AX25_SABME, AX25_POLLOFF, AX25_COMMAND);
}
break;
case AX25_STATE_2:
if (ax25->n2count == ax25->n2) {
ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
ax25_disconnect(ax25, ETIMEDOUT);
return;
} else {
ax25->n2count++;
}
break;
case AX25_STATE_3:
if (ax25->n2count == ax25->n2) {
ax25_send_control(ax25, AX25_DM, AX25_POLLON, AX25_RESPONSE);
ax25_disconnect(ax25, ETIMEDOUT); ax25_disconnect(ax25, ETIMEDOUT);
return; return;
} else { } else {
ax25->n2count++; ax25->modulus = AX25_MODULUS;
ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW];
ax25->n2count = 0;
ax25_send_control(ax25, AX25_SABM, AX25_POLLOFF, AX25_COMMAND);
} }
break; } else {
ax25->n2count++;
if (ax25->modulus == AX25_MODULUS)
ax25_send_control(ax25, AX25_SABM, AX25_POLLOFF, AX25_COMMAND);
else
ax25_send_control(ax25, AX25_SABME, AX25_POLLOFF, AX25_COMMAND);
}
break;
case AX25_STATE_2:
if (ax25->n2count == ax25->n2) {
ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
ax25_disconnect(ax25, ETIMEDOUT);
return;
} else {
ax25->n2count++;
}
break;
case AX25_STATE_3:
if (ax25->n2count == ax25->n2) {
ax25_send_control(ax25, AX25_DM, AX25_POLLON, AX25_RESPONSE);
ax25_disconnect(ax25, ETIMEDOUT);
return;
} else {
ax25->n2count++;
}
break;
} }
ax25_calculate_t1(ax25); ax25_calculate_t1(ax25);
......
...@@ -41,7 +41,7 @@ static struct protocol_struct { ...@@ -41,7 +41,7 @@ static struct protocol_struct {
unsigned int pid; unsigned int pid;
int (*func)(struct sk_buff *, ax25_cb *); int (*func)(struct sk_buff *, ax25_cb *);
} *protocol_list; } *protocol_list;
static spinlock_t protocol_list_lock = SPIN_LOCK_UNLOCKED; static rwlock_t protocol_list_lock = RW_LOCK_UNLOCKED;
static struct linkfail_struct { static struct linkfail_struct {
struct linkfail_struct *next; struct linkfail_struct *next;
...@@ -59,7 +59,6 @@ static spinlock_t listen_lock = SPIN_LOCK_UNLOCKED; ...@@ -59,7 +59,6 @@ static spinlock_t listen_lock = SPIN_LOCK_UNLOCKED;
int ax25_protocol_register(unsigned int pid, int (*func)(struct sk_buff *, ax25_cb *)) int ax25_protocol_register(unsigned int pid, int (*func)(struct sk_buff *, ax25_cb *))
{ {
struct protocol_struct *protocol; struct protocol_struct *protocol;
unsigned long flags;
if (pid == AX25_P_TEXT || pid == AX25_P_SEGMENT) if (pid == AX25_P_TEXT || pid == AX25_P_SEGMENT)
return 0; return 0;
...@@ -73,10 +72,10 @@ int ax25_protocol_register(unsigned int pid, int (*func)(struct sk_buff *, ax25_ ...@@ -73,10 +72,10 @@ int ax25_protocol_register(unsigned int pid, int (*func)(struct sk_buff *, ax25_
protocol->pid = pid; protocol->pid = pid;
protocol->func = func; protocol->func = func;
spin_lock_irqsave(&protocol_list_lock, flags); write_lock(&protocol_list_lock);
protocol->next = protocol_list; protocol->next = protocol_list;
protocol_list = protocol; protocol_list = protocol;
spin_unlock_irqrestore(&protocol_list_lock, flags); write_unlock(&protocol_list_lock);
return 1; return 1;
} }
...@@ -84,18 +83,17 @@ int ax25_protocol_register(unsigned int pid, int (*func)(struct sk_buff *, ax25_ ...@@ -84,18 +83,17 @@ int ax25_protocol_register(unsigned int pid, int (*func)(struct sk_buff *, ax25_
void ax25_protocol_release(unsigned int pid) void ax25_protocol_release(unsigned int pid)
{ {
struct protocol_struct *s, *protocol; struct protocol_struct *s, *protocol;
unsigned long flags;
spin_lock_irqsave(&protocol_list_lock, flags); write_lock(&protocol_list_lock);
protocol = protocol_list; protocol = protocol_list;
if (protocol == NULL) { if (protocol == NULL) {
spin_unlock_irqrestore(&protocol_list_lock, flags); write_unlock(&protocol_list_lock);
return; return;
} }
if (protocol->pid == pid) { if (protocol->pid == pid) {
protocol_list = protocol->next; protocol_list = protocol->next;
spin_unlock_irqrestore(&protocol_list_lock, flags); write_unlock(&protocol_list_lock);
kfree(protocol); kfree(protocol);
return; return;
} }
...@@ -104,14 +102,14 @@ void ax25_protocol_release(unsigned int pid) ...@@ -104,14 +102,14 @@ void ax25_protocol_release(unsigned int pid)
if (protocol->next->pid == pid) { if (protocol->next->pid == pid) {
s = protocol->next; s = protocol->next;
protocol->next = protocol->next->next; protocol->next = protocol->next->next;
spin_unlock_irqrestore(&protocol_list_lock, flags); write_unlock(&protocol_list_lock);
kfree(s); kfree(s);
return; return;
} }
protocol = protocol->next; protocol = protocol->next;
} }
spin_unlock_irqrestore(&protocol_list_lock, flags); write_unlock(&protocol_list_lock);
} }
int ax25_linkfail_register(void (*func)(ax25_cb *, int)) int ax25_linkfail_register(void (*func)(ax25_cb *, int))
...@@ -220,15 +218,14 @@ int (*ax25_protocol_function(unsigned int pid))(struct sk_buff *, ax25_cb *) ...@@ -220,15 +218,14 @@ int (*ax25_protocol_function(unsigned int pid))(struct sk_buff *, ax25_cb *)
{ {
int (*res)(struct sk_buff *, ax25_cb *) = NULL; int (*res)(struct sk_buff *, ax25_cb *) = NULL;
struct protocol_struct *protocol; struct protocol_struct *protocol;
unsigned long flags;
spin_lock_irqsave(&protocol_list_lock, flags); read_lock(&protocol_list_lock);
for (protocol = protocol_list; protocol != NULL; protocol = protocol->next) for (protocol = protocol_list; protocol != NULL; protocol = protocol->next)
if (protocol->pid == pid) { if (protocol->pid == pid) {
res = protocol->func; res = protocol->func;
break; break;
} }
spin_unlock_irqrestore(&protocol_list_lock, flags); read_unlock(&protocol_list_lock);
return res; return res;
} }
...@@ -261,16 +258,15 @@ void ax25_link_failed(ax25_cb *ax25, int reason) ...@@ -261,16 +258,15 @@ void ax25_link_failed(ax25_cb *ax25, int reason)
int ax25_protocol_is_registered(unsigned int pid) int ax25_protocol_is_registered(unsigned int pid)
{ {
struct protocol_struct *protocol; struct protocol_struct *protocol;
unsigned long flags;
int res = 0; int res = 0;
spin_lock_irqsave(&protocol_list_lock, flags); read_lock(&protocol_list_lock);
for (protocol = protocol_list; protocol != NULL; protocol = protocol->next) for (protocol = protocol_list; protocol != NULL; protocol = protocol->next)
if (protocol->pid == pid) { if (protocol->pid == pid) {
res = 1; res = 1;
break; break;
} }
spin_unlock_irqrestore(&protocol_list_lock, flags); read_unlock(&protocol_list_lock);
return res; return res;
} }
...@@ -199,18 +199,18 @@ static int ax25_process_rx_frame(ax25_cb *ax25, struct sk_buff *skb, int type, i ...@@ -199,18 +199,18 @@ static int ax25_process_rx_frame(ax25_cb *ax25, struct sk_buff *skb, int type, i
return 0; return 0;
switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) { switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
case AX25_PROTO_STD_SIMPLEX: case AX25_PROTO_STD_SIMPLEX:
case AX25_PROTO_STD_DUPLEX: case AX25_PROTO_STD_DUPLEX:
queued = ax25_std_frame_in(ax25, skb, type); queued = ax25_std_frame_in(ax25, skb, type);
break; break;
#ifdef CONFIG_AX25_DAMA_SLAVE #ifdef CONFIG_AX25_DAMA_SLAVE
case AX25_PROTO_DAMA_SLAVE: case AX25_PROTO_DAMA_SLAVE:
if (dama || ax25->ax25_dev->dama.slave) if (dama || ax25->ax25_dev->dama.slave)
queued = ax25_ds_frame_in(ax25, skb, type); queued = ax25_ds_frame_in(ax25, skb, type);
else else
queued = ax25_std_frame_in(ax25, skb, type); queued = ax25_std_frame_in(ax25, skb, type);
break; break;
#endif #endif
} }
...@@ -285,47 +285,47 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev, ax25_address *d ...@@ -285,47 +285,47 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev, ax25_address *d
/* Now we are pointing at the pid byte */ /* Now we are pointing at the pid byte */
switch (skb->data[1]) { switch (skb->data[1]) {
#ifdef CONFIG_INET #ifdef CONFIG_INET
case AX25_P_IP: case AX25_P_IP:
skb_pull(skb,2); /* drop PID/CTRL */ skb_pull(skb,2); /* drop PID/CTRL */
skb->h.raw = skb->data; skb->h.raw = skb->data;
skb->nh.raw = skb->data; skb->nh.raw = skb->data;
skb->dev = dev; skb->dev = dev;
skb->pkt_type = PACKET_HOST; skb->pkt_type = PACKET_HOST;
skb->protocol = htons(ETH_P_IP); skb->protocol = htons(ETH_P_IP);
ip_rcv(skb, dev, ptype); /* Note ptype here is the wrong one, fix me later */ ip_rcv(skb, dev, ptype); /* Note ptype here is the wrong one, fix me later */
break; break;
case AX25_P_ARP: case AX25_P_ARP:
skb_pull(skb,2); skb_pull(skb,2);
skb->h.raw = skb->data; skb->h.raw = skb->data;
skb->nh.raw = skb->data; skb->nh.raw = skb->data;
skb->dev = dev; skb->dev = dev;
skb->pkt_type = PACKET_HOST; skb->pkt_type = PACKET_HOST;
skb->protocol = htons(ETH_P_ARP); skb->protocol = htons(ETH_P_ARP);
arp_rcv(skb, dev, ptype); /* Note ptype here is wrong... */ arp_rcv(skb, dev, ptype); /* Note ptype here is wrong... */
break; break;
#endif #endif
case AX25_P_TEXT: case AX25_P_TEXT:
/* Now find a suitable dgram socket */ /* Now find a suitable dgram socket */
if ((sk = ax25_find_socket(&dest, &src, SOCK_DGRAM)) != NULL) { if ((sk = ax25_find_socket(&dest, &src, SOCK_DGRAM)) != NULL) {
if (atomic_read(&sk->rmem_alloc) >= sk->rcvbuf) { if (atomic_read(&sk->rmem_alloc) >= sk->rcvbuf) {
kfree_skb(skb);
} else {
/*
* Remove the control and PID.
*/
skb_pull(skb, 2);
if (sock_queue_rcv_skb(sk, skb) != 0)
kfree_skb(skb);
}
} else {
kfree_skb(skb); kfree_skb(skb);
} else {
/*
* Remove the control and PID.
*/
skb_pull(skb, 2);
if (sock_queue_rcv_skb(sk, skb) != 0)
kfree_skb(skb);
} }
break; } else {
kfree_skb(skb);
}
break;
default: default:
kfree_skb(skb); /* Will scan SOCK_AX25 RAW sockets */ kfree_skb(skb); /* Will scan SOCK_AX25 RAW sockets */
break; break;
} }
return 0; return 0;
......
...@@ -88,16 +88,16 @@ int ax25_encapsulate(struct sk_buff *skb, struct net_device *dev, unsigned short ...@@ -88,16 +88,16 @@ int ax25_encapsulate(struct sk_buff *skb, struct net_device *dev, unsigned short
/* Append a suitable AX.25 PID */ /* Append a suitable AX.25 PID */
switch (type) { switch (type) {
case ETH_P_IP: case ETH_P_IP:
*buff++ = AX25_P_IP; *buff++ = AX25_P_IP;
break; break;
case ETH_P_ARP: case ETH_P_ARP:
*buff++ = AX25_P_ARP; *buff++ = AX25_P_ARP;
break; break;
default: default:
printk(KERN_ERR "AX.25: ax25_encapsulate - wrong protocol type 0x%2.2x\n", type); printk(KERN_ERR "AX.25: ax25_encapsulate - wrong protocol type 0x%2.2x\n", type);
*buff++ = 0; *buff++ = 0;
break; break;
} }
if (daddr != NULL) if (daddr != NULL)
......
...@@ -104,18 +104,18 @@ ax25_cb *ax25_send_frame(struct sk_buff *skb, int paclen, ax25_address *src, ax2 ...@@ -104,18 +104,18 @@ ax25_cb *ax25_send_frame(struct sk_buff *skb, int paclen, ax25_address *src, ax2
} }
switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) { switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
case AX25_PROTO_STD_SIMPLEX: case AX25_PROTO_STD_SIMPLEX:
case AX25_PROTO_STD_DUPLEX: case AX25_PROTO_STD_DUPLEX:
ax25_std_establish_data_link(ax25); ax25_std_establish_data_link(ax25);
break; break;
#ifdef CONFIG_AX25_DAMA_SLAVE #ifdef CONFIG_AX25_DAMA_SLAVE
case AX25_PROTO_DAMA_SLAVE: case AX25_PROTO_DAMA_SLAVE:
if (ax25_dev->dama.slave) if (ax25_dev->dama.slave)
ax25_ds_establish_data_link(ax25); ax25_ds_establish_data_link(ax25);
else else
ax25_std_establish_data_link(ax25); ax25_std_establish_data_link(ax25);
break; break;
#endif #endif
} }
...@@ -203,19 +203,19 @@ void ax25_output(ax25_cb *ax25, int paclen, struct sk_buff *skb) ...@@ -203,19 +203,19 @@ void ax25_output(ax25_cb *ax25, int paclen, struct sk_buff *skb)
} }
switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) { switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
case AX25_PROTO_STD_SIMPLEX: case AX25_PROTO_STD_SIMPLEX:
case AX25_PROTO_STD_DUPLEX: case AX25_PROTO_STD_DUPLEX:
ax25_kick(ax25); ax25_kick(ax25);
break; break;
#ifdef CONFIG_AX25_DAMA_SLAVE #ifdef CONFIG_AX25_DAMA_SLAVE
/* /*
* A DAMA slave is _required_ to work as normal AX.25L2V2 * A DAMA slave is _required_ to work as normal AX.25L2V2
* if no DAMA master is available. * if no DAMA master is available.
*/ */
case AX25_PROTO_DAMA_SLAVE: case AX25_PROTO_DAMA_SLAVE:
if (!ax25->ax25_dev->dama.slave) ax25_kick(ax25); if (!ax25->ax25_dev->dama.slave) ax25_kick(ax25);
break; break;
#endif #endif
} }
} }
...@@ -306,15 +306,15 @@ void ax25_kick(ax25_cb *ax25) ...@@ -306,15 +306,15 @@ void ax25_kick(ax25_cb *ax25)
* in DAMA mode. * in DAMA mode.
*/ */
switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) { switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
case AX25_PROTO_STD_SIMPLEX: case AX25_PROTO_STD_SIMPLEX:
case AX25_PROTO_STD_DUPLEX: case AX25_PROTO_STD_DUPLEX:
ax25_send_iframe(ax25, skbn, (last) ? AX25_POLLON : AX25_POLLOFF); ax25_send_iframe(ax25, skbn, (last) ? AX25_POLLON : AX25_POLLOFF);
break; break;
#ifdef CONFIG_AX25_DAMA_SLAVE #ifdef CONFIG_AX25_DAMA_SLAVE
case AX25_PROTO_DAMA_SLAVE: case AX25_PROTO_DAMA_SLAVE:
ax25_send_iframe(ax25, skbn, AX25_POLLOFF); ax25_send_iframe(ax25, skbn, AX25_POLLOFF);
break; break;
#endif #endif
} }
......
...@@ -66,7 +66,7 @@ ...@@ -66,7 +66,7 @@
#include <linux/init.h> #include <linux/init.h>
static ax25_route *ax25_route_list; static ax25_route *ax25_route_list;
static spinlock_t ax25_route_lock = SPIN_LOCK_UNLOCKED; static rwlock_t ax25_route_lock = RW_LOCK_UNLOCKED;
static ax25_route *ax25_find_route(ax25_address *, struct net_device *); static ax25_route *ax25_find_route(ax25_address *, struct net_device *);
...@@ -89,9 +89,8 @@ static inline void ax25_route_invert(ax25_digi *in, ax25_digi *out) ...@@ -89,9 +89,8 @@ static inline void ax25_route_invert(ax25_digi *in, ax25_digi *out)
void ax25_rt_device_down(struct net_device *dev) void ax25_rt_device_down(struct net_device *dev)
{ {
ax25_route *s, *t, *ax25_rt; ax25_route *s, *t, *ax25_rt;
unsigned long flags;
spin_lock_irqsave(&ax25_route_lock, flags); write_lock(&ax25_route_lock);
ax25_rt = ax25_route_list; ax25_rt = ax25_route_list;
while (ax25_rt != NULL) { while (ax25_rt != NULL) {
s = ax25_rt; s = ax25_rt;
...@@ -116,12 +115,11 @@ void ax25_rt_device_down(struct net_device *dev) ...@@ -116,12 +115,11 @@ void ax25_rt_device_down(struct net_device *dev)
} }
} }
} }
spin_unlock_irqrestore(&ax25_route_lock, flags); write_unlock(&ax25_route_lock);
} }
int ax25_rt_ioctl(unsigned int cmd, void *arg) int ax25_rt_ioctl(unsigned int cmd, void *arg)
{ {
unsigned long flags;
ax25_route *s, *t, *ax25_rt; ax25_route *s, *t, *ax25_rt;
struct ax25_routes_struct route; struct ax25_routes_struct route;
struct ax25_route_opt_struct rt_option; struct ax25_route_opt_struct rt_option;
...@@ -129,115 +127,122 @@ int ax25_rt_ioctl(unsigned int cmd, void *arg) ...@@ -129,115 +127,122 @@ int ax25_rt_ioctl(unsigned int cmd, void *arg)
int i; int i;
switch (cmd) { switch (cmd) {
case SIOCADDRT: case SIOCADDRT:
if (copy_from_user(&route, arg, sizeof(route))) if (copy_from_user(&route, arg, sizeof(route)))
return -EFAULT; return -EFAULT;
if ((ax25_dev = ax25_addr_ax25dev(&route.port_addr)) == NULL) if ((ax25_dev = ax25_addr_ax25dev(&route.port_addr)) == NULL)
return -EINVAL; return -EINVAL;
if (route.digi_count > AX25_MAX_DIGIS) if (route.digi_count > AX25_MAX_DIGIS)
return -EINVAL; return -EINVAL;
for (ax25_rt = ax25_route_list; ax25_rt != NULL; ax25_rt = ax25_rt->next) { write_lock(ax25_route_lock);
if (ax25cmp(&ax25_rt->callsign, &route.dest_addr) == 0 && ax25_rt->dev == ax25_dev->dev) { for (ax25_rt = ax25_route_list; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
if (ax25_rt->digipeat != NULL) { if (ax25cmp(&ax25_rt->callsign, &route.dest_addr) == 0 && ax25_rt->dev == ax25_dev->dev) {
kfree(ax25_rt->digipeat); if (ax25_rt->digipeat != NULL) {
ax25_rt->digipeat = NULL; kfree(ax25_rt->digipeat);
ax25_rt->digipeat = NULL;
}
if (route.digi_count != 0) {
if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
write_unlock(ax25_route_lock);
return -ENOMEM;
} }
if (route.digi_count != 0) { ax25_rt->digipeat->lastrepeat = -1;
if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) ax25_rt->digipeat->ndigi = route.digi_count;
return -ENOMEM; for (i = 0; i < route.digi_count; i++) {
ax25_rt->digipeat->lastrepeat = -1; ax25_rt->digipeat->repeated[i] = 0;
ax25_rt->digipeat->ndigi = route.digi_count; ax25_rt->digipeat->calls[i] = route.digi_addr[i];
for (i = 0; i < route.digi_count; i++) {
ax25_rt->digipeat->repeated[i] = 0;
ax25_rt->digipeat->calls[i] = route.digi_addr[i];
}
} }
return 0;
} }
return 0;
} }
if ((ax25_rt = kmalloc(sizeof(ax25_route), GFP_ATOMIC)) == NULL) }
if ((ax25_rt = kmalloc(sizeof(ax25_route), GFP_ATOMIC)) == NULL) {
write_unlock(ax25_route_lock);
return -ENOMEM;
}
ax25_rt->callsign = route.dest_addr;
ax25_rt->dev = ax25_dev->dev;
ax25_rt->digipeat = NULL;
ax25_rt->ip_mode = ' ';
if (route.digi_count != 0) {
if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
write_unlock(ax25_route_lock);
kfree(ax25_rt);
return -ENOMEM; return -ENOMEM;
ax25_rt->callsign = route.dest_addr;
ax25_rt->dev = ax25_dev->dev;
ax25_rt->digipeat = NULL;
ax25_rt->ip_mode = ' ';
if (route.digi_count != 0) {
if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
kfree(ax25_rt);
return -ENOMEM;
}
ax25_rt->digipeat->lastrepeat = -1;
ax25_rt->digipeat->ndigi = route.digi_count;
for (i = 0; i < route.digi_count; i++) {
ax25_rt->digipeat->repeated[i] = 0;
ax25_rt->digipeat->calls[i] = route.digi_addr[i];
}
} }
spin_lock_irqsave(&ax25_route_lock, flags); ax25_rt->digipeat->lastrepeat = -1;
ax25_rt->next = ax25_route_list; ax25_rt->digipeat->ndigi = route.digi_count;
ax25_route_list = ax25_rt; for (i = 0; i < route.digi_count; i++) {
spin_unlock_irqrestore(&ax25_route_lock, flags); ax25_rt->digipeat->repeated[i] = 0;
ax25_rt->digipeat->calls[i] = route.digi_addr[i];
}
}
ax25_rt->next = ax25_route_list;
ax25_route_list = ax25_rt;
write_unlock(ax25_route_lock);
break; break;
case SIOCDELRT: case SIOCDELRT:
if (copy_from_user(&route, arg, sizeof(route))) if (copy_from_user(&route, arg, sizeof(route)))
return -EFAULT; return -EFAULT;
if ((ax25_dev = ax25_addr_ax25dev(&route.port_addr)) == NULL) if ((ax25_dev = ax25_addr_ax25dev(&route.port_addr)) == NULL)
return -EINVAL; return -EINVAL;
ax25_rt = ax25_route_list; ax25_rt = ax25_route_list;
while (ax25_rt != NULL) { while (ax25_rt != NULL) {
s = ax25_rt; s = ax25_rt;
ax25_rt = ax25_rt->next; ax25_rt = ax25_rt->next;
if (s->dev == ax25_dev->dev && ax25cmp(&route.dest_addr, &s->callsign) == 0) { if (s->dev == ax25_dev->dev && ax25cmp(&route.dest_addr, &s->callsign) == 0) {
if (ax25_route_list == s) { if (ax25_route_list == s) {
ax25_route_list = s->next; ax25_route_list = s->next;
if (s->digipeat != NULL) if (s->digipeat != NULL)
kfree(s->digipeat); kfree(s->digipeat);
kfree(s); kfree(s);
} else { } else {
for (t = ax25_route_list; t != NULL; t = t->next) { for (t = ax25_route_list; t != NULL; t = t->next) {
if (t->next == s) { if (t->next == s) {
t->next = s->next; t->next = s->next;
if (s->digipeat != NULL) if (s->digipeat != NULL)
kfree(s->digipeat); kfree(s->digipeat);
kfree(s); kfree(s);
break; break;
} }
} }
}
} }
} }
break; }
break;
case SIOCAX25OPTRT: case SIOCAX25OPTRT:
if (copy_from_user(&rt_option, arg, sizeof(rt_option))) if (copy_from_user(&rt_option, arg, sizeof(rt_option)))
return -EFAULT; return -EFAULT;
if ((ax25_dev = ax25_addr_ax25dev(&rt_option.port_addr)) == NULL) if ((ax25_dev = ax25_addr_ax25dev(&rt_option.port_addr)) == NULL)
return -EINVAL; return -EINVAL;
for (ax25_rt = ax25_route_list; ax25_rt != NULL; ax25_rt = ax25_rt->next) { write_lock(ax25_route_lock);
if (ax25_rt->dev == ax25_dev->dev && ax25cmp(&rt_option.dest_addr, &ax25_rt->callsign) == 0) { for (ax25_rt = ax25_route_list; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
switch (rt_option.cmd) { if (ax25_rt->dev == ax25_dev->dev && ax25cmp(&rt_option.dest_addr, &ax25_rt->callsign) == 0) {
case AX25_SET_RT_IPMODE: switch (rt_option.cmd) {
switch (rt_option.arg) { case AX25_SET_RT_IPMODE:
case ' ': switch (rt_option.arg) {
case 'D': case ' ':
case 'V': case 'D':
ax25_rt->ip_mode = rt_option.arg; case 'V':
break; ax25_rt->ip_mode = rt_option.arg;
default: break;
return -EINVAL; default:
} return -EINVAL;
break; }
default: break;
return -EINVAL; default:
} return -EINVAL;
} }
} }
break; }
write_unlock(ax25_route_lock);
break;
default: default:
return -EINVAL; return -EINVAL;
} }
return 0; return 0;
...@@ -246,14 +251,13 @@ int ax25_rt_ioctl(unsigned int cmd, void *arg) ...@@ -246,14 +251,13 @@ int ax25_rt_ioctl(unsigned int cmd, void *arg)
int ax25_rt_get_info(char *buffer, char **start, off_t offset, int length) int ax25_rt_get_info(char *buffer, char **start, off_t offset, int length)
{ {
ax25_route *ax25_rt; ax25_route *ax25_rt;
unsigned long flags;
int len = 0; int len = 0;
off_t pos = 0; off_t pos = 0;
off_t begin = 0; off_t begin = 0;
char *callsign; char *callsign;
int i; int i;
spin_lock_irqsave(&ax25_route_lock, flags); read_lock(&ax25_route_lock);
len += sprintf(buffer, "callsign dev mode digipeaters\n"); len += sprintf(buffer, "callsign dev mode digipeaters\n");
...@@ -267,15 +271,15 @@ int ax25_rt_get_info(char *buffer, char **start, off_t offset, int length) ...@@ -267,15 +271,15 @@ int ax25_rt_get_info(char *buffer, char **start, off_t offset, int length)
ax25_rt->dev ? ax25_rt->dev->name : "???"); ax25_rt->dev ? ax25_rt->dev->name : "???");
switch (ax25_rt->ip_mode) { switch (ax25_rt->ip_mode) {
case 'V': case 'V':
len += sprintf(buffer + len, " vc"); len += sprintf(buffer + len, " vc");
break; break;
case 'D': case 'D':
len += sprintf(buffer + len, " dg"); len += sprintf(buffer + len, " dg");
break; break;
default: default:
len += sprintf(buffer + len, " *"); len += sprintf(buffer + len, " *");
break; break;
} }
if (ax25_rt->digipeat != NULL) if (ax25_rt->digipeat != NULL)
...@@ -294,7 +298,7 @@ int ax25_rt_get_info(char *buffer, char **start, off_t offset, int length) ...@@ -294,7 +298,7 @@ int ax25_rt_get_info(char *buffer, char **start, off_t offset, int length)
if (pos > offset + length) if (pos > offset + length)
break; break;
} }
spin_unlock_irqrestore(&ax25_route_lock, flags); read_unlock(&ax25_route_lock);
*start = buffer + (offset - begin); *start = buffer + (offset - begin);
len -= (offset - begin); len -= (offset - begin);
...@@ -314,6 +318,7 @@ static ax25_route *ax25_find_route(ax25_address *addr, struct net_device *dev) ...@@ -314,6 +318,7 @@ static ax25_route *ax25_find_route(ax25_address *addr, struct net_device *dev)
ax25_route *ax25_def_rt = NULL; ax25_route *ax25_def_rt = NULL;
ax25_route *ax25_rt; ax25_route *ax25_rt;
read_lock(&ax25_route_lock);
/* /*
* Bind to the physical interface we heard them on, or the default * Bind to the physical interface we heard them on, or the default
* route if none is found; * route if none is found;
...@@ -331,6 +336,7 @@ static ax25_route *ax25_find_route(ax25_address *addr, struct net_device *dev) ...@@ -331,6 +336,7 @@ static ax25_route *ax25_find_route(ax25_address *addr, struct net_device *dev)
ax25_def_rt = ax25_rt; ax25_def_rt = ax25_rt;
} }
} }
read_unlock(&ax25_route_lock);
if (ax25_spe_rt != NULL) if (ax25_spe_rt != NULL)
return ax25_spe_rt; return ax25_spe_rt;
...@@ -448,6 +454,7 @@ void __exit ax25_rt_free(void) ...@@ -448,6 +454,7 @@ void __exit ax25_rt_free(void)
{ {
ax25_route *s, *ax25_rt = ax25_route_list; ax25_route *s, *ax25_rt = ax25_route_list;
write_unlock(&ax25_route_lock);
while (ax25_rt != NULL) { while (ax25_rt != NULL) {
s = ax25_rt; s = ax25_rt;
ax25_rt = ax25_rt->next; ax25_rt = ax25_rt->next;
...@@ -457,4 +464,5 @@ void __exit ax25_rt_free(void) ...@@ -457,4 +464,5 @@ void __exit ax25_rt_free(void)
kfree(s); kfree(s);
} }
write_unlock(&ax25_route_lock);
} }
This diff is collapsed.
...@@ -47,30 +47,29 @@ ...@@ -47,30 +47,29 @@
void ax25_std_heartbeat_expiry(ax25_cb *ax25) void ax25_std_heartbeat_expiry(ax25_cb *ax25)
{ {
switch (ax25->state) { switch (ax25->state) {
case AX25_STATE_0:
case AX25_STATE_0: /* Magic here: If we listen() and a new link dies before it
/* Magic here: If we listen() and a new link dies before it is accepted() it isn't 'dead' so doesn't get removed. */
is accepted() it isn't 'dead' so doesn't get removed. */ if (ax25->sk == NULL || ax25->sk->destroy || (ax25->sk->state == TCP_LISTEN && ax25->sk->dead)) {
if (ax25->sk == NULL || ax25->sk->destroy || (ax25->sk->state == TCP_LISTEN && ax25->sk->dead)) { ax25_destroy_socket(ax25);
ax25_destroy_socket(ax25); return;
return; }
} break;
break;
case AX25_STATE_3:
case AX25_STATE_3: case AX25_STATE_4:
case AX25_STATE_4: /*
/* * Check the state of the receive buffer.
* Check the state of the receive buffer. */
*/ if (ax25->sk != NULL) {
if (ax25->sk != NULL) { if (atomic_read(&ax25->sk->rmem_alloc) < (ax25->sk->rcvbuf / 2) &&
if (atomic_read(&ax25->sk->rmem_alloc) < (ax25->sk->rcvbuf / 2) && (ax25->condition & AX25_COND_OWN_RX_BUSY)) {
(ax25->condition & AX25_COND_OWN_RX_BUSY)) { ax25->condition &= ~AX25_COND_OWN_RX_BUSY;
ax25->condition &= ~AX25_COND_OWN_RX_BUSY; ax25->condition &= ~AX25_COND_ACK_PENDING;
ax25->condition &= ~AX25_COND_ACK_PENDING; ax25_send_control(ax25, AX25_RR, AX25_POLLOFF, AX25_RESPONSE);
ax25_send_control(ax25, AX25_RR, AX25_POLLOFF, AX25_RESPONSE); break;
break;
}
} }
}
} }
ax25_start_heartbeat(ax25); ax25_start_heartbeat(ax25);
...@@ -117,53 +116,53 @@ void ax25_std_idletimer_expiry(ax25_cb *ax25) ...@@ -117,53 +116,53 @@ void ax25_std_idletimer_expiry(ax25_cb *ax25)
void ax25_std_t1timer_expiry(ax25_cb *ax25) void ax25_std_t1timer_expiry(ax25_cb *ax25)
{ {
switch (ax25->state) { switch (ax25->state) {
case AX25_STATE_1: case AX25_STATE_1:
if (ax25->n2count == ax25->n2) { if (ax25->n2count == ax25->n2) {
if (ax25->modulus == AX25_MODULUS) { if (ax25->modulus == AX25_MODULUS) {
ax25_disconnect(ax25, ETIMEDOUT);
return;
} else {
ax25->modulus = AX25_MODULUS;
ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW];
ax25->n2count = 0;
ax25_send_control(ax25, AX25_SABM, AX25_POLLON, AX25_COMMAND);
}
} else {
ax25->n2count++;
if (ax25->modulus == AX25_MODULUS)
ax25_send_control(ax25, AX25_SABM, AX25_POLLON, AX25_COMMAND);
else
ax25_send_control(ax25, AX25_SABME, AX25_POLLON, AX25_COMMAND);
}
break;
case AX25_STATE_2:
if (ax25->n2count == ax25->n2) {
ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
ax25_disconnect(ax25, ETIMEDOUT); ax25_disconnect(ax25, ETIMEDOUT);
return; return;
} else { } else {
ax25->n2count++; ax25->modulus = AX25_MODULUS;
ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND); ax25->window = ax25->ax25_dev->values[AX25_VALUES_WINDOW];
ax25->n2count = 0;
ax25_send_control(ax25, AX25_SABM, AX25_POLLON, AX25_COMMAND);
} }
break; } else {
ax25->n2count++;
case AX25_STATE_3: if (ax25->modulus == AX25_MODULUS)
ax25->n2count = 1; ax25_send_control(ax25, AX25_SABM, AX25_POLLON, AX25_COMMAND);
else
ax25_send_control(ax25, AX25_SABME, AX25_POLLON, AX25_COMMAND);
}
break;
case AX25_STATE_2:
if (ax25->n2count == ax25->n2) {
ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
ax25_disconnect(ax25, ETIMEDOUT);
return;
} else {
ax25->n2count++;
ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
}
break;
case AX25_STATE_3:
ax25->n2count = 1;
ax25_std_transmit_enquiry(ax25);
ax25->state = AX25_STATE_4;
break;
case AX25_STATE_4:
if (ax25->n2count == ax25->n2) {
ax25_send_control(ax25, AX25_DM, AX25_POLLON, AX25_RESPONSE);
ax25_disconnect(ax25, ETIMEDOUT);
return;
} else {
ax25->n2count++;
ax25_std_transmit_enquiry(ax25); ax25_std_transmit_enquiry(ax25);
ax25->state = AX25_STATE_4; }
break; break;
case AX25_STATE_4:
if (ax25->n2count == ax25->n2) {
ax25_send_control(ax25, AX25_DM, AX25_POLLON, AX25_RESPONSE);
ax25_disconnect(ax25, ETIMEDOUT);
return;
} else {
ax25->n2count++;
ax25_std_transmit_enquiry(ax25);
}
break;
} }
ax25_calculate_t1(ax25); ax25_calculate_t1(ax25);
......
...@@ -257,18 +257,18 @@ void ax25_calculate_t1(ax25_cb *ax25) ...@@ -257,18 +257,18 @@ void ax25_calculate_t1(ax25_cb *ax25)
int n, t = 2; int n, t = 2;
switch (ax25->backoff) { switch (ax25->backoff) {
case 0: case 0:
break; break;
case 1: case 1:
t += 2 * ax25->n2count; t += 2 * ax25->n2count;
break; break;
case 2: case 2:
for (n = 0; n < ax25->n2count; n++) for (n = 0; n < ax25->n2count; n++)
t *= 2; t *= 2;
if (t > 8) t = 8; if (t > 8) t = 8;
break; break;
} }
ax25->t1 = t * ax25->rtt; ax25->t1 = t * ax25->rtt;
......
...@@ -159,18 +159,18 @@ static void ax25_heartbeat_expiry(unsigned long param) ...@@ -159,18 +159,18 @@ static void ax25_heartbeat_expiry(unsigned long param)
proto = ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]; proto = ax25->ax25_dev->values[AX25_VALUES_PROTOCOL];
switch (proto) { switch (proto) {
case AX25_PROTO_STD_SIMPLEX: case AX25_PROTO_STD_SIMPLEX:
case AX25_PROTO_STD_DUPLEX: case AX25_PROTO_STD_DUPLEX:
ax25_std_heartbeat_expiry(ax25); ax25_std_heartbeat_expiry(ax25);
break; break;
#ifdef CONFIG_AX25_DAMA_SLAVE #ifdef CONFIG_AX25_DAMA_SLAVE
case AX25_PROTO_DAMA_SLAVE: case AX25_PROTO_DAMA_SLAVE:
if (ax25->ax25_dev->dama.slave) if (ax25->ax25_dev->dama.slave)
ax25_ds_heartbeat_expiry(ax25); ax25_ds_heartbeat_expiry(ax25);
else else
ax25_std_heartbeat_expiry(ax25); ax25_std_heartbeat_expiry(ax25);
break; break;
#endif #endif
} }
} }
...@@ -180,16 +180,16 @@ static void ax25_t1timer_expiry(unsigned long param) ...@@ -180,16 +180,16 @@ static void ax25_t1timer_expiry(unsigned long param)
ax25_cb *ax25 = (ax25_cb *)param; ax25_cb *ax25 = (ax25_cb *)param;
switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) { switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
case AX25_PROTO_STD_SIMPLEX: case AX25_PROTO_STD_SIMPLEX:
case AX25_PROTO_STD_DUPLEX: case AX25_PROTO_STD_DUPLEX:
ax25_std_t1timer_expiry(ax25); ax25_std_t1timer_expiry(ax25);
break; break;
#ifdef CONFIG_AX25_DAMA_SLAVE #ifdef CONFIG_AX25_DAMA_SLAVE
case AX25_PROTO_DAMA_SLAVE: case AX25_PROTO_DAMA_SLAVE:
if (!ax25->ax25_dev->dama.slave) if (!ax25->ax25_dev->dama.slave)
ax25_std_t1timer_expiry(ax25); ax25_std_t1timer_expiry(ax25);
break; break;
#endif #endif
} }
} }
...@@ -199,16 +199,16 @@ static void ax25_t2timer_expiry(unsigned long param) ...@@ -199,16 +199,16 @@ static void ax25_t2timer_expiry(unsigned long param)
ax25_cb *ax25 = (ax25_cb *)param; ax25_cb *ax25 = (ax25_cb *)param;
switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) { switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
case AX25_PROTO_STD_SIMPLEX: case AX25_PROTO_STD_SIMPLEX:
case AX25_PROTO_STD_DUPLEX: case AX25_PROTO_STD_DUPLEX:
ax25_std_t2timer_expiry(ax25); ax25_std_t2timer_expiry(ax25);
break; break;
#ifdef CONFIG_AX25_DAMA_SLAVE #ifdef CONFIG_AX25_DAMA_SLAVE
case AX25_PROTO_DAMA_SLAVE: case AX25_PROTO_DAMA_SLAVE:
if (!ax25->ax25_dev->dama.slave) if (!ax25->ax25_dev->dama.slave)
ax25_std_t2timer_expiry(ax25); ax25_std_t2timer_expiry(ax25);
break; break;
#endif #endif
} }
} }
...@@ -218,18 +218,18 @@ static void ax25_t3timer_expiry(unsigned long param) ...@@ -218,18 +218,18 @@ static void ax25_t3timer_expiry(unsigned long param)
ax25_cb *ax25 = (ax25_cb *)param; ax25_cb *ax25 = (ax25_cb *)param;
switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) { switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
case AX25_PROTO_STD_SIMPLEX: case AX25_PROTO_STD_SIMPLEX:
case AX25_PROTO_STD_DUPLEX: case AX25_PROTO_STD_DUPLEX:
ax25_std_t3timer_expiry(ax25); ax25_std_t3timer_expiry(ax25);
break; break;
#ifdef CONFIG_AX25_DAMA_SLAVE #ifdef CONFIG_AX25_DAMA_SLAVE
case AX25_PROTO_DAMA_SLAVE: case AX25_PROTO_DAMA_SLAVE:
if (ax25->ax25_dev->dama.slave) if (ax25->ax25_dev->dama.slave)
ax25_ds_t3timer_expiry(ax25); ax25_ds_t3timer_expiry(ax25);
else else
ax25_std_t3timer_expiry(ax25); ax25_std_t3timer_expiry(ax25);
break; break;
#endif #endif
} }
} }
...@@ -239,18 +239,18 @@ static void ax25_idletimer_expiry(unsigned long param) ...@@ -239,18 +239,18 @@ static void ax25_idletimer_expiry(unsigned long param)
ax25_cb *ax25 = (ax25_cb *)param; ax25_cb *ax25 = (ax25_cb *)param;
switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) { switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
case AX25_PROTO_STD_SIMPLEX: case AX25_PROTO_STD_SIMPLEX:
case AX25_PROTO_STD_DUPLEX: case AX25_PROTO_STD_DUPLEX:
ax25_std_idletimer_expiry(ax25); ax25_std_idletimer_expiry(ax25);
break; break;
#ifdef CONFIG_AX25_DAMA_SLAVE #ifdef CONFIG_AX25_DAMA_SLAVE
case AX25_PROTO_DAMA_SLAVE: case AX25_PROTO_DAMA_SLAVE:
if (ax25->ax25_dev->dama.slave) if (ax25->ax25_dev->dama.slave)
ax25_ds_idletimer_expiry(ax25); ax25_ds_idletimer_expiry(ax25);
else else
ax25_std_idletimer_expiry(ax25); ax25_std_idletimer_expiry(ax25);
break; break;
#endif #endif
} }
} }
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
*/ */
static ax25_uid_assoc *ax25_uid_list; static ax25_uid_assoc *ax25_uid_list;
static spinlock_t ax25_uid_lock = SPIN_LOCK_UNLOCKED; static rwlock_t ax25_uid_lock = RW_LOCK_UNLOCKED;
int ax25_uid_policy = 0; int ax25_uid_policy = 0;
...@@ -56,16 +56,15 @@ ax25_address *ax25_findbyuid(uid_t uid) ...@@ -56,16 +56,15 @@ ax25_address *ax25_findbyuid(uid_t uid)
{ {
ax25_uid_assoc *ax25_uid; ax25_uid_assoc *ax25_uid;
ax25_address *res = NULL; ax25_address *res = NULL;
unsigned long flags;
spin_lock_irqsave(&ax25_uid_lock, flags); read_lock(&ax25_uid_lock);
for (ax25_uid = ax25_uid_list; ax25_uid != NULL; ax25_uid = ax25_uid->next) { for (ax25_uid = ax25_uid_list; ax25_uid != NULL; ax25_uid = ax25_uid->next) {
if (ax25_uid->uid == uid) { if (ax25_uid->uid == uid) {
res = &ax25_uid->call; res = &ax25_uid->call;
break; break;
} }
} }
spin_lock_irqsave(&ax25_uid_lock, flags); read_unlock(&ax25_uid_lock);
return NULL; return NULL;
} }
...@@ -73,78 +72,77 @@ ax25_address *ax25_findbyuid(uid_t uid) ...@@ -73,78 +72,77 @@ ax25_address *ax25_findbyuid(uid_t uid)
int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax) int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
{ {
ax25_uid_assoc *s, *ax25_uid; ax25_uid_assoc *s, *ax25_uid;
unsigned long flags;
unsigned long res; unsigned long res;
switch (cmd) { switch (cmd) {
case SIOCAX25GETUID: case SIOCAX25GETUID:
res = -ENOENT; res = -ENOENT;
spin_lock_irqsave(&ax25_uid_lock, flags); read_lock(&ax25_uid_lock);
for (ax25_uid = ax25_uid_list; ax25_uid != NULL; ax25_uid = ax25_uid->next) { 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) {
res = ax25_uid->uid; res = ax25_uid->uid;
break; break;
}
} }
spin_lock_irqsave(&ax25_uid_lock, flags); }
read_unlock(&ax25_uid_lock);
return res; return res;
case SIOCAX25ADDUID: case SIOCAX25ADDUID:
if (!capable(CAP_NET_ADMIN)) if (!capable(CAP_NET_ADMIN))
return -EPERM; return -EPERM;
if (ax25_findbyuid(sax->sax25_uid)) if (ax25_findbyuid(sax->sax25_uid))
return -EEXIST; return -EEXIST;
if (sax->sax25_uid == 0) if (sax->sax25_uid == 0)
return -EINVAL; return -EINVAL;
if ((ax25_uid = kmalloc(sizeof(*ax25_uid), GFP_KERNEL)) == NULL) if ((ax25_uid = kmalloc(sizeof(*ax25_uid), GFP_KERNEL)) == NULL)
return -ENOMEM; return -ENOMEM;
ax25_uid->uid = sax->sax25_uid; ax25_uid->uid = sax->sax25_uid;
ax25_uid->call = sax->sax25_call; ax25_uid->call = sax->sax25_call;
spin_lock_irqsave(&ax25_uid_lock, flags); write_lock(&ax25_uid_lock);
ax25_uid->next = ax25_uid_list; ax25_uid->next = ax25_uid_list;
ax25_uid_list = ax25_uid; ax25_uid_list = ax25_uid;
spin_unlock_irqrestore(&ax25_uid_lock, flags); write_unlock(&ax25_uid_lock);
return 0; return 0;
case SIOCAX25DELUID: case SIOCAX25DELUID:
if (!capable(CAP_NET_ADMIN)) if (!capable(CAP_NET_ADMIN))
return -EPERM; return -EPERM;
spin_lock_irqsave(&ax25_uid_lock, flags); write_lock(&ax25_uid_lock);
for (ax25_uid = ax25_uid_list; ax25_uid != NULL; ax25_uid = ax25_uid->next) { 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; break;
}
}
if (ax25_uid == NULL) {
spin_unlock_irqrestore(&ax25_uid_lock, flags);
return -ENOENT;
} }
if ((s = ax25_uid_list) == ax25_uid) { }
ax25_uid_list = s->next; if (ax25_uid == NULL) {
spin_unlock_irqrestore(&ax25_uid_lock, flags); write_unlock(&ax25_uid_lock);
return -ENOENT;
}
if ((s = ax25_uid_list) == ax25_uid) {
ax25_uid_list = s->next;
write_unlock(&ax25_uid_lock);
kfree(ax25_uid);
return 0;
}
while (s != NULL && s->next != NULL) {
if (s->next == ax25_uid) {
s->next = ax25_uid->next;
write_unlock(&ax25_uid_lock);
kfree(ax25_uid); kfree(ax25_uid);
return 0; return 0;
} }
while (s != NULL && s->next != NULL) { s = s->next;
if (s->next == ax25_uid) { }
s->next = ax25_uid->next; write_unlock(&ax25_uid_lock);
spin_unlock_irqrestore(&ax25_uid_lock, flags);
kfree(ax25_uid);
return 0;
}
s = s->next;
}
spin_unlock_irqrestore(&ax25_uid_lock, flags);
return -ENOENT; return -ENOENT;
default: default:
return -EINVAL; return -EINVAL;
} }
return -EINVAL; /*NOTREACHED */ return -EINVAL; /*NOTREACHED */
...@@ -152,13 +150,12 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax) ...@@ -152,13 +150,12 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
int ax25_uid_get_info(char *buffer, char **start, off_t offset, int length) int ax25_uid_get_info(char *buffer, char **start, off_t offset, int length)
{ {
unsigned long flags;
ax25_uid_assoc *pt; ax25_uid_assoc *pt;
int len = 0; int len = 0;
off_t pos = 0; off_t pos = 0;
off_t begin = 0; off_t begin = 0;
spin_lock_irqsave(&ax25_uid_lock, flags); read_lock(&ax25_uid_lock);
len += sprintf(buffer, "Policy: %d\n", ax25_uid_policy); len += sprintf(buffer, "Policy: %d\n", ax25_uid_policy);
for (pt = ax25_uid_list; pt != NULL; pt = pt->next) { for (pt = ax25_uid_list; pt != NULL; pt = pt->next) {
...@@ -174,7 +171,7 @@ int ax25_uid_get_info(char *buffer, char **start, off_t offset, int length) ...@@ -174,7 +171,7 @@ int ax25_uid_get_info(char *buffer, char **start, off_t offset, int length)
if (pos > offset + length) if (pos > offset + length)
break; break;
} }
spin_unlock_irqrestore(&ax25_uid_lock, flags); read_unlock(&ax25_uid_lock);
*start = buffer + (offset - begin); *start = buffer + (offset - begin);
len -= offset - begin; len -= offset - begin;
...@@ -191,9 +188,8 @@ int ax25_uid_get_info(char *buffer, char **start, off_t offset, int length) ...@@ -191,9 +188,8 @@ int ax25_uid_get_info(char *buffer, char **start, off_t offset, int length)
void __exit ax25_uid_free(void) void __exit ax25_uid_free(void)
{ {
ax25_uid_assoc *s, *ax25_uid; ax25_uid_assoc *s, *ax25_uid;
unsigned long flags;
spin_lock_irqsave(&ax25_uid_lock, flags); write_lock(&ax25_uid_lock);
ax25_uid = ax25_uid_list; ax25_uid = ax25_uid_list;
while (ax25_uid != NULL) { while (ax25_uid != NULL) {
s = ax25_uid; s = ax25_uid;
...@@ -202,5 +198,5 @@ void __exit ax25_uid_free(void) ...@@ -202,5 +198,5 @@ void __exit ax25_uid_free(void)
kfree(s); kfree(s);
} }
ax25_uid_list = NULL; ax25_uid_list = NULL;
spin_unlock_irqrestore(&ax25_uid_lock, flags); write_unlock(&ax25_uid_lock);
} }
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