1 /* $NetBSD: provider.c,v 1.2 2007/11/09 20:08:41 plunky Exp $ */ 2 /* $DragonFly: src/usr.sbin/sdpd/provider.c,v 1.1 2008/01/06 21:51:30 hasso Exp $ */ 3 4 /* 5 * provider.c 6 * 7 * Copyright (c) 2004 Maksim Yevmenkin <m_evmenkin@yahoo.com> 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * $Id: provider.c,v 1.2 2007/11/30 07:39:37 griffin Exp $ 32 * $FreeBSD: src/usr.sbin/bluetooth/sdpd/provider.c,v 1.1 2004/01/20 20:48:26 emax Exp $ 33 */ 34 35 #include <sys/queue.h> 36 #include <bluetooth.h> 37 #include <sdp.h> 38 #include <string.h> 39 #include <stdlib.h> 40 #include "profile.h" 41 #include "provider.h" 42 #include "uuid-private.h" 43 44 static TAILQ_HEAD(, provider) providers = TAILQ_HEAD_INITIALIZER(providers); 45 static uint32_t change_state = 0; 46 static uint32_t next_handle = 0; 47 48 /* 49 * Register Service Discovery provider. 50 * Should not be called more the once. 51 */ 52 53 int32_t 54 provider_register_sd(int32_t fd) 55 { 56 extern profile_t sd_profile_descriptor; 57 extern profile_t bgd_profile_descriptor; 58 59 provider_p sd = calloc(1, sizeof(*sd)); 60 provider_p bgd = calloc(1, sizeof(*bgd)); 61 62 if (sd == NULL || bgd == NULL) { 63 if (sd != NULL) 64 free(sd); 65 66 if (bgd != NULL) 67 free(bgd); 68 69 return (-1); 70 } 71 72 sd->profile = &sd_profile_descriptor; 73 bgd->handle = 0; 74 sd->fd = fd; 75 TAILQ_INSERT_HEAD(&providers, sd, provider_next); 76 77 bgd->profile = &bgd_profile_descriptor; 78 bgd->handle = 1; 79 sd->fd = fd; 80 TAILQ_INSERT_AFTER(&providers, sd, bgd, provider_next); 81 82 change_state ++; 83 84 return (0); 85 } 86 87 /* 88 * Register new provider for a given profile, bdaddr and session. 89 */ 90 91 provider_p 92 provider_register(profile_p const profile, bdaddr_t const *bdaddr, int32_t fd, 93 uint8_t const *data, uint32_t datalen) 94 { 95 provider_p provider = calloc(1, sizeof(*provider)); 96 97 if (provider != NULL) { 98 provider->data = malloc(datalen); 99 if (provider->data != NULL) { 100 provider->profile = profile; 101 memcpy(provider->data, data, datalen); 102 103 /* 104 * Record handles 0x0 and 0x1 are reserved 105 * for SDP itself 106 */ 107 108 if (++ next_handle <= 1) 109 next_handle = 2; 110 111 provider->handle = next_handle; 112 113 memcpy(&provider->bdaddr, bdaddr, 114 sizeof(provider->bdaddr)); 115 provider->fd = fd; 116 117 TAILQ_INSERT_TAIL(&providers, provider, provider_next); 118 change_state ++; 119 } else { 120 free(provider); 121 provider = NULL; 122 } 123 } 124 125 return (provider); 126 } 127 128 /* 129 * Unregister provider 130 */ 131 132 void 133 provider_unregister(provider_p provider) 134 { 135 TAILQ_REMOVE(&providers, provider, provider_next); 136 if (provider->data != NULL) 137 free(provider->data); 138 free(provider); 139 change_state ++; 140 } 141 142 /* 143 * Update provider data 144 */ 145 146 int32_t 147 provider_update(provider_p provider, uint8_t const *data, uint32_t datalen) 148 { 149 uint8_t *new_data = (uint8_t *) realloc(provider->data, datalen); 150 151 if (new_data == NULL) 152 return (-1); 153 154 memcpy(new_data, data, datalen); 155 provider->data = new_data; 156 157 return (0); 158 } 159 160 /* 161 * Get a provider for given record handle 162 */ 163 164 provider_p 165 provider_by_handle(uint32_t handle) 166 { 167 provider_p provider = NULL; 168 169 TAILQ_FOREACH(provider, &providers, provider_next) 170 if (provider->handle == handle) 171 break; 172 173 return (provider); 174 } 175 176 /* 177 * Cursor access 178 */ 179 180 provider_p 181 provider_get_first(void) 182 { 183 return (TAILQ_FIRST(&providers)); 184 } 185 186 provider_p 187 provider_get_next(provider_p provider) 188 { 189 return (TAILQ_NEXT(provider, provider_next)); 190 } 191 192 /* 193 * Return change state 194 */ 195 196 uint32_t 197 provider_get_change_state(void) 198 { 199 return (change_state); 200 } 201 202 /* 203 * Match provider to UUID list 204 * 205 * all UUIDs in list must match one of the 206 * provider UUIDs or the PublicBrowseGroup 207 */ 208 209 int 210 provider_match_uuid(provider_p provider, uint128_t *uuid, int ucount) 211 { 212 uint128_t puuid; 213 int num, max; 214 215 max = provider->profile->usize / sizeof(provider->profile->uuid[0]); 216 217 for (; ucount-- > 0 ; uuid++) { 218 if (memcmp(uuid, &uuid_public_browse_group, sizeof(*uuid)) == 0) 219 continue; 220 221 for (num = 0 ; ; num++) { 222 if (num == max) 223 return 0; 224 225 memcpy(&puuid, &uuid_base, sizeof(puuid)); 226 puuid.b[2] = provider->profile->uuid[num] >> 8; 227 puuid.b[3] = provider->profile->uuid[num]; 228 229 if (memcmp(uuid, &puuid, sizeof(*uuid)) == 0) 230 break; 231 } 232 } 233 234 return 1; 235 } 236