]>
Commit | Line | Data |
---|---|---|
c5ffa447 MM |
1 | /* |
2 | * BIRD -- Direct Device Routes | |
3 | * | |
394aec8f | 4 | * (c) 1998--2000 Martin Mares <mj@ucw.cz> |
c5ffa447 MM |
5 | * |
6 | * Can be freely distributed and used under the terms of the GNU GPL. | |
7 | */ | |
8 | ||
47f8e0c2 MM |
9 | /** |
10 | * DOC: Direct | |
11 | * | |
2e9b2421 | 12 | * The Direct protocol works by converting all ifa_notify() events it receives |
47f8e0c2 MM |
13 | * to rte_update() calls for the corresponding network. |
14 | */ | |
15 | ||
6b9fa320 | 16 | #undef LOCAL_DEBUG |
c5ffa447 MM |
17 | |
18 | #include "nest/bird.h" | |
19 | #include "nest/iface.h" | |
20 | #include "nest/protocol.h" | |
21 | #include "nest/route.h" | |
50d8424a MM |
22 | #include "nest/rt-dev.h" |
23 | #include "conf/conf.h" | |
c5ffa447 | 24 | #include "lib/resource.h" |
221135d6 | 25 | #include "lib/string.h" |
c5ffa447 | 26 | |
c5ffa447 | 27 | static void |
9a158361 | 28 | dev_ifa_notify(struct proto *p, unsigned c, struct ifa *ad) |
c5ffa447 | 29 | { |
31b3e1bb | 30 | struct rt_dev_config *P = (void *) p->cf; |
50d8424a | 31 | |
8edf2361 | 32 | if (!EMPTY_LIST(P->iface_list) && |
0aad2b92 | 33 | !iface_patt_find(&P->iface_list, ad->iface, ad->iface->addr)) |
8edf2361 | 34 | /* Empty list is automagically treated as "*" */ |
50d8424a | 35 | return; |
ff2857b0 | 36 | |
92f8878c OZ |
37 | if (ad->flags & IA_SECONDARY) |
38 | return; | |
ff2857b0 OZ |
39 | |
40 | if (ad->scope <= SCOPE_LINK) | |
41 | return; | |
42 | ||
b1e4f814 MM |
43 | if (c & IF_CHANGE_DOWN) |
44 | { | |
45 | net *n; | |
46 | ||
9a158361 MM |
47 | DBG("dev_if_notify: %s:%I going down\n", ad->iface->name, ad->ip); |
48 | n = net_find(p->table, ad->prefix, ad->pxlen); | |
b1e4f814 MM |
49 | if (!n) |
50 | { | |
6b9fa320 | 51 | DBG("dev_if_notify: device shutdown: prefix not found\n"); |
b1e4f814 MM |
52 | return; |
53 | } | |
ab4da342 OZ |
54 | |
55 | /* Use iface ID as local source ID */ | |
56 | struct rte_src *src = rt_get_source(p, ad->iface->index); | |
57 | rte_update2(p->main_ahook, n, NULL, src); | |
b1e4f814 MM |
58 | } |
59 | else if (c & IF_CHANGE_UP) | |
60 | { | |
094d2bdb | 61 | rta *a; |
b1e4f814 MM |
62 | net *n; |
63 | rte *e; | |
64 | ||
6b9fa320 | 65 | DBG("dev_if_notify: %s:%I going up\n", ad->iface->name, ad->ip); |
094d2bdb | 66 | |
ab4da342 OZ |
67 | /* Use iface ID as local source ID */ |
68 | struct rte_src *src = rt_get_source(p, ad->iface->index); | |
69 | ||
094d2bdb | 70 | rta a0 = { |
ab4da342 | 71 | .src = src, |
094d2bdb OZ |
72 | .source = RTS_DEVICE, |
73 | .scope = SCOPE_UNIVERSE, | |
74 | .cast = RTC_UNICAST, | |
75 | .dest = RTD_DEVICE, | |
76 | .iface = ad->iface | |
77 | }; | |
78 | ||
79 | a = rta_lookup(&a0); | |
6a636392 | 80 | n = net_get(p->table, ad->prefix, ad->pxlen); |
b1e4f814 | 81 | e = rte_get_temp(a); |
a0762910 | 82 | e->net = n; |
b1e4f814 | 83 | e->pflags = 0; |
ab4da342 | 84 | rte_update2(p->main_ahook, n, e, src); |
b1e4f814 | 85 | } |
c5ffa447 MM |
86 | } |
87 | ||
31b3e1bb MM |
88 | static struct proto * |
89 | dev_init(struct proto_config *c) | |
c5ffa447 | 90 | { |
31b3e1bb | 91 | struct proto *p = proto_new(c, sizeof(struct proto)); |
c5ffa447 | 92 | |
9a158361 | 93 | p->ifa_notify = dev_ifa_notify; |
31b3e1bb | 94 | return p; |
c5ffa447 MM |
95 | } |
96 | ||
88dc89f9 MM |
97 | static int |
98 | dev_reconfigure(struct proto *p, struct proto_config *new) | |
99 | { | |
100 | struct rt_dev_config *o = (struct rt_dev_config *) p->cf; | |
101 | struct rt_dev_config *n = (struct rt_dev_config *) new; | |
2bbc3083 | 102 | |
88dc89f9 MM |
103 | return iface_patts_equal(&o->iface_list, &n->iface_list, NULL); |
104 | } | |
105 | ||
a7f23f58 OZ |
106 | static void |
107 | dev_copy_config(struct proto_config *dest, struct proto_config *src) | |
108 | { | |
109 | struct rt_dev_config *d = (struct rt_dev_config *) dest; | |
110 | struct rt_dev_config *s = (struct rt_dev_config *) src; | |
111 | ||
112 | /* | |
113 | * We copy iface_list as ifaces can be shared by more direct protocols. | |
114 | * Copy suffices to be is shallow, because new nodes can be added, but | |
115 | * old nodes cannot be modified (although they contain internal lists). | |
116 | */ | |
117 | cfg_copy_list(&d->iface_list, &s->iface_list, sizeof(struct iface_patt)); | |
118 | } | |
119 | ||
c5ffa447 | 120 | struct protocol proto_device = { |
4a591d4b PT |
121 | .name = "Direct", |
122 | .template = "direct%d", | |
123 | .preference = DEF_PREF_DIRECT, | |
2bbc3083 | 124 | .config_size = sizeof(struct rt_dev_config), |
4a591d4b PT |
125 | .init = dev_init, |
126 | .reconfigure = dev_reconfigure, | |
127 | .copy_config = dev_copy_config | |
c5ffa447 | 128 | }; |