xref: /haiku/src/add-ons/kernel/network/stack/link.cpp (revision e53357d57adc145e4c36a3dc35cecde8bea07297)
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 <lock.h>
20 #include <util/AutoLock.h>
21 
22 #include <KernelExport.h>
23 
24 #include <net/if_types.h>
25 #include <new>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <sys/sockio.h>
29 
30 
31 class LinkProtocol : public net_protocol {
32 public:
33 	LinkProtocol();
34 	~LinkProtocol();
35 
36 	status_t InitCheck() const;
37 
38 	status_t StartMonitoring(const char *);
39 	status_t StopMonitoring();
40 
41 	ssize_t ReadData(size_t numBytes, uint32 flags, net_buffer **_buffer);
42 	ssize_t ReadAvail() const;
43 
44 private:
45 	status_t _Enqueue(net_buffer *buffer);
46 	status_t _Unregister();
47 
48 	mutable benaphore	fLock;
49 	Fifo				fFifo;
50 
51 	net_device_monitor	fMonitor;
52 	net_device_interface *fMonitoredDevice;
53 
54 	static status_t _MonitorData(net_device_monitor *monitor, net_buffer *buffer);
55 	static void _MonitorEvent(net_device_monitor *monitor, int32 event);
56 };
57 
58 
59 struct net_domain *sDomain;
60 
61 
62 LinkProtocol::LinkProtocol()
63 	: fFifo("packet monitor fifo", 65536)
64 {
65 	benaphore_init(&fLock, "packet monitor lock");
66 
67 	fMonitor.cookie = this;
68 	fMonitor.receive = _MonitorData;
69 	fMonitor.event = _MonitorEvent;
70 	fMonitoredDevice = NULL;
71 }
72 
73 
74 LinkProtocol::~LinkProtocol()
75 {
76 	if (fMonitoredDevice) {
77 		unregister_device_monitor(fMonitoredDevice->device, &fMonitor);
78 		put_device_interface(fMonitoredDevice);
79 	}
80 
81 	benaphore_destroy(&fLock);
82 }
83 
84 
85 status_t
86 LinkProtocol::InitCheck() const
87 {
88 	return fLock.sem >= 0 && fFifo.InitCheck();
89 }
90 
91 
92 status_t
93 LinkProtocol::StartMonitoring(const char *deviceName)
94 {
95 	BenaphoreLocker _(fLock);
96 
97 	if (fMonitoredDevice)
98 		return B_BUSY;
99 
100 	net_device_interface *interface = get_device_interface(deviceName);
101 	if (interface == NULL)
102 		return ENODEV;
103 
104 	status_t status = register_device_monitor(interface->device, &fMonitor);
105 	if (status < B_OK) {
106 		put_device_interface(interface);
107 		return status;
108 	}
109 
110 	fMonitoredDevice = interface;
111 	return B_OK;
112 }
113 
114 
115 status_t
116 LinkProtocol::StopMonitoring()
117 {
118 	BenaphoreLocker _(fLock);
119 
120 	// TODO compare our device with the supplied device name?
121 	return _Unregister();
122 }
123 
124 
125 ssize_t
126 LinkProtocol::ReadData(size_t numBytes, uint32 flags, net_buffer **_buffer)
127 {
128 	BenaphoreLocker _(fLock);
129 
130 	if (fMonitoredDevice == NULL) {
131 		if (fFifo.current_bytes == 0)
132 			return ENODEV;
133 	}
134 
135 	net_buffer *buffer;
136 	status_t status = fFifo.Dequeue(&fLock, flags, socket->receive.timeout,
137 		&buffer);
138 	if (status < B_OK)
139 		return status;
140 
141 	*_buffer = buffer;
142 	return B_OK;
143 }
144 
145 
146 ssize_t
147 LinkProtocol::ReadAvail() const
148 {
149 	BenaphoreLocker _(fLock);
150 	if (fMonitoredDevice == NULL)
151 		return ECONNRESET;
152 	return fFifo.current_bytes;
153 }
154 
155 
156 status_t
157 LinkProtocol::_Unregister()
158 {
159 	if (fMonitoredDevice == NULL)
160 		return B_BAD_VALUE;
161 
162 	status_t status = unregister_device_monitor(fMonitoredDevice->device,
163 		&fMonitor);
164 	put_device_interface(fMonitoredDevice);
165 	fMonitoredDevice = NULL;
166 
167 	return status;
168 }
169 
170 
171 status_t
172 LinkProtocol::_Enqueue(net_buffer *buffer)
173 {
174 	BenaphoreLocker _(fLock);
175 	return fFifo.EnqueueAndNotify(buffer, socket, B_SELECT_READ);
176 }
177 
178 
179 status_t
180 LinkProtocol::_MonitorData(net_device_monitor *monitor, net_buffer *packet)
181 {
182 	return ((LinkProtocol *)monitor->cookie)->_Enqueue(packet);
183 }
184 
185 
186 void
187 LinkProtocol::_MonitorEvent(net_device_monitor *monitor, int32 event)
188 {
189 	LinkProtocol *protocol = (LinkProtocol *)monitor->cookie;
190 
191 	// We currently maintain the monitor while the device is down
192 	if (event == B_DEVICE_BEING_REMOVED) {
193 		BenaphoreLocker _(protocol->fLock);
194 
195 		protocol->_Unregister();
196 		notify_socket(protocol->socket, B_SELECT_READ, ECONNRESET);
197 	}
198 }
199 
200 
201 //	#pragma mark -
202 
203 
204 net_protocol *
205 link_init_protocol(net_socket *socket)
206 {
207 	LinkProtocol *protocol = new (std::nothrow) LinkProtocol();
208 	if (protocol && protocol->InitCheck() < B_OK) {
209 		delete protocol;
210 		return NULL;
211 	}
212 
213 	return protocol;
214 }
215 
216 
217 status_t
218 link_uninit_protocol(net_protocol *protocol)
219 {
220 	delete (LinkProtocol *)protocol;
221 	return B_OK;
222 }
223 
224 
225 status_t
226 link_open(net_protocol *protocol)
227 {
228 	return B_OK;
229 }
230 
231 
232 status_t
233 link_close(net_protocol *protocol)
234 {
235 	return B_OK;
236 }
237 
238 
239 status_t
240 link_free(net_protocol *protocol)
241 {
242 	return B_OK;
243 }
244 
245 
246 status_t
247 link_connect(net_protocol *protocol, const struct sockaddr *address)
248 {
249 	return EOPNOTSUPP;
250 }
251 
252 
253 status_t
254 link_accept(net_protocol *protocol, struct net_socket **_acceptedSocket)
255 {
256 	return EOPNOTSUPP;
257 }
258 
259 
260 status_t
261 link_control(net_protocol *_protocol, int level, int option, void *value,
262 	size_t *_length)
263 {
264 	LinkProtocol *protocol = (LinkProtocol *)_protocol;
265 
266 	// TODO All of this common functionality should be elsewhere
267 
268 	switch (option) {
269 		case SIOCGIFINDEX:
270 		{
271 			// get index of interface
272 			struct ifreq request;
273 			if (user_memcpy(&request, value, IF_NAMESIZE) < B_OK)
274 				return B_BAD_ADDRESS;
275 
276 			net_device_interface *interface = get_device_interface(request.ifr_name);
277 			if (interface != NULL) {
278 				request.ifr_index = interface->device->index;
279 				put_device_interface(interface);
280 			} else
281 				request.ifr_index = 0;
282 
283 			return user_memcpy(value, &request, sizeof(struct ifreq));
284 		}
285 		case SIOCGIFNAME:
286 		{
287 			// get name of interface via index
288 			struct ifreq request;
289 			if (user_memcpy(&request, value, sizeof(struct ifreq)) < B_OK)
290 				return B_BAD_ADDRESS;
291 
292 			net_device_interface *interface = get_device_interface(request.ifr_index);
293 			if (interface != NULL) {
294 				strlcpy(request.ifr_name, interface->name, IF_NAMESIZE);
295 				put_device_interface(interface);
296 			} else
297 				return ENODEV;
298 
299 			return user_memcpy(value, &request, sizeof(struct ifreq));
300 		}
301 
302 		case SIOCGIFCOUNT:
303 		{
304 			// count number of interfaces
305 			struct ifconf config;
306 			config.ifc_value = count_device_interfaces();
307 
308 			return user_memcpy(value, &config, sizeof(struct ifconf));
309 		}
310 
311 		case SIOCGIFCONF:
312 		{
313 			// retrieve available interfaces
314 			struct ifconf config;
315 			if (user_memcpy(&config, value, sizeof(struct ifconf)) < B_OK)
316 				return B_BAD_ADDRESS;
317 
318 			status_t result = list_device_interfaces(config.ifc_buf,
319 				(size_t *)&config.ifc_len);
320 			if (result != B_OK)
321 				return result;
322 
323 			return user_memcpy(value, &config, sizeof(struct ifconf));
324 		}
325 
326 		case SIOCGIFADDR:
327 		{
328 			// get address of interface
329 			struct ifreq request;
330 			if (user_memcpy(&request, value, IF_NAMESIZE) < B_OK)
331 				return B_BAD_ADDRESS;
332 
333 			net_device_interface *interface = get_device_interface(request.ifr_name);
334 			if (interface != NULL) {
335 				get_device_interface_address(interface, &request.ifr_addr);
336 				put_device_interface(interface);
337 			} else
338 				return ENODEV;
339 
340 			return user_memcpy(&((struct ifreq *)value)->ifr_addr,
341 				&request.ifr_addr, request.ifr_addr.sa_len);
342 		}
343 
344 		case SIOCSPACKETCAP:
345 		{
346 			struct ifreq request;
347 			if (user_memcpy(&request, value, IF_NAMESIZE) < B_OK)
348 				return B_BAD_ADDRESS;
349 
350 			return protocol->StartMonitoring(request.ifr_name);
351 		}
352 
353 		case SIOCCPACKETCAP:
354 			return protocol->StopMonitoring();
355 	}
356 
357 	return datalink_control(sDomain, option, value, _length);
358 }
359 
360 
361 status_t
362 link_bind(net_protocol *protocol, struct sockaddr *address)
363 {
364 	// TODO: bind to a specific interface and ethernet type
365 	return B_ERROR;
366 }
367 
368 
369 status_t
370 link_unbind(net_protocol *protocol, struct sockaddr *address)
371 {
372 	return B_ERROR;
373 }
374 
375 
376 status_t
377 link_listen(net_protocol *protocol, int count)
378 {
379 	return EOPNOTSUPP;
380 }
381 
382 
383 status_t
384 link_shutdown(net_protocol *protocol, int direction)
385 {
386 	return EOPNOTSUPP;
387 }
388 
389 
390 status_t
391 link_send_data(net_protocol *protocol, net_buffer *buffer)
392 {
393 	return B_NOT_ALLOWED;
394 }
395 
396 
397 status_t
398 link_send_routed_data(net_protocol *protocol, struct net_route *route,
399 	net_buffer *buffer)
400 {
401 	return B_NOT_ALLOWED;
402 }
403 
404 
405 ssize_t
406 link_send_avail(net_protocol *protocol)
407 {
408 	return B_ERROR;
409 }
410 
411 
412 status_t
413 link_read_data(net_protocol *protocol, size_t numBytes, uint32 flags,
414 	net_buffer **_buffer)
415 {
416 	return ((LinkProtocol *)protocol)->ReadData(numBytes, flags, _buffer);
417 }
418 
419 
420 ssize_t
421 link_read_avail(net_protocol *protocol)
422 {
423 	return ((LinkProtocol *)protocol)->ReadAvail();
424 }
425 
426 
427 struct net_domain *
428 link_get_domain(net_protocol *protocol)
429 {
430 	return sDomain;
431 }
432 
433 
434 size_t
435 link_get_mtu(net_protocol *protocol, const struct sockaddr *address)
436 {
437 	// TODO: for now
438 	return 0;
439 }
440 
441 
442 status_t
443 link_receive_data(net_buffer *buffer)
444 {
445 	return B_ERROR;
446 }
447 
448 
449 status_t
450 link_error(uint32 code, net_buffer *data)
451 {
452 	return B_ERROR;
453 }
454 
455 
456 status_t
457 link_error_reply(net_protocol *protocol, net_buffer *causedError, uint32 code,
458 	void *errorData)
459 {
460 	return B_ERROR;
461 }
462 
463 
464 static status_t
465 link_std_ops(int32 op, ...)
466 {
467 	switch (op) {
468 		case B_MODULE_INIT:
469 			return register_domain(AF_LINK, "link", NULL, NULL, &sDomain);
470 
471 		case B_MODULE_UNINIT:
472 			unregister_domain(sDomain);
473 			return B_OK;
474 
475 		default:
476 			return B_ERROR;
477 	}
478 }
479 
480 
481 //	#pragma mark -
482 
483 
484 void
485 link_init()
486 {
487 	register_domain_protocols(AF_LINK, SOCK_DGRAM, 0, "network/stack/link/v1", NULL);
488 
489 	register_domain_datalink_protocols(AF_LINK, IFT_ETHER,
490 		"network/datalink_protocols/ethernet_frame/v1",
491 		NULL);
492 }
493 
494 
495 net_protocol_module_info gLinkModule = {
496 	{
497 		"network/stack/link/v1",
498 		0,
499 		link_std_ops
500 	},
501 	link_init_protocol,
502 	link_uninit_protocol,
503 	link_open,
504 	link_close,
505 	link_free,
506 	link_connect,
507 	link_accept,
508 	link_control,
509 	link_bind,
510 	link_unbind,
511 	link_listen,
512 	link_shutdown,
513 	link_send_data,
514 	link_send_routed_data,
515 	link_send_avail,
516 	link_read_data,
517 	link_read_avail,
518 	link_get_domain,
519 	link_get_mtu,
520 	link_receive_data,
521 	link_error,
522 	link_error_reply,
523 };
524