* Applied next work in progress patch by Atis that takes into account most of
my comments so far. Thanks! git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@37793 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -98,9 +98,11 @@ struct net_datalink_module_info {
|
|||||||
struct net_route_info *info);
|
struct net_route_info *info);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS 0x01
|
||||||
|
|
||||||
struct net_address_module_info {
|
struct net_address_module_info {
|
||||||
module_info info;
|
module_info info;
|
||||||
bool has_broadcast_address;
|
uint32 flags;
|
||||||
|
|
||||||
status_t (*copy_address)(const sockaddr *from, sockaddr **to,
|
status_t (*copy_address)(const sockaddr *from, sockaddr **to,
|
||||||
bool replaceWithZeros, const sockaddr *mask);
|
bool replaceWithZeros, const sockaddr *mask);
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ struct net_datalink_protocol_module_info {
|
|||||||
|
|
||||||
status_t (*send_data)(net_datalink_protocol *self,
|
status_t (*send_data)(net_datalink_protocol *self,
|
||||||
net_buffer *buffer);
|
net_buffer *buffer);
|
||||||
status_t (*receive_data)(net_buffer *buffer);
|
|
||||||
|
|
||||||
status_t (*interface_up)(net_datalink_protocol *self);
|
status_t (*interface_up)(net_datalink_protocol *self);
|
||||||
void (*interface_down)(net_datalink_protocol *self);
|
void (*interface_down)(net_datalink_protocol *self);
|
||||||
|
|||||||
@@ -1095,7 +1095,6 @@ static net_datalink_protocol_module_info sARPModule = {
|
|||||||
arp_init_protocol,
|
arp_init_protocol,
|
||||||
arp_uninit_protocol,
|
arp_uninit_protocol,
|
||||||
arp_send_data,
|
arp_send_data,
|
||||||
NULL, // receive_data
|
|
||||||
arp_up,
|
arp_up,
|
||||||
arp_down,
|
arp_down,
|
||||||
arp_control,
|
arp_control,
|
||||||
|
|||||||
@@ -210,7 +210,6 @@ static net_datalink_protocol_module_info sEthernetFrameModule = {
|
|||||||
ethernet_frame_init,
|
ethernet_frame_init,
|
||||||
ethernet_frame_uninit,
|
ethernet_frame_uninit,
|
||||||
ethernet_frame_send_data,
|
ethernet_frame_send_data,
|
||||||
NULL, // receive_data
|
|
||||||
ethernet_frame_up,
|
ethernet_frame_up,
|
||||||
ethernet_frame_down,
|
ethernet_frame_down,
|
||||||
ethernet_frame_control,
|
ethernet_frame_control,
|
||||||
|
|||||||
@@ -127,6 +127,7 @@ ipv4_datalink_std_ops(int32 op, ...)
|
|||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
net_datalink_protocol_module_info gIPv4DataLinkModule = {
|
net_datalink_protocol_module_info gIPv4DataLinkModule = {
|
||||||
{
|
{
|
||||||
"network/datalink_protocols/ipv4_datagram/v1",
|
"network/datalink_protocols/ipv4_datagram/v1",
|
||||||
@@ -136,7 +137,6 @@ net_datalink_protocol_module_info gIPv4DataLinkModule = {
|
|||||||
ipv4_datalink_init,
|
ipv4_datalink_init,
|
||||||
ipv4_datalink_uninit,
|
ipv4_datalink_uninit,
|
||||||
ipv4_datalink_send_data,
|
ipv4_datalink_send_data,
|
||||||
NULL, // receive_data
|
|
||||||
ipv4_datalink_up,
|
ipv4_datalink_up,
|
||||||
ipv4_datalink_down,
|
ipv4_datalink_down,
|
||||||
ipv4_datalink_control,
|
ipv4_datalink_control,
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ if $(TARGET_PLATFORM) != haiku {
|
|||||||
|
|
||||||
UsePrivateKernelHeaders ;
|
UsePrivateKernelHeaders ;
|
||||||
UsePrivateHeaders kernel net ;
|
UsePrivateHeaders kernel net ;
|
||||||
|
UseHeaders [ FDirName $(HAIKU_TOP) src add-ons kernel network protocols ] : true ;
|
||||||
|
|
||||||
KernelAddon ipv6_datagram :
|
KernelAddon ipv6_datagram :
|
||||||
ipv6_datagram.cpp
|
ipv6_datagram.cpp
|
||||||
|
|||||||
@@ -31,8 +31,9 @@
|
|||||||
|
|
||||||
#include <new>
|
#include <new>
|
||||||
|
|
||||||
#include "../../protocols/ipv6/jenkins.h" // TODO: move this file
|
#include <ipv6/jenkins.h>
|
||||||
#include "../../protocols/ipv6/ipv6_address.h"
|
#include <ipv6/ipv6_address.h>
|
||||||
|
#include "ndp.h"
|
||||||
|
|
||||||
|
|
||||||
#define TRACE_NDP
|
#define TRACE_NDP
|
||||||
@@ -83,6 +84,18 @@ struct neighbor_discovery_header {
|
|||||||
uint8 link_address[ETHER_ADDRESS_LENGTH];
|
uint8 link_address[ETHER_ADDRESS_LENGTH];
|
||||||
} _PACKED;
|
} _PACKED;
|
||||||
|
|
||||||
|
struct router_advertisement_header {
|
||||||
|
uint8 icmp6_type;
|
||||||
|
uint8 icmp6_code;
|
||||||
|
uint16 icmp6_checksum;
|
||||||
|
uint8 hop_limit;
|
||||||
|
uint8 flags;
|
||||||
|
uint16 router_lifetime;
|
||||||
|
uint32 reachable_time;
|
||||||
|
uint32 retransmit_timer;
|
||||||
|
uint8 options[];
|
||||||
|
} _PACKED;
|
||||||
|
|
||||||
|
|
||||||
struct ndp_entry {
|
struct ndp_entry {
|
||||||
ndp_entry* next;
|
ndp_entry* next;
|
||||||
@@ -532,8 +545,10 @@ ndp_update_local(ipv6_datalink_protocol* protocol)
|
|||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
handle_neighbor_solicitation(net_buffer* buffer)
|
ndp_receive_solicitation(net_buffer* buffer, bool* reuseBuffer)
|
||||||
{
|
{
|
||||||
|
*reuseBuffer = false;
|
||||||
|
|
||||||
NetBufferHeaderReader<neighbor_discovery_header> bufferHeader(buffer);
|
NetBufferHeaderReader<neighbor_discovery_header> bufferHeader(buffer);
|
||||||
if (bufferHeader.Status() < B_OK)
|
if (bufferHeader.Status() < B_OK)
|
||||||
return bufferHeader.Status();
|
return bufferHeader.Status();
|
||||||
@@ -594,22 +609,19 @@ handle_neighbor_solicitation(net_buffer* buffer)
|
|||||||
buffer->flags = 0;
|
buffer->flags = 0;
|
||||||
// make sure this won't be a broadcast message
|
// make sure this won't be a broadcast message
|
||||||
|
|
||||||
// TODO: there is not need to clone, could reuse old buffer
|
|
||||||
net_buffer* clone = gBufferModule->clone(buffer, true);
|
|
||||||
if (clone == NULL)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
|
|
||||||
if (sIPv6Protocol == NULL)
|
if (sIPv6Protocol == NULL)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
|
*reuseBuffer = true;
|
||||||
|
|
||||||
// send the ICMPv6 packet out
|
// send the ICMPv6 packet out
|
||||||
TRACE(("Sending Neighbor Advertisement\n"));
|
TRACE(("Sending Neighbor Advertisement\n"));
|
||||||
return sIPv6Module->send_data(sIPv6Protocol, clone);
|
return sIPv6Module->send_data(sIPv6Protocol, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_neighbor_advertisement(net_buffer* buffer)
|
ndp_receive_advertisement(net_buffer* buffer)
|
||||||
{
|
{
|
||||||
// TODO: also process unsolicited advertisments?
|
// TODO: also process unsolicited advertisments?
|
||||||
if ((buffer->flags & MSG_MCAST) != 0)
|
if ((buffer->flags & MSG_MCAST) != 0)
|
||||||
@@ -641,6 +653,53 @@ handle_neighbor_advertisement(net_buffer* buffer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
ndp_receive_router_advertisement(net_buffer* buffer)
|
||||||
|
{
|
||||||
|
NetBufferHeaderReader<router_advertisement_header> bufferHeader(buffer);
|
||||||
|
if (bufferHeader.Status() < B_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// TODO: check for validity
|
||||||
|
|
||||||
|
// TODO: parse the options
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
ndp_receive_data(net_buffer* buffer)
|
||||||
|
{
|
||||||
|
dprintf("ndp_receive_data\n");
|
||||||
|
|
||||||
|
NetBufferHeaderReader<icmp6_hdr> icmp6Header(buffer);
|
||||||
|
if (icmp6Header.Status() < B_OK)
|
||||||
|
return icmp6Header.Status();
|
||||||
|
|
||||||
|
bool reuseBuffer = false;
|
||||||
|
|
||||||
|
switch (icmp6Header->icmp6_type) {
|
||||||
|
case ND_NEIGHBOR_SOLICIT:
|
||||||
|
TRACE((" received Neighbor Solicitation\n"));
|
||||||
|
ndp_receive_solicitation(buffer, &reuseBuffer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ND_NEIGHBOR_ADVERT:
|
||||||
|
TRACE((" received Neighbor Advertisement\n"));
|
||||||
|
ndp_receive_advertisement(buffer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ND_ROUTER_ADVERT:
|
||||||
|
TRACE((" received Router Advertisement\n"));
|
||||||
|
ndp_receive_router_advertisement(buffer);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reuseBuffer == false)
|
||||||
|
gBufferModule->free(buffer);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ndp_timer(struct net_timer* timer, void* data)
|
ndp_timer(struct net_timer* timer, void* data)
|
||||||
{
|
{
|
||||||
@@ -897,30 +956,6 @@ ipv6_datalink_send_data(net_datalink_protocol* _protocol, net_buffer* buffer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
|
||||||
ipv6_datalink_receive_data(net_buffer* buffer)
|
|
||||||
{
|
|
||||||
NetBufferHeaderReader<icmp6_hdr> bufferHeader(buffer);
|
|
||||||
if (bufferHeader.Status() < B_OK)
|
|
||||||
return bufferHeader.Status();
|
|
||||||
|
|
||||||
switch (bufferHeader->icmp6_type) {
|
|
||||||
case ND_NEIGHBOR_SOLICIT:
|
|
||||||
TRACE((" received Neighbor Solicitation\n"));
|
|
||||||
handle_neighbor_solicitation(buffer);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ND_NEIGHBOR_ADVERT:
|
|
||||||
TRACE((" received Neighbor Advertisement\n"));
|
|
||||||
handle_neighbor_advertisement(buffer);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
gBufferModule->free(buffer);
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
ipv6_datalink_up(net_datalink_protocol* _protocol)
|
ipv6_datalink_up(net_datalink_protocol* _protocol)
|
||||||
{
|
{
|
||||||
@@ -1058,6 +1093,7 @@ ipv6_datalink_std_ops(int32 op, ...)
|
|||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
net_datalink_protocol_module_info gIPv6DataLinkModule = {
|
net_datalink_protocol_module_info gIPv6DataLinkModule = {
|
||||||
{
|
{
|
||||||
"network/datalink_protocols/ipv6_datagram/v1",
|
"network/datalink_protocols/ipv6_datagram/v1",
|
||||||
@@ -1067,7 +1103,6 @@ net_datalink_protocol_module_info gIPv6DataLinkModule = {
|
|||||||
ipv6_datalink_init,
|
ipv6_datalink_init,
|
||||||
ipv6_datalink_uninit,
|
ipv6_datalink_uninit,
|
||||||
ipv6_datalink_send_data,
|
ipv6_datalink_send_data,
|
||||||
ipv6_datalink_receive_data,
|
|
||||||
ipv6_datalink_up,
|
ipv6_datalink_up,
|
||||||
ipv6_datalink_down,
|
ipv6_datalink_down,
|
||||||
ipv6_datalink_control,
|
ipv6_datalink_control,
|
||||||
@@ -1075,6 +1110,14 @@ net_datalink_protocol_module_info gIPv6DataLinkModule = {
|
|||||||
ipv6_datalink_leave_multicast,
|
ipv6_datalink_leave_multicast,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
net_ndp_module_info gIPv6NDPModule = {
|
||||||
|
{
|
||||||
|
"network/datalink_protocols/ipv6_datagram/ndp/v1",
|
||||||
|
0,
|
||||||
|
NULL
|
||||||
|
},
|
||||||
|
ndp_receive_data
|
||||||
|
};
|
||||||
|
|
||||||
module_dependency module_dependencies[] = {
|
module_dependency module_dependencies[] = {
|
||||||
{NET_STACK_MODULE_NAME, (module_info**)&sStackModule},
|
{NET_STACK_MODULE_NAME, (module_info**)&sStackModule},
|
||||||
@@ -1085,5 +1128,6 @@ module_dependency module_dependencies[] = {
|
|||||||
|
|
||||||
module_info* modules[] = {
|
module_info* modules[] = {
|
||||||
(module_info*)&gIPv6DataLinkModule,
|
(module_info*)&gIPv6DataLinkModule,
|
||||||
|
(module_info*)&gIPv6NDPModule,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef IPV6_NDP_H
|
||||||
|
#define IPV6_NDP_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <net_buffer.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct net_ndp_module_info {
|
||||||
|
module_info info;
|
||||||
|
|
||||||
|
status_t (*receive_data)(net_buffer* buffer);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // IPV6_NDP_H
|
||||||
@@ -171,7 +171,6 @@ static net_datalink_protocol_module_info sLoopbackFrameModule = {
|
|||||||
loopback_frame_init,
|
loopback_frame_init,
|
||||||
loopback_frame_uninit,
|
loopback_frame_uninit,
|
||||||
loopback_frame_send_data,
|
loopback_frame_send_data,
|
||||||
NULL, // receive_data
|
|
||||||
loopback_frame_up,
|
loopback_frame_up,
|
||||||
loopback_frame_down,
|
loopback_frame_down,
|
||||||
loopback_frame_control,
|
loopback_frame_control,
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ if $(TARGET_PLATFORM) != haiku {
|
|||||||
}
|
}
|
||||||
|
|
||||||
UsePrivateHeaders kernel net ;
|
UsePrivateHeaders kernel net ;
|
||||||
|
UseHeaders [ FDirName $(HAIKU_TOP) src add-ons kernel network protocols ] : true ;
|
||||||
|
UseHeaders [ FDirName $(HAIKU_TOP) src add-ons kernel network datalink_protocols ] : true ;
|
||||||
|
|
||||||
KernelAddon icmp6 :
|
KernelAddon icmp6 :
|
||||||
icmp6.cpp
|
icmp6.cpp
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include <net_protocol.h>
|
#include <net_protocol.h>
|
||||||
#include <net_stack.h>
|
#include <net_stack.h>
|
||||||
#include <net_datalink_protocol.h>
|
#include <net_datalink_protocol.h>
|
||||||
|
#include <NetUtilities.h>
|
||||||
#include <NetBufferUtilities.h>
|
#include <NetBufferUtilities.h>
|
||||||
|
|
||||||
#include <KernelExport.h>
|
#include <KernelExport.h>
|
||||||
@@ -19,7 +20,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "../ipv6/ipv6_utils.h" // ipv6_checksum()
|
#include <ipv6_datagram/ndp.h>
|
||||||
|
|
||||||
|
|
||||||
#define TRACE_ICMP6
|
#define TRACE_ICMP6
|
||||||
@@ -35,7 +36,7 @@ typedef NetBufferField<uint16, offsetof(icmp6_hdr, icmp6_cksum)> ICMP6ChecksumFi
|
|||||||
|
|
||||||
net_buffer_module_info *gBufferModule;
|
net_buffer_module_info *gBufferModule;
|
||||||
static net_stack_module_info *sStackModule;
|
static net_stack_module_info *sStackModule;
|
||||||
static net_datalink_protocol_module_info *sIPv6DatalinkModule;
|
static net_ndp_module_info *sIPv6NDPModule;
|
||||||
|
|
||||||
|
|
||||||
net_protocol *
|
net_protocol *
|
||||||
@@ -212,17 +213,22 @@ icmp6_receive_data(net_buffer *buffer)
|
|||||||
TRACE((" got type %u, code %u, checksum 0x%x\n", header.icmp6_type,
|
TRACE((" got type %u, code %u, checksum 0x%x\n", header.icmp6_type,
|
||||||
header.icmp6_code, header.icmp6_cksum));
|
header.icmp6_code, header.icmp6_cksum));
|
||||||
|
|
||||||
|
net_domain* domain;
|
||||||
|
if (buffer->interface != NULL)
|
||||||
|
domain = buffer->interface->domain;
|
||||||
|
else
|
||||||
|
domain = sStackModule->get_domain(buffer->source->sa_family);
|
||||||
|
|
||||||
|
// TODO: possible?
|
||||||
|
if (domain == NULL || domain->module == NULL)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
net_address_module_info* addressModule = domain->address_module;
|
||||||
|
|
||||||
// compute and check the checksum
|
// compute and check the checksum
|
||||||
uint16 checksum;
|
if (Checksum::PseudoHeader(addressModule, gBufferModule, buffer,
|
||||||
checksum = gBufferModule->checksum(buffer, 0, buffer->size, false);
|
IPPROTO_ICMPV6) != 0)
|
||||||
checksum = ipv6_checksum(&((sockaddr_in6*)buffer->source)->sin6_addr,
|
return B_BAD_DATA;
|
||||||
&((sockaddr_in6*)buffer->destination)->sin6_addr,
|
|
||||||
buffer->size, IPPROTO_ICMPV6, checksum);
|
|
||||||
|
|
||||||
TRACE((" computed checksum: %ld\n", checksum));
|
|
||||||
|
|
||||||
if (checksum != 0)
|
|
||||||
return B_BAD_DATA;
|
|
||||||
|
|
||||||
switch (header.icmp6_type) {
|
switch (header.icmp6_type) {
|
||||||
case ICMP6_ECHO_REPLY:
|
case ICMP6_ECHO_REPLY:
|
||||||
@@ -230,20 +236,13 @@ icmp6_receive_data(net_buffer *buffer)
|
|||||||
|
|
||||||
case ICMP6_ECHO_REQUEST:
|
case ICMP6_ECHO_REQUEST:
|
||||||
{
|
{
|
||||||
net_domain *domain;
|
|
||||||
if (buffer->interface != NULL) {
|
if (buffer->interface != NULL) {
|
||||||
domain = buffer->interface->domain;
|
|
||||||
|
|
||||||
// We only reply to echo requests of our local interface; we
|
// We only reply to echo requests of our local interface; we
|
||||||
// don't reply to broadcast requests
|
// don't reply to broadcast requests
|
||||||
if (!domain->address_module->equal_addresses(
|
if (!domain->address_module->equal_addresses(
|
||||||
buffer->interface->address, buffer->destination))
|
buffer->interface->address, buffer->destination))
|
||||||
break;
|
break;
|
||||||
} else
|
}
|
||||||
domain = sStackModule->get_domain(buffer->source->sa_family);
|
|
||||||
|
|
||||||
if (domain == NULL || domain->module == NULL)
|
|
||||||
break;
|
|
||||||
|
|
||||||
net_buffer *reply = gBufferModule->duplicate(buffer);
|
net_buffer *reply = gBufferModule->duplicate(buffer);
|
||||||
if (reply == NULL)
|
if (reply == NULL)
|
||||||
@@ -260,11 +259,8 @@ icmp6_receive_data(net_buffer *buffer)
|
|||||||
|
|
||||||
header.Sync();
|
header.Sync();
|
||||||
|
|
||||||
checksum = gBufferModule->checksum(buffer, 0, buffer->size, false);
|
*ICMP6ChecksumField(reply) = Checksum::PseudoHeader(addressModule,
|
||||||
*ICMP6ChecksumField(reply) =
|
gBufferModule, buffer, IPPROTO_ICMPV6);
|
||||||
ipv6_checksum(&((sockaddr_in6*)buffer->source)->sin6_addr,
|
|
||||||
&((sockaddr_in6*)buffer->destination)->sin6_addr,
|
|
||||||
buffer->size, IPPROTO_ICMPV6, checksum);
|
|
||||||
|
|
||||||
status_t status = domain->module->send_data(NULL, reply);
|
status_t status = domain->module->send_data(NULL, reply);
|
||||||
if (status < B_OK) {
|
if (status < B_OK) {
|
||||||
@@ -274,8 +270,8 @@ icmp6_receive_data(net_buffer *buffer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// forward unrecognized messages to datalink layer
|
// unrecognized messages go to neighbor discovery protocol handler
|
||||||
return sIPv6DatalinkModule->receive_data(buffer);
|
return sIPv6NDPModule->receive_data(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
gBufferModule->free(buffer);
|
gBufferModule->free(buffer);
|
||||||
@@ -383,8 +379,8 @@ net_protocol_module_info sICMP6Module = {
|
|||||||
module_dependency module_dependencies[] = {
|
module_dependency module_dependencies[] = {
|
||||||
{NET_STACK_MODULE_NAME, (module_info **)&sStackModule},
|
{NET_STACK_MODULE_NAME, (module_info **)&sStackModule},
|
||||||
{NET_BUFFER_MODULE_NAME, (module_info **)&gBufferModule},
|
{NET_BUFFER_MODULE_NAME, (module_info **)&gBufferModule},
|
||||||
{"network/datalink_protocols/ipv6_datagram/v1",
|
{"network/datalink_protocols/ipv6_datagram/ndp/v1",
|
||||||
(module_info **)&sIPv6DatalinkModule},
|
(module_info **)&sIPv6NDPModule},
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -507,7 +507,7 @@ net_address_module_info gIPv4AddressModule = {
|
|||||||
0,
|
0,
|
||||||
NULL
|
NULL
|
||||||
},
|
},
|
||||||
true, // has_broadcast_address
|
NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS,
|
||||||
ipv4_copy_address,
|
ipv4_copy_address,
|
||||||
ipv4_mask_address,
|
ipv4_mask_address,
|
||||||
ipv4_equal_addresses,
|
ipv4_equal_addresses,
|
||||||
|
|||||||
@@ -52,13 +52,13 @@
|
|||||||
|
|
||||||
|
|
||||||
struct IPv6Header {
|
struct IPv6Header {
|
||||||
struct ip6_hdr h;
|
struct ip6_hdr header;
|
||||||
|
|
||||||
uint8 ProtocolVersion() const { return h.ip6_vfc & IPV6_VERSION_MASK; }
|
uint8 ProtocolVersion() const { return header.ip6_vfc & IPV6_VERSION_MASK; }
|
||||||
uint8 ServiceType() const { return ntohl(h.ip6_flow) >> 20;}
|
uint8 ServiceType() const { return ntohl(header.ip6_flow) >> 20;}
|
||||||
uint16 PayloadLength() const { return ntohs(h.ip6_plen); }
|
uint16 PayloadLength() const { return ntohs(header.ip6_plen); }
|
||||||
const in6_addr& Dst() const { return h.ip6_dst; }
|
const in6_addr& Dst() const { return header.ip6_dst; }
|
||||||
const in6_addr& Src() const { return h.ip6_src; }
|
const in6_addr& Src() const { return header.ip6_src; }
|
||||||
uint16 GetTransportHeaderOffset(net_buffer* buffer) const;
|
uint16 GetTransportHeaderOffset(net_buffer* buffer) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -139,7 +139,7 @@ uint16
|
|||||||
IPv6Header::GetTransportHeaderOffset(net_buffer* buffer) const
|
IPv6Header::GetTransportHeaderOffset(net_buffer* buffer) const
|
||||||
{
|
{
|
||||||
uint16 offset = sizeof(struct ip6_hdr);
|
uint16 offset = sizeof(struct ip6_hdr);
|
||||||
uint8 next = h.ip6_nxt;
|
uint8 next = header.ip6_nxt;
|
||||||
|
|
||||||
// these are the extension headers that might be supported one day
|
// these are the extension headers that might be supported one day
|
||||||
while (next == IPPROTO_HOPOPTS
|
while (next == IPPROTO_HOPOPTS
|
||||||
@@ -192,10 +192,11 @@ dump_ipv6_header(IPv6Header &header)
|
|||||||
dprintf(" version: %d\n", header.ProtocolVersion() >> 4);
|
dprintf(" version: %d\n", header.ProtocolVersion() >> 4);
|
||||||
dprintf(" service_type: %d\n", header.ServiceType());
|
dprintf(" service_type: %d\n", header.ServiceType());
|
||||||
dprintf(" payload_length: %d\n", header.PayloadLength());
|
dprintf(" payload_length: %d\n", header.PayloadLength());
|
||||||
dprintf(" next_header: %d\n", header.h.ip6_nxt);
|
dprintf(" next_header: %d\n", header.header.ip6_nxt);
|
||||||
dprintf(" hop_limit: %d\n", header.h.ip6_hops);
|
dprintf(" hop_limit: %d\n", header.header.ip6_hops);
|
||||||
dprintf(" source: %s\n", ip6_sprintf(&header.h.ip6_src, addrbuf));
|
dprintf(" source: %s\n", ip6_sprintf(&header.header.ip6_src, addrbuf));
|
||||||
dprintf(" destination: %s\n", ip6_sprintf(&header.h.ip6_dst, addrbuf));
|
dprintf(" destination: %s\n",
|
||||||
|
ip6_sprintf(&header.header.ip6_dst, addrbuf));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -968,8 +969,6 @@ ipv6_receive_data(net_buffer* buffer)
|
|||||||
uint16 transportHeaderOffset = header.GetTransportHeaderOffset(buffer);
|
uint16 transportHeaderOffset = header.GetTransportHeaderOffset(buffer);
|
||||||
uint8 protocol = buffer->protocol;
|
uint8 protocol = buffer->protocol;
|
||||||
|
|
||||||
buffer->hoplimit = header.h.ip6_hlim;
|
|
||||||
|
|
||||||
// remove any trailing/padding data
|
// remove any trailing/padding data
|
||||||
status_t status = gBufferModule->trim(buffer, packetLength);
|
status_t status = gBufferModule->trim(buffer, packetLength);
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
@@ -979,8 +978,15 @@ ipv6_receive_data(net_buffer* buffer)
|
|||||||
// TODO: check for fragmentation
|
// TODO: check for fragmentation
|
||||||
//
|
//
|
||||||
|
|
||||||
|
// tell the buffer to preserve removed ipv6 header - may need it later
|
||||||
|
gBufferModule->store_header(buffer);
|
||||||
|
|
||||||
|
TRACE("store_header for %p\n", buffer);
|
||||||
|
|
||||||
|
// remove ipv6 headers for now
|
||||||
gBufferModule->remove_header(buffer, transportHeaderOffset);
|
gBufferModule->remove_header(buffer, transportHeaderOffset);
|
||||||
|
|
||||||
|
// deliver the data to raw sockets
|
||||||
raw_receive_data(buffer);
|
raw_receive_data(buffer);
|
||||||
|
|
||||||
net_protocol_module_info* module = receiving_protocol(protocol);
|
net_protocol_module_info* module = receiving_protocol(protocol);
|
||||||
@@ -1029,30 +1035,45 @@ ipv6_error_reply(net_protocol* protocol, net_buffer* causedError, uint32 code,
|
|||||||
|
|
||||||
|
|
||||||
ssize_t
|
ssize_t
|
||||||
ipv6_process_ancillary_data_no_container(net_protocol* protocol,
|
ipv6_process_ancillary_data_no_container(net_protocol* _protocol,
|
||||||
net_buffer* buffer, void* msgControl, size_t msgControlLen)
|
net_buffer* buffer, void* msgControl, size_t msgControlLen)
|
||||||
{
|
{
|
||||||
|
ipv6_protocol* protocol = (ipv6_protocol*)_protocol;
|
||||||
ssize_t bytesWritten = 0;
|
ssize_t bytesWritten = 0;
|
||||||
|
|
||||||
if (((ipv6_protocol*)protocol)->receive_hoplimit != 0) {
|
if (protocol->receive_hoplimit != 0) {
|
||||||
TRACE("receive_hoplimit");
|
TRACE("receive_hoplimit");
|
||||||
|
|
||||||
if (msgControlLen < CMSG_SPACE(sizeof(int)))
|
if (msgControlLen < CMSG_SPACE(sizeof(int)))
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
TRACE("restore_header for %p\n", buffer);
|
||||||
|
|
||||||
|
if (gBufferModule->stored_header_length(buffer)
|
||||||
|
< (int)sizeof(ip6_hdr))
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
IPv6Header header;
|
||||||
|
if (gBufferModule->restore_header(buffer, 0, &header, sizeof(ip6_hdr))
|
||||||
|
!= B_OK)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
if (header.ProtocolVersion() != IPV6_VERSION)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
cmsghdr* messageHeader = (cmsghdr*)((char*)msgControl + bytesWritten);
|
cmsghdr* messageHeader = (cmsghdr*)((char*)msgControl + bytesWritten);
|
||||||
messageHeader->cmsg_len = CMSG_LEN(sizeof(int));
|
messageHeader->cmsg_len = CMSG_LEN(sizeof(int));
|
||||||
messageHeader->cmsg_level = IPPROTO_IPV6;
|
messageHeader->cmsg_level = IPPROTO_IPV6;
|
||||||
messageHeader->cmsg_type = IPV6_HOPLIMIT;
|
messageHeader->cmsg_type = IPV6_HOPLIMIT;
|
||||||
|
|
||||||
int hoplimit = buffer->hoplimit;
|
int hoplimit = header.header.ip6_hlim;
|
||||||
memcpy(CMSG_DATA(messageHeader), &hoplimit, sizeof(int));
|
memcpy(CMSG_DATA(messageHeader), &hoplimit, sizeof(int));
|
||||||
|
|
||||||
bytesWritten += CMSG_SPACE(sizeof(int));
|
bytesWritten += CMSG_SPACE(sizeof(int));
|
||||||
msgControlLen -= CMSG_SPACE(sizeof(int));
|
msgControlLen -= CMSG_SPACE(sizeof(int));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((ipv6_protocol*)protocol)->receive_pktinfo != 0) {
|
if (protocol->receive_pktinfo != 0) {
|
||||||
TRACE("receive_pktinfo");
|
TRACE("receive_pktinfo");
|
||||||
|
|
||||||
if (msgControlLen < CMSG_SPACE(sizeof(struct in6_pktinfo)))
|
if (msgControlLen < CMSG_SPACE(sizeof(struct in6_pktinfo)))
|
||||||
@@ -1161,7 +1182,6 @@ ipv6_std_ops(int32 op, ...)
|
|||||||
return init_ipv6();
|
return init_ipv6();
|
||||||
case B_MODULE_UNINIT:
|
case B_MODULE_UNINIT:
|
||||||
return uninit_ipv6();
|
return uninit_ipv6();
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -247,8 +247,8 @@ ipv6_first_mask_bit(const sockaddr *_mask)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (uint8 bit = 0; bit < 8; bit++) {
|
for (uint8 bit = 0; bit < 8; bit++) {
|
||||||
if (pmask[i] & (1 << bit))
|
if ((pmask[i] & (1 << (7 - bit))) == 0)
|
||||||
return bit;
|
return i * 8 + bit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,7 +276,7 @@ ipv6_check_mask(const sockaddr *_mask)
|
|||||||
} else if (pmask[i] == 0) {
|
} else if (pmask[i] == 0) {
|
||||||
zero = true;
|
zero = true;
|
||||||
} else {
|
} else {
|
||||||
for (int8 bit = 7; bit > 0; bit--) {
|
for (int8 bit = 7; bit >= 0; bit--) {
|
||||||
if (pmask[i] & (1 << bit)) {
|
if (pmask[i] & (1 << bit)) {
|
||||||
if (zero)
|
if (zero)
|
||||||
return false;
|
return false;
|
||||||
@@ -520,8 +520,8 @@ ipv6_checksum_address(struct Checksum *checksum, const sockaddr *address)
|
|||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
in6_addr &a = ((sockaddr_in6 *)address)->sin6_addr;
|
in6_addr &a = ((sockaddr_in6 *)address)->sin6_addr;
|
||||||
for (uint32 i = 0; i < sizeof(in6_addr); i++)
|
for (uint32 i = 0; i < sizeof(in6_addr); i += 2)
|
||||||
(*checksum) << a.s6_addr[i];
|
(*checksum) << *(uint16*)(a.s6_addr + i);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -544,7 +544,7 @@ net_address_module_info gIPv6AddressModule = {
|
|||||||
0,
|
0,
|
||||||
NULL
|
NULL
|
||||||
},
|
},
|
||||||
false, // has_broadcast_address
|
0, // flags
|
||||||
ipv6_copy_address,
|
ipv6_copy_address,
|
||||||
ipv6_mask_address,
|
ipv6_mask_address,
|
||||||
ipv6_equal_addresses,
|
ipv6_equal_addresses,
|
||||||
|
|||||||
@@ -413,7 +413,7 @@ net_address_module_info gL2cap4AddressModule = {
|
|||||||
0,
|
0,
|
||||||
NULL
|
NULL
|
||||||
},
|
},
|
||||||
true, // has_broadcast_address
|
NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS,
|
||||||
l2cap_copy_address,
|
l2cap_copy_address,
|
||||||
l2cap_mask_address,
|
l2cap_mask_address,
|
||||||
l2cap_equal_addresses,
|
l2cap_equal_addresses,
|
||||||
|
|||||||
@@ -756,6 +756,13 @@ tcp_init()
|
|||||||
NULL);
|
NULL);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
status = gStackModule->register_domain_protocols(AF_INET6,
|
||||||
|
SOCK_STREAM, 0,
|
||||||
|
"network/protocols/tcp/v1",
|
||||||
|
"network/protocols/ipv6/v1",
|
||||||
|
NULL);
|
||||||
|
if (status < B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
status = gStackModule->register_domain_protocols(AF_INET, SOCK_STREAM,
|
status = gStackModule->register_domain_protocols(AF_INET, SOCK_STREAM,
|
||||||
IPPROTO_TCP,
|
IPPROTO_TCP,
|
||||||
@@ -764,11 +771,22 @@ tcp_init()
|
|||||||
NULL);
|
NULL);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
status = gStackModule->register_domain_protocols(AF_INET6, SOCK_STREAM,
|
||||||
|
IPPROTO_TCP,
|
||||||
|
"network/protocols/tcp/v1",
|
||||||
|
"network/protocols/ipv6/v1",
|
||||||
|
NULL);
|
||||||
|
if (status < B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
status = gStackModule->register_domain_receiving_protocol(AF_INET,
|
status = gStackModule->register_domain_receiving_protocol(AF_INET,
|
||||||
IPPROTO_TCP, "network/protocols/tcp/v1");
|
IPPROTO_TCP, "network/protocols/tcp/v1");
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
status = gStackModule->register_domain_receiving_protocol(AF_INET6,
|
||||||
|
IPPROTO_TCP, "network/protocols/tcp/v1");
|
||||||
|
if (status < B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
add_debugger_command("tcp_endpoints", dump_endpoints,
|
add_debugger_command("tcp_endpoints", dump_endpoints,
|
||||||
"lists all open TCP endpoints");
|
"lists all open TCP endpoints");
|
||||||
|
|||||||
@@ -290,7 +290,7 @@ net_address_module_info gAddressModule = {
|
|||||||
0,
|
0,
|
||||||
NULL
|
NULL
|
||||||
},
|
},
|
||||||
true, // has_broadcast_address
|
NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS,
|
||||||
unix_copy_address,
|
unix_copy_address,
|
||||||
unix_mask_address,
|
unix_mask_address,
|
||||||
unix_equal_addresses,
|
unix_equal_addresses,
|
||||||
|
|||||||
@@ -30,7 +30,9 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <netinet6/in6.h> // TODO
|
// TODO: this is only needed for IPv6 multicast route code;
|
||||||
|
// remove it when the code will be refactored
|
||||||
|
#include <netinet6/in6.h>
|
||||||
|
|
||||||
|
|
||||||
struct datalink_protocol : net_protocol {
|
struct datalink_protocol : net_protocol {
|
||||||
@@ -752,7 +754,8 @@ interface_protocol_control(net_datalink_protocol* _protocol, int32 option,
|
|||||||
|
|
||||||
// reset the broadcast address if the address family has such
|
// reset the broadcast address if the address family has such
|
||||||
sockaddr* broadcast;
|
sockaddr* broadcast;
|
||||||
if (interface->domain->address_module->has_broadcast_address) {
|
if ((interface->domain->address_module->flags
|
||||||
|
& NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS) != 0) {
|
||||||
broadcast = reallocate_address(&interface->destination,
|
broadcast = reallocate_address(&interface->destination,
|
||||||
request.ifr_addr.sa_len);
|
request.ifr_addr.sa_len);
|
||||||
} else {
|
} else {
|
||||||
@@ -971,7 +974,6 @@ net_datalink_protocol_module_info gDatalinkInterfaceProtocolModule = {
|
|||||||
interface_protocol_init,
|
interface_protocol_init,
|
||||||
interface_protocol_uninit,
|
interface_protocol_uninit,
|
||||||
interface_protocol_send_data,
|
interface_protocol_send_data,
|
||||||
NULL, // receive_data
|
|
||||||
interface_protocol_up,
|
interface_protocol_up,
|
||||||
interface_protocol_down,
|
interface_protocol_down,
|
||||||
interface_protocol_control,
|
interface_protocol_control,
|
||||||
|
|||||||
Reference in New Issue
Block a user