1 2/* 3 * Interface functions. 4 * Copyright (C) 1997, 98 Kunihiro Ishiguro 5 * 6 * This file is part of GNU Zebra. 7 * 8 * GNU Zebra is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published 10 * by the Free Software Foundation; either version 2, or (at your 11 * option) any later version. 12 * 13 * GNU Zebra is distributed in the hope that it will be useful, but 14 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with GNU Zebra; see the file COPYING. If not, write to the 20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 21 * Boston, MA 02111-1307, USA. 22 */ 23 24#include <zebra.h> 25 26#include "linklist.h" 27#include "vector.h" 28#include "vty.h" 29#include "command.h" 30#include "if.h" 31#include "sockunion.h" 32#include "prefix.h" 33#include "memory.h" 34#include "table.h" 35#include "buffer.h" 36#include "str.h" 37#include "log.h" 38 39/* Master list of interfaces. */ 40struct list *iflist; 41 42/* One for each program. This structure is needed to store hooks. */ 43struct if_master 44{ 45 int (*if_new_hook) (struct interface *); 46 int (*if_delete_hook) (struct interface *); 47} if_master; 48 49/* Compare interface names, returning an integer greater than, equal to, or 50 * less than 0, (following the strcmp convention), according to the 51 * relationship between ifp1 and ifp2. Interface names consist of an 52 * alphabetic prefix and a numeric suffix. The primary sort key is 53 * lexicographic by name, and then numeric by number. No number sorts 54 * before all numbers. Examples: de0 < de1, de100 < fxp0 < xl0, devpty < 55 * devpty0, de0 < del0 56 */ 57int 58if_cmp_func (struct interface *ifp1, struct interface *ifp2) 59{ 60 unsigned int l1, l2; 61 long int x1, x2; 62 char *p1, *p2; 63 int res; 64 65 p1 = ifp1->name; 66 p2 = ifp2->name; 67 68 while (*p1 && *p2) { 69 /* look up to any number */ 70 l1 = strcspn(p1, "0123456789"); 71 l2 = strcspn(p2, "0123456789"); 72 73 /* name lengths are different -> compare names */ 74 if (l1 != l2) 75 return (strcmp(p1, p2)); 76 77 /* Note that this relies on all numbers being less than all letters, so 78 * that de0 < del0. 79 */ 80 res = strncmp(p1, p2, l1); 81 82 /* names are different -> compare them */ 83 if (res) 84 return res; 85 86 /* with identical name part, go to numeric part */ 87 p1 += l1; 88 p2 += l1; 89 90 if (!*p1) 91 return -1; 92 if (!*p2) 93 return 1; 94 95 x1 = strtol(p1, &p1, 10); 96 x2 = strtol(p2, &p2, 10); 97 98 /* let's compare numbers now */ 99 if (x1 < x2) 100 return -1; 101 if (x1 > x2) 102 return 1; 103 104 /* numbers were equal, lets do it again.. 105 (it happens with name like "eth123.456:789") */ 106 } 107 if (*p1) 108 return 1; 109 if (*p2) 110 return -1; 111 return 0; 112} 113 114/* Create new interface structure. */ 115struct interface * 116if_create (const char *name, int namelen) 117{ 118 struct interface *ifp; 119 120 ifp = XCALLOC (MTYPE_IF, sizeof (struct interface)); 121 ifp->ifindex = IFINDEX_INTERNAL; 122 123 assert (name); 124 assert (namelen <= INTERFACE_NAMSIZ); /* Need space for '\0' at end. */ 125 strncpy (ifp->name, name, namelen); 126 ifp->name[namelen] = '\0'; 127 if (if_lookup_by_name(ifp->name) == NULL) 128 listnode_add_sort (iflist, ifp); 129 else 130 zlog_err("if_create(%s): corruption detected -- interface with this " 131 "name exists already!", ifp->name); 132 ifp->connected = list_new (); 133 ifp->connected->del = (void (*) (void *)) connected_free; 134 135 if (if_master.if_new_hook) 136 (*if_master.if_new_hook) (ifp); 137 138 return ifp; 139} 140 141/* Delete interface structure. */ 142void 143if_delete_retain (struct interface *ifp) 144{ 145 if (if_master.if_delete_hook) 146 (*if_master.if_delete_hook) (ifp); 147 148 /* Free connected address list */ 149 list_delete_all_node (ifp->connected); 150} 151 152/* Delete and free interface structure. */ 153void 154if_delete (struct interface *ifp) 155{ 156 listnode_delete (iflist, ifp); 157 158 if_delete_retain(ifp); 159 160 list_free (ifp->connected); 161 162 XFREE (MTYPE_IF, ifp); 163} 164 165/* Add hook to interface master. */ 166void 167if_add_hook (int type, int (*func)(struct interface *ifp)) 168{ 169 switch (type) { 170 case IF_NEW_HOOK: 171 if_master.if_new_hook = func; 172 break; 173 case IF_DELETE_HOOK: 174 if_master.if_delete_hook = func; 175 break; 176 default: 177 break; 178 } 179} 180 181/* Interface existance check by index. */ 182struct interface * 183if_lookup_by_index (unsigned int index) 184{ 185 struct listnode *node; 186 struct interface *ifp; 187 188 for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp)) 189 { 190 if (ifp->ifindex == index) 191 return ifp; 192 } 193 return NULL; 194} 195 196const char * 197ifindex2ifname (unsigned int index) 198{ 199 struct interface *ifp; 200 201 return ((ifp = if_lookup_by_index(index)) != NULL) ? 202 ifp->name : "unknown"; 203} 204 205unsigned int 206ifname2ifindex (const char *name) 207{ 208 struct interface *ifp; 209 210 return ((ifp = if_lookup_by_name(name)) != NULL) ? ifp->ifindex 211 : IFINDEX_INTERNAL; 212} 213 214/* Interface existance check by interface name. */ 215struct interface * 216if_lookup_by_name (const char *name) 217{ 218 struct listnode *node; 219 struct interface *ifp; 220 221 if (name) 222 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) 223 { 224 if (strcmp(name, ifp->name) == 0) 225 return ifp; 226 } 227 return NULL; 228} 229 230struct interface * 231if_lookup_by_name_len(const char *name, size_t namelen) 232{ 233 struct listnode *node; 234 struct interface *ifp; 235 236 if (namelen > INTERFACE_NAMSIZ) 237 return NULL; 238 239 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) 240 { 241 if (!memcmp(name, ifp->name, namelen) && (ifp->name[namelen] == '\0')) 242 return ifp; 243 } 244 return NULL; 245} 246 247/* Lookup interface by IPv4 address. */ 248struct interface * 249if_lookup_exact_address (struct in_addr src) 250{ 251 struct listnode *node; 252 struct listnode *cnode; 253 struct interface *ifp; 254 struct prefix *p; 255 struct connected *c; 256 257 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) 258 { 259 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c)) 260 { 261 p = c->address; 262 263 if (p && p->family == AF_INET) 264 { 265 if (IPV4_ADDR_SAME (&p->u.prefix4, &src)) 266 return ifp; 267 } 268 } 269 } 270 return NULL; 271} 272 273/* Lookup interface by IPv4 address. */ 274struct interface * 275if_lookup_address (struct in_addr src) 276{ 277 struct listnode *node; 278 struct prefix addr; 279 int bestlen = 0; 280 struct listnode *cnode; 281 struct interface *ifp; 282 struct connected *c; 283 struct interface *match; 284 285 addr.family = AF_INET; 286 addr.u.prefix4 = src; 287 addr.prefixlen = IPV4_MAX_BITLEN; 288 289 match = NULL; 290 291 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) 292 { 293 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c)) 294 { 295 if (c->address && (c->address->family == AF_INET) && 296 prefix_match(CONNECTED_PREFIX(c), &addr) && 297 (c->address->prefixlen > bestlen)) 298 { 299 bestlen = c->address->prefixlen; 300 match = ifp; 301 } 302 } 303 } 304 return match; 305} 306 307/* Lookup interface by prefix */ 308struct interface * 309if_lookup_prefix (struct prefix *prefix) 310{ 311 struct listnode *node; 312 struct listnode *cnode; 313 struct interface *ifp; 314 struct connected *c; 315 316 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) 317 { 318 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c)) 319 { 320 if (prefix_cmp(c->address, prefix) == 0) 321 { 322 return ifp; 323 } 324 } 325 } 326 return NULL; 327} 328 329/* Get interface by name if given name interface doesn't exist create 330 one. */ 331struct interface * 332if_get_by_name (const char *name) 333{ 334 struct interface *ifp; 335 336 return ((ifp = if_lookup_by_name(name)) != NULL) ? ifp : 337 if_create(name, strlen(name)); 338} 339 340struct interface * 341if_get_by_name_len(const char *name, size_t namelen) 342{ 343 struct interface *ifp; 344 345 return ((ifp = if_lookup_by_name_len(name, namelen)) != NULL) ? ifp : 346 if_create(name, namelen); 347} 348 349/* Does interface up ? */ 350int 351if_is_up (struct interface *ifp) 352{ 353 return ifp->flags & IFF_UP; 354} 355 356/* Is interface running? */ 357int 358if_is_running (struct interface *ifp) 359{ 360 return ifp->flags & IFF_RUNNING; 361} 362 363/* Is the interface operative, eg. either UP & RUNNING 364 or UP & !ZEBRA_INTERFACE_LINK_DETECTION */ 365int 366if_is_operative (struct interface *ifp) 367{ 368 return ((ifp->flags & IFF_UP) && 369 (ifp->flags & IFF_RUNNING || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION))); 370} 371 372/* Is this loopback interface ? */ 373int 374if_is_loopback (struct interface *ifp) 375{ 376 /* XXX: Do this better, eg what if IFF_WHATEVER means X on platform M 377 * but Y on platform N? 378 */ 379 return (ifp->flags & (IFF_LOOPBACK|IFF_NOXMIT|IFF_VIRTUAL)); 380} 381 382/* Does this interface support broadcast ? */ 383int 384if_is_broadcast (struct interface *ifp) 385{ 386 return ifp->flags & IFF_BROADCAST; 387} 388 389/* Does this interface support broadcast ? */ 390int 391if_is_pointopoint (struct interface *ifp) 392{ 393 return ifp->flags & IFF_POINTOPOINT; 394} 395 396/* Does this interface support multicast ? */ 397int 398if_is_multicast (struct interface *ifp) 399{ 400 return ifp->flags & IFF_MULTICAST; 401} 402 403/* Printout flag information into log */ 404const char * 405if_flag_dump (unsigned long flag) 406{ 407 int separator = 0; 408 static char logbuf[BUFSIZ]; 409 410#define IFF_OUT_LOG(X,STR) \ 411 if (flag & (X)) \ 412 { \ 413 if (separator) \ 414 strlcat (logbuf, ",", BUFSIZ); \ 415 else \ 416 separator = 1; \ 417 strlcat (logbuf, STR, BUFSIZ); \ 418 } 419 420 strlcpy (logbuf, "<", BUFSIZ); 421 IFF_OUT_LOG (IFF_UP, "UP"); 422 IFF_OUT_LOG (IFF_BROADCAST, "BROADCAST"); 423 IFF_OUT_LOG (IFF_DEBUG, "DEBUG"); 424 IFF_OUT_LOG (IFF_LOOPBACK, "LOOPBACK"); 425 IFF_OUT_LOG (IFF_POINTOPOINT, "POINTOPOINT"); 426 IFF_OUT_LOG (IFF_NOTRAILERS, "NOTRAILERS"); 427 IFF_OUT_LOG (IFF_RUNNING, "RUNNING"); 428 IFF_OUT_LOG (IFF_NOARP, "NOARP"); 429 IFF_OUT_LOG (IFF_PROMISC, "PROMISC"); 430 IFF_OUT_LOG (IFF_ALLMULTI, "ALLMULTI"); 431 IFF_OUT_LOG (IFF_OACTIVE, "OACTIVE"); 432 IFF_OUT_LOG (IFF_SIMPLEX, "SIMPLEX"); 433 IFF_OUT_LOG (IFF_LINK0, "LINK0"); 434 IFF_OUT_LOG (IFF_LINK1, "LINK1"); 435 IFF_OUT_LOG (IFF_LINK2, "LINK2"); 436 IFF_OUT_LOG (IFF_MULTICAST, "MULTICAST"); 437 IFF_OUT_LOG (IFF_NOXMIT, "NOXMIT"); 438 IFF_OUT_LOG (IFF_NORTEXCH, "NORTEXCH"); 439 IFF_OUT_LOG (IFF_VIRTUAL, "VIRTUAL"); 440 IFF_OUT_LOG (IFF_IPV4, "IPv4"); 441 IFF_OUT_LOG (IFF_IPV6, "IPv6"); 442 443 strlcat (logbuf, ">", BUFSIZ); 444 445 return logbuf; 446#undef IFF_OUT_LOG 447} 448 449/* For debugging */ 450static void 451if_dump (const struct interface *ifp) 452{ 453 struct listnode *node; 454 struct connected *c __attribute__((unused)); 455 456 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, c)) 457 zlog_info ("Interface %s index %d metric %d mtu %d " 458#ifdef HAVE_IPV6 459 "mtu6 %d " 460#endif /* HAVE_IPV6 */ 461 "%s", 462 ifp->name, ifp->ifindex, ifp->metric, ifp->mtu, 463#ifdef HAVE_IPV6 464 ifp->mtu6, 465#endif /* HAVE_IPV6 */ 466 if_flag_dump (ifp->flags)); 467} 468 469/* Interface printing for all interface. */ 470void 471if_dump_all (void) 472{ 473 struct listnode *node; 474 void *p; 475 476 for (ALL_LIST_ELEMENTS_RO (iflist, node, p)) 477 if_dump (p); 478} 479 480DEFUN (interface_desc, 481 interface_desc_cmd, 482 "description .LINE", 483 "Interface specific description\n" 484 "Characters describing this interface\n") 485{ 486 struct interface *ifp; 487 488 if (argc == 0) 489 return CMD_SUCCESS; 490 491 ifp = vty->index; 492 if (ifp->desc) 493 XFREE (MTYPE_TMP, ifp->desc); 494 ifp->desc = argv_concat(argv, argc, 0); 495 496 return CMD_SUCCESS; 497} 498 499DEFUN (no_interface_desc, 500 no_interface_desc_cmd, 501 "no description", 502 NO_STR 503 "Interface specific description\n") 504{ 505 struct interface *ifp; 506 507 ifp = vty->index; 508 if (ifp->desc) 509 XFREE (MTYPE_TMP, ifp->desc); 510 ifp->desc = NULL; 511 512 return CMD_SUCCESS; 513} 514 515#ifdef SUNOS_5 516/* Need to handle upgrade from SUNWzebra to Quagga. SUNWzebra created 517 * a seperate struct interface for each logical interface, so config 518 * file may be full of 'interface fooX:Y'. Solaris however does not 519 * expose logical interfaces via PF_ROUTE, so trying to track logical 520 * interfaces can be fruitless, for that reason Quagga only tracks 521 * the primary IP interface. 522 * 523 * We try accomodate SUNWzebra by: 524 * - looking up the interface name, to see whether it exists, if so 525 * its useable 526 * - for protocol daemons, this could only because zebra told us of 527 * the interface 528 * - for zebra, only because it learnt from kernel 529 * - if not: 530 * - search the name to see if it contains a sub-ipif / logical interface 531 * seperator, the ':' char. If it does: 532 * - text up to that char must be the primary name - get that name. 533 * if not: 534 * - no idea, just get the name in its entirety. 535 */ 536static struct interface * 537if_sunwzebra_get (const char *name, size_t nlen) 538{ 539 struct interface *ifp; 540 size_t seppos = 0; 541 542 if ( (ifp = if_lookup_by_name_len(name, nlen)) != NULL) 543 return ifp; 544 545 /* hunt the primary interface name... */ 546 while (seppos < nlen && name[seppos] != ':') 547 seppos++; 548 549 /* Wont catch seperator as last char, e.g. 'foo0:' but thats invalid */ 550 if (seppos < nlen) 551 return if_get_by_name_len (name, seppos); 552 else 553 return if_get_by_name_len (name, nlen); 554} 555#endif /* SUNOS_5 */ 556 557DEFUN (interface, 558 interface_cmd, 559 "interface IFNAME", 560 "Select an interface to configure\n" 561 "Interface's name\n") 562{ 563 struct interface *ifp; 564 size_t sl; 565 566 if ((sl = strlen(argv[0])) > INTERFACE_NAMSIZ) 567 { 568 vty_out (vty, "%% Interface name %s is invalid: length exceeds " 569 "%d characters%s", 570 argv[0], INTERFACE_NAMSIZ, VTY_NEWLINE); 571 return CMD_WARNING; 572 } 573 574#ifdef SUNOS_5 575 ifp = if_sunwzebra_get (argv[0], sl); 576#else 577 ifp = if_get_by_name_len(argv[0], sl); 578#endif /* SUNOS_5 */ 579 580 vty->index = ifp; 581 vty->node = INTERFACE_NODE; 582 583 return CMD_SUCCESS; 584} 585 586DEFUN_NOSH (no_interface, 587 no_interface_cmd, 588 "no interface IFNAME", 589 NO_STR 590 "Delete a pseudo interface's configuration\n" 591 "Interface's name\n") 592{ 593 // deleting interface 594 struct interface *ifp; 595 596 ifp = if_lookup_by_name (argv[0]); 597 598 if (ifp == NULL) 599 { 600 vty_out (vty, "%% Interface %s does not exist%s", argv[0], VTY_NEWLINE); 601 return CMD_WARNING; 602 } 603 604 if (CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) 605 { 606 vty_out (vty, "%% Only inactive interfaces can be deleted%s", 607 VTY_NEWLINE); 608 return CMD_WARNING; 609 } 610 611 if_delete(ifp); 612 613 return CMD_SUCCESS; 614} 615 616/* For debug purpose. */ 617DEFUN (show_address, 618 show_address_cmd, 619 "show address", 620 SHOW_STR 621 "address\n") 622{ 623 struct listnode *node; 624 struct listnode *node2; 625 struct interface *ifp; 626 struct connected *ifc; 627 struct prefix *p; 628 629 for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp)) 630 { 631 for (ALL_LIST_ELEMENTS_RO (ifp->connected, node2, ifc)) 632 { 633 p = ifc->address; 634 635 if (p->family == AF_INET) 636 vty_out (vty, "%s/%d%s", inet_ntoa (p->u.prefix4), p->prefixlen, 637 VTY_NEWLINE); 638 } 639 } 640 return CMD_SUCCESS; 641} 642 643/* Allocate connected structure. */ 644struct connected * 645connected_new (void) 646{ 647 return XCALLOC (MTYPE_CONNECTED, sizeof (struct connected)); 648} 649 650/* Free connected structure. */ 651void 652connected_free (struct connected *connected) 653{ 654 if (connected->address) 655 prefix_free (connected->address); 656 657 if (connected->destination) 658 prefix_free (connected->destination); 659 660 if (connected->label) 661 XFREE (MTYPE_CONNECTED_LABEL, connected->label); 662 663 XFREE (MTYPE_CONNECTED, connected); 664} 665 666/* Print if_addr structure. */ 667static void __attribute__ ((unused)) 668connected_log (struct connected *connected, char *str) 669{ 670 struct prefix *p; 671 struct interface *ifp; 672 char logbuf[BUFSIZ]; 673 char buf[BUFSIZ]; 674 675 ifp = connected->ifp; 676 p = connected->address; 677 678 snprintf (logbuf, BUFSIZ, "%s interface %s %s %s/%d ", 679 str, ifp->name, prefix_family_str (p), 680 inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ), 681 p->prefixlen); 682 683 p = connected->destination; 684 if (p) 685 { 686 strncat (logbuf, inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ), 687 BUFSIZ - strlen(logbuf)); 688 } 689 zlog (NULL, LOG_INFO, "%s", logbuf); 690} 691 692/* If two connected address has same prefix return 1. */ 693static int 694connected_same_prefix (struct prefix *p1, struct prefix *p2) 695{ 696 if (p1->family == p2->family) 697 { 698 if (p1->family == AF_INET && 699 IPV4_ADDR_SAME (&p1->u.prefix4, &p2->u.prefix4)) 700 return 1; 701#ifdef HAVE_IPV6 702 if (p1->family == AF_INET6 && 703 IPV6_ADDR_SAME (&p1->u.prefix6, &p2->u.prefix6)) 704 return 1; 705#endif /* HAVE_IPV6 */ 706 } 707 return 0; 708} 709 710struct connected * 711connected_delete_by_prefix (struct interface *ifp, struct prefix *p) 712{ 713 struct listnode *node; 714 struct listnode *next; 715 struct connected *ifc; 716 717 /* In case of same prefix come, replace it with new one. */ 718 for (node = listhead (ifp->connected); node; node = next) 719 { 720 ifc = listgetdata (node); 721 next = node->next; 722 723 if (connected_same_prefix (ifc->address, p)) 724 { 725 listnode_delete (ifp->connected, ifc); 726 return ifc; 727 } 728 } 729 return NULL; 730} 731 732/* Find the IPv4 address on our side that will be used when packets 733 are sent to dst. */ 734struct connected * 735connected_lookup_address (struct interface *ifp, struct in_addr dst) 736{ 737 struct prefix addr; 738 struct listnode *cnode; 739 struct connected *c; 740 struct connected *match; 741 742 addr.family = AF_INET; 743 addr.u.prefix4 = dst; 744 addr.prefixlen = IPV4_MAX_BITLEN; 745 746 match = NULL; 747 748 for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c)) 749 { 750 if (c->address && (c->address->family == AF_INET) && 751 prefix_match(CONNECTED_PREFIX(c), &addr) && 752 (!match || (c->address->prefixlen > match->address->prefixlen))) 753 match = c; 754 } 755 return match; 756} 757 758struct connected * 759connected_add_by_prefix (struct interface *ifp, struct prefix *p, 760 struct prefix *destination) 761{ 762 struct connected *ifc; 763 764 /* Allocate new connected address. */ 765 ifc = connected_new (); 766 ifc->ifp = ifp; 767 768 /* Fetch interface address */ 769 ifc->address = prefix_new(); 770 memcpy (ifc->address, p, sizeof(struct prefix)); 771 772 /* Fetch dest address */ 773 if (destination) 774 { 775 ifc->destination = prefix_new(); 776 memcpy (ifc->destination, destination, sizeof(struct prefix)); 777 } 778 779 /* Add connected address to the interface. */ 780 listnode_add (ifp->connected, ifc); 781 return ifc; 782} 783 784#ifndef HAVE_IF_NAMETOINDEX 785unsigned int 786if_nametoindex (const char *name) 787{ 788 struct interface *ifp; 789 790 return ((ifp = if_lookup_by_name_len(name, strnlen(name, IFNAMSIZ))) != NULL) 791 ? ifp->ifindex : 0; 792} 793#endif 794 795#ifndef HAVE_IF_INDEXTONAME 796char * 797if_indextoname (unsigned int ifindex, char *name) 798{ 799 struct interface *ifp; 800 801 if (!(ifp = if_lookup_by_index(ifindex))) 802 return NULL; 803 strncpy (name, ifp->name, IFNAMSIZ); 804 return ifp->name; 805} 806#endif 807 808#if 0 /* this route_table of struct connected's is unused 809 * however, it would be good to use a route_table rather than 810 * a list.. 811 */ 812/* Interface looking up by interface's address. */ 813/* Interface's IPv4 address reverse lookup table. */ 814struct route_table *ifaddr_ipv4_table; 815/* struct route_table *ifaddr_ipv6_table; */ 816 817static void 818ifaddr_ipv4_add (struct in_addr *ifaddr, struct interface *ifp) 819{ 820 struct route_node *rn; 821 struct prefix_ipv4 p; 822 823 p.family = AF_INET; 824 p.prefixlen = IPV4_MAX_PREFIXLEN; 825 p.prefix = *ifaddr; 826 827 rn = route_node_get (ifaddr_ipv4_table, (struct prefix *) &p); 828 if (rn) 829 { 830 route_unlock_node (rn); 831 zlog_info ("ifaddr_ipv4_add(): address %s is already added", 832 inet_ntoa (*ifaddr)); 833 return; 834 } 835 rn->info = ifp; 836} 837 838static void 839ifaddr_ipv4_delete (struct in_addr *ifaddr, struct interface *ifp) 840{ 841 struct route_node *rn; 842 struct prefix_ipv4 p; 843 844 p.family = AF_INET; 845 p.prefixlen = IPV4_MAX_PREFIXLEN; 846 p.prefix = *ifaddr; 847 848 rn = route_node_lookup (ifaddr_ipv4_table, (struct prefix *) &p); 849 if (! rn) 850 { 851 zlog_info ("ifaddr_ipv4_delete(): can't find address %s", 852 inet_ntoa (*ifaddr)); 853 return; 854 } 855 rn->info = NULL; 856 route_unlock_node (rn); 857 route_unlock_node (rn); 858} 859 860/* Lookup interface by interface's IP address or interface index. */ 861static struct interface * 862ifaddr_ipv4_lookup (struct in_addr *addr, unsigned int ifindex) 863{ 864 struct prefix_ipv4 p; 865 struct route_node *rn; 866 struct interface *ifp; 867 868 if (addr) 869 { 870 p.family = AF_INET; 871 p.prefixlen = IPV4_MAX_PREFIXLEN; 872 p.prefix = *addr; 873 874 rn = route_node_lookup (ifaddr_ipv4_table, (struct prefix *) &p); 875 if (! rn) 876 return NULL; 877 878 ifp = rn->info; 879 route_unlock_node (rn); 880 return ifp; 881 } 882 else 883 return if_lookup_by_index(ifindex); 884} 885#endif /* ifaddr_ipv4_table */ 886 887/* Initialize interface list. */ 888void 889if_init (void) 890{ 891 iflist = list_new (); 892#if 0 893 ifaddr_ipv4_table = route_table_init (); 894#endif /* ifaddr_ipv4_table */ 895 896 if (iflist) { 897 iflist->cmp = (int (*)(void *, void *))if_cmp_func; 898 return; 899 } 900 901 memset (&if_master, 0, sizeof if_master); 902} 903 904void 905if_terminate (void) 906{ 907 for (;;) 908 { 909 struct interface *ifp; 910 911 ifp = listnode_head (iflist); 912 if (ifp == NULL) 913 break; 914 915 if_delete (ifp); 916 } 917 918 list_delete (iflist); 919 iflist = NULL; 920} 921