struct sock *ax25_find_listener(ax25_address *, int, struct net_device *, int);
struct sock *ax25_get_socket(ax25_address *, ax25_address *, int);
extern ax25_cb *ax25_find_cb(ax25_address *, ax25_address *, ax25_digi *, struct net_device *);
-extern struct sock *ax25_addr_match(ax25_address *);
-extern void ax25_send_to_raw(struct sock *, struct sk_buff *, int);
+extern void ax25_send_to_raw(ax25_address *, struct sk_buff *, int);
extern void ax25_destroy_socket(ax25_cb *);
extern ax25_cb *ax25_create_cb(void);
extern void ax25_fillin_cb(ax25_cb *, ax25_dev *);
return NULL;
}
-/*
- * Look for any matching address - RAW sockets can bind to arbitrary names
- */
-struct sock *ax25_addr_match(ax25_address *addr)
+void ax25_send_to_raw(ax25_address *addr, struct sk_buff *skb, int proto)
{
- struct sock *sk = NULL;
ax25_cb *s;
+ struct sk_buff *copy;
struct hlist_node *node;
spin_lock_bh(&ax25_list_lock);
ax25_for_each(s, node, &ax25_list) {
if (s->sk != NULL && ax25cmp(&s->source_addr, addr) == 0 &&
- s->sk->sk_type == SOCK_RAW) {
- sk = s->sk;
- lock_sock(sk);
- break;
- }
- }
-
- spin_unlock_bh(&ax25_list_lock);
-
- return sk;
-}
-
-void ax25_send_to_raw(struct sock *sk, struct sk_buff *skb, int proto)
-{
- struct sk_buff *copy;
- struct hlist_node *node;
-
- sk_for_each_from(sk, node)
- if (sk->sk_type == SOCK_RAW &&
- sk->sk_protocol == proto &&
- atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf) {
+ s->sk->sk_type == SOCK_RAW &&
+ s->sk->sk_protocol == proto &&
+ s->ax25_dev->dev == skb->dev &&
+ atomic_read(&s->sk->sk_rmem_alloc) <= s->sk->sk_rcvbuf) {
if ((copy = skb_clone(skb, GFP_ATOMIC)) == NULL)
- return;
-
- if (sock_queue_rcv_skb(sk, copy) != 0)
+ continue;
+ if (sock_queue_rcv_skb(s->sk, copy) != 0)
kfree_skb(copy);
}
+ }
}
/*
ax25_cb *sax25 = ax25_sk(skb->sk);
/* Queue the unaccepted socket for death */
- sock_set_flag(skb->sk, SOCK_DEAD);
+ sock_orphan(skb->sk);
ax25_start_heartbeat(sax25);
sax25->state = AX25_STATE_0;
if (oax25->digipeat != NULL) {
if ((ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
sk_free(sk);
+ ax25_cb_put(ax25);
return NULL;
}
return 0;
sock_hold(sk);
+ sock_orphan(sk);
lock_sock(sk);
ax25 = ax25_sk(sk);
if (sk->sk_type == SOCK_SEQPACKET) {
switch (ax25->state) {
case AX25_STATE_0:
+ release_sock(sk);
ax25_disconnect(ax25, 0);
+ lock_sock(sk);
ax25_destroy_socket(ax25);
break;
case AX25_STATE_1:
case AX25_STATE_2:
ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
+ release_sock(sk);
ax25_disconnect(ax25, 0);
+ lock_sock(sk);
ax25_destroy_socket(ax25);
break;
sk->sk_state = TCP_CLOSE;
sk->sk_shutdown |= SEND_SHUTDOWN;
sk->sk_state_change(sk);
- sock_set_flag(sk, SOCK_DEAD);
sock_set_flag(sk, SOCK_DESTROY);
break;
sk->sk_state = TCP_CLOSE;
sk->sk_shutdown |= SEND_SHUTDOWN;
sk->sk_state_change(sk);
- sock_set_flag(sk, SOCK_DEAD);
ax25_destroy_socket(ax25);
}
sock->sk = NULL;
- sk->sk_socket = NULL; /* Not used, but we should do this */
release_sock(sk);
sock_put(sk);
release_sock(sk);
current->state = TASK_INTERRUPTIBLE;
- if (flags & O_NONBLOCK)
+ if (flags & O_NONBLOCK) {
+ current->state = TASK_RUNNING;
+ remove_wait_queue(sk->sk_sleep, &wait);
return -EWOULDBLOCK;
+ }
if (!signal_pending(tsk)) {
schedule();
- current->state = TASK_RUNNING;
lock_sock(sk);
continue;
}
}
if (ax25->sk != NULL && ax25->ax25_dev->values[AX25_VALUES_CONMODE] == 2) {
- bh_lock_sock(ax25->sk);
if ((!ax25->pidincl && ax25->sk->sk_protocol == pid) ||
ax25->pidincl) {
if (sock_queue_rcv_skb(ax25->sk, skb) == 0)
else
ax25->condition |= AX25_COND_OWN_RX_BUSY;
}
- bh_unlock_sock(ax25->sk);
}
return queued;
{
ax25_address src, dest, *next_digi = NULL;
int type = 0, mine = 0, dama;
- struct sock *make, *sk, *raw;
+ struct sock *make, *sk;
ax25_digi dp, reverse_dp;
ax25_cb *ax25;
ax25_dev *ax25_dev;
if ((*skb->data & ~0x10) == AX25_UI && dp.lastrepeat + 1 == dp.ndigi) {
skb->h.raw = skb->data + 2; /* skip control and pid */
- if ((raw = ax25_addr_match(&dest)) != NULL) {
- ax25_send_to_raw(raw, skb, skb->data[1]);
- release_sock(raw);
- }
+ ax25_send_to_raw(&dest, skb, skb->data[1]);
if (!mine && ax25cmp(&dest, (ax25_address *)dev->broadcast) != 0) {
kfree_skb(skb);
sk->sk_ack_backlog++;
bh_unlock_sock(sk);
- sock_put(sk);
} else {
if (!mine) {
kfree_skb(skb);
(ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
kfree_skb(skb);
ax25_destroy_socket(ax25);
+ if (sk)
+ sock_put(sk);
return 0;
}
if (sk) {
if (!sock_flag(sk, SOCK_DEAD))
sk->sk_data_ready(sk, skb->len);
+ sock_put(sk);
} else
kfree_skb(skb);
sk->sk_state = TCP_CLOSE;
sk->sk_shutdown |= SEND_SHUTDOWN;
sk->sk_state_change(sk);
- sock_set_flag(sk, SOCK_DEAD);
+ sock_orphan(sk);
sock_set_flag(sk, SOCK_DESTROY);
sk->sk_socket = NULL;
break;
lock_sock(sk);
continue;
}
+ current->state = TASK_RUNNING;
+ remove_wait_queue(sk->sk_sleep, &wait);
return -ERESTARTSYS;
}
current->state = TASK_RUNNING;
current->state = TASK_INTERRUPTIBLE;
release_sock(sk);
- if (flags & O_NONBLOCK)
+ if (flags & O_NONBLOCK) {
+ current->state = TASK_RUNNING;
+ remove_wait_queue(sk->sk_sleep, &wait);
return -EWOULDBLOCK;
+ }
if (!signal_pending(tsk)) {
schedule();
lock_sock(sk);
continue;
}
+ current->state = TASK_RUNNING;
+ remove_wait_queue(sk->sk_sleep, &wait);
return -ERESTARTSYS;
}
current->state = TASK_RUNNING;
schedule();
continue;
}
+ current->state = TASK_RUNNING;
+ remove_wait_queue(sk->sk_sleep, &wait);
return -ERESTARTSYS;
}
current->state = TASK_RUNNING;
current->state = TASK_INTERRUPTIBLE;
release_sock(sk);
- if (flags & O_NONBLOCK)
+ if (flags & O_NONBLOCK) {
+ current->state = TASK_RUNNING;
+ remove_wait_queue(sk->sk_sleep, &wait);
return -EWOULDBLOCK;
+ }
if (!signal_pending(tsk)) {
schedule();
lock_sock(sk);