/* * Copyright 2006-2007, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: * Axel Dörfler, axeld@pinc-software.de */ #include #include #include #include #include #include #include #include #include #include struct loopback_device : net_device { }; struct net_buffer_module_info *gBufferModule; static struct net_stack_module_info *sStackModule; // #pragma mark - status_t loopback_init(const char *name, net_device **_device) { loopback_device *device; if (strncmp(name, "loop", 4)) return B_BAD_VALUE; status_t status = get_module(NET_STACK_MODULE_NAME, (module_info **)&sStackModule); if (status < B_OK) return status; status = get_module(NET_BUFFER_MODULE_NAME, (module_info **)&gBufferModule); 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)); strcpy(device->name, name); device->flags = IFF_LOOPBACK | IFF_LINK; device->type = IFT_LOOP; device->mtu = 65536; device->media = IFM_ACTIVE; *_device = device; return B_OK; err2: put_module(NET_BUFFER_MODULE_NAME); err1: put_module(NET_STACK_MODULE_NAME); return status; } status_t 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; return B_OK; } status_t loopback_up(net_device *device) { return B_OK; } void loopback_down(net_device *device) { } status_t loopback_control(net_device *device, int32 op, void *argument, size_t length) { return B_BAD_VALUE; } status_t loopback_send_data(net_device *device, net_buffer *buffer) { return sStackModule->device_enqueue_buffer(device, buffer); } status_t loopback_set_mtu(net_device *device, size_t mtu) { if (mtu > 65536 || mtu < 16) return B_BAD_VALUE; device->mtu = mtu; return B_OK; } status_t loopback_set_promiscuous(net_device *device, bool promiscuous) { return EOPNOTSUPP; } status_t loopback_set_media(net_device *device, uint32 media) { return EOPNOTSUPP; } status_t loopback_add_multicast(net_device *device, const sockaddr *address) { return B_OK; } status_t loopback_remove_multicast(net_device *device, const sockaddr *address) { return B_OK; } static status_t loopback_std_ops(int32 op, ...) { switch (op) { case B_MODULE_INIT: case B_MODULE_UNINIT: return B_OK; default: return B_ERROR; } } net_device_module_info sLoopbackModule = { { "network/devices/loopback/v1", 0, loopback_std_ops }, loopback_init, loopback_uninit, loopback_up, loopback_down, loopback_control, loopback_send_data, NULL, // receive_data loopback_set_mtu, loopback_set_promiscuous, loopback_set_media, loopback_add_multicast, loopback_remove_multicast, }; module_info *modules[] = { (module_info *)&sLoopbackModule, NULL };