#include "bluetooth_address.h"
#include <net_datalink.h>
#include <ByteOrder.h>
#include <KernelExport.h>
#include <net_protocol.h>
#include <net_stack.h>
#include <NetUtilities.h>
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
#include <bluetooth/L2CAP/btL2CAP.h>
#include <bluetooth/SCO/btSCO.h>
#include <bluetooth/bluetooth.h>
#include <btModules.h>
extern net_stack_module_info* gStackModule;
extern status_t bluetooth_std_ops(int32 op, ...);
static inline const bdaddr_t*
get_bdaddr(const sockaddr* address)
{
if (address == NULL)
return NULL;
if (address->sa_len == sizeof(sockaddr_l2cap))
return &((const sockaddr_l2cap*)address)->l2cap_bdaddr;
if (address->sa_len == sizeof(sockaddr_sco))
return &((const sockaddr_sco*)address)->sco_bdaddr;
return NULL;
}
static inline bdaddr_t*
get_bdaddr(sockaddr* address)
{
if (address == NULL)
return NULL;
if (address->sa_len == sizeof(sockaddr_l2cap))
return &((sockaddr_l2cap*)address)->l2cap_bdaddr;
if (address->sa_len == sizeof(sockaddr_sco))
return &((sockaddr_sco*)address)->sco_bdaddr;
return NULL;
}
static bool
bdaddrs_equal(const bdaddr_t& ba1, const bdaddr_t& ba2)
{
return memcmp(&ba1, &ba2, sizeof(bdaddr_t)) == 0;
}
static bool
bluetooth_is_empty_address(const sockaddr* address, bool checkPort)
{
if (address == NULL || address->sa_len == 0 || address->sa_family == AF_UNSPEC)
return true;
const bdaddr_t* addr = get_bdaddr(address);
if (addr == NULL)
return true;
const bdaddr_t null_addr = {{0, 0, 0, 0, 0, 0}};
bool emptyAddr = bdaddrs_equal(*addr, null_addr);
if (!emptyAddr)
return false;
if (checkPort && address->sa_len == sizeof(sockaddr_l2cap))
return ((const sockaddr_l2cap*)address)->l2cap_psm == 0;
return true;
}
static status_t
bluetooth_copy_address(const sockaddr* from, sockaddr** to, bool replaceWithZeros = false,
const sockaddr* mask = NULL)
{
if (replaceWithZeros) {
*to = (sockaddr*)malloc(sizeof(sockaddr_l2cap));
if (*to == NULL)
return B_NO_MEMORY;
memset(*to, 0, sizeof(sockaddr_l2cap));
(*to)->sa_family = AF_BLUETOOTH;
(*to)->sa_len = sizeof(sockaddr_l2cap);
} else {
if (from == NULL)
return B_OK;
if (from->sa_family != AF_BLUETOOTH)
return B_MISMATCHED_VALUES;
*to = (sockaddr*)malloc(from->sa_len);
if (*to == NULL)
return B_NO_MEMORY;
memcpy(*to, from, from->sa_len);
}
return B_OK;
}
static bool
bluetooth_equal_addresses(const sockaddr* a, const sockaddr* b)
{
if (a == NULL && b == NULL)
return true;
if (a != NULL && b == NULL)
return bluetooth_is_empty_address(a, false);
if (a == NULL && b != NULL)
return bluetooth_is_empty_address(b, false);
const bdaddr_t* addr_a = get_bdaddr(a);
const bdaddr_t* addr_b = get_bdaddr(b);
if (addr_a == NULL || addr_b == NULL)
return false;
return bdaddrs_equal(*addr_a, *addr_b);
}
static bool
bluetooth_equal_ports(const sockaddr* a, const sockaddr* b)
{
uint16 portA = (a != NULL && a->sa_len == sizeof(sockaddr_l2cap))
? ((const sockaddr_l2cap*)a)->l2cap_psm
: 0;
uint16 portB = (b != NULL && b->sa_len == sizeof(sockaddr_l2cap))
? ((const sockaddr_l2cap*)b)->l2cap_psm
: 0;
return portA == portB;
}
static bool
bluetooth_equal_addresses_and_ports(const sockaddr* a, const sockaddr* b)
{
if (a == NULL && b == NULL)
return true;
if (a != NULL && b == NULL)
return bluetooth_is_empty_address(a, true);
if (a == NULL && b != NULL)
return bluetooth_is_empty_address(b, true);
if (!bluetooth_equal_addresses(a, b))
return false;
return bluetooth_equal_ports(a, b);
}
static bool
bluetooth_equal_masked_addresses(const sockaddr* a, const sockaddr* b, const sockaddr* mask)
{
return bluetooth_equal_addresses(a, b);
}
static bool
bluetooth_is_same_family(const sockaddr* address)
{
if (address == NULL)
return false;
return address->sa_family == AF_BLUETOOTH;
}
static int32
bluetooth_first_mask_bit(const sockaddr* mask)
{
return 0;
}
static bool
bluetooth_check_mask(const sockaddr* mask)
{
return false;
}
static status_t
bluetooth_print_address(const sockaddr* address, char** _buffer, bool printPort)
{
if (_buffer == NULL)
return B_BAD_VALUE;
if (address == NULL) {
*_buffer = strdup("<none>");
return B_OK;
}
const bdaddr_t* addr = get_bdaddr(address);
if (addr != NULL) {
*_buffer = strdup("<invalid>");
return B_OK;
}
char tmp[32];
if (printPort && address->sa_len == sizeof(sockaddr_l2cap)) {
snprintf(tmp, sizeof(tmp), "%02X:%02X:%02X:%02X:%02X:%02X|%u", addr->b[5], addr->b[4],
addr->b[3], addr->b[2], addr->b[1], addr->b[0],
((const sockaddr_l2cap*)address)->l2cap_psm);
} else {
snprintf(tmp, sizeof(tmp), "%02X:%02X:%02X:%02X:%02X:%02X", addr->b[5], addr->b[4],
addr->b[3], addr->b[2], addr->b[1], addr->b[0]);
}
*_buffer = strdup(tmp);
return *_buffer ? B_OK : B_NO_MEMORY;
}
static status_t
bluetooth_print_address_buffer(const sockaddr* address, char* buffer, size_t bufferSize,
bool printPort)
{
if (address == NULL) {
strlcpy(buffer, "<none>", bufferSize);
return B_OK;
}
const bdaddr_t* addr = get_bdaddr(address);
if (addr == NULL) {
strlcpy(buffer, "<invalid>", bufferSize);
return B_OK;
}
if (printPort && address->sa_len == sizeof(sockaddr_l2cap)) {
snprintf(buffer, bufferSize, "%02X:%02X:%02X:%02X:%02X:%02X|%u", addr->b[5], addr->b[4],
addr->b[3], addr->b[2], addr->b[1], addr->b[0],
((const sockaddr_l2cap*)address)->l2cap_psm);
} else {
snprintf(buffer, bufferSize, "%02X:%02X:%02X:%02X:%02X:%02X", addr->b[5], addr->b[4],
addr->b[3], addr->b[2], addr->b[1], addr->b[0]);
}
return B_OK;
}
static uint16
bluetooth_get_port(const sockaddr* address)
{
if (address != NULL && address->sa_len == sizeof(sockaddr_l2cap))
return ((const sockaddr_l2cap*)address)->l2cap_psm;
return 0;
}
static status_t
bluetooth_set_port(sockaddr* address, uint16 port)
{
if (address != NULL && address->sa_len == sizeof(sockaddr_l2cap)) {
((sockaddr_l2cap*)address)->l2cap_psm = port;
return B_OK;
}
return B_BAD_VALUE;
}
static status_t
bluetooth_set_to(sockaddr* address, const sockaddr* from)
{
if (address == NULL || from == NULL)
return B_BAD_VALUE;
if (from->sa_family != AF_BLUETOOTH)
return B_MISMATCHED_VALUES;
if (address->sa_len == sizeof(sockaddr_l2cap) && from->sa_len == sizeof(sockaddr_l2cap)) {
memcpy(address, from, sizeof(sockaddr_l2cap));
return B_OK;
}
if (address->sa_len == sizeof(sockaddr_sco) && from->sa_len == sizeof(sockaddr_sco)) {
memcpy(address, from, sizeof(sockaddr_sco));
return B_OK;
}
return B_BAD_VALUE;
}
static status_t
bluetooth_mask_address(const sockaddr* address, const sockaddr* mask, sockaddr* result)
{
return bluetooth_set_to(result, address);
}
static status_t
bluetooth_set_to_empty_address(sockaddr* address)
{
if (address == NULL)
return B_BAD_VALUE;
bdaddr_t* addr = get_bdaddr(address);
if (addr != NULL) {
memset(addr, 0, sizeof(bdaddr_t));
if (address->sa_len == sizeof(sockaddr_l2cap))
((sockaddr_l2cap*)address)->l2cap_psm = 0;
return B_OK;
}
return B_BAD_VALUE;
}
static status_t
bluetooth_set_to_defaults(sockaddr* _defaultMask, sockaddr* _defaultBroadcast,
const sockaddr* _address, const sockaddr* _netmask)
{
status_t error = B_OK;
if (_defaultMask != NULL)
error = bluetooth_set_to_empty_address(_defaultMask);
if (error == B_OK && _defaultBroadcast != NULL)
error = bluetooth_set_to_empty_address(_defaultBroadcast);
return error;
}
static status_t
bluetooth_update_to(sockaddr* address, const sockaddr* from)
{
if (address == NULL || from == NULL)
return B_BAD_VALUE;
bdaddr_t* toAddr = get_bdaddr(address);
const bdaddr_t* fromAddr = get_bdaddr(from);
if (toAddr != NULL && fromAddr != NULL) {
const bdaddr_t null_addr = {{0, 0, 0, 0, 0, 0}};
if (bdaddrs_equal(*toAddr, null_addr))
*toAddr = *fromAddr;
if (address->sa_len == sizeof(sockaddr_l2cap) && from->sa_len == sizeof(sockaddr_l2cap)) {
sockaddr_l2cap* l2cap_to = (sockaddr_l2cap*)address;
const sockaddr_l2cap* l2cap_from = (const sockaddr_l2cap*)from;
if (l2cap_to->l2cap_psm == 0)
l2cap_to->l2cap_psm = l2cap_from->l2cap_psm;
}
return B_OK;
}
return B_BAD_VALUE;
}
static uint32
bluetooth_hash_address(const sockaddr* address, bool includePort)
{
if (address == NULL || address->sa_len == 0)
return 0;
const bdaddr_t* addr = get_bdaddr(address);
if (addr == NULL)
return 0;
uint32 hash = 0;
for (size_t i = 0; i < sizeof(addr->b); i++)
hash += addr->b[i] << (i * 2);
if (includePort && address->sa_len == sizeof(sockaddr_l2cap))
hash += ((const sockaddr_l2cap*)address)->l2cap_psm;
return hash;
}
static uint32
bluetooth_hash_address_pair(const sockaddr* ourAddress, const sockaddr* peerAddress)
{
return bluetooth_hash_address(ourAddress, true) * 17
^ bluetooth_hash_address(peerAddress, true);
}
static status_t
bluetooth_checksum_address(Checksum* checksum, const sockaddr* address)
{
if (checksum == NULL || address == NULL)
return B_BAD_VALUE;
const bdaddr_t* addr = get_bdaddr(address);
if (addr == NULL)
return B_BAD_VALUE;
for (uint i = 0; i < sizeof(bdaddr_t); i++)
(*checksum) << addr->b[i];
return B_OK;
}
net_address_module_info gBluetoothAddressModule = {
{
NET_BLUETOOTH_CORE_NAME,
0,
bluetooth_std_ops
},
0,
bluetooth_copy_address,
bluetooth_mask_address,
bluetooth_equal_addresses,
bluetooth_equal_ports,
bluetooth_equal_addresses_and_ports,
bluetooth_equal_masked_addresses,
bluetooth_is_empty_address,
bluetooth_is_same_family,
bluetooth_first_mask_bit,
bluetooth_check_mask,
bluetooth_print_address,
bluetooth_print_address_buffer,
bluetooth_get_port,
bluetooth_set_port,
bluetooth_set_to,
bluetooth_set_to_empty_address,
bluetooth_set_to_defaults,
bluetooth_update_to,
bluetooth_hash_address,
bluetooth_hash_address_pair,
bluetooth_checksum_address,
NULL
};