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