iof-bird-daemon / nest / rt-dev.c @ 62e64905
History | View | Annotate | Download (4.08 KB)
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 |
|
35 |
if (!EMPTY_LIST(cf->iface_list) &&
|
36 |
!iface_patt_find(&cf->iface_list, ad->iface, ad->iface->addr)) |
37 |
/* Empty list is automatically treated as "*" */
|
38 |
return;
|
39 |
|
40 |
if (ad->flags & IA_SECONDARY)
|
41 |
return;
|
42 |
|
43 |
if (ad->scope <= SCOPE_LINK)
|
44 |
return;
|
45 |
|
46 |
if (ad->prefix.type == NET_IP4)
|
47 |
c = p->ip4_channel; |
48 |
else if (ad->prefix.type == NET_IP6) |
49 |
c = p->ip6_channel; |
50 |
else
|
51 |
return;
|
52 |
|
53 |
if (!c)
|
54 |
return;
|
55 |
|
56 |
if (flags & IF_CHANGE_DOWN)
|
57 |
{ |
58 |
DBG("dev_if_notify: %s:%I going down\n", ad->iface->name, ad->ip);
|
59 |
|
60 |
/* Use iface ID as local source ID */
|
61 |
struct rte_src *src = rt_get_source(P, ad->iface->index);
|
62 |
rte_update2(c, &ad->prefix, NULL, src);
|
63 |
} |
64 |
else if (flags & IF_CHANGE_UP) |
65 |
{ |
66 |
rta *a; |
67 |
rte *e; |
68 |
|
69 |
DBG("dev_if_notify: %s:%I going up\n", ad->iface->name, ad->ip);
|
70 |
|
71 |
if (cf->check_link && !(ad->iface->flags & IF_LINK_UP))
|
72 |
return;
|
73 |
|
74 |
/* Use iface ID as local source ID */
|
75 |
struct rte_src *src = rt_get_source(P, ad->iface->index);
|
76 |
|
77 |
rta a0 = { |
78 |
.src = src, |
79 |
.source = RTS_DEVICE, |
80 |
.scope = SCOPE_UNIVERSE, |
81 |
.dest = RTD_UNICAST, |
82 |
.nh.iface = ad->iface, |
83 |
}; |
84 |
|
85 |
a = rta_lookup(&a0); |
86 |
e = rte_get_temp(a); |
87 |
e->pflags = 0;
|
88 |
rte_update2(c, &ad->prefix, e, src); |
89 |
} |
90 |
} |
91 |
|
92 |
static void |
93 |
dev_if_notify(struct proto *p, uint c, struct iface *iface) |
94 |
{ |
95 |
struct rt_dev_config *cf = (void *) p->cf; |
96 |
|
97 |
if (c & (IF_CHANGE_UP | IF_CHANGE_DOWN))
|
98 |
return;
|
99 |
|
100 |
if ((c & IF_CHANGE_LINK) && cf->check_link)
|
101 |
{ |
102 |
uint ac = (iface->flags & IF_LINK_UP) ? IF_CHANGE_UP : IF_CHANGE_DOWN; |
103 |
|
104 |
struct ifa *a;
|
105 |
WALK_LIST(a, iface->addrs) |
106 |
dev_ifa_notify(p, ac, a); |
107 |
} |
108 |
} |
109 |
|
110 |
|
111 |
static struct proto * |
112 |
dev_init(struct proto_config *CF)
|
113 |
{ |
114 |
struct proto *P = proto_new(CF);
|
115 |
struct rt_dev_proto *p = (void *) P; |
116 |
// struct rt_dev_config *cf = (void *) CF;
|
117 |
|
118 |
proto_configure_channel(P, &p->ip4_channel, proto_cf_find_channel(CF, NET_IP4)); |
119 |
proto_configure_channel(P, &p->ip6_channel, proto_cf_find_channel(CF, NET_IP6)); |
120 |
|
121 |
P->if_notify = dev_if_notify; |
122 |
P->ifa_notify = dev_ifa_notify; |
123 |
|
124 |
return P;
|
125 |
} |
126 |
|
127 |
static int |
128 |
dev_reconfigure(struct proto *P, struct proto_config *CF) |
129 |
{ |
130 |
struct rt_dev_proto *p = (void *) P; |
131 |
struct rt_dev_config *o = (void *) P->cf; |
132 |
struct rt_dev_config *n = (void *) CF; |
133 |
|
134 |
if (!iface_patts_equal(&o->iface_list, &n->iface_list, NULL) || |
135 |
(o->check_link != n->check_link)) |
136 |
return 0; |
137 |
|
138 |
return
|
139 |
proto_configure_channel(P, &p->ip4_channel, proto_cf_find_channel(CF, NET_IP4)) && |
140 |
proto_configure_channel(P, &p->ip6_channel, proto_cf_find_channel(CF, NET_IP6)); |
141 |
|
142 |
return 1; |
143 |
} |
144 |
|
145 |
static void |
146 |
dev_copy_config(struct proto_config *dest, struct proto_config *src) |
147 |
{ |
148 |
struct rt_dev_config *d = (void *) dest; |
149 |
struct rt_dev_config *s = (void *) src; |
150 |
|
151 |
/*
|
152 |
* We copy iface_list as ifaces can be shared by more direct protocols.
|
153 |
* Copy suffices to be is shallow, because new nodes can be added, but
|
154 |
* old nodes cannot be modified (although they contain internal lists).
|
155 |
*/
|
156 |
cfg_copy_list(&d->iface_list, &s->iface_list, sizeof(struct iface_patt)); |
157 |
|
158 |
d->check_link = s->check_link; |
159 |
} |
160 |
|
161 |
struct protocol proto_device = {
|
162 |
.name = "Direct",
|
163 |
.template = "direct%d",
|
164 |
.preference = DEF_PREF_DIRECT, |
165 |
.channel_mask = NB_IP, |
166 |
.proto_size = sizeof(struct rt_dev_proto), |
167 |
.config_size = sizeof(struct rt_dev_config), |
168 |
.init = dev_init, |
169 |
.reconfigure = dev_reconfigure, |
170 |
.copy_config = dev_copy_config |
171 |
}; |