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