Module Name:    src
Committed By:   plunky
Date:           Tue May 12 18:43:36 UTC 2009

Modified Files:
        src/usr.bin/rfcomm_sppd: Makefile rfcomm_sppd.c
Removed Files:
        src/usr.bin/rfcomm_sppd: rfcomm_sdp.c rfcomm_sdp.h

Log Message:
update rfcomm_sppd to use the new Service Discovery API


To generate a diff of this commit:
cvs rdiff -u -r1.4 -r1.5 src/usr.bin/rfcomm_sppd/Makefile
cvs rdiff -u -r1.1 -r0 src/usr.bin/rfcomm_sppd/rfcomm_sdp.c \
    src/usr.bin/rfcomm_sppd/rfcomm_sdp.h
cvs rdiff -u -r1.9 -r1.10 src/usr.bin/rfcomm_sppd/rfcomm_sppd.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.bin/rfcomm_sppd/Makefile
diff -u src/usr.bin/rfcomm_sppd/Makefile:1.4 src/usr.bin/rfcomm_sppd/Makefile:1.5
--- src/usr.bin/rfcomm_sppd/Makefile:1.4	Tue May 12 13:13:34 2009
+++ src/usr.bin/rfcomm_sppd/Makefile	Tue May 12 18:43:35 2009
@@ -1,13 +1,11 @@
-# $NetBSD: Makefile,v 1.4 2009/05/12 13:13:34 plunky Exp $
+# $NetBSD: Makefile,v 1.5 2009/05/12 18:43:35 plunky Exp $
 
 USE_FORT?= yes	# network client/server
 
 PROG=		rfcomm_sppd
-SRCS=		rfcomm_sppd.c rfcomm_sdp.c
+SRCS=		rfcomm_sppd.c
 
 DPADD+=		${LIBBLUETOOTH}
 LDADD+=		-lbluetooth
 
-CPPFLAGS+=	-DSDP_COMPAT
-
 .include <bsd.prog.mk>

Index: src/usr.bin/rfcomm_sppd/rfcomm_sppd.c
diff -u src/usr.bin/rfcomm_sppd/rfcomm_sppd.c:1.9 src/usr.bin/rfcomm_sppd/rfcomm_sppd.c:1.10
--- src/usr.bin/rfcomm_sppd/rfcomm_sppd.c:1.9	Mon Jul 21 14:19:25 2008
+++ src/usr.bin/rfcomm_sppd/rfcomm_sppd.c	Tue May 12 18:43:35 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: rfcomm_sppd.c,v 1.9 2008/07/21 14:19:25 lukem Exp $	*/
+/*	$NetBSD: rfcomm_sppd.c,v 1.10 2009/05/12 18:43:35 plunky Exp $	*/
 
 /*-
  * Copyright (c) 2006 Itronix Inc.
@@ -29,8 +29,7 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 /*
- * rfcomm_sppd.c
- *
+ * Copyright (c) 2009 The NetBSD Foundation, Inc.
  * Copyright (c) 2007 Iain Hibbert
  * Copyright (c) 2003 Maksim Yevmenkin <m_evmen...@yahoo.com>
  * All rights reserved.
@@ -58,11 +57,12 @@
  */
 
 #include <sys/cdefs.h>
-__COPYRIGHT("@(#) Copyright (c) 2007 Iain Hibbert.\
+__COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc.\
+  Copyright (c) 2007 Iain Hibbert.\
   Copyright (c) 2006 Itronix, Inc.\
   Copyright (c) 2003 Maksim Yevmenkin m_evmen...@yahoo.com.\
   All rights reserved.");
-__RCSID("$NetBSD: rfcomm_sppd.c,v 1.9 2008/07/21 14:19:25 lukem Exp $");
+__RCSID("$NetBSD: rfcomm_sppd.c,v 1.10 2009/05/12 18:43:35 plunky Exp $");
 
 #include <bluetooth.h>
 #include <ctype.h>
@@ -84,14 +84,13 @@
 
 #include <netbt/rfcomm.h>
 
-#include "rfcomm_sdp.h"
-
 #define max(a, b)	((a) > (b) ? (a) : (b))
 
 int open_tty(const char *);
 int open_client(bdaddr_t *, bdaddr_t *, int, const char *);
 int open_server(bdaddr_t *, uint8_t, int, const char *);
 void copy_data(int, int);
+int channel_lookup(const bdaddr_t *, const bdaddr_t *, uint16_t, uintmax_t *);
 void sighandler(int);
 void usage(void);
 void reset_tio(void);
@@ -100,27 +99,17 @@
 struct termios tio;	/* stored termios for reset on exit */
 
 struct service {
-	const char	*name;
-	const char	*description;
+	const char *	name;
+	const char *	description;
 	uint16_t	class;
-	int		pdulen;
 } services[] = {
 	{ "DUN",	"Dialup Networking",
-	  SDP_SERVICE_CLASS_DIALUP_NETWORKING,
-	  sizeof(struct sdp_dun_profile)
-	},
-	{ "LAN",	"Lan access using PPP",
-	  SDP_SERVICE_CLASS_LAN_ACCESS_USING_PPP,
-	  sizeof(struct sdp_lan_profile)
-	},
+	    SDP_SERVICE_CLASS_DIALUP_NETWORKING		},
+	{ "LAN",	"LAN access using PPP",
+	    SDP_SERVICE_CLASS_LAN_ACCESS_USING_PPP	},
 	{ "SP",		"Serial Port",
-	  SDP_SERVICE_CLASS_SERIAL_PORT,
-	  sizeof(struct sdp_sp_profile)
-	},
-	{ NULL,		NULL,
-	  0,
-	  0
-	}
+	    SDP_SERVICE_CLASS_SERIAL_PORT		},
+	{ NULL,		NULL,		0		}
 };
 
 int
@@ -335,26 +324,30 @@
 	struct service *s;
 	struct linger l;
 	char *ep;
-	int fd;
-	uint8_t channel;
+	int fd, error;
+	uintmax_t channel;
 
 	for (s = services ; ; s++) {
 		if (s->name == NULL) {
 			channel = strtoul(service, &ep, 10);
-			if (*ep != '\0' || channel < 1 || channel > 30)
-				errx(EXIT_FAILURE, "Invalid service: %s", service);
+			if (*ep != '\0')
+				errx(EXIT_FAILURE, "Unknown service: %s", service);
 
 			break;
 		}
 
 		if (strcasecmp(s->name, service) == 0) {
-			if (rfcomm_channel_lookup(laddr, raddr, s->class, &channel, &errno) < 0)
-				err(EXIT_FAILURE, "%s", s->name);
+			error = channel_lookup(laddr, raddr, s->class, &channel);
+			if (error != 0)
+				errx(EXIT_FAILURE, "%s: %s", s->name, strerror(error));
 
 			break;
 		}
 	}
 
+	if (channel < RFCOMM_CHANNEL_MIN || channel > RFCOMM_CHANNEL_MAX)
+		errx(EXIT_FAILURE, "Invalid channel %"PRIuMAX, channel);
+
 	memset(&sa, 0, sizeof(sa));
 	sa.bt_len = sizeof(sa);
 	sa.bt_family = AF_BLUETOOTH;
@@ -380,40 +373,42 @@
 	bdaddr_copy(&sa.bt_bdaddr, raddr);
 
 	if (connect(fd, (struct sockaddr *)&sa, sizeof(sa)) < 0)
-		err(EXIT_FAILURE, "connect(%s, %d)", bt_ntoa(raddr, NULL),
+		err(EXIT_FAILURE, "connect(%s, %"PRIuMAX")", bt_ntoa(raddr, NULL),
 						     channel);
 
 	return fd;
 }
 
-/*
- * In all the profiles we currently support registering, the channel
- * is the first octet in the PDU, and it seems all the rest can be
- * zero, so we just use an array of uint8_t big enough to store the
- * largest, currently LAN. See <sdp.h> for definitions..
- */
-#define pdu_len		sizeof(struct sdp_lan_profile)
-
 int
 open_server(bdaddr_t *laddr, uint8_t channel, int lm, const char *service)
 {
+	uint8_t	buffer[256];
 	struct sockaddr_bt sa;
+	struct service *s;
 	struct linger l;
 	socklen_t len;
-	void *ss;
-	int sv, fd, n;
-	uint8_t pdu[pdu_len];
+	sdp_session_t ss;
+	sdp_data_t rec;
+	int sv, fd;
 
-	memset(&sa, 0, sizeof(sa));
-	sa.bt_len = sizeof(sa);
-	sa.bt_family = AF_BLUETOOTH;
-	bdaddr_copy(&sa.bt_bdaddr, laddr);
-	sa.bt_channel = channel;
+	for (s = services; ; s++) {
+		if (s->name == NULL)
+			usage();
+
+		if (strcasecmp(s->name, service) == 0)
+			break;
+	}
 
+	/* Open server socket */
 	sv = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
 	if (sv < 0)
 		err(EXIT_FAILURE, "socket()");
 
+	memset(&sa, 0, sizeof(sa));
+	sa.bt_len = sizeof(sa);
+	sa.bt_family = AF_BLUETOOTH;
+	sa.bt_channel = channel;
+	bdaddr_copy(&sa.bt_bdaddr, laddr);
 	if (bind(sv, (struct sockaddr *)&sa, sizeof(sa)) < 0)
 		err(EXIT_FAILURE, "bind(%s, %d)", bt_ntoa(laddr, NULL),
 						  channel);
@@ -424,28 +419,74 @@
 	if (listen(sv, 1) < 0)
 		err(EXIT_FAILURE, "listen()");
 
-	/* Register service with SDP server */
-	for (n = 0 ; ; n++) {
-		if (services[n].name == NULL)
-			usage();
+	/* Build SDP record */
+	rec.next = buffer;
+	rec.end = buffer + sizeof(buffer);
+
+	sdp_put_uint16(&rec, SDP_ATTR_SERVICE_RECORD_HANDLE);
+	sdp_put_uint32(&rec, 0x00000000);
+
+	sdp_put_uint16(&rec, SDP_ATTR_SERVICE_CLASS_ID_LIST);
+	sdp_put_seq(&rec, 3);
+	sdp_put_uuid16(&rec, s->class);
+
+	sdp_put_uint16(&rec, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST);
+	sdp_put_seq(&rec, 12);
+	sdp_put_seq(&rec, 3);
+	sdp_put_uuid16(&rec, SDP_UUID_PROTOCOL_L2CAP);
+	sdp_put_seq(&rec, 5);
+	sdp_put_uuid16(&rec, SDP_UUID_PROTOCOL_RFCOMM);
+	sdp_put_uint8(&rec, channel);
+
+	sdp_put_uint16(&rec, SDP_ATTR_BROWSE_GROUP_LIST);
+	sdp_put_seq(&rec, 3);
+	sdp_put_uuid16(&rec, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP);
+
+	sdp_put_uint16(&rec, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST);
+	sdp_put_seq(&rec, 9);
+	sdp_put_uint16(&rec, 0x656e);	/* "en" */
+	sdp_put_uint16(&rec, 106);	/* UTF-8 */
+	sdp_put_uint16(&rec, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID);
+
+	if (s->class == SDP_SERVICE_CLASS_LAN_ACCESS_USING_PPP) {
+		sdp_put_uint16(&rec, SDP_ATTR_SERVICE_AVAILABILITY);
+		sdp_put_uint8(&rec, 0x00);
+	}
 
-		if (strcasecmp(services[n].name, service) == 0)
-			break;
+	sdp_put_uint16(&rec, SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST);
+	sdp_put_seq(&rec, 8);
+	sdp_put_seq(&rec, 6);
+	sdp_put_uuid16(&rec, s->class);
+	sdp_put_uint16(&rec, 0x0100);	/* v1.0 */
+
+	sdp_put_uint16(&rec, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID
+	    + SDP_ATTR_SERVICE_NAME_OFFSET);
+	sdp_put_str(&rec, s->description, -1);
+
+	if (s->class == SDP_SERVICE_CLASS_DIALUP_NETWORKING) {
+		sdp_put_uint16(&rec, SDP_ATTR_AUDIO_FEEDBACK_SUPPORT);
+		sdp_put_bool(&rec, false);
+	}
+
+#if 0
+	if (s->class == SDP_SERVICE_CLASS_LAN_ACCESS_USING_PPP) {
+		sdp_put_uint16(&rec, SDP_ATTR_IP_SUBNET);	/* TODO */
+		sdp_put_str(&rec, "0.0.0.0/0", -1);
 	}
+#endif
 
-	memset(pdu, 0, pdu_len);
-	pdu[0] = channel;
+	rec.end = rec.next;
+	rec.next = buffer;
 
+	/* Register service with SDP server */
 	ss = sdp_open_local(NULL);
-	if (ss == NULL || (errno = sdp_error(ss)) != 0)
+	if (ss == NULL)
 		err(EXIT_FAILURE, "sdp_open_local");
 
-	if (sdp_register_service(ss, services[n].class, laddr,
-		    pdu, services[n].pdulen, NULL) != 0) {
-		errno = sdp_error(ss);
-		err(EXIT_FAILURE, "sdp_register_service");
-	}
+	if (!sdp_record_insert(ss, laddr, NULL, &rec))
+		err(EXIT_FAILURE, "sdp_record_insert");
 
+	/* Accept client connection */
 	len = sizeof(sa);
 	fd = accept(sv, (struct sockaddr *)&sa, &len);
 	if (fd < 0)
@@ -485,6 +526,109 @@
 	}
 }
 
+int
+channel_lookup(bdaddr_t const *laddr, bdaddr_t const *raddr,
+    uint16_t class, uintmax_t *channel)
+{
+	uint8_t		buffer[6];	/* SSP (3 bytes) + AIL (3 bytes) */
+	sdp_session_t	ss;
+	sdp_data_t	ail, ssp, rsp, rec, value, pdl, seq;
+	uint16_t	attr;
+	bool		rv;
+
+	seq.next = buffer;
+	seq.end = buffer + sizeof(buffer);
+
+	/*
+	 * build ServiceSearchPattern (3 bytes)
+	 */
+	ssp.next = seq.next;
+	sdp_put_uuid16(&seq, class);
+	ssp.end = seq.next;
+
+	/*
+	 * build AttributeIDList (3 bytes)
+	 */
+	ail.next = seq.next;
+	sdp_put_uint16(&seq, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST);
+	ail.end = seq.next;
+
+	ss = sdp_open(laddr, raddr);
+	if (ss == NULL)
+		return errno;
+
+	rv = sdp_service_search_attribute(ss, &ssp, &ail, &rsp);
+	if (!rv) {
+		sdp_close(ss);
+		return errno;
+	}
+
+	/*
+	 * The response will be a list of records that matched our
+	 * ServiceSearchPattern, where each record is a sequence
+	 * containing a single ProtocolDescriptorList attribute and
+	 * value
+	 *
+	 *	seq
+	 *	  uint16	ProtocolDescriptorList
+	 *	  value
+	 *	seq
+	 *	  uint16	ProtocolDescriptorList
+	 *	  value
+	 *
+	 * If the ProtocolDescriptorList describes a single stack,
+	 * the attribute value takes the form of a single Data Element
+	 * Sequence where each member is a protocol descriptor.
+	 *
+	 *	seq
+	 *	  list
+	 *
+	 * If it is possible for more than one kind of protocol
+	 * stack to be used to gain access to the service, the
+	 * ProtocolDescriptorList takes the form of a Data Element
+	 * Alternative where each member is a Data Element Sequence
+	 * describing an alternative protocol stack.
+	 *
+	 *	alt
+	 *	  seq
+	 *	    list
+	 *	  seq
+	 *	    list
+	 *
+	 * Each protocol stack description contains a sequence for each
+	 * protocol, where each sequence contains the protocol UUID as
+	 * the first element, and any ProtocolSpecificParameters. We are
+	 * interested in the RFCOMM channel number, stored as parameter#1.
+	 *
+	 *	seq
+	 *	  uuid		L2CAP
+	 *	  uint16	psm
+	 *	seq
+	 *	  uuid		RFCOMM
+	 *	  uint8		channel
+	 */
+
+	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);	/* strip any alt container */
+		while (!rv && sdp_get_seq(&value, &pdl)) {
+			if (sdp_get_seq(&pdl, &seq)
+			    && sdp_match_uuid16(&seq, SDP_UUID_PROTOCOL_L2CAP)
+			    && sdp_get_seq(&pdl, &seq)
+			    && sdp_match_uuid16(&seq, SDP_UUID_PROTOCOL_RFCOMM)
+			    && sdp_get_uint(&seq, channel))
+				rv = true;
+		}
+	}
+
+	sdp_close(ss);
+	return (rv) ? 0 : ENOATTR;
+}
+
 void
 sighandler(int s)
 {

Reply via email to