Module Name: src
Committed By: plunky
Date: Tue May 12 21:50:38 UTC 2009
Modified Files:
src/usr.sbin/btpand: Makefile btpand.c btpand.h client.c server.c
Removed Files:
src/usr.sbin/btpand: sdp.c sdp.h
Log Message:
update to use the new Service Discovery API
To generate a diff of this commit:
cvs rdiff -u -r1.4 -r1.5 src/usr.sbin/btpand/Makefile
cvs rdiff -u -r1.3 -r1.4 src/usr.sbin/btpand/btpand.c \
src/usr.sbin/btpand/client.c src/usr.sbin/btpand/server.c
cvs rdiff -u -r1.2 -r1.3 src/usr.sbin/btpand/btpand.h
cvs rdiff -u -r1.2 -r0 src/usr.sbin/btpand/sdp.c src/usr.sbin/btpand/sdp.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/usr.sbin/btpand/Makefile
diff -u src/usr.sbin/btpand/Makefile:1.4 src/usr.sbin/btpand/Makefile:1.5
--- src/usr.sbin/btpand/Makefile:1.4 Tue May 12 13:11:18 2009
+++ src/usr.sbin/btpand/Makefile Tue May 12 21:50:38 2009
@@ -1,13 +1,11 @@
-# $NetBSD: Makefile,v 1.4 2009/05/12 13:11:18 plunky Exp $
+# $NetBSD: Makefile,v 1.5 2009/05/12 21:50:38 plunky Exp $
#
PROG= btpand
MAN= btpand.8
-SRCS= btpand.c bnep.c channel.c client.c packet.c server.c sdp.c tap.c
+SRCS= btpand.c bnep.c channel.c client.c packet.c server.c tap.c
DPADD+= ${LIBBLUETOOTH} ${LIBEVENT} ${LIBUTIL}
LDADD+= -lbluetooth -levent -lutil
-CPPFLAGS+= -DSDP_COMPAT
-
.include <bsd.prog.mk>
Index: src/usr.sbin/btpand/btpand.c
diff -u src/usr.sbin/btpand/btpand.c:1.3 src/usr.sbin/btpand/btpand.c:1.4
--- src/usr.sbin/btpand/btpand.c:1.3 Tue May 12 21:08:30 2009
+++ src/usr.sbin/btpand/btpand.c Tue May 12 21:50:38 2009
@@ -1,7 +1,7 @@
-/* $NetBSD: btpand.c,v 1.3 2009/05/12 21:08:30 plunky Exp $ */
+/* $NetBSD: btpand.c,v 1.4 2009/05/12 21:50:38 plunky Exp $ */
/*-
- * Copyright (c) 2008 Iain Hibbert
+ * Copyright (c) 2008-2009 Iain Hibbert
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,8 +26,8 @@
*/
#include <sys/cdefs.h>
-__COPYRIGHT("@(#) Copyright (c) 2008 Iain Hibbert. All rights reserved.");
-__RCSID("$NetBSD: btpand.c,v 1.3 2009/05/12 21:08:30 plunky Exp $");
+__COPYRIGHT("@(#) Copyright (c) 2008-2009 Iain Hibbert. All rights reserved.");
+__RCSID("$NetBSD: btpand.c,v 1.4 2009/05/12 21:50:38 plunky Exp $");
#include <sys/wait.h>
@@ -47,24 +47,35 @@
/* global variables */
const char * control_path; /* -c <path> */
const char * interface_name; /* -i <ifname> */
-const char * service_name; /* -s <service> */
+const char * service_type; /* -s <service> */
uint16_t service_class;
+const char * service_name;
+const char * service_desc;
bdaddr_t local_bdaddr; /* -d <addr> */
bdaddr_t remote_bdaddr; /* -a <addr> */
uint16_t l2cap_psm; /* -p <psm> */
int l2cap_mode; /* -m <mode> */
-
int server_limit; /* -n <limit> */
static const struct {
- const char * name;
+ const char * type;
uint16_t class;
+ const char * name;
const char * desc;
} services[] = {
- { "PANU", SDP_SERVICE_CLASS_PANU, "Personal Area Networking User" },
- { "NAP", SDP_SERVICE_CLASS_NAP, "Network Acess Point" },
- { "GN", SDP_SERVICE_CLASS_GN, "Group Network" },
+ { "PANU", SDP_SERVICE_CLASS_PANU,
+ "Personal Ad-hoc User Service",
+ "Personal Ad-hoc User Service"
+ },
+ { "NAP", SDP_SERVICE_CLASS_NAP,
+ "Network Acess Point",
+ "Personal Ad-hoc Network Service"
+ },
+ { "GN", SDP_SERVICE_CLASS_GN,
+ "Group Ad-hoc Network",
+ "Personal Group Ad-hoc Network Service"
+ },
};
static void main_exit(int);
@@ -139,18 +150,21 @@
|| ul > 0xffff || L2CAP_PSM_INVALID(ul))
errx(EXIT_FAILURE, "%s: invalid PSM", optarg);
- l2cap_psm = ul;
+ l2cap_psm = (uint16_t)ul;
break;
case 's': /* service */
case 'S': /* service (no SDP) */
- for (ul = 0; strcasecmp(optarg, services[ul].name); ul++) {
+ for (ul = 0; strcasecmp(optarg, services[ul].type); ul++) {
if (ul == __arraycount(services))
errx(EXIT_FAILURE, "%s: unknown service", optarg);
}
- if (ch == 's')
+ if (ch == 's') {
+ service_type = services[ul].type;
service_name = services[ul].name;
+ service_desc = services[ul].desc;
+ }
service_class = services[ul].class;
break;
@@ -169,7 +183,7 @@
usage();
if (!bdaddr_any(&remote_bdaddr) && (server_limit != 0 ||
- control_path != 0 || (service_name != NULL && l2cap_psm != 0)))
+ control_path != 0 || (service_type != NULL && l2cap_psm != 0)))
usage();
/* default options */
@@ -261,7 +275,7 @@
usage(void)
{
const char *p = getprogname();
- int n = strlen(p);
+ size_t n = strlen(p);
fprintf(stderr,
"usage: %s [-i ifname] [-m mode] -a address -d device\n"
@@ -283,8 +297,8 @@
"Known services:\n"
"", p, n, "", p, n, "");
- for (n = 0; n < (int)__arraycount(services); n++)
- fprintf(stderr, "\t%s\t%s\n", services[n].name, services[n].desc);
+ for (n = 0; n < __arraycount(services); n++)
+ fprintf(stderr, "\t%s\t%s\n", services[n].type, services[n].name);
exit(EXIT_FAILURE);
}
Index: src/usr.sbin/btpand/client.c
diff -u src/usr.sbin/btpand/client.c:1.3 src/usr.sbin/btpand/client.c:1.4
--- src/usr.sbin/btpand/client.c:1.3 Tue May 12 21:08:30 2009
+++ src/usr.sbin/btpand/client.c Tue May 12 21:50:38 2009
@@ -1,7 +1,7 @@
-/* $NetBSD: client.c,v 1.3 2009/05/12 21:08:30 plunky Exp $ */
+/* $NetBSD: client.c,v 1.4 2009/05/12 21:50:38 plunky Exp $ */
/*-
- * Copyright (c) 2008 Iain Hibbert
+ * Copyright (c) 2008-2009 Iain Hibbert
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: client.c,v 1.3 2009/05/12 21:08:30 plunky Exp $");
+__RCSID("$NetBSD: client.c,v 1.4 2009/05/12 21:50:38 plunky Exp $");
#include <bluetooth.h>
#include <errno.h>
@@ -35,7 +35,6 @@
#include "btpand.h"
#include "bnep.h"
-#include "sdp.h"
static void client_down(channel_t *);
static void client_query(void);
@@ -52,7 +51,7 @@
if (bdaddr_any(&remote_bdaddr))
return;
- if (service_name)
+ if (service_type)
client_query();
fd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
@@ -144,64 +143,83 @@
static void
client_query(void)
{
- uint8_t buffer[512];
- sdp_attr_t attr;
- uint32_t range;
- void *ss;
- int rv;
- uint8_t *seq0, *seq1;
-
- attr.flags = SDP_ATTR_INVALID;
- attr.attr = 0;
- attr.vlen = sizeof(buffer);
- attr.value = buffer;
-
- range = SDP_ATTR_RANGE(SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST,
- SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST);
+ uint8_t buf[12]; /* enough for SSP and AIL both */
+ sdp_session_t ss;
+ sdp_data_t ssp, ail, rsp, rec, value, pdl, seq;
+ uintmax_t psm;
+ uint16_t attr;
+ bool rv;
ss = sdp_open(&local_bdaddr, &remote_bdaddr);
- if (ss == NULL || (errno = sdp_error(ss)) != 0) {
- log_err("%s: %m", service_name);
+ if (ss == NULL) {
+ log_err("%s: %m", service_type);
exit(EXIT_FAILURE);
}
log_info("Searching for %s service at %s",
- service_name, bt_ntoa(&remote_bdaddr, NULL));
+ service_type, bt_ntoa(&remote_bdaddr, NULL));
- rv = sdp_search(ss, 1, &service_class, 1, &range, 1, &attr);
- if (rv != 0) {
- log_err("%s: %s", service_name, strerror(sdp_error(ss)));
- exit(EXIT_FAILURE);
- }
+ seq.next = buf;
+ seq.end = buf + sizeof(buf);
- sdp_close(ss);
+ /*
+ * build ServiceSearchPattern (9 bytes)
+ *
+ * uuid16 "service_class"
+ * uuid16 L2CAP
+ * uuid16 BNEP
+ */
+ ssp.next = seq.next;
+ sdp_put_uuid16(&seq, service_class);
+ sdp_put_uuid16(&seq, SDP_UUID_PROTOCOL_L2CAP);
+ sdp_put_uuid16(&seq, SDP_UUID_PROTOCOL_BNEP);
+ ssp.end = seq.next;
- if (attr.flags != SDP_ATTR_OK
- || attr.attr != SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST) {
- log_err("%s service not found", service_name);
+ /*
+ * build AttributeIDList (3 bytes)
+ *
+ * uint16 ProtocolDescriptorList
+ */
+ ail.next = seq.next;
+ sdp_put_uint16(&seq, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST);
+ ail.end = seq.next;
+
+ rv = sdp_service_search_attribute(ss, &ssp, &ail, &rsp);
+ if (!rv) {
+ log_err("%s: %m", service_type);
exit(EXIT_FAILURE);
}
/*
- * we expect the following protocol descriptor list
- *
- * seq len
- * seq len
- * uuid value == L2CAP
- * uint16 value16 => PSM
- * seq len
- * uuid value == BNEP
+ * we expect the response to contain a list of records
+ * containing a ProtocolDescriptorList. Find the first
+ * one containing L2CAP and BNEP protocols and extract
+ * the PSM.
*/
- if (_sdp_get_seq(&attr.value, attr.value + attr.vlen, &seq0)
- && _sdp_get_seq(&seq0, attr.value, &seq1)
- && _sdp_match_uuid16(&seq1, seq0, SDP_UUID_PROTOCOL_L2CAP)
- && _sdp_get_uint16(&seq1, seq0, &l2cap_psm)
- && _sdp_get_seq(&seq0, attr.value, &seq1)
- && _sdp_match_uuid16(&seq1, seq0, SDP_UUID_PROTOCOL_BNEP)) {
- log_info("Found PSM %d for service %s", l2cap_psm, service_name);
- return;
+ rv = false;
+ while (!rv && sdp_get_seq(&rsp, &rec)) {
+ if (!sdp_get_attr(&rec, &attr, &value)
+ || attr != SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST)
+ continue;
+
+ sdp_get_alt(&value, &value); /* drop any alt header */
+ while (!rv && sdp_get_seq(&value, &pdl)) {
+ if (sdp_get_seq(&pdl, &seq)
+ && sdp_match_uuid16(&seq, SDP_UUID_PROTOCOL_L2CAP)
+ && sdp_get_uint(&seq, &psm)
+ && sdp_get_seq(&pdl, &seq)
+ && sdp_match_uuid16(&seq, SDP_UUID_PROTOCOL_BNEP))
+ rv = true;
+ }
}
- log_err("%s query failed", service_name);
- exit(EXIT_FAILURE);
+ sdp_close(ss);
+
+ if (!rv) {
+ log_err("%s query failed", service_type);
+ exit(EXIT_FAILURE);
+ }
+
+ l2cap_psm = (uint16_t)psm;
+ log_info("Found PSM %u for service %s", l2cap_psm, service_type);
}
Index: src/usr.sbin/btpand/server.c
diff -u src/usr.sbin/btpand/server.c:1.3 src/usr.sbin/btpand/server.c:1.4
--- src/usr.sbin/btpand/server.c:1.3 Tue May 12 21:08:30 2009
+++ src/usr.sbin/btpand/server.c Tue May 12 21:50:38 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: server.c,v 1.3 2009/05/12 21:08:30 plunky Exp $ */
+/* $NetBSD: server.c,v 1.4 2009/05/12 21:50:38 plunky Exp $ */
/*-
* Copyright (c) 2008-2009 Iain Hibbert
@@ -26,10 +26,12 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: server.c,v 1.3 2009/05/12 21:08:30 plunky Exp $");
+__RCSID("$NetBSD: server.c,v 1.4 2009/05/12 21:50:38 plunky Exp $");
#include <sys/ioctl.h>
+#include <net/ethertypes.h>
+
#include <bluetooth.h>
#include <errno.h>
#include <sdp.h>
@@ -41,13 +43,20 @@
static struct event server_ev;
static int server_count;
-static void * server_ss;
+static sdp_session_t server_ss;
static uint32_t server_handle;
+static sdp_data_t server_record;
+
+static char * server_ipv4_subnet;
+static char * server_ipv6_subnet;
+static uint16_t server_proto[] = { ETHERTYPE_IP, ETHERTYPE_ARP, ETHERTYPE_IPV6 };
+static size_t server_nproto = __arraycount(server_proto);
static void server_open(void);
static void server_read(int, short, void *);
static void server_down(channel_t *);
static void server_update(void);
+static void server_mkrecord(void);
void
server_init(void)
@@ -247,35 +256,114 @@
static void
server_update(void)
{
- sdp_nap_profile_t p;
- int rv;
+ bool rv;
- if (service_name == NULL)
+ if (service_type == NULL)
return;
if (server_ss == NULL) {
server_ss = sdp_open_local(control_path);
- if (server_ss == NULL || sdp_error(server_ss) != 0) {
+ if (server_ss == NULL) {
log_err("failed to contact SDP server");
return;
}
}
- memset(&p, 0, sizeof(p));
- p.psm = l2cap_psm;
- p.load_factor = (UINT8_MAX - server_count * UINT8_MAX / server_limit);
- p.security_description = (l2cap_mode == 0 ? 0x0000 : 0x0001);
-
- if (server_handle)
- rv = sdp_change_service(server_ss, server_handle,
- (uint8_t *)&p, sizeof(p));
+ server_mkrecord();
+
+ if (server_handle == 0)
+ rv = sdp_record_insert(server_ss, &local_bdaddr,
+ &server_handle, &server_record);
else
- rv = sdp_register_service(server_ss, service_class,
- &local_bdaddr, (uint8_t *)&p, sizeof(p), &server_handle);
+ rv = sdp_record_update(server_ss, server_handle,
+ &server_record);
- if (rv != 0) {
- errno = sdp_error(server_ss);
- log_err("%s: %m", service_name);
+ if (!rv) {
+ log_err("%s: %m", service_type);
exit(EXIT_FAILURE);
}
}
+
+static void
+server_mkrecord(void)
+{
+ static uint8_t data[256]; /* tis enough */
+ sdp_data_t buf;
+ size_t i;
+
+ buf.next = data;
+ buf.end = data + sizeof(data);
+
+ sdp_put_uint16(&buf, SDP_ATTR_SERVICE_RECORD_HANDLE);
+ sdp_put_uint32(&buf, 0x00000000);
+
+ sdp_put_uint16(&buf, SDP_ATTR_SERVICE_CLASS_ID_LIST);
+ sdp_put_seq(&buf, 3);
+ sdp_put_uuid16(&buf, service_class);
+
+ sdp_put_uint16(&buf, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST);
+ sdp_put_seq(&buf, 8 + 10 + 3 * server_nproto);
+ sdp_put_seq(&buf, 6);
+ sdp_put_uuid16(&buf, SDP_UUID_PROTOCOL_L2CAP);
+ sdp_put_uint16(&buf, l2cap_psm);
+ sdp_put_seq(&buf, 8 + 3 * server_nproto);
+ sdp_put_uuid16(&buf, SDP_UUID_PROTOCOL_BNEP);
+ sdp_put_uint16(&buf, 0x0100); /* v1.0 */
+ sdp_put_seq(&buf, 3 * server_nproto);
+ for (i = 0; i < server_nproto; i++)
+ sdp_put_uint16(&buf, server_proto[i]);
+
+ sdp_put_uint16(&buf, SDP_ATTR_BROWSE_GROUP_LIST);
+ sdp_put_seq(&buf, 3);
+ sdp_put_uuid16(&buf, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP);
+
+ sdp_put_uint16(&buf, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST);
+ sdp_put_seq(&buf, 9);
+ sdp_put_uint16(&buf, 0x656e); /* "en" */
+ sdp_put_uint16(&buf, 106); /* UTF-8 */
+ sdp_put_uint16(&buf, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID);
+
+ sdp_put_uint16(&buf, SDP_ATTR_SERVICE_AVAILABILITY);
+ sdp_put_uint8(&buf, (UINT8_MAX - server_count * UINT8_MAX / server_limit));
+
+ sdp_put_uint16(&buf, SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST);
+ sdp_put_seq(&buf, 8);
+ sdp_put_seq(&buf, 6);
+ sdp_put_uuid16(&buf, service_class);
+ sdp_put_uint16(&buf, 0x0100); /* v1.0 */
+
+ sdp_put_uint16(&buf, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID
+ + SDP_ATTR_SERVICE_NAME_OFFSET);
+ sdp_put_str(&buf, service_name, -1);
+
+ sdp_put_uint16(&buf, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID
+ + SDP_ATTR_SERVICE_DESCRIPTION_OFFSET);
+ sdp_put_str(&buf, service_desc, -1);
+
+ sdp_put_uint16(&buf, SDP_ATTR_SECURITY_DESCRIPTION);
+ sdp_put_uint16(&buf, (l2cap_mode == 0) ? 0x0000 : 0x0001);
+
+ if (service_class == SDP_SERVICE_CLASS_NAP) {
+ sdp_put_uint16(&buf, SDP_ATTR_NET_ACCESS_TYPE);
+ sdp_put_uint16(&buf, 0x0004); /* 10Mb Ethernet */
+
+ sdp_put_uint16(&buf, SDP_ATTR_MAX_NET_ACCESS_RATE);
+ sdp_put_uint32(&buf, 10000); /* 10Mb/s (?) */
+ }
+
+ if (service_class == SDP_SERVICE_CLASS_NAP
+ || service_class == SDP_SERVICE_CLASS_GN) {
+ if (server_ipv4_subnet) {
+ sdp_put_uint16(&buf, SDP_ATTR_IPV4_SUBNET);
+ sdp_put_str(&buf, server_ipv4_subnet, -1);
+ }
+
+ if (server_ipv6_subnet) {
+ sdp_put_uint16(&buf, SDP_ATTR_IPV6_SUBNET);
+ sdp_put_str(&buf, server_ipv6_subnet, -1);
+ }
+ }
+
+ server_record.next = data;
+ server_record.end = buf.next;
+}
Index: src/usr.sbin/btpand/btpand.h
diff -u src/usr.sbin/btpand/btpand.h:1.2 src/usr.sbin/btpand/btpand.h:1.3
--- src/usr.sbin/btpand/btpand.h:1.2 Tue May 12 21:08:30 2009
+++ src/usr.sbin/btpand/btpand.h Tue May 12 21:50:38 2009
@@ -1,7 +1,7 @@
-/* $NetBSD: btpand.h,v 1.2 2009/05/12 21:08:30 plunky Exp $ */
+/* $NetBSD: btpand.h,v 1.3 2009/05/12 21:50:38 plunky Exp $ */
/*-
- * Copyright (c) 2008 Iain Hibbert
+ * Copyright (c) 2008-2009 Iain Hibbert
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -135,7 +135,9 @@
/* global variables */
extern const char * control_path;
+extern const char * service_type;
extern const char * service_name;
+extern const char * service_desc;
extern const char * interface_name;
extern bdaddr_t local_bdaddr;
extern bdaddr_t remote_bdaddr;