Commit 349f5838 authored by Jean Tourrilhes's avatar Jean Tourrilhes Committed by Linus Torvalds

[irda] connect watchdog fixes

	o [CRITICA] In case of connect watchdog, drop reference to the LAP
	o [CORRECT] Prevent dumping LSAP after connect watchdog
	o [CRITICA] Prevent dumping TSAP if dumping LSAP did fail
	o [CORRECT] Only set connected bit on response if LSAP state is correct
parent 67eb5250
...@@ -540,7 +540,8 @@ int irlmp_connect_response(struct lsap_cb *self, struct sk_buff *userdata) ...@@ -540,7 +540,8 @@ int irlmp_connect_response(struct lsap_cb *self, struct sk_buff *userdata)
ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;); ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
ASSERT(userdata != NULL, return -1;); ASSERT(userdata != NULL, return -1;);
set_bit(0, &self->connected); /* TRUE */ /* We set the connected bit and move the lsap to the connected list
* in the state machine itself. Jean II */
IRDA_DEBUG(2, "%s(), slsap_sel=%02x, dlsap_sel=%02x\n", IRDA_DEBUG(2, "%s(), slsap_sel=%02x, dlsap_sel=%02x\n",
__FUNCTION__, self->slsap_sel, self->dlsap_sel); __FUNCTION__, self->slsap_sel, self->dlsap_sel);
...@@ -612,13 +613,17 @@ struct lsap_cb *irlmp_dup(struct lsap_cb *orig, void *instance) ...@@ -612,13 +613,17 @@ struct lsap_cb *irlmp_dup(struct lsap_cb *orig, void *instance)
spin_lock_irqsave(&irlmp->unconnected_lsaps->hb_spinlock, flags); spin_lock_irqsave(&irlmp->unconnected_lsaps->hb_spinlock, flags);
/* Only allowed to duplicate unconnected LSAP's */ /* Only allowed to duplicate unconnected LSAP's, and only LSAPs
if (!hashbin_find(irlmp->unconnected_lsaps, (long) orig, NULL)) { * that have received a connect indication. Jean II */
IRDA_DEBUG(0, "%s(), unable to find LSAP\n", __FUNCTION__); if ((!hashbin_find(irlmp->unconnected_lsaps, (long) orig, NULL)) ||
(orig->lap == NULL)) {
IRDA_DEBUG(0, "%s(), invalid LSAP (wrong state)\n",
__FUNCTION__);
spin_unlock_irqrestore(&irlmp->unconnected_lsaps->hb_spinlock, spin_unlock_irqrestore(&irlmp->unconnected_lsaps->hb_spinlock,
flags); flags);
return NULL; return NULL;
} }
/* Allocate a new instance */ /* Allocate a new instance */
new = kmalloc(sizeof(struct lsap_cb), GFP_ATOMIC); new = kmalloc(sizeof(struct lsap_cb), GFP_ATOMIC);
if (!new) { if (!new) {
...@@ -643,8 +648,8 @@ struct lsap_cb *irlmp_dup(struct lsap_cb *orig, void *instance) ...@@ -643,8 +648,8 @@ struct lsap_cb *irlmp_dup(struct lsap_cb *orig, void *instance)
hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) new, hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) new,
(long) new, NULL); (long) new, NULL);
/* Make sure that we invalidate the cache */
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP #ifdef CONFIG_IRDA_CACHE_LAST_LSAP
/* Make sure that we invalidate the LSAP cache */
new->lap->cache.valid = FALSE; new->lap->cache.valid = FALSE;
#endif /* CONFIG_IRDA_CACHE_LAST_LSAP */ #endif /* CONFIG_IRDA_CACHE_LAST_LSAP */
......
...@@ -586,6 +586,8 @@ static int irlmp_state_connect(struct lsap_cb *self, IRLMP_EVENT event, ...@@ -586,6 +586,8 @@ static int irlmp_state_connect(struct lsap_cb *self, IRLMP_EVENT event,
hashbin_insert(self->lap->lsaps, (irda_queue_t *) self, hashbin_insert(self->lap->lsaps, (irda_queue_t *) self,
(long) self, NULL); (long) self, NULL);
set_bit(0, &self->connected); /* TRUE */
irlmp_send_lcf_pdu(self->lap, self->dlsap_sel, irlmp_send_lcf_pdu(self->lap, self->dlsap_sel,
self->slsap_sel, CONNECT_CNF, skb); self->slsap_sel, CONNECT_CNF, skb);
...@@ -599,10 +601,13 @@ static int irlmp_state_connect(struct lsap_cb *self, IRLMP_EVENT event, ...@@ -599,10 +601,13 @@ static int irlmp_state_connect(struct lsap_cb *self, IRLMP_EVENT event,
IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n", __FUNCTION__); IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n", __FUNCTION__);
/* Disconnect, get out... - Jean II */ /* Disconnect, get out... - Jean II */
self->lap = NULL;
self->dlsap_sel = LSAP_ANY; self->dlsap_sel = LSAP_ANY;
irlmp_next_lsap_state(self, LSAP_DISCONNECTED); irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
break; break;
default: default:
/* LM_LAP_DISCONNECT_INDICATION : Should never happen, we
* are *not* yet bound to the IrLAP link. Jean II */
IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n", IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
__FUNCTION__, irlmp_event[event], self->slsap_sel); __FUNCTION__, irlmp_event[event], self->slsap_sel);
break; break;
...@@ -659,6 +664,7 @@ static int irlmp_state_connect_pend(struct lsap_cb *self, IRLMP_EVENT event, ...@@ -659,6 +664,7 @@ static int irlmp_state_connect_pend(struct lsap_cb *self, IRLMP_EVENT event,
IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n", __FUNCTION__); IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n", __FUNCTION__);
/* Go back to disconnected mode, keep the socket waiting */ /* Go back to disconnected mode, keep the socket waiting */
self->lap = NULL;
self->dlsap_sel = LSAP_ANY; self->dlsap_sel = LSAP_ANY;
if(self->conn_skb) if(self->conn_skb)
dev_kfree_skb(self->conn_skb); dev_kfree_skb(self->conn_skb);
...@@ -666,6 +672,8 @@ static int irlmp_state_connect_pend(struct lsap_cb *self, IRLMP_EVENT event, ...@@ -666,6 +672,8 @@ static int irlmp_state_connect_pend(struct lsap_cb *self, IRLMP_EVENT event,
irlmp_next_lsap_state(self, LSAP_DISCONNECTED); irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
break; break;
default: default:
/* LM_LAP_DISCONNECT_INDICATION : Should never happen, we
* are *not* yet bound to the IrLAP link. Jean II */
IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n", IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
__FUNCTION__, irlmp_event[event], self->slsap_sel); __FUNCTION__, irlmp_event[event], self->slsap_sel);
break; break;
...@@ -721,6 +729,8 @@ static int irlmp_state_dtr(struct lsap_cb *self, IRLMP_EVENT event, ...@@ -721,6 +729,8 @@ static int irlmp_state_dtr(struct lsap_cb *self, IRLMP_EVENT event,
irlmp_send_lcf_pdu(self->lap, self->dlsap_sel, self->slsap_sel, irlmp_send_lcf_pdu(self->lap, self->dlsap_sel, self->slsap_sel,
DISCONNECT, skb); DISCONNECT, skb);
irlmp_next_lsap_state(self, LSAP_DISCONNECTED); irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
/* Called only from irlmp_disconnect_request(), will
* unbind from LAP over there. Jean II */
/* Try to close the LAP connection if its still there */ /* Try to close the LAP connection if its still there */
if (self->lap) { if (self->lap) {
......
...@@ -1428,9 +1428,16 @@ struct tsap_cb *irttp_dup(struct tsap_cb *orig, void *instance) ...@@ -1428,9 +1428,16 @@ struct tsap_cb *irttp_dup(struct tsap_cb *orig, void *instance)
/* We don't need the old instance any more */ /* We don't need the old instance any more */
spin_unlock_irqrestore(&irttp->tsaps->hb_spinlock, flags); spin_unlock_irqrestore(&irttp->tsaps->hb_spinlock, flags);
/* Try to dup the LSAP (may fail if we were too slow) */
new->lsap = irlmp_dup(orig->lsap, new);
if (!new->lsap) {
IRDA_DEBUG(0, "%s(), dup failed!\n", __FUNCTION__);
kfree(new);
return NULL;
}
/* Not everything should be copied */ /* Not everything should be copied */
new->notify.instance = instance; new->notify.instance = instance;
new->lsap = irlmp_dup(orig->lsap, new);
init_timer(&new->todo_timer); init_timer(&new->todo_timer);
skb_queue_head_init(&new->rx_queue); skb_queue_head_init(&new->rx_queue);
......
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