]> git.hungrycats.org Git - linux/commitdiff
[irda] connect watchdog fixes
authorJean Tourrilhes <jt@bougret.hpl.hp.com>
Fri, 5 Sep 2003 17:08:56 +0000 (13:08 -0400)
committerLinus Torvalds <torvalds@home.osdl.org>
Fri, 5 Sep 2003 17:08:56 +0000 (13:08 -0400)
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

net/irda/irlmp.c
net/irda/irlmp_event.c
net/irda/irttp.c

index f5866514a1cb318c4c418ea957d9f20ce8411c2f..d193ddacf0ed6a9ce0776b2cd26e579fe39c6f96 100644 (file)
@@ -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(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",
                   __FUNCTION__, self->slsap_sel, self->dlsap_sel);
@@ -612,13 +613,17 @@ struct lsap_cb *irlmp_dup(struct lsap_cb *orig, void *instance)
 
        spin_lock_irqsave(&irlmp->unconnected_lsaps->hb_spinlock, flags);
 
-       /* Only allowed to duplicate unconnected LSAP's */
-       if (!hashbin_find(irlmp->unconnected_lsaps, (long) orig, NULL)) {
-               IRDA_DEBUG(0, "%s(), unable to find LSAP\n", __FUNCTION__);
+       /* Only allowed to duplicate unconnected LSAP's, and only LSAPs
+        * that have received a connect indication. Jean II */
+       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,
                                       flags);
                return NULL;
        }
+
        /* Allocate a new instance */
        new = kmalloc(sizeof(struct lsap_cb), GFP_ATOMIC);
        if (!new)  {
@@ -643,8 +648,8 @@ struct lsap_cb *irlmp_dup(struct lsap_cb *orig, void *instance)
        hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) new,
                       (long) new, NULL);
 
-       /* Make sure that we invalidate the cache */
 #ifdef CONFIG_IRDA_CACHE_LAST_LSAP
+       /* Make sure that we invalidate the LSAP cache */
        new->lap->cache.valid = FALSE;
 #endif /* CONFIG_IRDA_CACHE_LAST_LSAP */
 
index 71585ba8cdbfc4af23e539b41c59d4714260b2c4..7ef8fd5ddf04c21a3d670b90cfbea5ea8629f805 100644 (file)
@@ -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,
                               (long) self, NULL);
 
+               set_bit(0, &self->connected);   /* TRUE */
+
                irlmp_send_lcf_pdu(self->lap, self->dlsap_sel,
                                   self->slsap_sel, CONNECT_CNF, skb);
 
@@ -599,10 +601,13 @@ static int irlmp_state_connect(struct lsap_cb *self, IRLMP_EVENT event,
                IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n",  __FUNCTION__);
 
                /* Disconnect, get out... - Jean II */
+               self->lap = NULL;
                self->dlsap_sel = LSAP_ANY;
                irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
                break;
        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", 
                           __FUNCTION__, irlmp_event[event], self->slsap_sel);
                break;
@@ -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__);
 
                /* Go back to disconnected mode, keep the socket waiting */
+               self->lap = NULL;
                self->dlsap_sel = LSAP_ANY;
                if(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,
                irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
                break;
        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",
                           __FUNCTION__, irlmp_event[event], self->slsap_sel);
                break;
@@ -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,
                                   DISCONNECT, skb);
                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 */
                if (self->lap) {
index 8575a217cc62d8c127afac31b30ad7aca576abb5..3161713dc43351cb63c4ad215d0ede12f3a1a307 100644 (file)
@@ -1428,9 +1428,16 @@ struct tsap_cb *irttp_dup(struct tsap_cb *orig, void *instance)
        /* We don't need the old instance any more */
        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 */
        new->notify.instance = instance;
-       new->lsap = irlmp_dup(orig->lsap, new);
        init_timer(&new->todo_timer);
 
        skb_queue_head_init(&new->rx_queue);