Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=6464f35f3771f69cd8d107fff166dc29ab392f97
Commit:     6464f35f3771f69cd8d107fff166dc29ab392f97
Parent:     f0709e03ac3552b1b048ee171cb96ecaacc6813c
Author:     Marcel Holtmann <[EMAIL PROTECTED]>
AuthorDate: Sat Oct 20 13:39:51 2007 +0200
Committer:  David S. Miller <[EMAIL PROTECTED]>
CommitDate: Mon Oct 22 02:59:43 2007 -0700

    [Bluetooth] Fall back to L2CAP in basic mode
    
    In case the remote entity tries to negogiate retransmission or flow
    control mode, reject it and fall back to basic mode.
    
    Signed-off-by: Marcel Holtmann <[EMAIL PROTECTED]>
---
 include/net/bluetooth/l2cap.h |   13 +++++++++++++
 net/bluetooth/l2cap.c         |   32 ++++++++++++++++++++++++--------
 2 files changed, 37 insertions(+), 8 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index e1ea640..73e115b 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -149,6 +149,19 @@ struct l2cap_conf_opt {
 
 #define L2CAP_CONF_MAX_SIZE    22
 
+struct l2cap_conf_rfc {
+       __u8       mode;
+       __u8       txwin_size;
+       __u8       max_transmit;
+       __le16     retrans_timeout;
+       __le16     monitor_timeout;
+       __le16     max_pdu_size;
+} __attribute__ ((packed));
+
+#define L2CAP_MODE_BASIC       0x00
+#define L2CAP_MODE_RETRANS     0x01
+#define L2CAP_MODE_FLOWCTL     0x02
+
 struct l2cap_disconn_req {
        __le16     dcid;
        __le16     scid;
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 733c95d..6fbbae7 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -1048,7 +1048,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int 
level, int optname, ch
                opts.imtu     = l2cap_pi(sk)->imtu;
                opts.omtu     = l2cap_pi(sk)->omtu;
                opts.flush_to = l2cap_pi(sk)->flush_to;
-               opts.mode     = 0x00;
+               opts.mode     = L2CAP_MODE_BASIC;
 
                len = min_t(unsigned int, sizeof(opts), optlen);
                if (copy_from_user((char *) &opts, optval, len)) {
@@ -1097,7 +1097,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int 
level, int optname, ch
                opts.imtu     = l2cap_pi(sk)->imtu;
                opts.omtu     = l2cap_pi(sk)->omtu;
                opts.flush_to = l2cap_pi(sk)->flush_to;
-               opts.mode     = 0x00;
+               opts.mode     = L2CAP_MODE_BASIC;
 
                len = min_t(unsigned int, len, sizeof(opts));
                if (copy_to_user(optval, (char *) &opts, len))
@@ -1376,6 +1376,7 @@ static int l2cap_parse_conf_req(struct sock *sk, void 
*data)
        int len = pi->conf_len;
        int type, hint, olen;
        unsigned long val;
+       struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
        u16 mtu = L2CAP_DEFAULT_MTU;
        u16 result = L2CAP_CONF_SUCCESS;
 
@@ -1399,6 +1400,11 @@ static int l2cap_parse_conf_req(struct sock *sk, void 
*data)
                case L2CAP_CONF_QOS:
                        break;
 
+               case L2CAP_CONF_RFC:
+                       if (olen == sizeof(rfc))
+                               memcpy(&rfc, (void *) val, olen);
+                       break;
+
                default:
                        if (hint)
                                break;
@@ -1413,14 +1419,24 @@ static int l2cap_parse_conf_req(struct sock *sk, void 
*data)
                /* Configure output options and let the other side know
                 * which ones we don't like. */
 
-               if (mtu < pi->omtu)
+               if (rfc.mode == L2CAP_MODE_BASIC) {
+                       if (mtu < pi->omtu)
+                               result = L2CAP_CONF_UNACCEPT;
+                       else {
+                               pi->omtu = mtu;
+                               pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
+                       }
+
+                       l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
+               } else {
                        result = L2CAP_CONF_UNACCEPT;
-               else {
-                       pi->omtu = mtu;
-                       pi->conf_state |= L2CAP_CONF_OUTPUT_DONE;
-               }
 
-               l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
+                       memset(&rfc, 0, sizeof(rfc));
+                       rfc.mode = L2CAP_MODE_BASIC;
+
+                       l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
+                                               sizeof(rfc), (unsigned long) 
&rfc);
+               }
        }
 
        rsp->scid   = cpu_to_le16(pi->dcid);
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to