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