]>
git.ipfire.org Git - thirdparty/bird.git/blob - nest/rt-dev.c
2 * BIRD -- Direct Device Routes
4 * (c) 1998--2000 Martin Mares <mj@ucw.cz>
6 * Can be freely distributed and used under the terms of the GNU GPL.
12 * The Direct protocol works by converting all ifa_notify() events it receives
13 * to rte_update() calls for the corresponding network.
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"
29 dev_ifa_notify(struct proto
*P
, uint flags
, struct ifa
*ad
)
31 struct rt_dev_proto
*p
= (void *) P
;
32 struct rt_dev_config
*cf
= (void *) P
->cf
;
34 net_addr
*net
= &ad
->prefix
;
36 if (!EMPTY_LIST(cf
->iface_list
) &&
37 !iface_patt_find(&cf
->iface_list
, ad
->iface
, ad
))
38 /* Empty list is automatically treated as "*" */
41 if (ad
->flags
& IA_SECONDARY
)
44 if (ad
->scope
<= SCOPE_LINK
)
47 if (ad
->prefix
.type
== NET_IP4
)
49 else if (ad
->prefix
.type
== NET_IP6
)
57 /* For IPv6 SADR, replace regular prefix with SADR prefix */
58 if (c
->net_type
== NET_IP6_SADR
)
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);
64 if (flags
& IF_CHANGE_DOWN
)
66 DBG("dev_if_notify: %s:%I going down\n", ad
->iface
->name
, ad
->ip
);
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
);
72 else if (flags
& IF_CHANGE_UP
)
77 DBG("dev_if_notify: %s:%I going up\n", ad
->iface
->name
, ad
->ip
);
79 if (cf
->check_link
&& !(ad
->iface
->flags
& IF_LINK_UP
))
82 /* Use iface ID as local source ID */
83 struct rte_src
*src
= rt_get_source(P
, ad
->iface
->index
);
88 .scope
= SCOPE_UNIVERSE
,
90 .nh
.iface
= ad
->iface
,
96 rte_update2(c
, net
, e
, src
);
101 dev_if_notify(struct proto
*p
, uint c
, struct iface
*iface
)
103 struct rt_dev_config
*cf
= (void *) p
->cf
;
105 if (c
& (IF_CHANGE_UP
| IF_CHANGE_DOWN
))
108 if ((c
& IF_CHANGE_LINK
) && cf
->check_link
)
110 uint ac
= (iface
->flags
& IF_LINK_UP
) ? IF_CHANGE_UP
: IF_CHANGE_DOWN
;
113 WALK_LIST(a
, iface
->addrs
)
114 dev_ifa_notify(p
, ac
, a
);
119 dev_postconfig(struct proto_config
*CF
)
121 struct rt_dev_config
*cf
= (void *) CF
;
122 struct channel_config
*ip4
, *ip6
, *ip6_sadr
;
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
);
129 cf_error("Both ipv6 and ipv6-sadr channels");
131 cf
->ip4_channel
= ip4
;
132 cf
->ip6_channel
= ip6
?: ip6_sadr
;
135 static struct proto
*
136 dev_init(struct proto_config
*CF
)
138 struct proto
*P
= proto_new(CF
);
139 struct rt_dev_proto
*p
= (void *) P
;
140 struct rt_dev_config
*cf
= (void *) CF
;
142 proto_configure_channel(P
, &p
->ip4_channel
, cf
->ip4_channel
);
143 proto_configure_channel(P
, &p
->ip6_channel
, cf
->ip6_channel
);
145 P
->if_notify
= dev_if_notify
;
146 P
->ifa_notify
= dev_ifa_notify
;
152 dev_reconfigure(struct proto
*P
, struct proto_config
*CF
)
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
;
158 if (!iface_patts_equal(&o
->iface_list
, &n
->iface_list
, NULL
) ||
159 (o
->check_link
!= n
->check_link
))
163 proto_configure_channel(P
, &p
->ip4_channel
, n
->ip4_channel
) &&
164 proto_configure_channel(P
, &p
->ip6_channel
, n
->ip6_channel
);
170 dev_copy_config(struct proto_config
*dest
, struct proto_config
*src
)
172 struct rt_dev_config
*d
= (void *) dest
;
173 struct rt_dev_config
*s
= (void *) src
;
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).
180 cfg_copy_list(&d
->iface_list
, &s
->iface_list
, sizeof(struct iface_patt
));
182 d
->check_link
= s
->check_link
;
185 struct protocol proto_device
= {
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
,
195 .reconfigure
= dev_reconfigure
,
196 .copy_config
= dev_copy_config