L2CAP, without functionality, for the moment my playground in the netstack
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25768 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
2ebec00b97
commit
3e24801283
21
headers/os/bluetooth/L2CAP/btL2CAP.h
Normal file
21
headers/os/bluetooth/L2CAP/btL2CAP.h
Normal file
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
|
||||
*
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _BTL2CAP_H_
|
||||
#define _BTL2CAP_H_
|
||||
|
||||
#include <bluetooth/bluetooth.h>
|
||||
|
||||
struct sockaddr_l2cap {
|
||||
uint8 l2cap_len; /* total length */
|
||||
uint8 l2cap_family; /* address family */
|
||||
uint16 l2cap_psm; /* PSM (Protocol/Service Multiplexor) */
|
||||
bdaddr_t l2cap_bdaddr; /* address */
|
||||
};
|
||||
|
||||
|
||||
#endif
|
26
src/add-ons/kernel/network/protocols/l2cap/Jamfile
Normal file
26
src/add-ons/kernel/network/protocols/l2cap/Jamfile
Normal file
@ -0,0 +1,26 @@
|
||||
SubDir HAIKU_TOP src add-ons kernel network protocols l2cap ;
|
||||
|
||||
SetSubDirSupportedPlatformsBeOSCompatible ;
|
||||
|
||||
if $(TARGET_PLATFORM) != haiku {
|
||||
UseHeaders [ FStandardOSHeaders ] : true ;
|
||||
# Needed for <support/Errors.h> and maybe other stuff.
|
||||
UseHeaders [ FDirName $(HAIKU_TOP) headers posix ] : true ;
|
||||
# We need the public network headers also when not compiling for Haiku.
|
||||
# Unfortunately we get more than we want, namely all POSIX headers.
|
||||
}
|
||||
|
||||
UsePrivateHeaders kernel net bluetooth ;
|
||||
|
||||
KernelAddon l2cap :
|
||||
l2cap.cpp
|
||||
l2cap_address.cpp
|
||||
;
|
||||
|
||||
# Installation
|
||||
HaikuInstall install-networking : /boot/home/config/add-ons/kernel/haiku_network/protocols
|
||||
: l2cap ;
|
||||
|
||||
Package haiku-networkingkit-cvs :
|
||||
haiku :
|
||||
boot home config add-ons kernel haiku_network protocols ;
|
304
src/add-ons/kernel/network/protocols/l2cap/l2cap.cpp
Normal file
304
src/add-ons/kernel/network/protocols/l2cap/l2cap.cpp
Normal file
@ -0,0 +1,304 @@
|
||||
#include <net_datalink.h>
|
||||
#include <net_protocol.h>
|
||||
#include <net_stack.h>
|
||||
#include <NetBufferUtilities.h>
|
||||
|
||||
#include <KernelExport.h>
|
||||
#include <util/list.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <new>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <bluetooth/HCI/btHCI_acl.h>
|
||||
#include <btDebug.h>
|
||||
|
||||
|
||||
typedef NetBufferField<uint16, offsetof(hci_acl_header, alen)> ICMPChecksumField;
|
||||
|
||||
#define ICMP_TYPE_ECHO_REPLY 0
|
||||
#define ICMP_TYPE_UNREACH 3
|
||||
#define ICMP_TYPE_REDIRECT 5
|
||||
#define ICMP_TYPE_ECHO_REQUEST 8
|
||||
|
||||
// type unreach codes
|
||||
#define ICMP_CODE_UNREACH_NEED_FRAGMENT 4 // this is used for path MTU discovery
|
||||
|
||||
struct l2cap_protocol : net_protocol {
|
||||
};
|
||||
|
||||
|
||||
net_buffer_module_info *gBufferModule;
|
||||
static net_stack_module_info *sStackModule;
|
||||
|
||||
|
||||
net_protocol *
|
||||
l2cap_init_protocol(net_socket *socket)
|
||||
{
|
||||
l2cap_protocol *protocol = new (std::nothrow) l2cap_protocol;
|
||||
if (protocol == NULL)
|
||||
return NULL;
|
||||
|
||||
return protocol;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
l2cap_uninit_protocol(net_protocol *protocol)
|
||||
{
|
||||
delete protocol;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
l2cap_open(net_protocol *protocol)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
l2cap_close(net_protocol *protocol)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
l2cap_free(net_protocol *protocol)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
l2cap_connect(net_protocol *protocol, const struct sockaddr *address)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
l2cap_accept(net_protocol *protocol, struct net_socket **_acceptedSocket)
|
||||
{
|
||||
return EOPNOTSUPP;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
l2cap_control(net_protocol *protocol, int level, int option, void *value,
|
||||
size_t *_length)
|
||||
{
|
||||
return protocol->next->module->control(protocol->next, level, option,
|
||||
value, _length);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
l2cap_getsockopt(net_protocol *protocol, int level, int option,
|
||||
void *value, int *length)
|
||||
{
|
||||
return protocol->next->module->getsockopt(protocol->next, level, option,
|
||||
value, length);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
l2cap_setsockopt(net_protocol *protocol, int level, int option,
|
||||
const void *value, int length)
|
||||
{
|
||||
return protocol->next->module->setsockopt(protocol->next, level, option,
|
||||
value, length);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
l2cap_bind(net_protocol *protocol, const struct sockaddr *address)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
l2cap_unbind(net_protocol *protocol, struct sockaddr *address)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
l2cap_listen(net_protocol *protocol, int count)
|
||||
{
|
||||
return EOPNOTSUPP;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
l2cap_shutdown(net_protocol *protocol, int direction)
|
||||
{
|
||||
return EOPNOTSUPP;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
l2cap_send_data(net_protocol *protocol, net_buffer *buffer)
|
||||
{
|
||||
return protocol->next->module->send_data(protocol->next, buffer);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
l2cap_send_routed_data(net_protocol *protocol, struct net_route *route,
|
||||
net_buffer *buffer)
|
||||
{
|
||||
return protocol->next->module->send_routed_data(protocol->next, route, buffer);
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
l2cap_send_avail(net_protocol *protocol)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
l2cap_read_data(net_protocol *protocol, size_t numBytes, uint32 flags,
|
||||
net_buffer **_buffer)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
l2cap_read_avail(net_protocol *protocol)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
struct net_domain *
|
||||
l2cap_get_domain(net_protocol *protocol)
|
||||
{
|
||||
return protocol->next->module->get_domain(protocol->next);
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
l2cap_get_mtu(net_protocol *protocol, const struct sockaddr *address)
|
||||
{
|
||||
return protocol->next->module->get_mtu(protocol->next, address);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
l2cap_receive_data(net_buffer *buffer)
|
||||
{
|
||||
debugf("ICMP received some data, buffer length %lu\n", buffer->size);
|
||||
|
||||
NetBufferHeaderReader<hci_acl_header> bufferHeader(buffer);
|
||||
if (bufferHeader.Status() < B_OK)
|
||||
return bufferHeader.Status();
|
||||
|
||||
hci_acl_header &header = bufferHeader.Data();
|
||||
|
||||
debugf(" got type %u, code %u, checksum %u\n", header.type, header.code, ntohs(header.checksum));
|
||||
debugf(" computed checksum: %ld\n", gBufferModule->checksum(buffer, 0, buffer->size, true));
|
||||
|
||||
if (gBufferModule->checksum(buffer, 0, buffer->size, true) != 0)
|
||||
return B_BAD_DATA;
|
||||
|
||||
gBufferModule->free(buffer);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
l2cap_error(uint32 code, net_buffer *data)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
l2cap_error_reply(net_protocol *protocol, net_buffer *causedError, uint32 code,
|
||||
void *errorData)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
static status_t
|
||||
l2cap_std_ops(int32 op, ...)
|
||||
{
|
||||
switch (op) {
|
||||
case B_MODULE_INIT:
|
||||
{
|
||||
sStackModule->register_domain_protocols(AF_INET, SOCK_DGRAM, IPPROTO_ICMP,
|
||||
"network/protocols/l2cap/v1",
|
||||
NULL);
|
||||
|
||||
sStackModule->register_domain_receiving_protocol(AF_INET, IPPROTO_ICMP,
|
||||
"network/protocols/l2cap/v1");
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
case B_MODULE_UNINIT:
|
||||
return B_OK;
|
||||
|
||||
default:
|
||||
return B_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
net_protocol_module_info sL2CAPModule = {
|
||||
{
|
||||
"network/protocols/l2cap/v1",
|
||||
0,
|
||||
l2cap_std_ops
|
||||
},
|
||||
NET_PROTOCOL_ATOMIC_MESSAGES,
|
||||
|
||||
l2cap_init_protocol,
|
||||
l2cap_uninit_protocol,
|
||||
l2cap_open,
|
||||
l2cap_close,
|
||||
l2cap_free,
|
||||
l2cap_connect,
|
||||
l2cap_accept,
|
||||
l2cap_control,
|
||||
l2cap_getsockopt,
|
||||
l2cap_setsockopt,
|
||||
l2cap_bind,
|
||||
l2cap_unbind,
|
||||
l2cap_listen,
|
||||
l2cap_shutdown,
|
||||
l2cap_send_data,
|
||||
l2cap_send_routed_data,
|
||||
l2cap_send_avail,
|
||||
l2cap_read_data,
|
||||
l2cap_read_avail,
|
||||
l2cap_get_domain,
|
||||
l2cap_get_mtu,
|
||||
l2cap_receive_data,
|
||||
NULL,
|
||||
l2cap_error,
|
||||
l2cap_error_reply,
|
||||
};
|
||||
|
||||
module_dependency module_dependencies[] = {
|
||||
{NET_STACK_MODULE_NAME, (module_info **)&sStackModule},
|
||||
{NET_BUFFER_MODULE_NAME, (module_info **)&gBufferModule},
|
||||
{}
|
||||
};
|
||||
|
||||
module_info *modules[] = {
|
||||
(module_info *)&sL2CAPModule,
|
||||
NULL
|
||||
};
|
416
src/add-ons/kernel/network/protocols/l2cap/l2cap_address.cpp
Normal file
416
src/add-ons/kernel/network/protocols/l2cap/l2cap_address.cpp
Normal file
@ -0,0 +1,416 @@
|
||||
/*
|
||||
* Copyright 2006-2008, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Oliver Ruiz Dorantes, oliver-ruiz.dorantes_at_gmail.com
|
||||
*/
|
||||
|
||||
|
||||
#include <net_datalink.h>
|
||||
|
||||
#include <ByteOrder.h>
|
||||
#include <KernelExport.h>
|
||||
|
||||
#include <NetUtilities.h>
|
||||
|
||||
#include <memory.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <bluetooth/L2CAP/btL2CAP.h>
|
||||
|
||||
#define L2CAP_CHECKSUM(address) (address.b[0]+\
|
||||
address.b[1]+\
|
||||
address.b[2]+\
|
||||
address.b[3]+\
|
||||
address.b[4]+\
|
||||
address.b[5])
|
||||
|
||||
/*!
|
||||
Routing utility function: copies address \a from into a new address
|
||||
that is put into \a to.
|
||||
If \a replaceWithZeros is set \a from will be replaced by an empty
|
||||
address.
|
||||
If a \a mask is given it is applied to \a from (such that \a to is the
|
||||
result of \a from & \a mask).
|
||||
\return B_OK if the address could be copied
|
||||
\return B_NO_MEMORY if the new address could not be allocated
|
||||
\return B_MISMATCHED_VALUES if \a address does not match family AF_INET
|
||||
*/
|
||||
static status_t
|
||||
l2cap_copy_address(const sockaddr *from, sockaddr **to,
|
||||
bool replaceWithZeros = false, const sockaddr *mask = NULL)
|
||||
{
|
||||
if (replaceWithZeros) {
|
||||
*to = (sockaddr *)malloc(sizeof(sockaddr_in));
|
||||
if (*to == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
memset(*to, 0, sizeof(sockaddr_in));
|
||||
(*to)->sa_family = AF_INET;
|
||||
(*to)->sa_len = sizeof(sockaddr_in);
|
||||
} else {
|
||||
if (from == NULL)
|
||||
return B_OK;
|
||||
if (from->sa_family != AF_INET)
|
||||
return B_MISMATCHED_VALUES;
|
||||
|
||||
*to = (sockaddr *)malloc(sizeof(sockaddr_in));
|
||||
if (*to == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
memcpy(*to, from, sizeof(sockaddr_l2cap));
|
||||
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Routing utility function: applies \a mask to given \a address and puts
|
||||
the resulting address into \a result.
|
||||
\return B_OK if the mask has been applied
|
||||
\return B_BAD_VALUE if \a address or \a mask is NULL
|
||||
*/
|
||||
static status_t
|
||||
l2cap_mask_address(const sockaddr *address, const sockaddr *mask, sockaddr *result)
|
||||
{
|
||||
if (address == NULL || result == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Checks if the given \a address is the empty address. By default, the port
|
||||
is checked, too, but you can avoid that by passing \a checkPort = false.
|
||||
\return true if \a address is NULL, uninitialized or the empty address,
|
||||
false if not
|
||||
*/
|
||||
static bool
|
||||
l2cap_is_empty_address(const sockaddr *address, bool checkPort)
|
||||
{
|
||||
if (address == NULL || address->sa_len == 0)
|
||||
return true;
|
||||
|
||||
return ((bacmp(&((sockaddr_l2cap *)address)->l2cap_bdaddr, BDADDR_NULL)==0)
|
||||
&& (!checkPort || ((sockaddr_l2cap *)address)->l2cap_psm == 0) );
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Compares the IP-addresses of the two given address structures \a a and \a b.
|
||||
\return true if IP-addresses of \a a and \a b are equal, false if not
|
||||
*/
|
||||
static bool
|
||||
l2cap_equal_addresses(const sockaddr *a, const sockaddr *b)
|
||||
{
|
||||
if (a == NULL && b == NULL)
|
||||
return true;
|
||||
if (a != NULL && b == NULL)
|
||||
return l2cap_is_empty_address(a, false);
|
||||
if (a == NULL && b != NULL)
|
||||
return l2cap_is_empty_address(b, false);
|
||||
|
||||
return (bacmp(&((sockaddr_l2cap*)a)->l2cap_bdaddr,
|
||||
&((sockaddr_l2cap*)b)->l2cap_bdaddr)==0);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Compares the ports of the two given address structures \a a and \a b.
|
||||
\return true if ports of \a a and \a b are equal, false if not
|
||||
*/
|
||||
static bool
|
||||
l2cap_equal_ports(const sockaddr *a, const sockaddr *b)
|
||||
{
|
||||
uint16 portA = a ? ((sockaddr_l2cap *)a)->l2cap_psm : 0;
|
||||
uint16 portB = b ? ((sockaddr_l2cap *)b)->l2cap_psm : 0;
|
||||
return portA == portB;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Compares the IP-addresses and ports of the two given address structures
|
||||
\a a and \a b.
|
||||
\return true if IP-addresses and ports of \a a and \a b are equal, false if not
|
||||
*/
|
||||
static bool
|
||||
l2cap_equal_addresses_and_ports(const sockaddr *a, const sockaddr *b)
|
||||
{
|
||||
if (a == NULL && b == NULL)
|
||||
return true;
|
||||
if (a != NULL && b == NULL)
|
||||
return l2cap_is_empty_address(a, true);
|
||||
if (a == NULL && b != NULL)
|
||||
return l2cap_is_empty_address(b, true);
|
||||
|
||||
return (bacmp(&((sockaddr_l2cap*)a)->l2cap_bdaddr,&((sockaddr_l2cap *)b)->l2cap_bdaddr)==0)
|
||||
&& ((sockaddr_l2cap *)a)->l2cap_psm == ((sockaddr_l2cap *)b)->l2cap_psm;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Applies the given \a mask two \a a and \a b and then checks whether
|
||||
the masked addresses match.
|
||||
\return true if \a a matches \a b after masking both, false if not
|
||||
*/
|
||||
static bool
|
||||
l2cap_equal_masked_addresses(const sockaddr *a, const sockaddr *b,
|
||||
const sockaddr *mask)
|
||||
{
|
||||
if (a == NULL && b == NULL)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Routing utility function: determines the least significant bit that is set
|
||||
in the given \a mask.
|
||||
\return the number of the first bit that is set (0-32, where 32 means
|
||||
that there's no bit set in the mask).
|
||||
*/
|
||||
static int32
|
||||
l2cap_first_mask_bit(const sockaddr *_mask)
|
||||
{
|
||||
if (_mask == NULL)
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Routing utility function: checks the given \a mask for correctness (which
|
||||
means that (starting with LSB) consists zero or more unset bits, followed
|
||||
by bits that are all set).
|
||||
\return true if \a mask is ok, false if not
|
||||
*/
|
||||
static bool
|
||||
l2cap_check_mask(const sockaddr *_mask)
|
||||
{
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Creates a buffer for the given \a address and prints the address into
|
||||
it (hexadecimal representation in host byte order or '<none>').
|
||||
If \a printPort is set, the port is printed, too.
|
||||
\return B_OK if the address could be printed, \a buffer will point to
|
||||
the resulting string
|
||||
\return B_BAD_VALUE if no buffer has been given
|
||||
\return B_NO_MEMORY if the buffer could not be allocated
|
||||
*/
|
||||
static status_t
|
||||
l2cap_print_address_buffer(const sockaddr *_address, char *buffer,
|
||||
size_t bufferSize, bool printPort)
|
||||
{
|
||||
const sockaddr_l2cap *address = (const sockaddr_l2cap *)_address;
|
||||
|
||||
if (buffer == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
if (address == NULL)
|
||||
strlcpy(buffer, "<none>", bufferSize);
|
||||
else {
|
||||
bdaddr_t addr = address->l2cap_bdaddr;
|
||||
if (printPort) {
|
||||
snprintf(buffer, bufferSize, "%2X:%2X:%2X:%2X:%2X:%2X|%u", addr.b[0],
|
||||
addr.b[1],addr.b[2],addr.b[3],addr.b[4],addr.b[5],address->l2cap_psm);
|
||||
}
|
||||
else {
|
||||
snprintf(buffer, bufferSize, "%2X:%2X:%2X:%2X:%2X:%2X",addr.b[0],
|
||||
addr.b[1],addr.b[2],addr.b[3],addr.b[4],addr.b[5]);
|
||||
}
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
l2cap_print_address(const sockaddr *_address, char **_buffer, bool printPort)
|
||||
{
|
||||
if (_buffer == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
char tmp[32];
|
||||
l2cap_print_address_buffer(_address, tmp, sizeof(tmp), printPort);
|
||||
|
||||
*_buffer = strdup(tmp);
|
||||
if (*_buffer == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Determines the port of the given \a address.
|
||||
\return uint16 representing the port-nr
|
||||
*/
|
||||
static uint16
|
||||
l2cap_get_port(const sockaddr *address)
|
||||
{
|
||||
if (address == NULL)
|
||||
return 0;
|
||||
|
||||
return ((sockaddr_l2cap *)address)->l2cap_psm;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Sets the port of the given \a address to \a port.
|
||||
\return B_OK if the port has been set
|
||||
\return B_BAD_VALUE if \a address is NULL
|
||||
*/
|
||||
static status_t
|
||||
l2cap_set_port(sockaddr *address, uint16 port)
|
||||
{
|
||||
if (address == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
((sockaddr_l2cap *)address)->l2cap_psm = port;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Sets \a address to \a from.
|
||||
\return B_OK if \a from has been copied into \a address
|
||||
\return B_BAD_VALUE if either \a address or \a from is NULL
|
||||
\return B_MISMATCHED_VALUES if from is not of family AF_INET
|
||||
*/
|
||||
static status_t
|
||||
l2cap_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;
|
||||
|
||||
memcpy(address, from, sizeof(sockaddr_l2cap));
|
||||
address->sa_len = sizeof(sockaddr_l2cap);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
l2cap_update_to(sockaddr *_address, const sockaddr *_from)
|
||||
{
|
||||
sockaddr_l2cap *address = (sockaddr_l2cap *)_address;
|
||||
const sockaddr_l2cap *from = (const sockaddr_l2cap *)_from;
|
||||
|
||||
if (address == NULL || from == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
if (from->l2cap_family != AF_BLUETOOTH)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
address->l2cap_family = AF_INET;
|
||||
address->l2cap_len = sizeof(sockaddr_l2cap);
|
||||
|
||||
if (address->l2cap_psm == 0)
|
||||
address->l2cap_psm = from->l2cap_psm;
|
||||
|
||||
if (bacmp(&address->l2cap_bdaddr, BDADDR_BROADCAST)==0)
|
||||
address->l2cap_bdaddr = from->l2cap_bdaddr;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Sets \a address to the empty address (0.0.0.0).
|
||||
\return B_OK if \a address has been set
|
||||
\return B_BAD_VALUE if \a address is NULL
|
||||
*/
|
||||
static status_t
|
||||
l2cap_set_to_empty_address(sockaddr *address)
|
||||
{
|
||||
if (address == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
memset(address, 0, sizeof(sockaddr_l2cap));
|
||||
address->sa_len = sizeof(sockaddr_l2cap);
|
||||
address->sa_family = AF_BLUETOOTH;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
l2cap_set_to_defaults(sockaddr *_defaultMask, sockaddr *_defaultBroadcast,
|
||||
sockaddr *_address, sockaddr *_mask)
|
||||
{
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
/*!
|
||||
Computes a hash-value of the given addresses \a ourAddress
|
||||
and \a peerAddress.
|
||||
\return uint32 representing the hash-value
|
||||
*/
|
||||
static uint32
|
||||
l2cap_hash_address_pair(const sockaddr *ourAddress, const sockaddr *peerAddress)
|
||||
{
|
||||
const sockaddr_l2cap *our = (const sockaddr_l2cap *)ourAddress;
|
||||
const sockaddr_l2cap *peer = (const sockaddr_l2cap *)peerAddress;
|
||||
|
||||
return ((our ? our->l2cap_psm : 0) | ((peer ? peer->l2cap_psm : 0) << 16))
|
||||
^ (our ? L2CAP_CHECKSUM(our->l2cap_bdaddr) : 0) ^ (peer ? L2CAP_CHECKSUM(peer->l2cap_bdaddr) : 0);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Adds the given \a address to the IP-checksum \a checksum.
|
||||
\return B_OK if \a address has been added to the checksum
|
||||
\return B_BAD_VALUE if either \a address or \a checksum is NULL
|
||||
*/
|
||||
static status_t
|
||||
l2cap_checksum_address(struct Checksum *checksum, const sockaddr *address)
|
||||
{
|
||||
if (checksum == NULL || address == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
for (uint i = 0; i < sizeof(bdaddr_t); i++)
|
||||
(*checksum) << ((sockaddr_l2cap*)address)->l2cap_bdaddr.b[i];
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
net_address_module_info gL2cap4AddressModule = {
|
||||
{
|
||||
NULL,
|
||||
0,
|
||||
NULL
|
||||
},
|
||||
l2cap_copy_address,
|
||||
l2cap_mask_address,
|
||||
l2cap_equal_addresses,
|
||||
l2cap_equal_ports,
|
||||
l2cap_equal_addresses_and_ports,
|
||||
l2cap_equal_masked_addresses,
|
||||
l2cap_is_empty_address,
|
||||
l2cap_first_mask_bit,
|
||||
l2cap_check_mask,
|
||||
l2cap_print_address,
|
||||
l2cap_print_address_buffer,
|
||||
l2cap_get_port,
|
||||
l2cap_set_port,
|
||||
l2cap_set_to,
|
||||
l2cap_set_to_empty_address,
|
||||
l2cap_set_to_defaults,
|
||||
l2cap_update_to,
|
||||
l2cap_hash_address_pair,
|
||||
l2cap_checksum_address,
|
||||
NULL // l2cap_matches_broadcast_address,
|
||||
};
|
15
src/add-ons/kernel/network/protocols/l2cap/l2cap_address.h
Normal file
15
src/add-ons/kernel/network/protocols/l2cap/l2cap_address.h
Normal file
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright 2006, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Oliver Ruiz Dorantes, oliver-ruiz.dorantes_at_gmail.com
|
||||
*/
|
||||
|
||||
|
||||
#ifndef L2CAP_ADDRESS_H
|
||||
#define L2CAP_ADDRESS_H
|
||||
|
||||
extern struct net_address_module_info gL2cap4AddressModule;
|
||||
|
||||
#endif // L2CAP_ADDRESS_H
|
Loading…
Reference in New Issue
Block a user