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		&ethernet_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