Annotation of embedaddon/bird/nest/iface.c, revision 1.1
1.1 ! misho 1: /*
! 2: * BIRD -- Management of Interfaces and Neighbor Cache
! 3: *
! 4: * (c) 1998--2000 Martin Mares <mj@ucw.cz>
! 5: *
! 6: * Can be freely distributed and used under the terms of the GNU GPL.
! 7: */
! 8:
! 9: /**
! 10: * DOC: Interfaces
! 11: *
! 12: * The interface module keeps track of all network interfaces in the
! 13: * system and their addresses.
! 14: *
! 15: * Each interface is represented by an &iface structure which carries
! 16: * interface capability flags (%IF_MULTIACCESS, %IF_BROADCAST etc.),
! 17: * MTU, interface name and index and finally a linked list of network
! 18: * prefixes assigned to the interface, each one represented by
! 19: * struct &ifa.
! 20: *
! 21: * The interface module keeps a `soft-up' state for each &iface which
! 22: * is a conjunction of link being up, the interface being of a `sane'
! 23: * type and at least one IP address assigned to it.
! 24: */
! 25:
! 26: #undef LOCAL_DEBUG
! 27:
! 28: #include "nest/bird.h"
! 29: #include "nest/iface.h"
! 30: #include "nest/protocol.h"
! 31: #include "nest/cli.h"
! 32: #include "lib/resource.h"
! 33: #include "lib/string.h"
! 34: #include "conf/conf.h"
! 35:
! 36: static pool *if_pool;
! 37:
! 38: list iface_list;
! 39:
! 40: /**
! 41: * ifa_dump - dump interface address
! 42: * @a: interface address descriptor
! 43: *
! 44: * This function dumps contents of an &ifa to the debug output.
! 45: */
! 46: void
! 47: ifa_dump(struct ifa *a)
! 48: {
! 49: debug("\t%I, net %I/%-2d bc %I -> %I%s%s%s\n", a->ip, a->prefix, a->pxlen, a->brd, a->opposite,
! 50: (a->flags & IF_UP) ? "" : " DOWN",
! 51: (a->flags & IA_PRIMARY) ? "" : " SEC",
! 52: (a->flags & IA_PEER) ? "PEER" : "");
! 53: }
! 54:
! 55: /**
! 56: * if_dump - dump interface
! 57: * @i: interface to dump
! 58: *
! 59: * This function dumps all information associated with a given
! 60: * network interface to the debug output.
! 61: */
! 62: void
! 63: if_dump(struct iface *i)
! 64: {
! 65: struct ifa *a;
! 66:
! 67: debug("IF%d: %s", i->index, i->name);
! 68: if (i->flags & IF_SHUTDOWN)
! 69: debug(" SHUTDOWN");
! 70: if (i->flags & IF_UP)
! 71: debug(" UP");
! 72: else
! 73: debug(" DOWN");
! 74: if (i->flags & IF_ADMIN_UP)
! 75: debug(" LINK-UP");
! 76: if (i->flags & IF_MULTIACCESS)
! 77: debug(" MA");
! 78: if (i->flags & IF_BROADCAST)
! 79: debug(" BC");
! 80: if (i->flags & IF_MULTICAST)
! 81: debug(" MC");
! 82: if (i->flags & IF_LOOPBACK)
! 83: debug(" LOOP");
! 84: if (i->flags & IF_IGNORE)
! 85: debug(" IGN");
! 86: if (i->flags & IF_TMP_DOWN)
! 87: debug(" TDOWN");
! 88: debug(" MTU=%d\n", i->mtu);
! 89: WALK_LIST(a, i->addrs)
! 90: {
! 91: ifa_dump(a);
! 92: ASSERT((a != i->addr) == !(a->flags & IA_PRIMARY));
! 93: }
! 94: }
! 95:
! 96: /**
! 97: * if_dump_all - dump all interfaces
! 98: *
! 99: * This function dumps information about all known network
! 100: * interfaces to the debug output.
! 101: */
! 102: void
! 103: if_dump_all(void)
! 104: {
! 105: struct iface *i;
! 106:
! 107: debug("Known network interfaces:\n");
! 108: WALK_LIST(i, iface_list)
! 109: if_dump(i);
! 110: debug("Router ID: %08x\n", config->router_id);
! 111: }
! 112:
! 113: static inline unsigned
! 114: if_what_changed(struct iface *i, struct iface *j)
! 115: {
! 116: unsigned c;
! 117:
! 118: if (((i->flags ^ j->flags) & ~(IF_UP | IF_SHUTDOWN | IF_UPDATED | IF_ADMIN_UP | IF_LINK_UP | IF_TMP_DOWN | IF_JUST_CREATED))
! 119: || i->index != j->index)
! 120: return IF_CHANGE_TOO_MUCH;
! 121: c = 0;
! 122: if ((i->flags ^ j->flags) & IF_UP)
! 123: c |= (i->flags & IF_UP) ? IF_CHANGE_DOWN : IF_CHANGE_UP;
! 124: if ((i->flags ^ j->flags) & IF_LINK_UP)
! 125: c |= IF_CHANGE_LINK;
! 126: if (i->mtu != j->mtu)
! 127: c |= IF_CHANGE_MTU;
! 128: return c;
! 129: }
! 130:
! 131: static inline void
! 132: if_copy(struct iface *to, struct iface *from)
! 133: {
! 134: to->flags = from->flags | (to->flags & IF_TMP_DOWN);
! 135: to->mtu = from->mtu;
! 136: }
! 137:
! 138: static inline void
! 139: ifa_send_notify(struct proto *p, unsigned c, struct ifa *a)
! 140: {
! 141: if (p->ifa_notify)
! 142: {
! 143: if (p->debug & D_IFACES)
! 144: log(L_TRACE "%s < %s address %I/%d on interface %s %s",
! 145: p->name, (a->flags & IA_PRIMARY) ? "primary" : "secondary",
! 146: a->prefix, a->pxlen, a->iface->name,
! 147: (c & IF_CHANGE_UP) ? "added" : "removed");
! 148: p->ifa_notify(p, c, a);
! 149: }
! 150: }
! 151:
! 152: static void
! 153: ifa_notify_change_(unsigned c, struct ifa *a)
! 154: {
! 155: struct proto *p;
! 156:
! 157: DBG("IFA change notification (%x) for %s:%I\n", c, a->iface->name, a->ip);
! 158:
! 159: WALK_LIST(p, active_proto_list)
! 160: ifa_send_notify(p, c, a);
! 161: }
! 162:
! 163: static inline void
! 164: ifa_notify_change(unsigned c, struct ifa *a)
! 165: {
! 166: if (c & IF_CHANGE_DOWN)
! 167: neigh_ifa_update(a);
! 168:
! 169: ifa_notify_change_(c, a);
! 170:
! 171: if (c & IF_CHANGE_UP)
! 172: neigh_ifa_update(a);
! 173: }
! 174:
! 175: static inline void
! 176: if_send_notify(struct proto *p, unsigned c, struct iface *i)
! 177: {
! 178: if (p->if_notify)
! 179: {
! 180: if (p->debug & D_IFACES)
! 181: log(L_TRACE "%s < interface %s %s", p->name, i->name,
! 182: (c & IF_CHANGE_UP) ? "goes up" :
! 183: (c & IF_CHANGE_DOWN) ? "goes down" :
! 184: (c & IF_CHANGE_MTU) ? "changes MTU" :
! 185: (c & IF_CHANGE_LINK) ? "changes link" :
! 186: (c & IF_CHANGE_CREATE) ? "created" :
! 187: "sends unknown event");
! 188: p->if_notify(p, c, i);
! 189: }
! 190: }
! 191:
! 192: static void
! 193: if_notify_change(unsigned c, struct iface *i)
! 194: {
! 195: struct proto *p;
! 196: struct ifa *a;
! 197:
! 198: if (i->flags & IF_JUST_CREATED)
! 199: {
! 200: i->flags &= ~IF_JUST_CREATED;
! 201: c |= IF_CHANGE_CREATE | IF_CHANGE_MTU;
! 202: }
! 203:
! 204: DBG("Interface change notification (%x) for %s\n", c, i->name);
! 205: #ifdef LOCAL_DEBUG
! 206: if_dump(i);
! 207: #endif
! 208:
! 209: if (c & IF_CHANGE_DOWN)
! 210: neigh_if_down(i);
! 211:
! 212: if (c & IF_CHANGE_DOWN)
! 213: WALK_LIST(a, i->addrs)
! 214: {
! 215: a->flags = (i->flags & ~IA_FLAGS) | (a->flags & IA_FLAGS);
! 216: ifa_notify_change_(IF_CHANGE_DOWN, a);
! 217: }
! 218:
! 219: WALK_LIST(p, active_proto_list)
! 220: if_send_notify(p, c, i);
! 221:
! 222: if (c & IF_CHANGE_UP)
! 223: WALK_LIST(a, i->addrs)
! 224: {
! 225: a->flags = (i->flags & ~IA_FLAGS) | (a->flags & IA_FLAGS);
! 226: ifa_notify_change_(IF_CHANGE_UP, a);
! 227: }
! 228:
! 229: if (c & IF_CHANGE_UP)
! 230: neigh_if_up(i);
! 231:
! 232: if ((c & (IF_CHANGE_UP | IF_CHANGE_DOWN | IF_CHANGE_LINK)) == IF_CHANGE_LINK)
! 233: neigh_if_link(i);
! 234: }
! 235:
! 236: static unsigned
! 237: if_recalc_flags(struct iface *i, unsigned flags)
! 238: {
! 239: if ((flags & (IF_SHUTDOWN | IF_TMP_DOWN)) ||
! 240: !(flags & IF_ADMIN_UP) ||
! 241: !i->addr)
! 242: flags &= ~IF_UP;
! 243: else
! 244: flags |= IF_UP;
! 245: return flags;
! 246: }
! 247:
! 248: static void
! 249: if_change_flags(struct iface *i, unsigned flags)
! 250: {
! 251: unsigned of = i->flags;
! 252:
! 253: i->flags = if_recalc_flags(i, flags);
! 254: if ((i->flags ^ of) & IF_UP)
! 255: if_notify_change((i->flags & IF_UP) ? IF_CHANGE_UP : IF_CHANGE_DOWN, i);
! 256: }
! 257:
! 258: /**
! 259: * if_delete - remove interface
! 260: * @old: interface
! 261: *
! 262: * This function is called by the low-level platform dependent code
! 263: * whenever it notices an interface disappears. It is just a shorthand
! 264: * for if_update().
! 265: */
! 266:
! 267: void
! 268: if_delete(struct iface *old)
! 269: {
! 270: struct iface f = {};
! 271: strncpy(f.name, old->name, sizeof(f.name)-1);
! 272: f.flags = IF_SHUTDOWN;
! 273: if_update(&f);
! 274: }
! 275:
! 276: /**
! 277: * if_update - update interface status
! 278: * @new: new interface status
! 279: *
! 280: * if_update() is called by the low-level platform dependent code
! 281: * whenever it notices an interface change.
! 282: *
! 283: * There exist two types of interface updates -- synchronous and asynchronous
! 284: * ones. In the synchronous case, the low-level code calls if_start_update(),
! 285: * scans all interfaces reported by the OS, uses if_update() and ifa_update()
! 286: * to pass them to the core and then it finishes the update sequence by
! 287: * calling if_end_update(). When working asynchronously, the sysdep code
! 288: * calls if_update() and ifa_update() whenever it notices a change.
! 289: *
! 290: * if_update() will automatically notify all other modules about the change.
! 291: */
! 292: struct iface *
! 293: if_update(struct iface *new)
! 294: {
! 295: struct iface *i;
! 296: unsigned c;
! 297:
! 298: WALK_LIST(i, iface_list)
! 299: if (!strcmp(new->name, i->name))
! 300: {
! 301: new->addr = i->addr;
! 302: new->flags = if_recalc_flags(new, new->flags);
! 303: c = if_what_changed(i, new);
! 304: if (c & IF_CHANGE_TOO_MUCH) /* Changed a lot, convert it to down/up */
! 305: {
! 306: DBG("Interface %s changed too much -- forcing down/up transition\n", i->name);
! 307: if_change_flags(i, i->flags | IF_TMP_DOWN);
! 308: rem_node(&i->n);
! 309: new->addr = i->addr;
! 310: memcpy(&new->addrs, &i->addrs, sizeof(i->addrs));
! 311: memcpy(i, new, sizeof(*i));
! 312: i->flags &= ~IF_UP; /* IF_TMP_DOWN will be added later */
! 313: goto newif;
! 314: }
! 315:
! 316: if_copy(i, new);
! 317: if (c)
! 318: if_notify_change(c, i);
! 319:
! 320: i->flags |= IF_UPDATED;
! 321: return i;
! 322: }
! 323: i = mb_alloc(if_pool, sizeof(struct iface));
! 324: memcpy(i, new, sizeof(*i));
! 325: init_list(&i->addrs);
! 326: newif:
! 327: init_list(&i->neighbors);
! 328: i->flags |= IF_UPDATED | IF_TMP_DOWN; /* Tmp down as we don't have addresses yet */
! 329: add_tail(&iface_list, &i->n);
! 330: return i;
! 331: }
! 332:
! 333: void
! 334: if_start_update(void)
! 335: {
! 336: struct iface *i;
! 337: struct ifa *a;
! 338:
! 339: WALK_LIST(i, iface_list)
! 340: {
! 341: i->flags &= ~IF_UPDATED;
! 342: WALK_LIST(a, i->addrs)
! 343: a->flags &= ~IF_UPDATED;
! 344: }
! 345: }
! 346:
! 347: void
! 348: if_end_partial_update(struct iface *i)
! 349: {
! 350: if (i->flags & IF_TMP_DOWN)
! 351: if_change_flags(i, i->flags & ~IF_TMP_DOWN);
! 352: }
! 353:
! 354: void
! 355: if_end_update(void)
! 356: {
! 357: struct iface *i;
! 358: struct ifa *a, *b;
! 359:
! 360: WALK_LIST(i, iface_list)
! 361: {
! 362: if (!(i->flags & IF_UPDATED))
! 363: if_change_flags(i, (i->flags & ~IF_ADMIN_UP) | IF_SHUTDOWN);
! 364: else
! 365: {
! 366: WALK_LIST_DELSAFE(a, b, i->addrs)
! 367: if (!(a->flags & IF_UPDATED))
! 368: ifa_delete(a);
! 369: if_end_partial_update(i);
! 370: }
! 371: }
! 372: }
! 373:
! 374: void
! 375: if_flush_ifaces(struct proto *p)
! 376: {
! 377: if (p->debug & D_EVENTS)
! 378: log(L_TRACE "%s: Flushing interfaces", p->name);
! 379: if_start_update();
! 380: if_end_update();
! 381: }
! 382:
! 383: /**
! 384: * if_feed_baby - advertise interfaces to a new protocol
! 385: * @p: protocol to feed
! 386: *
! 387: * When a new protocol starts, this function sends it a series
! 388: * of notifications about all existing interfaces.
! 389: */
! 390: void
! 391: if_feed_baby(struct proto *p)
! 392: {
! 393: struct iface *i;
! 394: struct ifa *a;
! 395:
! 396: if (!p->if_notify && !p->ifa_notify) /* shortcut */
! 397: return;
! 398: DBG("Announcing interfaces to new protocol %s\n", p->name);
! 399: WALK_LIST(i, iface_list)
! 400: {
! 401: if_send_notify(p, IF_CHANGE_CREATE | ((i->flags & IF_UP) ? IF_CHANGE_UP : 0), i);
! 402: if (i->flags & IF_UP)
! 403: WALK_LIST(a, i->addrs)
! 404: ifa_send_notify(p, IF_CHANGE_CREATE | IF_CHANGE_UP, a);
! 405: }
! 406: }
! 407:
! 408: /**
! 409: * if_find_by_index - find interface by ifindex
! 410: * @idx: ifindex
! 411: *
! 412: * This function finds an &iface structure corresponding to an interface
! 413: * of the given index @idx. Returns a pointer to the structure or %NULL
! 414: * if no such structure exists.
! 415: */
! 416: struct iface *
! 417: if_find_by_index(unsigned idx)
! 418: {
! 419: struct iface *i;
! 420:
! 421: WALK_LIST(i, iface_list)
! 422: if (i->index == idx && !(i->flags & IF_SHUTDOWN))
! 423: return i;
! 424: return NULL;
! 425: }
! 426:
! 427: /**
! 428: * if_find_by_name - find interface by name
! 429: * @name: interface name
! 430: *
! 431: * This function finds an &iface structure corresponding to an interface
! 432: * of the given name @name. Returns a pointer to the structure or %NULL
! 433: * if no such structure exists.
! 434: */
! 435: struct iface *
! 436: if_find_by_name(char *name)
! 437: {
! 438: struct iface *i;
! 439:
! 440: WALK_LIST(i, iface_list)
! 441: if (!strcmp(i->name, name))
! 442: return i;
! 443: return NULL;
! 444: }
! 445:
! 446: struct iface *
! 447: if_get_by_name(char *name)
! 448: {
! 449: struct iface *i;
! 450:
! 451: if (i = if_find_by_name(name))
! 452: return i;
! 453:
! 454: /* No active iface, create a dummy */
! 455: i = mb_allocz(if_pool, sizeof(struct iface));
! 456: strncpy(i->name, name, sizeof(i->name)-1);
! 457: i->flags = IF_SHUTDOWN;
! 458: init_list(&i->addrs);
! 459: init_list(&i->neighbors);
! 460: add_tail(&iface_list, &i->n);
! 461: return i;
! 462: }
! 463:
! 464: struct ifa *kif_choose_primary(struct iface *i);
! 465:
! 466: static int
! 467: ifa_recalc_primary(struct iface *i)
! 468: {
! 469: struct ifa *a = kif_choose_primary(i);
! 470:
! 471: if (a == i->addr)
! 472: return 0;
! 473:
! 474: if (i->addr)
! 475: i->addr->flags &= ~IA_PRIMARY;
! 476:
! 477: if (a)
! 478: {
! 479: a->flags |= IA_PRIMARY;
! 480: rem_node(&a->n);
! 481: add_head(&i->addrs, &a->n);
! 482: }
! 483:
! 484: i->addr = a;
! 485: return 1;
! 486: }
! 487:
! 488: void
! 489: ifa_recalc_all_primary_addresses(void)
! 490: {
! 491: struct iface *i;
! 492:
! 493: WALK_LIST(i, iface_list)
! 494: {
! 495: if (ifa_recalc_primary(i))
! 496: if_change_flags(i, i->flags | IF_TMP_DOWN);
! 497: }
! 498: }
! 499:
! 500: static inline int
! 501: ifa_same(struct ifa *a, struct ifa *b)
! 502: {
! 503: return ipa_equal(a->ip, b->ip) && ipa_equal(a->prefix, b->prefix) &&
! 504: a->pxlen == b->pxlen;
! 505: }
! 506:
! 507:
! 508: /**
! 509: * ifa_update - update interface address
! 510: * @a: new interface address
! 511: *
! 512: * This function adds address information to a network
! 513: * interface. It's called by the platform dependent code during
! 514: * the interface update process described under if_update().
! 515: */
! 516: struct ifa *
! 517: ifa_update(struct ifa *a)
! 518: {
! 519: struct iface *i = a->iface;
! 520: struct ifa *b;
! 521:
! 522: WALK_LIST(b, i->addrs)
! 523: if (ifa_same(b, a))
! 524: {
! 525: if (ipa_equal(b->brd, a->brd) &&
! 526: ipa_equal(b->opposite, a->opposite) &&
! 527: b->scope == a->scope &&
! 528: !((b->flags ^ a->flags) & IA_PEER))
! 529: {
! 530: b->flags |= IF_UPDATED;
! 531: return b;
! 532: }
! 533: ifa_delete(b);
! 534: break;
! 535: }
! 536:
! 537: #ifndef IPV6
! 538: if ((i->flags & IF_BROADCAST) && !ipa_nonzero(a->brd))
! 539: log(L_ERR "Missing broadcast address for interface %s", i->name);
! 540: #endif
! 541:
! 542: b = mb_alloc(if_pool, sizeof(struct ifa));
! 543: memcpy(b, a, sizeof(struct ifa));
! 544: add_tail(&i->addrs, &b->n);
! 545: b->flags = (i->flags & ~IA_FLAGS) | (a->flags & IA_FLAGS);
! 546: if (ifa_recalc_primary(i))
! 547: if_change_flags(i, i->flags | IF_TMP_DOWN);
! 548: if (b->flags & IF_UP)
! 549: ifa_notify_change(IF_CHANGE_CREATE | IF_CHANGE_UP, b);
! 550: return b;
! 551: }
! 552:
! 553: /**
! 554: * ifa_delete - remove interface address
! 555: * @a: interface address
! 556: *
! 557: * This function removes address information from a network
! 558: * interface. It's called by the platform dependent code during
! 559: * the interface update process described under if_update().
! 560: */
! 561: void
! 562: ifa_delete(struct ifa *a)
! 563: {
! 564: struct iface *i = a->iface;
! 565: struct ifa *b;
! 566:
! 567: WALK_LIST(b, i->addrs)
! 568: if (ifa_same(b, a))
! 569: {
! 570: rem_node(&b->n);
! 571: if (b->flags & IF_UP)
! 572: {
! 573: b->flags &= ~IF_UP;
! 574: ifa_notify_change(IF_CHANGE_DOWN, b);
! 575: }
! 576: if (b->flags & IA_PRIMARY)
! 577: {
! 578: if_change_flags(i, i->flags | IF_TMP_DOWN);
! 579: ifa_recalc_primary(i);
! 580: }
! 581: mb_free(b);
! 582: return;
! 583: }
! 584: }
! 585:
! 586: u32
! 587: if_choose_router_id(struct iface_patt *mask UNUSED6, u32 old_id UNUSED6)
! 588: {
! 589: #ifndef IPV6
! 590: struct iface *i;
! 591: struct ifa *a, *b;
! 592:
! 593: b = NULL;
! 594: WALK_LIST(i, iface_list)
! 595: {
! 596: if (!(i->flags & IF_ADMIN_UP) ||
! 597: (i->flags & IF_SHUTDOWN))
! 598: continue;
! 599:
! 600: WALK_LIST(a, i->addrs)
! 601: {
! 602: if (a->flags & IA_SECONDARY)
! 603: continue;
! 604:
! 605: if (a->scope <= SCOPE_LINK)
! 606: continue;
! 607:
! 608: /* Check pattern if specified */
! 609: if (mask && !iface_patt_match(mask, i, a))
! 610: continue;
! 611:
! 612: /* No pattern or pattern matched */
! 613: if (!b || ipa_to_u32(a->ip) < ipa_to_u32(b->ip))
! 614: b = a;
! 615: }
! 616: }
! 617:
! 618: if (!b)
! 619: return 0;
! 620:
! 621: u32 id = ipa_to_u32(b->ip);
! 622: if (id != old_id)
! 623: log(L_INFO "Chosen router ID %R according to interface %s", id, b->iface->name);
! 624:
! 625: return id;
! 626:
! 627: #else
! 628: return 0;
! 629: #endif
! 630: }
! 631:
! 632: /**
! 633: * if_init - initialize interface module
! 634: *
! 635: * This function is called during BIRD startup to initialize
! 636: * all data structures of the interface module.
! 637: */
! 638: void
! 639: if_init(void)
! 640: {
! 641: if_pool = rp_new(&root_pool, "Interfaces");
! 642: init_list(&iface_list);
! 643: neigh_init(if_pool);
! 644: }
! 645:
! 646: /*
! 647: * Interface Pattern Lists
! 648: */
! 649:
! 650: int
! 651: iface_patt_match(struct iface_patt *ifp, struct iface *i, struct ifa *a)
! 652: {
! 653: struct iface_patt_node *p;
! 654:
! 655: WALK_LIST(p, ifp->ipn_list)
! 656: {
! 657: char *t = p->pattern;
! 658: int pos = p->positive;
! 659:
! 660: if (t)
! 661: {
! 662: if (*t == '-')
! 663: {
! 664: t++;
! 665: pos = !pos;
! 666: }
! 667:
! 668: if (!patmatch(t, i->name))
! 669: continue;
! 670: }
! 671:
! 672: if (p->pxlen == 0)
! 673: return pos;
! 674:
! 675: if (!a)
! 676: continue;
! 677:
! 678: if (ipa_in_net(a->ip, p->prefix, p->pxlen))
! 679: return pos;
! 680:
! 681: if ((a->flags & IA_PEER) &&
! 682: ipa_in_net(a->opposite, p->prefix, p->pxlen))
! 683: return pos;
! 684:
! 685: continue;
! 686: }
! 687:
! 688: return 0;
! 689: }
! 690:
! 691: struct iface_patt *
! 692: iface_patt_find(list *l, struct iface *i, struct ifa *a)
! 693: {
! 694: struct iface_patt *p;
! 695:
! 696: WALK_LIST(p, *l)
! 697: if (iface_patt_match(p, i, a))
! 698: return p;
! 699:
! 700: return NULL;
! 701: }
! 702:
! 703: static int
! 704: iface_plists_equal(struct iface_patt *pa, struct iface_patt *pb)
! 705: {
! 706: struct iface_patt_node *x, *y;
! 707:
! 708: x = HEAD(pa->ipn_list);
! 709: y = HEAD(pb->ipn_list);
! 710: while (x->n.next && y->n.next)
! 711: {
! 712: if ((x->positive != y->positive) ||
! 713: (!x->pattern && y->pattern) || /* This nasty lines where written by me... :-( Feela */
! 714: (!y->pattern && x->pattern) ||
! 715: ((x->pattern != y->pattern) && strcmp(x->pattern, y->pattern)) ||
! 716: !ipa_equal(x->prefix, y->prefix) ||
! 717: (x->pxlen != y->pxlen))
! 718: return 0;
! 719: x = (void *) x->n.next;
! 720: y = (void *) y->n.next;
! 721: }
! 722: return (!x->n.next && !y->n.next);
! 723: }
! 724:
! 725: int
! 726: iface_patts_equal(list *a, list *b, int (*comp)(struct iface_patt *, struct iface_patt *))
! 727: {
! 728: struct iface_patt *x, *y;
! 729:
! 730: x = HEAD(*a);
! 731: y = HEAD(*b);
! 732: while (x->n.next && y->n.next)
! 733: {
! 734: if (!iface_plists_equal(x, y) ||
! 735: (comp && !comp(x, y)))
! 736: return 0;
! 737: x = (void *) x->n.next;
! 738: y = (void *) y->n.next;
! 739: }
! 740: return (!x->n.next && !y->n.next);
! 741: }
! 742:
! 743: /*
! 744: * CLI commands.
! 745: */
! 746:
! 747: static void
! 748: if_show_addr(struct ifa *a)
! 749: {
! 750: byte opp[STD_ADDRESS_P_LENGTH + 16];
! 751:
! 752: if (ipa_nonzero(a->opposite))
! 753: bsprintf(opp, ", opposite %I", a->opposite);
! 754: else
! 755: opp[0] = 0;
! 756: cli_msg(-1003, "\t%I/%d (%s%s, scope %s)",
! 757: a->ip, a->pxlen,
! 758: (a->flags & IA_PRIMARY) ? "Primary" : (a->flags & IA_SECONDARY) ? "Secondary" : "Unselected",
! 759: opp, ip_scope_text(a->scope));
! 760: }
! 761:
! 762: void
! 763: if_show(void)
! 764: {
! 765: struct iface *i;
! 766: struct ifa *a;
! 767: char *type;
! 768:
! 769: WALK_LIST(i, iface_list)
! 770: {
! 771: if (i->flags & IF_SHUTDOWN)
! 772: continue;
! 773:
! 774: cli_msg(-1001, "%s %s (index=%d)", i->name, (i->flags & IF_UP) ? "up" : "DOWN", i->index);
! 775: if (!(i->flags & IF_MULTIACCESS))
! 776: type = "PtP";
! 777: else
! 778: type = "MultiAccess";
! 779: cli_msg(-1004, "\t%s%s%s Admin%s Link%s%s%s MTU=%d",
! 780: type,
! 781: (i->flags & IF_BROADCAST) ? " Broadcast" : "",
! 782: (i->flags & IF_MULTICAST) ? " Multicast" : "",
! 783: (i->flags & IF_ADMIN_UP) ? "Up" : "Down",
! 784: (i->flags & IF_LINK_UP) ? "Up" : "Down",
! 785: (i->flags & IF_LOOPBACK) ? " Loopback" : "",
! 786: (i->flags & IF_IGNORE) ? " Ignored" : "",
! 787: i->mtu);
! 788: if (i->addr)
! 789: if_show_addr(i->addr);
! 790: WALK_LIST(a, i->addrs)
! 791: if (a != i->addr)
! 792: if_show_addr(a);
! 793: }
! 794: cli_msg(0, "");
! 795: }
! 796:
! 797: void
! 798: if_show_summary(void)
! 799: {
! 800: struct iface *i;
! 801: byte addr[STD_ADDRESS_P_LENGTH + 16];
! 802:
! 803: cli_msg(-2005, "interface state address");
! 804: WALK_LIST(i, iface_list)
! 805: {
! 806: if (i->addr)
! 807: bsprintf(addr, "%I/%d", i->addr->ip, i->addr->pxlen);
! 808: else
! 809: addr[0] = 0;
! 810: cli_msg(-1005, "%-9s %-5s %s", i->name, (i->flags & IF_UP) ? "up" : "DOWN", addr);
! 811: }
! 812: cli_msg(0, "");
! 813: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>