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 */ 8 9 10 #include "domains.h" 11 #include "interfaces.h" 12 #include "routes.h" 13 #include "stack_private.h" 14 #include "utility.h" 15 16 #include <net_device.h> 17 #include <NetUtilities.h> 18 19 #include <lock.h> 20 #include <util/AutoLock.h> 21 22 #include <KernelExport.h> 23 24 #include <net/if_dl.h> 25 #include <net/route.h> 26 #include <new> 27 #include <stdlib.h> 28 #include <string.h> 29 #include <sys/sockio.h> 30 31 32 //#define TRACE_ROUTES 33 #ifdef TRACE_ROUTES 34 # define TRACE(x...) dprintf(STACK_DEBUG_PREFIX x) 35 #else 36 # define TRACE(x...) ; 37 #endif 38 39 40 net_route_private::net_route_private() 41 { 42 destination = mask = gateway = NULL; 43 } 44 45 46 net_route_private::~net_route_private() 47 { 48 free(destination); 49 free(mask); 50 free(gateway); 51 } 52 53 54 // #pragma mark - private functions 55 56 57 static status_t 58 user_copy_address(const sockaddr* from, sockaddr** to) 59 { 60 if (from == NULL) { 61 *to = NULL; 62 return B_OK; 63 } 64 65 sockaddr address; 66 if (user_memcpy(&address, from, sizeof(struct sockaddr)) < B_OK) 67 return B_BAD_ADDRESS; 68 69 *to = (sockaddr*)malloc(address.sa_len); 70 if (*to == NULL) 71 return B_NO_MEMORY; 72 73 if (address.sa_len > sizeof(struct sockaddr)) { 74 if (user_memcpy(*to, from, address.sa_len) < B_OK) 75 return B_BAD_ADDRESS; 76 } else 77 memcpy(*to, &address, address.sa_len); 78 79 return B_OK; 80 } 81 82 83 static status_t 84 user_copy_address(const sockaddr* from, sockaddr_storage* to) 85 { 86 if (from == NULL) 87 return B_BAD_ADDRESS; 88 89 if (user_memcpy(to, from, sizeof(sockaddr)) < B_OK) 90 return B_BAD_ADDRESS; 91 92 if (to->ss_len > sizeof(sockaddr)) { 93 if (to->ss_len > sizeof(sockaddr_storage)) 94 return B_BAD_VALUE; 95 if (user_memcpy(to, from, to->ss_len) < B_OK) 96 return B_BAD_ADDRESS; 97 } 98 99 return B_OK; 100 } 101 102 103 static net_route_private* 104 find_route(struct net_domain* _domain, const net_route* description) 105 { 106 struct net_domain_private* domain = (net_domain_private*)_domain; 107 RouteList::Iterator iterator = domain->routes.GetIterator(); 108 109 while (iterator.HasNext()) { 110 net_route_private* route = iterator.Next(); 111 112 if ((route->flags & RTF_DEFAULT) != 0 113 && (description->flags & RTF_DEFAULT) != 0) { 114 // there can only be one default route per interface address family 115 // TODO: check this better 116 if (route->interface_address == description->interface_address) 117 return route; 118 119 continue; 120 } 121 122 if ((route->flags & (RTF_GATEWAY | RTF_HOST | RTF_LOCAL | RTF_DEFAULT)) 123 == (description->flags 124 & (RTF_GATEWAY | RTF_HOST | RTF_LOCAL | RTF_DEFAULT)) 125 && domain->address_module->equal_masked_addresses( 126 route->destination, description->destination, description->mask) 127 && domain->address_module->equal_addresses(route->mask, 128 description->mask) 129 && domain->address_module->equal_addresses(route->gateway, 130 description->gateway) 131 && (description->interface_address == NULL 132 || description->interface_address == route->interface_address)) 133 return route; 134 } 135 136 return NULL; 137 } 138 139 140 static net_route_private* 141 find_route(net_domain* _domain, const sockaddr* address) 142 { 143 net_domain_private* domain = (net_domain_private*)_domain; 144 145 // find last matching route 146 147 RouteList::Iterator iterator = domain->routes.GetIterator(); 148 net_route_private* candidate = NULL; 149 150 TRACE("test address %s for routes...\n", 151 AddressString(domain, address).Data()); 152 153 // TODO: alternate equal default routes 154 155 while (iterator.HasNext()) { 156 net_route_private* route = iterator.Next(); 157 158 if (route->mask) { 159 sockaddr maskedAddress; 160 domain->address_module->mask_address(address, route->mask, 161 &maskedAddress); 162 if (!domain->address_module->equal_addresses(&maskedAddress, 163 route->destination)) 164 continue; 165 } else if (!domain->address_module->equal_addresses(address, 166 route->destination)) 167 continue; 168 169 // neglect routes that point to devices that have no link 170 if ((route->interface_address->interface->device->flags & IFF_LINK) 171 == 0) { 172 if (candidate == NULL) { 173 TRACE(" found candidate: %s, flags %lx\n", AddressString( 174 domain, route->destination).Data(), route->flags); 175 candidate = route; 176 } 177 continue; 178 } 179 180 TRACE(" found route: %s, flags %lx\n", 181 AddressString(domain, route->destination).Data(), route->flags); 182 183 return route; 184 } 185 186 return candidate; 187 } 188 189 190 static void 191 put_route_internal(struct net_domain_private* domain, net_route* _route) 192 { 193 ASSERT_LOCKED_RECURSIVE(&domain->lock); 194 195 net_route_private* route = (net_route_private*)_route; 196 if (route == NULL || atomic_add(&route->ref_count, -1) != 1) 197 return; 198 199 // delete route - it must already have been removed at this point 200 if (route->interface_address != NULL) 201 ((InterfaceAddress*)route->interface_address)->ReleaseReference(); 202 203 delete route; 204 } 205 206 207 static struct net_route* 208 get_route_internal(struct net_domain_private* domain, 209 const struct sockaddr* address) 210 { 211 ASSERT_LOCKED_RECURSIVE(&domain->lock); 212 net_route_private* route = NULL; 213 214 if (address->sa_family == AF_LINK) { 215 // special address to find an interface directly 216 RouteList::Iterator iterator = domain->routes.GetIterator(); 217 const sockaddr_dl* link = (const sockaddr_dl*)address; 218 219 while (iterator.HasNext()) { 220 route = iterator.Next(); 221 222 net_device* device = route->interface_address->interface->device; 223 224 if ((link->sdl_nlen > 0 225 && !strncmp(device->name, (const char*)link->sdl_data, 226 IF_NAMESIZE)) 227 || (link->sdl_nlen == 0 && link->sdl_alen > 0 228 && !memcmp(LLADDR(link), device->address.data, 229 device->address.length))) 230 break; 231 } 232 } else 233 route = find_route(domain, address); 234 235 if (route != NULL && atomic_add(&route->ref_count, 1) == 0) { 236 // route has been deleted already 237 route = NULL; 238 } 239 240 return route; 241 } 242 243 244 static void 245 update_route_infos(struct net_domain_private* domain) 246 { 247 ASSERT_LOCKED_RECURSIVE(&domain->lock); 248 RouteInfoList::Iterator iterator = domain->route_infos.GetIterator(); 249 250 while (iterator.HasNext()) { 251 net_route_info* info = iterator.Next(); 252 253 put_route_internal(domain, info->route); 254 info->route = get_route_internal(domain, &info->address); 255 } 256 } 257 258 259 static sockaddr* 260 copy_address(UserBuffer& buffer, sockaddr* address) 261 { 262 if (address == NULL) 263 return NULL; 264 265 return (sockaddr*)buffer.Push(address, address->sa_len); 266 } 267 268 269 static status_t 270 fill_route_entry(route_entry* target, void* _buffer, size_t bufferSize, 271 net_route* route) 272 { 273 UserBuffer buffer(((uint8*)_buffer) + sizeof(route_entry), 274 bufferSize - sizeof(route_entry)); 275 276 target->destination = copy_address(buffer, route->destination); 277 target->mask = copy_address(buffer, route->mask); 278 target->gateway = copy_address(buffer, route->gateway); 279 target->source = copy_address(buffer, route->interface_address->local); 280 target->flags = route->flags; 281 target->mtu = route->mtu; 282 283 return buffer.Status(); 284 } 285 286 287 // #pragma mark - exported functions 288 289 290 /*! Determines the size of a buffer large enough to contain the whole 291 routing table. 292 */ 293 uint32 294 route_table_size(net_domain_private* domain) 295 { 296 RecursiveLocker locker(domain->lock); 297 uint32 size = 0; 298 299 RouteList::Iterator iterator = domain->routes.GetIterator(); 300 while (iterator.HasNext()) { 301 net_route_private* route = iterator.Next(); 302 size += IF_NAMESIZE + sizeof(route_entry); 303 304 if (route->destination) 305 size += route->destination->sa_len; 306 if (route->mask) 307 size += route->mask->sa_len; 308 if (route->gateway) 309 size += route->gateway->sa_len; 310 } 311 312 return size; 313 } 314 315 316 /*! Dumps a list of all routes into the supplied userland buffer. 317 If the routes don't fit into the buffer, an error (\c ENOBUFS) is 318 returned. 319 */ 320 status_t 321 list_routes(net_domain_private* domain, void* buffer, size_t size) 322 { 323 RecursiveLocker _(domain->lock); 324 325 RouteList::Iterator iterator = domain->routes.GetIterator(); 326 const size_t kBaseSize = IF_NAMESIZE + sizeof(route_entry); 327 size_t spaceLeft = size; 328 329 sockaddr zeros; 330 memset(&zeros, 0, sizeof(sockaddr)); 331 zeros.sa_family = domain->family; 332 zeros.sa_len = sizeof(sockaddr); 333 334 while (iterator.HasNext()) { 335 net_route* route = iterator.Next(); 336 337 size = kBaseSize; 338 339 sockaddr* destination = NULL; 340 sockaddr* mask = NULL; 341 sockaddr* gateway = NULL; 342 uint8* next = (uint8*)buffer + size; 343 344 if (route->destination != NULL) { 345 destination = (sockaddr*)next; 346 next += route->destination->sa_len; 347 size += route->destination->sa_len; 348 } 349 if (route->mask != NULL) { 350 mask = (sockaddr*)next; 351 next += route->mask->sa_len; 352 size += route->mask->sa_len; 353 } 354 if (route->gateway != NULL) { 355 gateway = (sockaddr*)next; 356 next += route->gateway->sa_len; 357 size += route->gateway->sa_len; 358 } 359 360 if (spaceLeft < size) 361 return ENOBUFS; 362 363 ifreq request; 364 memset(&request, 0, sizeof(request)); 365 366 strlcpy(request.ifr_name, route->interface_address->interface->name, 367 IF_NAMESIZE); 368 request.ifr_route.destination = destination; 369 request.ifr_route.mask = mask; 370 request.ifr_route.gateway = gateway; 371 request.ifr_route.mtu = route->mtu; 372 request.ifr_route.flags = route->flags; 373 374 // copy data into userland buffer 375 if (user_memcpy(buffer, &request, kBaseSize) < B_OK 376 || (route->destination != NULL 377 && user_memcpy(request.ifr_route.destination, 378 route->destination, route->destination->sa_len) < B_OK) 379 || (route->mask != NULL && user_memcpy(request.ifr_route.mask, 380 route->mask, route->mask->sa_len) < B_OK) 381 || (route->gateway != NULL && user_memcpy(request.ifr_route.gateway, 382 route->gateway, route->gateway->sa_len) < B_OK)) 383 return B_BAD_ADDRESS; 384 385 buffer = (void*)next; 386 spaceLeft -= size; 387 } 388 389 return B_OK; 390 } 391 392 393 status_t 394 control_routes(struct net_interface* _interface, net_domain* domain, 395 int32 option, void* argument, size_t length) 396 { 397 TRACE("control_routes(interface %p, domain %p, option %" B_PRId32 ")\n", 398 _interface, domain, option); 399 Interface* interface = (Interface*)_interface; 400 401 switch (option) { 402 case SIOCADDRT: 403 case SIOCDELRT: 404 { 405 // add or remove a route 406 if (length != sizeof(struct ifreq)) 407 return B_BAD_VALUE; 408 409 route_entry entry; 410 if (user_memcpy(&entry, &((ifreq*)argument)->ifr_route, 411 sizeof(route_entry)) != B_OK) 412 return B_BAD_ADDRESS; 413 414 net_route_private route; 415 status_t status; 416 if ((status = user_copy_address(entry.destination, 417 &route.destination)) != B_OK 418 || (status = user_copy_address(entry.mask, &route.mask)) != B_OK 419 || (status = user_copy_address(entry.gateway, &route.gateway)) 420 != B_OK) 421 return status; 422 423 InterfaceAddress* address 424 = interface->FirstForFamily(domain->family); 425 426 route.mtu = entry.mtu; 427 route.flags = entry.flags; 428 route.interface_address = address; 429 430 if (option == SIOCADDRT) 431 status = add_route(domain, &route); 432 else 433 status = remove_route(domain, &route); 434 435 if (address != NULL) 436 address->ReleaseReference(); 437 return status; 438 } 439 } 440 return B_BAD_VALUE; 441 } 442 443 444 status_t 445 add_route(struct net_domain* _domain, const struct net_route* newRoute) 446 { 447 struct net_domain_private* domain = (net_domain_private*)_domain; 448 449 TRACE("add route to domain %s: dest %s, mask %s, gw %s, flags %lx\n", 450 domain->name, 451 AddressString(domain, newRoute->destination 452 ? newRoute->destination : NULL).Data(), 453 AddressString(domain, newRoute->mask ? newRoute->mask : NULL).Data(), 454 AddressString(domain, newRoute->gateway 455 ? newRoute->gateway : NULL).Data(), 456 newRoute->flags); 457 458 if (domain == NULL || newRoute == NULL 459 || newRoute->interface_address == NULL 460 || ((newRoute->flags & RTF_HOST) != 0 && newRoute->mask != NULL) 461 || ((newRoute->flags & RTF_DEFAULT) == 0 462 && newRoute->destination == NULL) 463 || ((newRoute->flags & RTF_GATEWAY) != 0 && newRoute->gateway == NULL) 464 || !domain->address_module->check_mask(newRoute->mask)) 465 return B_BAD_VALUE; 466 467 RecursiveLocker _(domain->lock); 468 469 net_route_private* route = find_route(domain, newRoute); 470 if (route != NULL) 471 return B_FILE_EXISTS; 472 473 route = new (std::nothrow) net_route_private; 474 if (route == NULL) 475 return B_NO_MEMORY; 476 477 if (domain->address_module->copy_address(newRoute->destination, 478 &route->destination, (newRoute->flags & RTF_DEFAULT) != 0, 479 newRoute->mask) != B_OK 480 || domain->address_module->copy_address(newRoute->mask, &route->mask, 481 (newRoute->flags & RTF_DEFAULT) != 0, NULL) != B_OK 482 || domain->address_module->copy_address(newRoute->gateway, 483 &route->gateway, false, NULL) != B_OK) { 484 delete route; 485 return B_NO_MEMORY; 486 } 487 488 route->flags = newRoute->flags; 489 route->interface_address = newRoute->interface_address; 490 ((InterfaceAddress*)route->interface_address)->AcquireReference(); 491 route->mtu = 0; 492 route->ref_count = 1; 493 494 // Insert the route sorted by completeness of its mask 495 496 RouteList::Iterator iterator = domain->routes.GetIterator(); 497 net_route_private* before = NULL; 498 499 while ((before = iterator.Next()) != NULL) { 500 // if the before mask is less specific than the one of the route, 501 // we can insert it before that route. 502 if (domain->address_module->first_mask_bit(before->mask) 503 > domain->address_module->first_mask_bit(route->mask)) 504 break; 505 506 if ((route->flags & RTF_DEFAULT) != 0 507 && (before->flags & RTF_DEFAULT) != 0) { 508 // both routes are equal - let the link speed decide the 509 // order 510 if (before->interface_address->interface->device->link_speed 511 < route->interface_address->interface->device->link_speed) 512 break; 513 } 514 } 515 516 domain->routes.Insert(before, route); 517 update_route_infos(domain); 518 519 return B_OK; 520 } 521 522 523 status_t 524 remove_route(struct net_domain* _domain, const struct net_route* removeRoute) 525 { 526 struct net_domain_private* domain = (net_domain_private*)_domain; 527 528 TRACE("remove route from domain %s: dest %s, mask %s, gw %s, flags %lx\n", 529 domain->name, 530 AddressString(domain, removeRoute->destination 531 ? removeRoute->destination : NULL).Data(), 532 AddressString(domain, removeRoute->mask 533 ? removeRoute->mask : NULL).Data(), 534 AddressString(domain, removeRoute->gateway 535 ? removeRoute->gateway : NULL).Data(), 536 removeRoute->flags); 537 538 RecursiveLocker locker(domain->lock); 539 540 net_route_private* route = find_route(domain, removeRoute); 541 if (route == NULL) 542 return B_ENTRY_NOT_FOUND; 543 544 domain->routes.Remove(route); 545 546 put_route_internal(domain, route); 547 update_route_infos(domain); 548 549 return B_OK; 550 } 551 552 553 status_t 554 get_route_information(struct net_domain* _domain, void* value, size_t length) 555 { 556 struct net_domain_private* domain = (net_domain_private*)_domain; 557 558 if (length < sizeof(route_entry)) 559 return B_BAD_VALUE; 560 561 route_entry entry; 562 if (user_memcpy(&entry, value, sizeof(route_entry)) < B_OK) 563 return B_BAD_ADDRESS; 564 565 sockaddr_storage destination; 566 status_t status = user_copy_address(entry.destination, &destination); 567 if (status != B_OK) 568 return status; 569 570 RecursiveLocker locker(domain->lock); 571 572 net_route_private* route = find_route(domain, (sockaddr*)&destination); 573 if (route == NULL) 574 return B_ENTRY_NOT_FOUND; 575 576 status = fill_route_entry(&entry, value, length, route); 577 if (status != B_OK) 578 return status; 579 580 return user_memcpy(value, &entry, sizeof(route_entry)); 581 } 582 583 584 void 585 invalidate_routes(net_domain* _domain, net_interface* interface) 586 { 587 net_domain_private* domain = (net_domain_private*)_domain; 588 RecursiveLocker locker(domain->lock); 589 590 TRACE("invalidate_routes(%i, %s)\n", domain->family, interface->name); 591 592 RouteList::Iterator iterator = domain->routes.GetIterator(); 593 while (iterator.HasNext()) { 594 net_route* route = iterator.Next(); 595 596 if (route->interface_address->interface == interface) 597 remove_route(domain, route); 598 } 599 } 600 601 602 void 603 invalidate_routes(InterfaceAddress* address) 604 { 605 net_domain_private* domain = (net_domain_private*)address->domain; 606 607 TRACE("invalidate_routes(%s)\n", 608 AddressString(domain, address->local).Data()); 609 610 RecursiveLocker locker(domain->lock); 611 612 RouteList::Iterator iterator = domain->routes.GetIterator(); 613 while (iterator.HasNext()) { 614 net_route* route = iterator.Next(); 615 616 if (route->interface_address == address) 617 remove_route(domain, route); 618 } 619 } 620 621 622 struct net_route* 623 get_route(struct net_domain* _domain, const struct sockaddr* address) 624 { 625 struct net_domain_private* domain = (net_domain_private*)_domain; 626 RecursiveLocker locker(domain->lock); 627 628 return get_route_internal(domain, address); 629 } 630 631 632 status_t 633 get_device_route(struct net_domain* domain, uint32 index, net_route** _route) 634 { 635 Interface* interface = get_interface_for_device(domain, index); 636 if (interface == NULL) 637 return ENETUNREACH; 638 639 net_route_private* route 640 = &interface->DomainDatalink(domain->family)->direct_route; 641 642 atomic_add(&route->ref_count, 1); 643 *_route = route; 644 645 interface->ReleaseReference(); 646 return B_OK; 647 } 648 649 650 status_t 651 get_buffer_route(net_domain* _domain, net_buffer* buffer, net_route** _route) 652 { 653 net_domain_private* domain = (net_domain_private*)_domain; 654 655 RecursiveLocker _(domain->lock); 656 657 net_route* route = get_route_internal(domain, buffer->destination); 658 if (route == NULL) 659 return ENETUNREACH; 660 661 status_t status = B_OK; 662 sockaddr* source = buffer->source; 663 664 // TODO: we are quite relaxed in the address checking here 665 // as we might proceed with source = INADDR_ANY. 666 667 if (route->interface_address != NULL 668 && route->interface_address->local != NULL) { 669 status = domain->address_module->update_to(source, 670 route->interface_address->local); 671 } 672 673 if (status != B_OK) 674 put_route_internal(domain, route); 675 else 676 *_route = route; 677 678 return status; 679 } 680 681 682 void 683 put_route(struct net_domain* _domain, net_route* route) 684 { 685 struct net_domain_private* domain = (net_domain_private*)_domain; 686 if (domain == NULL || route == NULL) 687 return; 688 689 RecursiveLocker locker(domain->lock); 690 691 put_route_internal(domain, (net_route*)route); 692 } 693 694 695 status_t 696 register_route_info(struct net_domain* _domain, struct net_route_info* info) 697 { 698 struct net_domain_private* domain = (net_domain_private*)_domain; 699 RecursiveLocker locker(domain->lock); 700 701 domain->route_infos.Add(info); 702 info->route = get_route_internal(domain, &info->address); 703 704 return B_OK; 705 } 706 707 708 status_t 709 unregister_route_info(struct net_domain* _domain, struct net_route_info* info) 710 { 711 struct net_domain_private* domain = (net_domain_private*)_domain; 712 RecursiveLocker locker(domain->lock); 713 714 domain->route_infos.Remove(info); 715 if (info->route != NULL) 716 put_route_internal(domain, info->route); 717 718 return B_OK; 719 } 720 721 722 status_t 723 update_route_info(struct net_domain* _domain, struct net_route_info* info) 724 { 725 struct net_domain_private* domain = (net_domain_private*)_domain; 726 RecursiveLocker locker(domain->lock); 727 728 put_route_internal(domain, info->route); 729 info->route = get_route_internal(domain, &info->address); 730 return B_OK; 731 } 732 733