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	// We only support a single type!
50	if (interface->device->type != IFT_LOOP)
51		return B_BAD_TYPE;
52
53	loopback_frame_protocol* protocol;
54
55	net_stack_module_info* stack;
56	status_t status = get_module(NET_STACK_MODULE_NAME, (module_info**)&stack);
57	if (status != B_OK)
58		return status;
59
60	status = stack->register_device_deframer(interface->device,
61		&loopback_deframe);
62	if (status != B_OK)
63		goto err1;
64
65	// Locally received buffers don't need a domain device handler, as the
66	// buffer reception is handled internally.
67
68	protocol = new(std::nothrow) loopback_frame_protocol;
69	if (protocol == NULL) {
70		status = B_NO_MEMORY;
71		goto err2;
72	}
73
74	put_module(NET_STACK_MODULE_NAME);
75
76	*_protocol = protocol;
77	return B_OK;
78
79err2:
80	stack->unregister_device_deframer(interface->device);
81err1:
82	put_module(NET_STACK_MODULE_NAME);
83	return status;
84}
85
86
87status_t
88loopback_frame_uninit(net_datalink_protocol* protocol)
89{
90	net_stack_module_info* stack;
91	if (get_module(NET_STACK_MODULE_NAME, (module_info**)&stack) == B_OK) {
92		stack->unregister_device_deframer(protocol->interface->device);
93		stack->unregister_device_handler(protocol->interface->device, 0);
94		put_module(NET_STACK_MODULE_NAME);
95	}
96
97	delete protocol;
98	return B_OK;
99}
100
101
102status_t
103loopback_frame_send_data(net_datalink_protocol* protocol, net_buffer* buffer)
104{
105	return protocol->next->module->send_data(protocol->next, buffer);
106}
107
108
109status_t
110loopback_frame_up(net_datalink_protocol* protocol)
111{
112	return protocol->next->module->interface_up(protocol->next);
113}
114
115
116void
117loopback_frame_down(net_datalink_protocol* protocol)
118{
119	return protocol->next->module->interface_down(protocol->next);
120}
121
122
123status_t
124loopback_frame_change_address(net_datalink_protocol* protocol,
125	net_interface_address* address, int32 option,
126	const struct sockaddr* oldAddress, const struct sockaddr* newAddress)
127{
128	return protocol->next->module->change_address(protocol->next, address,
129		option, oldAddress, newAddress);
130}
131
132
133status_t
134loopback_frame_control(net_datalink_protocol* protocol, int32 option,
135	void* argument, size_t length)
136{
137	return protocol->next->module->control(protocol->next, option, argument,
138		length);
139}
140
141
142static status_t
143loopback_frame_join_multicast(net_datalink_protocol* protocol,
144	const sockaddr* address)
145{
146	return protocol->next->module->join_multicast(protocol->next, address);
147}
148
149
150static status_t
151loopback_frame_leave_multicast(net_datalink_protocol* protocol,
152	const sockaddr* address)
153{
154	return protocol->next->module->leave_multicast(protocol->next, address);
155}
156
157
158static status_t
159loopback_frame_std_ops(int32 op, ...)
160{
161	switch (op) {
162		case B_MODULE_INIT:
163			return get_module(NET_BUFFER_MODULE_NAME,
164				(module_info**)&gBufferModule);
165		case B_MODULE_UNINIT:
166			put_module(NET_BUFFER_MODULE_NAME);
167			return B_OK;
168
169		default:
170			return B_ERROR;
171	}
172}
173
174
175static net_datalink_protocol_module_info sLoopbackFrameModule = {
176	{
177		"network/datalink_protocols/loopback_frame/v1",
178		0,
179		loopback_frame_std_ops
180	},
181	loopback_frame_init,
182	loopback_frame_uninit,
183	loopback_frame_send_data,
184	loopback_frame_up,
185	loopback_frame_down,
186	loopback_frame_change_address,
187	loopback_frame_control,
188	loopback_frame_join_multicast,
189	loopback_frame_leave_multicast,
190};
191
192module_info* modules[] = {
193	(module_info*)&sLoopbackFrameModule,
194	NULL
195};
196