xref: /haiku/src/add-ons/kernel/network/stack/link.cpp (revision 0d5afa4decb83fc03232a420d85c7838f70d2266)
1 /*
2  * Copyright 2006-2007, 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 "datalink.h"
11 #include "domains.h"
12 #include "interfaces.h"
13 #include "link.h"
14 #include "stack_private.h"
15 #include "utility.h"
16 
17 #include <net_device.h>
18 
19 #include <KernelExport.h>
20 
21 #include <net/if_types.h>
22 #include <new>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/sockio.h>
26 
27 
28 struct link_protocol : net_protocol {
29 	net_fifo	fifo;
30 	char		registered_interface[IF_NAMESIZE];
31 	bool		registered_monitor;
32 };
33 
34 
35 struct net_domain *sDomain;
36 
37 
38 static status_t
39 link_monitor_data(void *cookie, net_buffer *packet)
40 {
41 	link_protocol *protocol = (link_protocol *)cookie;
42 
43 	return fifo_socket_enqueue_buffer(&protocol->fifo, protocol->socket,
44 						B_SELECT_READ, packet);
45 }
46 
47 
48 //	#pragma mark -
49 
50 
51 net_protocol *
52 link_init_protocol(net_socket *socket)
53 {
54 	link_protocol *protocol = new (std::nothrow) link_protocol;
55 	if (protocol == NULL)
56 		return NULL;
57 
58 	if (init_fifo(&protocol->fifo, "packet monitor socket", 65536) < B_OK) {
59 		delete protocol;
60 		return NULL;
61 	}
62 
63 	protocol->registered_monitor = false;
64 	return protocol;
65 }
66 
67 
68 status_t
69 link_uninit_protocol(net_protocol *_protocol)
70 {
71 	link_protocol *protocol = (link_protocol *)_protocol;
72 
73 	if (protocol->registered_monitor) {
74 		net_device_interface *interface = get_device_interface(protocol->registered_interface);
75 		if (interface != NULL) {
76 			unregister_device_monitor(interface->device, link_monitor_data, protocol);
77 			put_device_interface(interface);
78 		}
79 	}
80 
81 	uninit_fifo(&protocol->fifo);
82 	delete protocol;
83 	return B_OK;
84 }
85 
86 
87 status_t
88 link_open(net_protocol *protocol)
89 {
90 	return B_OK;
91 }
92 
93 
94 status_t
95 link_close(net_protocol *protocol)
96 {
97 	return B_OK;
98 }
99 
100 
101 status_t
102 link_free(net_protocol *protocol)
103 {
104 	return B_OK;
105 }
106 
107 
108 status_t
109 link_connect(net_protocol *protocol, const struct sockaddr *address)
110 {
111 	return EOPNOTSUPP;
112 }
113 
114 
115 status_t
116 link_accept(net_protocol *protocol, struct net_socket **_acceptedSocket)
117 {
118 	return EOPNOTSUPP;
119 }
120 
121 
122 status_t
123 link_control(net_protocol *_protocol, int level, int option, void *value,
124 	size_t *_length)
125 {
126 	link_protocol *protocol = (link_protocol *)_protocol;
127 
128 	switch (option) {
129 		case SIOCGIFINDEX:
130 		{
131 			// get index of interface
132 			struct ifreq request;
133 			if (user_memcpy(&request, value, IF_NAMESIZE) < B_OK)
134 				return B_BAD_ADDRESS;
135 
136 			net_device_interface *interface = get_device_interface(request.ifr_name);
137 			if (interface != NULL) {
138 				request.ifr_index = interface->device->index;
139 				put_device_interface(interface);
140 			} else
141 				request.ifr_index = 0;
142 
143 			return user_memcpy(value, &request, sizeof(struct ifreq));
144 		}
145 		case SIOCGIFNAME:
146 		{
147 			// get name of interface via index
148 			struct ifreq request;
149 			if (user_memcpy(&request, value, sizeof(struct ifreq)) < B_OK)
150 				return B_BAD_ADDRESS;
151 
152 			net_device_interface *interface = get_device_interface(request.ifr_index);
153 			if (interface != NULL) {
154 				strlcpy(request.ifr_name, interface->name, IF_NAMESIZE);
155 				put_device_interface(interface);
156 			} else
157 				return ENODEV;
158 
159 			return user_memcpy(value, &request, sizeof(struct ifreq));
160 		}
161 
162 		case SIOCGIFCOUNT:
163 		{
164 			// count number of interfaces
165 			struct ifconf config;
166 			config.ifc_value = count_device_interfaces();
167 
168 			return user_memcpy(value, &config, sizeof(struct ifconf));
169 		}
170 
171 		case SIOCGIFCONF:
172 		{
173 			// retrieve available interfaces
174 			struct ifconf config;
175 			if (user_memcpy(&config, value, sizeof(struct ifconf)) < B_OK)
176 				return B_BAD_ADDRESS;
177 
178 			status_t result = list_device_interfaces(config.ifc_buf,
179 				(size_t *)&config.ifc_len);
180 			if (result != B_OK)
181 				return result;
182 
183 			return user_memcpy(value, &config, sizeof(struct ifconf));
184 		}
185 
186 		case SIOCGIFADDR:
187 		{
188 			// get address of interface
189 			struct ifreq request;
190 			if (user_memcpy(&request, value, IF_NAMESIZE) < B_OK)
191 				return B_BAD_ADDRESS;
192 
193 			net_device_interface *interface = get_device_interface(request.ifr_name);
194 			if (interface != NULL) {
195 				get_device_interface_address(interface, &request.ifr_addr);
196 				put_device_interface(interface);
197 			} else
198 				return ENODEV;
199 
200 			return user_memcpy(&((struct ifreq *)value)->ifr_addr,
201 				&request.ifr_addr, request.ifr_addr.sa_len);
202 		}
203 
204 		case SIOCSPACKETCAP:
205 		{
206 			// start packet monitoring
207 
208 			if (protocol->registered_monitor)
209 				return B_BUSY;
210 
211 			struct ifreq request;
212 			if (user_memcpy(&request, value, IF_NAMESIZE) < B_OK)
213 				return B_BAD_ADDRESS;
214 
215 			net_device_interface *interface = get_device_interface(request.ifr_name);
216 			status_t status;
217 			if (interface != NULL) {
218 				status = register_device_monitor(interface->device,
219 					link_monitor_data, protocol);
220 				if (status == B_OK) {
221 					// we're now registered
222 					strlcpy(protocol->registered_interface, request.ifr_name, IF_NAMESIZE);
223 					protocol->registered_monitor = true;
224 				}
225 				put_device_interface(interface);
226 			} else
227 				status = ENODEV;
228 
229 			return status;
230 		}
231 
232 		case SIOCCPACKETCAP:
233 		{
234 			// stop packet monitoring
235 
236 			if (!protocol->registered_monitor)
237 				return B_BAD_VALUE;
238 
239 			struct ifreq request;
240 			if (user_memcpy(&request, value, IF_NAMESIZE) < B_OK)
241 				return B_BAD_ADDRESS;
242 
243 			net_device_interface *interface = get_device_interface(request.ifr_name);
244 			status_t status;
245 			if (interface != NULL) {
246 				status = unregister_device_monitor(interface->device,
247 					link_monitor_data, protocol);
248 				if (status == B_OK) {
249 					// we're now no longer registered
250 					protocol->registered_monitor = false;
251 				}
252 				put_device_interface(interface);
253 			} else
254 				status = ENODEV;
255 
256 			return status;
257 		}
258 	}
259 
260 	return datalink_control(sDomain, option, value, _length);
261 }
262 
263 
264 status_t
265 link_bind(net_protocol *protocol, struct sockaddr *address)
266 {
267 	// TODO: bind to a specific interface and ethernet type
268 	return B_ERROR;
269 }
270 
271 
272 status_t
273 link_unbind(net_protocol *protocol, struct sockaddr *address)
274 {
275 	return B_ERROR;
276 }
277 
278 
279 status_t
280 link_listen(net_protocol *protocol, int count)
281 {
282 	return EOPNOTSUPP;
283 }
284 
285 
286 status_t
287 link_shutdown(net_protocol *protocol, int direction)
288 {
289 	return EOPNOTSUPP;
290 }
291 
292 
293 status_t
294 link_send_data(net_protocol *protocol, net_buffer *buffer)
295 {
296 	return B_NOT_ALLOWED;
297 }
298 
299 
300 status_t
301 link_send_routed_data(net_protocol *protocol, struct net_route *route,
302 	net_buffer *buffer)
303 {
304 	return B_NOT_ALLOWED;
305 }
306 
307 
308 ssize_t
309 link_send_avail(net_protocol *protocol)
310 {
311 	return B_ERROR;
312 }
313 
314 
315 status_t
316 link_read_data(net_protocol *_protocol, size_t numBytes, uint32 flags,
317 	net_buffer **_buffer)
318 {
319 	link_protocol *protocol = (link_protocol *)_protocol;
320 
321 	dprintf("link_read is waiting for data...\n");
322 
323 	net_buffer *buffer;
324 	status_t status = fifo_dequeue_buffer(&protocol->fifo,
325 		flags, protocol->socket->receive.timeout, &buffer);
326 	if (status < B_OK)
327 		return status;
328 
329 	*_buffer = buffer;
330 	return B_OK;
331 }
332 
333 
334 ssize_t
335 link_read_avail(net_protocol *_protocol)
336 {
337 	link_protocol *protocol = (link_protocol *)_protocol;
338 	return protocol->fifo.current_bytes;
339 }
340 
341 
342 struct net_domain *
343 link_get_domain(net_protocol *protocol)
344 {
345 	return sDomain;
346 }
347 
348 
349 size_t
350 link_get_mtu(net_protocol *protocol, const struct sockaddr *address)
351 {
352 	// TODO: for now
353 	return 0;
354 }
355 
356 
357 status_t
358 link_receive_data(net_buffer *buffer)
359 {
360 	return B_ERROR;
361 }
362 
363 
364 status_t
365 link_error(uint32 code, net_buffer *data)
366 {
367 	return B_ERROR;
368 }
369 
370 
371 status_t
372 link_error_reply(net_protocol *protocol, net_buffer *causedError, uint32 code,
373 	void *errorData)
374 {
375 	return B_ERROR;
376 }
377 
378 
379 static status_t
380 link_std_ops(int32 op, ...)
381 {
382 	switch (op) {
383 		case B_MODULE_INIT:
384 			return register_domain(AF_LINK, "link", NULL, NULL, &sDomain);
385 
386 		case B_MODULE_UNINIT:
387 			unregister_domain(sDomain);
388 			return B_OK;
389 
390 		default:
391 			return B_ERROR;
392 	}
393 }
394 
395 
396 //	#pragma mark -
397 
398 
399 void
400 link_init()
401 {
402 	register_domain_protocols(AF_LINK, SOCK_DGRAM, 0, "network/stack/link/v1", NULL);
403 
404 	register_domain_datalink_protocols(AF_LINK, IFT_ETHER,
405 		"network/datalink_protocols/ethernet_frame/v1",
406 		NULL);
407 }
408 
409 
410 net_protocol_module_info gLinkModule = {
411 	{
412 		"network/stack/link/v1",
413 		0,
414 		link_std_ops
415 	},
416 	link_init_protocol,
417 	link_uninit_protocol,
418 	link_open,
419 	link_close,
420 	link_free,
421 	link_connect,
422 	link_accept,
423 	link_control,
424 	link_bind,
425 	link_unbind,
426 	link_listen,
427 	link_shutdown,
428 	link_send_data,
429 	link_send_routed_data,
430 	link_send_avail,
431 	link_read_data,
432 	link_read_avail,
433 	link_get_domain,
434 	link_get_mtu,
435 	link_receive_data,
436 	link_error,
437 	link_error_reply,
438 };
439