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