]>
Commit | Line | Data |
---|---|---|
eac6e3f0 RW |
1 | /* |
2 | * Copyright (C) 2016 by Open Source Routing. | |
3 | * | |
180fc2cd RW |
4 | * This program is free software; you can redistribute it and/or modify |
5 | * it under the terms of the GNU General Public License as published by | |
6 | * the Free Software Foundation; either version 2 of the License, or | |
7 | * (at your option) any later version. | |
eac6e3f0 | 8 | * |
180fc2cd | 9 | * This program is distributed in the hope that it will be useful, but |
eac6e3f0 RW |
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
12 | * General Public License for more details. | |
13 | * | |
180fc2cd RW |
14 | * You should have received a copy of the GNU General Public License |
15 | * along with this program; see the file COPYING; if not, write to the | |
16 | * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, | |
17 | * MA 02110-1301 USA | |
eac6e3f0 RW |
18 | */ |
19 | ||
20 | #include <zebra.h> | |
21 | ||
22 | #include "prefix.h" | |
23 | #include "stream.h" | |
24 | #include "memory.h" | |
25 | #include "zclient.h" | |
26 | #include "command.h" | |
27 | #include "network.h" | |
28 | #include "linklist.h" | |
ce549947 | 29 | #include "mpls.h" |
eac6e3f0 RW |
30 | |
31 | #include "ldpd.h" | |
32 | #include "ldpe.h" | |
33 | #include "lde.h" | |
34 | #include "log.h" | |
35 | #include "ldp_debug.h" | |
36 | ||
37 | static void ifp2kif(struct interface *, struct kif *); | |
38 | static void ifc2kaddr(struct interface *, struct connected *, | |
39 | struct kaddr *); | |
ce549947 | 40 | static int zebra_send_mpls_labels(int, struct kroute *); |
eac6e3f0 RW |
41 | static int ldp_router_id_update(int, struct zclient *, zebra_size_t, |
42 | vrf_id_t); | |
43 | static int ldp_interface_add(int, struct zclient *, zebra_size_t, | |
44 | vrf_id_t); | |
45 | static int ldp_interface_delete(int, struct zclient *, zebra_size_t, | |
46 | vrf_id_t); | |
47 | static int ldp_interface_status_change(int command, struct zclient *, | |
48 | zebra_size_t, vrf_id_t); | |
49 | static int ldp_interface_address_add(int, struct zclient *, zebra_size_t, | |
50 | vrf_id_t); | |
51 | static int ldp_interface_address_delete(int, struct zclient *, | |
52 | zebra_size_t, vrf_id_t); | |
53 | static int ldp_zebra_read_route(int, struct zclient *, zebra_size_t, | |
54 | vrf_id_t); | |
87b5f1b7 RW |
55 | static int ldp_zebra_read_pw_status_update(int, struct zclient *, |
56 | zebra_size_t, vrf_id_t); | |
eac6e3f0 RW |
57 | static void ldp_zebra_connected(struct zclient *); |
58 | ||
59 | static struct zclient *zclient; | |
60 | ||
61 | static void | |
62 | ifp2kif(struct interface *ifp, struct kif *kif) | |
63 | { | |
64 | memset(kif, 0, sizeof(*kif)); | |
65 | strlcpy(kif->ifname, ifp->name, sizeof(kif->ifname)); | |
66 | kif->ifindex = ifp->ifindex; | |
988ded8d | 67 | kif->operative = if_is_operative(ifp); |
26519d8c | 68 | if (ifp->ll_type == ZEBRA_LLT_ETHER) |
9bff8057 | 69 | memcpy(kif->mac, ifp->hw_addr, ETH_ALEN); |
eac6e3f0 RW |
70 | } |
71 | ||
72 | static void | |
73 | ifc2kaddr(struct interface *ifp, struct connected *ifc, struct kaddr *ka) | |
74 | { | |
75 | memset(ka, 0, sizeof(*ka)); | |
9cf67225 | 76 | strlcpy(ka->ifname, ifp->name, sizeof(ka->ifname)); |
eac6e3f0 RW |
77 | ka->ifindex = ifp->ifindex; |
78 | ka->af = ifc->address->family; | |
79 | ka->prefixlen = ifc->address->prefixlen; | |
80 | ||
81 | switch (ka->af) { | |
82 | case AF_INET: | |
83 | ka->addr.v4 = ifc->address->u.prefix4; | |
84 | if (ifc->destination) | |
85 | ka->dstbrd.v4 = ifc->destination->u.prefix4; | |
86 | break; | |
87 | case AF_INET6: | |
88 | ka->addr.v6 = ifc->address->u.prefix6; | |
89 | if (ifc->destination) | |
90 | ka->dstbrd.v6 = ifc->destination->u.prefix6; | |
91 | break; | |
92 | default: | |
93 | break; | |
94 | } | |
95 | } | |
96 | ||
87b5f1b7 RW |
97 | void |
98 | pw2zpw(struct l2vpn_pw *pw, struct zapi_pw *zpw) | |
99 | { | |
100 | memset(zpw, 0, sizeof(*zpw)); | |
101 | strlcpy(zpw->ifname, pw->ifname, sizeof(zpw->ifname)); | |
102 | zpw->ifindex = pw->ifindex; | |
103 | zpw->type = pw->l2vpn->pw_type; | |
104 | zpw->af = pw->af; | |
105 | zpw->nexthop.ipv6 = pw->addr.v6; | |
106 | zpw->local_label = NO_LABEL; | |
107 | zpw->remote_label = NO_LABEL; | |
108 | if (pw->flags & F_PW_CWORD) | |
109 | zpw->flags = F_PSEUDOWIRE_CWORD; | |
110 | zpw->data.ldp.lsr_id = pw->lsr_id; | |
111 | zpw->data.ldp.pwid = pw->pwid; | |
112 | strlcpy(zpw->data.ldp.vpn_name, pw->l2vpn->name, | |
113 | sizeof(zpw->data.ldp.vpn_name)); | |
114 | } | |
115 | ||
ce549947 RW |
116 | static int |
117 | zebra_send_mpls_labels(int cmd, struct kroute *kr) | |
118 | { | |
119 | struct stream *s; | |
120 | ||
121 | if (kr->local_label < MPLS_LABEL_RESERVED_MAX || | |
122 | kr->remote_label == NO_LABEL) | |
123 | return (0); | |
124 | ||
88d88a9c | 125 | debug_zebra_out("prefix %s/%u nexthop %s ifindex %u labels %s/%s (%s)", |
ce549947 | 126 | log_addr(kr->af, &kr->prefix), kr->prefixlen, |
88d88a9c RW |
127 | log_addr(kr->af, &kr->nexthop), kr->ifindex, |
128 | log_label(kr->local_label), log_label(kr->remote_label), | |
ce549947 RW |
129 | (cmd == ZEBRA_MPLS_LABELS_ADD) ? "add" : "delete"); |
130 | ||
131 | /* Reset stream. */ | |
132 | s = zclient->obuf; | |
133 | stream_reset(s); | |
134 | ||
135 | zclient_create_header(s, cmd, VRF_DEFAULT); | |
136 | stream_putc(s, ZEBRA_LSP_LDP); | |
137 | stream_putl(s, kr->af); | |
138 | switch (kr->af) { | |
139 | case AF_INET: | |
140 | stream_put_in_addr(s, &kr->prefix.v4); | |
141 | stream_putc(s, kr->prefixlen); | |
142 | stream_put_in_addr(s, &kr->nexthop.v4); | |
143 | break; | |
144 | case AF_INET6: | |
145 | stream_write(s, (u_char *)&kr->prefix.v6, 16); | |
146 | stream_putc(s, kr->prefixlen); | |
147 | stream_write(s, (u_char *)&kr->nexthop.v6, 16); | |
148 | break; | |
149 | default: | |
150 | fatalx("kr_change: unknown af"); | |
151 | } | |
88d88a9c | 152 | stream_putl(s, kr->ifindex); |
ce549947 RW |
153 | stream_putc(s, kr->priority); |
154 | stream_putl(s, kr->local_label); | |
155 | stream_putl(s, kr->remote_label); | |
156 | ||
157 | /* Put length at the first point of the stream. */ | |
158 | stream_putw_at(s, 0, stream_get_endp(s)); | |
159 | ||
160 | return (zclient_send_message(zclient)); | |
161 | } | |
162 | ||
eac6e3f0 RW |
163 | int |
164 | kr_change(struct kroute *kr) | |
165 | { | |
ce549947 | 166 | return (zebra_send_mpls_labels(ZEBRA_MPLS_LABELS_ADD, kr)); |
eac6e3f0 RW |
167 | } |
168 | ||
169 | int | |
170 | kr_delete(struct kroute *kr) | |
171 | { | |
ce549947 | 172 | return (zebra_send_mpls_labels(ZEBRA_MPLS_LABELS_DELETE, kr)); |
eac6e3f0 RW |
173 | } |
174 | ||
175 | int | |
87b5f1b7 | 176 | kmpw_add(struct zapi_pw *zpw) |
eac6e3f0 | 177 | { |
87b5f1b7 RW |
178 | debug_zebra_out("pseudowire %s nexthop %s (add)", |
179 | zpw->ifname, log_addr(zpw->af, (union ldpd_addr *)&zpw->nexthop)); | |
180 | ||
181 | return (zebra_send_pw(zclient, ZEBRA_PW_ADD, zpw)); | |
eac6e3f0 RW |
182 | } |
183 | ||
184 | int | |
87b5f1b7 | 185 | kmpw_del(struct zapi_pw *zpw) |
eac6e3f0 | 186 | { |
87b5f1b7 RW |
187 | debug_zebra_out("pseudowire %s nexthop %s (del)", |
188 | zpw->ifname, log_addr(zpw->af, (union ldpd_addr *)&zpw->nexthop)); | |
189 | ||
190 | return (zebra_send_pw(zclient, ZEBRA_PW_DELETE, zpw)); | |
191 | } | |
192 | ||
193 | int | |
194 | kmpw_set(struct zapi_pw *zpw) | |
195 | { | |
196 | debug_zebra_out("pseudowire %s nexthop %s labels %u/%u (set)", | |
197 | zpw->ifname, log_addr(zpw->af, (union ldpd_addr *)&zpw->nexthop), | |
198 | zpw->local_label, zpw->remote_label); | |
199 | ||
200 | return (zebra_send_pw(zclient, ZEBRA_PW_SET, zpw)); | |
201 | } | |
202 | ||
203 | int | |
204 | kmpw_unset(struct zapi_pw *zpw) | |
205 | { | |
206 | debug_zebra_out("pseudowire %s nexthop %s (unset)", | |
207 | zpw->ifname, log_addr(zpw->af, (union ldpd_addr *)&zpw->nexthop)); | |
208 | ||
209 | return (zebra_send_pw(zclient, ZEBRA_PW_UNSET, zpw)); | |
eac6e3f0 RW |
210 | } |
211 | ||
212 | void | |
213 | kif_redistribute(const char *ifname) | |
214 | { | |
f4e14fdb RW |
215 | struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); |
216 | struct listnode *cnode; | |
eac6e3f0 RW |
217 | struct interface *ifp; |
218 | struct connected *ifc; | |
219 | struct kif kif; | |
220 | struct kaddr ka; | |
221 | ||
451fda4f | 222 | FOR_ALL_INTERFACES (vrf, ifp) { |
eac6e3f0 RW |
223 | if (ifname && strcmp(ifname, ifp->name) != 0) |
224 | continue; | |
225 | ||
226 | ifp2kif(ifp, &kif); | |
52b530fc | 227 | main_imsg_compose_both(IMSG_IFSTATUS, &kif, sizeof(kif)); |
eac6e3f0 RW |
228 | |
229 | for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, ifc)) { | |
230 | ifc2kaddr(ifp, ifc, &ka); | |
231 | main_imsg_compose_ldpe(IMSG_NEWADDR, 0, &ka, | |
232 | sizeof(ka)); | |
233 | } | |
234 | } | |
235 | } | |
236 | ||
237 | static int | |
238 | ldp_router_id_update(int command, struct zclient *zclient, zebra_size_t length, | |
239 | vrf_id_t vrf_id) | |
240 | { | |
241 | struct prefix router_id; | |
242 | ||
243 | zebra_router_id_update_read(zclient->ibuf, &router_id); | |
244 | ||
245 | if (bad_addr_v4(router_id.u.prefix4)) | |
246 | return (0); | |
247 | ||
248 | debug_zebra_in("router-id update %s", inet_ntoa(router_id.u.prefix4)); | |
249 | ||
250 | global.rtr_id.s_addr = router_id.u.prefix4.s_addr; | |
251 | main_imsg_compose_ldpe(IMSG_RTRID_UPDATE, 0, &global.rtr_id, | |
252 | sizeof(global.rtr_id)); | |
253 | ||
254 | return (0); | |
255 | } | |
256 | ||
257 | static int | |
258 | ldp_interface_add(int command, struct zclient *zclient, zebra_size_t length, | |
259 | vrf_id_t vrf_id) | |
260 | { | |
261 | struct interface *ifp; | |
262 | struct kif kif; | |
263 | ||
264 | ifp = zebra_interface_add_read(zclient->ibuf, vrf_id); | |
265 | debug_zebra_in("interface add %s index %d mtu %d", ifp->name, | |
266 | ifp->ifindex, ifp->mtu); | |
267 | ||
268 | ifp2kif(ifp, &kif); | |
52b530fc | 269 | main_imsg_compose_both(IMSG_IFSTATUS, &kif, sizeof(kif)); |
eac6e3f0 RW |
270 | |
271 | return (0); | |
272 | } | |
273 | ||
274 | static int | |
275 | ldp_interface_delete(int command, struct zclient *zclient, zebra_size_t length, | |
276 | vrf_id_t vrf_id) | |
277 | { | |
278 | struct interface *ifp; | |
9cf67225 | 279 | struct kif kif; |
eac6e3f0 RW |
280 | |
281 | /* zebra_interface_state_read() updates interface structure in iflist */ | |
282 | ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); | |
283 | if (ifp == NULL) | |
284 | return (0); | |
285 | ||
286 | debug_zebra_in("interface delete %s index %d mtu %d", ifp->name, | |
287 | ifp->ifindex, ifp->mtu); | |
288 | ||
289 | /* To support pseudo interface do not free interface structure. */ | |
290 | /* if_delete(ifp); */ | |
ff880b78 | 291 | if_set_index(ifp, IFINDEX_INTERNAL); |
9cf67225 RW |
292 | |
293 | ifp2kif(ifp, &kif); | |
294 | main_imsg_compose_both(IMSG_IFSTATUS, &kif, sizeof(kif)); | |
eac6e3f0 RW |
295 | |
296 | return (0); | |
297 | } | |
298 | ||
299 | static int | |
300 | ldp_interface_status_change(int command, struct zclient *zclient, | |
301 | zebra_size_t length, vrf_id_t vrf_id) | |
302 | { | |
303 | struct interface *ifp; | |
304 | struct listnode *node; | |
305 | struct connected *ifc; | |
306 | struct kif kif; | |
307 | struct kaddr ka; | |
eac6e3f0 RW |
308 | |
309 | /* | |
310 | * zebra_interface_state_read() updates interface structure in | |
311 | * iflist. | |
312 | */ | |
313 | ifp = zebra_interface_state_read(zclient->ibuf, vrf_id); | |
314 | if (ifp == NULL) | |
315 | return (0); | |
316 | ||
317 | debug_zebra_in("interface %s state update", ifp->name); | |
318 | ||
319 | ifp2kif(ifp, &kif); | |
52b530fc | 320 | main_imsg_compose_both(IMSG_IFSTATUS, &kif, sizeof(kif)); |
eac6e3f0 | 321 | |
988ded8d | 322 | if (if_is_operative(ifp)) { |
eac6e3f0 RW |
323 | for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { |
324 | ifc2kaddr(ifp, ifc, &ka); | |
325 | main_imsg_compose_ldpe(IMSG_NEWADDR, 0, &ka, | |
326 | sizeof(ka)); | |
327 | } | |
328 | } else { | |
329 | for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) { | |
330 | ifc2kaddr(ifp, ifc, &ka); | |
331 | main_imsg_compose_ldpe(IMSG_DELADDR, 0, &ka, | |
332 | sizeof(ka)); | |
333 | } | |
334 | } | |
335 | ||
336 | return (0); | |
337 | } | |
338 | ||
339 | static int | |
340 | ldp_interface_address_add(int command, struct zclient *zclient, | |
341 | zebra_size_t length, vrf_id_t vrf_id) | |
342 | { | |
343 | struct connected *ifc; | |
344 | struct interface *ifp; | |
345 | struct kaddr ka; | |
346 | ||
347 | ifc = zebra_interface_address_read(command, zclient->ibuf, vrf_id); | |
348 | if (ifc == NULL) | |
349 | return (0); | |
350 | ||
351 | ifp = ifc->ifp; | |
352 | ifc2kaddr(ifp, ifc, &ka); | |
353 | ||
354 | /* Filter invalid addresses. */ | |
355 | if (bad_addr(ka.af, &ka.addr)) | |
356 | return (0); | |
357 | ||
9cf67225 RW |
358 | debug_zebra_in("address add %s/%u interface %s", |
359 | log_addr(ka.af, &ka.addr), ka.prefixlen, ifp->name); | |
eac6e3f0 RW |
360 | |
361 | /* notify ldpe about new address */ | |
362 | main_imsg_compose_ldpe(IMSG_NEWADDR, 0, &ka, sizeof(ka)); | |
363 | ||
364 | return (0); | |
365 | } | |
366 | ||
367 | static int | |
368 | ldp_interface_address_delete(int command, struct zclient *zclient, | |
369 | zebra_size_t length, vrf_id_t vrf_id) | |
370 | { | |
371 | struct connected *ifc; | |
372 | struct interface *ifp; | |
373 | struct kaddr ka; | |
374 | ||
375 | ifc = zebra_interface_address_read(command, zclient->ibuf, vrf_id); | |
376 | if (ifc == NULL) | |
377 | return (0); | |
378 | ||
379 | ifp = ifc->ifp; | |
380 | ifc2kaddr(ifp, ifc, &ka); | |
381 | connected_free(ifc); | |
382 | ||
383 | /* Filter invalid addresses. */ | |
384 | if (bad_addr(ka.af, &ka.addr)) | |
385 | return (0); | |
386 | ||
9cf67225 RW |
387 | debug_zebra_in("address delete %s/%u interface %s", |
388 | log_addr(ka.af, &ka.addr), ka.prefixlen, ifp->name); | |
eac6e3f0 RW |
389 | |
390 | /* notify ldpe about removed address */ | |
391 | main_imsg_compose_ldpe(IMSG_DELADDR, 0, &ka, sizeof(ka)); | |
392 | ||
393 | return (0); | |
394 | } | |
395 | ||
396 | static int | |
397 | ldp_zebra_read_route(int command, struct zclient *zclient, zebra_size_t length, | |
398 | vrf_id_t vrf_id) | |
399 | { | |
74489921 RW |
400 | struct zapi_route api; |
401 | struct zapi_nexthop *api_nh; | |
eac6e3f0 | 402 | struct kroute kr; |
74489921 RW |
403 | int i, add = 0; |
404 | ||
405 | if (zapi_route_decode(zclient->ibuf, &api) < 0) | |
406 | return -1; | |
407 | ||
408 | /* we completely ignore srcdest routes for now. */ | |
409 | if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) | |
410 | return (0); | |
eac6e3f0 RW |
411 | |
412 | memset(&kr, 0, sizeof(kr)); | |
74489921 RW |
413 | kr.af = api.prefix.family; |
414 | switch (kr.af) { | |
415 | case AF_INET: | |
416 | kr.prefix.v4 = api.prefix.u.prefix4; | |
417 | break; | |
418 | case AF_INET6: | |
419 | kr.prefix.v6 = api.prefix.u.prefix6; | |
420 | break; | |
421 | default: | |
422 | break; | |
423 | } | |
424 | kr.prefixlen = api.prefix.prefixlen; | |
425 | kr.priority = api.distance; | |
eac6e3f0 | 426 | |
74489921 | 427 | switch (api.type) { |
a695cc7b | 428 | case ZEBRA_ROUTE_CONNECT: |
eac6e3f0 | 429 | kr.flags |= F_CONNECTED; |
a695cc7b RW |
430 | break; |
431 | case ZEBRA_ROUTE_BGP: | |
432 | /* LDP should follow the IGP and ignore BGP routes */ | |
433 | return (0); | |
434 | default: | |
435 | break; | |
436 | } | |
437 | ||
eac6e3f0 RW |
438 | if (bad_addr(kr.af, &kr.prefix) || |
439 | (kr.af == AF_INET6 && IN6_IS_SCOPE_EMBED(&kr.prefix.v6))) | |
440 | return (0); | |
441 | ||
74489921 | 442 | if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) |
1f2ff5b5 RW |
443 | add = 1; |
444 | ||
74489921 | 445 | if (api.nexthop_num == 0) |
1f2ff5b5 RW |
446 | debug_zebra_in("route %s %s/%d (%s)", (add) ? "add" : "delete", |
447 | log_addr(kr.af, &kr.prefix), kr.prefixlen, | |
74489921 | 448 | zebra_route_string(api.type)); |
eac6e3f0 RW |
449 | |
450 | /* loop through all the nexthops */ | |
74489921 RW |
451 | for (i = 0; i < api.nexthop_num; i++) { |
452 | api_nh = &api.nexthops[i]; | |
453 | ||
eac6e3f0 RW |
454 | switch (kr.af) { |
455 | case AF_INET: | |
74489921 | 456 | kr.nexthop.v4 = api_nh->gate.ipv4; |
eac6e3f0 RW |
457 | break; |
458 | case AF_INET6: | |
74489921 | 459 | kr.nexthop.v6 = api_nh->gate.ipv6; |
eac6e3f0 RW |
460 | break; |
461 | default: | |
462 | break; | |
463 | } | |
74489921 | 464 | kr.ifindex = api_nh->ifindex;; |
eac6e3f0 | 465 | |
1f2ff5b5 RW |
466 | debug_zebra_in("route %s %s/%d nexthop %s ifindex %u (%s)", |
467 | (add) ? "add" : "delete", log_addr(kr.af, &kr.prefix), | |
468 | kr.prefixlen, log_addr(kr.af, &kr.nexthop), kr.ifindex, | |
74489921 | 469 | zebra_route_string(api.type)); |
1f2ff5b5 RW |
470 | |
471 | if (add) | |
eac6e3f0 RW |
472 | main_imsg_compose_lde(IMSG_NETWORK_ADD, 0, &kr, |
473 | sizeof(kr)); | |
eac6e3f0 RW |
474 | } |
475 | ||
8cb1fc45 | 476 | main_imsg_compose_lde(IMSG_NETWORK_UPDATE, 0, &kr, sizeof(kr)); |
134970a2 | 477 | |
eac6e3f0 RW |
478 | return (0); |
479 | } | |
480 | ||
87b5f1b7 RW |
481 | /* |
482 | * Receive PW status update from Zebra and send it to LDE process. | |
483 | */ | |
484 | static int | |
485 | ldp_zebra_read_pw_status_update(int command, struct zclient *zclient, | |
486 | zebra_size_t length, vrf_id_t vrf_id) | |
487 | { | |
488 | struct zapi_pw_status zpw; | |
489 | ||
490 | zebra_read_pw_status_update(command, zclient, length, vrf_id, &zpw); | |
491 | ||
492 | debug_zebra_in("pseudowire %s status %s", zpw.ifname, | |
493 | (zpw.status == PW_STATUS_UP) ? "up" : "down"); | |
494 | ||
495 | main_imsg_compose_lde(IMSG_PW_UPDATE, 0, &zpw, sizeof(zpw)); | |
496 | ||
497 | return (0); | |
498 | } | |
499 | ||
eac6e3f0 RW |
500 | static void |
501 | ldp_zebra_connected(struct zclient *zclient) | |
502 | { | |
eac6e3f0 | 503 | zclient_send_reg_requests(zclient, VRF_DEFAULT); |
a695cc7b RW |
504 | zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, |
505 | ZEBRA_ROUTE_ALL, 0, VRF_DEFAULT); | |
506 | zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6, | |
507 | ZEBRA_ROUTE_ALL, 0, VRF_DEFAULT); | |
eac6e3f0 RW |
508 | } |
509 | ||
342213ea DS |
510 | extern struct zebra_privs_t ldpd_privs; |
511 | ||
eac6e3f0 RW |
512 | void |
513 | ldp_zebra_init(struct thread_master *master) | |
514 | { | |
515 | /* Set default values. */ | |
e1a1880d | 516 | zclient = zclient_new_notify(master, &zclient_options_default); |
342213ea | 517 | zclient_init(zclient, ZEBRA_ROUTE_LDP, 0, &ldpd_privs); |
eac6e3f0 RW |
518 | |
519 | /* set callbacks */ | |
520 | zclient->zebra_connected = ldp_zebra_connected; | |
521 | zclient->router_id_update = ldp_router_id_update; | |
522 | zclient->interface_add = ldp_interface_add; | |
523 | zclient->interface_delete = ldp_interface_delete; | |
524 | zclient->interface_up = ldp_interface_status_change; | |
525 | zclient->interface_down = ldp_interface_status_change; | |
526 | zclient->interface_address_add = ldp_interface_address_add; | |
527 | zclient->interface_address_delete = ldp_interface_address_delete; | |
74489921 RW |
528 | zclient->redistribute_route_add = ldp_zebra_read_route; |
529 | zclient->redistribute_route_del = ldp_zebra_read_route; | |
87b5f1b7 | 530 | zclient->pw_status_update = ldp_zebra_read_pw_status_update; |
eac6e3f0 | 531 | } |
64dffe25 RW |
532 | |
533 | void | |
534 | ldp_zebra_destroy(void) | |
535 | { | |
536 | zclient_stop(zclient); | |
537 | zclient_free(zclient); | |
538 | zclient = NULL; | |
539 | } |