Annotation of embedaddon/bird2/nest/rt-dev.c, revision 1.1.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>