Annotation of embedaddon/bird2/nest/rt-dev.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  *     BIRD -- Direct Device Routes
        !             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: Direct
        !            11:  *
        !            12:  * The Direct protocol works by converting all ifa_notify() events it receives
        !            13:  * to rte_update() calls for the corresponding network.
        !            14:  */
        !            15: 
        !            16: #undef LOCAL_DEBUG
        !            17: 
        !            18: #include "nest/bird.h"
        !            19: #include "nest/iface.h"
        !            20: #include "nest/protocol.h"
        !            21: #include "nest/route.h"
        !            22: #include "nest/rt-dev.h"
        !            23: #include "conf/conf.h"
        !            24: #include "lib/resource.h"
        !            25: #include "lib/string.h"
        !            26: 
        !            27: 
        !            28: static void
        !            29: dev_ifa_notify(struct proto *P, uint flags, struct ifa *ad)
        !            30: {
        !            31:   struct rt_dev_proto *p = (void *) P;
        !            32:   struct rt_dev_config *cf = (void *) P->cf;
        !            33:   struct channel *c;
        !            34:   net_addr *net = &ad->prefix;
        !            35: 
        !            36:   if (!EMPTY_LIST(cf->iface_list) &&
        !            37:       !iface_patt_find(&cf->iface_list, ad->iface, ad))
        !            38:     /* Empty list is automatically treated as "*" */
        !            39:     return;
        !            40: 
        !            41:   if (ad->flags & IA_SECONDARY)
        !            42:     return;
        !            43: 
        !            44:   if (ad->scope <= SCOPE_LINK)
        !            45:     return;
        !            46: 
        !            47:   if (ad->prefix.type == NET_IP4)
        !            48:     c = p->ip4_channel;
        !            49:   else if (ad->prefix.type == NET_IP6)
        !            50:     c = p->ip6_channel;
        !            51:   else
        !            52:     return;
        !            53: 
        !            54:   if (!c)
        !            55:     return;
        !            56: 
        !            57:   /* For IPv6 SADR, replace regular prefix with SADR prefix */
        !            58:   if (c->net_type == NET_IP6_SADR)
        !            59:   {
        !            60:     net = alloca(sizeof(net_addr_ip6_sadr));
        !            61:     net_fill_ip6_sadr(net, net6_prefix(&ad->prefix), net6_pxlen(&ad->prefix), IP6_NONE, 0);
        !            62:   }
        !            63: 
        !            64:   if (flags & IF_CHANGE_DOWN)
        !            65:     {
        !            66:       DBG("dev_if_notify: %s:%I going down\n", ad->iface->name, ad->ip);
        !            67: 
        !            68:       /* Use iface ID as local source ID */
        !            69:       struct rte_src *src = rt_get_source(P, ad->iface->index);
        !            70:       rte_update2(c, net, NULL, src);
        !            71:     }
        !            72:   else if (flags & IF_CHANGE_UP)
        !            73:     {
        !            74:       rta *a;
        !            75:       rte *e;
        !            76: 
        !            77:       DBG("dev_if_notify: %s:%I going up\n", ad->iface->name, ad->ip);
        !            78: 
        !            79:       if (cf->check_link && !(ad->iface->flags & IF_LINK_UP))
        !            80:        return;
        !            81: 
        !            82:       /* Use iface ID as local source ID */
        !            83:       struct rte_src *src = rt_get_source(P, ad->iface->index);
        !            84: 
        !            85:       rta a0 = {
        !            86:        .src = src,
        !            87:        .source = RTS_DEVICE,
        !            88:        .scope = SCOPE_UNIVERSE,
        !            89:        .dest = RTD_UNICAST,
        !            90:        .nh.iface = ad->iface,
        !            91:       };
        !            92: 
        !            93:       a = rta_lookup(&a0);
        !            94:       e = rte_get_temp(a);
        !            95:       e->pflags = 0;
        !            96:       rte_update2(c, net, e, src);
        !            97:     }
        !            98: }
        !            99: 
        !           100: static void
        !           101: dev_if_notify(struct proto *p, uint c, struct iface *iface)
        !           102: {
        !           103:   struct rt_dev_config *cf = (void *) p->cf;
        !           104: 
        !           105:   if (c & (IF_CHANGE_UP | IF_CHANGE_DOWN))
        !           106:     return;
        !           107: 
        !           108:   if ((c & IF_CHANGE_LINK) && cf->check_link)
        !           109:   {
        !           110:     uint ac = (iface->flags & IF_LINK_UP) ? IF_CHANGE_UP : IF_CHANGE_DOWN;
        !           111: 
        !           112:     struct ifa *a;
        !           113:     WALK_LIST(a, iface->addrs)
        !           114:       dev_ifa_notify(p, ac, a);
        !           115:   }
        !           116: }
        !           117: 
        !           118: static void
        !           119: dev_postconfig(struct proto_config *CF)
        !           120: {
        !           121:   struct rt_dev_config *cf = (void *) CF;
        !           122:   struct channel_config *ip4, *ip6, *ip6_sadr;
        !           123: 
        !           124:   ip4 = proto_cf_find_channel(CF, NET_IP4);
        !           125:   ip6 = proto_cf_find_channel(CF, NET_IP6);
        !           126:   ip6_sadr = proto_cf_find_channel(CF, NET_IP6_SADR);
        !           127: 
        !           128:   if (ip6 && ip6_sadr)
        !           129:     cf_error("Both ipv6 and ipv6-sadr channels");
        !           130: 
        !           131:   cf->ip4_channel = ip4;
        !           132:   cf->ip6_channel = ip6 ?: ip6_sadr;
        !           133: }
        !           134: 
        !           135: static struct proto *
        !           136: dev_init(struct proto_config *CF)
        !           137: {
        !           138:   struct proto *P = proto_new(CF);
        !           139:   struct rt_dev_proto *p = (void *) P;
        !           140:   struct rt_dev_config *cf = (void *) CF;
        !           141: 
        !           142:   proto_configure_channel(P, &p->ip4_channel, cf->ip4_channel);
        !           143:   proto_configure_channel(P, &p->ip6_channel, cf->ip6_channel);
        !           144: 
        !           145:   P->if_notify = dev_if_notify;
        !           146:   P->ifa_notify = dev_ifa_notify;
        !           147: 
        !           148:   return P;
        !           149: }
        !           150: 
        !           151: static int
        !           152: dev_reconfigure(struct proto *P, struct proto_config *CF)
        !           153: {
        !           154:   struct rt_dev_proto *p = (void *) P;
        !           155:   struct rt_dev_config *o = (void *) P->cf;
        !           156:   struct rt_dev_config *n = (void *) CF;
        !           157: 
        !           158:   if (!iface_patts_equal(&o->iface_list, &n->iface_list, NULL) ||
        !           159:       (o->check_link != n->check_link))
        !           160:     return 0;
        !           161: 
        !           162:   return
        !           163:     proto_configure_channel(P, &p->ip4_channel, n->ip4_channel) &&
        !           164:     proto_configure_channel(P, &p->ip6_channel, n->ip6_channel);
        !           165: 
        !           166:   return 1;
        !           167: }
        !           168: 
        !           169: static void
        !           170: dev_copy_config(struct proto_config *dest, struct proto_config *src)
        !           171: {
        !           172:   struct rt_dev_config *d = (void *) dest;
        !           173:   struct rt_dev_config *s = (void *) src;
        !           174: 
        !           175:   /*
        !           176:    * We copy iface_list as ifaces can be shared by more direct protocols.
        !           177:    * Copy suffices to be is shallow, because new nodes can be added, but
        !           178:    * old nodes cannot be modified (although they contain internal lists).
        !           179:    */
        !           180:   cfg_copy_list(&d->iface_list, &s->iface_list, sizeof(struct iface_patt));
        !           181: 
        !           182:   d->check_link = s->check_link;
        !           183: }
        !           184: 
        !           185: struct protocol proto_device = {
        !           186:   .name =              "Direct",
        !           187:   .template =          "direct%d",
        !           188:   .class =             PROTOCOL_DIRECT,
        !           189:   .preference =                DEF_PREF_DIRECT,
        !           190:   .channel_mask =      NB_IP | NB_IP6_SADR,
        !           191:   .proto_size =                sizeof(struct rt_dev_proto),
        !           192:   .config_size =       sizeof(struct rt_dev_config),
        !           193:   .postconfig =                dev_postconfig,
        !           194:   .init =              dev_init,
        !           195:   .reconfigure =       dev_reconfigure,
        !           196:   .copy_config =       dev_copy_config
        !           197: };

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>