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 size_t spaceLeft = size; 327 328 sockaddr zeros; 329 memset(&zeros, 0, sizeof(sockaddr)); 330 zeros.sa_family = domain->family; 331 zeros.sa_len = sizeof(sockaddr); 332 333 while (iterator.HasNext()) { 334 net_route* route = iterator.Next(); 335 336 size = IF_NAMESIZE + sizeof(route_entry); 337 338 sockaddr* destination = NULL; 339 sockaddr* mask = NULL; 340 sockaddr* gateway = NULL; 341 uint8* next = (uint8*)buffer + size; 342 343 if (route->destination != NULL) { 344 destination = (sockaddr*)next; 345 next += route->destination->sa_len; 346 size += route->destination->sa_len; 347 } 348 if (route->mask != NULL) { 349 mask = (sockaddr*)next; 350 next += route->mask->sa_len; 351 size += route->mask->sa_len; 352 } 353 if (route->gateway != NULL) { 354 gateway = (sockaddr*)next; 355 next += route->gateway->sa_len; 356 size += route->gateway->sa_len; 357 } 358 359 if (spaceLeft < size) 360 return ENOBUFS; 361 362 ifreq request; 363 strlcpy(request.ifr_name, route->interface_address->interface->name, 364 IF_NAMESIZE); 365 request.ifr_route.destination = destination; 366 request.ifr_route.mask = mask; 367 request.ifr_route.gateway = gateway; 368 request.ifr_route.mtu = route->mtu; 369 request.ifr_route.flags = route->flags; 370 371 // copy data into userland buffer 372 if (user_memcpy(buffer, &request, size) < B_OK 373 || (route->destination != NULL 374 && user_memcpy(request.ifr_route.destination, 375 route->destination, route->destination->sa_len) < B_OK) 376 || (route->mask != NULL && user_memcpy(request.ifr_route.mask, 377 route->mask, route->mask->sa_len) < B_OK) 378 || (route->gateway != NULL && user_memcpy(request.ifr_route.gateway, 379 route->gateway, route->gateway->sa_len) < B_OK)) 380 return B_BAD_ADDRESS; 381 382 buffer = (void*)next; 383 spaceLeft -= size; 384 } 385 386 return B_OK; 387 } 388 389 390 status_t 391 control_routes(struct net_interface* _interface, net_domain* domain, 392 int32 option, void* argument, size_t length) 393 { 394 TRACE("control_routes(interface %p, domain %p, option %" B_PRId32 ")\n", 395 _interface, domain, option); 396 Interface* interface = (Interface*)_interface; 397 398 switch (option) { 399 case SIOCADDRT: 400 case SIOCDELRT: 401 { 402 // add or remove a route 403 if (length != sizeof(struct ifreq)) 404 return B_BAD_VALUE; 405 406 route_entry entry; 407 if (user_memcpy(&entry, &((ifreq*)argument)->ifr_route, 408 sizeof(route_entry)) != B_OK) 409 return B_BAD_ADDRESS; 410 411 net_route_private route; 412 status_t status; 413 if ((status = user_copy_address(entry.destination, 414 &route.destination)) != B_OK 415 || (status = user_copy_address(entry.mask, &route.mask)) != B_OK 416 || (status = user_copy_address(entry.gateway, &route.gateway)) 417 != B_OK) 418 return status; 419 420 InterfaceAddress* address 421 = interface->FirstForFamily(domain->family); 422 423 route.mtu = entry.mtu; 424 route.flags = entry.flags; 425 route.interface_address = address; 426 427 if (option == SIOCADDRT) 428 status = add_route(domain, &route); 429 else 430 status = remove_route(domain, &route); 431 432 if (address != NULL) 433 address->ReleaseReference(); 434 return status; 435 } 436 } 437 return B_BAD_VALUE; 438 } 439 440 441 status_t 442 add_route(struct net_domain* _domain, const struct net_route* newRoute) 443 { 444 struct net_domain_private* domain = (net_domain_private*)_domain; 445 446 TRACE("add route to domain %s: dest %s, mask %s, gw %s, flags %lx\n", 447 domain->name, 448 AddressString(domain, newRoute->destination 449 ? newRoute->destination : NULL).Data(), 450 AddressString(domain, newRoute->mask ? newRoute->mask : NULL).Data(), 451 AddressString(domain, newRoute->gateway 452 ? newRoute->gateway : NULL).Data(), 453 newRoute->flags); 454 455 if (domain == NULL || newRoute == NULL 456 || newRoute->interface_address == NULL 457 || ((newRoute->flags & RTF_HOST) != 0 && newRoute->mask != NULL) 458 || ((newRoute->flags & RTF_DEFAULT) == 0 459 && newRoute->destination == NULL) 460 || ((newRoute->flags & RTF_GATEWAY) != 0 && newRoute->gateway == NULL) 461 || !domain->address_module->check_mask(newRoute->mask)) 462 return B_BAD_VALUE; 463 464 RecursiveLocker _(domain->lock); 465 466 net_route_private* route = find_route(domain, newRoute); 467 if (route != NULL) 468 return B_FILE_EXISTS; 469 470 route = new (std::nothrow) net_route_private; 471 if (route == NULL) 472 return B_NO_MEMORY; 473 474 if (domain->address_module->copy_address(newRoute->destination, 475 &route->destination, (newRoute->flags & RTF_DEFAULT) != 0, 476 newRoute->mask) != B_OK 477 || domain->address_module->copy_address(newRoute->mask, &route->mask, 478 (newRoute->flags & RTF_DEFAULT) != 0, NULL) != B_OK 479 || domain->address_module->copy_address(newRoute->gateway, 480 &route->gateway, false, NULL) != B_OK) { 481 delete route; 482 return B_NO_MEMORY; 483 } 484 485 route->flags = newRoute->flags; 486 route->interface_address = newRoute->interface_address; 487 ((InterfaceAddress*)route->interface_address)->AcquireReference(); 488 route->mtu = 0; 489 route->ref_count = 1; 490 491 // Insert the route sorted by completeness of its mask 492 493 RouteList::Iterator iterator = domain->routes.GetIterator(); 494 net_route_private* before = NULL; 495 496 while ((before = iterator.Next()) != NULL) { 497 // if the before mask is less specific than the one of the route, 498 // we can insert it before that route. 499 if (domain->address_module->first_mask_bit(before->mask) 500 > domain->address_module->first_mask_bit(route->mask)) 501 break; 502 503 if ((route->flags & RTF_DEFAULT) != 0 504 && (before->flags & RTF_DEFAULT) != 0) { 505 // both routes are equal - let the link speed decide the 506 // order 507 if (before->interface_address->interface->device->link_speed 508 < route->interface_address->interface->device->link_speed) 509 break; 510 } 511 } 512 513 domain->routes.Insert(before, route); 514 update_route_infos(domain); 515 516 return B_OK; 517 } 518 519 520 status_t 521 remove_route(struct net_domain* _domain, const struct net_route* removeRoute) 522 { 523 struct net_domain_private* domain = (net_domain_private*)_domain; 524 525 TRACE("remove route from domain %s: dest %s, mask %s, gw %s, flags %lx\n", 526 domain->name, 527 AddressString(domain, removeRoute->destination 528 ? removeRoute->destination : NULL).Data(), 529 AddressString(domain, removeRoute->mask 530 ? removeRoute->mask : NULL).Data(), 531 AddressString(domain, removeRoute->gateway 532 ? removeRoute->gateway : NULL).Data(), 533 removeRoute->flags); 534 535 RecursiveLocker locker(domain->lock); 536 537 net_route_private* route = find_route(domain, removeRoute); 538 if (route == NULL) 539 return B_ENTRY_NOT_FOUND; 540 541 domain->routes.Remove(route); 542 543 put_route_internal(domain, route); 544 update_route_infos(domain); 545 546 return B_OK; 547 } 548 549 550 status_t 551 get_route_information(struct net_domain* _domain, void* value, size_t length) 552 { 553 struct net_domain_private* domain = (net_domain_private*)_domain; 554 555 if (length < sizeof(route_entry)) 556 return B_BAD_VALUE; 557 558 route_entry entry; 559 if (user_memcpy(&entry, value, sizeof(route_entry)) < B_OK) 560 return B_BAD_ADDRESS; 561 562 sockaddr_storage destination; 563 status_t status = user_copy_address(entry.destination, &destination); 564 if (status != B_OK) 565 return status; 566 567 RecursiveLocker locker(domain->lock); 568 569 net_route_private* route = find_route(domain, (sockaddr*)&destination); 570 if (route == NULL) 571 return B_ENTRY_NOT_FOUND; 572 573 status = fill_route_entry(&entry, value, length, route); 574 if (status != B_OK) 575 return status; 576 577 return user_memcpy(value, &entry, sizeof(route_entry)); 578 } 579 580 581 void 582 invalidate_routes(net_domain* _domain, net_interface* interface) 583 { 584 net_domain_private* domain = (net_domain_private*)_domain; 585 RecursiveLocker locker(domain->lock); 586 587 TRACE("invalidate_routes(%i, %s)\n", domain->family, interface->name); 588 589 RouteList::Iterator iterator = domain->routes.GetIterator(); 590 while (iterator.HasNext()) { 591 net_route* route = iterator.Next(); 592 593 if (route->interface_address->interface == interface) 594 remove_route(domain, route); 595 } 596 } 597 598 599 void 600 invalidate_routes(InterfaceAddress* address) 601 { 602 net_domain_private* domain = (net_domain_private*)address->domain; 603 604 TRACE("invalidate_routes(%s)\n", 605 AddressString(domain, address->local).Data()); 606 607 RecursiveLocker locker(domain->lock); 608 609 RouteList::Iterator iterator = domain->routes.GetIterator(); 610 while (iterator.HasNext()) { 611 net_route* route = iterator.Next(); 612 613 if (route->interface_address == address) 614 remove_route(domain, route); 615 } 616 } 617 618 619 struct net_route* 620 get_route(struct net_domain* _domain, const struct sockaddr* address) 621 { 622 struct net_domain_private* domain = (net_domain_private*)_domain; 623 RecursiveLocker locker(domain->lock); 624 625 return get_route_internal(domain, address); 626 } 627 628 629 status_t 630 get_device_route(struct net_domain* domain, uint32 index, net_route** _route) 631 { 632 Interface* interface = get_interface_for_device(domain, index); 633 if (interface == NULL) 634 return ENETUNREACH; 635 636 net_route_private* route 637 = &interface->DomainDatalink(domain->family)->direct_route; 638 639 atomic_add(&route->ref_count, 1); 640 *_route = route; 641 642 interface->ReleaseReference(); 643 return B_OK; 644 } 645 646 647 status_t 648 get_buffer_route(net_domain* _domain, net_buffer* buffer, net_route** _route) 649 { 650 net_domain_private* domain = (net_domain_private*)_domain; 651 652 RecursiveLocker _(domain->lock); 653 654 net_route* route = get_route_internal(domain, buffer->destination); 655 if (route == NULL) 656 return ENETUNREACH; 657 658 status_t status = B_OK; 659 sockaddr* source = buffer->source; 660 661 // TODO: we are quite relaxed in the address checking here 662 // as we might proceed with source = INADDR_ANY. 663 664 if (route->interface_address != NULL 665 && route->interface_address->local != NULL) { 666 status = domain->address_module->update_to(source, 667 route->interface_address->local); 668 } 669 670 if (status != B_OK) 671 put_route_internal(domain, route); 672 else 673 *_route = route; 674 675 return status; 676 } 677 678 679 void 680 put_route(struct net_domain* _domain, net_route* route) 681 { 682 struct net_domain_private* domain = (net_domain_private*)_domain; 683 if (domain == NULL || route == NULL) 684 return; 685 686 RecursiveLocker locker(domain->lock); 687 688 put_route_internal(domain, (net_route*)route); 689 } 690 691 692 status_t 693 register_route_info(struct net_domain* _domain, struct net_route_info* info) 694 { 695 struct net_domain_private* domain = (net_domain_private*)_domain; 696 RecursiveLocker locker(domain->lock); 697 698 domain->route_infos.Add(info); 699 info->route = get_route_internal(domain, &info->address); 700 701 return B_OK; 702 } 703 704 705 status_t 706 unregister_route_info(struct net_domain* _domain, struct net_route_info* info) 707 { 708 struct net_domain_private* domain = (net_domain_private*)_domain; 709 RecursiveLocker locker(domain->lock); 710 711 domain->route_infos.Remove(info); 712 if (info->route != NULL) 713 put_route_internal(domain, info->route); 714 715 return B_OK; 716 } 717 718 719 status_t 720 update_route_info(struct net_domain* _domain, struct net_route_info* info) 721 { 722 struct net_domain_private* domain = (net_domain_private*)_domain; 723 RecursiveLocker locker(domain->lock); 724 725 put_route_internal(domain, info->route); 726 info->route = get_route_internal(domain, &info->address); 727 return B_OK; 728 } 729 730