xref: /haiku/src/add-ons/kernel/network/stack/link.cpp (revision 746cac055adc6ac3308c7bc2d29040fb95689cc9)
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<MutexLocking, 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 	MutexLocker _(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 	MutexLocker _(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 		MutexLocker _(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 	if (protocol->next != NULL) {
327 		return protocol->next->module->getsockopt(protocol, level, option,
328 			value, length);
329 	}
330 
331 	return gNetSocketModule.get_option(protocol->socket, level, option, value,
332 		length);
333 }
334 
335 
336 status_t
337 link_setsockopt(net_protocol *protocol, int level, int option,
338 	const void *value, int length)
339 {
340 	if (protocol->next != NULL) {
341 		return protocol->next->module->setsockopt(protocol, level, option,
342 			value, length);
343 	}
344 
345 	return gNetSocketModule.set_option(protocol->socket, level, option,
346 		value, length);
347 }
348 
349 
350 status_t
351 link_bind(net_protocol *protocol, const struct sockaddr *address)
352 {
353 	// TODO: bind to a specific interface and ethernet type
354 	return B_ERROR;
355 }
356 
357 
358 status_t
359 link_unbind(net_protocol *protocol, struct sockaddr *address)
360 {
361 	return B_ERROR;
362 }
363 
364 
365 status_t
366 link_listen(net_protocol *protocol, int count)
367 {
368 	return EOPNOTSUPP;
369 }
370 
371 
372 status_t
373 link_shutdown(net_protocol *protocol, int direction)
374 {
375 	return EOPNOTSUPP;
376 }
377 
378 
379 status_t
380 link_send_data(net_protocol *protocol, net_buffer *buffer)
381 {
382 	return B_NOT_ALLOWED;
383 }
384 
385 
386 status_t
387 link_send_routed_data(net_protocol *protocol, struct net_route *route,
388 	net_buffer *buffer)
389 {
390 	return B_NOT_ALLOWED;
391 }
392 
393 
394 ssize_t
395 link_send_avail(net_protocol *protocol)
396 {
397 	return B_ERROR;
398 }
399 
400 
401 status_t
402 link_read_data(net_protocol *protocol, size_t numBytes, uint32 flags,
403 	net_buffer **_buffer)
404 {
405 	return ((LinkProtocol *)protocol)->SocketDequeue(flags, _buffer);
406 }
407 
408 
409 ssize_t
410 link_read_avail(net_protocol *protocol)
411 {
412 	return ((LinkProtocol *)protocol)->AvailableData();
413 }
414 
415 
416 struct net_domain *
417 link_get_domain(net_protocol *protocol)
418 {
419 	return sDomain;
420 }
421 
422 
423 size_t
424 link_get_mtu(net_protocol *protocol, const struct sockaddr *address)
425 {
426 	// TODO: for now
427 	return 0;
428 }
429 
430 
431 status_t
432 link_receive_data(net_buffer *buffer)
433 {
434 	return B_ERROR;
435 }
436 
437 
438 status_t
439 link_error(uint32 code, net_buffer *data)
440 {
441 	return B_ERROR;
442 }
443 
444 
445 status_t
446 link_error_reply(net_protocol *protocol, net_buffer *causedError, uint32 code,
447 	void *errorData)
448 {
449 	return B_ERROR;
450 }
451 
452 
453 static status_t
454 link_std_ops(int32 op, ...)
455 {
456 	switch (op) {
457 		case B_MODULE_INIT:
458 			return register_domain(AF_LINK, "link", NULL, NULL, &sDomain);
459 
460 		case B_MODULE_UNINIT:
461 			unregister_domain(sDomain);
462 			return B_OK;
463 
464 		default:
465 			return B_ERROR;
466 	}
467 }
468 
469 
470 //	#pragma mark -
471 
472 
473 void
474 link_init()
475 {
476 	register_domain_protocols(AF_LINK, SOCK_DGRAM, 0, "network/stack/link/v1", NULL);
477 
478 	register_domain_datalink_protocols(AF_LINK, IFT_ETHER,
479 		"network/datalink_protocols/ethernet_frame/v1",
480 		NULL);
481 }
482 
483 
484 net_protocol_module_info gLinkModule = {
485 	{
486 		"network/stack/link/v1",
487 		0,
488 		link_std_ops
489 	},
490 	NET_PROTOCOL_ATOMIC_MESSAGES,
491 
492 	link_init_protocol,
493 	link_uninit_protocol,
494 	link_open,
495 	link_close,
496 	link_free,
497 	link_connect,
498 	link_accept,
499 	link_control,
500 	link_getsockopt,
501 	link_setsockopt,
502 	link_bind,
503 	link_unbind,
504 	link_listen,
505 	link_shutdown,
506 	link_send_data,
507 	link_send_routed_data,
508 	link_send_avail,
509 	link_read_data,
510 	link_read_avail,
511 	link_get_domain,
512 	link_get_mtu,
513 	link_receive_data,
514 	NULL,
515 	link_error,
516 	link_error_reply,
517 };
518