Implemented loopback device - currently crashes the kernel pretty fast, though.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19065 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -2,3 +2,4 @@ SubDir HAIKU_TOP src add-ons kernel network datalink_protocols ;
|
|||||||
|
|
||||||
SubInclude HAIKU_TOP src add-ons kernel network datalink_protocols arp ;
|
SubInclude HAIKU_TOP src add-ons kernel network datalink_protocols arp ;
|
||||||
SubInclude HAIKU_TOP src add-ons kernel network datalink_protocols ethernet_frame ;
|
SubInclude HAIKU_TOP src add-ons kernel network datalink_protocols ethernet_frame ;
|
||||||
|
SubInclude HAIKU_TOP src add-ons kernel network datalink_protocols loopback_frame ;
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
SubDir HAIKU_TOP src add-ons kernel network datalink_protocols loopback_frame ;
|
||||||
|
|
||||||
|
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 ;
|
||||||
|
|
||||||
|
KernelAddon loopback_frame :
|
||||||
|
loopback_frame.cpp
|
||||||
|
;
|
||||||
|
|
||||||
|
# Installation
|
||||||
|
HaikuInstall install-networking : /boot/home/config/add-ons/kernel/haiku_network/datalink_protocols
|
||||||
|
: loopback_frame ;
|
||||||
|
|
||||||
|
Package haiku-networkingkit-cvs :
|
||||||
|
haiku :
|
||||||
|
boot home config add-ons kernel haiku_network datalink_protocols ;
|
||||||
@@ -0,0 +1,166 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Haiku, Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Axel Dörfler, [email protected]
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <ethernet.h>
|
||||||
|
#include <net_datalink_protocol.h>
|
||||||
|
#include <net_device.h>
|
||||||
|
#include <net_datalink.h>
|
||||||
|
#include <net_stack.h>
|
||||||
|
#include <NetBufferUtilities.h>
|
||||||
|
|
||||||
|
#include <ByteOrder.h>
|
||||||
|
#include <KernelExport.h>
|
||||||
|
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <net/if_types.h>
|
||||||
|
#include <net/if_dl.h>
|
||||||
|
#include <new>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct loopback_frame_protocol : net_datalink_protocol {
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct net_buffer_module_info *sBufferModule;
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
loopback_deframe(net_device *device, net_buffer *buffer)
|
||||||
|
{
|
||||||
|
// there is not that much to do...
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
loopback_frame_init(struct net_interface *interface, net_datalink_protocol **_protocol)
|
||||||
|
{
|
||||||
|
// We currently only support a single family and type!
|
||||||
|
if (interface->device->type != IFT_LOOP)
|
||||||
|
return B_BAD_TYPE;
|
||||||
|
|
||||||
|
loopback_frame_protocol *protocol;
|
||||||
|
|
||||||
|
net_stack_module_info *stack;
|
||||||
|
status_t status = get_module(NET_STACK_MODULE_NAME, (module_info **)&stack);
|
||||||
|
if (status < B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
status = stack->register_device_deframer(interface->device, &loopback_deframe);
|
||||||
|
if (status < B_OK)
|
||||||
|
goto err1;
|
||||||
|
|
||||||
|
// We also register the domain as a handler for our packets
|
||||||
|
status = stack->register_domain_device_handler(interface->device,
|
||||||
|
0, interface->domain);
|
||||||
|
if (status < B_OK)
|
||||||
|
goto err2;
|
||||||
|
|
||||||
|
put_module(NET_STACK_MODULE_NAME);
|
||||||
|
|
||||||
|
protocol = new (std::nothrow) loopback_frame_protocol;
|
||||||
|
if (protocol == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
*_protocol = protocol;
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
err2:
|
||||||
|
stack->unregister_device_deframer(interface->device);
|
||||||
|
err1:
|
||||||
|
put_module(NET_STACK_MODULE_NAME);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
loopback_frame_uninit(net_datalink_protocol *protocol)
|
||||||
|
{
|
||||||
|
net_stack_module_info *stack;
|
||||||
|
if (get_module(NET_STACK_MODULE_NAME, (module_info **)&stack) == B_OK) {
|
||||||
|
stack->unregister_device_deframer(protocol->interface->device);
|
||||||
|
stack->unregister_device_handler(protocol->interface->device, 0);
|
||||||
|
put_module(NET_STACK_MODULE_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete protocol;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
loopback_frame_send_data(net_datalink_protocol *protocol,
|
||||||
|
net_buffer *buffer)
|
||||||
|
{
|
||||||
|
return protocol->next->module->send_data(protocol->next, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
loopback_frame_up(net_datalink_protocol *_protocol)
|
||||||
|
{
|
||||||
|
loopback_frame_protocol *protocol = (loopback_frame_protocol *)_protocol;
|
||||||
|
|
||||||
|
return protocol->next->module->interface_up(protocol->next);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
loopback_frame_down(net_datalink_protocol *protocol)
|
||||||
|
{
|
||||||
|
return protocol->next->module->interface_down(protocol->next);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
loopback_frame_control(net_datalink_protocol *protocol,
|
||||||
|
int32 op, void *argument, size_t length)
|
||||||
|
{
|
||||||
|
return protocol->next->module->control(protocol->next, op, argument, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
loopback_frame_std_ops(int32 op, ...)
|
||||||
|
{
|
||||||
|
switch (op) {
|
||||||
|
case B_MODULE_INIT:
|
||||||
|
return get_module(NET_BUFFER_MODULE_NAME, (module_info **)&sBufferModule);
|
||||||
|
case B_MODULE_UNINIT:
|
||||||
|
put_module(NET_BUFFER_MODULE_NAME);
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static net_datalink_protocol_module_info sLoopbackFrameModule = {
|
||||||
|
{
|
||||||
|
"network/datalink_protocols/loopback_frame/v1",
|
||||||
|
0,
|
||||||
|
loopback_frame_std_ops
|
||||||
|
},
|
||||||
|
loopback_frame_init,
|
||||||
|
loopback_frame_uninit,
|
||||||
|
loopback_frame_send_data,
|
||||||
|
loopback_frame_up,
|
||||||
|
loopback_frame_down,
|
||||||
|
loopback_frame_control,
|
||||||
|
};
|
||||||
|
|
||||||
|
module_info *modules[] = {
|
||||||
|
(module_info *)&sLoopbackFrameModule,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
@@ -10,7 +10,7 @@ if $(TARGET_PLATFORM) != haiku {
|
|||||||
# Unfortunately we get more than we want, namely all POSIX headers.
|
# Unfortunately we get more than we want, namely all POSIX headers.
|
||||||
}
|
}
|
||||||
|
|
||||||
UsePrivateHeaders net ;
|
UsePrivateHeaders kernel net ;
|
||||||
|
|
||||||
KernelAddon loopback :
|
KernelAddon loopback :
|
||||||
loopback.cpp
|
loopback.cpp
|
||||||
|
|||||||
@@ -7,7 +7,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <net_buffer.h>
|
||||||
#include <net_device.h>
|
#include <net_device.h>
|
||||||
|
#include <net_stack.h>
|
||||||
|
|
||||||
#include <KernelExport.h>
|
#include <KernelExport.h>
|
||||||
|
|
||||||
@@ -19,18 +21,66 @@
|
|||||||
|
|
||||||
|
|
||||||
struct loopback_device : net_device {
|
struct loopback_device : net_device {
|
||||||
|
net_fifo fifo;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct net_buffer_module_info *sBufferModule;
|
||||||
|
static struct net_stack_module_info *sStackModule;
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Swaps \a size bytes of the memory pointed to by \a and \b with each other.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
swap_memory(void *a, void *b, size_t size)
|
||||||
|
{
|
||||||
|
uint32 *a4 = (uint32 *)a;
|
||||||
|
uint32 *b4 = (uint32 *)b;
|
||||||
|
while (size > 4) {
|
||||||
|
uint32 temp = *a4;
|
||||||
|
*(a4++) = *b4;
|
||||||
|
*(b4++) = temp;
|
||||||
|
|
||||||
|
size -= 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 *a1 = (uint8 *)a4;
|
||||||
|
uint8 *b1 = (uint8 *)b4;
|
||||||
|
while (size > 0) {
|
||||||
|
uint8 temp = *a1;
|
||||||
|
*(a1++) = *b1;
|
||||||
|
*(b1++) = temp;
|
||||||
|
|
||||||
|
size--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
loopback_init(const char *name, net_device **_device)
|
loopback_init(const char *name, net_device **_device)
|
||||||
{
|
{
|
||||||
|
loopback_device *device;
|
||||||
|
|
||||||
if (strncmp(name, "loop", 4))
|
if (strncmp(name, "loop", 4))
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
loopback_device *device = new (std::nothrow) loopback_device;
|
status_t status = get_module(NET_STACK_MODULE_NAME, (module_info **)&sStackModule);
|
||||||
if (device == NULL)
|
if (status < B_OK)
|
||||||
return B_NO_MEMORY;
|
return status;
|
||||||
|
|
||||||
|
status = get_module(NET_BUFFER_MODULE_NAME, (module_info **)&sBufferModule);
|
||||||
|
if (status < B_OK)
|
||||||
|
goto err1;
|
||||||
|
|
||||||
|
device = new (std::nothrow) loopback_device;
|
||||||
|
if (device == NULL) {
|
||||||
|
status = B_NO_MEMORY;
|
||||||
|
goto err2;
|
||||||
|
}
|
||||||
|
|
||||||
memset(device, 0, sizeof(loopback_device));
|
memset(device, 0, sizeof(loopback_device));
|
||||||
|
|
||||||
@@ -41,27 +91,41 @@ loopback_init(const char *name, net_device **_device)
|
|||||||
|
|
||||||
*_device = device;
|
*_device = device;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
|
err2:
|
||||||
|
put_module(NET_BUFFER_MODULE_NAME);
|
||||||
|
err1:
|
||||||
|
put_module(NET_STACK_MODULE_NAME);
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
loopback_uninit(net_device *device)
|
loopback_uninit(net_device *_device)
|
||||||
{
|
{
|
||||||
|
loopback_device *device = (loopback_device *)_device;
|
||||||
|
|
||||||
|
put_module(NET_STACK_MODULE_NAME);
|
||||||
|
put_module(NET_BUFFER_MODULE_NAME);
|
||||||
delete device;
|
delete device;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
loopback_up(net_device *device)
|
loopback_up(net_device *_device)
|
||||||
{
|
{
|
||||||
return B_OK;
|
loopback_device *device = (loopback_device *)_device;
|
||||||
|
return sStackModule->init_fifo(&device->fifo, "loopback fifo", 65536);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
loopback_down(net_device *device)
|
loopback_down(net_device *_device)
|
||||||
{
|
{
|
||||||
|
loopback_device *device = (loopback_device *)_device;
|
||||||
|
sStackModule->uninit_fifo(&device->fifo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -74,37 +138,55 @@ loopback_control(net_device *device, int32 op, void *argument,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
loopback_send_data(net_device *device, net_buffer *buffer)
|
loopback_send_data(net_device *_device, net_buffer *buffer)
|
||||||
{
|
{
|
||||||
return B_ERROR;
|
loopback_device *device = (loopback_device *)_device;
|
||||||
|
return sStackModule->fifo_enqueue_buffer(&device->fifo, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
loopback_receive_data(net_device *device, net_buffer **_buffer)
|
loopback_receive_data(net_device *_device, net_buffer **_buffer)
|
||||||
{
|
{
|
||||||
return B_ERROR;
|
loopback_device *device = (loopback_device *)_device;
|
||||||
|
net_buffer *buffer;
|
||||||
|
|
||||||
|
status_t status = sStackModule->fifo_dequeue_buffer(&device->fifo, 0, 0, &buffer);
|
||||||
|
if (status < B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
// switch network addresses before delivering
|
||||||
|
swap_memory(&buffer->source, &buffer->destination,
|
||||||
|
max_c(buffer->source.ss_len, buffer->destination.ss_len));
|
||||||
|
|
||||||
|
*_buffer = buffer;
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
loopback_set_mtu(net_device *device, size_t mtu)
|
loopback_set_mtu(net_device *device, size_t mtu)
|
||||||
{
|
{
|
||||||
return B_ERROR;
|
if (mtu > 65536
|
||||||
|
|| mtu < 16)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
device->mtu = mtu;
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
loopback_set_promiscuous(net_device *device, bool promiscuous)
|
loopback_set_promiscuous(net_device *device, bool promiscuous)
|
||||||
{
|
{
|
||||||
return B_ERROR;
|
return EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
loopback_set_media(net_device *device, uint32 media)
|
loopback_set_media(net_device *device, uint32 media)
|
||||||
{
|
{
|
||||||
return B_ERROR;
|
return EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -790,7 +790,8 @@ init_stack()
|
|||||||
scan_modules("network/datalink_protocols");
|
scan_modules("network/datalink_protocols");
|
||||||
|
|
||||||
// TODO: for now!
|
// TODO: for now!
|
||||||
register_domain_datalink_protocols(AF_INET, IFT_LOOP, NULL);
|
register_domain_datalink_protocols(AF_INET, IFT_LOOP,
|
||||||
|
"network/datalink_protocols/loopback_frame/v1", NULL);
|
||||||
register_domain_datalink_protocols(AF_INET, IFT_ETHER,
|
register_domain_datalink_protocols(AF_INET, IFT_ETHER,
|
||||||
"network/datalink_protocols/arp/v1",
|
"network/datalink_protocols/arp/v1",
|
||||||
"network/datalink_protocols/ethernet_frame/v1",
|
"network/datalink_protocols/ethernet_frame/v1",
|
||||||
|
|||||||
Reference in New Issue
Block a user