Annotation of embedaddon/bird/nest/iface.c, revision 1.1.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>