xref: /freebsd/usr.sbin/bluetooth/sdpd/provider.c (revision 42b388439bd3795e09258c57a74ce9eec3651c7b)
11de7b4b8SPedro F. Giffuni /*-
207be7a6cSMaksim Yevmenkin  * provider.c
307be7a6cSMaksim Yevmenkin  *
4*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
51de7b4b8SPedro F. Giffuni  *
607be7a6cSMaksim Yevmenkin  * Copyright (c) 2004 Maksim Yevmenkin <m_evmenkin@yahoo.com>
707be7a6cSMaksim Yevmenkin  * All rights reserved.
807be7a6cSMaksim Yevmenkin  *
907be7a6cSMaksim Yevmenkin  * Redistribution and use in source and binary forms, with or without
1007be7a6cSMaksim Yevmenkin  * modification, are permitted provided that the following conditions
1107be7a6cSMaksim Yevmenkin  * are met:
1207be7a6cSMaksim Yevmenkin  * 1. Redistributions of source code must retain the above copyright
1307be7a6cSMaksim Yevmenkin  *    notice, this list of conditions and the following disclaimer.
1407be7a6cSMaksim Yevmenkin  * 2. Redistributions in binary form must reproduce the above copyright
1507be7a6cSMaksim Yevmenkin  *    notice, this list of conditions and the following disclaimer in the
1607be7a6cSMaksim Yevmenkin  *    documentation and/or other materials provided with the distribution.
1707be7a6cSMaksim Yevmenkin  *
1807be7a6cSMaksim Yevmenkin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1907be7a6cSMaksim Yevmenkin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2007be7a6cSMaksim Yevmenkin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2107be7a6cSMaksim Yevmenkin  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2207be7a6cSMaksim Yevmenkin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2307be7a6cSMaksim Yevmenkin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2407be7a6cSMaksim Yevmenkin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2507be7a6cSMaksim Yevmenkin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2607be7a6cSMaksim Yevmenkin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2707be7a6cSMaksim Yevmenkin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2807be7a6cSMaksim Yevmenkin  * SUCH DAMAGE.
2907be7a6cSMaksim Yevmenkin  *
3007be7a6cSMaksim Yevmenkin  * $Id: provider.c,v 1.5 2004/01/13 01:54:39 max Exp $
3107be7a6cSMaksim Yevmenkin  */
3207be7a6cSMaksim Yevmenkin 
3307be7a6cSMaksim Yevmenkin #include <sys/queue.h>
348d6f425dSTakanori Watanabe #define L2CAP_SOCKET_CHECKED
3507be7a6cSMaksim Yevmenkin #include <bluetooth.h>
3607be7a6cSMaksim Yevmenkin #include <string.h>
3707be7a6cSMaksim Yevmenkin #include <stdlib.h>
3807be7a6cSMaksim Yevmenkin #include "profile.h"
3907be7a6cSMaksim Yevmenkin #include "provider.h"
4007be7a6cSMaksim Yevmenkin 
4107be7a6cSMaksim Yevmenkin static TAILQ_HEAD(, provider)	providers = TAILQ_HEAD_INITIALIZER(providers);
4207be7a6cSMaksim Yevmenkin static uint32_t			change_state = 0;
4307be7a6cSMaksim Yevmenkin static uint32_t			handle = 0;
4407be7a6cSMaksim Yevmenkin 
4507be7a6cSMaksim Yevmenkin /*
4607be7a6cSMaksim Yevmenkin  * Register Service Discovery provider.
4707be7a6cSMaksim Yevmenkin  * Should not be called more the once.
4807be7a6cSMaksim Yevmenkin  */
4907be7a6cSMaksim Yevmenkin 
5007be7a6cSMaksim Yevmenkin int32_t
provider_register_sd(int32_t fd)5107be7a6cSMaksim Yevmenkin provider_register_sd(int32_t fd)
5207be7a6cSMaksim Yevmenkin {
5307be7a6cSMaksim Yevmenkin 	extern profile_t	sd_profile_descriptor;
5407be7a6cSMaksim Yevmenkin 	extern profile_t	bgd_profile_descriptor;
5507be7a6cSMaksim Yevmenkin 
5607be7a6cSMaksim Yevmenkin 	provider_p		sd = calloc(1, sizeof(*sd));
5707be7a6cSMaksim Yevmenkin 	provider_p		bgd = calloc(1, sizeof(*bgd));
5807be7a6cSMaksim Yevmenkin 
5907be7a6cSMaksim Yevmenkin 	if (sd == NULL || bgd == NULL) {
6007be7a6cSMaksim Yevmenkin 		if (sd != NULL)
6107be7a6cSMaksim Yevmenkin 			free(sd);
6207be7a6cSMaksim Yevmenkin 
6307be7a6cSMaksim Yevmenkin 		if (bgd != NULL)
6407be7a6cSMaksim Yevmenkin 			free(bgd);
6507be7a6cSMaksim Yevmenkin 
6607be7a6cSMaksim Yevmenkin 		return (-1);
6707be7a6cSMaksim Yevmenkin 	}
6807be7a6cSMaksim Yevmenkin 
6907be7a6cSMaksim Yevmenkin 	sd->profile = &sd_profile_descriptor;
7007be7a6cSMaksim Yevmenkin 	bgd->handle = 0;
7107be7a6cSMaksim Yevmenkin 	sd->fd = fd;
7207be7a6cSMaksim Yevmenkin 	TAILQ_INSERT_HEAD(&providers, sd, provider_next);
7307be7a6cSMaksim Yevmenkin 
7407be7a6cSMaksim Yevmenkin 	bgd->profile = &bgd_profile_descriptor;
7507be7a6cSMaksim Yevmenkin 	bgd->handle = 1;
7607be7a6cSMaksim Yevmenkin 	sd->fd = fd;
7707be7a6cSMaksim Yevmenkin 	TAILQ_INSERT_AFTER(&providers, sd, bgd, provider_next);
7807be7a6cSMaksim Yevmenkin 
7907be7a6cSMaksim Yevmenkin 	change_state ++;
8007be7a6cSMaksim Yevmenkin 
8107be7a6cSMaksim Yevmenkin 	return (0);
8207be7a6cSMaksim Yevmenkin }
8307be7a6cSMaksim Yevmenkin 
8407be7a6cSMaksim Yevmenkin /*
8507be7a6cSMaksim Yevmenkin  * Register new provider for a given profile, bdaddr and session.
8607be7a6cSMaksim Yevmenkin  */
8707be7a6cSMaksim Yevmenkin 
8807be7a6cSMaksim Yevmenkin provider_p
provider_register(profile_p const profile,bdaddr_p const bdaddr,int32_t fd,uint8_t const * data,uint32_t datalen)8907be7a6cSMaksim Yevmenkin provider_register(profile_p const profile, bdaddr_p const bdaddr, int32_t fd,
9007be7a6cSMaksim Yevmenkin 	uint8_t const *data, uint32_t datalen)
9107be7a6cSMaksim Yevmenkin {
9207be7a6cSMaksim Yevmenkin 	provider_p	provider = calloc(1, sizeof(*provider));
9307be7a6cSMaksim Yevmenkin 
9407be7a6cSMaksim Yevmenkin 	if (provider != NULL) {
9507be7a6cSMaksim Yevmenkin 		provider->data = malloc(datalen);
9607be7a6cSMaksim Yevmenkin 		if (provider->data != NULL) {
9707be7a6cSMaksim Yevmenkin 			provider->profile = profile;
9807be7a6cSMaksim Yevmenkin 			memcpy(provider->data, data, datalen);
9907be7a6cSMaksim Yevmenkin 
10007be7a6cSMaksim Yevmenkin 			/*
10107be7a6cSMaksim Yevmenkin 			 * Record handles 0x0 and 0x1 are reserved
10207be7a6cSMaksim Yevmenkin 			 * for SDP itself
10307be7a6cSMaksim Yevmenkin 			 */
10407be7a6cSMaksim Yevmenkin 
10507be7a6cSMaksim Yevmenkin 			if (++ handle <= 1)
10607be7a6cSMaksim Yevmenkin 				handle = 2;
10707be7a6cSMaksim Yevmenkin 
10807be7a6cSMaksim Yevmenkin 			provider->handle = handle;
10907be7a6cSMaksim Yevmenkin 
11007be7a6cSMaksim Yevmenkin 			memcpy(&provider->bdaddr, bdaddr,
11107be7a6cSMaksim Yevmenkin 				sizeof(provider->bdaddr));
11207be7a6cSMaksim Yevmenkin 			provider->fd = fd;
11307be7a6cSMaksim Yevmenkin 
11407be7a6cSMaksim Yevmenkin 			TAILQ_INSERT_TAIL(&providers, provider, provider_next);
11507be7a6cSMaksim Yevmenkin 			change_state ++;
11607be7a6cSMaksim Yevmenkin 		} else {
11707be7a6cSMaksim Yevmenkin 			free(provider);
11807be7a6cSMaksim Yevmenkin 			provider = NULL;
11907be7a6cSMaksim Yevmenkin 		}
12007be7a6cSMaksim Yevmenkin 	}
12107be7a6cSMaksim Yevmenkin 
12207be7a6cSMaksim Yevmenkin 	return (provider);
12307be7a6cSMaksim Yevmenkin }
12407be7a6cSMaksim Yevmenkin 
12507be7a6cSMaksim Yevmenkin /*
12607be7a6cSMaksim Yevmenkin  * Unregister provider
12707be7a6cSMaksim Yevmenkin  */
12807be7a6cSMaksim Yevmenkin 
12907be7a6cSMaksim Yevmenkin void
provider_unregister(provider_p provider)13007be7a6cSMaksim Yevmenkin provider_unregister(provider_p provider)
13107be7a6cSMaksim Yevmenkin {
13207be7a6cSMaksim Yevmenkin 	TAILQ_REMOVE(&providers, provider, provider_next);
13307be7a6cSMaksim Yevmenkin 	if (provider->data != NULL)
13407be7a6cSMaksim Yevmenkin 		free(provider->data);
13507be7a6cSMaksim Yevmenkin 	free(provider);
13607be7a6cSMaksim Yevmenkin 	change_state ++;
13707be7a6cSMaksim Yevmenkin }
13807be7a6cSMaksim Yevmenkin 
13907be7a6cSMaksim Yevmenkin /*
14007be7a6cSMaksim Yevmenkin  * Update provider data
14107be7a6cSMaksim Yevmenkin  */
14207be7a6cSMaksim Yevmenkin 
14307be7a6cSMaksim Yevmenkin int32_t
provider_update(provider_p provider,uint8_t const * data,uint32_t datalen)14407be7a6cSMaksim Yevmenkin provider_update(provider_p provider, uint8_t const *data, uint32_t datalen)
14507be7a6cSMaksim Yevmenkin {
14607be7a6cSMaksim Yevmenkin 	uint8_t	*new_data = (uint8_t *) realloc(provider->data, datalen);
14707be7a6cSMaksim Yevmenkin 
14807be7a6cSMaksim Yevmenkin 	if (new_data == NULL)
14907be7a6cSMaksim Yevmenkin 		return (-1);
15007be7a6cSMaksim Yevmenkin 
15107be7a6cSMaksim Yevmenkin 	memcpy(new_data, data, datalen);
15207be7a6cSMaksim Yevmenkin 	provider->data = new_data;
15307be7a6cSMaksim Yevmenkin 
15407be7a6cSMaksim Yevmenkin 	return (0);
15507be7a6cSMaksim Yevmenkin }
15607be7a6cSMaksim Yevmenkin 
15707be7a6cSMaksim Yevmenkin /*
15807be7a6cSMaksim Yevmenkin  * Get a provider for given record handle
15907be7a6cSMaksim Yevmenkin  */
16007be7a6cSMaksim Yevmenkin 
16107be7a6cSMaksim Yevmenkin provider_p
provider_by_handle(uint32_t handle)16207be7a6cSMaksim Yevmenkin provider_by_handle(uint32_t handle)
16307be7a6cSMaksim Yevmenkin {
16407be7a6cSMaksim Yevmenkin 	provider_p	provider = NULL;
16507be7a6cSMaksim Yevmenkin 
16607be7a6cSMaksim Yevmenkin 	TAILQ_FOREACH(provider, &providers, provider_next)
16707be7a6cSMaksim Yevmenkin 		if (provider->handle == handle)
16807be7a6cSMaksim Yevmenkin 			break;
16907be7a6cSMaksim Yevmenkin 
17007be7a6cSMaksim Yevmenkin 	return (provider);
17107be7a6cSMaksim Yevmenkin }
17207be7a6cSMaksim Yevmenkin 
17307be7a6cSMaksim Yevmenkin /*
17407be7a6cSMaksim Yevmenkin  * Cursor access
17507be7a6cSMaksim Yevmenkin  */
17607be7a6cSMaksim Yevmenkin 
17707be7a6cSMaksim Yevmenkin provider_p
provider_get_first(void)17807be7a6cSMaksim Yevmenkin provider_get_first(void)
17907be7a6cSMaksim Yevmenkin {
18007be7a6cSMaksim Yevmenkin 	return (TAILQ_FIRST(&providers));
18107be7a6cSMaksim Yevmenkin }
18207be7a6cSMaksim Yevmenkin 
18307be7a6cSMaksim Yevmenkin provider_p
provider_get_next(provider_p provider)18407be7a6cSMaksim Yevmenkin provider_get_next(provider_p provider)
18507be7a6cSMaksim Yevmenkin {
18607be7a6cSMaksim Yevmenkin 	return (TAILQ_NEXT(provider, provider_next));
18707be7a6cSMaksim Yevmenkin }
18807be7a6cSMaksim Yevmenkin 
18907be7a6cSMaksim Yevmenkin /*
19007be7a6cSMaksim Yevmenkin  * Return change state
19107be7a6cSMaksim Yevmenkin  */
19207be7a6cSMaksim Yevmenkin 
19307be7a6cSMaksim Yevmenkin uint32_t
provider_get_change_state(void)19407be7a6cSMaksim Yevmenkin provider_get_change_state(void)
19507be7a6cSMaksim Yevmenkin {
19607be7a6cSMaksim Yevmenkin 	return (change_state);
19707be7a6cSMaksim Yevmenkin }
19807be7a6cSMaksim Yevmenkin 
199