* [PATCH 1/2] obexd: Remove obc_session_setpath limit
From: Christian Fetzer @ 2013-02-13 14:02 UTC (permalink / raw)
To: linux-bluetooth
From: Christian Fetzer <christian.fetzer@bmw-carit.de>
obc_session_setpath is able to handle multiple folder changes at once.
This removes the limit, that was introduced because of PBAP's limitation
to 3 levels (75d32c6b3a3bddaad19b7880950f9a503afe652b).
Other profiles like MAP might have deeper folder hierarchies.
---
obexd/client/session.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/obexd/client/session.c b/obexd/client/session.c
index db37a86..f8aae5d 100644
--- a/obexd/client/session.c
+++ b/obexd/client/session.c
@@ -929,7 +929,7 @@ guint obc_session_setpath(struct obc_session *session, const char *path,
data = g_new0(struct setpath_data, 1);
data->func = func;
data->user_data = user_data;
- data->remaining = g_strsplit(path, "/", 3);
+ data->remaining = g_strsplit(path, "/", 0);
p = pending_request_new(session, NULL, setpath_complete, data);
--
1.8.1.3
^ permalink raw reply related
* [PATCH BlueZ] tools: Track transport state if player status is not supported
From: Luiz Augusto von Dentz @ 2013-02-13 12:07 UTC (permalink / raw)
To: linux-bluetooth
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This makes PlayPause method to work properly even if remote device
supports only AVRCP 1.0.
---
tools/mpris-player.c | 73 ++++++++++++++++++++++++++++++++++------------------
1 file changed, 48 insertions(+), 25 deletions(-)
diff --git a/tools/mpris-player.c b/tools/mpris-player.c
index 4dbde90..8809f2c 100644
--- a/tools/mpris-player.c
+++ b/tools/mpris-player.c
@@ -851,17 +851,48 @@ static void player_control(struct player *player, DBusMessage *msg,
p, pending_call_free);
}
+static const char *status_to_playback(const char *status)
+{
+ if (strcasecmp(status, "playing") == 0)
+ return "Playing";
+ else if (strcasecmp(status, "paused") == 0)
+ return "Paused";
+ else
+ return "Stopped";
+}
+
+static const char *player_get_status(struct player *player)
+{
+ const char *status;
+ DBusMessageIter value;
+
+ if (g_dbus_proxy_get_property(player->proxy, "Status", &value)) {
+ dbus_message_iter_get_basic(&value, &status);
+ return status_to_playback(status);
+ }
+
+ if (player->transport == NULL)
+ goto done;
+
+ if (!g_dbus_proxy_get_property(player->transport, "State", &value))
+ goto done;
+
+ dbus_message_iter_get_basic(&value, &status);
+
+ if (strcasecmp(status, "active") == 0)
+ return "Playing";
+
+done:
+ return "Stopped";
+}
+
static DBusMessage *player_toggle(DBusConnection *conn, DBusMessage *msg,
void *data)
{
struct player *player = data;
- DBusMessageIter value;
const char *status;
- if (!g_dbus_proxy_get_property(player->proxy, "Status", &value))
- return FALSE;
-
- dbus_message_iter_get_basic(&value, &status);
+ status = player_get_status(player);
if (strcasecmp(status, "Playing") == 0)
player_control(player, msg, "Pause");
@@ -923,35 +954,18 @@ static DBusMessage *player_previous(DBusConnection *conn, DBusMessage *msg,
static gboolean status_exists(const GDBusPropertyTable *property, void *data)
{
- DBusMessageIter iter;
struct player *player = data;
- return g_dbus_proxy_get_property(player->proxy, "Status", &iter);
-}
-
-static const char *status_to_playback(const char *status)
-{
- if (strcasecmp(status, "playing") == 0)
- return "Playing";
- else if (strcasecmp(status, "paused") == 0)
- return "Paused";
- else
- return "Stopped";
+ return player_get_status(player) != NULL;
}
static gboolean get_status(const GDBusPropertyTable *property,
DBusMessageIter *iter, void *data)
{
struct player *player = data;
- DBusMessageIter value;
const char *status;
- if (!g_dbus_proxy_get_property(player->proxy, "Status", &value))
- return FALSE;
-
- dbus_message_iter_get_basic(&value, &status);
-
- status = status_to_playback(status);
+ status = player_get_status(player);
dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &status);
@@ -1689,7 +1703,7 @@ static void transport_property_changed(GDBusProxy *proxy, const char *name,
DBusMessageIter var;
const char *path;
- if (strcasecmp(name, "Volume") != 0)
+ if (strcasecmp(name, "Volume") != 0 && strcasecmp(name, "State") != 0)
return;
if (!g_dbus_proxy_get_property(proxy, "Device", &var))
@@ -1701,6 +1715,15 @@ static void transport_property_changed(GDBusProxy *proxy, const char *name,
if (player == NULL)
return;
+ if (strcasecmp(name, "State") == 0) {
+ if (!g_dbus_proxy_get_property(player->proxy, "Status", &var))
+ g_dbus_emit_property_changed(player->conn,
+ MPRIS_PLAYER_PATH,
+ MPRIS_PLAYER_INTERFACE,
+ "PlaybackStatus");
+ return;
+ }
+
g_dbus_emit_property_changed(player->conn, MPRIS_PLAYER_PATH,
MPRIS_PLAYER_INTERFACE,
name);
--
1.8.1.2
^ permalink raw reply related
* Fwd: Beginner Using a2dpsink, avdtpsink, and rtpsbcpay
From: John Westing @ 2013-02-12 21:17 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <CAPjuhm5ojRkhYBa3n_N1XBkQfE1xpM-uXekLDCgXqFFs-psWNw@mail.gmail.com>
I'm using Ubuntu 12.04 and was hoping to payload and send MP3s using
Bluetooth and the BlueZ GStreamer plugin. My first test was to see if
I could stream SBC audio so I used the following command
gst-launch filesrc location=~/music/song.mp3 ! flump3dec ! sbcenc !
a2dpsink device=00:01:1A:FA:5C:AA
and it streamed correctly. Next I wanted to see if I could use the
rtpsbcpay RTP payloader element, so executed the command
gst-launch filesrc location= ~/music/song.mp3 ! flump3dec ! sbcenc !
rtpsbcpay min-frames=-1 ! avdtpsink device= 00:01:1A:FA:5C:AA
but it failed with the following errors:
Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
0:00:02.056144952 2475 0x8cdb690 ERROR avdtpsink
audio/gstavdtpsink.c:1912:gst_avdtp_sink_audioservice_recv:<avdtpsink0>
BT_START_STREAM failed : Success(0)
0:00:02.057025034 2475 0x8cdb690 ERROR avdtpsink
audio/gstavdtpsink.c:1507:gst_avdtp_sink_stream_start:<avdtpsink0>
Error while stream start confirmation
0:00:02.063086880 2475 0x8cdb690 WARN basesrc
gstbasesrc.c:2625:gst_base_src_loop:<filesrc0> error: Internal data
flow error.
0:00:02.063446032 2475 0x8cdb690 WARN basesrc
gstbasesrc.c:2625:gst_base_src_loop:<filesrc0> error: streaming task
paused, reason error (-5)
ERROR: from element /GstPipeline:pipeline0/GstFileSrc:filesrc0:
Internal data flow error.
Additional debug info:
gstbasesrc.c(2625): gst_base_src_loop ():
/GstPipeline:pipeline0/GstFileSrc:filesrc0:
streaming task paused, reason error (-5)
ERROR: pipeline doesn't want to preroll.
Setting pipeline to NULL ...
Freeing pipeline ...
I looked at the code for a2dpsink and it simply loads the 2 elements
into a GstBin, I don't see why the functionality would be different
when using rtpsbcpay and avdtpsink explicitly.
If I can't use the rtpsbcpay element to payload SBC data I'm not going
be able to paylod MP3 data either. Does anyone have any idea what the
problem is?
John
^ permalink raw reply
* [RFC] bloodpressure: Add Blood Pressure API
From: Waldemar Rymarkiewicz @ 2013-02-12 11:21 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Waldemar Rymarkiewicz
Change-Id: I7165ecee0186dfdb51cd01838f28768d94ff12b9
---
doc/bloodpressure-api.txt | 138 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 138 insertions(+)
create mode 100644 doc/bloodpressure-api.txt
diff --git a/doc/bloodpressure-api.txt b/doc/bloodpressure-api.txt
new file mode 100644
index 0000000..2acc660
--- /dev/null
+++ b/doc/bloodpressure-api.txt
@@ -0,0 +1,138 @@
+Blood Pressure API description
+******************************
+
+
+Blood Pressure Manager hierarchy
+================================
+
+Serviceorg.bluez
+Interface org.bluez.BloodPressureManager1
+Object path [variable prefix]/{hci0,hci1,...}
+
+Methods RegisterWatcher(object agent)
+
+ Registers a watcher to monitor blood pressure
+ measurements. This agent will be notified about
+ final pressure measurements.
+
+ Possible Errors: org.bluez.Error.InvalidArguments
+
+ UnregisterWatcher(object agent)
+
+ Unregisters a watcher.
+
+ EnableIntermediateMeasurement(object agent)
+
+ Enables intermediate measurement notifications
+ for this agent. Intermediate measurements will
+ be enabled only for devices which support it.
+
+ Possible Errors: org.bluez.Error.InvalidArguments
+
+ DisableIntermediateMeasurement(object agent)
+
+ Disables intermediate measurement notifications
+ for this agent. It will disable notifications in
+ devices when the last agent removes the
+ watcher for intermediate measurements.
+
+ Possible Errors: org.bluez.Error.InvalidArguments
+ org.bluez.Error.NotFound
+
+Blood Pressure Profile hierarchy
+================================
+
+Service org.bluez
+Interface org.bluez.BloodPressure1
+Object path [variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX
+
+Properties boolean Intermediate [readonly]
+
+ True if the device supports intermediate
+ measurement notifications.
+
+Blood Pressure Watcher hierarchy
+================================
+
+Service unique name
+Interface org.bluez.BloodPressureWatcher1
+Object path freely definable
+
+Methods void MeasurementReceived(object device, dict measurement)
+
+ This callback is called whenever a blood pressure
+ measurement is received from the blood pressure device.
+
+ Measurement:
+
+ string Measurement:
+
+ Posible values: "final" or
+ "intermediate"
+
+ uint16 CurrentCuffPressure:
+
+ Current cuff pressure value is only
+ present in intermediate measurement.
+
+ uint16 Systolic:
+
+ Systolic Blood Pressure value is only
+ present in final measurement.
+
+ uint16 Diastolic:
+
+ Diastolic Blood Pressure value is only
+ present in final final measurement.
+
+ uint16 Mean:
+
+ Mean Arterial Pressure value is only
+ present in final measurement.
+
+ string Unit:
+
+ The unit of blood pressure measurement.
+
+ Possible values: "mmHg" or "kPa".
+
+ uint64 Time (optional):
+
+ Time of measurement expresed in seconds
+ from epoch.
+
+ uint16 PulseRate (optional):
+
+ Pulse rate value.
+
+ uint8 UserID (optional):
+
+ User ID if the device supports
+ multiusers measurements.
+
+ boolean BodyMovement (optional)
+
+ True if body movement during
+ measurement has been detected.
+
+ boolean CuffTooLoose (optional)
+
+ True if too loose cuff during
+ measurement has been detected.
+
+ boolean IrregularPulse (optional)
+
+ True if irrgular pulse during
+ measurement has been detected.
+
+ uint8 PulseRateNotInRange (optional)
+
+ Possible values:
+
+ 0 - pulse rate exceeds upper limit
+ 1 - pulse rate is less then lower limit
+
+ boolean MeasurementPosition (optional)
+
+ True if improper measurement position
+ has been detected.
--
1.8.0.209.gf3828dc
^ permalink raw reply related
* Re: [RFC 0/8] MAP client: notification support
From: Luiz Augusto von Dentz @ 2013-02-12 9:02 UTC (permalink / raw)
To: Christian Fetzer; +Cc: linux-bluetooth@vger.kernel.org
In-Reply-To: <1360161922-6585-1-git-send-email-christian.fetzer@oss.bmw-carit.de>
Hi Christian,
On Wed, Feb 6, 2013 at 4:45 PM, Christian Fetzer
<christian.fetzer@oss.bmw-carit.de> wrote:
> From: Christian Fetzer <christian.fetzer@bmw-carit.de>
>
> This patchset adds the necessary blocks for receiving notifications in the MAP client.
> So far this covers only bluetooth protocol related additions, leaving out end user D-Bus API changes.
>
> The patchset consists of the following parts:
> - Message Notification Server (MNS)
> Once connected, the MNS will receive XML based event reports from the MSE and parse them into a struct
> for further processing.
>
> - RegisterNotification function
> The function sends the SetNotificationRegistration command to the MSE which will then try to connect
> to the MNS.
>
> - Notification dispatcher (that dispatches event reports by their MAS instance id to the correct client instance)
> The message access part of every client instance registers a notification handler function.
> The MNS will call the associated handler for all received event report.
>
> Since the dispatching needs to be done on the mas instance id, the message access part of the client
> needs to be aware of the instance id of the server it connects to. Unfortunately this information is only
> available as SDP attribute.
>
> Due to the current transport layer abstraction in obexd, the MAP client has no direct access to SDP.
> Therefore I have extended obc_transport to allow concrete transports (like Bluetooth) to specify
> a get_service_record function and made it available through obc_session_get_service_record.
> This way, transports can provide additional service information to the client implementations.
> The bluetooth transport will now always do a sdp lookup (if the driver's obc_driver->force_service_lookup is set).
> In addition it will cache sdp record associated with the connection and make it accessible in get_service_record.
>
> Christian Fetzer (8):
> obexd: Add get_service_record to obc_transport
> obexd: Provide SDP record in get_service_record
> obexd: Read MAP client SDP attributes
> obexd: Add Message Notification Server (MNS)
> obexd: Add RegisterNotifications function
> obexd: Add MAP notification dispatcher
> obexd: Register MAP notification handler
> obexd: Notify registered notification handlers
>
> Makefile.obexd | 4 +
> doc/obex-api.txt | 7 +
> lib/sdp.h | 2 +
> obexd/client/bluetooth.c | 51 ++++++-
> obexd/client/driver.h | 1 +
> obexd/client/map-dispatcher.c | 86 +++++++++++
> obexd/client/map-dispatcher.h | 45 ++++++
> obexd/client/map-event.h | 42 +++++
> obexd/client/map.c | 144 +++++++++++++++++-
> obexd/client/mns.c | 346 ++++++++++++++++++++++++++++++++++++++++++
> obexd/client/session.c | 11 +-
> obexd/client/session.h | 2 +
> obexd/client/transport.h | 2 +
> obexd/plugins/bluetooth.c | 2 +
> obexd/src/obexd.h | 1 +
> src/profile.c | 55 +++++++
> 16 files changed, 790 insertions(+), 11 deletions(-)
> create mode 100644 obexd/client/map-dispatcher.c
> create mode 100644 obexd/client/map-dispatcher.h
> create mode 100644 obexd/client/map-event.h
> create mode 100644 obexd/client/mns.c
>
> --
> 1.8.1.2
Did not like so much the thing with force_service_lookup although I
see that we gonna need it, but perhaps we should try to think about
other alternatives. The implementation of MNS as a proper driver is
what made us to integrate the server and client but we should go one
step forward and integrate client and server core specially the plugin
handling should be common to both client and server just the drivers
need to be different.
--
Luiz Augusto von Dentz
^ permalink raw reply
* [PATCH BlueZ v0] transport: Fix inconsistent transport state
From: Mikel Astiz @ 2013-02-12 8:23 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Mikel Astiz
From: Mikel Astiz <mikel.astiz@bmw-carit.de>
If a2dp_resume() fails, the transport state should not be modified. It
would otherwise enter an incosistent state where the transport will be
impossible to resume, since acquire() will see the transport in
TRANSPORT_STATE_REQUESTING state and will thus return
btd_error_not_authorized().
---
profiles/audio/transport.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/profiles/audio/transport.c b/profiles/audio/transport.c
index 5b3fcbc..32ba50b 100644
--- a/profiles/audio/transport.c
+++ b/profiles/audio/transport.c
@@ -329,6 +329,7 @@ static guint resume_a2dp(struct media_transport *transport,
struct a2dp_transport *a2dp = transport->data;
struct media_endpoint *endpoint = transport->endpoint;
struct a2dp_sep *sep = media_endpoint_get_sep(endpoint);
+ guint id;
if (a2dp->session == NULL) {
a2dp->session = avdtp_get(transport->device);
@@ -337,16 +338,23 @@ static guint resume_a2dp(struct media_transport *transport,
}
if (state_in_use(transport->state))
- goto done;
+ return a2dp_resume(a2dp->session, sep, a2dp_resume_complete,
+ owner);
if (a2dp_sep_lock(sep, a2dp->session) == FALSE)
return 0;
+ id = a2dp_resume(a2dp->session, sep, a2dp_resume_complete, owner);
+
+ if (id == 0) {
+ a2dp_sep_unlock(sep, a2dp->session);
+ return 0;
+ }
+
if (transport->state == TRANSPORT_STATE_IDLE)
transport_set_state(transport, TRANSPORT_STATE_REQUESTING);
-done:
- return a2dp_resume(a2dp->session, sep, a2dp_resume_complete, owner);
+ return id;
}
static void a2dp_suspend_complete(struct avdtp *session,
--
1.8.1
^ permalink raw reply related
* Re: Missing manpage for main.conf
From: Rebecca Menessec @ 2013-02-11 21:09 UTC (permalink / raw)
To: Johan Hedberg; +Cc: linux-bluetooth
In-Reply-To: <20130211193754.GA12283@x220.P-661HNU-F1>
Thanks for the update. I'll ask rsyslog to send bluetoothd output to
/dev/null until / unless I need it, then. :)
I've been trying to turn off all unnecessary logging on a
resource-constrained system so as to avoid wasting the CPU cycles and
wake-ups.
On 2013-02-11 21:37:54 (+0200), Johan Hedberg wrote:
> Hi Rebecca,
>
> On Sat, Feb 09, 2013, Rebecca Menessec wrote:
> > I was looking for a way to disable BlueZ logging (Ubuntu machine), and
> > came across this, in the bluetoothd manpage:
> >
> > 'bluetoothd itself does not accept many command-line options, as most of
> > its configuration is done in the /etc/bluetooth/main.conf file, which
> > has its own man page.'
> >
> > That doesn't appear to be true. I can't find any trace in any distro, or
> > in the source. I've found a bug filed here and there against the lack of
> > manpage, but no manpage.
>
> This is indeed a bug. I just pushed a patch to remove this reference
> from the bluetoothd man page. main.conf might deserve its own man page
> (even though the upstream sample is self-documenting) but as long one
> doesn't exist it's at least better not to have a bogus reference to it.
>
> It's also worth noting that we're really trying to promote systems
> without any /etc/bluetooth directory at all since the bluetoothd
> defaults should be usable by as many as possible.
>
> > There's definitely logging going on by default:
> >
> > localhost ~ [0]# lsof -n 2> /dev/null | grep blue | grep log
> > rsyslogd 804 syslog 2w REG 0,21
> > 2027 8482 /var/log/bluetoothd.log
> > rs:main 804 813 syslog 2w REG 0,21
> > 2027 8482 /var/log/bluetoothd.log
> > rsyslogd 804 814 syslog 2w REG 0,21
> > 2027 8482 /var/log/bluetoothd.log
> > rsyslogd 804 815 syslog 2w REG 0,21
> > 2027 8482 /var/log/bluetoothd.log
> >
> > Unfortunately, there's no hint anywhere what's causing bluetoothd to
> > log, or how to stop it.
>
> There is no way to stop bluetoothd from logging errors. You can
> enable/disable debug logs with the -d switch but that's it.
>
> Johan
^ permalink raw reply
* Re: Missing manpage for main.conf
From: Johan Hedberg @ 2013-02-11 19:37 UTC (permalink / raw)
To: Rebecca Menessec; +Cc: linux-bluetooth
In-Reply-To: <1360448522.23439.140661189177761.7087C9E4@webmail.messagingengine.com>
Hi Rebecca,
On Sat, Feb 09, 2013, Rebecca Menessec wrote:
> I was looking for a way to disable BlueZ logging (Ubuntu machine), and
> came across this, in the bluetoothd manpage:
>
> 'bluetoothd itself does not accept many command-line options, as most of
> its configuration is done in the /etc/bluetooth/main.conf file, which
> has its own man page.'
>
> That doesn't appear to be true. I can't find any trace in any distro, or
> in the source. I've found a bug filed here and there against the lack of
> manpage, but no manpage.
This is indeed a bug. I just pushed a patch to remove this reference
from the bluetoothd man page. main.conf might deserve its own man page
(even though the upstream sample is self-documenting) but as long one
doesn't exist it's at least better not to have a bogus reference to it.
It's also worth noting that we're really trying to promote systems
without any /etc/bluetooth directory at all since the bluetoothd
defaults should be usable by as many as possible.
> There's definitely logging going on by default:
>
> localhost ~ [0]# lsof -n 2> /dev/null | grep blue | grep log
> rsyslogd 804 syslog 2w REG 0,21
> 2027 8482 /var/log/bluetoothd.log
> rs:main 804 813 syslog 2w REG 0,21
> 2027 8482 /var/log/bluetoothd.log
> rsyslogd 804 814 syslog 2w REG 0,21
> 2027 8482 /var/log/bluetoothd.log
> rsyslogd 804 815 syslog 2w REG 0,21
> 2027 8482 /var/log/bluetoothd.log
>
> Unfortunately, there's no hint anywhere what's causing bluetoothd to
> log, or how to stop it.
There is no way to stop bluetoothd from logging errors. You can
enable/disable debug logs with the -d switch but that's it.
Johan
^ permalink raw reply
* Re: [PATCH 00/14] neard plugin update
From: Szymon Janc @ 2013-02-11 9:52 UTC (permalink / raw)
To: linux-bluetooth@vger.kernel.org; +Cc: Ravi kumar Veeramally
In-Reply-To: <1360224844-12280-1-git-send-email-szymon.janc@tieto.com>
Hi All,
On Thursday 07 of February 2013 10:13:50 Janc Szymon wrote:
> This set adds some new features to neard plugin to match it with
> recent changes in neard daemon:
> - support for carrier power state hint (already merged)
> - update register API [with fallback to legacy support] (pending review)
Just to notify that register API changes were just merged into neard.git so all
code needed is now present in neard daemon.
>
> Power state hint could be use to improve IOP e.g. delay or retry pairing when
> remote device in activating or incative state.
>
> Other than that bugfixes, small improvements and some code refactoring to
> make it better prepared for future feature addition e.g. to perform more
> action on PushOOB than only pairing.
>
> There are still some open points regarding how to properly map adapter
> state (powered/pairable/connectable) to carrier power state but those
> could be discussed separately later on.
>
> Comments are welcome.
>
> BR
> Szymon Janc
>
> Ravi kumar Veeramally (1):
> neard: Updated neard handover registration agent api calls.
>
> Szymon Janc (13):
> neard: Adjust errors to latest API changes
> neard: Refactor message processing
> neard: Add ability to parse 'State' field
> neard: Move pairable check from check_adapter
> adapter: Add btd_adapter_get_powered function
> neard: Check if adapter is powered in PushOOB
> adapter: Add btd_adapter_get_connectable function
> neard: Add support for setting power state in RequestOOB reply
> neard: Use path instead of boolean to track if registered to neard
> neard: Restrict method calls only to neard process
> neard: Use bool instead of gboolean for agent_register_postpone
> neard: Update copyright information
> neard: Add fallback to legacy register if register failed
>
> plugins/neard.c | 562 ++++++++++++++++++++++++++++++++++----------------------
> src/adapter.c | 16 ++
> src/adapter.h | 2 +
> 3 files changed, 361 insertions(+), 219 deletions(-)
>
>
^ permalink raw reply
* Re: [PATCH BlueZ 0/2] Add device_set_trusted()
From: Antonio Ospite @ 2013-02-10 21:30 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Antonio Ospite
In-Reply-To: <1359908071-15024-1-git-send-email-ospite@studenti.unina.it>
On Sun, 3 Feb 2013 17:14:29 +0100
Antonio Ospite <ospite@studenti.unina.it> wrote:
> Hi,
>
> In patch 1 a device_set_trusted() function is proposed, which I plan to
> use for the playstation-peripheral plugin; I am in the process of
> rebasing the plugin on top of BlueZ 5.2.
>
> In patch 2 the newly introduced function is used in order to avoid some
> duplication.
>
> device_set_trusted() looks a lot like device_set_temporary() and
> device_set_legacy(), I hope it makes sense to you too.
>
> Thanks,
> Antonio
>
> Antonio Ospite (2):
> device: add a device_set_trusted() function
> device: use device_set_trusted() in set_trust()
>
Ping for these two patches.
> src/device.c | 30 +++++++++++++++++++-----------
> src/device.h | 1 +
> 2 files changed, 20 insertions(+), 11 deletions(-)
>
--
Antonio Ospite
http://ao2.it
A: Because it messes up the order in which people normally read text.
See http://en.wikipedia.org/wiki/Posting_style
Q: Why is top-posting such a bad thing?
^ permalink raw reply
* [PATCH BlueZ 13/13] unit: Add tests for sdp_get_server_ver()
From: Anderson Lizardo @ 2013-02-10 21:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1360531597-3506-1-git-send-email-anderson.lizardo@openbossa.org>
---
unit/test-sdp-lib.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 49 insertions(+)
diff --git a/unit/test-sdp-lib.c b/unit/test-sdp-lib.c
index 346942f..a7480c3 100644
--- a/unit/test-sdp-lib.c
+++ b/unit/test-sdp-lib.c
@@ -387,6 +387,53 @@ static void test_profile_desc_workaround(void)
sdp_record_free(rec);
}
+static void test_server_ver(void)
+{
+ uint16_t u16 = 0x1234;
+ uint32_t u32 = 0xdeadbeeb;
+ uint8_t dtd1 = SDP_UINT16, dtd2 = SDP_UINT32;
+ void *dtds1[] = { &dtd1 };
+ void *values1[] = { &u16 };
+ void *dtds2[] = { &dtd2 };
+ void *values2[] = { &u32 };
+ sdp_record_t *rec;
+ sdp_data_t *data;
+ sdp_list_t *list;
+ int err;
+
+ rec = sdp_record_alloc();
+
+ err = sdp_get_server_ver(rec, &list);
+ g_assert(err == -1 && errno == ENODATA);
+
+ /* Valid DTD */
+ data = sdp_seq_alloc(dtds1, values1, 1);
+ sdp_attr_add(rec, SDP_ATTR_VERSION_NUM_LIST, data);
+ err = sdp_get_server_ver(rec, &list);
+ g_assert(err == 0 && list != NULL);
+ sdp_list_free(list, NULL);
+
+ /* Invalid: UINT32 */
+ data = sdp_data_alloc(SDP_UINT32, &u32);
+ sdp_attr_replace(rec, SDP_ATTR_VERSION_NUM_LIST, data);
+ err = sdp_get_server_ver(rec, &list);
+ g_assert(err == -1 && errno == EINVAL);
+
+ /* Invalid: SEQ8() */
+ data = sdp_seq_alloc(NULL, NULL, 0);
+ sdp_attr_replace(rec, SDP_ATTR_VERSION_NUM_LIST, data);
+ err = sdp_get_server_ver(rec, &list);
+ g_assert(err == -1 && errno == EINVAL);
+
+ /* Invalid: SEQ8(UINT32) */
+ data = sdp_seq_alloc(dtds2, values2, 1);
+ sdp_attr_replace(rec, SDP_ATTR_VERSION_NUM_LIST, data);
+ err = sdp_get_server_ver(rec, &list);
+ g_assert(err == -1 && errno == EINVAL);
+
+ sdp_record_free(rec);
+}
+
int main(int argc, char *argv[])
{
g_test_init(&argc, &argv, NULL);
@@ -417,5 +464,7 @@ int main(int argc, char *argv[])
g_test_add_func("/sdp/lib/profile_desc/workaround",
test_profile_desc_workaround);
+ g_test_add_func("/sdp/lib/server_ver", test_server_ver);
+
return g_test_run();
}
--
1.7.9.5
^ permalink raw reply related
* [PATCH BlueZ 12/13] unit: Add tests for sdp_get_profile_descs()
From: Anderson Lizardo @ 2013-02-10 21:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1360531597-3506-1-git-send-email-anderson.lizardo@openbossa.org>
---
unit/test-sdp-lib.c | 171 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 171 insertions(+)
diff --git a/unit/test-sdp-lib.c b/unit/test-sdp-lib.c
index 51e5873..346942f 100644
--- a/unit/test-sdp-lib.c
+++ b/unit/test-sdp-lib.c
@@ -226,6 +226,167 @@ static void test_language_base_invalid_dtd(void)
sdp_record_free(rec);
}
+static void test_profile_desc_valid(void)
+{
+ sdp_profile_desc_t profile;
+ sdp_record_t *rec;
+ sdp_list_t *list;
+ int err;
+
+ rec = sdp_record_alloc();
+
+ sdp_uuid16_create(&profile.uuid, NAP_PROFILE_ID);
+ profile.version = 0x0100;
+ list = sdp_list_append(NULL, &profile);
+ err = sdp_set_profile_descs(rec, list);
+ sdp_list_free(list, NULL);
+ g_assert(err == 0);
+
+ list = NULL;
+ err = sdp_get_profile_descs(rec, &list);
+ sdp_list_free(list, free);
+ g_assert(err == 0 && list != NULL);
+
+ sdp_record_free(rec);
+}
+
+static void test_profile_desc_nodata(void)
+{
+ sdp_record_t *rec;
+ sdp_list_t *list;
+ int err;
+
+ rec = sdp_record_alloc();
+
+ err = sdp_get_profile_descs(rec, &list);
+ g_assert(err == -1 && errno == ENODATA);
+
+ sdp_record_free(rec);
+}
+
+static void test_profile_desc_invalid_dtd(void)
+{
+ uint8_t dtd1 = SDP_UUID16, dtd2 = SDP_UINT32;
+ uint32_t u32 = 0xdeadbeeb;
+ uint16_t u16 = 0x1234;
+ void *dtds[1], *values[1];
+ void *dtds2[] = { &dtd1, &dtd2 };
+ void *values2[] = { &u16, &u32 };
+ sdp_record_t *rec;
+ sdp_data_t *data;
+ sdp_list_t *list;
+ int err;
+
+ rec = sdp_record_alloc();
+
+ /* UINT32 */
+ data = sdp_data_alloc(SDP_UINT32, &u32);
+ g_assert(data != NULL);
+ sdp_attr_add(rec, SDP_ATTR_PFILE_DESC_LIST, data);
+ err = sdp_get_profile_descs(rec, &list);
+ g_assert(err == -1 && errno == EINVAL);
+
+ /* SEQ8() */
+ data = sdp_seq_alloc(NULL, NULL, 0);
+ sdp_attr_replace(rec, SDP_ATTR_PFILE_DESC_LIST, data);
+ err = sdp_get_profile_descs(rec, &list);
+ g_assert(err == -1 && errno == EINVAL);
+
+ /* SEQ8(UINT32) */
+ data = sdp_seq_alloc(&dtds2[1], &values2[1], 1);
+ sdp_attr_replace(rec, SDP_ATTR_PFILE_DESC_LIST, data);
+ err = sdp_get_profile_descs(rec, &list);
+ g_assert(err == -1 && errno == EINVAL);
+
+ /* SEQ8(SEQ8()) */
+ data = sdp_seq_alloc(NULL, NULL, 0);
+ dtds[0] = &data->dtd;
+ values[0] = data;
+ data = sdp_seq_alloc(dtds, values, 1);
+ sdp_attr_replace(rec, SDP_ATTR_PFILE_DESC_LIST, data);
+ err = sdp_get_profile_descs(rec, &list);
+ g_assert(err == -1 && errno == EINVAL);
+
+ /* SEQ8(SEQ8(UINT32)) */
+ data = sdp_seq_alloc(&dtds2[1], &values2[1], 1);
+ dtds[0] = &data->dtd;
+ values[0] = data;
+ data = sdp_seq_alloc(dtds, values, 1);
+ sdp_attr_replace(rec, SDP_ATTR_PFILE_DESC_LIST, data);
+ err = sdp_get_profile_descs(rec, &list);
+ g_assert(err == -1 && errno == EINVAL);
+
+ /* SEQ8(SEQ8(UUID16)) */
+ data = sdp_seq_alloc(dtds2, values2, 1);
+ dtds[0] = &data->dtd;
+ values[0] = data;
+ data = sdp_seq_alloc(dtds, values, 1);
+ sdp_attr_replace(rec, SDP_ATTR_PFILE_DESC_LIST, data);
+ err = sdp_get_profile_descs(rec, &list);
+ g_assert(err == -1 && errno == EINVAL);
+
+ /* SEQ8(SEQ8(UUID16, UINT32)) */
+ data = sdp_seq_alloc(dtds2, values2, 2);
+ dtds[0] = &data->dtd;
+ values[0] = data;
+ data = sdp_seq_alloc(dtds, values, 1);
+ sdp_attr_replace(rec, SDP_ATTR_PFILE_DESC_LIST, data);
+ err = sdp_get_profile_descs(rec, &list);
+ g_assert(err == -1 && errno == EINVAL);
+
+ sdp_record_free(rec);
+}
+
+static void test_profile_desc_workaround(void)
+{
+ uint8_t dtd1 = SDP_UUID16, dtd2 = SDP_UINT16, dtd3 = SDP_UINT32;
+ uint16_t u16 = 0x1234;
+ uint32_t u32 = 0xdeadbeeb;
+ void *dtds[] = { &dtd1, &dtd2 };
+ void *values[] = { &u16, &u16 };
+ void *dtds2[] = { &dtd1, &dtd3 };
+ void *values2[] = { &u16, &u32 };
+ sdp_record_t *rec;
+ sdp_data_t *data;
+ sdp_list_t *list;
+ int err;
+
+ rec = sdp_record_alloc();
+
+ /* SEQ8(UUID16) */
+ data = sdp_seq_alloc(dtds, values, 1);
+ sdp_attr_add(rec, SDP_ATTR_PFILE_DESC_LIST, data);
+ list = NULL;
+ err = sdp_get_profile_descs(rec, &list);
+ sdp_list_free(list, free);
+ g_assert(err == 0 && list != NULL);
+
+ /* SEQ8(UUID16, UINT16) */
+ data = sdp_seq_alloc(dtds, values, 2);
+ sdp_attr_replace(rec, SDP_ATTR_PFILE_DESC_LIST, data);
+ list = NULL;
+ err = sdp_get_profile_descs(rec, &list);
+ sdp_list_free(list, free);
+ g_assert(err == 0 && list != NULL);
+
+ /* SEQ8(UUID16) */
+ data = sdp_seq_alloc(dtds, values, 1);
+ sdp_attr_replace(rec, SDP_ATTR_PFILE_DESC_LIST, data);
+ list = NULL;
+ err = sdp_get_profile_descs(rec, &list);
+ sdp_list_free(list, free);
+ g_assert(err == 0 && list != NULL);
+
+ /* SEQ8(UUID16, UINT32) */
+ data = sdp_seq_alloc(dtds2, values2, 2);
+ sdp_attr_replace(rec, SDP_ATTR_PFILE_DESC_LIST, data);
+ list = NULL;
+ err = sdp_get_profile_descs(rec, &list);
+ g_assert(err == -1 && errno == EINVAL);
+
+ sdp_record_free(rec);
+}
+
int main(int argc, char *argv[])
{
g_test_init(&argc, &argv, NULL);
@@ -246,5 +407,15 @@ int main(int argc, char *argv[])
g_test_add_func("/sdp/lib/language_base/invalid_dtd",
test_language_base_invalid_dtd);
+ g_test_add_func("/sdp/lib/profile_desc/valid",
+ test_profile_desc_valid);
+ g_test_add_func("/sdp/lib/profile_desc/nodata",
+ test_profile_desc_nodata);
+ g_test_add_func("/sdp/lib/profile_desc/invalid_dtd",
+ test_profile_desc_invalid_dtd);
+ /* Test for workaround commented on sdp_get_profile_descs() */
+ g_test_add_func("/sdp/lib/profile_desc/workaround",
+ test_profile_desc_workaround);
+
return g_test_run();
}
--
1.7.9.5
^ permalink raw reply related
* [PATCH BlueZ 11/13] lib: Validate DTDs when parsing VersionNumberList
From: Anderson Lizardo @ 2013-02-10 21:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1360531597-3506-1-git-send-email-anderson.lizardo@openbossa.org>
---
lib/sdp.c | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/lib/sdp.c b/lib/sdp.c
index a8a4010..bb7dc6b 100644
--- a/lib/sdp.c
+++ b/lib/sdp.c
@@ -2155,9 +2155,24 @@ int sdp_get_server_ver(const sdp_record_t *rec, sdp_list_t **u16)
errno = ENODATA;
return -1;
}
- for (curr = d->val.dataseq; curr; curr = curr->next)
+
+ if (!SDP_IS_SEQ(d->dtd) || d->val.dataseq == NULL)
+ goto invalid;
+
+ for (curr = d->val.dataseq; curr; curr = curr->next) {
+ if (curr->dtd != SDP_UINT16)
+ goto invalid;
*u16 = sdp_list_append(*u16, &curr->val.uint16);
+ }
+
return 0;
+
+invalid:
+ sdp_list_free(*u16, NULL);
+ *u16 = NULL;
+ errno = EINVAL;
+
+ return -1;
}
/* flexible extraction of basic attributes - Jean II */
--
1.7.9.5
^ permalink raw reply related
* [PATCH BlueZ 10/13] lib: Add comment to BluetoothProfileDescriptorList parsing workaround
From: Anderson Lizardo @ 2013-02-10 21:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1360531597-3506-1-git-send-email-anderson.lizardo@openbossa.org>
Commits 0f5a5a9580084a3c4e0644ef5cd75689aeb5ff40 and
46b3a3d2d00bf70bc57ef0c9ad5542a2271e3350 introduced this workaround.
---
lib/sdp.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/lib/sdp.c b/lib/sdp.c
index c5bc16e..a8a4010 100644
--- a/lib/sdp.c
+++ b/lib/sdp.c
@@ -2091,6 +2091,11 @@ int sdp_get_profile_descs(const sdp_record_t *rec, sdp_list_t **profDescSeq)
uint16_t version = 0x100;
if (SDP_IS_UUID(seq->dtd)) {
+ /* Mac OS X 10.7.3 and old Samsung phones do not comply
+ * to the SDP specification for
+ * BluetoothProfileDescriptorList. This workaround
+ * allows to properly parse UUID/version from SDP
+ * record published by these systems. */
sdp_data_t *next = seq->next;
uuid = &seq->val.uuid;
if (next && next->dtd == SDP_UINT16) {
--
1.7.9.5
^ permalink raw reply related
* [PATCH BlueZ 09/13] lib: Validate DTDs when parsing BluetoothProfileDescriptorList
From: Anderson Lizardo @ 2013-02-10 21:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1360531597-3506-1-git-send-email-anderson.lizardo@openbossa.org>
The "seq->val.dataseq != NULL" check is also removed from the for()
statement because it should be done after verifying that the data
element is a sequence (inside the "if (SDP_IS_SEQ(...))" block.)
---
lib/sdp.c | 37 ++++++++++++++++++++++++++++---------
1 file changed, 28 insertions(+), 9 deletions(-)
diff --git a/lib/sdp.c b/lib/sdp.c
index ba55fc4..c5bc16e 100644
--- a/lib/sdp.c
+++ b/lib/sdp.c
@@ -2078,11 +2078,15 @@ int sdp_get_profile_descs(const sdp_record_t *rec, sdp_list_t **profDescSeq)
*profDescSeq = NULL;
sdpdata = sdp_data_get(rec, SDP_ATTR_PFILE_DESC_LIST);
- if (!sdpdata || !sdpdata->val.dataseq) {
+ if (sdpdata == NULL) {
errno = ENODATA;
return -1;
}
- for (seq = sdpdata->val.dataseq; seq && seq->val.dataseq; seq = seq->next) {
+
+ if (!SDP_IS_SEQ(sdpdata->dtd) || sdpdata->val.dataseq == NULL)
+ goto invalid;
+
+ for (seq = sdpdata->val.dataseq; seq; seq = seq->next) {
uuid_t *uuid = NULL;
uint16_t version = 0x100;
@@ -2094,13 +2098,21 @@ int sdp_get_profile_descs(const sdp_record_t *rec, sdp_list_t **profDescSeq)
seq = next;
}
} else if (SDP_IS_SEQ(seq->dtd)) {
- sdp_data_t *puuid = seq->val.dataseq;
- sdp_data_t *pVnum = seq->val.dataseq->next;
- if (puuid && pVnum) {
- uuid = &puuid->val.uuid;
- version = pVnum->val.uint16;
- }
- }
+ sdp_data_t *puuid, *pVnum;
+
+ puuid = seq->val.dataseq;
+ if (puuid == NULL || !SDP_IS_UUID(puuid->dtd))
+ goto invalid;
+
+ uuid = &puuid->val.uuid;
+
+ pVnum = puuid->next;
+ if (pVnum == NULL || pVnum->dtd != SDP_UINT16)
+ goto invalid;
+
+ version = pVnum->val.uint16;
+ } else
+ goto invalid;
if (uuid != NULL) {
profDesc = malloc(sizeof(sdp_profile_desc_t));
@@ -2119,6 +2131,13 @@ int sdp_get_profile_descs(const sdp_record_t *rec, sdp_list_t **profDescSeq)
}
}
return 0;
+
+invalid:
+ sdp_list_free(*profDescSeq, free);
+ *profDescSeq = NULL;
+ errno = EINVAL;
+
+ return -1;
}
int sdp_get_server_ver(const sdp_record_t *rec, sdp_list_t **u16)
--
1.7.9.5
^ permalink raw reply related
* [PATCH BlueZ 08/13] lib: Validate DTDs when parsing LanguageBaseAttributeIDList
From: Anderson Lizardo @ 2013-02-10 21:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1360531597-3506-1-git-send-email-anderson.lizardo@openbossa.org>
Also check if the required number of entries is present.
---
lib/sdp.c | 32 +++++++++++++++++++++++++-------
1 file changed, 25 insertions(+), 7 deletions(-)
diff --git a/lib/sdp.c b/lib/sdp.c
index 21dfe1b..ba55fc4 100644
--- a/lib/sdp.c
+++ b/lib/sdp.c
@@ -2019,19 +2019,30 @@ int sdp_get_lang_attr(const sdp_record_t *rec, sdp_list_t **langSeq)
errno = ENODATA;
return -1;
}
+
+ if (!SDP_IS_SEQ(sdpdata->dtd))
+ goto invalid;
curr_data = sdpdata->val.dataseq;
+
while (curr_data) {
- sdp_data_t *pCode = curr_data;
- sdp_data_t *pEncoding;
- sdp_data_t *pOffset;
+ sdp_data_t *pCode, *pEncoding, *pOffset;
+
+ pCode = curr_data;
+ if (pCode->dtd != SDP_UINT16)
+ goto invalid;
+
+ /* LanguageBaseAttributeIDList entries are always grouped as
+ * triplets */
+ if (!pCode->next || !pCode->next->next)
+ goto invalid;
pEncoding = pCode->next;
- if (!pEncoding)
- break;
+ if (pEncoding->dtd != SDP_UINT16)
+ goto invalid;
pOffset = pEncoding->next;
- if (!pOffset)
- break;
+ if (pOffset->dtd != SDP_UINT16)
+ goto invalid;
lang = malloc(sizeof(sdp_lang_attr_t));
if (!lang) {
@@ -2051,6 +2062,13 @@ int sdp_get_lang_attr(const sdp_record_t *rec, sdp_list_t **langSeq)
}
return 0;
+
+invalid:
+ sdp_list_free(*langSeq, free);
+ *langSeq = NULL;
+ errno = EINVAL;
+
+ return -1;
}
int sdp_get_profile_descs(const sdp_record_t *rec, sdp_list_t **profDescSeq)
--
1.7.9.5
^ permalink raw reply related
* [PATCH BlueZ 07/13] lib: Add missing DTD validation in sdp_record_print()
From: Anderson Lizardo @ 2013-02-10 21:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1360531597-3506-1-git-send-email-anderson.lizardo@openbossa.org>
---
lib/sdp.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/lib/sdp.c b/lib/sdp.c
index f65138c..21dfe1b 100644
--- a/lib/sdp.c
+++ b/lib/sdp.c
@@ -1603,13 +1603,13 @@ static void print_dataseq(sdp_data_t *p)
void sdp_record_print(const sdp_record_t *rec)
{
sdp_data_t *d = sdp_data_get(rec, SDP_ATTR_SVCNAME_PRIMARY);
- if (d)
+ if (d && SDP_IS_TEXT_STR(d->dtd))
printf("Service Name: %.*s\n", d->unitSize, d->val.str);
d = sdp_data_get(rec, SDP_ATTR_SVCDESC_PRIMARY);
- if (d)
+ if (d && SDP_IS_TEXT_STR(d->dtd))
printf("Service Description: %.*s\n", d->unitSize, d->val.str);
d = sdp_data_get(rec, SDP_ATTR_PROVNAME_PRIMARY);
- if (d)
+ if (d && SDP_IS_TEXT_STR(d->dtd))
printf("Service Provider: %.*s\n", d->unitSize, d->val.str);
}
--
1.7.9.5
^ permalink raw reply related
* [PATCH BlueZ 06/13] unit: Add tests for sdp_get_lang_attr()
From: Anderson Lizardo @ 2013-02-10 21:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1360531597-3506-1-git-send-email-anderson.lizardo@openbossa.org>
---
unit/test-sdp-lib.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 87 insertions(+)
diff --git a/unit/test-sdp-lib.c b/unit/test-sdp-lib.c
index f1f7c0e..51e5873 100644
--- a/unit/test-sdp-lib.c
+++ b/unit/test-sdp-lib.c
@@ -146,6 +146,86 @@ static void test_access_protos_invalid_dtd2(void)
sdp_record_free(rec);
}
+static void test_language_base_valid(void)
+{
+ sdp_record_t *rec;
+ sdp_list_t *list;
+ int err;
+
+ rec = sdp_record_alloc();
+ sdp_add_lang_attr(rec);
+
+ err = sdp_get_lang_attr(rec, &list);
+ g_assert(err == 0);
+
+ sdp_list_free(list, free);
+ sdp_record_free(rec);
+}
+
+static void test_language_base_nodata(void)
+{
+ sdp_record_t *rec;
+ sdp_list_t *list;
+ int err;
+
+ rec = sdp_record_alloc();
+
+ err = sdp_get_lang_attr(rec, &list);
+ g_assert(err == -1 && errno == ENODATA);
+
+ sdp_record_free(rec);
+}
+
+static void test_language_base_invalid_dtd(void)
+{
+ uint8_t dtd1 = SDP_UINT16, dtd2 = SDP_UINT32;
+ uint32_t u32 = 0xdeadbeeb;
+ uint16_t u16 = 0x1234;
+ void *dtds1[] = { &dtd1, &dtd2, &dtd2 };
+ void *values1[] = { &u16, &u32, &u32 };
+ void *dtds2[] = { &dtd1, &dtd1, &dtd2 };
+ void *values2[] = { &u16, &u16, &u32 };
+ sdp_record_t *rec;
+ sdp_data_t *data;
+ sdp_list_t *list;
+ int err;
+
+ rec = sdp_record_alloc();
+
+ /* UINT32 */
+ data = sdp_data_alloc(SDP_UINT32, &u32);
+ g_assert(data != NULL);
+ sdp_attr_add(rec, SDP_ATTR_LANG_BASE_ATTR_ID_LIST, data);
+ err = sdp_get_lang_attr(rec, &list);
+ g_assert(err == -1 && errno == EINVAL);
+
+ /* SEQ8(UINT32) */
+ data = sdp_seq_alloc(&dtds1[1], &values1[1], 1);
+ sdp_attr_replace(rec, SDP_ATTR_LANG_BASE_ATTR_ID_LIST, data);
+ err = sdp_get_lang_attr(rec, &list);
+ g_assert(err == -1 && errno == EINVAL);
+
+ /* SEQ8(UINT16, UINT16) */
+ data = sdp_seq_alloc(dtds2, values2, 2);
+ sdp_attr_replace(rec, SDP_ATTR_LANG_BASE_ATTR_ID_LIST, data);
+ err = sdp_get_lang_attr(rec, &list);
+ g_assert(err == -1 && errno == EINVAL);
+
+ /* SEQ8(UINT16, UINT32, UINT32) */
+ data = sdp_seq_alloc(dtds1, values1, 3);
+ sdp_attr_replace(rec, SDP_ATTR_LANG_BASE_ATTR_ID_LIST, data);
+ err = sdp_get_lang_attr(rec, &list);
+ g_assert(err == -1 && errno == EINVAL);
+
+ /* SEQ8(UINT16, UINT16, UINT32) */
+ data = sdp_seq_alloc(dtds2, values2, 3);
+ sdp_attr_replace(rec, SDP_ATTR_LANG_BASE_ATTR_ID_LIST, data);
+ err = sdp_get_lang_attr(rec, &list);
+ g_assert(err == -1 && errno == EINVAL);
+
+ sdp_record_free(rec);
+}
+
int main(int argc, char *argv[])
{
g_test_init(&argc, &argv, NULL);
@@ -159,5 +239,12 @@ int main(int argc, char *argv[])
g_test_add_func("/sdp/lib/access_protos/invalid_dtd2",
test_access_protos_invalid_dtd2);
+ g_test_add_func("/sdp/lib/language_base/valid",
+ test_language_base_valid);
+ g_test_add_func("/sdp/lib/language_base/nodata",
+ test_language_base_nodata);
+ g_test_add_func("/sdp/lib/language_base/invalid_dtd",
+ test_language_base_invalid_dtd);
+
return g_test_run();
}
--
1.7.9.5
^ permalink raw reply related
* [PATCH BlueZ 05/13] lib: Fix missing DTD validation while accessing SDP data elements
From: Anderson Lizardo @ 2013-02-10 21:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1360531597-3506-1-git-send-email-anderson.lizardo@openbossa.org>
It is necessary to validate the sdp_data_t "dtd" field before accessing
the "val" union members, specially when handling SDP_SEQ*, SDP_ALT* and
SDP_STR* elements, otherwise remote devices can trigger memory
corruption by passing invalid data elements where others are expected.
---
lib/sdp.c | 26 ++++++++++++++++++++++++--
1 file changed, 24 insertions(+), 2 deletions(-)
diff --git a/lib/sdp.c b/lib/sdp.c
index aa67f2a..f65138c 100644
--- a/lib/sdp.c
+++ b/lib/sdp.c
@@ -1874,19 +1874,41 @@ static int sdp_get_proto_descs(uint16_t attr_id, const sdp_record_t *rec,
SDPDBG("Attribute value type: 0x%02x\n", pdlist->dtd);
- if (attr_id == SDP_ATTR_ADD_PROTO_DESC_LIST)
+ if (attr_id == SDP_ATTR_ADD_PROTO_DESC_LIST) {
+ if (!SDP_IS_SEQ(pdlist->dtd)) {
+ errno = EINVAL;
+ return -1;
+ }
pdlist = pdlist->val.dataseq;
+ }
for (; pdlist; pdlist = pdlist->next) {
sdp_list_t *pds = NULL;
- for (curr = pdlist->val.dataseq; curr; curr = curr->next)
+
+ if (!SDP_IS_SEQ(pdlist->dtd) && !SDP_IS_ALT(pdlist->dtd))
+ goto failed;
+
+ for (curr = pdlist->val.dataseq; curr; curr = curr->next) {
+ if (!SDP_IS_SEQ(curr->dtd)) {
+ sdp_list_free(pds, NULL);
+ goto failed;
+ }
pds = sdp_list_append(pds, curr->val.dataseq);
+ }
+
ap = sdp_list_append(ap, pds);
}
*pap = ap;
return 0;
+
+failed:
+ sdp_list_foreach(ap, (sdp_list_func_t) sdp_list_free, NULL);
+ sdp_list_free(ap, NULL);
+ errno = EINVAL;
+
+ return -1;
}
int sdp_get_access_protos(const sdp_record_t *rec, sdp_list_t **pap)
--
1.7.9.5
^ permalink raw reply related
* [PATCH BlueZ 04/13] lib: Cleanup coding style in sdp_get_proto_descs()
From: Anderson Lizardo @ 2013-02-10 21:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1360531597-3506-1-git-send-email-anderson.lizardo@openbossa.org>
---
lib/sdp.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/lib/sdp.c b/lib/sdp.c
index c4afed7..aa67f2a 100644
--- a/lib/sdp.c
+++ b/lib/sdp.c
@@ -1864,25 +1864,28 @@ static int sdp_get_proto_descs(uint16_t attr_id, const sdp_record_t *rec,
sdp_list_t **pap)
{
sdp_data_t *pdlist, *curr;
- sdp_list_t *ap = 0;
+ sdp_list_t *ap = NULL;
pdlist = sdp_data_get(rec, attr_id);
if (pdlist == NULL) {
errno = ENODATA;
return -1;
}
- SDPDBG("AP type : 0%x\n", pdlist->dtd);
+
+ SDPDBG("Attribute value type: 0x%02x\n", pdlist->dtd);
if (attr_id == SDP_ATTR_ADD_PROTO_DESC_LIST)
pdlist = pdlist->val.dataseq;
for (; pdlist; pdlist = pdlist->next) {
- sdp_list_t *pds = 0;
+ sdp_list_t *pds = NULL;
for (curr = pdlist->val.dataseq; curr; curr = curr->next)
pds = sdp_list_append(pds, curr->val.dataseq);
ap = sdp_list_append(ap, pds);
}
+
*pap = ap;
+
return 0;
}
--
1.7.9.5
^ permalink raw reply related
* [PATCH BlueZ 03/13] lib: Reuse identical code in sdp_get_{add,}_access_protos()
From: Anderson Lizardo @ 2013-02-10 21:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1360531597-3506-1-git-send-email-anderson.lizardo@openbossa.org>
sdp_get_access_protos() and sdp_get_add_access_protos() do almost
exactly the same thing, except for an additional statement for the
latter.
---
lib/sdp.c | 34 ++++++++++++----------------------
1 file changed, 12 insertions(+), 22 deletions(-)
diff --git a/lib/sdp.c b/lib/sdp.c
index b87f392..c4afed7 100644
--- a/lib/sdp.c
+++ b/lib/sdp.c
@@ -1860,18 +1860,22 @@ sdp_data_t *sdp_get_proto_desc(sdp_list_t *list, int proto)
return NULL;
}
-int sdp_get_access_protos(const sdp_record_t *rec, sdp_list_t **pap)
+static int sdp_get_proto_descs(uint16_t attr_id, const sdp_record_t *rec,
+ sdp_list_t **pap)
{
sdp_data_t *pdlist, *curr;
sdp_list_t *ap = 0;
- pdlist = sdp_data_get(rec, SDP_ATTR_PROTO_DESC_LIST);
+ pdlist = sdp_data_get(rec, attr_id);
if (pdlist == NULL) {
errno = ENODATA;
return -1;
}
SDPDBG("AP type : 0%x\n", pdlist->dtd);
+ if (attr_id == SDP_ATTR_ADD_PROTO_DESC_LIST)
+ pdlist = pdlist->val.dataseq;
+
for (; pdlist; pdlist = pdlist->next) {
sdp_list_t *pds = 0;
for (curr = pdlist->val.dataseq; curr; curr = curr->next)
@@ -1882,28 +1886,14 @@ int sdp_get_access_protos(const sdp_record_t *rec, sdp_list_t **pap)
return 0;
}
-int sdp_get_add_access_protos(const sdp_record_t *rec, sdp_list_t **pap)
+int sdp_get_access_protos(const sdp_record_t *rec, sdp_list_t **pap)
{
- sdp_data_t *pdlist, *curr;
- sdp_list_t *ap = 0;
-
- pdlist = sdp_data_get(rec, SDP_ATTR_ADD_PROTO_DESC_LIST);
- if (pdlist == NULL) {
- errno = ENODATA;
- return -1;
- }
- SDPDBG("AP type : 0%x\n", pdlist->dtd);
-
- pdlist = pdlist->val.dataseq;
+ return sdp_get_proto_descs(SDP_ATTR_PROTO_DESC_LIST, rec, pap);
+}
- for (; pdlist; pdlist = pdlist->next) {
- sdp_list_t *pds = 0;
- for (curr = pdlist->val.dataseq; curr; curr = curr->next)
- pds = sdp_list_append(pds, curr->val.dataseq);
- ap = sdp_list_append(ap, pds);
- }
- *pap = ap;
- return 0;
+int sdp_get_add_access_protos(const sdp_record_t *rec, sdp_list_t **pap)
+{
+ return sdp_get_proto_descs(SDP_ATTR_ADD_PROTO_DESC_LIST, rec, pap);
}
int sdp_get_uuidseq_attr(const sdp_record_t *rec, uint16_t attr,
--
1.7.9.5
^ permalink raw reply related
* [PATCH BlueZ 02/13] lib: Add SDP_IS_ALT() macro
From: Anderson Lizardo @ 2013-02-10 21:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1360531597-3506-1-git-send-email-anderson.lizardo@openbossa.org>
This macro will simplify internal SDP library code, and is similar to
the existing SDP_IS_SEQ() macro.
---
lib/sdp.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/sdp.h b/lib/sdp.h
index a81e857..baae15f 100644
--- a/lib/sdp.h
+++ b/lib/sdp.h
@@ -440,6 +440,7 @@ typedef struct {
#define SDP_IS_UUID(x) ((x) == SDP_UUID16 || (x) == SDP_UUID32 || \
(x) == SDP_UUID128)
+#define SDP_IS_ALT(x) ((x) == SDP_ALT8 || (x) == SDP_ALT16 || (x) == SDP_ALT32)
#define SDP_IS_SEQ(x) ((x) == SDP_SEQ8 || (x) == SDP_SEQ16 || (x) == SDP_SEQ32)
#define SDP_IS_TEXT_STR(x) ((x) == SDP_TEXT_STR8 || (x) == SDP_TEXT_STR16 || \
(x) == SDP_TEXT_STR32)
--
1.7.9.5
^ permalink raw reply related
* [PATCH BlueZ 01/13] unit: Add initial SDP library unit tests
From: Anderson Lizardo @ 2013-02-10 21:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1360531597-3506-1-git-send-email-anderson.lizardo@openbossa.org>
These tests will cover all public SDP library API not covered yet by the
tests in test-sdp.c (which focus on the SDP server).
---
.gitignore | 1 +
Makefile.am | 5 +-
unit/test-sdp-lib.c | 163 +++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 168 insertions(+), 1 deletion(-)
create mode 100644 unit/test-sdp-lib.c
diff --git a/.gitignore b/.gitignore
index b818659..55d6011 100644
--- a/.gitignore
+++ b/.gitignore
@@ -65,6 +65,7 @@ unit/test-uuid
unit/test-textfile
unit/test-gdbus-client
unit/test-sdp
+unit/test-sdp-lib
unit/test-mgmt
tools/mgmt-tester
tools/gap-tester
diff --git a/Makefile.am b/Makefile.am
index 5ebf5e6..fec73ea 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -234,7 +234,7 @@ unit_test_mgmt_SOURCES = unit/test-mgmt.c \
src/shared/mgmt.h src/shared/mgmt.c
unit_test_mgmt_LDADD = @GLIB_LIBS@
-unit_tests += unit/test-sdp
+unit_tests += unit/test-sdp unit/test-sdp-lib
unit_test_sdp_SOURCES = unit/test-sdp.c \
src/shared/util.h src/shared/util.c \
@@ -242,6 +242,9 @@ unit_test_sdp_SOURCES = unit/test-sdp.c \
src/sdpd-service.c src/sdpd-request.c
unit_test_sdp_LDADD = lib/libbluetooth-private.la @GLIB_LIBS@
+unit_test_sdp_lib_SOURCES = unit/test-sdp-lib.c
+unit_test_sdp_lib_LDADD = lib/libbluetooth-private.la @GLIB_LIBS@
+
unit_tests += unit/test-gdbus-client
unit_test_gdbus_client_SOURCES = $(gdbus_sources) unit/test-gdbus-client.c
diff --git a/unit/test-sdp-lib.c b/unit/test-sdp-lib.c
new file mode 100644
index 0000000..f1f7c0e
--- /dev/null
+++ b/unit/test-sdp-lib.c
@@ -0,0 +1,163 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2013 Intel Corporation. All rights reserved.
+ * Copyright (C) 2013 Instituto Nokia de Tecnologia - INdT
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "lib/sdp.h"
+#include "lib/sdp_lib.h"
+
+static void test_access_protos_valid(void)
+{
+ sdp_record_t *rec;
+ sdp_list_t *aproto, *apseq, *proto[2];
+ const uint8_t u8 = 1;
+ uuid_t l2cap, rfcomm;
+ sdp_data_t *channel;
+ int err;
+
+ rec = sdp_record_alloc();
+ sdp_uuid16_create(&l2cap, L2CAP_UUID);
+ proto[0] = sdp_list_append(NULL, &l2cap);
+ apseq = sdp_list_append(NULL, proto[0]);
+
+ sdp_uuid16_create(&rfcomm, RFCOMM_UUID);
+ proto[1] = sdp_list_append(NULL, &rfcomm);
+ channel = sdp_data_alloc(SDP_UINT8, &u8);
+ proto[1] = sdp_list_append(proto[1], channel);
+ apseq = sdp_list_append(apseq, proto[1]);
+
+ aproto = sdp_list_append(NULL, apseq);
+ sdp_set_access_protos(rec, aproto);
+ sdp_set_add_access_protos(rec, aproto);
+ sdp_data_free(channel);
+ sdp_list_free(proto[0], NULL);
+ sdp_list_free(proto[1], NULL);
+ sdp_list_free(apseq, NULL);
+ sdp_list_free(aproto, NULL);
+
+ err = sdp_get_access_protos(rec, &aproto);
+ g_assert(err == 0);
+ sdp_list_foreach(aproto, (sdp_list_func_t) sdp_list_free, NULL);
+ sdp_list_free(aproto, NULL);
+
+ err = sdp_get_add_access_protos(rec, &aproto);
+ g_assert(err == 0);
+ sdp_list_foreach(aproto, (sdp_list_func_t) sdp_list_free, NULL);
+ sdp_list_free(aproto, NULL);
+
+ sdp_record_free(rec);
+}
+
+static void test_access_protos_nodata(void)
+{
+ sdp_record_t *rec;
+ sdp_list_t *aproto;
+ int err;
+
+ rec = sdp_record_alloc();
+
+ err = sdp_get_access_protos(rec, &aproto);
+ g_assert(err == -1 && errno == ENODATA);
+
+ err = sdp_get_add_access_protos(rec, &aproto);
+ g_assert(err == -1 && errno == ENODATA);
+
+ sdp_record_free(rec);
+}
+
+static void test_access_protos_invalid_dtd1(void)
+{
+ const uint32_t u32 = 0xdeadbeeb;
+ sdp_record_t *rec;
+ sdp_list_t *aproto;
+ sdp_data_t *data;
+ int err;
+
+ rec = sdp_record_alloc();
+
+ data = sdp_data_alloc(SDP_UINT32, &u32);
+ g_assert(data != NULL);
+ sdp_attr_replace(rec, SDP_ATTR_PROTO_DESC_LIST, data);
+
+ err = sdp_get_access_protos(rec, &aproto);
+ g_assert(err == -1 && errno == EINVAL);
+
+ data = sdp_data_alloc(SDP_UINT32, &u32);
+ g_assert(data != NULL);
+ sdp_attr_replace(rec, SDP_ATTR_ADD_PROTO_DESC_LIST, data);
+
+ err = sdp_get_add_access_protos(rec, &aproto);
+ g_assert(err == -1 && errno == EINVAL);
+
+ sdp_record_free(rec);
+}
+
+static void test_access_protos_invalid_dtd2(void)
+{
+ uint8_t dtd = SDP_UINT8, u8 = 0xff;
+ void *dtds = &dtd, *values = &u8;
+ sdp_record_t *rec;
+ sdp_list_t *aproto;
+ sdp_data_t *data;
+ int err;
+
+ rec = sdp_record_alloc();
+
+ data = sdp_seq_alloc(&dtds, &values, 1);
+ g_assert(data != NULL);
+ sdp_attr_replace(rec, SDP_ATTR_PROTO_DESC_LIST, data);
+
+ err = sdp_get_access_protos(rec, &aproto);
+ g_assert(err == -1 && errno == EINVAL);
+
+ data = sdp_seq_alloc(&dtds, &values, 1);
+ g_assert(data != NULL);
+ sdp_attr_replace(rec, SDP_ATTR_ADD_PROTO_DESC_LIST, data);
+
+ err = sdp_get_add_access_protos(rec, &aproto);
+ g_assert(err == -1 && errno == EINVAL);
+
+ sdp_record_free(rec);
+}
+
+int main(int argc, char *argv[])
+{
+ g_test_init(&argc, &argv, NULL);
+
+ g_test_add_func("/sdp/lib/access_protos/valid",
+ test_access_protos_valid);
+ g_test_add_func("/sdp/lib/access_protos/nodata",
+ test_access_protos_nodata);
+ g_test_add_func("/sdp/lib/access_protos/invalid_dtd1",
+ test_access_protos_invalid_dtd1);
+ g_test_add_func("/sdp/lib/access_protos/invalid_dtd2",
+ test_access_protos_invalid_dtd2);
+
+ return g_test_run();
+}
--
1.7.9.5
^ permalink raw reply related
* [PATCH BlueZ 00/13] Fix SDP DE Type Descriptor validation issues
From: Anderson Lizardo @ 2013-02-10 21:26 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Anderson Lizardo
Hi,
This series adds various missing DTD validations, specially for SEQ* types. The
lack of these validations allows for a remote device to crash BlueZ due to
invalid memory access.
I also added unit tests for all affected functions. They are in a separate C
file (unit/test-sdp-lib.c), which can contain tests for SDP library API that is
not covered by SDP server tests in unit/test-sdp.c. It also contains various
tests for corner cases that increase code coverage (as measured by gcov/lcov).
The only pending related fixes from my part are some missing NULL pointer
checks when accessing empty sequences. These will take some time to fix as they
affect profile code as well.
Best Regards,
Anderson Lizardo (13):
unit: Add initial SDP library unit tests
lib: Add SDP_IS_ALT() macro
lib: Reuse identical code in sdp_get_{add,}_access_protos()
lib: Cleanup coding style in sdp_get_proto_descs()
lib: Fix missing DTD validation while accessing SDP data elements
unit: Add tests for sdp_get_lang_attr()
lib: Add missing DTD validation in sdp_record_print()
lib: Validate DTDs when parsing LanguageBaseAttributeIDList
lib: Validate DTDs when parsing BluetoothProfileDescriptorList
lib: Add comment to BluetoothProfileDescriptorList parsing workaround
lib: Validate DTDs when parsing VersionNumberList
unit: Add tests for sdp_get_profile_descs()
unit: Add tests for sdp_get_server_ver()
.gitignore | 1 +
Makefile.am | 5 +-
lib/sdp.c | 164 +++++++++++++-----
lib/sdp.h | 1 +
unit/test-sdp-lib.c | 470 +++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 594 insertions(+), 47 deletions(-)
create mode 100644 unit/test-sdp-lib.c
--
1.7.9.5
^ permalink raw reply
* [PATCHv2 BlueZ 2/2] configure.ac: call AC_SUBST(*_CFLAGS) and AC_SUBST(*_LIBS) only when needed
From: Antonio Ospite @ 2013-02-10 21:20 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Marcel Holtmann, Antonio Ospite
In-Reply-To: <1360531251-18371-1-git-send-email-ospite@studenti.unina.it>
Bring AC_SUBST(*_CFLAGS) and AC_SUBST(*_LIBS) in the same block of the
corresponding PKG_CHECK_MODULES() call.
Having these variables defined outside of the if tests is more than what
is needed as the corresponding PKG_CHECK_MODULES() might not have been
called at all there.
This is the same logic already used for USB_CFLAGS and USB_LIBS.
---
configure.ac | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/configure.ac b/configure.ac
index b11dcf1..4ac8a78 100644
--- a/configure.ac
+++ b/configure.ac
@@ -140,12 +140,12 @@ AC_ARG_ENABLE(udev, AC_HELP_STRING([--disable-udev],
if (test "${enable_tools}" != "no" && test "${enable_udev}" != "no"); then
PKG_CHECK_MODULES(UDEV, libudev >= 143, dummy=yes,
AC_MSG_ERROR(libudev >= 143 is required))
+ AC_SUBST(UDEV_CFLAGS)
+ AC_SUBST(UDEV_LIBS)
AC_CHECK_LIB(udev, udev_hwdb_new,
AC_DEFINE(HAVE_UDEV_HWDB_NEW, 1,
[Define to 1 if you have the udev_hwdb_new() function.]))
fi
-AC_SUBST(UDEV_CFLAGS)
-AC_SUBST(UDEV_LIBS)
AM_CONDITIONAL(UDEV, test "${enable_udev}" != "no")
AC_ARG_WITH([udevdir], AC_HELP_STRING([--with-udevdir=DIR],
@@ -172,9 +172,9 @@ AC_ARG_ENABLE(obex, AC_HELP_STRING([--disable-obex],
if (test "${enable_obex}" != "no"); then
PKG_CHECK_MODULES(ICAL, libical, dummy=yes,
AC_MSG_ERROR(libical is required))
+ AC_SUBST(ICAL_CFLAGS)
+ AC_SUBST(ICAL_LIBS)
fi
-AC_SUBST(ICAL_CFLAGS)
-AC_SUBST(ICAL_LIBS)
AM_CONDITIONAL(OBEX, test "${enable_obex}" != "no")
AC_ARG_ENABLE(client, AC_HELP_STRING([--disable-client],
--
1.7.10.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox