Mon Mar 5 19:01:50 2012 UTC ()
Pull up the following revisions(s) (requested by joerg in ticket #74):
	usr.sbin/sdpd/sdpd.h:	revision 1.2
	usr.sbin/sdpd/server.c:	revision 1.11

Fix format string. Make sure problem doesn't reappear by using __printf_like
as appropriate.


(sborrill)
diff -r1.1 -r1.1.10.1 src/usr.sbin/sdpd/sdpd.h
diff -r1.10 -r1.10.4.1 src/usr.sbin/sdpd/server.c

cvs diff -r1.1 -r1.1.10.1 src/usr.sbin/sdpd/sdpd.h (switch to unified diff)

--- src/usr.sbin/sdpd/sdpd.h 2009/05/12 10:05:07 1.1
+++ src/usr.sbin/sdpd/sdpd.h 2012/03/05 19:01:49 1.1.10.1
@@ -1,162 +1,162 @@ @@ -1,162 +1,162 @@
1/* $NetBSD: sdpd.h,v 1.1 2009/05/12 10:05:07 plunky Exp $ */ 1/* $NetBSD: sdpd.h,v 1.1.10.1 2012/03/05 19:01:49 sborrill Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2006 Itronix Inc. 4 * Copyright (c) 2006 Itronix Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of Itronix Inc. may not be used to endorse 15 * 3. The name of Itronix Inc. may not be used to endorse
16 * or promote products derived from this software without specific 16 * or promote products derived from this software without specific
17 * prior written permission. 17 * prior written permission.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND 19 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN 26 * ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31/* 31/*
32 * Copyright (c) 2009 The NetBSD Foundation, Inc. 32 * Copyright (c) 2009 The NetBSD Foundation, Inc.
33 * Copyright (c) 2004 Maksim Yevmenkin <m_evmenkin@yahoo.com> 33 * Copyright (c) 2004 Maksim Yevmenkin <m_evmenkin@yahoo.com>
34 * All rights reserved. 34 * All rights reserved.
35 * 35 *
36 * Redistribution and use in source and binary forms, with or without 36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions 37 * modification, are permitted provided that the following conditions
38 * are met: 38 * are met:
39 * 1. Redistributions of source code must retain the above copyright 39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer. 40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright 41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the 42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution. 43 * documentation and/or other materials provided with the distribution.
44 * 44 *
45 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 45 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 48 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * SUCH DAMAGE. 55 * SUCH DAMAGE.
56 */ 56 */
57 57
58#ifndef _SDPD_H_ 58#ifndef _SDPD_H_
59#define _SDPD_H_ 59#define _SDPD_H_
60 60
61#include <sys/types.h> 61#include <sys/types.h>
62#include <sys/queue.h> 62#include <sys/queue.h>
63 63
64#include <bluetooth.h> 64#include <bluetooth.h>
65#include <sdp.h> 65#include <sdp.h>
66#include <stdbool.h> 66#include <stdbool.h>
67 67
68/* 68/*
69 * Service Record entry 69 * Service Record entry
70 */ 70 */
71struct record { 71struct record {
72 int fd; /* owner */ 72 int fd; /* owner */
73 bool valid; /* record is current */ 73 bool valid; /* record is current */
74 uint32_t handle; /* ServiceRecord handle */ 74 uint32_t handle; /* ServiceRecord handle */
75 sdp_data_t data; /* ServiceRecord data */ 75 sdp_data_t data; /* ServiceRecord data */
76 bdaddr_t bdaddr; /* restricted device address */ 76 bdaddr_t bdaddr; /* restricted device address */
77 int refcnt; /* reference count */ 77 int refcnt; /* reference count */
78 fd_set refset; /* reference bitset */ 78 fd_set refset; /* reference bitset */
79 LIST_ENTRY(record) next; /* next ServiceRecord */ 79 LIST_ENTRY(record) next; /* next ServiceRecord */
80 uint8_t ext[0]; /* raw data storage ... */ 80 uint8_t ext[0]; /* raw data storage ... */
81}; 81};
82 82
83typedef struct record record_t; 83typedef struct record record_t;
84 84
85/* 85/*
86 * File descriptor (client) index entry 86 * File descriptor (client) index entry
87 */ 87 */
88struct fd_idx { 88struct fd_idx {
89 bool valid; /* descriptor is valid */ 89 bool valid; /* descriptor is valid */
90 bool server; /* descriptor is listening */ 90 bool server; /* descriptor is listening */
91 bool control;/* descriptor is control socket */ 91 bool control;/* descriptor is control socket */
92 bool priv; /* descriptor may modify service record db */ 92 bool priv; /* descriptor may modify service record db */
93 uint16_t omtu; /* outgoing MTU */ 93 uint16_t omtu; /* outgoing MTU */
94 uint16_t offset; /* stored ContinuationState */ 94 uint16_t offset; /* stored ContinuationState */
95 bdaddr_t bdaddr; /* clients local device address */ 95 bdaddr_t bdaddr; /* clients local device address */
96}; 96};
97 97
98typedef struct fd_idx fd_idx_t; 98typedef struct fd_idx fd_idx_t;
99 99
100/* 100/*
101 * SDP server 101 * SDP server
102 */ 102 */
103struct server { 103struct server {
104 uint16_t imtu; /* incoming MTU */ 104 uint16_t imtu; /* incoming MTU */
105 uint8_t * ibuf; /* input buffer */ 105 uint8_t * ibuf; /* input buffer */
106 size_t ctllen; /* control msg buffer length */ 106 size_t ctllen; /* control msg buffer length */
107 uint8_t * ctlbuf; /* control msg buffer */ 107 uint8_t * ctlbuf; /* control msg buffer */
108 sdp_pdu_t pdu; /* PDU header */ 108 sdp_pdu_t pdu; /* PDU header */
109 uint16_t omtu; /* outgoing MTU */ 109 uint16_t omtu; /* outgoing MTU */
110 uint8_t * obuf; /* output buffer */ 110 uint8_t * obuf; /* output buffer */
111 uint32_t handle; /* next ServiceRecordHandle */ 111 uint32_t handle; /* next ServiceRecordHandle */
112 LIST_HEAD(, record) rlist; /* ServiceRecord list */ 112 LIST_HEAD(, record) rlist; /* ServiceRecord list */
113 int fdmax; /* descriptor max index */ 113 int fdmax; /* descriptor max index */
114 fd_idx_t * fdidx; /* descriptor index */ 114 fd_idx_t * fdidx; /* descriptor index */
115 fd_set fdset; /* current descriptor set */ 115 fd_set fdset; /* current descriptor set */
116 const char * sgroup; /* privileged group */ 116 const char * sgroup; /* privileged group */
117}; 117};
118 118
119typedef struct server server_t; 119typedef struct server server_t;
120 120
121/* compat.c */ 121/* compat.c */
122uint16_t compat_register_request(server_t *, int); 122uint16_t compat_register_request(server_t *, int);
123uint16_t compat_change_request(server_t *, int); 123uint16_t compat_change_request(server_t *, int);
124 124
125/* db.c */ 125/* db.c */
126bool db_init(server_t *); 126bool db_init(server_t *);
127bool db_next(server_t *, int, record_t **); 127bool db_next(server_t *, int, record_t **);
128void db_select_ssp(server_t *, int, sdp_data_t *); 128void db_select_ssp(server_t *, int, sdp_data_t *);
129void db_select_handle(server_t *, int, uint32_t); 129void db_select_handle(server_t *, int, uint32_t);
130bool db_create(server_t *, int, const bdaddr_t *, uint32_t, sdp_data_t *); 130bool db_create(server_t *, int, const bdaddr_t *, uint32_t, sdp_data_t *);
131void db_unselect(server_t *, int); 131void db_unselect(server_t *, int);
132void db_release(server_t *, int); 132void db_release(server_t *, int);
133 133
134/* log.c */ 134/* log.c */
135void log_open(char const *, bool); 135void log_open(char const *, bool);
136void log_close(void); 136void log_close(void);
137void log_emerg(char const *, ...); 137void log_emerg(char const *, ...) __printflike(1, 2);
138void log_alert(char const *, ...); 138void log_alert(char const *, ...) __printflike(1, 2);
139void log_crit(char const *, ...); 139void log_crit(char const *, ...) __printflike(1, 2);
140void log_err(char const *, ...); 140void log_err(char const *, ...) __printflike(1, 2);
141void log_warning(char const *, ...); 141void log_warning(char const *, ...) __printflike(1, 2);
142void log_notice(char const *, ...); 142void log_notice(char const *, ...) __printflike(1, 2);
143void log_info(char const *, ...); 143void log_info(char const *, ...) __printflike(1, 2);
144void log_debug(char const *, ...); 144void log_debug(char const *, ...) __printflike(1, 2);
145 145
146/* record.c */ 146/* record.c */
147uint16_t record_insert_request(server_t *, int); 147uint16_t record_insert_request(server_t *, int);
148uint16_t record_update_request(server_t *, int); 148uint16_t record_update_request(server_t *, int);
149uint16_t record_remove_request(server_t *, int); 149uint16_t record_remove_request(server_t *, int);
150 150
151/* server.c */ 151/* server.c */
152bool server_init(server_t *, const char *, const char *); 152bool server_init(server_t *, const char *, const char *);
153void server_shutdown(server_t *); 153void server_shutdown(server_t *);
154bool server_do(server_t *); 154bool server_do(server_t *);
155void server_error_response(server_t *, int, uint16_t); 155void server_error_response(server_t *, int, uint16_t);
156 156
157/* service.c */ 157/* service.c */
158uint16_t service_search_request(server_t *, int); 158uint16_t service_search_request(server_t *, int);
159uint16_t service_attribute_request(server_t *, int); 159uint16_t service_attribute_request(server_t *, int);
160uint16_t service_search_attribute_request(server_t *, int); 160uint16_t service_search_attribute_request(server_t *, int);
161 161
162#endif /* _SDPD_H_ */ 162#endif /* _SDPD_H_ */

cvs diff -r1.10 -r1.10.4.1 src/usr.sbin/sdpd/server.c (switch to unified diff)

--- src/usr.sbin/sdpd/server.c 2011/07/01 03:07:21 1.10
+++ src/usr.sbin/sdpd/server.c 2012/03/05 19:01:49 1.10.4.1
@@ -1,619 +1,619 @@ @@ -1,619 +1,619 @@
1/* $NetBSD: server.c,v 1.10 2011/07/01 03:07:21 joerg Exp $ */ 1/* $NetBSD: server.c,v 1.10.4.1 2012/03/05 19:01:49 sborrill Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2006 Itronix Inc. 4 * Copyright (c) 2006 Itronix Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of Itronix Inc. may not be used to endorse 15 * 3. The name of Itronix Inc. may not be used to endorse
16 * or promote products derived from this software without specific 16 * or promote products derived from this software without specific
17 * prior written permission. 17 * prior written permission.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND 19 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN 26 * ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31/*- 31/*-
32 * Copyright (c) 2009 The NetBSD Foundation, Inc. 32 * Copyright (c) 2009 The NetBSD Foundation, Inc.
33 * Copyright (c) 2004 Maksim Yevmenkin <m_evmenkin@yahoo.com> 33 * Copyright (c) 2004 Maksim Yevmenkin <m_evmenkin@yahoo.com>
34 * All rights reserved. 34 * All rights reserved.
35 * 35 *
36 * Redistribution and use in source and binary forms, with or without 36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions 37 * modification, are permitted provided that the following conditions
38 * are met: 38 * are met:
39 * 1. Redistributions of source code must retain the above copyright 39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer. 40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright 41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the 42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution. 43 * documentation and/or other materials provided with the distribution.
44 * 44 *
45 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 45 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 48 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * SUCH DAMAGE. 55 * SUCH DAMAGE.
56 * 56 *
57 * $FreeBSD: src/usr.sbin/bluetooth/sdpd/server.c,v 1.2 2005/12/06 17:56:36 emax Exp $ 57 * $FreeBSD: src/usr.sbin/bluetooth/sdpd/server.c,v 1.2 2005/12/06 17:56:36 emax Exp $
58 */ 58 */
59 59
60#include <sys/cdefs.h> 60#include <sys/cdefs.h>
61__RCSID("$NetBSD: server.c,v 1.10 2011/07/01 03:07:21 joerg Exp $"); 61__RCSID("$NetBSD: server.c,v 1.10.4.1 2012/03/05 19:01:49 sborrill Exp $");
62 62
63#include <sys/select.h> 63#include <sys/select.h>
64#include <sys/stat.h> 64#include <sys/stat.h>
65#include <sys/ucred.h> 65#include <sys/ucred.h>
66#include <sys/un.h> 66#include <sys/un.h>
67 67
68#include <assert.h> 68#include <assert.h>
69#include <bluetooth.h> 69#include <bluetooth.h>
70#include <errno.h> 70#include <errno.h>
71#include <grp.h> 71#include <grp.h>
72#include <pwd.h> 72#include <pwd.h>
73#include <sdp.h> 73#include <sdp.h>
74#include <stdio.h> 74#include <stdio.h>
75#include <stdlib.h> 75#include <stdlib.h>
76#include <string.h> 76#include <string.h>
77#include <unistd.h> 77#include <unistd.h>
78 78
79#include "sdpd.h" 79#include "sdpd.h"
80 80
81static bool server_open_control (server_t *, char const *); 81static bool server_open_control (server_t *, char const *);
82static bool server_open_l2cap (server_t *); 82static bool server_open_l2cap (server_t *);
83static void server_accept_client (server_t *, int); 83static void server_accept_client (server_t *, int);
84static bool server_process_request (server_t *, int); 84static bool server_process_request (server_t *, int);
85static void server_close_fd (server_t *, int); 85static void server_close_fd (server_t *, int);
86static bool server_auth_check (server_t *, void *); 86static bool server_auth_check (server_t *, void *);
87 87
88/* number of groups we allocate space for in cmsg */ 88/* number of groups we allocate space for in cmsg */
89#define MAX_GROUPS 20 89#define MAX_GROUPS 20
90 90
91/* 91/*
92 * Initialize server 92 * Initialize server
93 */ 93 */
94bool 94bool
95server_init(server_t *srv, char const *control, char const *sgroup) 95server_init(server_t *srv, char const *control, char const *sgroup)
96{ 96{
97 97
98 assert(srv != NULL); 98 assert(srv != NULL);
99 assert(control != NULL); 99 assert(control != NULL);
100 100
101 memset(srv, 0, sizeof(*srv)); 101 memset(srv, 0, sizeof(*srv));
102 FD_ZERO(&srv->fdset); 102 FD_ZERO(&srv->fdset);
103 srv->sgroup = sgroup; 103 srv->sgroup = sgroup;
104 104
105 srv->fdmax = -1; 105 srv->fdmax = -1;
106 srv->fdidx = calloc(FD_SETSIZE, sizeof(fd_idx_t)); 106 srv->fdidx = calloc(FD_SETSIZE, sizeof(fd_idx_t));
107 if (srv->fdidx == NULL) { 107 if (srv->fdidx == NULL) {
108 log_crit("Failed to allocate fd index"); 108 log_crit("Failed to allocate fd index");
109 goto fail; 109 goto fail;
110 } 110 }
111 111
112 srv->ctllen = CMSG_SPACE(SOCKCREDSIZE(MAX_GROUPS)); 112 srv->ctllen = CMSG_SPACE(SOCKCREDSIZE(MAX_GROUPS));
113 srv->ctlbuf = malloc(srv->ctllen); 113 srv->ctlbuf = malloc(srv->ctllen);
114 if (srv->ctlbuf == NULL) { 114 if (srv->ctlbuf == NULL) {
115 log_crit("Malloc cmsg buffer (len=%d) failed.", srv->ctllen); 115 log_crit("Malloc cmsg buffer (len=%zu) failed.", srv->ctllen);
116 goto fail; 116 goto fail;
117 } 117 }
118 118
119 srv->imtu = SDP_LOCAL_MTU - sizeof(sdp_pdu_t); 119 srv->imtu = SDP_LOCAL_MTU - sizeof(sdp_pdu_t);
120 srv->ibuf = malloc(srv->imtu); 120 srv->ibuf = malloc(srv->imtu);
121 if (srv->ibuf == NULL) { 121 if (srv->ibuf == NULL) {
122 log_crit("Malloc input buffer (imtu=%d) failed.", srv->imtu); 122 log_crit("Malloc input buffer (imtu=%d) failed.", srv->imtu);
123 goto fail; 123 goto fail;
124 } 124 }
125 125
126 srv->omtu = L2CAP_MTU_DEFAULT - sizeof(sdp_pdu_t); 126 srv->omtu = L2CAP_MTU_DEFAULT - sizeof(sdp_pdu_t);
127 srv->obuf = malloc(srv->omtu); 127 srv->obuf = malloc(srv->omtu);
128 if (srv->obuf == NULL) { 128 if (srv->obuf == NULL) {
129 log_crit("Malloc output buffer (omtu=%d) failed.", srv->omtu); 129 log_crit("Malloc output buffer (omtu=%d) failed.", srv->omtu);
130 goto fail; 130 goto fail;
131 } 131 }
132 132
133 if (db_init(srv) 133 if (db_init(srv)
134 && server_open_control(srv, control) 134 && server_open_control(srv, control)
135 && server_open_l2cap(srv)) 135 && server_open_l2cap(srv))
136 return true; 136 return true;
137 137
138fail: 138fail:
139 server_shutdown(srv); 139 server_shutdown(srv);
140 return false; 140 return false;
141} 141}
142 142
143/* 143/*
144 * Open local control socket 144 * Open local control socket
145 */ 145 */
146static bool 146static bool
147server_open_control(server_t *srv, char const *control) 147server_open_control(server_t *srv, char const *control)
148{ 148{
149 struct sockaddr_un un; 149 struct sockaddr_un un;
150 int opt, fd; 150 int opt, fd;
151 151
152 if (unlink(control) == -1 && errno != ENOENT) { 152 if (unlink(control) == -1 && errno != ENOENT) {
153 log_crit("Could not unlink(%s). %s (%d)", 153 log_crit("Could not unlink(%s). %s (%d)",
154 control, strerror(errno), errno); 154 control, strerror(errno), errno);
155 155
156 return false; 156 return false;
157 } 157 }
158 158
159 fd = socket(PF_LOCAL, SOCK_STREAM, 0); 159 fd = socket(PF_LOCAL, SOCK_STREAM, 0);
160 if (fd == -1) { 160 if (fd == -1) {
161 log_crit("Could not create control socket. %s (%d)", 161 log_crit("Could not create control socket. %s (%d)",
162 strerror(errno), errno); 162 strerror(errno), errno);
163 163
164 return false; 164 return false;
165 } 165 }
166 166
167 opt = 1; 167 opt = 1;
168 if (setsockopt(fd, 0, LOCAL_CREDS, &opt, sizeof(opt)) == -1) 168 if (setsockopt(fd, 0, LOCAL_CREDS, &opt, sizeof(opt)) == -1)
169 log_crit("Warning: No credential checks on control socket"); 169 log_crit("Warning: No credential checks on control socket");
170 170
171 memset(&un, 0, sizeof(un)); 171 memset(&un, 0, sizeof(un));
172 un.sun_len = sizeof(un); 172 un.sun_len = sizeof(un);
173 un.sun_family = AF_LOCAL; 173 un.sun_family = AF_LOCAL;
174 strlcpy(un.sun_path, control, sizeof(un.sun_path)); 174 strlcpy(un.sun_path, control, sizeof(un.sun_path));
175 175
176 if (bind(fd, (struct sockaddr *) &un, sizeof(un)) == -1) { 176 if (bind(fd, (struct sockaddr *) &un, sizeof(un)) == -1) {
177 log_crit("Could not bind control socket. %s (%d)", 177 log_crit("Could not bind control socket. %s (%d)",
178 strerror(errno), errno); 178 strerror(errno), errno);
179 179
180 close(fd); 180 close(fd);
181 return false; 181 return false;
182 } 182 }
183 183
184 if (chmod(control, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) == -1) { 184 if (chmod(control, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) == -1) {
185 log_crit("Could not set permissions on control socket. %s (%d)", 185 log_crit("Could not set permissions on control socket. %s (%d)",
186 strerror(errno), errno); 186 strerror(errno), errno);
187 187
188 close(fd); 188 close(fd);
189 return false; 189 return false;
190 } 190 }
191 191
192 if (listen(fd, 5) == -1) { 192 if (listen(fd, 5) == -1) {
193 log_crit("Could not listen on control socket. %s (%d)", 193 log_crit("Could not listen on control socket. %s (%d)",
194 strerror(errno), errno); 194 strerror(errno), errno);
195 195
196 close(fd); 196 close(fd);
197 return false; 197 return false;
198 } 198 }
199 199
200 /* Add control descriptor to index */ 200 /* Add control descriptor to index */
201 if (fd > srv->fdmax) 201 if (fd > srv->fdmax)
202 srv->fdmax = fd; 202 srv->fdmax = fd;
203 203
204 FD_SET(fd, &srv->fdset); 204 FD_SET(fd, &srv->fdset);
205 srv->fdidx[fd].valid = true; 205 srv->fdidx[fd].valid = true;
206 srv->fdidx[fd].server = true; 206 srv->fdidx[fd].server = true;
207 srv->fdidx[fd].control = true; 207 srv->fdidx[fd].control = true;
208 srv->fdidx[fd].priv = false; 208 srv->fdidx[fd].priv = false;
209 return true; 209 return true;
210} 210}
211 211
212/* 212/*
213 * Open L2CAP server socket 213 * Open L2CAP server socket
214 */ 214 */
215static bool 215static bool
216server_open_l2cap(server_t *srv) 216server_open_l2cap(server_t *srv)
217{ 217{
218 struct sockaddr_bt sa; 218 struct sockaddr_bt sa;
219 int fd; 219 int fd;
220 220
221 fd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); 221 fd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
222 if (fd == -1) { 222 if (fd == -1) {
223 log_crit("Could not create L2CAP socket. %s (%d)", 223 log_crit("Could not create L2CAP socket. %s (%d)",
224 strerror(errno), errno); 224 strerror(errno), errno);
225 225
226 return false; 226 return false;
227 } 227 }
228 228
229 if (setsockopt(fd, BTPROTO_L2CAP, SO_L2CAP_IMTU, 229 if (setsockopt(fd, BTPROTO_L2CAP, SO_L2CAP_IMTU,
230 &srv->imtu, sizeof(srv->imtu)) == -1) { 230 &srv->imtu, sizeof(srv->imtu)) == -1) {
231 log_crit("Could not set L2CAP Incoming MTU. %s (%d)", 231 log_crit("Could not set L2CAP Incoming MTU. %s (%d)",
232 strerror(errno), errno); 232 strerror(errno), errno);
233 233
234 close(fd); 234 close(fd);
235 return false; 235 return false;
236 } 236 }
237 237
238 memset(&sa, 0, sizeof(sa)); 238 memset(&sa, 0, sizeof(sa));
239 sa.bt_len = sizeof(sa); 239 sa.bt_len = sizeof(sa);
240 sa.bt_family = AF_BLUETOOTH; 240 sa.bt_family = AF_BLUETOOTH;
241 sa.bt_psm = L2CAP_PSM_SDP; 241 sa.bt_psm = L2CAP_PSM_SDP;
242 bdaddr_copy(&sa.bt_bdaddr, BDADDR_ANY); 242 bdaddr_copy(&sa.bt_bdaddr, BDADDR_ANY);
243 243
244 if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) == -1) { 244 if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) == -1) {
245 log_crit("Could not bind L2CAP socket. %s (%d)", 245 log_crit("Could not bind L2CAP socket. %s (%d)",
246 strerror(errno), errno); 246 strerror(errno), errno);
247 247
248 close(fd); 248 close(fd);
249 return false; 249 return false;
250 } 250 }
251 251
252 if (listen(fd, 5) == -1) { 252 if (listen(fd, 5) == -1) {
253 log_crit("Could not listen on L2CAP socket. %s (%d)", 253 log_crit("Could not listen on L2CAP socket. %s (%d)",
254 strerror(errno), errno); 254 strerror(errno), errno);
255 255
256 close(fd); 256 close(fd);
257 return false; 257 return false;
258 } 258 }
259 259
260 /* Add L2CAP descriptor to index */ 260 /* Add L2CAP descriptor to index */
261 if (fd > srv->fdmax) 261 if (fd > srv->fdmax)
262 srv->fdmax = fd; 262 srv->fdmax = fd;
263 263
264 FD_SET(fd, &srv->fdset); 264 FD_SET(fd, &srv->fdset);
265 srv->fdidx[fd].valid = true; 265 srv->fdidx[fd].valid = true;
266 srv->fdidx[fd].server = true; 266 srv->fdidx[fd].server = true;
267 srv->fdidx[fd].control = false; 267 srv->fdidx[fd].control = false;
268 srv->fdidx[fd].priv = false; 268 srv->fdidx[fd].priv = false;
269 return true; 269 return true;
270} 270}
271 271
272/* 272/*
273 * Shutdown server 273 * Shutdown server
274 */ 274 */
275void 275void
276server_shutdown(server_t *srv) 276server_shutdown(server_t *srv)
277{ 277{
278 record_t *r; 278 record_t *r;
279 int fd; 279 int fd;
280 280
281 assert(srv != NULL); 281 assert(srv != NULL);
282 282
283 while ((r = LIST_FIRST(&srv->rlist)) != NULL) { 283 while ((r = LIST_FIRST(&srv->rlist)) != NULL) {
284 LIST_REMOVE(r, next); 284 LIST_REMOVE(r, next);
285 free(r); 285 free(r);
286 } 286 }
287 287
288 for (fd = 0; fd < srv->fdmax + 1; fd ++) { 288 for (fd = 0; fd < srv->fdmax + 1; fd ++) {
289 if (srv->fdidx[fd].valid) 289 if (srv->fdidx[fd].valid)
290 server_close_fd(srv, fd); 290 server_close_fd(srv, fd);
291 } 291 }
292 292
293 free(srv->fdidx); 293 free(srv->fdidx);
294 free(srv->ctlbuf); 294 free(srv->ctlbuf);
295 free(srv->ibuf); 295 free(srv->ibuf);
296 free(srv->obuf); 296 free(srv->obuf);
297 297
298 memset(srv, 0, sizeof(*srv)); 298 memset(srv, 0, sizeof(*srv));
299} 299}
300 300
301/* 301/*
302 * Do one server iteration 302 * Do one server iteration
303 */ 303 */
304bool 304bool
305server_do(server_t *srv) 305server_do(server_t *srv)
306{ 306{
307 fd_set fdset; 307 fd_set fdset;
308 int n, fd; 308 int n, fd;
309 309
310 assert(srv != NULL); 310 assert(srv != NULL);
311 311
312 memcpy(&fdset, &srv->fdset, sizeof(fdset)); 312 memcpy(&fdset, &srv->fdset, sizeof(fdset));
313 n = select(srv->fdmax + 1, &fdset, NULL, NULL, NULL); 313 n = select(srv->fdmax + 1, &fdset, NULL, NULL, NULL);
314 if (n == -1) { 314 if (n == -1) {
315 if (errno == EINTR) 315 if (errno == EINTR)
316 return true; 316 return true;
317 317
318 log_err("Could not select(%d, %p). %s (%d)", 318 log_err("Could not select(%d, %p). %s (%d)",
319 srv->fdmax + 1, &fdset, strerror(errno), errno); 319 srv->fdmax + 1, &fdset, strerror(errno), errno);
320 320
321 return false; 321 return false;
322 } 322 }
323 323
324 for (fd = 0; fd < srv->fdmax + 1 && n > 0; fd++) { 324 for (fd = 0; fd < srv->fdmax + 1 && n > 0; fd++) {
325 if (!FD_ISSET(fd, &fdset)) 325 if (!FD_ISSET(fd, &fdset))
326 continue; 326 continue;
327 327
328 assert(srv->fdidx[fd].valid); 328 assert(srv->fdidx[fd].valid);
329 329
330 if (srv->fdidx[fd].server) 330 if (srv->fdidx[fd].server)
331 server_accept_client(srv, fd); 331 server_accept_client(srv, fd);
332 else if (!server_process_request(srv, fd)) 332 else if (!server_process_request(srv, fd))
333 server_close_fd(srv, fd); 333 server_close_fd(srv, fd);
334 334
335 n--; 335 n--;
336 } 336 }
337 337
338 return true; 338 return true;
339 339
340} 340}
341 341
342/* 342/*
343 * Accept new client connection and register it with index 343 * Accept new client connection and register it with index
344 */ 344 */
345static void 345static void
346server_accept_client(server_t *srv, int fd) 346server_accept_client(server_t *srv, int fd)
347{ 347{
348 struct sockaddr_bt sa; 348 struct sockaddr_bt sa;
349 socklen_t len; 349 socklen_t len;
350 int cfd; 350 int cfd;
351 uint16_t omtu; 351 uint16_t omtu;
352 352
353 do { 353 do {
354 cfd = accept(fd, NULL, NULL); 354 cfd = accept(fd, NULL, NULL);
355 } while (cfd == -1 && errno == EINTR); 355 } while (cfd == -1 && errno == EINTR);
356 356
357 if (cfd == -1) { 357 if (cfd == -1) {
358 log_err("Could not accept connection on %s socket. %s (%d)", 358 log_err("Could not accept connection on %s socket. %s (%d)",
359 srv->fdidx[fd].control ? "control" : "L2CAP", 359 srv->fdidx[fd].control ? "control" : "L2CAP",
360 strerror(errno), errno); 360 strerror(errno), errno);
361 361
362 return; 362 return;
363 } 363 }
364 364
365 if (cfd >= FD_SETSIZE) { 365 if (cfd >= FD_SETSIZE) {
366 log_crit("File descriptor too large"); 366 log_crit("File descriptor too large");
367 close(cfd); 367 close(cfd);
368 return; 368 return;
369 } 369 }
370 370
371 assert(!FD_ISSET(cfd, &srv->fdset)); 371 assert(!FD_ISSET(cfd, &srv->fdset));
372 assert(!srv->fdidx[cfd].valid); 372 assert(!srv->fdidx[cfd].valid);
373 373
374 memset(&sa, 0, sizeof(sa)); 374 memset(&sa, 0, sizeof(sa));
375 omtu = srv->omtu; 375 omtu = srv->omtu;
376 376
377 if (!srv->fdidx[fd].control) { 377 if (!srv->fdidx[fd].control) {
378 len = sizeof(sa); 378 len = sizeof(sa);
379 if (getsockname(cfd, (struct sockaddr *)&sa, &len) == -1) 379 if (getsockname(cfd, (struct sockaddr *)&sa, &len) == -1)
380 log_warning("getsockname failed, using BDADDR_ANY"); 380 log_warning("getsockname failed, using BDADDR_ANY");
381 381
382 len = sizeof(omtu); 382 len = sizeof(omtu);
383 if (getsockopt(cfd, BTPROTO_L2CAP, SO_L2CAP_OMTU, &omtu, &len) == -1) 383 if (getsockopt(cfd, BTPROTO_L2CAP, SO_L2CAP_OMTU, &omtu, &len) == -1)
384 log_warning("Could not get L2CAP OMTU, using %d", omtu); 384 log_warning("Could not get L2CAP OMTU, using %d", omtu);
385 else 385 else
386 omtu -= sizeof(sdp_pdu_t); 386 omtu -= sizeof(sdp_pdu_t);
387 } 387 }
388 388
389 /* Add client descriptor to the index */ 389 /* Add client descriptor to the index */
390 if (cfd > srv->fdmax) 390 if (cfd > srv->fdmax)
391 srv->fdmax = cfd; 391 srv->fdmax = cfd;
392 392
393 FD_SET(cfd, &srv->fdset); 393 FD_SET(cfd, &srv->fdset);
394 srv->fdidx[cfd].valid = true; 394 srv->fdidx[cfd].valid = true;
395 srv->fdidx[cfd].server = false; 395 srv->fdidx[cfd].server = false;
396 srv->fdidx[cfd].control = srv->fdidx[fd].control; 396 srv->fdidx[cfd].control = srv->fdidx[fd].control;
397 srv->fdidx[cfd].priv = false; 397 srv->fdidx[cfd].priv = false;
398 srv->fdidx[cfd].omtu = (omtu > srv->omtu) ? srv->omtu : omtu; 398 srv->fdidx[cfd].omtu = (omtu > srv->omtu) ? srv->omtu : omtu;
399 srv->fdidx[cfd].offset = 0; 399 srv->fdidx[cfd].offset = 0;
400 bdaddr_copy(&srv->fdidx[cfd].bdaddr, &sa.bt_bdaddr); 400 bdaddr_copy(&srv->fdidx[cfd].bdaddr, &sa.bt_bdaddr);
401 401
402 log_debug("new %s client on fd#%d", 402 log_debug("new %s client on fd#%d",
403 srv->fdidx[cfd].control ? "control" : "L2CAP", cfd); 403 srv->fdidx[cfd].control ? "control" : "L2CAP", cfd);
404} 404}
405 405
406/* 406/*
407 * Process request from the client 407 * Process request from the client
408 */ 408 */
409static bool 409static bool
410server_process_request(server_t *srv, int fd) 410server_process_request(server_t *srv, int fd)
411{ 411{
412 struct msghdr msg; 412 struct msghdr msg;
413 struct iovec iov[2]; 413 struct iovec iov[2];
414 struct cmsghdr *cmsg; 414 struct cmsghdr *cmsg;
415 ssize_t len; 415 ssize_t len;
416 uint16_t error; 416 uint16_t error;
417 417
418 assert(FD_ISSET(fd, &srv->fdset)); 418 assert(FD_ISSET(fd, &srv->fdset));
419 assert(srv->fdidx[fd].valid); 419 assert(srv->fdidx[fd].valid);
420 assert(!srv->fdidx[fd].server); 420 assert(!srv->fdidx[fd].server);
421 421
422 iov[0].iov_base = &srv->pdu; 422 iov[0].iov_base = &srv->pdu;
423 iov[0].iov_len = sizeof(srv->pdu); 423 iov[0].iov_len = sizeof(srv->pdu);
424 iov[1].iov_base = srv->ibuf; 424 iov[1].iov_base = srv->ibuf;
425 iov[1].iov_len = srv->imtu; 425 iov[1].iov_len = srv->imtu;
426 426
427 msg.msg_name = NULL; 427 msg.msg_name = NULL;
428 msg.msg_namelen = 0; 428 msg.msg_namelen = 0;
429 msg.msg_iov = iov; 429 msg.msg_iov = iov;
430 msg.msg_iovlen = __arraycount(iov); 430 msg.msg_iovlen = __arraycount(iov);
431 msg.msg_control = srv->ctlbuf; 431 msg.msg_control = srv->ctlbuf;
432 msg.msg_controllen = srv->ctllen; 432 msg.msg_controllen = srv->ctllen;
433 msg.msg_flags = 0; 433 msg.msg_flags = 0;
434 434
435 do { 435 do {
436 len = recvmsg(fd, &msg, 0); 436 len = recvmsg(fd, &msg, 0);
437 } while (len == -1 && errno == EINTR); 437 } while (len == -1 && errno == EINTR);
438 438
439 if (len == -1) { 439 if (len == -1) {
440 log_err("Could not receive SDP request on %s socket. %s (%d)", 440 log_err("Could not receive SDP request on %s socket. %s (%d)",
441 srv->fdidx[fd].control ? "control" : "L2CAP", 441 srv->fdidx[fd].control ? "control" : "L2CAP",
442 strerror(errno), errno); 442 strerror(errno), errno);
443 443
444 return false; 444 return false;
445 } 445 }
446 446
447 if (len == 0) { 447 if (len == 0) {
448 log_info("Client on %s socket has disconnected", 448 log_info("Client on %s socket has disconnected",
449 srv->fdidx[fd].control ? "control" : "L2CAP"); 449 srv->fdidx[fd].control ? "control" : "L2CAP");
450 450
451 return false; 451 return false;
452 } 452 }
453 453
454 if (msg.msg_flags & MSG_TRUNC) 454 if (msg.msg_flags & MSG_TRUNC)
455 log_info("Truncated message on %s socket", 455 log_info("Truncated message on %s socket",
456 srv->fdidx[fd].control ? "control" : "L2CAP"); 456 srv->fdidx[fd].control ? "control" : "L2CAP");
457 457
458 if ((cmsg = CMSG_FIRSTHDR(&msg)) != NULL 458 if ((cmsg = CMSG_FIRSTHDR(&msg)) != NULL
459 && cmsg->cmsg_level == SOL_SOCKET 459 && cmsg->cmsg_level == SOL_SOCKET
460 && cmsg->cmsg_type == SCM_CREDS 460 && cmsg->cmsg_type == SCM_CREDS
461 && cmsg->cmsg_len >= CMSG_LEN(SOCKCREDSIZE(0))) 461 && cmsg->cmsg_len >= CMSG_LEN(SOCKCREDSIZE(0)))
462 srv->fdidx[fd].priv = server_auth_check(srv, CMSG_DATA(cmsg)); 462 srv->fdidx[fd].priv = server_auth_check(srv, CMSG_DATA(cmsg));
463 463
464 srv->pdu.len = be16toh(srv->pdu.len); 464 srv->pdu.len = be16toh(srv->pdu.len);
465 465
466 if ((uint32_t)len < sizeof(srv->pdu) 466 if ((uint32_t)len < sizeof(srv->pdu)
467 || (uint32_t)len != sizeof(srv->pdu) + srv->pdu.len) { 467 || (uint32_t)len != sizeof(srv->pdu) + srv->pdu.len) {
468 error = SDP_ERROR_CODE_INVALID_PDU_SIZE; 468 error = SDP_ERROR_CODE_INVALID_PDU_SIZE;
469 } else { 469 } else {
470 switch (srv->pdu.pid) { 470 switch (srv->pdu.pid) {
471 case SDP_PDU_SERVICE_SEARCH_REQUEST: 471 case SDP_PDU_SERVICE_SEARCH_REQUEST:
472 error = service_search_request(srv, fd); 472 error = service_search_request(srv, fd);
473 break; 473 break;
474 474
475 case SDP_PDU_SERVICE_ATTRIBUTE_REQUEST: 475 case SDP_PDU_SERVICE_ATTRIBUTE_REQUEST:
476 error = service_attribute_request(srv, fd); 476 error = service_attribute_request(srv, fd);
477 break; 477 break;
478 478
479 case SDP_PDU_SERVICE_SEARCH_ATTRIBUTE_REQUEST: 479 case SDP_PDU_SERVICE_SEARCH_ATTRIBUTE_REQUEST:
480 error = service_search_attribute_request(srv, fd); 480 error = service_search_attribute_request(srv, fd);
481 break; 481 break;
482 482
483#ifdef SDP_COMPAT 483#ifdef SDP_COMPAT
484 case SDP_PDU_SERVICE_REGISTER_REQUEST: 484 case SDP_PDU_SERVICE_REGISTER_REQUEST:
485 error = compat_register_request(srv, fd); 485 error = compat_register_request(srv, fd);
486 break; 486 break;
487 487
488 case SDP_PDU_SERVICE_CHANGE_REQUEST: 488 case SDP_PDU_SERVICE_CHANGE_REQUEST:
489 error = compat_change_request(srv, fd); 489 error = compat_change_request(srv, fd);
490 break; 490 break;
491#endif 491#endif
492 492
493 case SDP_PDU_RECORD_INSERT_REQUEST: 493 case SDP_PDU_RECORD_INSERT_REQUEST:
494 error = record_insert_request(srv, fd); 494 error = record_insert_request(srv, fd);
495 break; 495 break;
496 496
497 case SDP_PDU_RECORD_UPDATE_REQUEST: 497 case SDP_PDU_RECORD_UPDATE_REQUEST:
498 error = record_update_request(srv, fd); 498 error = record_update_request(srv, fd);
499 break; 499 break;
500 500
501 case SDP_PDU_RECORD_REMOVE_REQUEST: 501 case SDP_PDU_RECORD_REMOVE_REQUEST:
502 error = record_remove_request(srv, fd); 502 error = record_remove_request(srv, fd);
503 break; 503 break;
504 504
505 default: 505 default:
506 error = SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX; 506 error = SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX;
507 break; 507 break;
508 } 508 }
509 } 509 }
510 510
511 if (error != 0) { 511 if (error != 0) {
512 srv->fdidx[fd].offset = 0; 512 srv->fdidx[fd].offset = 0;
513 db_unselect(srv, fd); 513 db_unselect(srv, fd);
514 srv->pdu.pid = SDP_PDU_ERROR_RESPONSE; 514 srv->pdu.pid = SDP_PDU_ERROR_RESPONSE;
515 srv->pdu.len = sizeof(error); 515 srv->pdu.len = sizeof(error);
516 be16enc(srv->obuf, error); 516 be16enc(srv->obuf, error);
517 log_debug("sending ErrorResponse (error=0x%04x)", error); 517 log_debug("sending ErrorResponse (error=0x%04x)", error);
518 } 518 }
519 519
520 iov[0].iov_base = &srv->pdu; 520 iov[0].iov_base = &srv->pdu;
521 iov[0].iov_len = sizeof(srv->pdu); 521 iov[0].iov_len = sizeof(srv->pdu);
522 iov[1].iov_base = srv->obuf; 522 iov[1].iov_base = srv->obuf;
523 iov[1].iov_len = srv->pdu.len; 523 iov[1].iov_len = srv->pdu.len;
524 524
525 srv->pdu.len = htobe16(srv->pdu.len); 525 srv->pdu.len = htobe16(srv->pdu.len);
526 526
527 msg.msg_name = NULL; 527 msg.msg_name = NULL;
528 msg.msg_namelen = 0; 528 msg.msg_namelen = 0;
529 msg.msg_iov = iov; 529 msg.msg_iov = iov;
530 msg.msg_iovlen = __arraycount(iov); 530 msg.msg_iovlen = __arraycount(iov);
531 msg.msg_control = NULL; 531 msg.msg_control = NULL;
532 msg.msg_controllen = 0; 532 msg.msg_controllen = 0;
533 msg.msg_flags = 0; 533 msg.msg_flags = 0;
534 534
535 do { 535 do {
536 len = sendmsg(fd, &msg, 0); 536 len = sendmsg(fd, &msg, 0);
537 } while (len == -1 && errno == EINTR); 537 } while (len == -1 && errno == EINTR);
538 538
539 if (len == -1) { 539 if (len == -1) {
540 log_err("Could not send SDP response on %s socket. %s (%d)", 540 log_err("Could not send SDP response on %s socket. %s (%d)",
541 srv->fdidx[fd].control ? "control" : "L2CAP", 541 srv->fdidx[fd].control ? "control" : "L2CAP",
542 strerror(errno), errno); 542 strerror(errno), errno);
543 543
544 return false; 544 return false;
545 } 545 }
546 546
547 return true; 547 return true;
548} 548}
549 549
550/* 550/*
551 * Close descriptor and remove it from index 551 * Close descriptor and remove it from index
552 */ 552 */
553static void 553static void
554server_close_fd(server_t *srv, int fd) 554server_close_fd(server_t *srv, int fd)
555{ 555{
556 556
557 assert(FD_ISSET(fd, &srv->fdset)); 557 assert(FD_ISSET(fd, &srv->fdset));
558 assert(srv->fdidx[fd].valid); 558 assert(srv->fdidx[fd].valid);
559 559
560 db_unselect(srv, fd); /* release selected records */ 560 db_unselect(srv, fd); /* release selected records */
561 db_release(srv, fd); /* expire owned records */ 561 db_release(srv, fd); /* expire owned records */
562 562
563 close(fd); 563 close(fd);
564 FD_CLR(fd, &srv->fdset); 564 FD_CLR(fd, &srv->fdset);
565 srv->fdidx[fd].valid = false; 565 srv->fdidx[fd].valid = false;
566 566
567 log_debug("client on fd#%d closed", fd); 567 log_debug("client on fd#%d closed", fd);
568 568
569 if (fd == srv->fdmax) { 569 if (fd == srv->fdmax) {
570 while (fd > 0 && !srv->fdidx[fd].valid) 570 while (fd > 0 && !srv->fdidx[fd].valid)
571 fd--; 571 fd--;
572 572
573 srv->fdmax = fd; 573 srv->fdmax = fd;
574 } 574 }
575} 575}
576 576
577/* 577/*
578 * check credentials, return true when permitted to modify service records 578 * check credentials, return true when permitted to modify service records
579 */ 579 */
580static bool 580static bool
581server_auth_check(server_t *srv, void *data) 581server_auth_check(server_t *srv, void *data)
582{ 582{
583 struct sockcred *cred = data; 583 struct sockcred *cred = data;
584 struct group *grp; 584 struct group *grp;
585 int n; 585 int n;
586 586
587 if (cred == NULL) 587 if (cred == NULL)
588 return false; 588 return false;
589 589
590 if (cred->sc_uid == 0 || cred->sc_euid == 0) 590 if (cred->sc_uid == 0 || cred->sc_euid == 0)
591 return true; 591 return true;
592 592
593 if (srv->sgroup == NULL) 593 if (srv->sgroup == NULL)
594 return false; 594 return false;
595 595
596 grp = getgrnam(srv->sgroup); 596 grp = getgrnam(srv->sgroup);
597 if (grp == NULL) { 597 if (grp == NULL) {
598 log_err("No gid for group '%s'", srv->sgroup); 598 log_err("No gid for group '%s'", srv->sgroup);
599 srv->sgroup = NULL; 599 srv->sgroup = NULL;
600 return false; 600 return false;
601 } 601 }
602 602
603 if (cred->sc_gid == grp->gr_gid || cred->sc_egid == grp->gr_gid) 603 if (cred->sc_gid == grp->gr_gid || cred->sc_egid == grp->gr_gid)
604 return true; 604 return true;
605 605
606 if (cred->sc_ngroups > MAX_GROUPS) { 606 if (cred->sc_ngroups > MAX_GROUPS) {
607 log_info("Credentials truncated, lost %d groups", 607 log_info("Credentials truncated, lost %d groups",
608 MAX_GROUPS - cred->sc_ngroups); 608 MAX_GROUPS - cred->sc_ngroups);
609 609
610 cred->sc_ngroups = MAX_GROUPS; 610 cred->sc_ngroups = MAX_GROUPS;
611 } 611 }
612 612
613 for (n = 0 ; n < cred->sc_ngroups ; n++) { 613 for (n = 0 ; n < cred->sc_ngroups ; n++) {
614 if (cred->sc_groups[n] == grp->gr_gid) 614 if (cred->sc_groups[n] == grp->gr_gid)
615 return true; 615 return true;
616 } 616 }
617 617
618 return false; 618 return false;
619} 619}