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;