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>