added join_multicast/leave_multicast to datalink protocols, preparing for full multicast support.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20944 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Hugo Santos 2007-05-01 11:38:39 +00:00
parent 5d1514bdd9
commit 1a41adbcd2
5 changed files with 122 additions and 22 deletions

View File

@ -30,6 +30,11 @@ struct net_datalink_protocol_module_info {
status_t (*control)(net_datalink_protocol *self,
int32 op, void *argument, size_t length);
status_t (*join_multicast)(net_datalink_protocol *self,
const sockaddr *address);
status_t (*leave_multicast)(net_datalink_protocol *self,
const sockaddr *address);
};
#endif // NET_DATALINK_PROTOCOL_H

View File

@ -248,6 +248,32 @@ arp_entry::MarkValid()
}
static void
ipv4_to_ether_multicast(sockaddr_dl *destination, const sockaddr_in *source)
{
// RFC 1112 - Host extensions for IP multicasting
//
// ``An IP host group address is mapped to an Ethernet multicast
// address by placing the low-order 23-bits of the IP address into
// the low-order 23 bits of the Ethernet multicast address
// 01-00-5E-00-00-00 (hex).''
memcpy(((uint8 *)destination->sdl_data) + 2, &source->sin_addr,
sizeof(in_addr));
destination->sdl_len = sizeof(sockaddr_dl);
destination->sdl_family = AF_DLI;
destination->sdl_index = 0;
destination->sdl_type = IFT_ETHER;
destination->sdl_e_type = ETHER_TYPE_IP;
destination->sdl_nlen = destination->sdl_slen = 0;
destination->sdl_alen = ETHER_ADDRESS_LENGTH;
uint32 *data = (uint32 *)destination->sdl_data;
data[0] = (data[0] & htonl(0x7f)) | htonl(0x01005e00);
}
// #pragma mark -
@ -791,28 +817,11 @@ arp_send_data(net_datalink_protocol *protocol,
entry->hardware_address.sdl_len);
if (buffer->flags & MSG_MCAST) {
// RFC 1112 - Host extensions for IP multicasting
//
// ``An IP host group address is mapped to an Ethernet multicast
// address by placing the low-order 23-bits of the IP address into
// the low-order 23 bits of the Ethernet multicast address
// 01-00-5E-00-00-00 (hex).''
sockaddr_dl *destination = (sockaddr_dl *)&buffer->destination;
memmove(((uint8 *)destination->sdl_data) + 2,
&((sockaddr_in *)&buffer->destination)->sin_addr, sizeof(in_addr));
destination->sdl_len = sizeof(sockaddr_dl);
destination->sdl_family = AF_DLI;
destination->sdl_index = 0;
destination->sdl_type = IFT_ETHER;
destination->sdl_e_type = ETHER_TYPE_IP;
destination->sdl_nlen = destination->sdl_slen = 0;
destination->sdl_alen = ETHER_ADDRESS_LENGTH;
uint32 *data = (uint32 *)destination->sdl_data;
data[0] = (data[0] & htonl(0x7f)) | htonl(0x01005e00);
sockaddr_dl multicastDestination;
ipv4_to_ether_multicast(&multicastDestination,
(sockaddr_in *)&buffer->destination);
memcpy(&buffer->destination, &multicastDestination,
sizeof(multicastDestination));
} else if ((buffer->flags & MSG_BCAST) == 0) {
// Lookup destination (we may need to wait for this)
entry = arp_entry::Lookup(
@ -927,6 +936,34 @@ arp_control(net_datalink_protocol *protocol,
}
static status_t
arp_join_multicast(net_datalink_protocol *protocol, const sockaddr *address)
{
if (address->sa_family != AF_INET)
return EINVAL;
sockaddr_dl multicastAddress;
ipv4_to_ether_multicast(&multicastAddress, (const sockaddr_in *)address);
return protocol->next->module->join_multicast(protocol->next,
(sockaddr *)&multicastAddress);
}
static status_t
arp_leave_multicast(net_datalink_protocol *protocol, const sockaddr *address)
{
if (address->sa_family != AF_INET)
return EINVAL;
sockaddr_dl multicastAddress;
ipv4_to_ether_multicast(&multicastAddress, (const sockaddr_in *)address);
return protocol->next->module->leave_multicast(protocol->next,
(sockaddr *)&multicastAddress);
}
static status_t
arp_std_ops(int32 op, ...)
{
@ -954,6 +991,8 @@ static net_datalink_protocol_module_info sARPModule = {
arp_up,
arp_down,
arp_control,
arp_join_multicast,
arp_leave_multicast,
};

View File

@ -169,6 +169,22 @@ ethernet_frame_control(net_datalink_protocol *protocol,
}
static status_t
ethernet_frame_join_multicast(net_datalink_protocol *protocol,
const sockaddr *address)
{
return protocol->next->module->join_multicast(protocol, address);
}
static status_t
ethernet_frame_leave_multicast(net_datalink_protocol *protocol,
const sockaddr *address)
{
return protocol->next->module->leave_multicast(protocol, address);
}
static status_t
ethernet_frame_std_ops(int32 op, ...)
{
@ -197,6 +213,8 @@ static net_datalink_protocol_module_info sEthernetFrameModule = {
ethernet_frame_up,
ethernet_frame_down,
ethernet_frame_control,
ethernet_frame_join_multicast,
ethernet_frame_leave_multicast,
};
module_info *modules[] = {

View File

@ -130,6 +130,22 @@ loopback_frame_control(net_datalink_protocol *protocol,
}
static status_t
loopback_frame_join_multicast(net_datalink_protocol *protocol,
const sockaddr *address)
{
return protocol->next->module->join_multicast(protocol, address);
}
static status_t
loopback_frame_leave_multicast(net_datalink_protocol *protocol,
const sockaddr *address)
{
return protocol->next->module->leave_multicast(protocol, address);
}
static status_t
loopback_frame_std_ops(int32 op, ...)
{
@ -158,6 +174,8 @@ static net_datalink_protocol_module_info sLoopbackFrameModule = {
loopback_frame_up,
loopback_frame_down,
loopback_frame_control,
loopback_frame_join_multicast,
loopback_frame_leave_multicast,
};
module_info *modules[] = {

View File

@ -799,6 +799,24 @@ interface_protocol_control(net_datalink_protocol *_protocol,
}
static status_t
interface_protocol_join_multicast(net_datalink_protocol *_protocol,
const sockaddr *address)
{
// TODO
return EINVAL;
}
static status_t
interface_protocol_leave_multicast(net_datalink_protocol *_protocol,
const sockaddr *address)
{
// TODO
return EINVAL;
}
net_datalink_module_info gNetDatalinkModule = {
{
NET_DATALINK_MODULE_NAME,
@ -835,4 +853,6 @@ net_datalink_protocol_module_info gDatalinkInterfaceProtocolModule = {
interface_protocol_up,
interface_protocol_down,
interface_protocol_control,
interface_protocol_join_multicast,
interface_protocol_leave_multicast,
};