Hi,

        When you remove the IrDA stack, IrNET may complain that the
LAP is invalid. If you don't have DEBUG enabled, it may even crash.
        I took this opportunity to clean the procedure to put back
socket in listen mode.
        And also included a fix for IrNET event...

        Jean
diff -u -p linux/include/net/irda/irlmp.d3.h linux/include/net/irda/irlmp.h
--- linux/include/net/irda/irlmp.d3.h   Thu Nov 29 10:33:26 2001
+++ linux/include/net/irda/irlmp.h      Thu Nov 29 11:04:59 2001
@@ -264,4 +264,16 @@ static inline int irlmp_get_lap_tx_queue
        return IRLAP_GET_TX_QUEUE_LEN(self->lap->irlap);
 }
 
+/* After doing a irlmp_dup(), this get one of the two socket back into
+ * a state where it's waiting incomming connections.
+ * Note : this can be used *only* if the socket is not yet connected
+ * (i.e. NO irlmp_connect_response() done on this socket).
+ * - Jean II */
+static inline void irlmp_listen(struct lsap_cb *self)
+{
+       self->dlsap_sel = LSAP_ANY;
+       self->lap = NULL;
+       self->lsap_state = LSAP_DISCONNECTED;
+}
+
 #endif
diff -u -p linux/include/net/irda/irttp.d3.h linux/include/net/irda/irttp.h
--- linux/include/net/irda/irttp.d3.h   Thu Nov 29 11:02:29 2001
+++ linux/include/net/irda/irttp.h      Thu Nov 29 11:10:51 2001
@@ -148,6 +148,17 @@ static __inline __u32 irttp_get_max_seg_
        return self->max_seg_size;
 }
 
+/* After doing a irttp_dup(), this get one of the two socket back into
+ * a state where it's waiting incomming connections.
+ * Note : this can be used *only* if the socket is not yet connected
+ * (i.e. NO irttp_connect_response() done on this socket).
+ * - Jean II */
+static inline void irttp_listen(struct tsap_cb *self)
+{
+       irlmp_listen(self->lsap);
+       self->dtsap_sel = LSAP_ANY;
+}
+
 extern struct irttp_cb *irttp;
 
 #endif /* IRTTP_H */
diff -u -p linux/net/irda/irlmp.d3.c linux/net/irda/irlmp.c
--- linux/net/irda/irlmp.d3.c   Tue Nov 20 11:21:44 2001
+++ linux/net/irda/irlmp.c      Thu Nov 29 10:57:04 2001
@@ -469,7 +469,12 @@ void irlmp_connect_indication(struct lsa
 
        IRDA_DEBUG(2, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n", 
                   self->slsap_sel, self->dlsap_sel);
-       
+
+       /* Note : self->lap is set in irlmp_link_data_indication(),
+        * (case CONNECT_CMD:) because we have no way to set it here.
+        * Similarly, self->dlsap_sel is usually set in irlmp_find_lsap().
+        * Jean II */
+
        self->qos = *self->lap->qos;
 
        max_seg_size = self->lap->qos->data_size.value-LMP_HEADER;
@@ -577,7 +582,9 @@ struct lsap_cb *irlmp_dup(struct lsap_cb
        /* Dup */
        memcpy(new, orig, sizeof(struct lsap_cb));
        new->notify.instance = instance;
-       
+       /* new->lap = orig->lap; => done in the memcpy() */
+       /* new->slsap_sel = orig->slsap_sel; => done in the memcpy() */
+
        init_timer(&new->watchdog_timer);
        
        hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) new, (int) new, 
diff -u -p linux/net/irda/iriap.d3.c linux/net/irda/iriap.c
--- linux/net/irda/iriap.d3.c   Thu Nov 29 11:12:55 2001
+++ linux/net/irda/iriap.c      Thu Nov 29 11:13:25 2001
@@ -800,9 +800,7 @@ static void iriap_connect_indication(voi
        new->max_header_size = max_header_size;
 
        /* Clean up the original one to keep it in listen state */
-       self->lsap->dlsap_sel = LSAP_ANY;
-       self->lsap->lsap_state = LSAP_DISCONNECTED;
-       /* FIXME: refcount in irlmp might get wrong */
+       irlmp_listen(self->lsap);
        
        iriap_do_server_event(new, IAP_LM_CONNECT_INDICATION, userdata);
 }
diff -u -p linux/net/irda/af_irda.d3b.c linux/net/irda/af_irda.c
--- linux/net/irda/af_irda.d3b.c        Thu Nov 29 11:09:09 2001
+++ linux/net/irda/af_irda.c    Thu Nov 29 11:09:36 2001
@@ -914,8 +914,7 @@ static int irda_accept(struct socket *so
        memcpy(&new->qos_tx, &self->qos_tx, sizeof(struct qos_info));
 
        /* Clean up the original one to keep it in listen state */
-       self->tsap->dtsap_sel = self->tsap->lsap->dlsap_sel = LSAP_ANY;
-       self->tsap->lsap->lsap_state = LSAP_DISCONNECTED;
+       irttp_listen(self->tsap);
 
        skb->sk = NULL;
        skb->destructor = NULL;
diff -u -p linux/net/irda/irnet/irnet.d3.h linux/net/irda/irnet/irnet.h
--- linux/net/irda/irnet/irnet.d3.h     Wed Nov 28 10:15:54 2001
+++ linux/net/irda/irnet/irnet.h        Thu Nov 29 11:15:57 2001
@@ -199,6 +199,13 @@
  *     o Avoid leaking discovery log and skb
  *     o Replace "self" with "server" in irnet_connect_indication() to
  *       better detect cut'n'paste error ;-)
+ *
+ * v9 - 29.11.01 - Jean II
+ *     o Fix event generation in disconnect indication that I broke in v8
+ *       It was always generation "No-Answer" because I was testing ttp_open
+ *       just after clearing it. *blush*.
+ *     o Use newly created irttp_listen() to fix potential crash when LAP
+ *       destroyed before irnet module removed.
  */
 
 /***************************** INCLUDES *****************************/
diff -u -p linux/net/irda/irnet/irnet_irda.d3.c linux/net/irda/irnet/irnet_irda.c
--- linux/net/irda/irnet/irnet_irda.d3.c        Tue Nov 27 16:19:28 2001
+++ linux/net/irda/irnet/irnet_irda.c   Thu Nov 29 11:50:00 2001
@@ -830,8 +830,7 @@ irnet_connect_socket(irnet_socket * serv
 #endif /* STREAM_COMPAT */
 
   /* Clean up the original one to keep it in listen state */
-  server->tsap->dtsap_sel = server->tsap->lsap->dlsap_sel = LSAP_ANY;
-  server->tsap->lsap->lsap_state = LSAP_DISCONNECTED;
+  irttp_listen(server->tsap);
 
   /* Send a connection response on the new socket */
   irttp_connect_response(new->tsap, new->max_sdu_size_rx, NULL);
@@ -897,8 +896,7 @@ irnet_disconnect_server(irnet_socket *      s
                   self->saddr, self->daddr, self->rname);
 
   /* Clean up the server to keep it in listen state */
-  self->tsap->dtsap_sel = self->tsap->lsap->dlsap_sel = LSAP_ANY;
-  self->tsap->lsap->lsap_state = LSAP_DISCONNECTED;
+  irttp_listen(self->tsap);
 
   DEXIT(IRDA_SERV_TRACE, "\n");
   return;
@@ -1081,7 +1079,8 @@ irnet_disconnect_indication(void *        insta
                            struct sk_buff *skb)
 {
   irnet_socket *       self = (irnet_socket *) instance;
-  int                  test = 0;
+  int                  test_open;
+  int                  test_connect;
 
   DENTER(IRDA_TCB_TRACE, "(self=0x%X)\n", (unsigned int) self);
   DASSERT(self != NULL, , IRDA_CB_ERROR, "Self is NULL !!!\n");
@@ -1091,23 +1090,23 @@ irnet_disconnect_indication(void *      insta
     dev_kfree_skb(skb);
 
   /* Prevent higher layer from accessing IrTTP */
-  test = test_and_clear_bit(0, &self->ttp_open);
+  test_open = test_and_clear_bit(0, &self->ttp_open);
   /* Not connecting anymore...
    * (note : TSAP is open, so IAP callbacks are no longer pending...) */
-  test |= test_and_clear_bit(0, &self->ttp_connect);
+  test_connect = test_and_clear_bit(0, &self->ttp_connect);
 
   /* If both self->ttp_open and self->ttp_connect are NULL, it mean that we
    * have a race condition with irda_irnet_destroy() or
    * irnet_connect_indication(), so don't mess up tsap...
    */
-  if(!test)
+  if(!(test_open || test_connect))
     {
       DERROR(IRDA_CB_ERROR, "Race condition detected...\n");
       return;
     }
 
   /* If we were active, notify the control channel */
-  if(test_bit(0, &self->ttp_open))
+  if(test_open)
     irnet_post_event(self, IRNET_DISCONNECT_FROM,
                     self->saddr, self->daddr, self->rname);
   else

Reply via email to