2 * Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
6 * Axel Dörfler, axeld@pinc-software.de
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>
21 #include <net/if_types.h>
22 #include <net/if_dl.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
;
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
78 buffer
->type
= B_NET_FRAME_TYPE_IPV4
;
81 buffer
->type
= B_NET_FRAME_TYPE_IPV6
;
84 buffer
->type
= B_NET_FRAME_TYPE_IPX
;
88 buffer
->type
= B_NET_FRAME_TYPE(IFT_ETHER
, type
);
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
);
108 status
= stack
->register_device_deframer(interface
->device
,
111 put_module(NET_STACK_MODULE_NAME
);
116 ethernet_frame_protocol
* protocol
117 = new(std::nothrow
) ethernet_frame_protocol
;
118 if (protocol
== NULL
)
121 *_protocol
= protocol
;
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
);
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
)
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
);
160 memcpy(header
.destination
, LLADDR(&destination
), ETHER_ADDRESS_LENGTH
);
163 // make sure the framing is already written to the buffer at this point
165 return protocol
->next
->module
->send_data(protocol
->next
, buffer
);
170 ethernet_frame_up(net_datalink_protocol
* protocol
)
172 return protocol
->next
->module
->interface_up(protocol
->next
);
177 ethernet_frame_down(net_datalink_protocol
* protocol
)
179 return protocol
->next
->module
->interface_down(protocol
->next
);
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
);
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
,
203 ethernet_frame_join_multicast(net_datalink_protocol
* protocol
,
204 const sockaddr
* address
)
206 return protocol
->next
->module
->join_multicast(protocol
->next
, address
);
211 ethernet_frame_leave_multicast(net_datalink_protocol
* protocol
,
212 const sockaddr
* address
)
214 return protocol
->next
->module
->leave_multicast(protocol
->next
, address
);
219 ethernet_frame_std_ops(int32 op
, ...)
223 return get_module(NET_BUFFER_MODULE_NAME
,
224 (module_info
**)&gBufferModule
);
225 case B_MODULE_UNINIT
:
226 put_module(NET_BUFFER_MODULE_NAME
);
235 static net_datalink_protocol_module_info sEthernetFrameModule
= {
237 "network/datalink_protocols/ethernet_frame/v1",
239 ethernet_frame_std_ops
242 ethernet_frame_uninit
,
243 ethernet_frame_send_data
,
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
,