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