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 ethernet_frame_protocol : net_datalink_protocol { 28}; 29 30 31static const uint8 kBroadcastAddress[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 32 33struct net_buffer_module_info* gBufferModule; 34 35 36int32 37ethernet_deframe(net_device* device, net_buffer* buffer) 38{ 39 //dprintf("asked to deframe buffer for device %s\n", device->name); 40 41 NetBufferHeaderRemover<ether_header> bufferHeader(buffer); 42 if (bufferHeader.Status() != B_OK) 43 return bufferHeader.Status(); 44 45 ether_header& header = bufferHeader.Data(); 46 uint16 type = B_BENDIAN_TO_HOST_INT16(header.type); 47 48 struct sockaddr_dl& source = *(struct sockaddr_dl*)buffer->source; 49 struct sockaddr_dl& destination = *(struct sockaddr_dl*)buffer->destination; 50 51 source.sdl_len = sizeof(sockaddr_dl); 52 source.sdl_family = AF_LINK; 53 source.sdl_index = device->index; 54 source.sdl_type = IFT_ETHER; 55 source.sdl_e_type = header.type; 56 source.sdl_nlen = source.sdl_slen = 0; 57 source.sdl_alen = ETHER_ADDRESS_LENGTH; 58 memcpy(source.sdl_data, header.source, ETHER_ADDRESS_LENGTH); 59 60 destination.sdl_len = sizeof(sockaddr_dl); 61 destination.sdl_family = AF_LINK; 62 destination.sdl_index = device->index; 63 destination.sdl_type = IFT_ETHER; 64 destination.sdl_e_type = header.type; 65 destination.sdl_nlen = destination.sdl_slen = 0; 66 destination.sdl_alen = ETHER_ADDRESS_LENGTH; 67 memcpy(destination.sdl_data, header.destination, ETHER_ADDRESS_LENGTH); 68 69 // Mark buffer if it was a broadcast/multicast packet 70 if (!memcmp(header.destination, kBroadcastAddress, ETHER_ADDRESS_LENGTH)) 71 buffer->flags |= MSG_BCAST; 72 else if ((header.destination[0] & 0x01) != 0) 73 buffer->flags |= MSG_MCAST; 74 75 // Translate the ethernet specific type to a generic one if possible 76 switch (type) { 77 case ETHER_TYPE_IP: 78 buffer->type = B_NET_FRAME_TYPE_IPV4; 79 break; 80 case ETHER_TYPE_IPV6: 81 buffer->type = B_NET_FRAME_TYPE_IPV6; 82 break; 83 case ETHER_TYPE_IPX: 84 buffer->type = B_NET_FRAME_TYPE_IPX; 85 break; 86 87 default: 88 buffer->type = B_NET_FRAME_TYPE(IFT_ETHER, type); 89 break; 90 } 91 92 return B_OK; 93} 94 95 96// #pragma mark - 97 98 99status_t 100ethernet_frame_init(struct net_interface* interface, net_domain* domain, 101 net_datalink_protocol** _protocol) 102{ 103 net_stack_module_info* stack; 104 status_t status = get_module(NET_STACK_MODULE_NAME, (module_info**)&stack); 105 if (status < B_OK) 106 return status; 107 108 status = stack->register_device_deframer(interface->device, 109 ðernet_deframe); 110 111 put_module(NET_STACK_MODULE_NAME); 112 113 if (status != B_OK) 114 return status; 115 116 ethernet_frame_protocol* protocol 117 = new(std::nothrow) ethernet_frame_protocol; 118 if (protocol == NULL) 119 return B_NO_MEMORY; 120 121 *_protocol = protocol; 122 return B_OK; 123} 124 125 126status_t 127ethernet_frame_uninit(net_datalink_protocol* protocol) 128{ 129 net_stack_module_info* stack; 130 if (get_module(NET_STACK_MODULE_NAME, (module_info**)&stack) == B_OK) { 131 stack->unregister_device_deframer(protocol->interface->device); 132 put_module(NET_STACK_MODULE_NAME); 133 } 134 135 delete protocol; 136 return B_OK; 137} 138 139 140status_t 141ethernet_frame_send_data(net_datalink_protocol* protocol, net_buffer* buffer) 142{ 143 struct sockaddr_dl& source = *(struct sockaddr_dl*)buffer->source; 144 struct sockaddr_dl& destination = *(struct sockaddr_dl*)buffer->destination; 145 146 if (source.sdl_family != AF_LINK || source.sdl_type != IFT_ETHER) 147 return B_ERROR; 148 149 NetBufferPrepend<ether_header> bufferHeader(buffer); 150 if (bufferHeader.Status() != B_OK) 151 return bufferHeader.Status(); 152 153 ether_header &header = bufferHeader.Data(); 154 155 header.type = source.sdl_e_type; 156 memcpy(header.source, LLADDR(&source), ETHER_ADDRESS_LENGTH); 157 if ((buffer->flags & MSG_BCAST) != 0) 158 memcpy(header.destination, kBroadcastAddress, ETHER_ADDRESS_LENGTH); 159 else 160 memcpy(header.destination, LLADDR(&destination), ETHER_ADDRESS_LENGTH); 161 162 bufferHeader.Sync(); 163 // make sure the framing is already written to the buffer at this point 164 165 return protocol->next->module->send_data(protocol->next, buffer); 166} 167 168 169status_t 170ethernet_frame_up(net_datalink_protocol* protocol) 171{ 172 return protocol->next->module->interface_up(protocol->next); 173} 174 175 176void 177ethernet_frame_down(net_datalink_protocol* protocol) 178{ 179 return protocol->next->module->interface_down(protocol->next); 180} 181 182 183status_t 184ethernet_frame_change_address(net_datalink_protocol* protocol, 185 net_interface_address* address, int32 option, 186 const struct sockaddr* oldAddress, const struct sockaddr* newAddress) 187{ 188 return protocol->next->module->change_address(protocol->next, address, 189 option, oldAddress, newAddress); 190} 191 192 193status_t 194ethernet_frame_control(net_datalink_protocol* protocol, int32 option, 195 void* argument, size_t length) 196{ 197 return protocol->next->module->control(protocol->next, option, argument, 198 length); 199} 200 201 202static status_t 203ethernet_frame_join_multicast(net_datalink_protocol* protocol, 204 const sockaddr* address) 205{ 206 return protocol->next->module->join_multicast(protocol->next, address); 207} 208 209 210static status_t 211ethernet_frame_leave_multicast(net_datalink_protocol* protocol, 212 const sockaddr* address) 213{ 214 return protocol->next->module->leave_multicast(protocol->next, address); 215} 216 217 218static status_t 219ethernet_frame_std_ops(int32 op, ...) 220{ 221 switch (op) { 222 case B_MODULE_INIT: 223 return get_module(NET_BUFFER_MODULE_NAME, 224 (module_info**)&gBufferModule); 225 case B_MODULE_UNINIT: 226 put_module(NET_BUFFER_MODULE_NAME); 227 return B_OK; 228 229 default: 230 return B_ERROR; 231 } 232} 233 234 235static net_datalink_protocol_module_info sEthernetFrameModule = { 236 { 237 "network/datalink_protocols/ethernet_frame/v1", 238 0, 239 ethernet_frame_std_ops 240 }, 241 ethernet_frame_init, 242 ethernet_frame_uninit, 243 ethernet_frame_send_data, 244 ethernet_frame_up, 245 ethernet_frame_down, 246 ethernet_frame_change_address, 247 ethernet_frame_control, 248 ethernet_frame_join_multicast, 249 ethernet_frame_leave_multicast, 250}; 251 252module_info* modules[] = { 253 (module_info*)&sEthernetFrameModule, 254 NULL 255}; 256