1/* 2 * Copyright 2006-2010, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Axel D��rfler, axeld@pinc-software.de 7 */ 8 9 10#include <ethernet.h> 11#include <net_datalink_protocol.h> 12#include <net_device.h> 13#include <net_datalink.h> 14#include <net_stack.h> 15#include <NetBufferUtilities.h> 16 17#include <ByteOrder.h> 18#include <KernelExport.h> 19 20#include <net/if.h> 21#include <net/if_types.h> 22#include <net/if_dl.h> 23#include <new> 24#include <string.h> 25 26 27struct loopback_frame_protocol : net_datalink_protocol { 28}; 29 30 31struct net_buffer_module_info* gBufferModule; 32 33 34status_t 35loopback_deframe(net_device* device, net_buffer* buffer) 36{ 37 // there is not that much to do... 38 return B_OK; 39} 40 41 42// #pragma mark - 43 44 45status_t 46loopback_frame_init(struct net_interface*interface, net_domain* domain, 47 net_datalink_protocol** _protocol) 48{ 49 if (interface->device->type != IFT_LOOP && interface->device->type != IFT_TUNNEL) 50 return B_BAD_TYPE; 51 52 loopback_frame_protocol* protocol; 53 54 net_stack_module_info* stack; 55 status_t status = get_module(NET_STACK_MODULE_NAME, (module_info**)&stack); 56 if (status != B_OK) 57 return status; 58 status = stack->register_device_deframer(interface->device, 59 &loopback_deframe); 60 if (status != B_OK) 61 goto err1; 62 63 if (interface->device->type == IFT_LOOP) { 64 // Locally received buffers don't need a domain device handler, as the 65 // buffer reception is handled internally. 66 } else if (interface->device->type == IFT_TUNNEL) { 67 status = stack->register_domain_device_handler( 68 interface->device, B_NET_FRAME_TYPE_IPV4, domain); 69 if (status != B_OK) 70 return status; 71 } 72 73 protocol = new(std::nothrow) loopback_frame_protocol; 74 if (protocol == NULL) { 75 status = B_NO_MEMORY; 76 goto err2; 77 } 78 79 put_module(NET_STACK_MODULE_NAME); 80 81 *_protocol = protocol; 82 return B_OK; 83 84err2: 85 stack->unregister_device_deframer(interface->device); 86err1: 87 put_module(NET_STACK_MODULE_NAME); 88 return status; 89} 90 91 92status_t 93loopback_frame_uninit(net_datalink_protocol* protocol) 94{ 95 net_stack_module_info* stack; 96 if (get_module(NET_STACK_MODULE_NAME, (module_info**)&stack) == B_OK) { 97 stack->unregister_device_deframer(protocol->interface->device); 98 stack->unregister_device_handler(protocol->interface->device, 0); 99 put_module(NET_STACK_MODULE_NAME); 100 } 101 102 delete protocol; 103 return B_OK; 104} 105 106 107status_t 108loopback_frame_send_data(net_datalink_protocol* protocol, net_buffer* buffer) 109{ 110 return protocol->next->module->send_data(protocol->next, buffer); 111} 112 113 114status_t 115loopback_frame_up(net_datalink_protocol* protocol) 116{ 117 return protocol->next->module->interface_up(protocol->next); 118} 119 120 121void 122loopback_frame_down(net_datalink_protocol* protocol) 123{ 124 return protocol->next->module->interface_down(protocol->next); 125} 126 127 128status_t 129loopback_frame_change_address(net_datalink_protocol* protocol, 130 net_interface_address* address, int32 option, 131 const struct sockaddr* oldAddress, const struct sockaddr* newAddress) 132{ 133 return protocol->next->module->change_address(protocol->next, address, 134 option, oldAddress, newAddress); 135} 136 137 138status_t 139loopback_frame_control(net_datalink_protocol* protocol, int32 option, 140 void* argument, size_t length) 141{ 142 return protocol->next->module->control(protocol->next, option, argument, 143 length); 144} 145 146 147static status_t 148loopback_frame_join_multicast(net_datalink_protocol* protocol, 149 const sockaddr* address) 150{ 151 return protocol->next->module->join_multicast(protocol->next, address); 152} 153 154 155static status_t 156loopback_frame_leave_multicast(net_datalink_protocol* protocol, 157 const sockaddr* address) 158{ 159 return protocol->next->module->leave_multicast(protocol->next, address); 160} 161 162 163static status_t 164loopback_frame_std_ops(int32 op, ...) 165{ 166 switch (op) { 167 case B_MODULE_INIT: 168 return get_module(NET_BUFFER_MODULE_NAME, 169 (module_info**)&gBufferModule); 170 case B_MODULE_UNINIT: 171 put_module(NET_BUFFER_MODULE_NAME); 172 return B_OK; 173 174 default: 175 return B_ERROR; 176 } 177} 178 179 180static net_datalink_protocol_module_info sLoopbackFrameModule = { 181 { 182 "network/datalink_protocols/loopback_frame/v1", 183 0, 184 loopback_frame_std_ops 185 }, 186 loopback_frame_init, 187 loopback_frame_uninit, 188 loopback_frame_send_data, 189 loopback_frame_up, 190 loopback_frame_down, 191 loopback_frame_change_address, 192 loopback_frame_control, 193 loopback_frame_join_multicast, 194 loopback_frame_leave_multicast, 195}; 196 197module_info* modules[] = { 198 (module_info*)&sLoopbackFrameModule, 199 NULL 200}; 201