1 /*
2 * Copyright 2006-2010, 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 * Hugo Santos, hugosantos@gmail.com
8 */
9
10
11 #include <net/if.h>
12 #include <net/if_dl.h>
13 #include <net/if_media.h>
14 #include <net/route.h>
15 #include <new>
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <string.h>
19 #include <sys/sockio.h>
20
21 #include <KernelExport.h>
22
23 #include <net_datalink.h>
24 #include <net_device.h>
25 #include <NetUtilities.h>
26
27 #include "device_interfaces.h"
28 #include "domains.h"
29 #include "interfaces.h"
30 #include "routes.h"
31 #include "stack_private.h"
32 #include "utility.h"
33
34
35 //#define TRACE_DATALINK
36 #ifdef TRACE_DATALINK
37 # define TRACE(x...) dprintf(STACK_DEBUG_PREFIX x)
38 #else
39 # define TRACE(x...) ;
40 #endif
41
42
43 struct datalink_protocol : net_protocol {
44 struct net_domain_private* domain;
45 };
46
47 struct interface_protocol : net_datalink_protocol {
48 struct net_device_module_info* device_module;
49 struct net_device* device;
50 };
51
52
53 #ifdef TRACE_DATALINK
54
55
56 static const char*
option_to_string(int32 option)57 option_to_string(int32 option)
58 {
59 # define CODE(x) case x: return #x;
60 switch (option) {
61 CODE(SIOCADDRT) /* add route */
62 CODE(SIOCDELRT) /* delete route */
63 CODE(SIOCSIFADDR) /* set interface address */
64 CODE(SIOCGIFADDR) /* get interface address */
65 CODE(SIOCSIFDSTADDR) /* set point-to-point address */
66 CODE(SIOCGIFDSTADDR) /* get point-to-point address */
67 CODE(SIOCSIFFLAGS) /* set interface flags */
68 CODE(SIOCGIFFLAGS) /* get interface flags */
69 CODE(SIOCGIFBRDADDR) /* get broadcast address */
70 CODE(SIOCSIFBRDADDR) /* set broadcast address */
71 CODE(SIOCGIFCOUNT) /* count interfaces */
72 CODE(SIOCGIFCONF) /* get interface list */
73 CODE(SIOCGIFINDEX) /* interface name -> index */
74 CODE(SIOCGIFNAME) /* interface index -> name */
75 CODE(SIOCGIFNETMASK) /* get net address mask */
76 CODE(SIOCSIFNETMASK) /* set net address mask */
77 CODE(SIOCGIFMETRIC) /* get interface metric */
78 CODE(SIOCSIFMETRIC) /* set interface metric */
79 CODE(SIOCDIFADDR) /* delete interface address */
80 CODE(SIOCAIFADDR) /* configure interface alias */
81 CODE(SIOCADDMULTI) /* add multicast address */
82 CODE(SIOCDELMULTI) /* delete multicast address */
83 CODE(SIOCGIFMTU) /* get interface MTU */
84 CODE(SIOCSIFMTU) /* set interface MTU */
85 CODE(SIOCSIFMEDIA) /* set net media */
86 CODE(SIOCGIFMEDIA) /* get net media */
87
88 CODE(SIOCGRTSIZE) /* get route table size */
89 CODE(SIOCGRTTABLE) /* get route table */
90 CODE(SIOCGETRT) /* get route information for destination */
91
92 CODE(SIOCGIFSTATS) /* get interface stats */
93 CODE(SIOCGIFTYPE) /* get interface type */
94
95 CODE(SIOCSPACKETCAP) /* Start capturing packets on an interface */
96 CODE(SIOCCPACKETCAP) /* Stop capturing packets on an interface */
97
98 CODE(SIOCSHIWAT) /* set high watermark */
99 CODE(SIOCGHIWAT) /* get high watermark */
100 CODE(SIOCSLOWAT) /* set low watermark */
101 CODE(SIOCGLOWAT) /* get low watermark */
102 CODE(SIOCATMARK) /* at out-of-band mark? */
103 CODE(SIOCSPGRP) /* set process group */
104 CODE(SIOCGPGRP) /* get process group */
105
106 CODE(SIOCGPRIVATE_0) /* device private 0 */
107 CODE(SIOCGPRIVATE_1) /* device private 1 */
108 CODE(SIOCSDRVSPEC) /* set driver-specific parameters */
109 CODE(SIOCGDRVSPEC) /* get driver-specific parameters */
110
111 CODE(SIOCSIFGENERIC) /* generic IF set op */
112 CODE(SIOCGIFGENERIC) /* generic IF get op */
113
114 CODE(B_SOCKET_SET_ALIAS) /* set interface alias, ifaliasreq */
115 CODE(B_SOCKET_GET_ALIAS) /* get interface alias, ifaliasreq */
116 CODE(B_SOCKET_COUNT_ALIASES) /* count interface aliases */
117
118 default:
119 static char buffer[24];
120 snprintf(buffer, sizeof(buffer), "%" B_PRId32, option);
121 return buffer;
122 }
123 # undef CODE
124 }
125
126
127 #endif // TRACE_DATALINK
128
129
130 static status_t
get_interface_name_or_index(net_domain * domain,int32 option,void * value,size_t * _length)131 get_interface_name_or_index(net_domain* domain, int32 option, void* value,
132 size_t* _length)
133 {
134 ASSERT(option == SIOCGIFINDEX || option == SIOCGIFNAME);
135
136 size_t expected = option == SIOCGIFINDEX ? IF_NAMESIZE : sizeof(ifreq);
137 if (*_length > 0 && *_length < expected)
138 return B_BAD_VALUE;
139
140 ifreq request;
141 memset(&request, 0, sizeof(request));
142
143 if (user_memcpy(&request, value, expected) < B_OK)
144 return B_BAD_ADDRESS;
145
146 Interface* interface = NULL;
147 if (option == SIOCGIFINDEX)
148 interface = get_interface(domain, request.ifr_name);
149 else
150 interface = get_interface(domain, request.ifr_index);
151
152 if (interface == NULL)
153 return B_BAD_VALUE;
154
155 if (option == SIOCGIFINDEX)
156 request.ifr_index = interface->index;
157 else
158 strlcpy(request.ifr_name, interface->name, IF_NAMESIZE);
159
160 *_length = sizeof(ifreq);
161 interface->ReleaseReference();
162
163 return user_memcpy(value, &request, sizeof(ifreq));
164 }
165
166
167 static void
set_interface_address(net_interface_address * & target,InterfaceAddress * address)168 set_interface_address(net_interface_address*& target, InterfaceAddress* address)
169 {
170 if (target != NULL)
171 static_cast<InterfaceAddress*>(target)->ReleaseReference();
172
173 target = address;
174 }
175
176
177 static status_t
fill_address(const sockaddr * from,sockaddr * to,size_t maxLength)178 fill_address(const sockaddr* from, sockaddr* to, size_t maxLength)
179 {
180 if (from != NULL) {
181 // Copy address over
182 return user_memcpy(to, from, min_c(from->sa_len, maxLength));
183 }
184
185 // Fill in empty address
186 sockaddr empty;
187 empty.sa_len = 2;
188 empty.sa_family = AF_UNSPEC;
189
190 return user_memcpy(to, &empty, min_c(2, maxLength));
191 }
192
193
194 static void
update_device_send_stats(struct net_device * device,status_t status,size_t packetSize)195 update_device_send_stats(struct net_device* device, status_t status, size_t packetSize)
196 {
197 if (status == B_OK) {
198 atomic_add((int32*)&device->stats.send.packets, 1);
199 atomic_add64((int64*)&device->stats.send.bytes, packetSize);
200 } else {
201 atomic_add((int32*)&device->stats.send.errors, 1);
202 }
203 }
204
205
206 // #pragma mark - datalink module
207
208
209 static status_t
datalink_control(net_domain * _domain,int32 option,void * value,size_t * _length)210 datalink_control(net_domain* _domain, int32 option, void* value,
211 size_t* _length)
212 {
213 TRACE("%s(domain %p, option %s, value %p, length %zu)\n", __FUNCTION__,
214 _domain, option_to_string(option), value, *_length);
215
216 net_domain_private* domain = (net_domain_private*)_domain;
217 if (domain == NULL || domain->family == AF_LINK) {
218 // the AF_LINK family is already handled completely in the link protocol
219 return B_BAD_VALUE;
220 }
221
222 switch (option) {
223 case SIOCGIFINDEX:
224 case SIOCGIFNAME:
225 return get_interface_name_or_index(domain, option, value, _length);
226
227 case SIOCAIFADDR: /* same as B_SOCKET_ADD_ALIAS */
228 {
229 // add new interface address
230 if (*_length > 0 && *_length < sizeof(struct ifaliasreq))
231 return B_BAD_VALUE;
232
233 struct ifaliasreq request;
234 if (user_memcpy(&request, value, sizeof(struct ifaliasreq)) != B_OK)
235 return B_BAD_ADDRESS;
236
237 Interface* interface = get_interface(domain, request.ifra_name);
238 if (interface != NULL) {
239 // A new alias is added to this interface
240 status_t status = add_interface_address(interface, domain,
241 request);
242 notify_interface_changed(interface);
243 interface->ReleaseReference();
244
245 return status;
246 }
247
248 // A new interface needs to be added
249 net_device_interface* deviceInterface
250 = get_device_interface(request.ifra_name);
251 if (deviceInterface == NULL)
252 return B_DEVICE_NOT_FOUND;
253
254 status_t status = add_interface(request.ifra_name, domain, request,
255 deviceInterface);
256
257 put_device_interface(deviceInterface);
258 return status;
259 }
260
261 case SIOCDIFADDR: /* same as B_SOCKET_REMOVE_ALIAS */
262 {
263 // remove interface (address)
264 struct ifreq request;
265 if (user_memcpy(&request, value, sizeof(struct ifreq)) != B_OK)
266 return B_BAD_ADDRESS;
267
268 Interface* interface = get_interface(domain, request.ifr_name);
269 if (interface == NULL)
270 return B_BAD_VALUE;
271
272 status_t status = B_OK;
273
274 if (request.ifr_addr.sa_family != AF_UNSPEC
275 && request.ifr_addr.sa_len != 0) {
276 status = interface->Control(domain, SIOCDIFADDR, request,
277 (ifreq*)value, *_length);
278 } else
279 remove_interface(interface);
280
281 interface->ReleaseReference();
282
283 return status;
284 }
285
286 case SIOCGIFCOUNT:
287 {
288 // count number of interfaces
289 struct ifconf config;
290 config.ifc_value = count_interfaces();
291
292 return user_memcpy(value, &config, sizeof(struct ifconf));
293 }
294
295 case SIOCGIFCONF:
296 {
297 // retrieve ifreqs for all interfaces
298 struct ifconf config;
299 if (user_memcpy(&config, value, sizeof(struct ifconf)) < B_OK)
300 return B_BAD_ADDRESS;
301
302 size_t size = config.ifc_len;
303 status_t status
304 = list_interfaces(domain->family, config.ifc_buf, &size);
305 if (status != B_OK)
306 return status;
307
308 config.ifc_len = (int)size;
309 return user_memcpy(value, &config, sizeof(struct ifconf));
310 }
311
312 case SIOCGRTSIZE:
313 {
314 // determine size of buffer to hold the routing table
315 struct ifconf config;
316 config.ifc_value = route_table_size(domain);
317
318 return user_memcpy(value, &config, sizeof(struct ifconf));
319 }
320 case SIOCGRTTABLE:
321 {
322 // retrieve all routes for this domain
323 struct ifconf config;
324 if (user_memcpy(&config, value, sizeof(struct ifconf)) < B_OK)
325 return B_BAD_ADDRESS;
326
327 return list_routes(domain, config.ifc_buf, config.ifc_len);
328 }
329 case SIOCGETRT:
330 return get_route_information(domain, value, *_length);
331
332 default:
333 {
334 // We also accept partial ifreqs as long as the name is complete.
335 size_t length = sizeof(struct ifreq);
336 if (*_length > 0 && *_length >= IF_NAMESIZE)
337 length = min_c(length, *_length);
338
339 // try to pass the request to an existing interface
340 struct ifreq request;
341 if (user_memcpy(&request, value, length) != B_OK)
342 return B_BAD_ADDRESS;
343
344 Interface* interface = get_interface(domain, request.ifr_name);
345 if (interface == NULL)
346 return B_BAD_VALUE;
347
348 status_t status = interface->Control(domain, option, request,
349 (ifreq*)value, *_length);
350
351 interface->ReleaseReference();
352 return status;
353 }
354 }
355 return B_BAD_VALUE;
356 }
357
358
359 static status_t
datalink_send_routed_data(struct net_route * route,net_buffer * buffer)360 datalink_send_routed_data(struct net_route* route, net_buffer* buffer)
361 {
362 TRACE("%s(route %p, buffer %p)\n", __FUNCTION__, route, buffer);
363
364 InterfaceAddress* address = (InterfaceAddress*)route->interface_address;
365 Interface* interface = (Interface*)address->interface;
366
367 //dprintf("send buffer (%ld bytes) to interface %s (route flags %lx)\n",
368 // buffer->size, interface->name, route->flags);
369
370 if ((route->flags & RTF_REJECT) != 0) {
371 TRACE(" rejected route\n");
372 return ENETUNREACH;
373 }
374
375 if ((route->flags & RTF_HOST) != 0) {
376 TRACE(" host route\n");
377 // We set the interface address here, so the buffer is delivered
378 // directly to the domain in interfaces.cpp:device_consumer_thread()
379 address->AcquireReference();
380 set_interface_address(buffer->interface_address, address);
381 }
382
383 if ((route->flags & RTF_LOCAL) != 0) {
384 TRACE(" local route\n");
385
386 // We set the interface address here, so the buffer is delivered
387 // directly to the domain in interfaces.cpp:device_consumer_thread()
388 address->AcquireReference();
389 set_interface_address(buffer->interface_address, address);
390
391 if (atomic_get(&interface->DeviceInterface()->monitor_count) > 0)
392 device_interface_monitor_receive(interface->DeviceInterface(), buffer);
393
394 // this one goes back to the domain directly
395 const size_t packetSize = buffer->size;
396 status_t status = fifo_enqueue_buffer(
397 &interface->DeviceInterface()->receive_queue, buffer);
398 update_device_send_stats(interface->DeviceInterface()->device,
399 status, packetSize);
400 return status;
401 }
402
403 if ((route->flags & RTF_GATEWAY) != 0) {
404 TRACE(" gateway route\n");
405
406 // This route involves a gateway, we need to use the gateway address
407 // instead of the destination address:
408 if (route->gateway == NULL)
409 return B_MISMATCHED_VALUES;
410 memcpy(buffer->destination, route->gateway, route->gateway->sa_len);
411 }
412
413 // this goes out to the datalink protocols
414 domain_datalink* datalink
415 = interface->DomainDatalink(address->domain->family);
416 return datalink->first_info->send_data(datalink->first_protocol, buffer);
417 }
418
419
420 /*! Finds a route for the given \a buffer in the given \a domain, and calls
421 net_protocol_info::send_routed_data() on either the \a protocol (if
422 non-NULL), or the domain.
423 */
424 static status_t
datalink_send_data(net_protocol * protocol,net_domain * domain,net_buffer * buffer)425 datalink_send_data(net_protocol* protocol, net_domain* domain,
426 net_buffer* buffer)
427 {
428 TRACE("%s(%p, domain %p, buffer %p)\n", __FUNCTION__, protocol, domain,
429 buffer);
430
431 if (protocol == NULL && domain == NULL)
432 return B_BAD_VALUE;
433
434 net_protocol_module_info* module = protocol != NULL
435 ? protocol->module : domain->module;
436
437 if (domain == NULL)
438 domain = protocol->module->get_domain(protocol);
439
440 net_route* route = NULL;
441 status_t status;
442 if (protocol != NULL && protocol->socket != NULL
443 && protocol->socket->bound_to_device != 0) {
444 status = get_device_route(domain, protocol->socket->bound_to_device,
445 &route);
446 } else
447 status = get_buffer_route(domain, buffer, &route);
448
449 TRACE(" route status: %s\n", strerror(status));
450
451 if (status != B_OK)
452 return status;
453
454 status = module->send_routed_data(protocol, route, buffer);
455 put_route(domain, route);
456 return status;
457 }
458
459
460 /*! Tests if \a address is a local address in the domain.
461
462 \param _interfaceAddress will be set to the interface address belonging to
463 that address if non-NULL. If the address \a _interfaceAddress points to
464 is not NULL, it is assumed that it already points to an address, which
465 is then released before the new address is assigned.
466 \param _matchedType will be set to either zero or MSG_BCAST if non-NULL.
467 */
468 static bool
datalink_is_local_address(net_domain * domain,const struct sockaddr * address,net_interface_address ** _interfaceAddress,uint32 * _matchedType)469 datalink_is_local_address(net_domain* domain, const struct sockaddr* address,
470 net_interface_address** _interfaceAddress, uint32* _matchedType)
471 {
472 TRACE("%s(domain %p, address %s)\n", __FUNCTION__, domain,
473 AddressString(domain, address).Data());
474
475 if (domain == NULL || address == NULL
476 || domain->family != address->sa_family)
477 return false;
478
479 uint32 matchedType = 0;
480
481 InterfaceAddress* interfaceAddress = get_interface_address(address);
482 if (interfaceAddress == NULL) {
483 // Check for matching broadcast address
484 if ((domain->address_module->flags
485 & NET_ADDRESS_MODULE_FLAG_BROADCAST_ADDRESS) != 0) {
486 interfaceAddress
487 = get_interface_address_for_destination(domain, address);
488 matchedType = MSG_BCAST;
489 }
490 if (interfaceAddress == NULL) {
491 TRACE(" no\n");
492 return false;
493 }
494 }
495
496 TRACE(" it is, interface address %p\n", interfaceAddress);
497
498 if (_interfaceAddress != NULL)
499 set_interface_address(*_interfaceAddress, interfaceAddress);
500 else
501 interfaceAddress->ReleaseReference();
502
503 if (_matchedType != NULL)
504 *_matchedType = matchedType;
505
506 return true;
507 }
508
509
510 /*! Tests if \a address is a local link address in the domain.
511
512 \param unconfiguredOnly only unconfigured interfaces are taken into account.
513 \param _interfaceAddress will be set to the first address of the interface
514 and domain belonging to that address if non-NULL. If the address
515 \a _interfaceAddress points to is not NULL, it is assumed that it
516 already points to an address, which is then released before the new
517 address is assigned.
518 */
519 static bool
datalink_is_local_link_address(net_domain * domain,bool unconfiguredOnly,const struct sockaddr * address,net_interface_address ** _interfaceAddress)520 datalink_is_local_link_address(net_domain* domain, bool unconfiguredOnly,
521 const struct sockaddr* address, net_interface_address** _interfaceAddress)
522 {
523 if (domain == NULL || address == NULL || address->sa_family != AF_LINK)
524 return false;
525
526 #ifdef TRACE_DATALINK
527 uint8* data = LLADDR((sockaddr_dl*)address);
528 TRACE("%s(domain %p, unconfiguredOnly %d, address %02x:%02x:%02x:%02x:%02x"
529 ":%02x)\n", __FUNCTION__, domain, unconfiguredOnly, data[0], data[1],
530 data[2], data[3], data[4], data[5]);
531 #endif
532
533 InterfaceAddress* interfaceAddress = get_interface_address_for_link(domain,
534 address, unconfiguredOnly);
535 if (interfaceAddress == NULL) {
536 TRACE(" no\n");
537 return false;
538 }
539
540 if (_interfaceAddress != NULL)
541 set_interface_address(*_interfaceAddress, interfaceAddress);
542 else
543 interfaceAddress->ReleaseReference();
544
545 return true;
546 }
547
548
549 static net_interface*
datalink_get_interface(net_domain * domain,uint32 index)550 datalink_get_interface(net_domain* domain, uint32 index)
551 {
552 return get_interface(domain, index);
553 }
554
555
556 static net_interface*
datalink_get_interface_with_address(const sockaddr * address)557 datalink_get_interface_with_address(const sockaddr* address)
558 {
559 InterfaceAddress* interfaceAddress = get_interface_address(address);
560 if (interfaceAddress == NULL)
561 return NULL;
562
563 Interface* interface = static_cast<Interface*>(interfaceAddress->interface);
564
565 interface->AcquireReference();
566 interfaceAddress->ReleaseReference();
567
568 return interface;
569 }
570
571
572 static void
datalink_put_interface(net_interface * interface)573 datalink_put_interface(net_interface* interface)
574 {
575 if (interface == NULL)
576 return;
577
578 ((Interface*)interface)->ReleaseReference();
579 }
580
581
582 static net_interface_address*
datalink_get_interface_address(const struct sockaddr * address)583 datalink_get_interface_address(const struct sockaddr* address)
584 {
585 return get_interface_address(address);
586 }
587
588
589 /*! Returns a reference to the next address of the given interface in
590 \a _address. When you call this function the first time, \a _address must
591 point to a NULL address. Upon the next call, the reference to the previous
592 address is taken over again.
593
594 If you do not traverse the list to the end, you'll have to manually release
595 the reference to the address where you stopped.
596
597 \param interface The interface whose address list should be iterated over.
598 \param _address A pointer to the location where the next address should
599 be stored.
600
601 \return \c true if an address reference was returned, \c false if not.
602 */
603 static bool
datalink_get_next_interface_address(net_interface * _interface,net_interface_address ** _address)604 datalink_get_next_interface_address(net_interface* _interface,
605 net_interface_address** _address)
606 {
607 Interface* interface = (Interface*)_interface;
608
609 InterfaceAddress* address = (InterfaceAddress*)*_address;
610 bool gotOne = interface->GetNextAddress(&address);
611 *_address = address;
612
613 return gotOne;
614 }
615
616
617 static void
datalink_put_interface_address(net_interface_address * address)618 datalink_put_interface_address(net_interface_address* address)
619 {
620 if (address == NULL)
621 return;
622
623 ((InterfaceAddress*)address)->ReleaseReference();
624 }
625
626
627 static status_t
datalink_join_multicast(net_interface * _interface,net_domain * domain,const struct sockaddr * address)628 datalink_join_multicast(net_interface* _interface, net_domain* domain,
629 const struct sockaddr* address)
630 {
631 Interface* interface = (Interface*)_interface;
632 domain_datalink* datalink = interface->DomainDatalink(domain->family);
633
634 return datalink->first_info->join_multicast(datalink->first_protocol,
635 address);
636 }
637
638
639 static status_t
datalink_leave_multicast(net_interface * _interface,net_domain * domain,const struct sockaddr * address)640 datalink_leave_multicast(net_interface* _interface, net_domain* domain,
641 const struct sockaddr* address)
642 {
643 Interface* interface = (Interface*)_interface;
644 domain_datalink* datalink = interface->DomainDatalink(domain->family);
645
646 return datalink->first_info->leave_multicast(datalink->first_protocol,
647 address);
648 }
649
650
651 static status_t
datalink_std_ops(int32 op,...)652 datalink_std_ops(int32 op, ...)
653 {
654 switch (op) {
655 case B_MODULE_INIT:
656 case B_MODULE_UNINIT:
657 return B_OK;
658
659 default:
660 return B_ERROR;
661 }
662 }
663
664
665 // #pragma mark - net_datalink_protocol
666
667
668 static status_t
interface_protocol_init(net_interface * interface,net_domain * domain,net_datalink_protocol ** _protocol)669 interface_protocol_init(net_interface* interface, net_domain* domain,
670 net_datalink_protocol** _protocol)
671 {
672 interface_protocol* protocol = new(std::nothrow) interface_protocol;
673 if (protocol == NULL)
674 return B_NO_MEMORY;
675
676 TRACE("%s(%p, interface %p - %s, domain %p)\n", __FUNCTION__, protocol,
677 interface, interface->name, domain);
678
679 protocol->device_module = interface->device->module;
680 protocol->device = interface->device;
681
682 *_protocol = protocol;
683 return B_OK;
684 }
685
686
687 static status_t
interface_protocol_uninit(net_datalink_protocol * protocol)688 interface_protocol_uninit(net_datalink_protocol* protocol)
689 {
690 TRACE("%s(%p)\n", __FUNCTION__, protocol);
691
692 delete protocol;
693 return B_OK;
694 }
695
696
697 static status_t
interface_protocol_send_data(net_datalink_protocol * _protocol,net_buffer * buffer)698 interface_protocol_send_data(net_datalink_protocol* _protocol,
699 net_buffer* buffer)
700 {
701 TRACE("%s(%p, buffer %p)\n", __FUNCTION__, _protocol, buffer);
702
703 interface_protocol* protocol = (interface_protocol*)_protocol;
704 Interface* interface = (Interface*)protocol->interface;
705
706 if (atomic_get(&interface->DeviceInterface()->monitor_count) > 0)
707 device_interface_monitor_receive(interface->DeviceInterface(), buffer);
708
709 const size_t packetSize = buffer->size;
710 status_t status = protocol->device_module->send_data(protocol->device, buffer);
711 update_device_send_stats(protocol->device, status, packetSize);
712 return status;
713 }
714
715
716 static status_t
interface_protocol_up(net_datalink_protocol * protocol)717 interface_protocol_up(net_datalink_protocol* protocol)
718 {
719 TRACE("%s(%p)\n", __FUNCTION__, protocol);
720 return B_OK;
721 }
722
723
724 static void
interface_protocol_down(net_datalink_protocol * _protocol)725 interface_protocol_down(net_datalink_protocol* _protocol)
726 {
727 TRACE("%s(%p)\n", __FUNCTION__, _protocol);
728
729 interface_protocol* protocol = (interface_protocol*)_protocol;
730 Interface* interface = (Interface*)protocol->interface;
731 net_device_interface* deviceInterface = interface->DeviceInterface();
732
733 if (deviceInterface->up_count == 0)
734 return;
735
736 deviceInterface->up_count--;
737
738 interface->WentDown();
739
740 if (deviceInterface->up_count > 0)
741 return;
742
743 down_device_interface(deviceInterface);
744 }
745
746
747 static status_t
interface_protocol_change_address(net_datalink_protocol * protocol,net_interface_address * interfaceAddress,int32 option,const struct sockaddr * oldAddress,const struct sockaddr * newAddress)748 interface_protocol_change_address(net_datalink_protocol* protocol,
749 net_interface_address* interfaceAddress, int32 option,
750 const struct sockaddr* oldAddress, const struct sockaddr* newAddress)
751 {
752 TRACE("%s(%p, interface address %p, option %s, old %p, new %p)\n",
753 __FUNCTION__, protocol, interfaceAddress, option_to_string(option),
754 oldAddress, newAddress);
755
756 switch (option) {
757 case SIOCSIFADDR:
758 case SIOCSIFNETMASK:
759 case SIOCSIFBRDADDR:
760 case SIOCSIFDSTADDR:
761 case SIOCDIFADDR:
762 return update_interface_address((InterfaceAddress*)interfaceAddress,
763 option, oldAddress, newAddress);
764 }
765
766 return B_OK;
767 }
768
769
770 static status_t
interface_protocol_control(net_datalink_protocol * _protocol,int32 option,void * argument,size_t length)771 interface_protocol_control(net_datalink_protocol* _protocol, int32 option,
772 void* argument, size_t length)
773 {
774 TRACE("%s(%p, option %s, argument %p, length %zu)\n", __FUNCTION__,
775 _protocol, option_to_string(option), argument, length);
776
777 interface_protocol* protocol = (interface_protocol*)_protocol;
778 Interface* interface = (Interface*)protocol->interface;
779
780 switch (option) {
781 case SIOCGIFADDR:
782 case SIOCGIFNETMASK:
783 case SIOCGIFBRDADDR:
784 case SIOCGIFDSTADDR:
785 {
786 if (length == 0)
787 length = sizeof(ifreq);
788 else if (length < sizeof(ifreq))
789 return B_BAD_VALUE;
790
791 ifreq request;
792 if (user_memcpy(&request, argument, sizeof(struct ifreq)) != B_OK)
793 return B_BAD_ADDRESS;
794
795 InterfaceAddress* interfaceAddress
796 = get_interface_address(&request.ifr_addr);
797 if (interfaceAddress == NULL) {
798 interfaceAddress
799 = interface->FirstForFamily(protocol->domain->family);
800 if (interfaceAddress == NULL)
801 return B_BAD_VALUE;
802 }
803
804 size_t maxLength = length - offsetof(ifreq, ifr_addr);
805
806 status_t status = fill_address(
807 *interfaceAddress->AddressFor(option),
808 &((struct ifreq*)argument)->ifr_addr, maxLength);
809
810 interfaceAddress->ReleaseReference();
811 return status;
812 }
813
814 case B_SOCKET_COUNT_ALIASES:
815 {
816 ifreq request;
817 request.ifr_count = interface->CountAddresses();
818
819 return user_memcpy(&((struct ifreq*)argument)->ifr_count,
820 &request.ifr_count, sizeof(request.ifr_count));
821 }
822
823 case B_SOCKET_GET_ALIAS:
824 {
825 ifaliasreq request;
826 if (user_memcpy(&request, argument, sizeof(ifaliasreq)) != B_OK)
827 return B_BAD_ADDRESS;
828
829 InterfaceAddress* address = NULL;
830 if (request.ifra_index < 0) {
831 if (!protocol->domain->address_module->is_empty_address(
832 (const sockaddr*)&request.ifra_addr, false)) {
833 // Find first address that matches the local address
834 address = interface->AddressForLocal(protocol->domain,
835 (const sockaddr*)&request.ifra_addr);
836 } else {
837 // Find first address for family
838 address = interface->FirstForFamily(
839 protocol->domain->family);
840 }
841
842 request.ifra_index = interface->IndexOfAddress(address);
843 } else
844 address = interface->AddressAt(request.ifra_index);
845 if (address == NULL)
846 return B_BAD_VALUE;
847
848 // Copy index (in case none was specified)
849 status_t status = user_memcpy(
850 &((struct ifaliasreq*)argument)->ifra_index,
851 &request.ifra_index, sizeof(request.ifra_index));
852
853 // Copy address info
854 if (status == B_OK) {
855 status = fill_address(address->local,
856 (sockaddr*)&((struct ifaliasreq*)argument)->ifra_addr,
857 sizeof(sockaddr_storage));
858 }
859 if (status == B_OK) {
860 status = fill_address(address->mask,
861 (sockaddr*)&((struct ifaliasreq*)argument)->ifra_mask,
862 sizeof(sockaddr_storage));
863 }
864 if (status == B_OK) {
865 status = fill_address(address->destination,
866 (sockaddr*)&((struct ifaliasreq*)argument)
867 ->ifra_destination,
868 sizeof(sockaddr_storage));
869 }
870
871 address->ReleaseReference();
872
873 return status;
874 }
875
876 case SIOCGIFFLAGS:
877 {
878 // get flags
879 struct ifreq request;
880 request.ifr_flags = interface->flags | interface->device->flags;
881
882 return user_memcpy(&((struct ifreq*)argument)->ifr_flags,
883 &request.ifr_flags, sizeof(request.ifr_flags));
884 }
885
886 case SIOCGIFSTATS:
887 {
888 // get stats
889 struct ifreq_stats stats = interface->DeviceInterface()->device->stats;
890
891 struct ifreq_stats deviceStats;
892 if (protocol->device_module->control(protocol->device, SIOCGIFSTATS,
893 &deviceStats, sizeof(struct ifreq_stats)) == B_OK) {
894 stats.receive.dropped += deviceStats.receive.dropped;
895 stats.receive.errors += deviceStats.receive.errors;
896 stats.send = deviceStats.send;
897 stats.collisions += deviceStats.collisions;
898 }
899
900 return user_memcpy(&((struct ifreq*)argument)->ifr_stats,
901 &stats, sizeof(struct ifreq_stats));
902 }
903
904 case SIOCGIFTYPE:
905 {
906 // get type
907 struct ifreq request;
908 request.ifr_type = interface->type;
909
910 return user_memcpy(&((struct ifreq*)argument)->ifr_type,
911 &request.ifr_type, sizeof(request.ifr_type));
912 }
913
914 case SIOCGIFMTU:
915 {
916 // get MTU
917 struct ifreq request;
918 request.ifr_mtu = interface->device->mtu;
919
920 return user_memcpy(&((struct ifreq*)argument)->ifr_mtu,
921 &request.ifr_mtu, sizeof(request.ifr_mtu));
922 }
923 case SIOCSIFMTU:
924 {
925 // set MTU
926 struct ifreq request;
927 if (user_memcpy(&request, argument, sizeof(struct ifreq)) != B_OK)
928 return B_BAD_ADDRESS;
929
930 status_t status = interface->device->module->set_mtu(
931 interface->device, request.ifr_mtu);
932 if (status == B_OK)
933 notify_interface_changed(interface);
934 return status;
935 }
936
937 case SIOCSIFMEDIA:
938 {
939 // set media
940 struct ifreq request;
941 if (user_memcpy(&request, argument, sizeof(struct ifreq)) != B_OK)
942 return B_BAD_ADDRESS;
943
944 status_t status
945 = interface->device->module->set_media(
946 interface->device, request.ifr_media);
947 if (status == B_NOT_SUPPORTED) {
948 // TODO: this isn't so nice, and should be solved differently
949 // (for example by removing the set_media() call altogether, or
950 // making it able to deal properly with FreeBSD drivers as well)
951 // try driver directly
952 status = interface->device->module->control(
953 interface->device, SIOCSIFMEDIA, &request, sizeof(request));
954 }
955
956 return status;
957 }
958 case SIOCGIFMEDIA:
959 {
960 // get media
961 const size_t copylen = offsetof(ifreq, ifr_media) + sizeof(ifreq::ifr_media);
962 if (length > 0 && length < copylen)
963 return B_BAD_VALUE;
964
965 struct ifreq request;
966 if (user_memcpy(&request, argument, copylen) != B_OK)
967 return B_BAD_ADDRESS;
968
969 request.ifr_media = interface->device->media;
970 return user_memcpy(argument, &request, copylen);
971 }
972
973 case SIOCGIFMETRIC:
974 {
975 // get metric
976 struct ifreq request;
977 request.ifr_metric = interface->metric;
978
979 return user_memcpy(&((struct ifreq*)argument)->ifr_metric,
980 &request.ifr_metric, sizeof(request.ifr_metric));
981 }
982 case SIOCSIFMETRIC:
983 {
984 // set metric
985 struct ifreq request;
986 if (user_memcpy(&request, argument, sizeof(struct ifreq)) < B_OK)
987 return B_BAD_ADDRESS;
988
989 interface->metric = request.ifr_metric;
990 notify_interface_changed(interface);
991 return B_OK;
992 }
993
994 case SIOCADDRT:
995 case SIOCDELRT:
996 // interface related route options
997 return control_routes(interface, protocol->domain, option, argument,
998 length);
999 }
1000
1001 return protocol->device_module->control(protocol->device,
1002 option, argument, length);
1003 }
1004
1005
1006 static status_t
interface_protocol_join_multicast(net_datalink_protocol * _protocol,const sockaddr * address)1007 interface_protocol_join_multicast(net_datalink_protocol* _protocol,
1008 const sockaddr* address)
1009 {
1010 interface_protocol* protocol = (interface_protocol*)_protocol;
1011
1012 return protocol->device_module->add_multicast(protocol->device, address);
1013 }
1014
1015
1016 static status_t
interface_protocol_leave_multicast(net_datalink_protocol * _protocol,const sockaddr * address)1017 interface_protocol_leave_multicast(net_datalink_protocol* _protocol,
1018 const sockaddr* address)
1019 {
1020 interface_protocol* protocol = (interface_protocol*)_protocol;
1021
1022 return protocol->device_module->remove_multicast(protocol->device,
1023 address);
1024 }
1025
1026
1027 net_datalink_module_info gNetDatalinkModule = {
1028 {
1029 NET_DATALINK_MODULE_NAME,
1030 0,
1031 datalink_std_ops
1032 },
1033
1034 datalink_control,
1035 datalink_send_routed_data,
1036 datalink_send_data,
1037
1038 datalink_is_local_address,
1039 datalink_is_local_link_address,
1040
1041 datalink_get_interface,
1042 datalink_get_interface_with_address,
1043 datalink_put_interface,
1044
1045 datalink_get_interface_address,
1046 datalink_get_next_interface_address,
1047 datalink_put_interface_address,
1048
1049 datalink_join_multicast,
1050 datalink_leave_multicast,
1051
1052 add_route,
1053 remove_route,
1054 get_route,
1055 get_buffer_route,
1056 put_route,
1057 register_route_info,
1058 unregister_route_info,
1059 update_route_info
1060 };
1061
1062 net_datalink_protocol_module_info gDatalinkInterfaceProtocolModule = {
1063 {
1064 NULL,
1065 0,
1066 NULL
1067 },
1068 interface_protocol_init,
1069 interface_protocol_uninit,
1070 interface_protocol_send_data,
1071 interface_protocol_up,
1072 interface_protocol_down,
1073 interface_protocol_change_address,
1074 interface_protocol_control,
1075 interface_protocol_join_multicast,
1076 interface_protocol_leave_multicast,
1077 };
1078