From 21d9e30ed020d24336cc3bee2a4e04da232ed554 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 13 Sep 2005 01:32:25 +0200 Subject: [PATCH 1/9] [Bluetooth] Add support for extended inquiry responses This patch adds the handling of the extended inquiry responses and inserts them into the inquiry cache. Signed-off-by: Marcel Holtmann --- include/net/bluetooth/hci.h | 11 +++++++++++ net/bluetooth/hci_event.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 371e7d3f2e6f..fa2d12b0579b 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -463,6 +463,17 @@ struct inquiry_info_with_rssi_and_pscan_mode { __s8 rssi; } __attribute__ ((packed)); +#define HCI_EV_EXTENDED_INQUIRY_RESULT 0x2F +struct extended_inquiry_info { + bdaddr_t bdaddr; + __u8 pscan_rep_mode; + __u8 pscan_period_mode; + __u8 dev_class[3]; + __u16 clock_offset; + __s8 rssi; + __u8 data[240]; +} __attribute__ ((packed)); + #define HCI_EV_CONN_COMPLETE 0x03 struct hci_ev_conn_complete { __u8 status; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index d6da0939216d..b61b4e8e36fd 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -558,6 +558,35 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct hci_dev_unlock(hdev); } +/* Extended Inquiry Result */ +static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) +{ + struct inquiry_data data; + struct extended_inquiry_info *info = (struct extended_inquiry_info *) (skb->data + 1); + int num_rsp = *((__u8 *) skb->data); + + BT_DBG("%s num_rsp %d", hdev->name, num_rsp); + + if (!num_rsp) + return; + + hci_dev_lock(hdev); + + for (; num_rsp; num_rsp--) { + bacpy(&data.bdaddr, &info->bdaddr); + data.pscan_rep_mode = info->pscan_rep_mode; + data.pscan_period_mode = info->pscan_period_mode; + data.pscan_mode = 0x00; + memcpy(data.dev_class, info->dev_class, 3); + data.clock_offset = info->clock_offset; + data.rssi = info->rssi; + info++; + hci_inquiry_cache_update(hdev, &data); + } + + hci_dev_unlock(hdev); +} + /* Connect Request */ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) { @@ -940,6 +969,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) hci_inquiry_result_with_rssi_evt(hdev, skb); break; + case HCI_EV_EXTENDED_INQUIRY_RESULT: + hci_extended_inquiry_result_evt(hdev, skb); + break; + case HCI_EV_CONN_REQUEST: hci_conn_request_evt(hdev, skb); break; From 354d28d5f8546e115ebaae9311897f0bc4b6a8d4 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 13 Sep 2005 01:32:31 +0200 Subject: [PATCH 2/9] [Bluetooth] Prevent RFCOMM connections through the RAW socket This patch adds additional checks to prevent RFCOMM connections be established through the RAW socket interface. Signed-off-by: Marcel Holtmann --- net/bluetooth/rfcomm/sock.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 90e19eb6d3cc..f49e7e938bfb 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -363,6 +363,11 @@ static int rfcomm_sock_bind(struct socket *sock, struct sockaddr *addr, int addr goto done; } + if (sk->sk_type != SOCK_STREAM) { + err = -EINVAL; + goto done; + } + write_lock_bh(&rfcomm_sk_list.lock); if (sa->rc_channel && __rfcomm_get_sock_by_addr(sa->rc_channel, &sa->rc_bdaddr)) { @@ -393,14 +398,18 @@ static int rfcomm_sock_connect(struct socket *sock, struct sockaddr *addr, int a if (addr->sa_family != AF_BLUETOOTH || alen < sizeof(struct sockaddr_rc)) return -EINVAL; - if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND) - return -EBADFD; - - if (sk->sk_type != SOCK_STREAM) - return -EINVAL; - lock_sock(sk); + if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND) { + err = -EBADFD; + goto done; + } + + if (sk->sk_type != SOCK_STREAM) { + err = -EINVAL; + goto done; + } + sk->sk_state = BT_CONNECT; bacpy(&bt_sk(sk)->dst, &sa->rc_bdaddr); rfcomm_pi(sk)->channel = sa->rc_channel; @@ -410,6 +419,7 @@ static int rfcomm_sock_connect(struct socket *sock, struct sockaddr *addr, int a err = bt_sock_wait_state(sk, BT_CONNECTED, sock_sndtimeo(sk, flags & O_NONBLOCK)); +done: release_sock(sk); return err; } @@ -428,6 +438,11 @@ static int rfcomm_sock_listen(struct socket *sock, int backlog) goto done; } + if (sk->sk_type != SOCK_STREAM) { + err = -EINVAL; + goto done; + } + if (!rfcomm_pi(sk)->channel) { bdaddr_t *src = &bt_sk(sk)->src; u8 channel; @@ -472,6 +487,11 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f goto done; } + if (sk->sk_type != SOCK_STREAM) { + err = -EINVAL; + goto done; + } + timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); BT_DBG("sk %p timeo %ld", sk, timeo); From 0915e8865fe4684dc82f043ac7036f34bf89f52a Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 13 Sep 2005 01:32:37 +0200 Subject: [PATCH 3/9] [Bluetooth] Add ignore parameters to the HCI USB driver This patch adds the module parameters ignore_csr and ignore_sniffer to the HCI USB driver. This allows an easier use of CSR ROM chips that need an additional initialization routine and the Frontline sniffers. Signed-off-by: Marcel Holtmann --- drivers/bluetooth/hci_usb.c | 19 ++++++++++++++++++- drivers/bluetooth/hci_usb.h | 5 +++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c index 67d96b5cbb96..57c48bbf6fe6 100644 --- a/drivers/bluetooth/hci_usb.c +++ b/drivers/bluetooth/hci_usb.c @@ -65,13 +65,15 @@ #endif static int ignore = 0; +static int ignore_csr = 0; +static int ignore_sniffer = 0; static int reset = 0; #ifdef CONFIG_BT_HCIUSB_SCO static int isoc = 2; #endif -#define VERSION "2.8" +#define VERSION "2.9" static struct usb_driver hci_usb_driver; @@ -98,6 +100,9 @@ static struct usb_device_id bluetooth_ids[] = { MODULE_DEVICE_TABLE (usb, bluetooth_ids); static struct usb_device_id blacklist_ids[] = { + /* CSR BlueCore devices */ + { USB_DEVICE(0x0a12, 0x0001), .driver_info = HCI_CSR }, + /* Broadcom BCM2033 without firmware */ { USB_DEVICE(0x0a5c, 0x2033), .driver_info = HCI_IGNORE }, @@ -836,6 +841,12 @@ static int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id if (ignore || id->driver_info & HCI_IGNORE) return -ENODEV; + if (ignore_csr && id->driver_info & HCI_CSR) + return -ENODEV; + + if (ignore_sniffer && id->driver_info & HCI_SNIFFER) + return -ENODEV; + if (intf->cur_altsetting->desc.bInterfaceNumber > 0) return -ENODEV; @@ -1061,6 +1072,12 @@ module_exit(hci_usb_exit); module_param(ignore, bool, 0644); MODULE_PARM_DESC(ignore, "Ignore devices from the matching table"); +module_param(ignore_csr, bool, 0644); +MODULE_PARM_DESC(ignore_csr, "Ignore devices with id 0a12:0001"); + +module_param(ignore_sniffer, bool, 0644); +MODULE_PARM_DESC(ignore_sniffer, "Ignore devices with id 0a12:0002"); + module_param(reset, bool, 0644); MODULE_PARM_DESC(reset, "Send HCI reset command on initialization"); diff --git a/drivers/bluetooth/hci_usb.h b/drivers/bluetooth/hci_usb.h index 29936b43d4f8..37100a6ea1a8 100644 --- a/drivers/bluetooth/hci_usb.h +++ b/drivers/bluetooth/hci_usb.h @@ -31,9 +31,10 @@ #define HCI_IGNORE 0x01 #define HCI_RESET 0x02 #define HCI_DIGIANSWER 0x04 -#define HCI_SNIFFER 0x08 -#define HCI_BROKEN_ISOC 0x10 +#define HCI_CSR 0x08 +#define HCI_SNIFFER 0x10 #define HCI_BCM92035 0x20 +#define HCI_BROKEN_ISOC 0x40 #define HCI_MAX_IFACE_NUM 3 From 5cb30640ce01d76d256533bb2824c9cc14eb4070 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Tue, 13 Sep 2005 13:48:00 -0700 Subject: [PATCH 4/9] [NETFILTER]: Use correct type for "ports" module parameter With large port numbers the helper_names buffer can overflow. Noticed by Samir Bellabes Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/netfilter/ip_conntrack_ftp.c | 6 +++--- net/ipv4/netfilter/ip_conntrack_irc.c | 6 +++--- net/ipv4/netfilter/ip_conntrack_tftp.c | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/net/ipv4/netfilter/ip_conntrack_ftp.c b/net/ipv4/netfilter/ip_conntrack_ftp.c index 1b79ec36085f..d77d6b3f5f80 100644 --- a/net/ipv4/netfilter/ip_conntrack_ftp.c +++ b/net/ipv4/netfilter/ip_conntrack_ftp.c @@ -29,9 +29,9 @@ static char *ftp_buffer; static DEFINE_SPINLOCK(ip_ftp_lock); #define MAX_PORTS 8 -static int ports[MAX_PORTS]; +static short ports[MAX_PORTS]; static int ports_c; -module_param_array(ports, int, &ports_c, 0400); +module_param_array(ports, short, &ports_c, 0400); static int loose; module_param(loose, int, 0600); @@ -450,7 +450,7 @@ out_update_nl: } static struct ip_conntrack_helper ftp[MAX_PORTS]; -static char ftp_names[MAX_PORTS][10]; +static char ftp_names[MAX_PORTS][sizeof("ftp-65535")]; /* Not __exit: called from init() */ static void fini(void) diff --git a/net/ipv4/netfilter/ip_conntrack_irc.c b/net/ipv4/netfilter/ip_conntrack_irc.c index d7a8a98c05e1..15457415a4f3 100644 --- a/net/ipv4/netfilter/ip_conntrack_irc.c +++ b/net/ipv4/netfilter/ip_conntrack_irc.c @@ -34,7 +34,7 @@ #include #define MAX_PORTS 8 -static int ports[MAX_PORTS]; +static short ports[MAX_PORTS]; static int ports_c; static int max_dcc_channels = 8; static unsigned int dcc_timeout = 300; @@ -52,7 +52,7 @@ EXPORT_SYMBOL_GPL(ip_nat_irc_hook); MODULE_AUTHOR("Harald Welte "); MODULE_DESCRIPTION("IRC (DCC) connection tracking helper"); MODULE_LICENSE("GPL"); -module_param_array(ports, int, &ports_c, 0400); +module_param_array(ports, short, &ports_c, 0400); MODULE_PARM_DESC(ports, "port numbers of IRC servers"); module_param(max_dcc_channels, int, 0400); MODULE_PARM_DESC(max_dcc_channels, "max number of expected DCC channels per IRC session"); @@ -240,7 +240,7 @@ static int help(struct sk_buff **pskb, } static struct ip_conntrack_helper irc_helpers[MAX_PORTS]; -static char irc_names[MAX_PORTS][10]; +static char irc_names[MAX_PORTS][sizeof("irc-65535")]; static void fini(void); diff --git a/net/ipv4/netfilter/ip_conntrack_tftp.c b/net/ipv4/netfilter/ip_conntrack_tftp.c index d2b590533452..a78736b8525d 100644 --- a/net/ipv4/netfilter/ip_conntrack_tftp.c +++ b/net/ipv4/netfilter/ip_conntrack_tftp.c @@ -26,9 +26,9 @@ MODULE_DESCRIPTION("tftp connection tracking helper"); MODULE_LICENSE("GPL"); #define MAX_PORTS 8 -static int ports[MAX_PORTS]; +static short ports[MAX_PORTS]; static int ports_c; -module_param_array(ports, int, &ports_c, 0400); +module_param_array(ports, short, &ports_c, 0400); MODULE_PARM_DESC(ports, "port numbers of tftp servers"); #if 0 @@ -100,7 +100,7 @@ static int tftp_help(struct sk_buff **pskb, } static struct ip_conntrack_helper tftp[MAX_PORTS]; -static char tftp_names[MAX_PORTS][10]; +static char tftp_names[MAX_PORTS][sizeof("tftp-65535")]; static void fini(void) { From e7fa1bd93f977c03050bd6b3d13846aa43310fef Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Tue, 13 Sep 2005 13:48:34 -0700 Subject: [PATCH 5/9] [NETFILTER]: Simplify netbios helper Don't parse the packet, the data is already available in the conntrack structure. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/netfilter/ip_conntrack_netbios_ns.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/net/ipv4/netfilter/ip_conntrack_netbios_ns.c b/net/ipv4/netfilter/ip_conntrack_netbios_ns.c index bb7246683b74..71ef19d126d0 100644 --- a/net/ipv4/netfilter/ip_conntrack_netbios_ns.c +++ b/net/ipv4/netfilter/ip_conntrack_netbios_ns.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -31,6 +30,8 @@ #include #include +#define NMBD_PORT 137 + MODULE_AUTHOR("Patrick McHardy "); MODULE_DESCRIPTION("NetBIOS name service broadcast connection tracking helper"); MODULE_LICENSE("GPL"); @@ -44,7 +45,6 @@ static int help(struct sk_buff **pskb, { struct ip_conntrack_expect *exp; struct iphdr *iph = (*pskb)->nh.iph; - struct udphdr _uh, *uh; struct rtable *rt = (struct rtable *)(*pskb)->dst; struct in_device *in_dev; u_int32_t mask = 0; @@ -72,20 +72,15 @@ static int help(struct sk_buff **pskb, if (mask == 0) goto out; - uh = skb_header_pointer(*pskb, iph->ihl * 4, sizeof(_uh), &_uh); - BUG_ON(uh == NULL); - exp = ip_conntrack_expect_alloc(ct); if (exp == NULL) goto out; - memset(&exp->tuple, 0, sizeof(exp->tuple)); - exp->tuple.src.ip = iph->daddr & mask; - exp->tuple.dst.ip = iph->saddr; - exp->tuple.dst.u.udp.port = uh->source; - exp->tuple.dst.protonum = IPPROTO_UDP; - memset(&exp->mask, 0, sizeof(exp->mask)); + exp->tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple; + exp->tuple.src.u.udp.port = ntohs(NMBD_PORT); + exp->mask.src.ip = mask; + exp->mask.src.u.udp.port = 0xFFFF; exp->mask.dst.ip = 0xFFFFFFFF; exp->mask.dst.u.udp.port = 0xFFFF; exp->mask.dst.protonum = 0xFF; @@ -107,7 +102,7 @@ static struct ip_conntrack_helper helper = { .src = { .u = { .udp = { - .port = __constant_htons(137), + .port = __constant_htons(NMBD_PORT), } } }, From cd0bf2d796ebb51c346b1ed4208cdbfd86e98a61 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Tue, 13 Sep 2005 13:48:58 -0700 Subject: [PATCH 6/9] [NETFILTER]: Fix rcu race in ipt_REDIRECT Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/netfilter/ipt_REDIRECT.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c index d2e13447678e..715cb613405c 100644 --- a/net/ipv4/netfilter/ipt_REDIRECT.c +++ b/net/ipv4/netfilter/ipt_REDIRECT.c @@ -88,14 +88,18 @@ redirect_target(struct sk_buff **pskb, newdst = htonl(0x7F000001); else { struct in_device *indev; + struct in_ifaddr *ifa; - /* Device might not have an associated in_device. */ - indev = (struct in_device *)(*pskb)->dev->ip_ptr; - if (indev == NULL || indev->ifa_list == NULL) + newdst = 0; + + rcu_read_lock(); + indev = __in_dev_get((*pskb)->dev); + if (indev && (ifa = indev->ifa_list)) + newdst = ifa->ifa_local; + rcu_read_unlock(); + + if (!newdst) return NF_DROP; - - /* Grab first address on interface. */ - newdst = indev->ifa_list->ifa_local; } /* Transfer from original range. */ From adcb5ad1e5ba3996d53a047c5486efa6e734b413 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Tue, 13 Sep 2005 13:49:15 -0700 Subject: [PATCH 7/9] [NETFILTER]: Fix DHCP + MASQUERADE problem In 2.6.13-rcX the MASQUERADE target was changed not to exclude local packets for better source address consistency. This breaks DHCP clients using UDP sockets when the DHCP requests are caught by a MASQUERADE rule because the MASQUERADE target drops packets when no address is configured on the outgoing interface. This patch makes it ignore packets with a source address of 0. Thanks to Rusty for this suggestion. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/netfilter/ipt_MASQUERADE.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c index 2f3e181c8e97..275a174c6fe6 100644 --- a/net/ipv4/netfilter/ipt_MASQUERADE.c +++ b/net/ipv4/netfilter/ipt_MASQUERADE.c @@ -90,6 +90,12 @@ masquerade_target(struct sk_buff **pskb, IP_NF_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED || ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY)); + /* Source address is 0.0.0.0 - locally generated packet that is + * probably not supposed to be masqueraded. + */ + if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip == 0) + return NF_ACCEPT; + mr = targinfo; rt = (struct rtable *)(*pskb)->dst; newsrc = inet_select_addr(out, rt->rt_gateway, RT_SCOPE_UNIVERSE); From 811265b8e8bf84e3b91507bf6a3a8eea20e7a4b7 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 13 Sep 2005 19:03:15 -0300 Subject: [PATCH 8/9] [DCCP]: Check if already in the CLOSING state in dccp_rcv_closereq It is possible to receive more than one CLOSEREQ packet if the CLOSE packet sent in response is somehow lost, change the state to DCCP_CLOSING only on the first CLOSEREQ packet received. Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/input.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/dccp/input.c b/net/dccp/input.c index c60bc3433f5e..f01d588299c8 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c @@ -50,7 +50,8 @@ static void dccp_rcv_closereq(struct sock *sk, struct sk_buff *skb) return; } - dccp_set_state(sk, DCCP_CLOSING); + if (sk->sk_state != DCCP_CLOSING) + dccp_set_state(sk, DCCP_CLOSING); dccp_send_close(sk, 0); } From 2b80230a7f8cd346c1e2ebafdd02be432bf10459 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 13 Sep 2005 19:05:08 -0300 Subject: [PATCH 9/9] [DCCP]: Handle SYNC packets in dccp_rcv_state_process Eliciting a SYNCACK in response, we were handling SYNC packets only in the DCCP_OPEN state, in dccp_rcv_established. Signed-off-by: Arnaldo Carvalho de Melo --- net/dccp/input.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/dccp/input.c b/net/dccp/input.c index f01d588299c8..c74034cf7ede 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c @@ -562,6 +562,12 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, return 0; } + if (unlikely(dh->dccph_type == DCCP_PKT_SYNC)) { + dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq, + DCCP_PKT_SYNCACK); + goto discard; + } + switch (sk->sk_state) { case DCCP_CLOSED: return 1;