1 /* $NetBSD: server.c,v 1.5 2009/10/24 20:06:42 plunky Exp $ */
4 * Copyright (c) 2008-2009 Iain Hibbert
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include <sys/cdefs.h>
29 __RCSID("$NetBSD: server.c,v 1.5 2009/10/24 20:06:42 plunky Exp $");
31 #include <sys/ioctl.h>
33 #include <net/ethertypes.h>
35 #include <bluetooth.h>
43 static struct event server_ev
;
44 static int server_count
;
46 static sdp_session_t server_ss
;
47 static uint32_t server_handle
;
48 static sdp_data_t server_record
;
50 static char * server_ipv4_subnet
;
51 static char * server_ipv6_subnet
;
52 static uint16_t server_proto
[] = { ETHERTYPE_IP
, ETHERTYPE_ARP
, ETHERTYPE_IPV6
};
53 static size_t server_nproto
= __arraycount(server_proto
);
55 static void server_open(void);
56 static void server_read(int, short, void *);
57 static void server_down(channel_t
*);
58 static void server_update(void);
59 static void server_mkrecord(void);
65 if (server_limit
== 0)
73 * Start listening on server socket
78 struct sockaddr_bt sa
;
83 fd
= socket(PF_BLUETOOTH
, SOCK_SEQPACKET
, BTPROTO_L2CAP
);
85 log_err("Could not open L2CAP socket: %m");
89 memset(&sa
, 0, sizeof(sa
));
90 sa
.bt_family
= AF_BLUETOOTH
;
91 sa
.bt_len
= sizeof(sa
);
92 sa
.bt_psm
= l2cap_psm
;
93 bdaddr_copy(&sa
.bt_bdaddr
, &local_bdaddr
);
94 if (bind(fd
, (struct sockaddr
*)&sa
, sizeof(sa
)) == -1) {
95 log_err("Could not bind server socket: %m");
99 if (setsockopt(fd
, BTPROTO_L2CAP
,
100 SO_L2CAP_LM
, &l2cap_mode
, sizeof(l2cap_mode
)) == -1) {
101 log_err("Could not set link mode (0x%4.4x): %m", l2cap_mode
);
104 len
= sizeof(l2cap_mode
);
105 getsockopt(fd
, BTPROTO_L2CAP
, SO_L2CAP_LM
, &l2cap_mode
, &len
);
108 if (setsockopt(fd
, BTPROTO_L2CAP
,
109 SO_L2CAP_IMTU
, &mru
, sizeof(mru
)) == -1) {
110 log_err("Could not set L2CAP IMTU (%d): %m", mru
);
114 if (listen(fd
, 0) == -1) {
115 log_err("Could not listen on server socket: %m");
119 event_set(&server_ev
, fd
, EV_READ
| EV_PERSIST
, server_read
, NULL
);
120 if (event_add(&server_ev
, NULL
) == -1) {
121 log_err("Could not add server event: %m");
125 log_info("server socket open");
129 * handle connection request
132 server_read(int s
, short ev
, void *arg
)
134 struct sockaddr_bt ra
, la
;
140 assert(server_count
< server_limit
);
143 fd
= accept(s
, (struct sockaddr
*)&ra
, &len
);
148 if (ioctl(fd
, FIONBIO
, &n
) == -1) {
149 log_err("Could not set NonBlocking IO: %m");
155 if (getsockopt(fd
, BTPROTO_L2CAP
, SO_L2CAP_IMTU
, &mru
, &len
) == -1) {
156 log_err("Could not get L2CAP IMTU: %m");
160 if(mru
< BNEP_MTU_MIN
) {
161 log_err("L2CAP IMTU too small (%d)", mru
);
167 if (getsockopt(fd
, BTPROTO_L2CAP
, SO_L2CAP_OMTU
, &mtu
, &len
) == -1) {
168 log_err("Could not get L2CAP OMTU: %m");
172 if (mtu
< BNEP_MTU_MIN
) {
173 log_err("L2CAP OMTU too small (%d)", mtu
);
179 if (getsockopt(fd
, SOL_SOCKET
, SO_SNDBUF
, &n
, &len
) == -1) {
180 log_err("Could not get socket send buffer size: %m");
187 if (setsockopt(fd
, SOL_SOCKET
, SO_SNDBUF
, &n
, sizeof(n
)) == -1) {
188 log_err("Could not set socket send buffer size (%d): %m", n
);
195 if (setsockopt(fd
, SOL_SOCKET
, SO_SNDLOWAT
, &n
, sizeof(n
)) == -1) {
196 log_err("Could not set socket low water mark (%d): %m", n
);
202 if (getsockname(fd
, (struct sockaddr
*)&la
, &len
) == -1) {
203 log_err("Could not get socket address: %m");
208 log_info("Accepted connection from %s", bt_ntoa(&ra
.bt_bdaddr
, NULL
));
210 chan
= channel_alloc();
216 chan
->send
= bnep_send
;
217 chan
->recv
= bnep_recv
;
218 chan
->down
= server_down
;
221 b2eaddr(chan
->raddr
, &ra
.bt_bdaddr
);
222 b2eaddr(chan
->laddr
, &la
.bt_bdaddr
);
223 chan
->state
= CHANNEL_WAIT_CONNECT_REQ
;
224 channel_timeout(chan
, 10);
225 if (!channel_open(chan
, fd
)) {
226 chan
->state
= CHANNEL_CLOSED
;
232 if (++server_count
== server_limit
) {
233 log_info("Server limit reached, closing server socket");
234 event_del(&server_ev
);
242 * Shut down a server channel, we need to update the service record and
243 * may want to restart accepting connections on the server socket
246 server_down(channel_t
*chan
)
249 assert(server_count
> 0);
253 if (server_count
-- == server_limit
)
264 if (service_type
== NULL
)
267 if (server_ss
== NULL
) {
268 server_ss
= sdp_open_local(control_path
);
269 if (server_ss
== NULL
) {
270 log_err("failed to contact SDP server");
277 if (server_handle
== 0)
278 rv
= sdp_record_insert(server_ss
, &local_bdaddr
,
279 &server_handle
, &server_record
);
281 rv
= sdp_record_update(server_ss
, server_handle
,
285 log_err("%s: %m", service_type
);
291 server_mkrecord(void)
293 static uint8_t data
[256]; /* tis enough */
298 buf
.end
= data
+ sizeof(data
);
300 sdp_put_uint16(&buf
, SDP_ATTR_SERVICE_RECORD_HANDLE
);
301 sdp_put_uint32(&buf
, 0x00000000);
303 sdp_put_uint16(&buf
, SDP_ATTR_SERVICE_CLASS_ID_LIST
);
304 sdp_put_seq(&buf
, 3);
305 sdp_put_uuid16(&buf
, service_class
);
307 sdp_put_uint16(&buf
, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST
);
308 sdp_put_seq(&buf
, 8 + 10 + 3 * server_nproto
);
309 sdp_put_seq(&buf
, 6);
310 sdp_put_uuid16(&buf
, SDP_UUID_PROTOCOL_L2CAP
);
311 sdp_put_uint16(&buf
, l2cap_psm
);
312 sdp_put_seq(&buf
, 8 + 3 * server_nproto
);
313 sdp_put_uuid16(&buf
, SDP_UUID_PROTOCOL_BNEP
);
314 sdp_put_uint16(&buf
, 0x0100); /* v1.0 */
315 sdp_put_seq(&buf
, 3 * server_nproto
);
316 for (i
= 0; i
< server_nproto
; i
++)
317 sdp_put_uint16(&buf
, server_proto
[i
]);
319 sdp_put_uint16(&buf
, SDP_ATTR_BROWSE_GROUP_LIST
);
320 sdp_put_seq(&buf
, 3);
321 sdp_put_uuid16(&buf
, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP
);
323 sdp_put_uint16(&buf
, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST
);
324 sdp_put_seq(&buf
, 9);
325 sdp_put_uint16(&buf
, 0x656e); /* "en" */
326 sdp_put_uint16(&buf
, 106); /* UTF-8 */
327 sdp_put_uint16(&buf
, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID
);
329 sdp_put_uint16(&buf
, SDP_ATTR_SERVICE_AVAILABILITY
);
330 sdp_put_uint8(&buf
, (UINT8_MAX
- server_count
* UINT8_MAX
/ server_limit
));
332 sdp_put_uint16(&buf
, SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST
);
333 sdp_put_seq(&buf
, 8);
334 sdp_put_seq(&buf
, 6);
335 sdp_put_uuid16(&buf
, service_class
);
336 sdp_put_uint16(&buf
, 0x0100); /* v1.0 */
338 sdp_put_uint16(&buf
, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID
339 + SDP_ATTR_SERVICE_NAME_OFFSET
);
340 sdp_put_str(&buf
, service_name
, -1);
342 sdp_put_uint16(&buf
, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID
343 + SDP_ATTR_SERVICE_DESCRIPTION_OFFSET
);
344 sdp_put_str(&buf
, service_desc
, -1);
346 sdp_put_uint16(&buf
, SDP_ATTR_SECURITY_DESCRIPTION
);
347 sdp_put_uint16(&buf
, (l2cap_mode
& L2CAP_LM_AUTH
) ? 0x0001 : 0x0000);
349 if (service_class
== SDP_SERVICE_CLASS_NAP
) {
350 sdp_put_uint16(&buf
, SDP_ATTR_NET_ACCESS_TYPE
);
351 sdp_put_uint16(&buf
, 0x0004); /* 10Mb Ethernet */
353 sdp_put_uint16(&buf
, SDP_ATTR_MAX_NET_ACCESS_RATE
);
354 sdp_put_uint32(&buf
, IF_Mbps(10) / 8); /* octets/second */
357 if (service_class
== SDP_SERVICE_CLASS_NAP
358 || service_class
== SDP_SERVICE_CLASS_GN
) {
359 if (server_ipv4_subnet
) {
360 sdp_put_uint16(&buf
, SDP_ATTR_IPV4_SUBNET
);
361 sdp_put_str(&buf
, server_ipv4_subnet
, -1);
364 if (server_ipv6_subnet
) {
365 sdp_put_uint16(&buf
, SDP_ATTR_IPV6_SUBNET
);
366 sdp_put_str(&buf
, server_ipv6_subnet
, -1);
370 server_record
.next
= data
;
371 server_record
.end
= buf
.next
;