vfs: check userland buffers before reading them.
[haiku.git] / src / add-ons / kernel / network / datalink_protocols / ethernet_frame / ethernet_frame.cpp
bloba46b35da3960e2fe6479d1822ec4110c10caa219
1 /*
2 * Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Axel Dörfler, axeld@pinc-software.de
7 */
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>
17 #include <ByteOrder.h>
18 #include <KernelExport.h>
20 #include <net/if.h>
21 #include <net/if_types.h>
22 #include <net/if_dl.h>
23 #include <new>
24 #include <string.h>
27 struct ethernet_frame_protocol : net_datalink_protocol {
31 static const uint8 kBroadcastAddress[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
33 struct net_buffer_module_info* gBufferModule;
36 int32
37 ethernet_deframe(net_device* device, net_buffer* buffer)
39 //dprintf("asked to deframe buffer for device %s\n", device->name);
41 NetBufferHeaderRemover<ether_header> bufferHeader(buffer);
42 if (bufferHeader.Status() != B_OK)
43 return bufferHeader.Status();
45 ether_header& header = bufferHeader.Data();
46 uint16 type = ntohs(header.type);
48 struct sockaddr_dl& source = *(struct sockaddr_dl*)buffer->source;
49 struct sockaddr_dl& destination = *(struct sockaddr_dl*)buffer->destination;
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);
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);
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;
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;
87 default:
88 buffer->type = B_NET_FRAME_TYPE(IFT_ETHER, type);
89 break;
92 return B_OK;
96 // #pragma mark -
99 status_t
100 ethernet_frame_init(struct net_interface* interface, net_domain* domain,
101 net_datalink_protocol** _protocol)
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;
108 status = stack->register_device_deframer(interface->device,
109 &ethernet_deframe);
111 put_module(NET_STACK_MODULE_NAME);
113 if (status != B_OK)
114 return status;
116 ethernet_frame_protocol* protocol
117 = new(std::nothrow) ethernet_frame_protocol;
118 if (protocol == NULL)
119 return B_NO_MEMORY;
121 *_protocol = protocol;
122 return B_OK;
126 status_t
127 ethernet_frame_uninit(net_datalink_protocol* protocol)
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);
135 delete protocol;
136 return B_OK;
140 status_t
141 ethernet_frame_send_data(net_datalink_protocol* protocol, net_buffer* buffer)
143 struct sockaddr_dl& source = *(struct sockaddr_dl*)buffer->source;
144 struct sockaddr_dl& destination = *(struct sockaddr_dl*)buffer->destination;
146 if (source.sdl_family != AF_LINK || source.sdl_type != IFT_ETHER)
147 return B_ERROR;
149 NetBufferPrepend<ether_header> bufferHeader(buffer);
150 if (bufferHeader.Status() != B_OK)
151 return bufferHeader.Status();
153 ether_header &header = bufferHeader.Data();
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);
162 bufferHeader.Sync();
163 // make sure the framing is already written to the buffer at this point
165 return protocol->next->module->send_data(protocol->next, buffer);
169 status_t
170 ethernet_frame_up(net_datalink_protocol* protocol)
172 return protocol->next->module->interface_up(protocol->next);
176 void
177 ethernet_frame_down(net_datalink_protocol* protocol)
179 return protocol->next->module->interface_down(protocol->next);
183 status_t
184 ethernet_frame_change_address(net_datalink_protocol* protocol,
185 net_interface_address* address, int32 option,
186 const struct sockaddr* oldAddress, const struct sockaddr* newAddress)
188 return protocol->next->module->change_address(protocol->next, address,
189 option, oldAddress, newAddress);
193 status_t
194 ethernet_frame_control(net_datalink_protocol* protocol, int32 option,
195 void* argument, size_t length)
197 return protocol->next->module->control(protocol->next, option, argument,
198 length);
202 static status_t
203 ethernet_frame_join_multicast(net_datalink_protocol* protocol,
204 const sockaddr* address)
206 return protocol->next->module->join_multicast(protocol->next, address);
210 static status_t
211 ethernet_frame_leave_multicast(net_datalink_protocol* protocol,
212 const sockaddr* address)
214 return protocol->next->module->leave_multicast(protocol->next, address);
218 static status_t
219 ethernet_frame_std_ops(int32 op, ...)
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;
229 default:
230 return B_ERROR;
235 static net_datalink_protocol_module_info sEthernetFrameModule = {
237 "network/datalink_protocols/ethernet_frame/v1",
239 ethernet_frame_std_ops
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,
252 module_info* modules[] = {
253 (module_info*)&sEthernetFrameModule,
254 NULL